File size: 10,351 Bytes
d3b9fea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ce92291
d3b9fea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ce92291
 
 
 
 
 
 
 
 
 
d3b9fea
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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()