from collections import defaultdict import pandas as pd import streamlit as st st.set_page_config(layout="wide") SHORT_CAPTIONS = [ 'ALIGN:align-base:coyo700m', 'OpenCLIP:ViT-B-32:openai', 'OpenCLIP:ViT-B-16:openai', 'OpenCLIP:ViT-L-14:openai', 'OpenCLIP:ViT-L-14-336:openai', 'OpenCLIP:ViT-B-32:laion2b_s34b_b79k', 'OpenCLIP:ViT-B-16:laion2b_s34b_b88k', 'OpenCLIP:ViT-L-14:laion2b_s32b_b82k', 'OpenCLIP:ViT-g-14:laion2b_s34b_b88k', 'OpenCLIP:ViT-H-14:laion2b_s32b_b79k', 'OpenCLIP:roberta-ViT-B-32:laion2b_s12b_b32k', 'OpenCLIP:ViT-B-16-SigLIP:webli', 'OpenCLIP:ViT-B-16-SigLIP-384:webli', 'OpenCLIP:ViT-L-16-SigLIP-256:webli', 'OpenCLIP:ViT-L-16-SigLIP-384:webli', 'OpenCLIP:ViT-SO400M-14-SigLIP:webli', 'OpenCLIP:coca_ViT-B-32:laion2b_s13b_b90k', 'OpenCLIP:coca_ViT-L-14:laion2b_s13b_b90k' ] LONG_CAPTIONS = [ 'DreamLIP:dreamlip-vitb16:cc3m-long', 'DreamLIP:dreamlip-vitb16:cc12m-long', 'DreamLIP:dreamlip-vitb16:yfcc15m-long', 'DreamLIP:dreamlip-vitb16:cc30m-long', 'FLAIR:flair-vitb16:cc3m-recap', 'FLAIR:flair-vitb16:cc12m-recap', 'FLAIR:flair-vitb16:yfcc15m-recap', 'FLAIR:flair-vitb16:cc30m-recap', 'CLIPS:CLIPS-Large-14-224:recap-datacomp1b', 'CLIPS:CLIPS-Large-14-336:recap-datacomp1b', 'CLIPS:CLIPS-Huge-14-224:recap-datacomp1b', 'LoTLIP:LoTLIP-ViT-B-32:lotlip100m', 'LoTLIP:LoTLIP-ViT-B-16:lotlip100m', 'Recap-CLIP:ViT-L-16-HTxt-Recap-CLIP:recap-datacomp1b', 'LongCLIP:longclip-vitb32:sharegpt4v-1m', 'LongCLIP:longclip-vitb16:sharegpt4v-1m', 'LongCLIP:longclip-vitl14:sharegpt4v-1m', 'LongCLIP:longclip-vitl14_336px:sharegpt4v-1m', "TULIP:TULIP-ViT-L-14-RoPE:sharegpt4v-1m", "TULIP:TULIP-ViT-L-14-RoPE_CL512:sharegpt4v-1m", 'Jina-CLIP:jina-clip-v1:jinaai', 'Jina-CLIP:jina-clip-v2:jinaai' ] COMPOSITIONALITY = [ "OpenCLIP:ViT-B-32:openai", 'StructuredCLIP:NegCLIP-ViT-B-32:coco-ft', 'StructuredCLIP:CE-CLIP-ViT-B-32:coco-ft', 'StructuredCLIP:DAC-LLM-ViT-B-32:cc3m-ft', 'StructuredCLIP:DAC-SAM-ViT-B-32:cc3m-ft', 'FSC-CLIP:fsc-clip-ViT-B-32:laioncoco-ft', 'FSC-CLIP:fsc-clip-ViT-B-16:laioncoco-ft', 'FSC-CLIP:fsc-clip-ViT-L-14:laioncoco-ft' ] DECODERS = [ 'vqascore:instructblip-flant5-xl:none', 'vqascore:clip-flant5-xl:none', 'vqascore:llava-v1.5-7b:none', 'vqascore:sharegpt4v-7b:none', 'visualgptscore:instructblip-flant5-xl:none', 'visualgptscore:clip-flant5-xl:none', 'visualgptscore:llava-v1.5-7b:none', 'visualgptscore:sharegpt4v-7b:none' ] MODEL_GROUPS = { "short_captions": SHORT_CAPTIONS, "long_captions": LONG_CAPTIONS, "compositionality": COMPOSITIONALITY, "decoder-based": DECODERS } def format_df(df): cols = [] for col in df.columns: if col in ["family", "model", "tag"]: continue cols.append(col) formatted_df = df.style.format({col: "{:.1f}" for col in cols}) return formatted_df def print_table_overall(df, model_names, metric_group, metric_columns): named_rows = df[["family", "model", "tag"]].apply(lambda row: ":".join(row), axis=1) new_rows = [] for name in model_names: new_rows.append(df[named_rows == name]) new_rows = pd.concat(new_rows, axis=0).reset_index(drop=True) # select columns selected_cols = [f"{metric_group}-{col}" for col in metric_columns] selected = new_rows[["family", "model", "tag"] + selected_cols] selected.columns = ["family", "model", "tag"] + metric_columns st.table(format_df(selected)) return # Streamlit app def main(): st.title("Interface") df = pd.read_csv("data/250206/report.csv") df_decoder = pd.read_csv("data/250206/decoder_report.csv") df = pd.concat((df, df_decoder), axis=0).reset_index(drop=True) selected = st.selectbox( "Select the evaluation data, after filtering or before filtering:", ["after filtering", "before filtering"] ) if selected == "before filtering": st.write( "It prints the accuracy gap; `filtered` - `unfiltered`. gap이 positive로 크면 filtering 후 accuracy가 더 높아짐" ) df_all = pd.read_csv("data/250206/report_all_samples.csv") df_decoder_all = pd.read_csv("data/250206/decoder_report_all.csv") df_all = pd.concat((df_all, df_decoder_all), axis=0).reset_index(drop=True) cols_all = [col for col in df.columns if col not in ["family", "model", "tag"]] df[cols_all] = df[cols_all] - df_all[cols_all] textonly_df = pd.read_csv("./data/250206/textonly_decoder_report.csv") columns = list(df.columns) col_dict = defaultdict(list) for col in columns: if "-" not in col: continue metric_group, metric_name = col.split("-") if metric_group == "all_tasks": continue col_dict[metric_group].append(metric_name) for metric_group, metric_columns in col_dict.items(): with st.expander(f"Expand: {metric_group}"): if metric_group == "neg_start_positions": st.write("- `add` 및 `replace` split에서 negative sentence 시작 토큰 위치 별 accuracy.") st.write( "- short caption model에서는 negative 판별이 가능한 context length에 한정해서 evaluation 가능. Long caption model에서는 negative sentence 시작 위치별로 정확도 비교 가능." ) st.write( "- Negative sentence 시작 위치 (토큰); `XS` <= 77 / 77 < `S` <= 128 / 128 < `M` <= 248 / `L` > 248." ) if metric_group == "summary": st.write( "- operation별 `add_*`, `replace_*`, `swap_*` 그리고 negative type별 `relation`, `attribute`, `entity`으로 averaged accuracy." ) for group, model_names in MODEL_GROUPS.items(): st.markdown(f"### {group} models") if metric_group == "summary" and group == "short_captions": st.markdown( "- negative sentence의 시작 위치가 77 토큰 밖에 있는 sample들의 영향, 대체로 random chance accuracy에 아주 근접." ) if metric_group == "summary" and group == "long_captions": st.markdown( "- Context lengths: `DreamLIP, FLAIR`: 77 / `CLIPS`: 80 / `LOTLIP, Recap-CLIP`: 128 / `LongCLIP`: 248 / `TULIP`: 248 or 512 / `Jina-CLIP`: 512" ) st.markdown("- FLAIR 이후 `replace`의 난이도가 `swap`보다 쉬워지는 경우 종종 있음.") st.markdown( "- negative 대상별 난이도 (difficulty)는 `relation` > `entity` > `attrubite`." ) st.markdown( "- Context length가 충분한 모델도 random chance에 근접하는 케이스 많음 (대체로 50%대 accuracy, 좀 잘 나오면 60%대)" ) if metric_group == "summary" and group == "compositionality": st.markdown("- Pretrained CLIP 대비 fine-tuning 후에 정확도 약간 상승") if metric_group == "summary" and group == "decoder-based": # st.markdown("- InstructBLIP의 context length: 128. ") st.markdown("- VQAScore는 Random chance accuracy에 근접하지만, 그래도 CLIP기반 모델보다 성능 좋음") st.markdown( "- VisualGPTScore의 경우 `add`는 정말 못하지만 `replace`나 `swap`같이 word level modification은 극단적으로 잘함. (왜?)" ) st.markdown( "- autoregressive text generation 관점에서, `add` split은 language prior가 없지만, `replace`나 `swap`은 아직 language bias (shortcut)로 정답을 판별할 여지가 있는건가?" ) st.markdown( "- VQAScore에서는 `replace`가 `swap`보다 우세, VisualGPTScore는 `swap`이 우세. " ) st.markdown( "- VQAScore, VisualGPTScore 공통적으로 negative type별 `relation` < `attribute` < `entity` 순으로 어려움." ) if metric_group == "neg_start_positions" and group == "long_captions": st.markdown( "- 대체로 `XS` 위치 (negative sentence 시작이 77 토큰 이내)에서 정확도가 가장 높음. neg sentence가 이후에 시작될수록 정확도가 낮은 경향, but `L 그룹`; 248 토큰 이후 negative sample에서 정확도 증가할 수도 있음" ) if metric_group == "neg_start_positions" and group == "decoder-based": st.markdown( "- InstructBLIP은 input context length 128, output context length는 256으로 제한. description을 input에 태우면 (VQAScore) context length 초과로 evaluation 불가, output에는 태우기 가능 (VisualGPTScore)" ) print_table_overall(df, model_names, metric_group, metric_columns) if selected == "after filtering" and group == "decoder-based": st.write("### decoder-based models (zero-tensor images)") if metric_group == "summary": st.markdown( "- Image 정보가 없을 때 전반적으로 accuracy 하락. VQAScore는 random chance accuracy (50%) 근처인 반면 VisualGPTScore는 여전히 text input만으로 `replace`, `swap` split에서 outperforming 가능" ) st.markdown( "- From VisualGPTScore, Output token propability is critical to identify negative descriptions, even one token change." ) print_table_overall(textonly_df, model_names, metric_group, metric_columns) st.markdown("---") if __name__ == "__main__": main()