KilogramModelComparison

Imports and constants

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.0     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggtext)
library(here)
here() starts at /Users/ben/Documents/vlm-tangram
library(glue)
DATA_FILES <- c(
  "clip_stimulus_level_predictions_model-|scr|benpry|kilogram-models|clip_controlled|augmented|model2.pth.csv",
  "clip_stimulus_level_predictions_model-|scr|benpry|kilogram-models|clip_controlled|parts+color|model1.pth.csv",
  "clip_stimulus_level_predictions_model-|scr|benpry|kilogram-models|clip_controlled|whole+black|model0.pth.csv",
  "clip_stimulus_level_predictions_model-|scr|benpry|kilogram-models|clip_random|augmented|model2.pth.csv",
  "clip_stimulus_level_predictions_model-|scr|benpry|kilogram-models|clip_random|parts+color|model1.pth.csv",
  "clip_stimulus_level_predictions_model-|scr|benpry|kilogram-models|clip_random|whole+black|model0.pth.csv"
)

Read data

df <- tibble()
for (filename in DATA_FILES) {
  model_name = gsub("clip_stimulus_level_predictions_model-\\|scr\\|benpry\\|kilogram-models\\||.pth.csv", "", filename)
  df_file <- read_csv(here(glue("model_predictions/{filename}")), col_types=cols()) |>
    mutate(
      model_name = gsub("\\||\\+", "_", model_name)
    )
  df <- rbind(df, df_file)
}

df_wide <- df |>
  select(gameId, trialNum, utterance, prediction, model_name) |>
  pivot_wider(
    id_cols = c(gameId, trialNum, utterance),
    names_from = model_name,
    values_from = prediction
  )
make_conf_mat <- function(col1, col2) {
  confusion <- df_wide |>
    select(matches(glue("{col1}|{col2}"))) |>
    rename(
      label = !!rlang::sym(col1),
      prediction = !!rlang::sym(col2)
      ) |>
    group_by(label, prediction) |>
    tally() |>
    group_by(label) |>
    mutate(pct = n / sum(n))
  
  return(confusion)
}

images <- "images"
labels <- c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L") |> map(~ str_c("<img src=", here(images, str_c("tangram_", ., ".png")), " width='20'/>"))
label <- c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L")

plot_conf_mat <- function(confusion, col1, col2) {
  self <- confusion |>
    filter(label == prediction) |>
    select(label, self = pct)
  
  corr_order <- tibble(label, labels) |>
    left_join(self) |>
    arrange(self)
  
  self_2 <- confusion |>
    ungroup() |>
    filter(label == prediction) |>
    select(prediction, self_2 = pct)
  
  
  p <- confusion |>
    left_join(self) |>
    left_join(self_2) |>
    ggplot(aes(x = reorder(label, self, FUN = mean), y = reorder(prediction, self_2, FUN = mean), fill = pct)) +
    geom_tile() +
    scale_fill_gradient(low = "white", high = "blue") +
    scale_x_discrete(name = col1, labels = corr_order$labels) +
    scale_y_discrete(name = col2, labels = corr_order$labels) +
    theme(axis.text = element_markdown(color = "black", size = 11))+labs(title="Fine tuned")
  
  return(p)
}

compute_agreement <- function(col1, col2) {
  n_agreements <- df_wide |>
    filter(!!rlang::sym(col1) == !!rlang::sym(col2)) |>
    nrow()
  return(n_agreements / nrow(df_wide))
}

The different Kilogram-finetuned models don’t agree a ton

model_names <- df |> pull(model_name) |> unique()
for (i in 1:(length(model_names)-1)) {
  col1 = model_names[i]
  for (j in (i+1):length(model_names)) {
    col2 = model_names[j]
    conf <- make_conf_mat(col1, col2)
    p <- plot_conf_mat(conf, col1, col2)
    plot(p)
    agreement <- compute_agreement(col1, col2)
    print(glue("{col1} vs. {col2} agreement: {agreement}"))
  }
}
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`
clip_controlled_augmented_model2 vs. clip_controlled_parts_color_model1 agreement: 0.46590243902439
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_augmented_model2 vs. clip_controlled_whole_black_model0 agreement: 0.421024390243902
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_augmented_model2 vs. clip_random_augmented_model2 agreement: 0.51409756097561
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_augmented_model2 vs. clip_random_parts_color_model1 agreement: 0.422487804878049
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_augmented_model2 vs. clip_random_whole_black_model0 agreement: 0.415317073170732
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_parts_color_model1 vs. clip_controlled_whole_black_model0 agreement: 0.47780487804878
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_parts_color_model1 vs. clip_random_augmented_model2 agreement: 0.421707317073171
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_parts_color_model1 vs. clip_random_parts_color_model1 agreement: 0.628487804878049
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_parts_color_model1 vs. clip_random_whole_black_model0 agreement: 0.484146341463415
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_whole_black_model0 vs. clip_random_augmented_model2 agreement: 0.354682926829268
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_whole_black_model0 vs. clip_random_parts_color_model1 agreement: 0.434829268292683
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_controlled_whole_black_model0 vs. clip_random_whole_black_model0 agreement: 0.90190243902439
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_random_augmented_model2 vs. clip_random_parts_color_model1 agreement: 0.423024390243902
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_random_augmented_model2 vs. clip_random_whole_black_model0 agreement: 0.347951219512195
Joining with `by = join_by(label)`
Joining with `by = join_by(label)`
Joining with `by = join_by(prediction)`

clip_random_parts_color_model1 vs. clip_random_whole_black_model0 agreement: 0.441560975609756