yfan07 commited on
Commit
f1106d1
·
verified ·
1 Parent(s): 51e0ad4

Add files using upload-large-folder tool

Browse files
Files changed (47) hide show
  1. .gitattributes +0 -0
  2. ChatUniVi/__init__.py +1 -0
  3. ChatUniVi/config/__init__.py +17 -0
  4. ChatUniVi/config/dataset_config.py +52 -0
  5. ChatUniVi/config/model_config.py +24 -0
  6. ChatUniVi/constants.py +19 -0
  7. ChatUniVi/conversation.py +273 -0
  8. ChatUniVi/demo.py +117 -0
  9. ChatUniVi/eval/evaluate/evaluate_benchmark_1_correctness.py +199 -0
  10. ChatUniVi/eval/evaluate/evaluate_benchmark_2_detailed_orientation.py +199 -0
  11. ChatUniVi/eval/evaluate/evaluate_benchmark_3_context.py +199 -0
  12. ChatUniVi/eval/evaluate/evaluate_benchmark_4_temporal.py +198 -0
  13. ChatUniVi/eval/evaluate/evaluate_benchmark_5_consistency.py +206 -0
  14. ChatUniVi/eval/evaluate/evaluate_gpt_review_visual.py +118 -0
  15. ChatUniVi/eval/evaluate/evaluate_science_qa.py +142 -0
  16. ChatUniVi/eval/evaluate/evaluate_video_qa.py +212 -0
  17. ChatUniVi/eval/evaluate/summarize_gpt_review.py +67 -0
  18. ChatUniVi/eval/model_coco_vqa.py +220 -0
  19. ChatUniVi/eval/model_video_consistency.py +252 -0
  20. ChatUniVi/eval/model_video_general.py +213 -0
  21. ChatUniVi/eval/model_video_qa.py +232 -0
  22. ChatUniVi/eval/model_vqa.py +125 -0
  23. ChatUniVi/eval/model_vqa_scienceqa.py +164 -0
  24. ChatUniVi/eval/questions/coco2014_val_qa_eval/qa90_gpt4_answer.jsonl +90 -0
  25. ChatUniVi/eval/questions/coco2014_val_qa_eval/qa90_questions.jsonl +90 -0
  26. ChatUniVi/eval/questions/coco_pope/coco_pope_adversarial.jsonl +0 -0
  27. ChatUniVi/eval/questions/coco_pope/coco_pope_popular.jsonl +0 -0
  28. ChatUniVi/eval/questions/coco_pope/coco_pope_random.jsonl +0 -0
  29. ChatUniVi/eval/questions/scienceqa/pid_splits.json +0 -0
  30. ChatUniVi/eval/questions/scienceqa/test_QCM-LEA.json +0 -0
  31. ChatUniVi/eval/questions/video_qa/activitynet_a_list.json +2105 -0
  32. ChatUniVi/eval/questions/video_qa/activitynet_qa.json +0 -0
  33. ChatUniVi/eval/questions/video_qa/consistency_qa.json +0 -0
  34. ChatUniVi/eval/questions/video_qa/generic_qa.json +0 -0
  35. ChatUniVi/eval/questions/video_qa/msrvtt_a_list.json +4175 -0
  36. ChatUniVi/eval/questions/video_qa/msrvtt_qa.json +0 -0
  37. ChatUniVi/eval/questions/video_qa/msvd_a_list.json +1202 -0
  38. ChatUniVi/mm_utils.py +73 -0
  39. ChatUniVi/utils.py +126 -0
  40. README.md +88 -0
  41. SEG_LTPO_results.md +348 -0
  42. load_model.py +877 -0
  43. requirements.txt +76 -0
  44. save_audio_feats.py +83 -0
  45. save_sam_feats.py +96 -0
  46. seg_ltpo.py +786 -0
  47. train.py +534 -0
.gitattributes CHANGED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .model import ChatUniViLlamaForCausalLM
ChatUniVi/config/__init__.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .dataset_config import *
2
+ from .model_config import *
3
+
4
+
5
+ ModelConfig = {
6
+ "PRETUNE": model_config_pretune,
7
+ "FINETUNE": model_config_finetune,
8
+ }
9
+
10
+
11
+ DataConfig = {
12
+ "Pretrain": [Pretrain, COCO_CAP, COCO_REG, COCO_REC],
13
+ "SQA": [SQA],
14
+ "FINETUNE": [VIT, MIMIC_imageonly, VIDEO],
15
+ "Pretrainv1.5": [Pretrain, Pretrain_valley_llava],
16
+ "FINETUNEv1.5": [VIT, VIDEO, LLaVA],
17
+ }
ChatUniVi/config/dataset_config.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Pretrain = {
2
+ "chat_path": "${PATH}/CC3M-595K/chat.json",
3
+ "CC3M": "${PATH}/CC3M-595K",
4
+ }
5
+
6
+ VIT = {
7
+ "chat_path": "${PATH}/llava_instruct_150k.json",
8
+ "COCO2017": "${PATH}/COCO2017/train2017",
9
+ }
10
+
11
+ MIMIC_imageonly = {
12
+ "chat_path": "${PATH}/MIMIC-IT-imageonly.json",
13
+ "CDG": "${PATH}/CGD/images",
14
+ "LA": "${PATH}/LA/images",
15
+ "SD": "${PATH}/SD/images",
16
+ }
17
+
18
+ COCO_CAP = {
19
+ "chat_path": "${PATH}/COCO/coco_cap_chat.json",
20
+ "COCO2014": "${PATH}/COCO2014/train2014",
21
+ }
22
+
23
+ COCO_REG = {
24
+ "chat_path": "${PATH}/COCO/coco_reg_chat.json",
25
+ "COCO2014": "${PATH}/COCO2014/train2014",
26
+ }
27
+
28
+ COCO_REC = {
29
+ "chat_path": "${PATH}/COCO/coco_rec_chat.json",
30
+ "COCO2014": "${PATH}/COCO2014/train2014",
31
+ }
32
+
33
+ VIDEO = {
34
+ "chat_path": "${PATH}/video_chat.json",
35
+ "VIDEO": "${PATH}/Activity_Videos",
36
+ }
37
+
38
+ SQA = {
39
+ "chat_path": "${PATH}/llava_train_QCM-LEA.json",
40
+ "ScienceQA": "${PATH}/scienceqa/train",
41
+ }
42
+
43
+ Pretrain_valley_llava = {
44
+ "chat_path": "${PATH}/valley_llavaimage.json",
45
+ "valley": "${PATH}/Data",
46
+ "llava": "${PATH}/Data", # from llava v1.5
47
+ }
48
+
49
+ LLaVA = {
50
+ "chat_path": "${PATH}/llavaimage_tune.json",
51
+ "llava": "${PATH}/Data", # from llava v1.5
52
+ }
ChatUniVi/config/model_config.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model_config_pretune = {
2
+ "use_cluster": True,
3
+ "freeze": False,
4
+ "vision_tune": False,
5
+
6
+ "spatial_cluster_rate0": 64, # 0.25
7
+ "spatial_cluster_rate1": 32, # 0.5
8
+ "spatial_cluster_rate2": 16, # 0.5
9
+
10
+ "temporal_cluster_rate": 1/16,
11
+ }
12
+
13
+ model_config_finetune = {
14
+ "use_cluster": True,
15
+ "freeze": False,
16
+ "mm_tune": True,
17
+ "vision_tune": False,
18
+
19
+ "spatial_cluster_rate0": 64, # 0.25
20
+ "spatial_cluster_rate1": 32, # 0.5
21
+ "spatial_cluster_rate2": 16, # 0.5
22
+
23
+ "temporal_cluster_rate": 1/16,
24
+ }
ChatUniVi/constants.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CONTROLLER_HEART_BEAT_EXPIRATION = 30
2
+ WORKER_HEART_BEAT_INTERVAL = 15
3
+
4
+ LOGDIR = "."
5
+
6
+ # Model Constants
7
+ MAX_IMAGE_LENGTH = 64
8
+ IGNORE_INDEX = -100
9
+ IMAGE_TOKEN_INDEX = -200
10
+ DEFAULT_IMAGE_TOKEN = "<image>"
11
+ DEFAULT_VIDEO_TOKEN = "<video>"
12
+ DEFAULT_IMAGE_PATCH_TOKEN = "<im_patch>"
13
+ DEFAULT_IM_START_TOKEN = "<im_start>"
14
+ DEFAULT_IM_END_TOKEN = "<im_end>"
15
+ DEFAULT_VIDEO_PATCH_TOKEN = "<vid_patch>"
16
+ DEFAULT_VID_START_TOKEN = "<vid_start>"
17
+ DEFAULT_VID_END_TOKEN = "<vid_end>"
18
+ DEFAULT_BOX_START_TOKEN = "<box_start>"
19
+ DEFAULT_BOX_END_TOKEN = "<box_end>"
ChatUniVi/conversation.py ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dataclasses
2
+ from enum import auto, Enum
3
+ from typing import List, Tuple
4
+
5
+
6
+ class SeparatorStyle(Enum):
7
+ """Different separator style."""
8
+ SINGLE = auto()
9
+ TWO = auto()
10
+ MPT = auto()
11
+ PLAIN = auto()
12
+ LLAMA_2 = auto()
13
+
14
+
15
+ @dataclasses.dataclass
16
+ class Conversation:
17
+ """A class that keeps all conversation history."""
18
+ system: str
19
+ roles: List[str]
20
+ messages: List[List[str]]
21
+ offset: int
22
+ sep_style: SeparatorStyle = SeparatorStyle.SINGLE
23
+ sep: str = "###"
24
+ sep2: str = None
25
+ version: str = "Unknown"
26
+
27
+ skip_next: bool = False
28
+
29
+ def get_prompt(self):
30
+ messages = self.messages
31
+ if len(messages) > 0 and type(messages[0][1]) is tuple:
32
+ messages = self.messages.copy()
33
+ init_role, init_msg = messages[0].copy()
34
+ init_msg = init_msg[0].replace("<image>", "").strip()
35
+ if 'mmtag' in self.version:
36
+ messages[0] = (init_role, init_msg)
37
+ messages.insert(0, (self.roles[0], "<Image><image></Image>"))
38
+ messages.insert(1, (self.roles[1], "Received."))
39
+ else:
40
+ messages[0] = (init_role, "<image>\n" + init_msg)
41
+
42
+ if self.sep_style == SeparatorStyle.SINGLE:
43
+ ret = self.system + self.sep
44
+ for role, message in messages:
45
+ if message:
46
+ if type(message) is tuple:
47
+ message, _, _ = message
48
+ ret += role + ": " + message + self.sep
49
+ else:
50
+ ret += role + ":"
51
+ elif self.sep_style == SeparatorStyle.TWO:
52
+ seps = [self.sep, self.sep2]
53
+ ret = self.system + seps[0]
54
+ for i, (role, message) in enumerate(messages):
55
+ if message:
56
+ if type(message) is tuple:
57
+ message, _, _ = message
58
+ ret += role + ": " + message + seps[i % 2]
59
+ else:
60
+ ret += role + ":"
61
+ elif self.sep_style == SeparatorStyle.MPT:
62
+ ret = self.system + self.sep
63
+ for role, message in messages:
64
+ if message:
65
+ if type(message) is tuple:
66
+ message, _, _ = message
67
+ ret += role + message + self.sep
68
+ else:
69
+ ret += role
70
+ elif self.sep_style == SeparatorStyle.LLAMA_2:
71
+ wrap_sys = lambda msg: f"<<SYS>>\n{msg}\n<</SYS>>\n\n"
72
+ wrap_inst = lambda msg: f"[INST] {msg} [/INST]"
73
+ ret = ""
74
+
75
+ for i, (role, message) in enumerate(messages):
76
+ if i == 0:
77
+ assert message, "first message should not be none"
78
+ assert role == self.roles[0], "first message should come from user"
79
+ if message:
80
+ if type(message) is tuple:
81
+ message, _, _ = message
82
+ if i == 0: message = wrap_sys(self.system) + message
83
+ if i % 2 == 0:
84
+ message = wrap_inst(message)
85
+ ret += self.sep + message
86
+ else:
87
+ ret += " " + message + " " + self.sep2
88
+ else:
89
+ ret += ""
90
+ ret = ret.lstrip(self.sep)
91
+ elif self.sep_style == SeparatorStyle.PLAIN:
92
+ seps = [self.sep, self.sep2]
93
+ ret = self.system
94
+ for i, (role, message) in enumerate(messages):
95
+ if message:
96
+ if type(message) is tuple:
97
+ message, _, _ = message
98
+ ret += message + seps[i % 2]
99
+ else:
100
+ ret += ""
101
+ else:
102
+ raise ValueError(f"Invalid style: {self.sep_style}")
103
+
104
+ return ret
105
+
106
+ def append_message(self, role, message):
107
+ self.messages.append([role, message])
108
+
109
+ def get_images(self, return_pil=False):
110
+ images = []
111
+ for i, (role, msg) in enumerate(self.messages[self.offset:]):
112
+ if i % 2 == 0:
113
+ if type(msg) is tuple:
114
+ import base64
115
+ from io import BytesIO
116
+ from PIL import Image
117
+ msg, image, image_process_mode = msg
118
+ if image_process_mode == "Pad":
119
+ def expand2square(pil_img, background_color=(122, 116, 104)):
120
+ width, height = pil_img.size
121
+ if width == height:
122
+ return pil_img
123
+ elif width > height:
124
+ result = Image.new(pil_img.mode, (width, width), background_color)
125
+ result.paste(pil_img, (0, (width - height) // 2))
126
+ return result
127
+ else:
128
+ result = Image.new(pil_img.mode, (height, height), background_color)
129
+ result.paste(pil_img, ((height - width) // 2, 0))
130
+ return result
131
+ image = expand2square(image)
132
+ elif image_process_mode == "Crop":
133
+ pass
134
+ elif image_process_mode == "Resize":
135
+ image = image.resize((336, 336))
136
+ else:
137
+ raise ValueError(f"Invalid image_process_mode: {image_process_mode}")
138
+ max_hw, min_hw = max(image.size), min(image.size)
139
+ aspect_ratio = max_hw / min_hw
140
+ max_len, min_len = 800, 400
141
+ shortest_edge = int(min(max_len / aspect_ratio, min_len, min_hw))
142
+ longest_edge = int(shortest_edge * aspect_ratio)
143
+ W, H = image.size
144
+ if H > W:
145
+ H, W = longest_edge, shortest_edge
146
+ else:
147
+ H, W = shortest_edge, longest_edge
148
+ image = image.resize((W, H))
149
+ if return_pil:
150
+ images.append(image)
151
+ else:
152
+ buffered = BytesIO()
153
+ image.save(buffered, format="PNG")
154
+ img_b64_str = base64.b64encode(buffered.getvalue()).decode()
155
+ images.append(img_b64_str)
156
+ return images
157
+
158
+ def to_gradio_chatbot(self):
159
+ ret = []
160
+ for i, (role, msg) in enumerate(self.messages[self.offset:]):
161
+ if i % 2 == 0:
162
+ if type(msg) is tuple:
163
+ import base64
164
+ from io import BytesIO
165
+ msg, image, image_process_mode = msg
166
+ max_hw, min_hw = max(image.size), min(image.size)
167
+ aspect_ratio = max_hw / min_hw
168
+ max_len, min_len = 800, 400
169
+ shortest_edge = int(min(max_len / aspect_ratio, min_len, min_hw))
170
+ longest_edge = int(shortest_edge * aspect_ratio)
171
+ W, H = image.size
172
+ if H > W:
173
+ H, W = longest_edge, shortest_edge
174
+ else:
175
+ H, W = shortest_edge, longest_edge
176
+ image = image.resize((W, H))
177
+ buffered = BytesIO()
178
+ image.save(buffered, format="JPEG")
179
+ img_b64_str = base64.b64encode(buffered.getvalue()).decode()
180
+ img_str = f'<img src="data:image/png;base64,{img_b64_str}" alt="user upload image" />'
181
+ ret.append([img_str, None])
182
+ msg = msg.replace('<image>', '').strip()
183
+ if len(msg) > 0:
184
+ ret.append([msg, None])
185
+ else:
186
+ ret.append([msg, None])
187
+ else:
188
+ ret[-1][-1] = msg
189
+ return ret
190
+
191
+ def copy(self):
192
+ return Conversation(
193
+ system=self.system,
194
+ roles=self.roles,
195
+ messages=[[x, y] for x, y in self.messages],
196
+ offset=self.offset,
197
+ sep_style=self.sep_style,
198
+ sep=self.sep,
199
+ sep2=self.sep2,
200
+ version=self.version)
201
+
202
+ def dict(self):
203
+ if len(self.get_images()) > 0:
204
+ return {
205
+ "system": self.system,
206
+ "roles": self.roles,
207
+ "messages": [[x, y[0] if type(y) is tuple else y] for x, y in self.messages],
208
+ "offset": self.offset,
209
+ "sep": self.sep,
210
+ "sep2": self.sep2,
211
+ }
212
+ return {
213
+ "system": self.system,
214
+ "roles": self.roles,
215
+ "messages": self.messages,
216
+ "offset": self.offset,
217
+ "sep": self.sep,
218
+ "sep2": self.sep2,
219
+ }
220
+
221
+
222
+ conv_v1 = Conversation(
223
+ system="A chat between a curious user and an artificial intelligence assistant. "
224
+ "The assistant gives helpful, detailed, and polite answers to the user's questions.",
225
+ roles=("USER", "ASSISTANT"),
226
+ version="v1",
227
+ messages=(),
228
+ offset=0,
229
+ sep_style=SeparatorStyle.TWO,
230
+ sep=" ",
231
+ sep2="</s>",
232
+ )
233
+
234
+
235
+ simple_qa = Conversation(
236
+ system="A chat between a curious human and an artificial intelligence assistant. "
237
+ "The assistant gives helpful, detailed, and polite answers to the human's questions. "
238
+ " If you don't know the answer to a question, please don't share false information.",
239
+ roles=("Human", "Assistant"),
240
+ messages=(
241
+ ("Human", "Is there a snowboard in the image?"),
242
+ ("Assistant", "Yes, there is a snowboard in the image, and the person is riding it down a snow-covered slope.")
243
+ ),
244
+ offset=2,
245
+ sep_style=SeparatorStyle.SINGLE,
246
+ sep="###",
247
+ )
248
+
249
+ simple_conv = Conversation(
250
+ system="A chat between a curious human and an artificial intelligence assistant. "
251
+ "The assistant gives helpful, detailed, and polite answers to the human's questions.",
252
+ roles=("Human", "Assistant"),
253
+ messages=(
254
+ ("Human", "Hi!"),
255
+ ("Assistant", "Hi there! How can I help you today?")
256
+ ),
257
+ offset=2,
258
+ sep_style=SeparatorStyle.SINGLE,
259
+ sep="###",
260
+ )
261
+
262
+
263
+ default_conversation = simple_conv
264
+ conv_templates = {
265
+ "default": simple_conv,
266
+ "simple": simple_conv,
267
+ "simpleqa": simple_qa,
268
+ "v1": conv_v1,
269
+ }
270
+
271
+
272
+ if __name__ == "__main__":
273
+ print(default_conversation.get_prompt())
ChatUniVi/demo.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from .constants import *
3
+ from .conversation import conv_templates, SeparatorStyle
4
+ from .model.builder import load_pretrained_model
5
+ from .utils import disable_torch_init
6
+ from .mm_utils import tokenizer_image_token, KeywordsStoppingCriteria
7
+ from PIL import Image
8
+ import os
9
+ from decord import VideoReader, cpu
10
+ import numpy as np
11
+
12
+
13
+ class Chat:
14
+ def __init__(self, model_path, conv_mode="simple"):
15
+ disable_torch_init()
16
+ self.tokenizer, self.model, self.image_processor, context_len = load_pretrained_model(model_path, None, model_name="ChatUniVi")
17
+
18
+ mm_use_im_start_end = getattr(self.model.config, "mm_use_im_start_end", False)
19
+ mm_use_im_patch_token = getattr(self.model.config, "mm_use_im_patch_token", True)
20
+ if mm_use_im_patch_token:
21
+ self.tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
22
+ if mm_use_im_start_end:
23
+ self.tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
24
+ self.model.resize_token_embeddings(len(self.tokenizer))
25
+
26
+ vision_tower = self.model.get_vision_tower()
27
+ if not vision_tower.is_loaded:
28
+ vision_tower.load_model()
29
+
30
+ self.image_processor = vision_tower.image_processor
31
+ self.conv_mode = conv_mode
32
+ print(self.model)
33
+
34
+ def get_prompt(self, qs, state):
35
+ state.append_message(state.roles[0], qs)
36
+ state.append_message(state.roles[1], None)
37
+ return state
38
+
39
+ def _get_rawvideo_dec(self, video_path, image_processor, max_frames=MAX_IMAGE_LENGTH, image_resolution=224,
40
+ video_framerate=1, s=None, e=None):
41
+ if s is None:
42
+ start_time, end_time = None, None
43
+ else:
44
+ start_time = int(s)
45
+ end_time = int(e)
46
+ start_time = start_time if start_time >= 0. else 0.
47
+ end_time = end_time if end_time >= 0. else 0.
48
+ if start_time > end_time:
49
+ start_time, end_time = end_time, start_time
50
+ elif start_time == end_time:
51
+ end_time = start_time + 1
52
+
53
+ if os.path.exists(video_path):
54
+ vreader = VideoReader(video_path, ctx=cpu(0))
55
+ else:
56
+ print(video_path)
57
+ raise FileNotFoundError
58
+
59
+ fps = vreader.get_avg_fps()
60
+ f_start = 0 if start_time is None else int(start_time * fps)
61
+ f_end = int(min(1000000000 if end_time is None else end_time * fps, len(vreader) - 1))
62
+ num_frames = f_end - f_start + 1
63
+ if num_frames > 0:
64
+ sample_fps = int(video_framerate)
65
+ t_stride = int(round(float(fps) / sample_fps))
66
+
67
+ all_pos = list(range(f_start, f_end + 1, t_stride))
68
+ if len(all_pos) > max_frames:
69
+ sample_pos = [all_pos[_] for _ in np.linspace(0, len(all_pos) - 1, num=max_frames, dtype=int)]
70
+ else:
71
+ sample_pos = all_pos
72
+
73
+ patch_images = [Image.fromarray(f) for f in vreader.get_batch(sample_pos).asnumpy()]
74
+ return patch_images
75
+
76
+ @torch.inference_mode()
77
+ def generate(self, images_tensor: list, prompt: str, first_run: bool, state):
78
+ tokenizer, model, image_processor = self.tokenizer, self.model, self.image_processor
79
+
80
+ state = self.get_prompt(prompt, state)
81
+ prompt = state.get_prompt()
82
+ print(prompt)
83
+
84
+ images_tensor = torch.stack(images_tensor, dim=0)
85
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(0).cuda()
86
+
87
+ temperature = 0.2
88
+ max_new_tokens = 1024
89
+
90
+ stop_str = conv_templates[self.conv_mode].copy().sep if conv_templates[self.conv_mode].copy().sep_style != SeparatorStyle.TWO else \
91
+ conv_templates[self.conv_mode].copy().sep2
92
+ keywords = [stop_str]
93
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
94
+
95
+ with torch.inference_mode():
96
+ output_ids = model.generate(
97
+ input_ids,
98
+ images=images_tensor,
99
+ do_sample=True,
100
+ temperature=temperature,
101
+ num_beams=1,
102
+ max_new_tokens=max_new_tokens,
103
+ use_cache=True,
104
+ stopping_criteria=[stopping_criteria])
105
+
106
+ input_token_len = input_ids.shape[1]
107
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
108
+ if n_diff_input_output > 0:
109
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
110
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
111
+ outputs = outputs.strip()
112
+ if outputs.endswith(stop_str):
113
+ outputs = outputs[:-len(stop_str)]
114
+ outputs = outputs.strip()
115
+
116
+ print('response', outputs)
117
+ return outputs, state
ChatUniVi/eval/evaluate/evaluate_benchmark_1_correctness.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import os
3
+ import argparse
4
+ import json
5
+ import jsonlines
6
+ import ast
7
+ from multiprocessing.pool import Pool
8
+
9
+
10
+ def read_jsonl(file):
11
+ results = []
12
+ with open(file, encoding='utf-8') as f:
13
+ for item in jsonlines.Reader(f):
14
+ results.append(item)
15
+ return results
16
+
17
+
18
+ def parse_args():
19
+ parser = argparse.ArgumentParser(description="question-answer-generation-using-gpt-3")
20
+ parser.add_argument("--pred_path", required=True, help="The path to file containing prediction.")
21
+ parser.add_argument("--output_dir", required=True, help="The path to save annotation json files.")
22
+ parser.add_argument("--output_json", required=True, help="The path to save annotation final combined json file.")
23
+ parser.add_argument("--api_key", required=True, help="OpenAI API key.")
24
+ parser.add_argument("--num_tasks", required=True, type=int, help="Number of splits.")
25
+ args = parser.parse_args()
26
+ return args
27
+
28
+
29
+ def annotate(prediction_set, caption_files, output_dir):
30
+ """
31
+ Evaluates question and answer pairs using GPT-3
32
+ Returns a score for correctness.
33
+ """
34
+ for file in caption_files:
35
+ key = file[:-5] # Strip file extension
36
+ qa_set = prediction_set[key]
37
+ question = qa_set['q']
38
+ answer = qa_set['a']
39
+ pred = qa_set['pred']
40
+ try:
41
+ # Compute the correctness score
42
+ completion = openai.ChatCompletion.create(
43
+ model="gpt-3.5-turbo",
44
+ messages=[
45
+ {
46
+ "role": "system",
47
+ "content":
48
+ "You are an intelligent chatbot designed for evaluating the factual accuracy of generative outputs for video-based question-answer pairs. "
49
+ "Your task is to compare the predicted answer with the correct answer and determine if they are factually consistent. Here's how you can accomplish the task:"
50
+ "------"
51
+ "##INSTRUCTIONS: "
52
+ "- Focus on the factual consistency between the predicted answer and the correct answer. The predicted answer should not contain any misinterpretations or misinformation.\n"
53
+ "- The predicted answer must be factually accurate and align with the video content.\n"
54
+ "- Consider synonyms or paraphrases as valid matches.\n"
55
+ "- Evaluate the factual accuracy of the prediction compared to the answer."
56
+ },
57
+ {
58
+ "role": "user",
59
+ "content":
60
+ "Please evaluate the following video-based question-answer pair:\n\n"
61
+ f"Question: {question}\n"
62
+ f"Correct Answer: {answer}\n"
63
+ f"Predicted Answer: {pred}\n\n"
64
+ "Provide your evaluation only as a factual accuracy score where the factual accuracy score is an integer value between 0 and 5, with 5 indicating the highest level of factual consistency. "
65
+ "Please generate the response in the form of a Python dictionary string with keys 'score', where its value is the factual accuracy score in INTEGER, not STRING."
66
+ "DO NOT PROVIDE ANY OTHER OUTPUT TEXT OR EXPLANATION. Only provide the Python dictionary string. "
67
+ "For example, your response should look like this: {''score': 4.8}."
68
+ }
69
+ ]
70
+ )
71
+ # Convert response to a Python dictionary.
72
+ response_message = completion["choices"][0]["message"]["content"]
73
+ response_dict = ast.literal_eval(response_message)
74
+ result_qa_pair = [response_dict, qa_set]
75
+
76
+ # Save the question-answer pairs to a json file.
77
+ with open(f"{output_dir}/{key}.json", "w") as f:
78
+ json.dump(result_qa_pair, f)
79
+
80
+ except Exception as e:
81
+ print(f"Error processing file '{key}': {e}")
82
+
83
+
84
+ def main():
85
+ """
86
+ Main function to control the flow of the program.
87
+ """
88
+ # Parse arguments.
89
+ args = parse_args()
90
+
91
+ file = args.pred_path
92
+ try:
93
+ pred_contents = json.load(file)
94
+ except:
95
+ pred_contents = read_jsonl(file)
96
+
97
+ # Dictionary to store the count of occurrences for each video_id
98
+ video_id_counts = {}
99
+ new_pred_contents = []
100
+
101
+ # Iterate through each sample in pred_contents
102
+ for sample in pred_contents:
103
+ sample['video_name'] = 1
104
+ video_id = sample['video_name']
105
+ if video_id in video_id_counts:
106
+ video_id_counts[video_id] += 1
107
+ else:
108
+ video_id_counts[video_id] = 0
109
+
110
+ # Create a new sample with the modified key
111
+ new_sample = sample
112
+ new_sample['video_name'] = f"{video_id}_{video_id_counts[video_id]}"
113
+ new_pred_contents.append(new_sample)
114
+
115
+ # Generating list of id's and corresponding files
116
+ id_list = [x['video_name'] for x in new_pred_contents]
117
+ caption_files = [f"{id}.json" for id in id_list]
118
+
119
+ output_dir = args.output_dir
120
+ # Generate output directory if not exists.
121
+ if not os.path.exists(output_dir):
122
+ os.makedirs(output_dir)
123
+
124
+ # Preparing dictionary of question-answer sets
125
+ prediction_set = {}
126
+ for sample in new_pred_contents:
127
+ id = sample['video_name']
128
+ question = sample['prompt']
129
+ answer = sample['answer']
130
+ pred = sample['text']
131
+ qa_set = {"q": question, "a": answer, "pred": pred}
132
+ prediction_set[id] = qa_set
133
+
134
+ # Set the OpenAI API key.
135
+ openai.api_key = args.api_key
136
+ num_tasks = args.num_tasks
137
+
138
+ # While loop to ensure that all captions are processed.
139
+ while True:
140
+ try:
141
+ # Files that have not been processed yet.
142
+ completed_files = os.listdir(output_dir)
143
+ print(f"completed_files: {len(completed_files)}")
144
+
145
+ # Files that have not been processed yet.
146
+ incomplete_files = [f for f in caption_files if f not in completed_files]
147
+ print(f"incomplete_files: {len(incomplete_files)}")
148
+
149
+ # Break the loop when there are no incomplete files
150
+ if len(incomplete_files) == 0:
151
+ break
152
+ if len(incomplete_files) <= num_tasks:
153
+ num_tasks = 1
154
+
155
+ # Split tasks into parts.
156
+ part_len = len(incomplete_files) // num_tasks
157
+ all_parts = [incomplete_files[i:i + part_len] for i in range(0, len(incomplete_files), part_len)]
158
+ task_args = [(prediction_set, part, args.output_dir) for part in all_parts]
159
+
160
+ # Use a pool of workers to process the files in parallel.
161
+ with Pool() as pool:
162
+ pool.starmap(annotate, task_args)
163
+
164
+ except Exception as e:
165
+ print(f"Error: {e}")
166
+
167
+ # Combine all the processed files into one
168
+ combined_contents = {}
169
+ json_path = args.output_json
170
+
171
+ # Iterate through json files
172
+ for file_name in os.listdir(output_dir):
173
+ if file_name.endswith(".json"):
174
+ file_path = os.path.join(output_dir, file_name)
175
+ with open(file_path, "r") as json_file:
176
+ content = json.load(json_file)
177
+ combined_contents[file_name[:-5]] = content
178
+
179
+ # Write combined content to a json file
180
+ with open(json_path, "w") as json_file:
181
+ json.dump(combined_contents, json_file)
182
+ print("All evaluation completed!")
183
+
184
+ # Calculate average score
185
+ score_sum = 0
186
+ count = 0
187
+ for key, result in combined_contents.items():
188
+ count += 1
189
+ score_match = result[0]['score']
190
+ score = int(score_match)
191
+ score_sum += score
192
+ average_score = score_sum / count
193
+
194
+ print("Average score for correctness:", average_score * 20)
195
+
196
+
197
+ if __name__ == "__main__":
198
+ main()
199
+
ChatUniVi/eval/evaluate/evaluate_benchmark_2_detailed_orientation.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import os
3
+ import argparse
4
+ import json
5
+ import jsonlines
6
+ import ast
7
+ from multiprocessing.pool import Pool
8
+
9
+
10
+ def read_jsonl(file):
11
+ results = []
12
+ with open(file, encoding='utf-8') as f:
13
+ for item in jsonlines.Reader(f):
14
+ results.append(item)
15
+ return results
16
+
17
+
18
+ def parse_args():
19
+ parser = argparse.ArgumentParser(description="question-answer-generation-using-gpt-3")
20
+ parser.add_argument("--pred_path", required=True, help="The path to file containing prediction.")
21
+ parser.add_argument("--output_dir", required=True, help="The path to save annotation json files.")
22
+ parser.add_argument("--output_json", required=True, help="The path to save annotation final combined json file.")
23
+ parser.add_argument("--api_key", required=True, help="OpenAI API key.")
24
+ parser.add_argument("--num_tasks", required=True, type=int, help="Number of splits.")
25
+ args = parser.parse_args()
26
+ return args
27
+
28
+
29
+ def annotate(prediction_set, caption_files, output_dir):
30
+ """
31
+ Evaluates question and answer pairs using GPT-3 and
32
+ returns a score for detailed orientation.
33
+ """
34
+ for file in caption_files:
35
+ key = file[:-5] # Strip file extension
36
+ qa_set = prediction_set[key]
37
+ question = qa_set['q']
38
+ answer = qa_set['a']
39
+ pred = qa_set['pred']
40
+ try:
41
+ # Compute the detailed-orientation score
42
+ completion = openai.ChatCompletion.create(
43
+ model="gpt-3.5-turbo",
44
+ messages=[
45
+ {
46
+ "role": "system",
47
+ "content":
48
+ "You are an intelligent chatbot designed for evaluating the detail orientation of generative outputs for video-based question-answer pairs. "
49
+ "Your task is to compare the predicted answer with the correct answer and determine its level of detail, considering both completeness and specificity. Here's how you can accomplish the task:"
50
+ "------"
51
+ "##INSTRUCTIONS: "
52
+ "- Check if the predicted answer covers all major points from the video. The response should not leave out any key aspects.\n"
53
+ "- Evaluate whether the predicted answer includes specific details rather than just generic points. It should provide comprehensive information that is tied to specific elements of the video.\n"
54
+ "- Consider synonyms or paraphrases as valid matches.\n"
55
+ "- Provide a single evaluation score that reflects the level of detail orientation of the prediction, considering both completeness and specificity."
56
+ },
57
+ {
58
+ "role": "user",
59
+ "content":
60
+ "Please evaluate the following video-based question-answer pair:\n\n"
61
+ f"Question: {question}\n"
62
+ f"Correct Answer: {answer}\n"
63
+ f"Predicted Answer: {pred}\n\n"
64
+ "Provide your evaluation only as a detail orientation score where the detail orientation score is an integer value between 0 and 5, with 5 indicating the highest level of detail orientation. "
65
+ "Please generate the response in the form of a Python dictionary string with keys 'score', where its value is the detail orientation score in INTEGER, not STRING."
66
+ "DO NOT PROVIDE ANY OTHER OUTPUT TEXT OR EXPLANATION. Only provide the Python dictionary string. "
67
+ "For example, your response should look like this: {''score': 4.8}."
68
+ }
69
+ ]
70
+ )
71
+ # Convert response to a Python dictionary.
72
+ response_message = completion["choices"][0]["message"]["content"]
73
+ response_dict = ast.literal_eval(response_message)
74
+ result_qa_pair = [response_dict, qa_set]
75
+
76
+ # Save the question-answer pairs to a json file.
77
+ with open(f"{output_dir}/{key}.json", "w") as f:
78
+ json.dump(result_qa_pair, f)
79
+
80
+ except Exception as e:
81
+ print(f"Error processing file '{key}': {e}")
82
+
83
+
84
+ def main():
85
+ """
86
+ Main function to control the flow of the program.
87
+ """
88
+ # Parse arguments.
89
+ args = parse_args()
90
+
91
+ file = args.pred_path
92
+ try:
93
+ pred_contents = json.load(file)
94
+ except:
95
+ pred_contents = read_jsonl(file)
96
+
97
+ # Dictionary to store the count of occurrences for each video_id
98
+ video_id_counts = {}
99
+ new_pred_contents = []
100
+
101
+ # Iterate through each sample in pred_contents
102
+ for sample in pred_contents:
103
+ sample['video_name'] = 1
104
+ video_id = sample['video_name']
105
+ if video_id in video_id_counts:
106
+ video_id_counts[video_id] += 1
107
+ else:
108
+ video_id_counts[video_id] = 0
109
+
110
+ # Create a new sample with the modified key
111
+ new_sample = sample
112
+ new_sample['video_name'] = f"{video_id}_{video_id_counts[video_id]}"
113
+ new_pred_contents.append(new_sample)
114
+
115
+ # Generating list of id's and corresponding files
116
+ id_list = [x['video_name'] for x in new_pred_contents]
117
+ caption_files = [f"{id}.json" for id in id_list]
118
+
119
+ output_dir = args.output_dir
120
+ # Generate output directory if not exists.
121
+ if not os.path.exists(output_dir):
122
+ os.makedirs(output_dir)
123
+
124
+ # Preparing dictionary of question-answer sets
125
+ prediction_set = {}
126
+ for sample in new_pred_contents:
127
+ id = sample['video_name']
128
+ question = sample['prompt']
129
+ answer = sample['answer']
130
+ pred = sample['text']
131
+ qa_set = {"q": question, "a": answer, "pred": pred}
132
+ prediction_set[id] = qa_set
133
+
134
+ # Set the OpenAI API key.
135
+ openai.api_key = args.api_key
136
+ num_tasks = args.num_tasks
137
+
138
+ # While loop to ensure that all captions are processed.
139
+ while True:
140
+ try:
141
+ # Files that have not been processed yet.
142
+ completed_files = os.listdir(output_dir)
143
+ print(f"completed_files: {len(completed_files)}")
144
+
145
+ # Files that have not been processed yet.
146
+ incomplete_files = [f for f in caption_files if f not in completed_files]
147
+ print(f"incomplete_files: {len(incomplete_files)}")
148
+
149
+ # Break the loop when there are no incomplete files
150
+ if len(incomplete_files) == 0:
151
+ break
152
+ if len(incomplete_files) <= num_tasks:
153
+ num_tasks = 1
154
+
155
+ # Split tasks into parts.
156
+ part_len = len(incomplete_files) // num_tasks
157
+ all_parts = [incomplete_files[i:i + part_len] for i in range(0, len(incomplete_files), part_len)]
158
+ task_args = [(prediction_set, part, args.output_dir) for part in all_parts]
159
+
160
+ # Use a pool of workers to process the files in parallel.
161
+ with Pool() as pool:
162
+ pool.starmap(annotate, task_args)
163
+
164
+ except Exception as e:
165
+ print(f"Error: {e}")
166
+
167
+ # Combine all the processed files into one
168
+ combined_contents = {}
169
+ json_path = args.output_json
170
+
171
+ # Iterate through json files
172
+ for file_name in os.listdir(output_dir):
173
+ if file_name.endswith(".json"):
174
+ file_path = os.path.join(output_dir, file_name)
175
+ with open(file_path, "r") as json_file:
176
+ content = json.load(json_file)
177
+ combined_contents[file_name[:-5]] = content
178
+
179
+ # Write combined content to a json file
180
+ with open(json_path, "w") as json_file:
181
+ json.dump(combined_contents, json_file)
182
+ print("All evaluation completed!")
183
+
184
+ # Calculate average score
185
+ score_sum = 0
186
+ count = 0
187
+ for key, result in combined_contents.items():
188
+ count += 1
189
+ score_match = result[0]['score']
190
+ score = int(score_match)
191
+ score_sum += score
192
+ average_score = score_sum / count
193
+
194
+ print("Average score for detailed orientation:", average_score * 20)
195
+
196
+
197
+ if __name__ == "__main__":
198
+ main()
199
+
ChatUniVi/eval/evaluate/evaluate_benchmark_3_context.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import os
3
+ import argparse
4
+ import json
5
+ import jsonlines
6
+ import ast
7
+ from multiprocessing.pool import Pool
8
+
9
+
10
+ def read_jsonl(file):
11
+ results = []
12
+ with open(file, encoding='utf-8') as f:
13
+ for item in jsonlines.Reader(f):
14
+ results.append(item)
15
+ return results
16
+
17
+
18
+ def parse_args():
19
+ parser = argparse.ArgumentParser(description="question-answer-generation-using-gpt-3")
20
+ parser.add_argument("--pred_path", required=True, help="The path to file containing prediction.")
21
+ parser.add_argument("--output_dir", required=True, help="The path to save annotation json files.")
22
+ parser.add_argument("--output_json", required=True, help="The path to save annotation final combined json file.")
23
+ parser.add_argument("--api_key", required=True, help="OpenAI API key.")
24
+ parser.add_argument("--num_tasks", required=True, type=int, help="Number of splits.")
25
+ args = parser.parse_args()
26
+ return args
27
+
28
+
29
+ def annotate(prediction_set, caption_files, output_dir):
30
+ """
31
+ Evaluates question and answer pairs using GPT-3 and
32
+ returns a score for contextual understanding.
33
+ """
34
+ for file in caption_files:
35
+ key = file[:-5] # Strip file extension
36
+ qa_set = prediction_set[key]
37
+ question = qa_set['q']
38
+ answer = qa_set['a']
39
+ pred = qa_set['pred']
40
+ try:
41
+ # Compute the contextual understanding score
42
+ completion = openai.ChatCompletion.create(
43
+ model="gpt-3.5-turbo",
44
+ messages=[
45
+ {
46
+ "role": "system",
47
+ "content":
48
+ "You are an intelligent chatbot designed for evaluating the contextual understanding of generative outputs for video-based question-answer pairs. "
49
+ "Your task is to compare the predicted answer with the correct answer and determine if the generated response aligns with the overall context of the video content. Here's how you can accomplish the task:"
50
+ "------"
51
+ "##INSTRUCTIONS: "
52
+ "- Evaluate whether the predicted answer aligns with the overall context of the video content. It should not provide information that is out of context or misaligned.\n"
53
+ "- The predicted answer must capture the main themes and sentiments of the video.\n"
54
+ "- Consider synonyms or paraphrases as valid matches.\n"
55
+ "- Provide your evaluation of the contextual understanding of the prediction compared to the answer."
56
+ },
57
+ {
58
+ "role": "user",
59
+ "content":
60
+ "Please evaluate the following video-based question-answer pair:\n\n"
61
+ f"Question: {question}\n"
62
+ f"Correct Answer: {answer}\n"
63
+ f"Predicted Answer: {pred}\n\n"
64
+ "Provide your evaluation only as a contextual understanding score where the contextual understanding score is an integer value between 0 and 5, with 5 indicating the highest level of contextual understanding. "
65
+ "Please generate the response in the form of a Python dictionary string with keys 'score', where its value is contextual understanding score in INTEGER, not STRING."
66
+ "DO NOT PROVIDE ANY OTHER OUTPUT TEXT OR EXPLANATION. Only provide the Python dictionary string. "
67
+ "For example, your response should look like this: {''score': 4.8}."
68
+ }
69
+ ]
70
+ )
71
+ # Convert response to a Python dictionary.
72
+ response_message = completion["choices"][0]["message"]["content"]
73
+ response_dict = ast.literal_eval(response_message)
74
+ result_qa_pair = [response_dict, qa_set]
75
+
76
+ # Save the question-answer pairs to a json file.
77
+ with open(f"{output_dir}/{key}.json", "w") as f:
78
+ json.dump(result_qa_pair, f)
79
+
80
+ except Exception as e:
81
+ print(f"Error processing file '{key}': {e}")
82
+
83
+
84
+ def main():
85
+ """
86
+ Main function to control the flow of the program.
87
+ """
88
+ # Parse arguments.
89
+ args = parse_args()
90
+
91
+ file = args.pred_path
92
+ try:
93
+ pred_contents = json.load(file)
94
+ except:
95
+ pred_contents = read_jsonl(file)
96
+
97
+ # Dictionary to store the count of occurrences for each video_id
98
+ video_id_counts = {}
99
+ new_pred_contents = []
100
+
101
+ # Iterate through each sample in pred_contents
102
+ for sample in pred_contents:
103
+ sample['video_name'] = 1
104
+ video_id = sample['video_name']
105
+ if video_id in video_id_counts:
106
+ video_id_counts[video_id] += 1
107
+ else:
108
+ video_id_counts[video_id] = 0
109
+
110
+ # Create a new sample with the modified key
111
+ new_sample = sample
112
+ new_sample['video_name'] = f"{video_id}_{video_id_counts[video_id]}"
113
+ new_pred_contents.append(new_sample)
114
+
115
+ # Generating list of id's and corresponding files
116
+ id_list = [x['video_name'] for x in new_pred_contents]
117
+ caption_files = [f"{id}.json" for id in id_list]
118
+
119
+ output_dir = args.output_dir
120
+ # Generate output directory if not exists.
121
+ if not os.path.exists(output_dir):
122
+ os.makedirs(output_dir)
123
+
124
+ # Preparing dictionary of question-answer sets
125
+ prediction_set = {}
126
+ for sample in new_pred_contents:
127
+ id = sample['video_name']
128
+ question = sample['prompt']
129
+ answer = sample['answer']
130
+ pred = sample['text']
131
+ qa_set = {"q": question, "a": answer, "pred": pred}
132
+ prediction_set[id] = qa_set
133
+
134
+ # Set the OpenAI API key.
135
+ openai.api_key = args.api_key
136
+ num_tasks = args.num_tasks
137
+
138
+ # While loop to ensure that all captions are processed.
139
+ while True:
140
+ try:
141
+ # Files that have not been processed yet.
142
+ completed_files = os.listdir(output_dir)
143
+ print(f"completed_files: {len(completed_files)}")
144
+
145
+ # Files that have not been processed yet.
146
+ incomplete_files = [f for f in caption_files if f not in completed_files]
147
+ print(f"incomplete_files: {len(incomplete_files)}")
148
+
149
+ # Break the loop when there are no incomplete files
150
+ if len(incomplete_files) == 0:
151
+ break
152
+ if len(incomplete_files) <= num_tasks:
153
+ num_tasks = 1
154
+
155
+ # Split tasks into parts.
156
+ part_len = len(incomplete_files) // num_tasks
157
+ all_parts = [incomplete_files[i:i + part_len] for i in range(0, len(incomplete_files), part_len)]
158
+ task_args = [(prediction_set, part, args.output_dir) for part in all_parts]
159
+
160
+ # Use a pool of workers to process the files in parallel.
161
+ with Pool() as pool:
162
+ pool.starmap(annotate, task_args)
163
+
164
+ except Exception as e:
165
+ print(f"Error: {e}")
166
+
167
+ # Combine all the processed files into one
168
+ combined_contents = {}
169
+ json_path = args.output_json
170
+
171
+ # Iterate through json files
172
+ for file_name in os.listdir(output_dir):
173
+ if file_name.endswith(".json"):
174
+ file_path = os.path.join(output_dir, file_name)
175
+ with open(file_path, "r") as json_file:
176
+ content = json.load(json_file)
177
+ combined_contents[file_name[:-5]] = content
178
+
179
+ # Write combined content to a json file
180
+ with open(json_path, "w") as json_file:
181
+ json.dump(combined_contents, json_file)
182
+ print("All evaluation completed!")
183
+
184
+ # Calculate average score
185
+ score_sum = 0
186
+ count = 0
187
+ for key, result in combined_contents.items():
188
+ count += 1
189
+ score_match = result[0]['score']
190
+ score = int(score_match)
191
+ score_sum += score
192
+ average_score = score_sum / count
193
+
194
+ print("Average score for contextual understanding:", average_score * 20)
195
+
196
+
197
+ if __name__ == "__main__":
198
+ main()
199
+
ChatUniVi/eval/evaluate/evaluate_benchmark_4_temporal.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import os
3
+ import argparse
4
+ import json
5
+ import jsonlines
6
+ import ast
7
+ from multiprocessing.pool import Pool
8
+
9
+
10
+ def read_jsonl(file):
11
+ results = []
12
+ with open(file, encoding='utf-8') as f:
13
+ for item in jsonlines.Reader(f):
14
+ results.append(item)
15
+ return results
16
+
17
+
18
+ def parse_args():
19
+ parser = argparse.ArgumentParser(description="question-answer-generation-using-gpt-3")
20
+ parser.add_argument("--pred_path", required=True, help="The path to file containing prediction.")
21
+ parser.add_argument("--output_dir", required=True, help="The path to save annotation json files.")
22
+ parser.add_argument("--output_json", required=True, help="The path to save annotation final combined json file.")
23
+ parser.add_argument("--api_key", required=True, help="OpenAI API key.")
24
+ parser.add_argument("--num_tasks", required=True, type=int, help="Number of splits.")
25
+ args = parser.parse_args()
26
+ return args
27
+
28
+
29
+ def annotate(prediction_set, caption_files, output_dir):
30
+ """
31
+ Evaluates question and answer pairs using GPT-3 and
32
+ returns a score for temporal understanding.
33
+ """
34
+ for file in caption_files:
35
+ key = file[:-5] # Strip file extension
36
+ qa_set = prediction_set[key]
37
+ question = qa_set['q']
38
+ answer = qa_set['a']
39
+ pred = qa_set['pred']
40
+ try:
41
+ # Compute the temporal understanding score
42
+ completion = openai.ChatCompletion.create(
43
+ model="gpt-3.5-turbo",
44
+ messages=[
45
+ {
46
+ "role": "system",
47
+ "content":
48
+ "You are an intelligent chatbot designed for evaluating the temporal understanding of generative outputs for video-based question-answer pairs. "
49
+ "Your task is to compare the predicted answer with the correct answer and determine if they correctly reflect the temporal sequence of events in the video content. Here's how you can accomplish the task:"
50
+ "------"
51
+ "##INSTRUCTIONS: "
52
+ "- Focus on the temporal consistency between the predicted answer and the correct answer. The predicted answer should correctly reflect the sequence of events or details as they are presented in the video content.\n"
53
+ "- Consider synonyms or paraphrases as valid matches, but only if the temporal order is maintained.\n"
54
+ "- Evaluate the temporal accuracy of the prediction compared to the answer."
55
+ },
56
+ {
57
+ "role": "user",
58
+ "content":
59
+ "Please evaluate the following video-based question-answer pair:\n\n"
60
+ f"Question: {question}\n"
61
+ f"Correct Answer: {answer}\n"
62
+ f"Predicted Answer: {pred}\n\n"
63
+ "Provide your evaluation only as a temporal accuracy score where the temporal accuracy score is an integer value between 0 and 5, with 5 indicating the highest level of temporal consistency. "
64
+ "Please generate the response in the form of a Python dictionary string with keys 'score', where its value is the temporal accuracy score in INTEGER, not STRING."
65
+ "DO NOT PROVIDE ANY OTHER OUTPUT TEXT OR EXPLANATION. Only provide the Python dictionary string. "
66
+ "For example, your response should look like this: {''score': 4.8}."
67
+ }
68
+ ]
69
+ )
70
+ # Convert response to a Python dictionary.
71
+ response_message = completion["choices"][0]["message"]["content"]
72
+ response_dict = ast.literal_eval(response_message)
73
+ result_qa_pair = [response_dict, qa_set]
74
+
75
+ # Save the question-answer pairs to a json file.
76
+ with open(f"{output_dir}/{key}.json", "w") as f:
77
+ json.dump(result_qa_pair, f)
78
+
79
+ except Exception as e:
80
+ print(f"Error processing file '{key}': {e}")
81
+
82
+
83
+ def main():
84
+ """
85
+ Main function to control the flow of the program.
86
+ """
87
+ # Parse arguments.
88
+ args = parse_args()
89
+
90
+ file = args.pred_path
91
+ try:
92
+ pred_contents = json.load(file)
93
+ except:
94
+ pred_contents = read_jsonl(file)
95
+
96
+ # Dictionary to store the count of occurrences for each video_id
97
+ video_id_counts = {}
98
+ new_pred_contents = []
99
+
100
+ # Iterate through each sample in pred_contents
101
+ for sample in pred_contents:
102
+ sample['video_name'] = 1
103
+ video_id = sample['video_name']
104
+ if video_id in video_id_counts:
105
+ video_id_counts[video_id] += 1
106
+ else:
107
+ video_id_counts[video_id] = 0
108
+
109
+ # Create a new sample with the modified key
110
+ new_sample = sample
111
+ new_sample['video_name'] = f"{video_id}_{video_id_counts[video_id]}"
112
+ new_pred_contents.append(new_sample)
113
+
114
+ # Generating list of id's and corresponding files
115
+ id_list = [x['video_name'] for x in new_pred_contents]
116
+ caption_files = [f"{id}.json" for id in id_list]
117
+
118
+ output_dir = args.output_dir
119
+ # Generate output directory if not exists.
120
+ if not os.path.exists(output_dir):
121
+ os.makedirs(output_dir)
122
+
123
+ # Preparing dictionary of question-answer sets
124
+ prediction_set = {}
125
+ for sample in new_pred_contents:
126
+ id = sample['video_name']
127
+ question = sample['prompt']
128
+ answer = sample['answer']
129
+ pred = sample['text']
130
+ qa_set = {"q": question, "a": answer, "pred": pred}
131
+ prediction_set[id] = qa_set
132
+
133
+ # Set the OpenAI API key.
134
+ openai.api_key = args.api_key
135
+ num_tasks = args.num_tasks
136
+
137
+ # While loop to ensure that all captions are processed.
138
+ while True:
139
+ try:
140
+ # Files that have not been processed yet.
141
+ completed_files = os.listdir(output_dir)
142
+ print(f"completed_files: {len(completed_files)}")
143
+
144
+ # Files that have not been processed yet.
145
+ incomplete_files = [f for f in caption_files if f not in completed_files]
146
+ print(f"incomplete_files: {len(incomplete_files)}")
147
+
148
+ # Break the loop when there are no incomplete files
149
+ if len(incomplete_files) == 0:
150
+ break
151
+ if len(incomplete_files) <= num_tasks:
152
+ num_tasks = 1
153
+
154
+ # Split tasks into parts.
155
+ part_len = len(incomplete_files) // num_tasks
156
+ all_parts = [incomplete_files[i:i + part_len] for i in range(0, len(incomplete_files), part_len)]
157
+ task_args = [(prediction_set, part, args.output_dir) for part in all_parts]
158
+
159
+ # Use a pool of workers to process the files in parallel.
160
+ with Pool() as pool:
161
+ pool.starmap(annotate, task_args)
162
+
163
+ except Exception as e:
164
+ print(f"Error: {e}")
165
+
166
+ # Combine all the processed files into one
167
+ combined_contents = {}
168
+ json_path = args.output_json
169
+
170
+ # Iterate through json files
171
+ for file_name in os.listdir(output_dir):
172
+ if file_name.endswith(".json"):
173
+ file_path = os.path.join(output_dir, file_name)
174
+ with open(file_path, "r") as json_file:
175
+ content = json.load(json_file)
176
+ combined_contents[file_name[:-5]] = content
177
+
178
+ # Write combined content to a json file
179
+ with open(json_path, "w") as json_file:
180
+ json.dump(combined_contents, json_file)
181
+ print("All evaluation completed!")
182
+
183
+ # Calculate average score
184
+ score_sum = 0
185
+ count = 0
186
+ for key, result in combined_contents.items():
187
+ count += 1
188
+ score_match = result[0]['score']
189
+ score = int(score_match)
190
+ score_sum += score
191
+ average_score = score_sum / count
192
+
193
+ print("Average score temporal understanding:", average_score * 20)
194
+
195
+
196
+ if __name__ == "__main__":
197
+ main()
198
+
ChatUniVi/eval/evaluate/evaluate_benchmark_5_consistency.py ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import os
3
+ import argparse
4
+ import json
5
+ import jsonlines
6
+ import ast
7
+ from multiprocessing.pool import Pool
8
+
9
+
10
+ def read_jsonl(file):
11
+ results = []
12
+ with open(file, encoding='utf-8') as f:
13
+ for item in jsonlines.Reader(f):
14
+ results.append(item)
15
+ return results
16
+
17
+
18
+ def parse_args():
19
+ parser = argparse.ArgumentParser(description="question-answer-generation-using-gpt-3")
20
+ parser.add_argument("--pred_path", required=True, help="The path to file containing prediction.")
21
+ parser.add_argument("--output_dir", required=True, help="The path to save annotation json files.")
22
+ parser.add_argument("--output_json", required=True, help="The path to save annotation final combined json file.")
23
+ parser.add_argument("--api_key", required=True, help="OpenAI API key.")
24
+ parser.add_argument("--num_tasks", required=True, type=int, help="Number of splits.")
25
+ args = parser.parse_args()
26
+ return args
27
+
28
+
29
+ def annotate(prediction_set, caption_files, output_dir):
30
+ """
31
+ Evaluates question and answer pairs using GPT-3 and
32
+ returns a score for consistency.
33
+ """
34
+ for file in caption_files:
35
+ key = file[:-5] # Strip file extension
36
+ qa_set = prediction_set[key]
37
+ question1 = qa_set['q1']
38
+ question2 = qa_set['q2']
39
+ answer = qa_set['a']
40
+ pred1 = qa_set['pred1']
41
+ pred2 = qa_set['pred2']
42
+ try:
43
+ # Compute the consistency score
44
+ completion = openai.ChatCompletion.create(
45
+ model="gpt-3.5-turbo",
46
+ messages=[
47
+ {
48
+ "role": "system",
49
+ "content":
50
+ "You are an intelligent chatbot designed for evaluating the consistency of generative outputs for similar video-based question-answer pairs. "
51
+ "You will be given two very similar questions, a common answer common to both the questions and predicted answers for the two questions ."
52
+ "Your task is to compare the predicted answers for two very similar question, with a common correct answer and determine if they are consistent. Here's how you can accomplish the task:"
53
+ "------"
54
+ "##INSTRUCTIONS: "
55
+ "- Focus on the consistency between the two predicted answers and the correct answer. Both predicted answers should correspond to the correct answer and to each other, and should not contain any contradictions or significant differences in the conveyed information.\n"
56
+ "- Both predicted answers must be consistent with each other and the correct answer, in terms of the information they provide about the video content.\n"
57
+ "- Consider synonyms or paraphrases as valid matches, but only if they maintain the consistency in the conveyed information.\n"
58
+ "- Evaluate the consistency of the two predicted answers compared to the correct answer."
59
+ },
60
+ {
61
+ "role": "user",
62
+ "content":
63
+ "Please evaluate the following video-based question-answer pair:\n\n"
64
+ f"Question 1: {question1}\n"
65
+ f"Question 2: {question2}\n"
66
+ f"Correct Answer: {answer}\n"
67
+ f"Predicted Answer to Question 1: {pred1}\n"
68
+ f"Predicted Answer to Question 2: {pred2}\n\n"
69
+ "Provide your evaluation only as a consistency score where the consistency score is an integer value between 0 and 5, with 5 indicating the highest level of consistency. "
70
+ "Please generate the response in the form of a Python dictionary string with keys 'score', where its value is the consistency score in INTEGER, not STRING."
71
+ "DO NOT PROVIDE ANY OTHER OUTPUT TEXT OR EXPLANATION. Only provide the Python dictionary string. "
72
+ "For example, your response should look like this: {''score': 4.8}."
73
+ }
74
+ ],
75
+ )
76
+ # Convert response to a Python dictionary.
77
+ response_message = completion["choices"][0]["message"]["content"]
78
+ response_dict = ast.literal_eval(response_message)
79
+ result_qa_pair = [response_dict, qa_set]
80
+
81
+ # Save the question-answer pairs to a json file.
82
+ with open(f"{output_dir}/{key}.json", "w") as f:
83
+ json.dump(result_qa_pair, f)
84
+
85
+ except Exception as e:
86
+ print(f"Error processing file '{key}': {e}")
87
+
88
+
89
+ def main():
90
+ """
91
+ Main function to control the flow of the program.
92
+ """
93
+ # Parse arguments.
94
+ args = parse_args()
95
+
96
+ file = args.pred_path
97
+ try:
98
+ pred_contents = json.load(file)
99
+ except:
100
+ pred_contents = read_jsonl(file)
101
+
102
+ # Dictionary to store the count of occurrences for each video_id
103
+ video_id_counts = {}
104
+ new_pred_contents = []
105
+
106
+ # Iterate through each sample in pred_contents
107
+ for sample in pred_contents:
108
+ # video_id = sample['video_name']
109
+ video_id = 1
110
+ if video_id in video_id_counts:
111
+ video_id_counts[video_id] += 1
112
+ else:
113
+ video_id_counts[video_id] = 0
114
+
115
+ # Create a new sample with the modified key
116
+ new_sample = sample
117
+ new_sample['video_name'] = f"{video_id}_{video_id_counts[video_id]}"
118
+ new_pred_contents.append(new_sample)
119
+
120
+ # Generating list of id's and corresponding files
121
+ id_list = [x['video_name'] for x in new_pred_contents]
122
+ caption_files = [f"{id}.json" for id in id_list]
123
+
124
+ output_dir = args.output_dir
125
+ # Generate output directory if not exists.
126
+ if not os.path.exists(output_dir):
127
+ os.makedirs(output_dir)
128
+
129
+ # Preparing dictionary of question-answer sets
130
+ prediction_set = {}
131
+ for sample in new_pred_contents:
132
+ id = sample['video_name']
133
+ question1 = sample['prompt_1']
134
+ question2 = sample['prompt_2']
135
+ answer = sample['answer']
136
+ pred1 = sample['text_1']
137
+ pred2 = sample['text_2']
138
+ qa_set = {"q1": question1, "q2": question2, "a": answer, "pred1": pred1, "pred2": pred2}
139
+ prediction_set[id] = qa_set
140
+
141
+ # Set the OpenAI API key.
142
+ openai.api_key = args.api_key
143
+ num_tasks = args.num_tasks
144
+
145
+ # While loop to ensure that all captions are processed.
146
+ while True:
147
+ try:
148
+ # Files that have not been processed yet.
149
+ completed_files = os.listdir(output_dir)
150
+ print(f"completed_files: {len(completed_files)}")
151
+
152
+ # Files that have not been processed yet.
153
+ incomplete_files = [f for f in caption_files if f not in completed_files]
154
+ print(f"incomplete_files: {len(incomplete_files)}")
155
+
156
+ # Break the loop when there are no incomplete files
157
+ if len(incomplete_files) == 0:
158
+ break
159
+ if len(incomplete_files) <= num_tasks:
160
+ num_tasks = 1
161
+
162
+ # Split tasks into parts.
163
+ part_len = len(incomplete_files) // num_tasks
164
+ all_parts = [incomplete_files[i:i + part_len] for i in range(0, len(incomplete_files), part_len)]
165
+ task_args = [(prediction_set, part, args.output_dir) for part in all_parts]
166
+
167
+ # Use a pool of workers to process the files in parallel.
168
+ with Pool() as pool:
169
+ pool.starmap(annotate, task_args)
170
+
171
+ except Exception as e:
172
+ print(f"Error: {e}")
173
+
174
+ # Combine all the processed files into one
175
+ combined_contents = {}
176
+ json_path = args.output_json
177
+
178
+ # Iterate through json files
179
+ for file_name in os.listdir(output_dir):
180
+ if file_name.endswith(".json"):
181
+ file_path = os.path.join(output_dir, file_name)
182
+ with open(file_path, "r") as json_file:
183
+ content = json.load(json_file)
184
+ combined_contents[file_name[:-5]] = content
185
+
186
+ # Write combined content to a json file
187
+ with open(json_path, "w") as json_file:
188
+ json.dump(combined_contents, json_file)
189
+ print("All evaluation completed!")
190
+
191
+ # Calculate average score
192
+ score_sum = 0
193
+ count = 0
194
+ for key, result in combined_contents.items():
195
+ count += 1
196
+ score_match = result[0]['score']
197
+ score = int(score_match)
198
+ score_sum += score
199
+ average_score = score_sum / count
200
+
201
+ print("Average score for consistency:", average_score * 20)
202
+
203
+
204
+ if __name__ == "__main__":
205
+ main()
206
+
ChatUniVi/eval/evaluate/evaluate_gpt_review_visual.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import json
3
+ import os
4
+ import requests
5
+ import openai
6
+ import time
7
+
8
+ NUM_SECONDS_TO_SLEEP = 0.5
9
+
10
+
11
+ def get_eval(content: str, max_tokens: int):
12
+ while True:
13
+ try:
14
+ response = openai.ChatCompletion.create(
15
+ model='gpt-4-0314', # gpt-4-0314
16
+ messages=[{
17
+ 'role': 'system',
18
+ 'content': 'You are a helpful and precise assistant for checking the quality of the answer.'
19
+ }, {
20
+ 'role': 'user',
21
+ 'content': content,
22
+ }],
23
+ temperature=0.2, # TODO: figure out which temperature is best for evaluation
24
+ max_tokens=max_tokens,
25
+ )
26
+ break
27
+ except openai.error.RateLimitError:
28
+ pass
29
+ except Exception as e:
30
+ print(e)
31
+ time.sleep(NUM_SECONDS_TO_SLEEP)
32
+
33
+ return response['choices'][0]['message']['content']
34
+
35
+
36
+ def parse_score(review):
37
+ try:
38
+ score_pair = review.split('\n')[0]
39
+ score_pair = score_pair.replace(',', ' ')
40
+ sp = score_pair.split(' ')
41
+ if len(sp) == 2:
42
+ return [float(sp[0]), float(sp[1])]
43
+ else:
44
+ print('error', review)
45
+ return [-1, -1]
46
+ except Exception as e:
47
+ print(e)
48
+ print('error', review)
49
+ return [-1, -1]
50
+
51
+
52
+ if __name__ == '__main__':
53
+ parser = argparse.ArgumentParser(description='ChatGPT-based QA evaluation.')
54
+ parser.add_argument('-q', '--question')
55
+ parser.add_argument('-c', '--context')
56
+ parser.add_argument('-a', '--answer-list', nargs='+', default=[])
57
+ parser.add_argument('-r', '--rule')
58
+ parser.add_argument('-o', '--output')
59
+ parser.add_argument('--max-tokens', type=int, default=1024, help='maximum number of tokens produced in the output')
60
+ args = parser.parse_args()
61
+
62
+ f_q = open(os.path.expanduser(args.question))
63
+ f_ans1 = open(os.path.expanduser(args.answer_list[0]))
64
+ f_ans2 = open(os.path.expanduser(args.answer_list[1]))
65
+ rule_dict = json.load(open(os.path.expanduser(args.rule), 'r'))
66
+
67
+ if os.path.isfile(os.path.expanduser(args.output)):
68
+ cur_reviews = [json.loads(line) for line in open(os.path.expanduser(args.output))]
69
+ else:
70
+ cur_reviews = []
71
+
72
+ review_file = open(f'{args.output}', 'a')
73
+
74
+ context_list = [json.loads(line) for line in open(os.path.expanduser(args.context))]
75
+ image_to_context = {context['image']: context for context in context_list}
76
+
77
+ handles = []
78
+ idx = 0
79
+ for ques_js, ans1_js, ans2_js in zip(f_q, f_ans1, f_ans2):
80
+ ques = json.loads(ques_js)
81
+ ans1 = json.loads(ans1_js)
82
+ ans2 = json.loads(ans2_js)
83
+
84
+ inst = image_to_context[ques['image']]
85
+ cap_str = '\n'.join(inst['captions'])
86
+ box_str = '\n'.join([f'{instance["category"]}: {instance["bbox"]}' for instance in inst['instances']])
87
+
88
+ category = json.loads(ques_js)['category']
89
+ if category in rule_dict:
90
+ rule = rule_dict[category]
91
+ else:
92
+ assert False, f"Visual QA category not found in rule file: {category}."
93
+ prompt = rule['prompt']
94
+ role = rule['role']
95
+ content = (f'[Context]\n{cap_str}\n\n{box_str}\n\n'
96
+ f'[Question]\n{ques["text"]}\n\n'
97
+ f'[{role} 1]\n{ans1["text"]}\n\n[End of {role} 1]\n\n'
98
+ f'[{role} 2]\n{ans2["text"]}\n\n[End of {role} 2]\n\n'
99
+ f'[System]\n{prompt}\n\n')
100
+ cur_js = {
101
+ 'id': idx+1,
102
+ 'question_id': ques['question_id'],
103
+ 'answer1_id': ans1.get('answer_id', ans1['question_id']),
104
+ 'answer2_id': ans2.get('answer_id', ans2['answer_id']),
105
+ 'category': category
106
+ }
107
+ if idx >= len(cur_reviews):
108
+ review = get_eval(content, args.max_tokens)
109
+ scores = parse_score(review)
110
+ cur_js['content'] = review
111
+ cur_js['tuple'] = scores
112
+ review_file.write(json.dumps(cur_js) + '\n')
113
+ review_file.flush()
114
+ else:
115
+ print(f'Skipping {idx} as we already have it.')
116
+ idx += 1
117
+ print(idx)
118
+ review_file.close()
ChatUniVi/eval/evaluate/evaluate_science_qa.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import json
3
+ import os
4
+ import re
5
+ import random
6
+ import numpy as np
7
+
8
+
9
+ def get_args():
10
+ parser = argparse.ArgumentParser()
11
+ parser.add_argument('--base-dir', type=str)
12
+ parser.add_argument('--result-file', type=str)
13
+ parser.add_argument('--output-file', type=str)
14
+ parser.add_argument('--output-result', type=str)
15
+ parser.add_argument('--split', type=str, default='test')
16
+ parser.add_argument('--options', type=list, default=["A", "B", "C", "D", "E"])
17
+ return parser.parse_args()
18
+
19
+
20
+ def convert_caps(results):
21
+ fakecaps = []
22
+ for result in results:
23
+ image_id = result['question_id']
24
+ caption = result['text']
25
+ fakecaps.append({"image_id": int(image_id), "caption": caption})
26
+ return fakecaps
27
+
28
+
29
+ def get_pred_idx(prediction, choices, options):
30
+ """
31
+ Get the index (e.g. 2) from the prediction (e.g. 'C')
32
+ """
33
+ if prediction in options[:len(choices)]:
34
+ return options.index(prediction)
35
+ else:
36
+ return random.choice(range(len(choices)))
37
+
38
+
39
+ if __name__ == "__main__":
40
+ args = get_args()
41
+
42
+ base_dir = args.base_dir
43
+ split_indices = json.load(open(os.path.join(base_dir, "pid_splits.json")))[args.split]
44
+ problems = json.load(open(os.path.join(base_dir, "problems.json")))
45
+ predictions = [json.loads(line) for line in open(args.result_file)]
46
+ predictions = {pred['question_id']: pred for pred in predictions}
47
+ split_problems = {idx: problems[idx] for idx in split_indices}
48
+
49
+ results = {'correct': [], 'incorrect': []}
50
+ sqa_results = {}
51
+ sqa_results['acc'] = None
52
+ sqa_results['correct'] = None
53
+ sqa_results['count'] = None
54
+ sqa_results['results'] = {}
55
+ sqa_results['outputs'] = {}
56
+
57
+ sqa_results['NAT'] = []
58
+ sqa_results['SOC'] = []
59
+ sqa_results['LAN'] = []
60
+ sqa_results['TXT'] = []
61
+ sqa_results['IMG'] = []
62
+ sqa_results['NO'] = []
63
+ sqa_results['G1-6'] = []
64
+ sqa_results['G7-12'] = []
65
+
66
+ for prob_id, prob in split_problems.items():
67
+ if prob_id not in predictions:
68
+ continue
69
+ pred = predictions[prob_id]
70
+ pred_text = pred['text']
71
+
72
+ pattern = re.compile(r'The answer is ([A-Z]).')
73
+ res = pattern.findall(pred_text)
74
+ if len(res) == 1:
75
+ answer = res[0] # 'A', 'B', ...
76
+ else:
77
+ answer = pred['pred']
78
+
79
+ pred_idx = get_pred_idx(answer, prob['choices'], args.options)
80
+
81
+ analysis = {
82
+ 'question_id': prob_id,
83
+ 'parsed_ans': answer,
84
+ 'ground_truth': args.options[prob['answer']],
85
+ 'question': pred['prompt'],
86
+ 'pred': pred_text,
87
+ 'is_multimodal': '<image>' in pred['prompt'],
88
+ }
89
+
90
+ sqa_results['results'][prob_id] = get_pred_idx(answer, prob['choices'], args.options)
91
+ sqa_results['outputs'][prob_id] = pred_text
92
+
93
+ if pred_idx == prob['answer']:
94
+ results['correct'].append(analysis)
95
+ cur_result = 1
96
+ else:
97
+ results['incorrect'].append(analysis)
98
+ cur_result = 0
99
+
100
+ if prob['subject'] == 'natural science':
101
+ sqa_results['NAT'].append(cur_result)
102
+ elif prob['subject'] == 'social science':
103
+ sqa_results['SOC'].append(cur_result)
104
+ elif prob['subject'] == 'language science':
105
+ sqa_results['LAN'].append(cur_result)
106
+
107
+ if prob['hint']:
108
+ sqa_results['TXT'].append(cur_result)
109
+ if prob['image']:
110
+ sqa_results['IMG'].append(cur_result)
111
+ if not prob['hint'] and not prob['image']:
112
+ sqa_results['NO'].append(cur_result)
113
+
114
+ if prob['grade'] in ['grade1', 'grade2', 'grade3', 'grade4', 'grade5', 'grade6']:
115
+ sqa_results['G1-6'].append(cur_result)
116
+ elif prob['grade'] in ['grade7', 'grade8', 'grade9', 'grade10', 'grade11', 'grade12']:
117
+ sqa_results['G7-12'].append(cur_result)
118
+
119
+
120
+ correct = len(results['correct'])
121
+ total = len(results['correct']) + len(results['incorrect'])
122
+ print(f'Total: {total}, Correct: {correct}, Accuracy: {correct / total * 100:.2f}%')
123
+
124
+ print(f'Subject NAT: {len(sqa_results["NAT"])}, Correct: {sum(sqa_results["NAT"])}, Accuracy: {np.mean(sqa_results["NAT"]) * 100:.2f}%')
125
+ print(f'Subject SOC: {len(sqa_results["SOC"])}, Correct: {sum(sqa_results["SOC"])}, Accuracy: {np.mean(sqa_results["SOC"]) * 100:.2f}%')
126
+ print(f'Subject LAN: {len(sqa_results["LAN"])}, Correct: {sum(sqa_results["LAN"])}, Accuracy: {np.mean(sqa_results["LAN"]) * 100:.2f}%')
127
+
128
+ print(f'Context Modality TXT: {len(sqa_results["TXT"])}, Correct: {sum(sqa_results["TXT"])}, Accuracy: {np.mean(sqa_results["TXT"]) * 100:.2f}%')
129
+ print(f'Context Modality IMG: {len(sqa_results["IMG"])}, Correct: {sum(sqa_results["IMG"])}, Accuracy: {np.mean(sqa_results["IMG"]) * 100:.2f}%')
130
+ print(f'Context Modality NO: {len(sqa_results["NO"])}, Correct: {sum(sqa_results["NO"])}, Accuracy: {np.mean(sqa_results["NO"]) * 100:.2f}%')
131
+
132
+ print(f'Grade G1-6: {len(sqa_results["G1-6"])}, Correct: {sum(sqa_results["G1-6"])}, Accuracy: {np.mean(sqa_results["G1-6"]) * 100:.2f}%')
133
+ print(f'Grade G7-12: {len(sqa_results["G7-12"])}, Correct: {sum(sqa_results["G7-12"])}, Accuracy: {np.mean(sqa_results["G7-12"]) * 100:.2f}%')
134
+
135
+ sqa_results['acc'] = correct / total * 100
136
+ sqa_results['correct'] = correct
137
+ sqa_results['count'] = total
138
+
139
+ with open(args.output_file, 'w') as f:
140
+ json.dump(results, f, indent=2)
141
+ with open(args.output_result, 'w') as f:
142
+ json.dump(sqa_results, f, indent=2)
ChatUniVi/eval/evaluate/evaluate_video_qa.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import os
3
+ import argparse
4
+ import json
5
+ import jsonlines
6
+ import ast
7
+ from multiprocessing.pool import Pool
8
+
9
+
10
+ def read_jsonl(file):
11
+ results = []
12
+ with open(file, encoding='utf-8') as f:
13
+ for item in jsonlines.Reader(f):
14
+ results.append(item)
15
+ return results
16
+
17
+
18
+ def parse_args():
19
+ parser = argparse.ArgumentParser(description="question-answer-generation-using-gpt-3")
20
+ parser.add_argument("--pred_path", required=True, help="The path to file containing prediction.")
21
+ parser.add_argument("--output_dir", required=True, help="The path to save annotation json files.")
22
+ parser.add_argument("--output_json", required=True, help="The path to save annotation final combined json file.")
23
+ parser.add_argument("--api_key", required=True, help="OpenAI API key.")
24
+ parser.add_argument("--num_tasks", required=True, type=int, help="Number of splits.")
25
+ args = parser.parse_args()
26
+ return args
27
+
28
+
29
+ def annotate(prediction_set, caption_files, output_dir):
30
+ """
31
+ Evaluates question and answer pairs using GPT-3
32
+ Returns a score for correctness.
33
+ """
34
+ for file in caption_files:
35
+ key = file[:-5] # Strip file extension
36
+ qa_set = prediction_set[key]
37
+ question = qa_set['q']
38
+ answer = qa_set['a']
39
+ pred = qa_set['pred']
40
+ try:
41
+ # Compute the correctness score
42
+ completion = openai.ChatCompletion.create(
43
+ model="gpt-3.5-turbo",
44
+ messages=[
45
+ {
46
+ "role": "system",
47
+ "content":
48
+ "You are an intelligent chatbot designed for evaluating the correctness of generative outputs for question-answer pairs. "
49
+ "Your task is to compare the predicted answer with the correct answer and determine if they match meaningfully. Here's how you can accomplish the task:"
50
+ "------"
51
+ "##INSTRUCTIONS: "
52
+ "- Focus on the meaningful match between the predicted answer and the correct answer.\n"
53
+ "- Consider synonyms or paraphrases as valid matches.\n"
54
+ "- Evaluate the correctness of the prediction compared to the answer."
55
+ },
56
+ {
57
+ "role": "user",
58
+ "content":
59
+ "Please evaluate the following video-based question-answer pair:\n\n"
60
+ f"Question: {question}\n"
61
+ f"Correct Answer: {answer}\n"
62
+ f"Predicted Answer: {pred}\n\n"
63
+ "Provide your evaluation only as a yes/no and score where the score is an integer value between 0 and 5, with 5 indicating the highest meaningful match. "
64
+ "Please generate the response in the form of a Python dictionary string with keys 'pred' and 'score', where value of 'pred' is a string of 'yes' or 'no' and value of 'score' is in INTEGER, not STRING."
65
+ "DO NOT PROVIDE ANY OTHER OUTPUT TEXT OR EXPLANATION. Only provide the Python dictionary string. "
66
+ "For example, your response should look like this: {'pred': 'yes', 'score': 4.8}."
67
+ }
68
+ ]
69
+ )
70
+ # Convert response to a Python dictionary.
71
+ response_message = completion["choices"][0]["message"]["content"]
72
+ response_dict = ast.literal_eval(response_message)
73
+ result_qa_pair = [response_dict, qa_set]
74
+
75
+ # Save the question-answer pairs to a json file.
76
+ with open(f"{output_dir}/{key}.json", "w") as f:
77
+ json.dump(result_qa_pair, f)
78
+
79
+ except Exception as e:
80
+ print(f"Error processing file '{key}': {e}")
81
+
82
+
83
+ def main():
84
+ """
85
+ Main function to control the flow of the program.
86
+ """
87
+ # Parse arguments.
88
+ args = parse_args()
89
+
90
+ file = args.pred_path
91
+ try:
92
+ pred_contents = json.load(file)
93
+ except:
94
+ pred_contents = read_jsonl(file)
95
+
96
+ # Dictionary to store the count of occurrences for each video_id
97
+ video_id_counts = {}
98
+ new_pred_contents = []
99
+
100
+ # Iterate through each sample in pred_contents
101
+ for sample in pred_contents:
102
+ sample['video_name'] = 1
103
+ video_id = sample['video_name']
104
+ if video_id in video_id_counts:
105
+ video_id_counts[video_id] += 1
106
+ else:
107
+ video_id_counts[video_id] = 0
108
+
109
+ # Create a new sample with the modified key
110
+ new_sample = sample
111
+ new_sample['video_name'] = f"{video_id}_{video_id_counts[video_id]}"
112
+ new_pred_contents.append(new_sample)
113
+
114
+ # Generating list of id's and corresponding files
115
+ id_list = [x['video_name'] for x in new_pred_contents]
116
+ caption_files = [f"{id}.json" for id in id_list]
117
+
118
+ output_dir = args.output_dir
119
+ # Generate output directory if not exists.
120
+ if not os.path.exists(output_dir):
121
+ os.makedirs(output_dir)
122
+
123
+ # Preparing dictionary of question-answer sets
124
+ prediction_set = {}
125
+ for sample in new_pred_contents:
126
+ id = sample['video_name']
127
+ question = sample['prompt']
128
+ answer = sample['answer']
129
+ pred = sample['text']
130
+ qa_set = {"q": question, "a": answer, "pred": pred}
131
+ prediction_set[id] = qa_set
132
+
133
+ # Set the OpenAI API key.
134
+ openai.api_key = args.api_key
135
+ num_tasks = args.num_tasks
136
+
137
+ # While loop to ensure that all captions are processed.
138
+ while True:
139
+ try:
140
+ # Files that have not been processed yet.
141
+ completed_files = os.listdir(output_dir)
142
+ print(f"completed_files: {len(completed_files)}")
143
+
144
+ # Files that have not been processed yet.
145
+ incomplete_files = [f for f in caption_files if f not in completed_files]
146
+ print(f"incomplete_files: {len(incomplete_files)}")
147
+
148
+ # Break the loop when there are no incomplete files
149
+ if len(incomplete_files) == 0:
150
+ break
151
+ if len(incomplete_files) <= num_tasks:
152
+ num_tasks = 1
153
+
154
+ # Split tasks into parts.
155
+ part_len = len(incomplete_files) // num_tasks
156
+ all_parts = [incomplete_files[i:i + part_len] for i in range(0, len(incomplete_files), part_len)]
157
+ task_args = [(prediction_set, part, args.output_dir) for part in all_parts]
158
+
159
+ # Use a pool of workers to process the files in parallel.
160
+ with Pool() as pool:
161
+ pool.starmap(annotate, task_args)
162
+
163
+ except Exception as e:
164
+ print(f"Error: {e}")
165
+
166
+ # Combine all the processed files into one
167
+ combined_contents = {}
168
+ json_path = args.output_json
169
+
170
+ # Iterate through json files
171
+ for file_name in os.listdir(output_dir):
172
+ if file_name.endswith(".json"):
173
+ file_path = os.path.join(output_dir, file_name)
174
+ with open(file_path, "r") as json_file:
175
+ content = json.load(json_file)
176
+ combined_contents[file_name[:-5]] = content
177
+
178
+ # Write combined content to a json file
179
+ with open(json_path, "w") as json_file:
180
+ json.dump(combined_contents, json_file)
181
+ print("All evaluation completed!")
182
+
183
+ # Calculate average score and accuracy
184
+ score_sum = 0
185
+ count = 0
186
+ yes_count = 0
187
+ no_count = 0
188
+ for key, result in combined_contents.items():
189
+ # Computing score
190
+ count += 1
191
+ score_match = result[0]['score']
192
+ score = int(score_match)
193
+ score_sum += score
194
+
195
+ # Computing accuracy
196
+ pred = result[0]['pred']
197
+ if "yes" in pred.lower():
198
+ yes_count += 1
199
+ elif "no" in pred.lower():
200
+ no_count += 1
201
+
202
+ average_score = score_sum / count
203
+ accuracy = yes_count / (yes_count + no_count)
204
+ print("Yes count:", yes_count)
205
+ print("No count:", no_count)
206
+ print("Accuracy:", accuracy)
207
+ print("Average score:", average_score)
208
+
209
+
210
+ if __name__ == "__main__":
211
+ main()
212
+
ChatUniVi/eval/evaluate/summarize_gpt_review.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from collections import defaultdict
4
+ import numpy as np
5
+ import argparse
6
+
7
+
8
+ def parse_args():
9
+ parser = argparse.ArgumentParser(description='ChatGPT-based QA evaluation.')
10
+ parser.add_argument('-d', '--dir', default=None)
11
+ parser.add_argument('-f', '--files', nargs='*', default=None)
12
+ parser.add_argument('-i', '--ignore', nargs='*', default=None)
13
+ return parser.parse_args()
14
+
15
+
16
+ if __name__ == '__main__0':
17
+ args = parse_args()
18
+
19
+ if args.ignore is not None:
20
+ args.ignore = [int(x) for x in args.ignore]
21
+
22
+ if args.files is not None and len(args.files) > 0:
23
+ review_files = args.files
24
+ else:
25
+ review_files = [x for x in os.listdir(args.dir) if x.endswith('.jsonl') and (x.startswith('gpt4_text') or x.startswith('reviews_') or x.startswith('review_'))]
26
+
27
+ for review_file in sorted(review_files):
28
+ config = os.path.basename(review_file).replace('gpt4_text_', '').replace('.jsonl', '')
29
+ scores = defaultdict(list)
30
+ print(config)
31
+ with open(os.path.join(args.dir, review_file) if args.dir is not None else review_file) as f:
32
+ for review_str in f:
33
+ review = json.loads(review_str)
34
+ if args.ignore is not None and review['question_id'] in args.ignore:
35
+ continue
36
+ if 'category' in review:
37
+ scores[review['category']].append(review['tuple'])
38
+ scores['all'].append(review['tuple'])
39
+ else:
40
+ if 'tuple' in review:
41
+ scores['all'].append(review['tuple'])
42
+ else:
43
+ scores['all'].append(review['score'])
44
+ for k, v in sorted(scores.items()):
45
+ stats = np.asarray(v).mean(0).tolist()
46
+ stats = [round(x, 3) for x in stats]
47
+ # print(k, stats, round(stats[1]/stats[0]*100, 1))
48
+ print(k, round(stats[1]/stats[0]*100, 1))
49
+ print('=================================')
50
+
51
+
52
+ if __name__ == '__main__':
53
+ args = parse_args()
54
+
55
+ scores = defaultdict(list)
56
+ print(f'GPT-4 vs. {args.dir}')
57
+
58
+ with open(args.dir) as f:
59
+ for review_str in f:
60
+ review = json.loads(review_str)
61
+ scores[review['category']].append(review['tuple'])
62
+ scores['all'].append(review['tuple'])
63
+ for k, v in scores.items():
64
+ stats = np.asarray(v).mean(0).tolist()
65
+ stats = [round(x, 3) for x in stats]
66
+ print(k, stats, round(stats[1]/stats[0]*100, 1))
67
+ print('=================================')
ChatUniVi/eval/model_coco_vqa.py ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import os
4
+ import json
5
+ from tqdm import tqdm
6
+ import shortuuid
7
+ from ChatUniVi.constants import *
8
+ from ChatUniVi.conversation import conv_templates, SeparatorStyle
9
+ from ChatUniVi.model.builder import load_pretrained_model
10
+ from ChatUniVi.utils import disable_torch_init
11
+ from ChatUniVi.mm_utils import tokenizer_image_token, get_model_name_from_path, KeywordsStoppingCriteria
12
+ from PIL import Image
13
+ import math
14
+ from abc import ABC
15
+ import numpy as np
16
+ import jsonlines
17
+
18
+
19
+ def get_acc(file):
20
+ acc, num = 0, 0
21
+ yes, no, fail = 0, 0, 0
22
+ tp, fp, fn, tn = 0, 0, 0, 0
23
+
24
+ with open(file, "r", encoding="utf8") as f:
25
+ for item in jsonlines.Reader(f):
26
+ num += 1
27
+ if "Yes" in item["text"] or "yes" in item["text"]:
28
+ yes += 1
29
+ if "Yes" in item["label"] or "yes" in item["label"]:
30
+ acc += 1
31
+ tp += 1
32
+ else:
33
+ fp += 1
34
+
35
+ elif "No" in item["text"] or "no" in item["text"]:
36
+ no += 1
37
+ if "No" in item["label"] or "no" in item["label"]:
38
+ acc += 1
39
+ tn += 1
40
+ else:
41
+ fn += 1
42
+ else:
43
+ fail += 1
44
+
45
+ result = {
46
+ "acc": acc / num,
47
+ "yes": yes / num,
48
+ "no": no / num,
49
+ "fail": fail / num,
50
+ "precision": tp / (tp + fp),
51
+ "recall": tp / (tp + fn),
52
+ }
53
+ result["F1-score"] = 2 * result["precision"] * result["recall"] / (result["precision"] + result["recall"])
54
+ print("\n========================================================================")
55
+ print(file)
56
+ print(result)
57
+ print("========================================================================\n")
58
+ return result
59
+
60
+
61
+ def split_list(lst, n):
62
+ """Split a list into n (roughly) equal-sized chunks"""
63
+ chunk_size = math.ceil(len(lst) / n) # integer division
64
+ return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]
65
+
66
+
67
+ def get_chunk(lst, n, k):
68
+ chunks = split_list(lst, n)
69
+ return chunks[k]
70
+
71
+
72
+ class LogitsProcessor(ABC):
73
+ """Abstract base class for all logit processors that can be applied during generation."""
74
+ def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor) -> torch.FloatTensor:
75
+ """Torch method for processing logits."""
76
+ raise NotImplementedError(
77
+ f"{self.__class__} is an abstract class. Only classes inheriting this class can be called."
78
+ )
79
+
80
+
81
+ def eval_model(args):
82
+ # Model
83
+ disable_torch_init()
84
+ model_path = os.path.expanduser(args.model_path)
85
+ model_name = "ChatUniVi"
86
+ tokenizer, model, image_processor, context_len = load_pretrained_model(model_path, args.model_base, model_name)
87
+
88
+ mm_use_im_start_end = getattr(model.config, "mm_use_im_start_end", False)
89
+ mm_use_im_patch_token = getattr(model.config, "mm_use_im_patch_token", True)
90
+ if mm_use_im_patch_token:
91
+ tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
92
+ if mm_use_im_start_end:
93
+ tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
94
+ model.resize_token_embeddings(len(tokenizer))
95
+
96
+ vision_tower = model.get_vision_tower()
97
+ if not vision_tower.is_loaded:
98
+ vision_tower.load_model()
99
+ image_processor = vision_tower.image_processor
100
+
101
+ questions = [json.loads(q) for q in open(os.path.expanduser(args.question_file), "r")]
102
+ questions = get_chunk(questions, args.num_chunks, args.chunk_idx)
103
+ answers_file = os.path.expanduser(args.answers_file)
104
+ os.makedirs(os.path.dirname(answers_file), exist_ok=True)
105
+ ans_file = open(answers_file, "w")
106
+ for line in tqdm(questions):
107
+ try:
108
+ idx = line["question_id"]
109
+ image_file = line["image"]
110
+ qs = line["text"]
111
+ label = line["label"]
112
+
113
+ cur_prompt = qs
114
+ if model.config.mm_use_im_start_end:
115
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN + DEFAULT_IM_END_TOKEN + '\n' + qs
116
+ else:
117
+ qs = DEFAULT_IMAGE_TOKEN + '\n' + qs
118
+
119
+ conv = conv_templates[args.conv_mode].copy()
120
+ conv.append_message(conv.roles[0], qs)
121
+ conv.append_message(conv.roles[1], None)
122
+ prompt = conv.get_prompt()
123
+
124
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(0).cuda()
125
+
126
+ image = Image.open(os.path.join(args.image_folder, image_file))
127
+
128
+ image_tensor = image_processor.preprocess(image, return_tensors='pt')['pixel_values'][0]
129
+
130
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
131
+ keywords = [stop_str]
132
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
133
+
134
+ if args.answer_prompter:
135
+ with torch.inference_mode():
136
+ output_ids = model.generate(
137
+ input_ids,
138
+ images=image_tensor.unsqueeze(0).half().cuda(),
139
+ do_sample=True,
140
+ temperature=args.temperature,
141
+ top_p=args.top_p,
142
+ num_beams=args.num_beams,
143
+ max_new_tokens=1024,
144
+ use_cache=True,
145
+ stopping_criteria=[stopping_criteria]
146
+ )
147
+
148
+ input_token_len = input_ids.shape[1]
149
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
150
+ if n_diff_input_output > 0:
151
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
152
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
153
+ outputs = outputs.strip()
154
+ if outputs.endswith(stop_str):
155
+ outputs = outputs[:-len(stop_str)]
156
+ outputs = outputs.strip()
157
+
158
+ outputs_reasoning = outputs
159
+ input_ids = tokenizer_image_token(prompt + outputs_reasoning + ' The answer is ', tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(0).cuda()
160
+
161
+ else:
162
+ outputs_reasoning = ""
163
+
164
+ with torch.inference_mode():
165
+ output_ids = model.generate(
166
+ input_ids,
167
+ images=image_tensor.unsqueeze(0).half().cuda(),
168
+ do_sample=True,
169
+ temperature=args.temperature,
170
+ top_p=args.top_p,
171
+ num_beams=args.num_beams,
172
+ output_scores=True,
173
+ return_dict_in_generate=True,
174
+ max_new_tokens=1024,
175
+ use_cache=True,
176
+ stopping_criteria=[stopping_criteria]
177
+ )
178
+
179
+ scores = output_ids.scores[0][0].to(torch.float32)
180
+ label_score = []
181
+ candidates = ["yes", "Yes", "no", "No"]
182
+ for can in candidates:
183
+ can_id = tokenizer.encode(can)[-1]
184
+ label_score.append(scores[can_id].item())
185
+ outputs = candidates[np.argmax(label_score)]
186
+
187
+ ans_id = shortuuid.uuid()
188
+ ans_file.write(json.dumps({"question_id": idx,
189
+ "prompt": cur_prompt,
190
+ "outputs_reasoning": outputs_reasoning + ' The answer is ' + outputs,
191
+ "text": outputs,
192
+ "label": label,
193
+ "answer_id": ans_id,
194
+ "model_id": model_name,
195
+ "metadata": {}}) + "\n")
196
+ ans_file.flush()
197
+ except Exception as e:
198
+ print(f"Error processing image file '{image_file}': {e}")
199
+ ans_file.close()
200
+ get_acc(answers_file)
201
+
202
+
203
+ if __name__ == "__main__":
204
+ parser = argparse.ArgumentParser()
205
+ parser.add_argument("--model-path", type=str, default="facebook/opt-350m")
206
+ parser.add_argument("--model-base", type=str, default=None)
207
+ parser.add_argument("--image-folder", type=str, default="")
208
+ parser.add_argument("--question-file", type=str, default="tables/question.jsonl")
209
+ parser.add_argument("--answers-file", type=str, default="answer.jsonl")
210
+ parser.add_argument("--conv-mode", type=str, default="simpleqa")
211
+ parser.add_argument("--num-chunks", type=int, default=1)
212
+ parser.add_argument("--chunk-idx", type=int, default=0)
213
+ parser.add_argument("--temperature", type=float, default=0.2)
214
+ parser.add_argument("--top_p", type=float, default=None)
215
+ parser.add_argument("--num_beams", type=int, default=1)
216
+ parser.add_argument("--model_use", type=str, default="BASE")
217
+ parser.add_argument("--answer-prompter", action="store_true")
218
+ args = parser.parse_args()
219
+
220
+ eval_model(args)
ChatUniVi/eval/model_video_consistency.py ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import os
4
+ import json
5
+ from tqdm import tqdm
6
+ import shortuuid
7
+ from ChatUniVi.constants import *
8
+ from ChatUniVi.conversation import conv_templates, SeparatorStyle
9
+ from ChatUniVi.model.builder import load_pretrained_model
10
+ from ChatUniVi.utils import disable_torch_init
11
+ from ChatUniVi.mm_utils import tokenizer_image_token, get_model_name_from_path, KeywordsStoppingCriteria
12
+ from PIL import Image
13
+ import math
14
+ from decord import VideoReader, cpu
15
+ import numpy as np
16
+
17
+
18
+ def split_list(lst, n):
19
+ """Split a list into n (roughly) equal-sized chunks"""
20
+ chunk_size = math.ceil(len(lst) / n) # integer division
21
+ return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]
22
+
23
+
24
+ def get_chunk(lst, n, k):
25
+ chunks = split_list(lst, n)
26
+ return chunks[k]
27
+
28
+
29
+ def _get_rawvideo_dec(video_path, image_processor, max_frames=MAX_IMAGE_LENGTH, image_resolution=224, video_framerate=1, s=None, e=None):
30
+ # speed up video decode via decord.
31
+ video_mask = np.zeros(max_frames, dtype=np.int64)
32
+ max_video_length = 0
33
+
34
+ # T x 3 x H x W
35
+ video = np.zeros((max_frames, 3, image_resolution, image_resolution), dtype=np.float64)
36
+
37
+ if s is None:
38
+ start_time, end_time = None, None
39
+ else:
40
+ start_time = int(s)
41
+ end_time = int(e)
42
+ start_time = start_time if start_time >= 0. else 0.
43
+ end_time = end_time if end_time >= 0. else 0.
44
+ if start_time > end_time:
45
+ start_time, end_time = end_time, start_time
46
+ elif start_time == end_time:
47
+ end_time = start_time + 1
48
+
49
+ if os.path.exists(video_path):
50
+ vreader = VideoReader(video_path, ctx=cpu(0))
51
+ else:
52
+ print(video_path)
53
+ raise FileNotFoundError
54
+
55
+ fps = vreader.get_avg_fps()
56
+ f_start = 0 if start_time is None else int(start_time * fps)
57
+ f_end = int(min(1000000000 if end_time is None else end_time * fps, len(vreader) - 1))
58
+ num_frames = f_end - f_start + 1
59
+ if num_frames > 0:
60
+ # T x 3 x H x W
61
+ sample_fps = int(video_framerate)
62
+ t_stride = int(round(float(fps) / sample_fps))
63
+
64
+ all_pos = list(range(f_start, f_end + 1, t_stride))
65
+ if len(all_pos) > max_frames:
66
+ sample_pos = [all_pos[_] for _ in np.linspace(0, len(all_pos) - 1, num=max_frames, dtype=int)]
67
+ else:
68
+ sample_pos = all_pos
69
+
70
+ patch_images = [Image.fromarray(f) for f in vreader.get_batch(sample_pos).asnumpy()]
71
+
72
+ patch_images = torch.stack([image_processor.preprocess(img, return_tensors='pt')['pixel_values'][0] for img in patch_images])
73
+ slice_len = patch_images.shape[0]
74
+
75
+ max_video_length = max_video_length if max_video_length > slice_len else slice_len
76
+ if slice_len < 1:
77
+ pass
78
+ else:
79
+ video[:slice_len, ...] = patch_images
80
+
81
+ return patch_images, slice_len
82
+ else:
83
+ print("video path: {} error.".format(video_path))
84
+
85
+ video_mask[:max_video_length] = [1] * max_video_length
86
+
87
+ return torch.from_numpy(video), video_mask
88
+
89
+
90
+ def eval_model(args):
91
+ # Model
92
+ disable_torch_init()
93
+ model_path = os.path.expanduser(args.model_path)
94
+ model_name = "ChatUniVi"
95
+ tokenizer, model, image_processor, context_len = load_pretrained_model(model_path, args.model_base, model_name)
96
+
97
+ mm_use_im_start_end = getattr(model.config, "mm_use_im_start_end", False)
98
+ mm_use_im_patch_token = getattr(model.config, "mm_use_im_patch_token", True)
99
+ if mm_use_im_patch_token:
100
+ tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
101
+ if mm_use_im_start_end:
102
+ tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
103
+ model.resize_token_embeddings(len(tokenizer))
104
+
105
+ vision_tower = model.get_vision_tower()
106
+ if not vision_tower.is_loaded:
107
+ vision_tower.load_model()
108
+ image_processor = vision_tower.image_processor
109
+
110
+ if model.config.config["use_cluster"]:
111
+ for n, m in model.named_modules():
112
+ m = m.to(dtype=torch.bfloat16)
113
+
114
+ # Load the ground truth file
115
+ with open(args.question_file) as file:
116
+ gt_contents = json.load(file)
117
+
118
+ answers_file = os.path.expanduser(args.answers_file)
119
+ os.makedirs(os.path.dirname(answers_file), exist_ok=True)
120
+ ans_file = open(answers_file, "w")
121
+
122
+ video_formats = ['.mp4', '.avi', '.mov', '.mkv']
123
+
124
+ # Iterate over each sample in the ground truth file
125
+ for sample in tqdm(gt_contents):
126
+ video_name = sample['video_name']
127
+ question_1 = sample['Q1']
128
+ question_2 = sample['Q2']
129
+
130
+ # Load the video file
131
+ for fmt in video_formats: # Added this line
132
+ temp_path = os.path.join(args.video_folder, f"{video_name}{fmt}")
133
+ if os.path.exists(temp_path):
134
+ video_path = temp_path
135
+ break
136
+
137
+ # Check if the video exists
138
+ if video_path is not None: # Modified this line
139
+ video_frames, slice_len = _get_rawvideo_dec(video_path, image_processor, max_frames=MAX_IMAGE_LENGTH)
140
+
141
+ qs = question_1
142
+ if model.config.mm_use_im_start_end:
143
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN * slice_len + DEFAULT_IM_END_TOKEN + '\n' + qs
144
+ else:
145
+ qs = DEFAULT_IMAGE_TOKEN * slice_len + '\n' + qs
146
+
147
+ conv = conv_templates[args.conv_mode].copy()
148
+ conv.append_message(conv.roles[0], qs)
149
+ conv.append_message(conv.roles[1], None)
150
+ prompt = conv.get_prompt()
151
+
152
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(
153
+ 0).cuda()
154
+
155
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
156
+ keywords = [stop_str]
157
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
158
+
159
+ with torch.inference_mode():
160
+ output_ids = model.generate(
161
+ input_ids,
162
+ images=video_frames.half().cuda(),
163
+ do_sample=True,
164
+ temperature=args.temperature,
165
+ top_p=args.top_p,
166
+ num_beams=args.num_beams,
167
+ max_new_tokens=1024,
168
+ use_cache=True,
169
+ stopping_criteria=[stopping_criteria])
170
+
171
+ input_token_len = input_ids.shape[1]
172
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
173
+ if n_diff_input_output > 0:
174
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
175
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
176
+ outputs = outputs.strip()
177
+ if outputs.endswith(stop_str):
178
+ outputs = outputs[:-len(stop_str)]
179
+ outputs_1 = outputs.strip()
180
+
181
+ qs = question_2
182
+ if model.config.mm_use_im_start_end:
183
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN * slice_len + DEFAULT_IM_END_TOKEN + '\n' + qs
184
+ else:
185
+ qs = DEFAULT_IMAGE_TOKEN * slice_len + '\n' + qs
186
+
187
+ conv = conv_templates[args.conv_mode].copy()
188
+ conv.append_message(conv.roles[0], qs)
189
+ conv.append_message(conv.roles[1], None)
190
+ prompt = conv.get_prompt()
191
+
192
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(
193
+ 0).cuda()
194
+
195
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
196
+ keywords = [stop_str]
197
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
198
+
199
+ with torch.inference_mode():
200
+ output_ids = model.generate(
201
+ input_ids,
202
+ images=torch.from_numpy(video_frames).half().cuda(),
203
+ do_sample=True,
204
+ temperature=args.temperature,
205
+ top_p=args.top_p,
206
+ num_beams=args.num_beams,
207
+ max_new_tokens=1024,
208
+ use_cache=True,
209
+ stopping_criteria=[stopping_criteria])
210
+
211
+ input_token_len = input_ids.shape[1]
212
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
213
+ if n_diff_input_output > 0:
214
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
215
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
216
+ outputs = outputs.strip()
217
+ if outputs.endswith(stop_str):
218
+ outputs = outputs[:-len(stop_str)]
219
+ outputs_2 = outputs.strip()
220
+
221
+ ans_id = shortuuid.uuid()
222
+ ans_file.write(json.dumps({"video_name": sample['video_name'],
223
+ "prompt_1": question_1,
224
+ "text_1": outputs_1,
225
+ "prompt_2": question_2,
226
+ "text_2": outputs_2,
227
+ "answer_id": ans_id,
228
+ "model_id": model_name,
229
+ "answer": sample['A'],
230
+ "metadata": {}}) + "\n")
231
+ ans_file.flush()
232
+
233
+ ans_file.close()
234
+
235
+
236
+ if __name__ == "__main__":
237
+ parser = argparse.ArgumentParser()
238
+ parser.add_argument("--model-path", type=str, default="facebook/opt-350m")
239
+ parser.add_argument("--model-base", type=str, default=None)
240
+ parser.add_argument("--video-folder", type=str, default="")
241
+ parser.add_argument("--question-file", type=str, default="tables/question.jsonl")
242
+ parser.add_argument("--answers-file", type=str, default="answer.jsonl")
243
+ parser.add_argument("--conv-mode", type=str, default="v1")
244
+ parser.add_argument("--num-chunks", type=int, default=1)
245
+ parser.add_argument("--chunk-idx", type=int, default=0)
246
+ parser.add_argument("--temperature", type=float, default=0.2)
247
+ parser.add_argument("--top_p", type=float, default=None)
248
+ parser.add_argument("--num_beams", type=int, default=1)
249
+ parser.add_argument("--model_use", type=str, default="BASE")
250
+ args = parser.parse_args()
251
+
252
+ eval_model(args)
ChatUniVi/eval/model_video_general.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import os
4
+ import json
5
+ from tqdm import tqdm
6
+ import shortuuid
7
+ from ChatUniVi.constants import *
8
+ from ChatUniVi.conversation import conv_templates, SeparatorStyle
9
+ from ChatUniVi.model.builder import load_pretrained_model
10
+ from ChatUniVi.utils import disable_torch_init
11
+ from ChatUniVi.mm_utils import tokenizer_image_token, get_model_name_from_path, KeywordsStoppingCriteria
12
+ from PIL import Image
13
+ import math
14
+ from decord import VideoReader, cpu
15
+ import numpy as np
16
+
17
+
18
+ def split_list(lst, n):
19
+ """Split a list into n (roughly) equal-sized chunks"""
20
+ chunk_size = math.ceil(len(lst) / n) # integer division
21
+ return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]
22
+
23
+
24
+ def get_chunk(lst, n, k):
25
+ chunks = split_list(lst, n)
26
+ return chunks[k]
27
+
28
+
29
+ def _get_rawvideo_dec(video_path, image_processor, max_frames=MAX_IMAGE_LENGTH, image_resolution=224, video_framerate=1, s=None, e=None):
30
+ # speed up video decode via decord.
31
+ video_mask = np.zeros(max_frames, dtype=np.int64)
32
+ max_video_length = 0
33
+
34
+ # T x 3 x H x W
35
+ video = np.zeros((max_frames, 3, image_resolution, image_resolution), dtype=np.float64)
36
+
37
+ if s is None:
38
+ start_time, end_time = None, None
39
+ else:
40
+ start_time = int(s)
41
+ end_time = int(e)
42
+ start_time = start_time if start_time >= 0. else 0.
43
+ end_time = end_time if end_time >= 0. else 0.
44
+ if start_time > end_time:
45
+ start_time, end_time = end_time, start_time
46
+ elif start_time == end_time:
47
+ end_time = start_time + 1
48
+
49
+ if os.path.exists(video_path):
50
+ vreader = VideoReader(video_path, ctx=cpu(0))
51
+ else:
52
+ print(video_path)
53
+ raise FileNotFoundError
54
+
55
+ fps = vreader.get_avg_fps()
56
+ f_start = 0 if start_time is None else int(start_time * fps)
57
+ f_end = int(min(1000000000 if end_time is None else end_time * fps, len(vreader) - 1))
58
+ num_frames = f_end - f_start + 1
59
+ if num_frames > 0:
60
+ # T x 3 x H x W
61
+ sample_fps = int(video_framerate)
62
+ t_stride = int(round(float(fps) / sample_fps))
63
+
64
+ all_pos = list(range(f_start, f_end + 1, t_stride))
65
+ if len(all_pos) > max_frames:
66
+ sample_pos = [all_pos[_] for _ in np.linspace(0, len(all_pos) - 1, num=max_frames, dtype=int)]
67
+ else:
68
+ sample_pos = all_pos
69
+
70
+ patch_images = [Image.fromarray(f) for f in vreader.get_batch(sample_pos).asnumpy()]
71
+
72
+ patch_images = torch.stack([image_processor.preprocess(img, return_tensors='pt')['pixel_values'][0] for img in patch_images])
73
+ slice_len = patch_images.shape[0]
74
+
75
+ max_video_length = max_video_length if max_video_length > slice_len else slice_len
76
+ if slice_len < 1:
77
+ pass
78
+ else:
79
+ video[:slice_len, ...] = patch_images
80
+
81
+ return patch_images, slice_len
82
+ else:
83
+ print("video path: {} error.".format(video_path))
84
+
85
+ video_mask[:max_video_length] = [1] * max_video_length
86
+
87
+ return torch.from_numpy(video), video_mask
88
+
89
+
90
+ def eval_model(args):
91
+ # Model
92
+ disable_torch_init()
93
+ model_path = os.path.expanduser(args.model_path)
94
+ model_name = "ChatUniVi"
95
+ tokenizer, model, image_processor, context_len = load_pretrained_model(model_path, args.model_base, model_name)
96
+
97
+ mm_use_im_start_end = getattr(model.config, "mm_use_im_start_end", False)
98
+ mm_use_im_patch_token = getattr(model.config, "mm_use_im_patch_token", True)
99
+ if mm_use_im_patch_token:
100
+ tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
101
+ if mm_use_im_start_end:
102
+ tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
103
+ model.resize_token_embeddings(len(tokenizer))
104
+
105
+ vision_tower = model.get_vision_tower()
106
+ if not vision_tower.is_loaded:
107
+ vision_tower.load_model()
108
+ image_processor = vision_tower.image_processor
109
+
110
+ if model.config.config["use_cluster"]:
111
+ for n, m in model.named_modules():
112
+ m = m.to(dtype=torch.bfloat16)
113
+
114
+ # Load the ground truth file
115
+ with open(args.question_file) as file:
116
+ gt_contents = json.load(file)
117
+
118
+ answers_file = os.path.expanduser(args.answers_file)
119
+ os.makedirs(os.path.dirname(answers_file), exist_ok=True)
120
+ ans_file = open(answers_file, "w")
121
+
122
+ video_formats = ['.mp4', '.avi', '.mov', '.mkv']
123
+
124
+ # Iterate over each sample in the ground truth file
125
+ for sample in tqdm(gt_contents):
126
+ video_name = sample['video_name']
127
+ sample_set = sample
128
+ qs = sample['Q']
129
+
130
+ # Load the video file
131
+ for fmt in video_formats: # Added this line
132
+ temp_path = os.path.join(args.video_folder, f"{video_name}{fmt}")
133
+ if os.path.exists(temp_path):
134
+ video_path = temp_path
135
+ break
136
+
137
+ # Check if the video exists
138
+ if video_path is not None: # Modified this line
139
+ video_frames, slice_len = _get_rawvideo_dec(video_path, image_processor, max_frames=MAX_IMAGE_LENGTH)
140
+
141
+ try:
142
+ cur_prompt = qs
143
+ if model.config.mm_use_im_start_end:
144
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN * slice_len + DEFAULT_IM_END_TOKEN + '\n' + qs
145
+ else:
146
+ qs = DEFAULT_IMAGE_TOKEN * slice_len + '\n' + qs
147
+
148
+ conv = conv_templates[args.conv_mode].copy()
149
+ conv.append_message(conv.roles[0], qs)
150
+ conv.append_message(conv.roles[1], None)
151
+ prompt = conv.get_prompt()
152
+
153
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(
154
+ 0).cuda()
155
+
156
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
157
+ keywords = [stop_str]
158
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
159
+
160
+ with torch.inference_mode():
161
+ output_ids = model.generate(
162
+ input_ids,
163
+ images=video_frames.half().cuda(),
164
+ do_sample=True,
165
+ temperature=args.temperature,
166
+ top_p=args.top_p,
167
+ num_beams=args.num_beams,
168
+ max_new_tokens=1024,
169
+ use_cache=True,
170
+ stopping_criteria=[stopping_criteria])
171
+
172
+ input_token_len = input_ids.shape[1]
173
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
174
+ if n_diff_input_output > 0:
175
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
176
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
177
+ outputs = outputs.strip()
178
+ if outputs.endswith(stop_str):
179
+ outputs = outputs[:-len(stop_str)]
180
+ outputs = outputs.strip()
181
+
182
+ ans_id = shortuuid.uuid()
183
+ ans_file.write(json.dumps({'video_name': sample['video_name'],
184
+ "prompt": cur_prompt,
185
+ "text": outputs,
186
+ "answer_id": ans_id,
187
+ "model_id": model_name,
188
+ "answer": sample['A'],
189
+ "metadata": {}}) + "\n")
190
+ ans_file.flush()
191
+ except Exception as e:
192
+ print(f"Error processing video file '{video_name}': {e}")
193
+
194
+ ans_file.close()
195
+
196
+
197
+ if __name__ == "__main__":
198
+ parser = argparse.ArgumentParser()
199
+ parser.add_argument("--model-path", type=str, default="facebook/opt-350m")
200
+ parser.add_argument("--model-base", type=str, default=None)
201
+ parser.add_argument("--video-folder", type=str, default="")
202
+ parser.add_argument("--question-file", type=str, default="tables/question.jsonl")
203
+ parser.add_argument("--answers-file", type=str, default="answer.jsonl")
204
+ parser.add_argument("--conv-mode", type=str, default="v1")
205
+ parser.add_argument("--num-chunks", type=int, default=1)
206
+ parser.add_argument("--chunk-idx", type=int, default=0)
207
+ parser.add_argument("--temperature", type=float, default=0.2)
208
+ parser.add_argument("--top_p", type=float, default=None)
209
+ parser.add_argument("--num_beams", type=int, default=1)
210
+ parser.add_argument("--model_use", type=str, default="BASE")
211
+ args = parser.parse_args()
212
+
213
+ eval_model(args)
ChatUniVi/eval/model_video_qa.py ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import os
4
+ import json
5
+ from tqdm import tqdm
6
+ import shortuuid
7
+ from ChatUniVi.constants import *
8
+ from ChatUniVi.conversation import conv_templates, SeparatorStyle
9
+ from ChatUniVi.model.builder import load_pretrained_model
10
+ from ChatUniVi.utils import disable_torch_init
11
+ from ChatUniVi.mm_utils import tokenizer_image_token, get_model_name_from_path, KeywordsStoppingCriteria
12
+ from PIL import Image
13
+ import math
14
+ from decord import VideoReader, cpu
15
+ import numpy as np
16
+
17
+
18
+ def read_json(file):
19
+ with open(file, "r", encoding='utf-8') as f:
20
+ data = json.load(f)
21
+ return data
22
+
23
+ def split_list(lst, n):
24
+ """Split a list into n (roughly) equal-sized chunks"""
25
+ chunk_size = math.ceil(len(lst) / n) # integer division
26
+ return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]
27
+
28
+
29
+ def get_chunk(lst, n, k):
30
+ chunks = split_list(lst, n)
31
+ return chunks[k]
32
+
33
+
34
+ def _get_rawvideo_dec(video_path, image_processor, max_frames=MAX_IMAGE_LENGTH, image_resolution=224, video_framerate=1, s=None, e=None):
35
+ # speed up video decode via decord.
36
+ video_mask = np.zeros(max_frames, dtype=np.int64)
37
+ max_video_length = 0
38
+
39
+ # T x 3 x H x W
40
+ video = np.zeros((max_frames, 3, image_resolution, image_resolution), dtype=np.float64)
41
+
42
+ if s is None:
43
+ start_time, end_time = None, None
44
+ else:
45
+ start_time = int(s)
46
+ end_time = int(e)
47
+ start_time = start_time if start_time >= 0. else 0.
48
+ end_time = end_time if end_time >= 0. else 0.
49
+ if start_time > end_time:
50
+ start_time, end_time = end_time, start_time
51
+ elif start_time == end_time:
52
+ end_time = start_time + 1
53
+
54
+ if os.path.exists(video_path):
55
+ vreader = VideoReader(video_path, ctx=cpu(0))
56
+ else:
57
+ print(video_path)
58
+ raise FileNotFoundError
59
+
60
+ fps = vreader.get_avg_fps()
61
+ f_start = 0 if start_time is None else int(start_time * fps)
62
+ f_end = int(min(1000000000 if end_time is None else end_time * fps, len(vreader) - 1))
63
+ num_frames = f_end - f_start + 1
64
+ if num_frames > 0:
65
+ # T x 3 x H x W
66
+ sample_fps = int(video_framerate)
67
+ t_stride = int(round(float(fps) / sample_fps))
68
+
69
+ all_pos = list(range(f_start, f_end + 1, t_stride))
70
+ if len(all_pos) > max_frames:
71
+ sample_pos = [all_pos[_] for _ in np.linspace(0, len(all_pos) - 1, num=max_frames, dtype=int)]
72
+ else:
73
+ sample_pos = all_pos
74
+
75
+ patch_images = [Image.fromarray(f) for f in vreader.get_batch(sample_pos).asnumpy()]
76
+
77
+ patch_images = torch.stack([image_processor.preprocess(img, return_tensors='pt')['pixel_values'][0] for img in patch_images])
78
+ slice_len = patch_images.shape[0]
79
+
80
+ max_video_length = max_video_length if max_video_length > slice_len else slice_len
81
+ if slice_len < 1:
82
+ pass
83
+ else:
84
+ video[:slice_len, ...] = patch_images
85
+
86
+ return patch_images, slice_len
87
+ else:
88
+ print("video path: {} error.".format(video_path))
89
+
90
+ video_mask[:max_video_length] = [1] * max_video_length
91
+
92
+ return torch.from_numpy(video), video_mask
93
+
94
+
95
+ def eval_model(args):
96
+ # Model
97
+ disable_torch_init()
98
+ model_path = os.path.expanduser(args.model_path)
99
+ model_name = "ChatUniVi"
100
+ tokenizer, model, image_processor, context_len = load_pretrained_model(model_path, args.model_base, model_name)
101
+
102
+ mm_use_im_start_end = getattr(model.config, "mm_use_im_start_end", False)
103
+ mm_use_im_patch_token = getattr(model.config, "mm_use_im_patch_token", True)
104
+ if mm_use_im_patch_token:
105
+ tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
106
+ if mm_use_im_start_end:
107
+ tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
108
+ model.resize_token_embeddings(len(tokenizer))
109
+
110
+ vision_tower = model.get_vision_tower()
111
+ if not vision_tower.is_loaded:
112
+ vision_tower.load_model()
113
+ image_processor = vision_tower.image_processor
114
+
115
+ if model.config.config["use_cluster"]:
116
+ for n, m in model.named_modules():
117
+ m = m.to(dtype=torch.bfloat16)
118
+
119
+ # Load the ground truth file
120
+ with open(args.question_file) as file:
121
+ gt_contents = json.load(file)
122
+ answers_list = read_json(args.answers_list)
123
+
124
+ answers_file = os.path.expanduser(args.answers_file)
125
+ os.makedirs(os.path.dirname(answers_file), exist_ok=True)
126
+ ans_file = open(answers_file, "w")
127
+
128
+ video_formats = ['.mp4', '.avi', '.mov', '.mkv']
129
+
130
+ # Iterate over each sample in the ground truth file
131
+ for sample in tqdm(gt_contents):
132
+ sample_set = sample
133
+ qs = sample['question']
134
+
135
+ # Load the video file
136
+ for fmt in video_formats: # Added this line
137
+ video_name = sample['video_name']
138
+ temp_path = os.path.join(args.video_folder, f"{video_name}{fmt}")
139
+ if os.path.exists(temp_path):
140
+ video_path = temp_path
141
+ break
142
+
143
+ video_name = "v_" + sample['video_name']
144
+ temp_path = os.path.join(args.video_folder, f"{video_name}{fmt}")
145
+ if os.path.exists(temp_path):
146
+ video_path = temp_path
147
+ break
148
+
149
+ # Check if the video exists
150
+ if video_path is not None: # Modified this line
151
+ if args.max_frames:
152
+ video_frames, slice_len = _get_rawvideo_dec(video_path, image_processor, max_frames=args.max_frames)
153
+ else:
154
+ video_frames, slice_len = _get_rawvideo_dec(video_path, image_processor, max_frames=MAX_IMAGE_LENGTH)
155
+
156
+ try:
157
+ cur_prompt = qs
158
+ if model.config.mm_use_im_start_end:
159
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN * slice_len + DEFAULT_IM_END_TOKEN + '\n' + qs
160
+ else:
161
+ qs = DEFAULT_IMAGE_TOKEN * slice_len + '\n' + qs
162
+
163
+ conv = conv_templates[args.conv_mode].copy()
164
+ conv.append_message(conv.roles[0], qs)
165
+ conv.append_message(conv.roles[1], None)
166
+ prompt = conv.get_prompt()
167
+
168
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(
169
+ 0).cuda()
170
+
171
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
172
+ keywords = [stop_str]
173
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
174
+
175
+ with torch.inference_mode():
176
+ output_ids = model.generate(
177
+ input_ids,
178
+ images=video_frames.half().cuda(),
179
+ do_sample=True,
180
+ temperature=args.temperature,
181
+ top_p=args.top_p,
182
+ num_beams=args.num_beams,
183
+ output_scores=True,
184
+ return_dict_in_generate=True,
185
+ max_new_tokens=1024,
186
+ use_cache=True,
187
+ stopping_criteria=[stopping_criteria])
188
+
189
+ output_ids = output_ids.sequences
190
+ input_token_len = input_ids.shape[1]
191
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
192
+ if n_diff_input_output > 0:
193
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
194
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
195
+ outputs = outputs.strip()
196
+ if outputs.endswith(stop_str):
197
+ outputs = outputs[:-len(stop_str)]
198
+ outputs = outputs.strip()
199
+
200
+ ans_id = shortuuid.uuid()
201
+ ans_file.write(json.dumps({"video_name": sample['video_name'],
202
+ "prompt": cur_prompt,
203
+ "text": outputs,
204
+ "answer_id": ans_id,
205
+ "model_id": model_name,
206
+ "answer": sample['answer'],
207
+ "metadata": {}}) + "\n")
208
+ ans_file.flush()
209
+ except Exception as e:
210
+ print(f"Error processing video file '{video_name}': {e}")
211
+
212
+ ans_file.close()
213
+
214
+
215
+ if __name__ == "__main__":
216
+ parser = argparse.ArgumentParser()
217
+ parser.add_argument("--model-path", type=str, default="facebook/opt-350m")
218
+ parser.add_argument("--model-base", type=str, default=None)
219
+ parser.add_argument("--video-folder", type=str, default="")
220
+ parser.add_argument("--question-file", type=str, default="tables/question.jsonl")
221
+ parser.add_argument("--answers-list", type=str, default="tables/answers_list.json")
222
+ parser.add_argument("--answers-file", type=str, default="answer.jsonl")
223
+ parser.add_argument("--conv-mode", type=str, default="v1")
224
+ parser.add_argument("--num-chunks", type=int, default=1)
225
+ parser.add_argument("--chunk-idx", type=int, default=0)
226
+ parser.add_argument("--temperature", type=float, default=0.2)
227
+ parser.add_argument("--top_p", type=float, default=None)
228
+ parser.add_argument("--num_beams", type=int, default=1)
229
+ parser.add_argument("--max_frames", type=int, default=None)
230
+ args = parser.parse_args()
231
+
232
+ eval_model(args)
ChatUniVi/eval/model_vqa.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import os
4
+ import json
5
+ from tqdm import tqdm
6
+ import shortuuid
7
+ from ChatUniVi.constants import *
8
+ from ChatUniVi.conversation import conv_templates, SeparatorStyle
9
+ from ChatUniVi.model.builder import load_pretrained_model
10
+ from ChatUniVi.utils import disable_torch_init
11
+ from ChatUniVi.mm_utils import tokenizer_image_token, get_model_name_from_path, KeywordsStoppingCriteria
12
+ from PIL import Image
13
+ import math
14
+
15
+
16
+ def split_list(lst, n):
17
+ """Split a list into n (roughly) equal-sized chunks"""
18
+ chunk_size = math.ceil(len(lst) / n) # integer division
19
+ return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]
20
+
21
+
22
+ def get_chunk(lst, n, k):
23
+ chunks = split_list(lst, n)
24
+ return chunks[k]
25
+
26
+
27
+ def eval_model(args):
28
+ # Model
29
+ disable_torch_init()
30
+ model_path = os.path.expanduser(args.model_path)
31
+ model_name = "ChatUniVi"
32
+ tokenizer, model, image_processor, context_len = load_pretrained_model(model_path, args.model_base, model_name)
33
+
34
+ mm_use_im_start_end = getattr(model.config, "mm_use_im_start_end", False)
35
+ mm_use_im_patch_token = getattr(model.config, "mm_use_im_patch_token", True)
36
+ if mm_use_im_patch_token:
37
+ tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
38
+ if mm_use_im_start_end:
39
+ tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
40
+ model.resize_token_embeddings(len(tokenizer))
41
+
42
+ vision_tower = model.get_vision_tower()
43
+ if not vision_tower.is_loaded:
44
+ vision_tower.load_model()
45
+ image_processor = vision_tower.image_processor
46
+
47
+ questions = [json.loads(q) for q in open(os.path.expanduser(args.question_file), "r")]
48
+ questions = get_chunk(questions, args.num_chunks, args.chunk_idx)
49
+ answers_file = os.path.expanduser(args.answers_file)
50
+ os.makedirs(os.path.dirname(answers_file), exist_ok=True)
51
+ ans_file = open(answers_file, "w")
52
+ for line in tqdm(questions):
53
+ idx = line["question_id"]
54
+ image_file = line["image"]
55
+ qs = line["text"]
56
+ cur_prompt = qs
57
+ if model.config.mm_use_im_start_end:
58
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN + DEFAULT_IM_END_TOKEN + '\n' + qs
59
+ else:
60
+ qs = DEFAULT_IMAGE_TOKEN + '\n' + qs
61
+
62
+ conv = conv_templates[args.conv_mode].copy()
63
+ conv.append_message(conv.roles[0], qs)
64
+ conv.append_message(conv.roles[1], None)
65
+ prompt = conv.get_prompt()
66
+
67
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(0).cuda()
68
+
69
+ image = Image.open(os.path.join(args.image_folder, image_file))
70
+ image_tensor = image_processor.preprocess(image, return_tensors='pt')['pixel_values'][0]
71
+
72
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
73
+ keywords = [stop_str]
74
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
75
+
76
+ with torch.inference_mode():
77
+ output_ids = model.generate(
78
+ input_ids,
79
+ images=image_tensor.unsqueeze(0).half().cuda(),
80
+ do_sample=True,
81
+ temperature=args.temperature,
82
+ top_p=args.top_p,
83
+ num_beams=args.num_beams,
84
+ max_new_tokens=args.max_new_tokens,
85
+ use_cache=True,
86
+ stopping_criteria=[stopping_criteria])
87
+
88
+ input_token_len = input_ids.shape[1]
89
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
90
+ if n_diff_input_output > 0:
91
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
92
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
93
+ outputs = outputs.strip()
94
+ if outputs.endswith(stop_str):
95
+ outputs = outputs[:-len(stop_str)]
96
+ outputs = outputs.strip()
97
+
98
+ ans_id = shortuuid.uuid()
99
+ ans_file.write(json.dumps({"question_id": idx,
100
+ "prompt": cur_prompt,
101
+ "text": outputs,
102
+ "answer_id": ans_id,
103
+ "model_id": model_name,
104
+ "metadata": {}}) + "\n")
105
+ ans_file.flush()
106
+ ans_file.close()
107
+
108
+ if __name__ == "__main__":
109
+ parser = argparse.ArgumentParser()
110
+ parser.add_argument("--model-path", type=str, default="facebook/opt-350m")
111
+ parser.add_argument("--model-base", type=str, default=None)
112
+ parser.add_argument("--image-folder", type=str, default="")
113
+ parser.add_argument("--question-file", type=str, default="tables/question.jsonl")
114
+ parser.add_argument("--answers-file", type=str, default="answer.jsonl")
115
+ parser.add_argument("--conv-mode", type=str, default="simple")
116
+ parser.add_argument("--num-chunks", type=int, default=1)
117
+ parser.add_argument("--chunk-idx", type=int, default=0)
118
+ parser.add_argument("--temperature", type=float, default=0.2)
119
+ parser.add_argument("--top_p", type=float, default=None)
120
+ parser.add_argument("--num_beams", type=int, default=1)
121
+ parser.add_argument("--model_use", type=str, default="BASE")
122
+ parser.add_argument("--max_new_tokens", type=int, default=1024)
123
+ args = parser.parse_args()
124
+
125
+ eval_model(args)
ChatUniVi/eval/model_vqa_scienceqa.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import os
4
+ import json
5
+ from tqdm import tqdm
6
+ import shortuuid
7
+
8
+ from ChatUniVi.constants import IMAGE_TOKEN_INDEX, DEFAULT_IMAGE_TOKEN, DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN
9
+ from ChatUniVi.conversation import conv_templates, SeparatorStyle
10
+ from ChatUniVi.model.builder import load_pretrained_model
11
+ from ChatUniVi.utils import disable_torch_init
12
+ from ChatUniVi.mm_utils import tokenizer_image_token, get_model_name_from_path, KeywordsStoppingCriteria
13
+
14
+ from PIL import Image
15
+ import math
16
+ import numpy as np
17
+
18
+
19
+ def split_list(lst, n):
20
+ """Split a list into n (roughly) equal-sized chunks"""
21
+ chunk_size = math.ceil(len(lst) / n) # integer division
22
+ return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]
23
+
24
+
25
+ def get_chunk(lst, n, k):
26
+ chunks = split_list(lst, n)
27
+ return chunks[k]
28
+
29
+
30
+ def eval_model(args):
31
+ # Model
32
+ disable_torch_init()
33
+ model_path = os.path.expanduser(args.model_path)
34
+ model_name = "ChatUniVi"
35
+ tokenizer, model, image_processor, context_len = load_pretrained_model(model_path, args.model_base, model_name)
36
+
37
+ vision_tower = model.get_vision_tower()
38
+ if not vision_tower.is_loaded:
39
+ vision_tower.load_model()
40
+ image_processor = vision_tower.image_processor
41
+
42
+ questions = json.load(open(os.path.expanduser(args.question_file), "r"))
43
+ questions = get_chunk(questions, args.num_chunks, args.chunk_idx)
44
+ answers_file = os.path.expanduser(args.answers_file)
45
+ os.makedirs(os.path.dirname(answers_file), exist_ok=True)
46
+ ans_file = open(answers_file, "w")
47
+ for i, line in enumerate(tqdm(questions)):
48
+ idx = line["id"]
49
+ question = line['conversations'][0]
50
+ gt_ans = line["conversations"][1]
51
+ qs = question['value'].replace('<image>', '').strip()
52
+ cur_prompt = qs
53
+
54
+ if 'image' in line:
55
+ image_file = line["image"].replace("\\", "/")
56
+ image = Image.open(os.path.join(args.image_folder, image_file))
57
+ image_tensor = image_processor.preprocess(image, return_tensors='pt')['pixel_values'][0]
58
+ images = image_tensor.unsqueeze(0).half().cuda()
59
+ if getattr(model.config, 'mm_use_im_start_end', False):
60
+ qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN + DEFAULT_IM_END_TOKEN + '\n' + qs
61
+ else:
62
+ qs = DEFAULT_IMAGE_TOKEN + '\n' + qs
63
+ cur_prompt = '<image>' + '\n' + cur_prompt
64
+ else:
65
+ images = None
66
+
67
+ conv = conv_templates[args.conv_mode].copy()
68
+ conv.append_message(conv.roles[0], qs)
69
+ conv.append_message(conv.roles[1], None)
70
+ prompt = conv.get_prompt()
71
+
72
+ input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(0).cuda()
73
+
74
+ stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
75
+ keywords = [stop_str]
76
+ stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
77
+
78
+ with torch.inference_mode():
79
+ output_ids = model.generate(
80
+ input_ids,
81
+ images=images,
82
+ do_sample=True,
83
+ temperature=0.2,
84
+ max_new_tokens=1024,
85
+ use_cache=True,
86
+ stopping_criteria=[stopping_criteria])
87
+
88
+ input_token_len = input_ids.shape[1]
89
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
90
+ if n_diff_input_output > 0:
91
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
92
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
93
+ outputs = outputs.strip()
94
+ if outputs.endswith(stop_str):
95
+ outputs = outputs[:-len(stop_str)]
96
+ outputs = outputs.strip()
97
+
98
+ outputs_reasoning = outputs
99
+ input_ids = tokenizer_image_token(prompt + outputs_reasoning + ' ###\nANSWER:', tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(0).cuda()
100
+
101
+ with torch.inference_mode():
102
+ output_ids = model.generate(
103
+ input_ids,
104
+ images=images,
105
+ do_sample=True,
106
+ temperature=0.2,
107
+ max_new_tokens=64,
108
+ use_cache=True,
109
+ output_scores=True,
110
+ return_dict_in_generate=True,
111
+ stopping_criteria=[stopping_criteria])
112
+
113
+ scores = output_ids.scores[0][0].to(torch.float32)
114
+ label_score = []
115
+
116
+ candidates = []
117
+ answers_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
118
+ for i in answers_list:
119
+ if "(" + i + ")" in cur_prompt:
120
+ candidates.append(i)
121
+
122
+ for can in candidates:
123
+ can_id = tokenizer.encode(can)[-1]
124
+ label_score.append(scores[can_id].item())
125
+ outputs_answer = candidates[np.argmax(label_score)]
126
+
127
+ output_ids = output_ids.sequences
128
+
129
+ input_token_len = input_ids.shape[1]
130
+ n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
131
+ if n_diff_input_output > 0:
132
+ print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
133
+ outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
134
+ outputs = outputs.strip()
135
+ if outputs.endswith(stop_str):
136
+ outputs = outputs[:-len(stop_str)]
137
+ outputs = outputs.strip()
138
+ outputs = outputs_reasoning + '\n The answer is ' + outputs
139
+
140
+ ans_id = shortuuid.uuid()
141
+ ans_file.write(json.dumps({"question_id": idx,
142
+ "prompt": cur_prompt,
143
+ "text": outputs,
144
+ "answer_id": ans_id,
145
+ "model_id": model_name,
146
+ "pred": outputs_answer,
147
+ "metadata": {}}) + "\n")
148
+ ans_file.flush()
149
+ ans_file.close()
150
+
151
+
152
+ if __name__ == "__main__":
153
+ parser = argparse.ArgumentParser()
154
+ parser.add_argument("--model-path", type=str, default="facebook/opt-350m")
155
+ parser.add_argument("--model-base", type=str, default=None)
156
+ parser.add_argument("--image-folder", type=str, default="")
157
+ parser.add_argument("--question-file", type=str, default="tables/question.json")
158
+ parser.add_argument("--answers-file", type=str, default="answer.jsonl")
159
+ parser.add_argument("--conv-mode", type=str, default="simple")
160
+ parser.add_argument("--num-chunks", type=int, default=1)
161
+ parser.add_argument("--chunk-idx", type=int, default=0)
162
+ args = parser.parse_args()
163
+
164
+ eval_model(args)
ChatUniVi/eval/questions/coco2014_val_qa_eval/qa90_gpt4_answer.jsonl ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {"question_id": 0, "text": "The colors of the two suitcases in the image are black and brown with yellow details.", "category": "conv"}
2
+ {"question_id": 1, "text": "The image features two antique suitcases made of leather, stacked one on top of the other. The top suitcase is black, while the bottom one has a combination of brown and yellow colors. Both suitcases are prominently displayed side by side, taking up a large portion of the image. They appear to be vintage luggage, possibly available for purchase with price tags attached, showcasing their classic design and craftsmanship.", "category": "detail"}
3
+ {"question_id": 2, "text": "Several factors could make the two stacked suitcases valuable. In the image, they are described as antique, which suggests that they are potentially rare or have some historical significance. Their age and rarity could contribute to their value. Additionally, they are made of leather, which is a material known for its durability and, in some cases, luxury. The suitcases also differ in color, featuring black, brown, and yellow tones, which may attract buyers due to their aesthetic appeal or the desire to own a unique piece of luggage. Furthermore, the presence of price tags on the luggage indicates that they are being sold, drawing attention to their perceived value in the market. Collectors or enthusiasts of vintage items may find these suitcases valuable due to their material, design, age, and distinct appearance.", "category": "complex"}
4
+ {"question_id": 3, "text": "The main objects on the table in the image are plates, glasses, eating utensils, and possibly a bottle of something.", "category": "conv"}
5
+ {"question_id": 4, "text": "The image showcases a dining table filled with various dirty dishes, eating utensils, and a bottle. The table has plates and glasses scattered across it. There are at least two cups on the table, with one positioned on the left and another on the right side. \n\nTwo forks can be seen, one resting on a small white plate and the other located towards the left side of the table. A spoon is also present, placed near the left corner of the table. Additionally, there is a bottle located in the upper central area of the table.", "category": "detail"}
6
+ {"question_id": 5, "text": "A meal or gathering might have recently taken place around this table, as evidenced by the variety of dirty dishes, utensils, and drinkware present on it. The aftermath of this meal or event could involve the need to clean up and wash the dirty dishes, glasses, and eating utensils. Items on the table include plates, forks, spoons, cups, and a bottle, which are typically used during such occasions. Participants might have engaged in conversation, shared food and beverages, and enjoyed each other's company at this table. Once the gathering is complete, disposing of any leftovers and cleaning the table area would be necessary to prepare it for the next use.", "category": "complex"}
7
+ {"question_id": 6, "text": "The main focus of the image is a cat or kitten sitting on or next to a laptop computer.", "category": "conv"}
8
+ {"question_id": 7, "text": "The image features a cat sitting on a wooden desk, intently staring at a black laptop computer that is open in front of it. The desk is quite organized, with several books spread around, both on the left and right sides of the laptop. Some books are neatly piled and others are laid out individually. The scene could be interpreted as the cat appearing to use the laptop or showing interest in what's on the screen.", "category": "detail"}
9
+ {"question_id": 8, "text": "The cat may be interested in the laptop due to the light coming from the screen, the movement of the cursor, or the sounds produced by the laptop, such as keystrokes or notifications. Cats are known to be naturally curious creatures and are often attracted to objects that stimulate their senses. The visual display, warmth emanating from the device, and interactive nature of the laptop could be appealing to the cat, prompting it to sit on the desk and face the open laptop. Additionally, the cat may simply be seeking its owner's attention or wanting to be close to them while they use the laptop.", "category": "complex"}
10
+ {"question_id": 9, "text": "The dog in the image is black.", "category": "conv"}
11
+ {"question_id": 10, "text": "The image features a large black dog with a red collar laying down on a kitchen floor. The tiled floor provides a comfortable space for the dog to relax. The dog is positioned towards the middle of the scene. Next to the dog, there are two bowls placed on the floor, one around the top-left side and the other slightly further to the right. These could be the dog's food and water bowls. The scene depicts a cozy domestic environment for the dog.", "category": "detail"}
12
+ {"question_id": 11, "text": "The dog may have chosen to lay down on the kitchen floor in this location for several reasons. First, the tiled floor can provide a cool surface, which could be comforting compared to a warm or soft surface. This is particularly true if the dog has a thick coat or if the temperature in the room is high. Second, the dog is positioned next to its bowls and a toy, which suggests that the location is familiar and associated with food, water, and playtime. The dog could be resting near these resources for convenience and ease of access. Lastly, the location could be a central spot in the home, and dogs often prefer to stay near their owners or members of the household. By laying on the kitchen floor, the dog might be able to keep an eye on the activities happening around it and remain close to its family.", "category": "complex"}
13
+ {"question_id": 12, "text": "The cart with luggage bags is located in a lobby.", "category": "conv"}
14
+ {"question_id": 13, "text": "The scene is set in a lobby at a commercial business, where a wheeled luggage cart is filled with various suitcases and bags. There are a number of luggage bags, including two backpacks, one near the front of the cart and another near the back, as well as multiple suitcases placed on different sections of the cart. \n\nA handbag is also visible, placed near the front of the cart. Two people are present in the scene: one person standing near the left side and another person on the right side, possibly engaging in conversation or waiting to transport their luggage to their rooms.", "category": "detail"}
15
+ {"question_id": 14, "text": "In the image, a cart is filled with numerous pieces of luggage, including suitcases, bags, and backpacks, in the lobby of a commercial business. The staff responsible for handling the luggage might face several challenges such as:\n\n1. Efficiently organizing and placing the luggage on the cart to prevent any damages or items from falling off during transportation.\n2. Identifying and keeping track of each guest's belongings to avoid misplacement or mixing up the luggage.\n3. Maneuvering the heavily loaded cart without causing hindrances to other guests in the lobby while ensuring their safety.\n4. Carrying or transporting the luggage to the guests' rooms in a timely manner to maintain customer satisfaction and efficient use of staff resources.\n\nTo overcome these challenges, staff might need proper training in luggage handling, organization, and customer service skills. Maintaining clear luggage tags and taking note of each item could help them ensure accurate delivery to the corresponding guests' rooms.", "category": "complex"}
16
+ {"question_id": 15, "text": "The image features a large, placid lake.", "category": "conv"}
17
+ {"question_id": 16, "text": "The image depicts a serene and picturesque landscape with a large, placid lake surrounded by beautiful tree-covered mountains. Cliffs rise majestically on the edge of the lake, showcasing the grandeur of nature. \n\nIn the distance, near the waterfront, a train can be seen traveling on a track. The train adds a touch of human presence to the otherwise untouched landscape and further enhances the scenic view.", "category": "detail"}
18
+ {"question_id": 17, "text": "There could be several reasons for the train to be traveling on this scenic route surrounded by mountains, water, and trees. First, the train route might have been built to provide transportation services to local communities or businesses located in this remote or picturesque area. It may facilitate travel, trade, or tourism in the region. Second, the scenic route could be intentionally designed to attract tourists who seek leisure train journeys that showcase natural beauty and captivating landscapes. These types of train rides offer a unique and immersive experience for people who enjoy exploring breathtaking scenery and discovering new destinations while traveling comfortably. Ultimately, the train route could serve both practical and recreational purposes, fostering connectivity and promoting tourism for the area.", "category": "complex"}
19
+ {"question_id": 18, "text": "The main object in the image is a colorful striped umbrella standing on the beach.", "category": "conv"}
20
+ {"question_id": 19, "text": "The image features a colorful striped umbrella on the beach, with its vibrant appearance attracting attention. The umbrella is firmly positioned in the sand, providing shade and comfort for visitors. The umbrella sits near the ocean, offering a lovely view of the water and contributing to the pleasant beach atmosphere.", "category": "detail"}
21
+ {"question_id": 20, "text": "The colorful umbrella set up on the beach serves several purposes. First, it provides shade from the sun, which helps protect people from direct sunlight and the associated harmful UV rays, reducing the risk of sunburn and heatstroke. Second, it offers a comfortable spot to relax, rest, and enjoy the beach ambiance without being exposed to the intense sun or heat. Finally, the umbrella creates a designated area for beach-goers to keep their belongings and have a visible landmark to locate their spot quickly when in the crowded beach environment.", "category": "complex"}
22
+ {"question_id": 21, "text": "The house is in the beginning stages of its construction, with the wooden structure, studs, and staircase partially built but not yet completed.", "category": "conv"}
23
+ {"question_id": 22, "text": "The image shows the beginning stages of a house under construction. The wooden structure is still being built, and there are lots of wooden studs visible throughout the scene, indicating work in progress. Additionally, a partially-built staircase can be seen within the house, giving an idea of the floor plan layout.\n\nDespite the house still being under construction, a bed and a TV are already present in the area. The bed is located near the center of the image, with the TV placed to its left. This shows that some household items have been brought in, probably in anticipation of the house's completion.", "category": "detail"}
24
+ {"question_id": 23, "text": "In the current state of the house construction with wooden studs and a partially-built staircase, a potential obstacle that might occur is the incomplete structure being exposed to external elements like rain, snow, or strong winds. These conditions can potentially damage the building materials, delay construction work, and cause additional unexpected costs for repairing or replacing materials. It is essential for the builders to properly cover the construction site and store materials accordingly to protect them from potential damage when not in use.", "category": "complex"}
25
+ {"question_id": 24, "text": "There are three pizzas in the image.", "category": "conv"}
26
+ {"question_id": 25, "text": "The image displays three open pizza boxes with pizzas inside. The first pizza box, situated to the left, contains a smaller pizza. The second pizza box, positioned in the middle, features a larger pizza topped with tortilla chips. The third pizza box, located to the right, contains another smaller pizza. \n\nBeside the large pizza, there are two side orders of sauce in bowls, accompanying the delicious meal. The arrangement showcases a delicious spread of pizzas, inviting everyone to enjoy their different flavors and sizes.", "category": "detail"}
27
+ {"question_id": 26, "text": "When dividing these pizzas equitably among a group of people, one might face several challenges due to the different sizes and potential toppings on the pizzas. In the image, there are three pizzas sitting in their delivery boxes, with one pizza being larger than the other two. This size difference may complicate equal distribution of pizza slices among the group, as some people might want more of the larger pizza, while others may prefer the smaller ones.\n\nFurthermore, one of the pizzas is topped with tortilla chips, which could lead to preference differences among the group, as some people might like this topping while others may not. Lastly, alongside one of the pizzas, there are two side orders of sauce, which may need to be shared among those who enjoy sauce with their pizza. All these factors make it a challenge to ensure that everyone in the group has an equal and satisfying share of the pizzas and accompanying sauces. One possible solution is to have a group discussion and decide on rules or a plan for dividing the pizzas, taking into account individual preferences and dietary restrictions if any.", "category": "complex"}
28
+ {"question_id": 27, "text": "There are four doughnuts in the box.", "category": "conv"}
29
+ {"question_id": 28, "text": "The image features a box filled with four different kinds of doughnuts sitting on a table. Each doughnut appears to have a unique design or topping. One of the doughnuts is a cake-style doughnut, while another has nuts and coconut on top. The third doughnut appears to be a glazed one, and the last doughnut also has various toppings. The doughnuts are positioned inside the box in close proximity to one another, showcasing their delicious variety.", "category": "detail"}
30
+ {"question_id": 29, "text": "The box contains a variety of doughnuts with unique taste combinations. Among the four doughnuts, there are cake doughnuts, a glazed doughnut, and one with a mix of nuts and coconut as toppings. These different toppings and textures provide a diverse selection for those who want to try various flavors and types of doughnuts. Combining the flavors of nuts and coconut on one doughnut, in particular, offers a unique taste experience that blends the richness of nuts with the tropical sweetness of coconut. Thus, the box offers a selection that caters to different preferences and invites people to discover new taste combinations.", "category": "complex"}
31
+ {"question_id": 30, "text": "In the image, the man is holding up clothes on hangers, possibly in some hanger bags, and appears to be preparing for travel, as a suitcase is also in front of him.", "category": "conv"}
32
+ {"question_id": 31, "text": "The image depicts a man standing near a window, holding two clothing hangers with garments in both hands, one red and one white. In front of him, there is a suitcase, possibly indicating that he is preparing for travel or organizing his belongings. The man appears to be showing or comparing these clothes while packing his luggage.", "category": "detail"}
33
+ {"question_id": 32, "text": "The man might be holding the clothes on hangers because he is preparing to pack his suitcase for a trip or has just arrived at his destination and is unpacking his belongings. By holding the clothes on hangers, he can avoid wrinkles and ensure that the garments remain in good condition for wearing during his journey or at his destination. The presence of a suitcase in front of him supports this idea, as it is commonly used for transportation and storage of personal belongings when traveling.", "category": "complex"}
34
+ {"question_id": 33, "text": "There are four giraffes in the image.", "category": "conv"}
35
+ {"question_id": 34, "text": "The image showcases a group of four giraffes standing in their natural habitat, a grassy field with some dry brush. They are dispersed across the field, with one giraffe positioned more towards the left, and the other three clustered closer together on the right side. The giraffes appear to be grazing peacefully or engaging in social interactions. A tree can be seen in the scene, providing shade and a point of interest for the giraffes to gather around.", "category": "detail"}
36
+ {"question_id": 35, "text": "In the image, there are four giraffes gathered near the same tree in their natural habitat, a grass field with dry brush. Giraffes may gather near the same tree for various reasons. One common reason is to feed, as their long necks enable them to reach high branches for fresh leaves and foliage, which is a primary part of their diet. Giraffes are also social animals, so they may gather around the same tree to interact with each other and maintain their social bonds. Furthermore, the tree can provide shade in the hot African sun, offering a place for the giraffes to rest and regulate their body temperature.", "category": "complex"}
37
+ {"question_id": 36, "text": "The main focus of the image is the head of a giraffe, shown in a close-up headshot.", "category": "conv"}
38
+ {"question_id": 37, "text": "The image is a clear and colorful close up of a giraffe's head, showcasing its beautiful features. The giraffe is standing tall among several bright green trees, likely in its natural habitat. It appears to be chewing on some leaves, while its face is turned to the side, providing a detailed view of its profile.", "category": "detail"}
39
+ {"question_id": 38, "text": "From the image, it can be inferred that the giraffe's habitat is likely a natural environment with an abundance of greenery. The giraffe is standing tall among several bright green trees, which suggests that the area is rich in vegetation and provides plenty of food sources for the giraffe, such as leaves. This natural habitat is likely suitable for giraffes to thrive and maintain their unique characteristics, such as their long necks, which are adapted for reaching leaves on tall trees.", "category": "complex"}
40
+ {"question_id": 39, "text": "The art installation includes a display of large artworks, such as an oversized bench, painted feline heads, and potentially other artistic sculptures or images.", "category": "conv"}
41
+ {"question_id": 40, "text": "The image features an art installation placed on a city street. The display consists of a large, oversized wooden bench and two massive animal art sculptures, which appear to be painted feline heads. \n\nThere are several people in the scene, with two people sitting near the art display, one person standing nearby, and another person further to the left. A parked car is visible behind the bench, close to the edge of the street. Additionally, a backpack can be seen on the ground, closer to the left side of the bench.", "category": "detail"}
42
+ {"question_id": 41, "text": "The art installation, featuring an oversized wooden bench and two massive animal art sculptures, encourages interaction among people by providing a visually intriguing and inviting space to sit or gather. People are naturally drawn to the unique and whimsical nature of these installations, sparking curiosity and conversation among those who encounter them. The oversized bench provides seating for multiple individuals, prompting people to sit down, rest, or socialize while admiring the giant painted feline heads and other artworks on display. Additionally, the installations capture the attention of passersby, creating a shared experience and a sense of community among those who visit the area. The artistic environment stimulates discussion and appreciation of the art, facilitating social interactions and connections among those who gather near the sculptures and oversized bench.", "category": "complex"}
43
+ {"question_id": 42, "text": "The main focus of the image is a car parked on the side of the road, next to a parking meter.", "category": "conv"}
44
+ {"question_id": 43, "text": "The scene features a black car parked on the side of the road next to a parking meter. There is another parking meter slightly further ahead of the car. The car is parked in front of a building, which seems to be the destination for the driver. \n\nAdditionally, there are other vehicles in the image. A gray car is situated further behind the black car, and a truck can be seen in the background on the right side. Moreover, there is another vehicle barely visible on the left side of the scene.", "category": "detail"}
45
+ {"question_id": 44, "text": "The most plausible reason for the car to be parked on the side of the road is that it is utilizing the available parking spot with parking meters. In the image, the car is parked next to two parking meters, which indicates that the driver has parked the car to follow parking regulations and likely paid for their parking session. The car might be parked there so the driver or passengers can go to a nearby building, shop, or participate in any other activities in the area. Parking meters are commonly used in urban and commercial areas to manage and regulate limited street parking spaces, and it's reasonable to assume the driver is abiding by these parking rules.", "category": "complex"}
46
+ {"question_id": 45, "text": "The unusual aspect of the elderly man's facial appearance in the image is that he has the head of a toothbrush under his nose, which mimics a mustache, specifically a toothbrush mustache.", "category": "conv"}
47
+ {"question_id": 46, "text": "The image features an elderly man humorously wearing the head of a toothbrush under his nose, creating the illusion of a toothbrush mustache. Since the toothbrush head is positioned like a mustache, it is reminiscent of a toothbrush mustache caricature often associated with Hitler. The man takes up most of the frame, appearing front and center in the scene.", "category": "detail"}
48
+ {"question_id": 47, "text": "The elderly man wearing the head of a toothbrush under his nose as a moustache could be conveying a satirical or humorous message. By mimicking a toothbrush mustache, he may be making light of or criticizing a specific historical figure or style associated with the toothbrush mustache, such as Adolf Hitler. Using a toothbrush instead of an actual mustache allows him to dramatically emphasize the point and create a lighthearted or comical effect. However, it's essential to consider cultural and social contexts when interpreting such unconventional expressions, as the message may not always be clear or universally accepted.", "category": "complex"}
49
+ {"question_id": 48, "text": "There are two large passenger airplanes visible in the image.", "category": "conv"}
50
+ {"question_id": 49, "text": "The scene captures a picturesque view of two large passenger jets, one in the air and one on the ground. They are flying over a beautiful beach filled with various birds. Many birds can be seen scattered across the scene, both near the water and around the area. The blue water in the background adds a calming touch to the image.", "category": "detail"}
51
+ {"question_id": 50, "text": "The presence of two large passenger jets flying in close proximity to the beach filled with birds can have a negative impact on the avian population. The noise generated by the engines can be stressful and disruptive for the birds, potentially resulting in altered behaviors, flight patterns, or even relocation from the area. In addition, the airplanes could pose a risk of bird strikes, in which birds collide with the planes, leading to injuries or fatalities for the birds and damage to the aircraft. This highlights the importance of maintaining safe distances between airplanes and wildlife habitats in order to minimize the risk of adverse effects on both the environment and aviation.", "category": "complex"}
52
+ {"question_id": 51, "text": "The cat is curled up and sleeping on the red couch.", "category": "conv"}
53
+ {"question_id": 52, "text": "A tan and black cat is curled up and comfortably asleep on a vibrant red couch. The cat is situated towards the center of the plush seat. The red couch itself is prominent in the image, occupying a large portion of the frame. The peaceful sleeping cat adds a sense of warmth and coziness to the scene.", "category": "detail"}
54
+ {"question_id": 53, "text": "The cat may have chosen to sleep on the red couch for several reasons. The couch appears to be plush and comfortable, providing a soft surface for the cat to curl up and maintain its body heat. Cats also prefer quiet and low-traffic areas to rest. The couch may be located in such an area, providing a sense of security for the cat while sleeping. Furthermore, felines are known to be attracted to soft and warm materials, making the red velvet seat an appealing spot for relaxation. It's also common for cats to sleep in locations familiar to them or near their human companions, so the couch might be a place where the cat often spends time or feels safe.", "category": "complex"}
55
+ {"question_id": 54, "text": "An old Volkswagen Bug is parked next to the stop sign in the image.", "category": "conv"}
56
+ {"question_id": 55, "text": "In the scene, a woman is standing in front of a window, observing the street outside. On the street, a vintage Volkswagen Bug is parked near a stop sign, which is located towards the center of the image. Several other cars occupy the street, including one positioned to the left of the Volkswagen and two others in the background. On the far left and far right sides of the image, there are additional cars partially visible. The street also features a tree growing near the stop sign, adding a touch of greenery to the urban setting.", "category": "detail"}
57
+ {"question_id": 56, "text": "From the image, it can be inferred that the traffic situation in the area is relatively light or calm. There is an old VW Bug parked near a stop sign, and a few other cars are also visible on the street. However, there doesn't seem to be any congestion or significant traffic. The presence of the stop sign indicates that there is some traffic regulation and order in place to manage vehicle movement, contributing to the overall calmness of the area. Moreover, no people are seen near the stop sign, which further suggests that there might be low pedestrian activity at the time the picture was taken.", "category": "complex"}
58
+ {"question_id": 57, "text": "The man in the image is using his cell phone and giving a thumbs up, possibly posing for a picture.", "category": "conv"}
59
+ {"question_id": 58, "text": "The image depicts a group of people gathered inside a room, creating a lively social atmosphere. A man is prominently featured in the scene, holding a cell phone to his ear and smiling with a thumbs-up gesture, possibly posing for a picture or simply enjoying the conversation.\n\nThere are multiple other people in the room, adding to the gathering and engaging in various conversations. The scene also has two cups visible, one on the left side of the room and another on the right side, indicating that the gathering may be a casual social event.", "category": "detail"}
60
+ {"question_id": 59, "text": "It is likely that the man is giving a thumbs-up gesture while talking on the phone to express a positive emotion or to signal agreement, approval, or satisfaction with the conversation he is having. This non-verbal communication can be conveyed to the people around him or to the person taking the picture of him while on the phone call. The man might be receiving good news, agreeing with the person on the phone, or sharing his excitement with the group of people surrounding him in the room. The specific reason cannot be precisely determined from the image alone, but it does indicate a positive sentiment associated with the phone call.", "category": "complex"}
61
+ {"question_id": 60, "text": "The dog in the image is a husky.", "category": "conv"}
62
+ {"question_id": 61, "text": "The image shows a large, adorable husky dog sleeping peacefully on a dog bed in a room. The room has a somewhat dark ambiance, making the scene feel cozy and comfortable. \n\nIn the same room, there are two chairs, one positioned towards the center and another one closer to the right side. Additionally, there are two potted plants, one situated slightly behind and to the right of the dog and the other placed further to the right in the room. The presence of these elements gives the room a warm, inviting atmosphere.", "category": "detail"}
63
+ {"question_id": 62, "text": "The dog owner seems to have taken several measures to make their dog feel comfortable in the room. Based on the image, an adorable husky dog has a designated dog bed to sleep in, providing cushioning and a cozy space for rest. The room is also dimly lit or dark, which contributes to a calmer atmosphere that promotes sleep and relaxation. There might be other considerations, such as room temperature or air circulation, that aid in creating a comfortable environment for the dog. It's essential for pet owners to ensure that their pets have a secure and comfortable space to rest in order to maintain their well-being and happiness.", "category": "complex"}
64
+ {"question_id": 63, "text": "The color of the elephant in the image is grey.", "category": "conv"}
65
+ {"question_id": 64, "text": "The image depicts a baby elephant standing alone inside an enclosure. The elephant is positioned towards the center of the pen with a large sand dune, or dirt mount, nearby. In the background, there is a brick building that serves as part of the exhibit. The grey elephant stands calmly, occupying the majority of the scene in this pen.", "category": "detail"}
66
+ {"question_id": 65, "text": "A potential concern for the baby elephant standing alone inside the pen could be the lack of social interaction with other elephants. Elephants are highly social creatures and form strong bonds within their family units. The absence of other elephants in the enclosure might lead to feelings of loneliness, stress, and anxiety for the baby elephant. It is crucial for the mental and emotional well-being of elephants, especially young ones, to have regular opportunities to interact with their peers and family members in a naturalistic, supportive environment. By addressing this concern, the caretakers of the baby elephant can help ensure its psychological well-being and overall health.", "category": "complex"}
67
+ {"question_id": 66, "text": "On the orange plate, there are a burger or sandwich, a bowl of broccoli, and a pickle.", "category": "conv"}
68
+ {"question_id": 67, "text": "The image features a dining table with an orange plate in the center. On the plate, there is a half of a sandwich, a pickle, and a bowl of broccoli, creating a visually appealing and mouth-watering combination. A fork is also placed alongside the plate, ready to be used for enjoying the meal. Several individual pieces of broccoli can be seen around the bowl, adding variety and color to the scene.", "category": "detail"}
69
+ {"question_id": 68, "text": "Based on the image, it can be inferred that the individual has a balanced approach to their dietary choices. The meal on the table consists of a sandwich, a bowl of broccoli, and a pickle on an orange plate. The sandwich likely provides carbohydrates and proteins, while the broccoli offers essential vitamins, minerals, and fiber. The pickle adds some flavor and tanginess to the meal. This combination of foods illustrates that the person is interested in having a diverse and nutritious diet, incorporating both proteins and vegetables in their meal. Additionally, the presence of a fork suggests that they prefer using cutlery while eating, which can be seen as a more cultured and organized approach to dining.", "category": "complex"}
70
+ {"question_id": 69, "text": "A white duck is pictured in the image.", "category": "conv"}
71
+ {"question_id": 70, "text": "The image features a single white bird, likely a duck or a goose, walking along a paved road. The bird appears to be closely examining the ground as it walks. The road runs adjacent to a patch of grass, providing a contrasting backdrop for the scene. The bird occupies a predominant part of the image, offering a close-up view of its action.", "category": "detail"}
72
+ {"question_id": 71, "text": "While walking along the paved road, the duck may face various challenges. Firstly, the duck could be at risk of encountering vehicles, which might not notice or expect to see wildlife on the road. This could put the duck in danger of being hit or injured by passing traffic. Secondly, the duck might struggle to find appropriate food sources on or near the paved road, as opposed to its natural habitat, such as a body of water or a grassy area, where it would have easier access to its regular diet.\n\nFurthermore, the duck might be exposed to potential predators, like domestic pets or other animals that live in urban environments, increasing the risk of harm for the duck. Lastly, walking on the paved concrete surface could be less comfortable for the duck than walking on softer natural ground, causing discomfort over time. Overall, the duck's safety and well-being may be compromised by navigating this environment that is not adapted to its natural behaviors and needs.", "category": "complex"}
73
+ {"question_id": 72, "text": "Yes, the little boy is wearing a helmet to ensure his safety while riding his bike.", "category": "conv"}
74
+ {"question_id": 73, "text": "The image depicts a little boy riding his bike on a road. He is practicing safety by wearing a yellow helmet while cycling. The boy is visible from a side angle, capturing both him and his bicycle in motion.", "category": "detail"}
75
+ {"question_id": 74, "text": "The little boy's precaution of wearing a helmet is noteworthy because it shows that the child or their guardian is aware of and strictly adhering to safety precautions. Wearing a helmet while riding a bicycle is crucial for reducing the risk of severe head injuries in the event of a crash, fall, or any other unforeseen incident. It is especially important for children, who are often more prone to accidents due to their limited experience with balancing and negotiating obstacles. By wearing a helmet, the boy is demonstrating responsible behavior and setting a positive example for others to follow, promoting a culture of safety awareness.", "category": "complex"}
76
+ {"question_id": 75, "text": "There are three people visible in the image - two women and one man.", "category": "conv"}
77
+ {"question_id": 76, "text": "The image shows a group of people at a celebration, likely participating in a wine tasting event. There are a total of six people, with three young adults prominently in the foreground. A man wearing glasses stands in the middle, flanked by a couple of women on either side. They are all holding wine glasses, enjoying the event and smiling.\n\nAt the table, there are several wine bottles dispersed along its surface, showing the variety of options available for tasting. Additionally, there is a handbag placed on the table, possibly belonging to one of the women attending the event. \n\nTwo more people are visible in the background. They are smiling and making conversation while engaging in the celebration with the others.", "category": "detail"}
78
+ {"question_id": 77, "text": "It appears that the group of people are gathered for a wine tasting or celebration in which they are enjoying various types of wine. They are seen standing and sitting around a table with several wine bottles and holding wine glasses. Their smiles and the friendly atmosphere indicate that it's a social event where they have gathered to indulge in sampling different wines, engage in conversations, and enjoy each other's company.", "category": "complex"}
79
+ {"question_id": 78, "text": "The main object featured in the image is the clock mounted on a pole or a short tower, standing on the sidewalk next to a building.", "category": "conv"}
80
+ {"question_id": 79, "text": "The image features a quiet street with a tall clock mounted on a pole at the side of the pavement, near a building. The pole stands prominently on the empty sidewalk, offering a convenient time-keeping source for pedestrians.\n\nThere are a few potted plants along the sidewalk, adding a touch of greenery to the scene. Bicycles can also be seen parked nearby, and a couple of cars are parked further down the street. A person is walking in the background, adding some life to the otherwise calm environment.", "category": "detail"}
81
+ {"question_id": 80, "text": "As you walk down this quiet street, you can easily tell the time by looking at the tall clock that is mounted on a pole along the sidewalk. This clock stands out significantly, making it easily noticeable. Regarding the direction of the sidewalk, the presence of potted plants, bicycles, and cars suggest that this is a well-maintained and organized street. As you follow the sidewalk further, you will see that it is lined with trees, potted plants, and parked bicycles and cars, guiding you in the direction it leads. Additionally, the building next to the clock also gives you context for the orientation and direction of the street.", "category": "complex"}
82
+ {"question_id": 81, "text": "The person is riding a motorbike, which can also be referred to as a motorcycle or a moped. In this case, the terms motorcycle, scooter, and moped are used interchangeably to describe the same vehicle the woman is riding.", "category": "conv"}
83
+ {"question_id": 82, "text": "The scene showcases a dirt road, with a woman riding a motorcycle in the middle of the road. She is accompanied by a man walking alongside her, with another man further down the road. Various animals, including three cows, are also present in the scene, suggesting a rural setting. The main cow is positioned to the right of the motorcycle while two smaller cows can be seen on the left side of the road. The people and animals all appear to be going in the same direction down the dirt road.", "category": "detail"}
84
+ {"question_id": 83, "text": "The woman on the motorcycle might face challenges navigating the dirt road, especially because of the presence of multiple objects and living beings on the road. In the image, a cow is nearby, along with two other smaller cows, two men, and a dog. Dirt roads can be uneven, dusty, and unpredictable, making it important for the woman to maneuver cautiously to avoid any potential accidents. Additionally, she needs to be aware of the animals and people around her to ensure both her safety and the safety of others. This situation requires her to be vigilant, slow down when necessary, and carefully navigate through the environment.", "category": "complex"}
85
+ {"question_id": 84, "text": "The skateboard in the image is in an upside-down position, with its wheels pointing up and laying on the ground.", "category": "conv"}
86
+ {"question_id": 85, "text": "In the image, a person wearing camo shorts is standing on a cement surface next to an overturned skateboard. The skateboard is laying upside down with its wheels pointing up, giving a sense of it having been flipped or potentially used for a trick. The boy appears to be standing in front of the skateboard, engaging with it or possibly preparing for his next move.", "category": "detail"}
87
+ {"question_id": 86, "text": "It's plausible that prior to this moment, the person standing next to the overturned skateboard might have attempted a trick or maneuver on the skateboard, which resulted in either a failed attempt or a wipeout. As a consequence, the skateboard ended up upside down on the ground, with its wheels pointed upward. The person, possibly the skateboarder, is standing next to it, possibly pondering their next move, contemplating a retry or assessing any potential damage to the skateboard.", "category": "complex"}
88
+ {"question_id": 87, "text": "The man and woman are wearing umbrella hats, which are designed to provide protection from the rain.", "category": "conv"}
89
+ {"question_id": 88, "text": "The image depicts a man and a woman sitting on top of a bridge, both wearing umbrella hats. The quirky umbrella hats provide them with some cover from the rainy weather. A dog is accompanying the couple, taking a break with them on the bridge. \n\nThe surrounding area has a view of the ocean, and there are boats visible in the water. One boat can be found close to the right edge of the scene, while two other boats are in the middle and the far left side of the frame. Additional umbrellas can be spotted in the area, signifying that other pedestrians have also sought shelter from the rain.", "category": "detail"}
90
+ {"question_id": 89, "text": "On this rainy day, the umbrella hats provide the couple several benefits as they sit on top of a bridge near the ocean with their dog. First, the umbrella hats enable them to keep their hands free, allowing them to hold their dog's leash, interact with each other, and perform other tasks without holding a traditional umbrella. Second, the umbrella hats protect their heads and upper bodies from getting wet due to rain, making their outdoor experience more comfortable. Additionally, the novel and fun nature of the umbrella hats can be a conversation starter and bring some humor to their day despite the gloomy weather.", "category": "complex"}
ChatUniVi/eval/questions/coco2014_val_qa_eval/qa90_questions.jsonl ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {"question_id": 0, "image": "COCO_val2014_000000441147.jpg", "text": "What is the color of the two suitcases in the image?", "category": "conv"}
2
+ {"question_id": 1, "image": "COCO_val2014_000000441147.jpg", "text": "Analyze the image in a comprehensive and detailed manner.", "category": "detail"}
3
+ {"question_id": 2, "image": "COCO_val2014_000000441147.jpg", "text": "What potential factors could make these suitcases valuable?", "category": "complex"}
4
+ {"question_id": 3, "image": "COCO_val2014_000000353536.jpg", "text": "What are the main objects on the table in the image?", "category": "conv"}
5
+ {"question_id": 4, "image": "COCO_val2014_000000353536.jpg", "text": "Describe the following image.", "category": "detail"}
6
+ {"question_id": 5, "image": "COCO_val2014_000000353536.jpg", "text": "What activity might have recently taken place around this table and what could be its aftermath?", "category": "complex"}
7
+ {"question_id": 6, "image": "COCO_val2014_000000506095.jpg", "text": "What is the main focus of the image?", "category": "conv"}
8
+ {"question_id": 7, "image": "COCO_val2014_000000506095.jpg", "text": "What is this photo about'?", "category": "detail"}
9
+ {"question_id": 8, "image": "COCO_val2014_000000506095.jpg", "text": "What could be a reason for the cat's interest in the laptop?", "category": "complex"}
10
+ {"question_id": 9, "image": "COCO_val2014_000000514915.jpg", "text": "What color is the dog in the image?", "category": "conv"}
11
+ {"question_id": 10, "image": "COCO_val2014_000000514915.jpg", "text": "Describe the following image.", "category": "detail"}
12
+ {"question_id": 11, "image": "COCO_val2014_000000514915.jpg", "text": "Why might the dog have chosen to lay down on the floor in this location?", "category": "complex"}
13
+ {"question_id": 12, "image": "COCO_val2014_000000056013.jpg", "text": "Where is the cart with luggage bags located?", "category": "conv"}
14
+ {"question_id": 13, "image": "COCO_val2014_000000056013.jpg", "text": "Describe the following image.", "category": "detail"}
15
+ {"question_id": 14, "image": "COCO_val2014_000000056013.jpg", "text": "What challenges might the staff encounter with handling luggage in the lobby?", "category": "complex"}
16
+ {"question_id": 15, "image": "COCO_val2014_000000408439.jpg", "text": "What is the body of water seen in the image?", "category": "conv"}
17
+ {"question_id": 16, "image": "COCO_val2014_000000408439.jpg", "text": "Can you elaborate on the elements of the picture provided?", "category": "detail"}
18
+ {"question_id": 17, "image": "COCO_val2014_000000408439.jpg", "text": "What are potential reasons for the train to be traveling in such a scenic route?", "category": "complex"}
19
+ {"question_id": 18, "image": "COCO_val2014_000000164255.jpg", "text": "What is the main object in the image?", "category": "conv"}
20
+ {"question_id": 19, "image": "COCO_val2014_000000164255.jpg", "text": "What do you think is going on in this snapshot?", "category": "detail"}
21
+ {"question_id": 20, "image": "COCO_val2014_000000164255.jpg", "text": "What purpose does the umbrella serve on the beach?", "category": "complex"}
22
+ {"question_id": 21, "image": "COCO_val2014_000000034096.jpg", "text": "What stage is the house in regarding its construction?", "category": "conv"}
23
+ {"question_id": 22, "image": "COCO_val2014_000000034096.jpg", "text": "What is this photo about'?", "category": "detail"}
24
+ {"question_id": 23, "image": "COCO_val2014_000000034096.jpg", "text": "What may be a potential obstacle for the house construction in its current state?", "category": "complex"}
25
+ {"question_id": 24, "image": "COCO_val2014_000000385873.jpg", "text": "How many pizzas are there in the image?", "category": "conv"}
26
+ {"question_id": 25, "image": "COCO_val2014_000000385873.jpg", "text": "Explain the visual content of the image in great detail.", "category": "detail"}
27
+ {"question_id": 26, "image": "COCO_val2014_000000385873.jpg", "text": "What are the possible challenges one might face when dividing these pizzas equitably among a group of people?", "category": "complex"}
28
+ {"question_id": 27, "image": "COCO_val2014_000000367571.jpg", "text": "How many doughnuts are in the box?", "category": "conv"}
29
+ {"question_id": 28, "image": "COCO_val2014_000000367571.jpg", "text": "Write a detailed description of the given image.", "category": "detail"}
30
+ {"question_id": 29, "image": "COCO_val2014_000000367571.jpg", "text": "What unique taste combinations can be found in this box of doughnuts?", "category": "complex"}
31
+ {"question_id": 30, "image": "COCO_val2014_000000319432.jpg", "text": "What is the man doing in the image?", "category": "conv"}
32
+ {"question_id": 31, "image": "COCO_val2014_000000319432.jpg", "text": "Can you describe the main features of this image for me?", "category": "detail"}
33
+ {"question_id": 32, "image": "COCO_val2014_000000319432.jpg", "text": "Why might the man be holding the clothes on hangers?", "category": "complex"}
34
+ {"question_id": 33, "image": "COCO_val2014_000000225738.jpg", "text": "How many giraffes are depicted in the image?", "category": "conv"}
35
+ {"question_id": 34, "image": "COCO_val2014_000000225738.jpg", "text": "Write a detailed description of the given image.", "category": "detail"}
36
+ {"question_id": 35, "image": "COCO_val2014_000000225738.jpg", "text": "Why might these giraffes be gathering near the same tree?", "category": "complex"}
37
+ {"question_id": 36, "image": "COCO_val2014_000000092109.jpg", "text": "What is the main focus of the image?", "category": "conv"}
38
+ {"question_id": 37, "image": "COCO_val2014_000000092109.jpg", "text": "What is this photo about'?", "category": "detail"}
39
+ {"question_id": 38, "image": "COCO_val2014_000000092109.jpg", "text": "What can be inferred about the giraffe's habitat from this image?", "category": "complex"}
40
+ {"question_id": 39, "image": "COCO_val2014_000000506483.jpg", "text": "What kind of objects are included in the art installation?", "category": "conv"}
41
+ {"question_id": 40, "image": "COCO_val2014_000000506483.jpg", "text": "Explain the visual content of the image in great detail.", "category": "detail"}
42
+ {"question_id": 41, "image": "COCO_val2014_000000506483.jpg", "text": "How might the art installation encourage interaction among people?", "category": "complex"}
43
+ {"question_id": 42, "image": "COCO_val2014_000000097131.jpg", "text": "What is the main focus of the image?", "category": "conv"}
44
+ {"question_id": 43, "image": "COCO_val2014_000000097131.jpg", "text": "Can you elaborate on the elements of the picture provided?", "category": "detail"}
45
+ {"question_id": 44, "image": "COCO_val2014_000000097131.jpg", "text": "What might be the reason for the car to be parked on the side of the road?", "category": "complex"}
46
+ {"question_id": 45, "image": "COCO_val2014_000000052312.jpg", "text": "What is unusual about the elderly man's facial appearance in the image?", "category": "conv"}
47
+ {"question_id": 46, "image": "COCO_val2014_000000052312.jpg", "text": "What's happening in the scene?", "category": "detail"}
48
+ {"question_id": 47, "image": "COCO_val2014_000000052312.jpg", "text": "What message could be conveyed by the man's unusual facial adornment?", "category": "complex"}
49
+ {"question_id": 48, "image": "COCO_val2014_000000258285.jpg", "text": "How many airplanes are visible in the image?", "category": "conv"}
50
+ {"question_id": 49, "image": "COCO_val2014_000000258285.jpg", "text": "What do you see happening in this image?", "category": "detail"}
51
+ {"question_id": 50, "image": "COCO_val2014_000000258285.jpg", "text": "What environmental impact might these planes' activity have on the birds?", "category": "complex"}
52
+ {"question_id": 51, "image": "COCO_val2014_000000081552.jpg", "text": "What is the cat doing on the red couch?", "category": "conv"}
53
+ {"question_id": 52, "image": "COCO_val2014_000000081552.jpg", "text": "Write a detailed description of the given image.", "category": "detail"}
54
+ {"question_id": 53, "image": "COCO_val2014_000000081552.jpg", "text": "What factors may have led the cat to choose this location for sleep?", "category": "complex"}
55
+ {"question_id": 54, "image": "COCO_val2014_000000066144.jpg", "text": "What type of car is parked next to the stop sign in the image?", "category": "conv"}
56
+ {"question_id": 55, "image": "COCO_val2014_000000066144.jpg", "text": "Explain the visual content of the image in great detail.", "category": "detail"}
57
+ {"question_id": 56, "image": "COCO_val2014_000000066144.jpg", "text": "What can be inferred about the traffic situation in the area?", "category": "complex"}
58
+ {"question_id": 57, "image": "COCO_val2014_000000203629.jpg", "text": "What is the man doing in the image?", "category": "conv"}
59
+ {"question_id": 58, "image": "COCO_val2014_000000203629.jpg", "text": "Can you describe the main features of this image for me?", "category": "detail"}
60
+ {"question_id": 59, "image": "COCO_val2014_000000203629.jpg", "text": "What might be the reason behind the man's thumbs-up gesture while on the phone?", "category": "complex"}
61
+ {"question_id": 60, "image": "COCO_val2014_000000109532.jpg", "text": "What breed is the dog in the image?", "category": "conv"}
62
+ {"question_id": 61, "image": "COCO_val2014_000000109532.jpg", "text": "What are the key elements in this picture?", "category": "detail"}
63
+ {"question_id": 62, "image": "COCO_val2014_000000109532.jpg", "text": "What measures may be taken by the dog's owner to make the dog feel comfortable in the room?", "category": "complex"}
64
+ {"question_id": 63, "image": "COCO_val2014_000000431165.jpg", "text": "What is the color of the elephant in the image?", "category": "conv"}
65
+ {"question_id": 64, "image": "COCO_val2014_000000431165.jpg", "text": "What do you think is going on in this snapshot?", "category": "detail"}
66
+ {"question_id": 65, "image": "COCO_val2014_000000431165.jpg", "text": "What could be a potential concern for the baby elephant in this setting?", "category": "complex"}
67
+ {"question_id": 66, "image": "COCO_val2014_000000020650.jpg", "text": "What type of food items are present on the orange plate?", "category": "conv"}
68
+ {"question_id": 67, "image": "COCO_val2014_000000020650.jpg", "text": "What are the key elements in this picture?", "category": "detail"}
69
+ {"question_id": 68, "image": "COCO_val2014_000000020650.jpg", "text": "What can be inferred about the individual's dietary choices?", "category": "complex"}
70
+ {"question_id": 69, "image": "COCO_val2014_000000205183.jpg", "text": "What type of bird is pictured in the image?", "category": "conv"}
71
+ {"question_id": 70, "image": "COCO_val2014_000000205183.jpg", "text": "What do you see happening in this image?", "category": "detail"}
72
+ {"question_id": 71, "image": "COCO_val2014_000000205183.jpg", "text": "What challenges could the duck face while walking along the paved road?", "category": "complex"}
73
+ {"question_id": 72, "image": "COCO_val2014_000000210299.jpg", "text": "Is the little boy wearing any safety gear while riding his bike?", "category": "conv"}
74
+ {"question_id": 73, "image": "COCO_val2014_000000210299.jpg", "text": "Can you elaborate on the elements of the picture provided?", "category": "detail"}
75
+ {"question_id": 74, "image": "COCO_val2014_000000210299.jpg", "text": "Why is the little boy's precaution noteworthy?", "category": "complex"}
76
+ {"question_id": 75, "image": "COCO_val2014_000000515716.jpg", "text": "How many people are visible in the image?", "category": "conv"}
77
+ {"question_id": 76, "image": "COCO_val2014_000000515716.jpg", "text": "What do you see happening in this image?", "category": "detail"}
78
+ {"question_id": 77, "image": "COCO_val2014_000000515716.jpg", "text": "What might be the reason behind this gathering?", "category": "complex"}
79
+ {"question_id": 78, "image": "COCO_val2014_000000460149.jpg", "text": "What is the main object featured in the image?", "category": "conv"}
80
+ {"question_id": 79, "image": "COCO_val2014_000000460149.jpg", "text": "Describe the following image.", "category": "detail"}
81
+ {"question_id": 80, "image": "COCO_val2014_000000460149.jpg", "text": "Imagine you are walking down this street; how would you know the time or which direction the sidewalk leads?", "category": "complex"}
82
+ {"question_id": 81, "image": "COCO_val2014_000000293505.jpg", "text": "Is the person riding a motorbike or scooter?", "category": "conv"}
83
+ {"question_id": 82, "image": "COCO_val2014_000000293505.jpg", "text": "Explain the visual content of the image in great detail.", "category": "detail"}
84
+ {"question_id": 83, "image": "COCO_val2014_000000293505.jpg", "text": "What challenges might the woman on the motorcycle face in this situation?", "category": "complex"}
85
+ {"question_id": 84, "image": "COCO_val2014_000000525439.jpg", "text": "What is the position of the skateboard in the image?", "category": "conv"}
86
+ {"question_id": 85, "image": "COCO_val2014_000000525439.jpg", "text": "Can you elaborate on the elements of the picture provided?", "category": "detail"}
87
+ {"question_id": 86, "image": "COCO_val2014_000000525439.jpg", "text": "What might have happened prior to this moment?", "category": "complex"}
88
+ {"question_id": 87, "image": "COCO_val2014_000000534270.jpg", "text": "What type of hats are the man and woman wearing?", "category": "conv"}
89
+ {"question_id": 88, "image": "COCO_val2014_000000534270.jpg", "text": "Can you describe the main features of this image for me?", "category": "detail"}
90
+ {"question_id": 89, "image": "COCO_val2014_000000534270.jpg", "text": "What benefits do umbrella hats provide to the couple on this rainy day?", "category": "complex"}
ChatUniVi/eval/questions/coco_pope/coco_pope_adversarial.jsonl ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/coco_pope/coco_pope_popular.jsonl ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/coco_pope/coco_pope_random.jsonl ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/scienceqa/pid_splits.json ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/scienceqa/test_QCM-LEA.json ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/video_qa/activitynet_a_list.json ADDED
@@ -0,0 +1,2105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "no",
3
+ "yes",
4
+ "day",
5
+ "outdoor",
6
+ "good looking",
7
+ "bit dangerous",
8
+ "secondary",
9
+ "simple",
10
+ "much simpler",
11
+ "more difficult",
12
+ "difficulty",
13
+ "low",
14
+ "unsafe",
15
+ "sunny",
16
+ "cloudy",
17
+ "2",
18
+ "1",
19
+ "5",
20
+ "3",
21
+ "4",
22
+ "6",
23
+ "11",
24
+ "7",
25
+ "8",
26
+ "female",
27
+ "male",
28
+ "indoor",
29
+ "shopkeepers and customers",
30
+ "friend",
31
+ "brother",
32
+ "bath towel",
33
+ "tie rope",
34
+ "combat training",
35
+ "play football on table",
36
+ "chipping potatoes",
37
+ "dishwashing",
38
+ "skateboard with water",
39
+ "defoliation",
40
+ "brush ones teeth",
41
+ "baton tennis",
42
+ "play ball",
43
+ "performing martial arts",
44
+ "play",
45
+ "dance",
46
+ "gargle",
47
+ "slider",
48
+ "wine dressing",
49
+ "rowing",
50
+ "pacify horse",
51
+ "drum",
52
+ "cook dish",
53
+ "do floor exercises",
54
+ "match",
55
+ "gymnastics in parallel bars",
56
+ "be referee",
57
+ "dishware",
58
+ "skin care",
59
+ "train",
60
+ "hammer throw",
61
+ "draw eyes shadow",
62
+ "wash horse",
63
+ "car wash",
64
+ "play musical instrument",
65
+ "kayaking",
66
+ "skiing",
67
+ "make cake",
68
+ "sweep snow for cars",
69
+ "paracentesis",
70
+ "drink",
71
+ "practice martial arts",
72
+ "make cold dishes",
73
+ "contain water",
74
+ "put shot",
75
+ "bathe horse",
76
+ "making cocktails",
77
+ "clean room",
78
+ "wipe glass",
79
+ "shovel snow",
80
+ "make spaghetti",
81
+ "dig up soil",
82
+ "cut tomato",
83
+ "tattoo",
84
+ "boxing",
85
+ "bodybuilding",
86
+ "sailing competition",
87
+ "hopping hula hoop",
88
+ "somersault",
89
+ "paint fingernails",
90
+ "make sandwich",
91
+ "introduce tool",
92
+ "walk dog",
93
+ "make ice cream",
94
+ "manicure",
95
+ "make hair",
96
+ "brushing horse",
97
+ "wrapping paper",
98
+ "play game",
99
+ "wear shoe",
100
+ "play with sand",
101
+ "chopping wood",
102
+ "smear sunscreen",
103
+ "weightlifting",
104
+ "do some washing",
105
+ "assemble bicycle",
106
+ "bathe dog",
107
+ "shoe polish",
108
+ "fire",
109
+ "sharpening",
110
+ "wear contact lenses",
111
+ "parade",
112
+ "brush shoes",
113
+ "cleaning deciduous leaves",
114
+ "wash clothes",
115
+ "play tennis",
116
+ "clink with dog",
117
+ "tires dismantling",
118
+ "snow removal",
119
+ "squeezed juice",
120
+ "play table tennis",
121
+ "run",
122
+ "diving",
123
+ "decorating christmas tree",
124
+ "shooting",
125
+ "pruning branches",
126
+ "javelin throw",
127
+ "shuttlecock",
128
+ "wallpaper",
129
+ "practice stick method",
130
+ "control remote control ship",
131
+ "assembling tires",
132
+ "sweeping snow",
133
+ "sailing",
134
+ "cut nails for cat",
135
+ "assembly slate",
136
+ "push ice pot",
137
+ "physical exercise",
138
+ "assemble christmas tree",
139
+ "hair removal",
140
+ "surfing",
141
+ "making lollipops",
142
+ "bungee jumping",
143
+ "weed",
144
+ "handcraft",
145
+ "clean glass",
146
+ "loading chain",
147
+ "play magic cube",
148
+ "landscaping",
149
+ "play volleyball",
150
+ "play harmonica",
151
+ "cooking",
152
+ "shave legs",
153
+ "taking something",
154
+ "perform",
155
+ "drinking",
156
+ "play weeding machine",
157
+ "clean desk",
158
+ "make drink",
159
+ "peeling sweet potatoes",
160
+ "licensing",
161
+ "pole vault",
162
+ "bowling",
163
+ "skip lattices",
164
+ "introduction of lawn mower",
165
+ "hula hoop",
166
+ "play bounce shoes",
167
+ "yoga teaching",
168
+ "throwing discus",
169
+ "balance beam",
170
+ "flute",
171
+ "fly kite",
172
+ "leaping",
173
+ "finger guessing game",
174
+ "blow sax",
175
+ "comb ones hair",
176
+ "make face",
177
+ "weave hair",
178
+ "chat",
179
+ "sunscreen",
180
+ "photograph",
181
+ "trailing ground",
182
+ "iron clothes",
183
+ "chipping",
184
+ "ride camel",
185
+ "demonstrating",
186
+ "riding",
187
+ "make light",
188
+ "paint fence",
189
+ "making sandwiches",
190
+ "discus throwing",
191
+ "gymnastics on horizontal bar",
192
+ "water gliding",
193
+ "shot put",
194
+ "kicking sand",
195
+ "fertilizer application",
196
+ "strap rope skipping",
197
+ "play baseball",
198
+ "interview",
199
+ "sit on ground",
200
+ "be pulled forward",
201
+ "shave",
202
+ "teaching",
203
+ "play computer games",
204
+ "play football",
205
+ "teaching martial arts",
206
+ "play jumper",
207
+ "help to cut hair",
208
+ "table tennis",
209
+ "play bumper car",
210
+ "skateboard",
211
+ "bike ride",
212
+ "paddle",
213
+ "tire repair",
214
+ "long jump",
215
+ "swimming",
216
+ "shine shoes",
217
+ "broadcast news",
218
+ "scavenging leaves",
219
+ "sail",
220
+ "training dog",
221
+ "use of vacuum cleaner",
222
+ "wrist wrestling",
223
+ "blow ones hair",
224
+ "field shooting",
225
+ "ride on bicycle",
226
+ "rock climbing",
227
+ "play slide",
228
+ "high jump",
229
+ "drive car",
230
+ "brush wall",
231
+ "skateboarding",
232
+ "slippery pulley",
233
+ "playing harmonica",
234
+ "cook",
235
+ "play beach volleyball",
236
+ "explain ice hockey",
237
+ "pray",
238
+ "play basketball",
239
+ "tug of war",
240
+ "dismantling gifts",
241
+ "football match",
242
+ "laying tile",
243
+ "explain",
244
+ "play with smarthphone",
245
+ "hair care",
246
+ "spruce up",
247
+ "gift of gift",
248
+ "throwing darts",
249
+ "play tai chi",
250
+ "play parallel bars",
251
+ "turn magic cube",
252
+ "draw",
253
+ "watch tv",
254
+ "dog",
255
+ "dog and cat",
256
+ "competition archery",
257
+ "throwing javelin",
258
+ "bicycle race",
259
+ "throw hammer",
260
+ "throwing discuses",
261
+ "training",
262
+ "mountain bike ride",
263
+ "ice curling",
264
+ "exercise gymnastics",
265
+ "water polo",
266
+ "turn somersault",
267
+ "gymnastics",
268
+ "throw ball",
269
+ "wrestling",
270
+ "enhanced collaboration",
271
+ "black",
272
+ "yellow",
273
+ "dodgeball",
274
+ "eat ice cream",
275
+ "haystack",
276
+ "kindling wood",
277
+ "smoking",
278
+ "tree planting",
279
+ "curly",
280
+ "make skis",
281
+ "play violin",
282
+ "grooming",
283
+ "shoes polish",
284
+ "cut persons head",
285
+ "by cable car",
286
+ "wire walking",
287
+ "do yoga",
288
+ "masonry wall",
289
+ "clean dog",
290
+ "push car",
291
+ "rope skipping",
292
+ "leather shoes",
293
+ "measurement length",
294
+ "car repair tires",
295
+ "pruning trees",
296
+ "tread on stilts",
297
+ "paint chair",
298
+ "tilling",
299
+ "dance hip hop",
300
+ "drink beer",
301
+ "dive to feed fish",
302
+ "windsurfing",
303
+ "boxing practice",
304
+ "haircut",
305
+ "ride bicycle",
306
+ "do shape packing",
307
+ "play piano",
308
+ "play hockey",
309
+ "eat something",
310
+ "rubbing feet",
311
+ "sleep",
312
+ "play with phone",
313
+ "light roof",
314
+ "ride bike",
315
+ "wash hands",
316
+ "play guitar",
317
+ "shoe rope",
318
+ "throw spear",
319
+ "fight",
320
+ "play music",
321
+ "prepare for dive",
322
+ "singing",
323
+ "tread",
324
+ "face",
325
+ "hockey game",
326
+ "helmet",
327
+ "hat",
328
+ "play billiards",
329
+ "knit sweater",
330
+ "make salad",
331
+ "use stick",
332
+ "skiing leather ring",
333
+ "light cigarette",
334
+ "tree pruning",
335
+ "tire change",
336
+ "performing gymnastics",
337
+ "play roller skating",
338
+ "wheel change",
339
+ "dance tai chi sword",
340
+ "wrists",
341
+ "be manicure",
342
+ "make sandwich biscuits",
343
+ "reaction capacity",
344
+ "gray",
345
+ "blue",
346
+ "green",
347
+ "red",
348
+ "white",
349
+ "black and white",
350
+ "orange",
351
+ "pink",
352
+ "purple",
353
+ "brown",
354
+ "golden",
355
+ "dynamic bicycle",
356
+ "white glove",
357
+ "glove",
358
+ "rest",
359
+ "lying on ground",
360
+ "introduce people",
361
+ "motorcycle jump",
362
+ "jump up",
363
+ "take cell phone",
364
+ "play with mud",
365
+ "and then drums",
366
+ "audience left",
367
+ "audience came to court",
368
+ "raise hand to celebrate",
369
+ "cheer",
370
+ "throw snowball",
371
+ "to ground",
372
+ "video end",
373
+ "audience applauded",
374
+ "then shovel snow",
375
+ "jump into sand pit",
376
+ "talk to passer by",
377
+ "run up",
378
+ "serve",
379
+ "take ball",
380
+ "go on court",
381
+ "introduction of products",
382
+ "drink drink",
383
+ "clean horse",
384
+ "lens shaky",
385
+ "end of demonstration",
386
+ "wash hair",
387
+ "start",
388
+ "add ice",
389
+ "prepare for start",
390
+ "shedding rope",
391
+ "check rope",
392
+ "take skates",
393
+ "get ready",
394
+ "coach guidance",
395
+ "referee throws the ball",
396
+ "cat peppermint",
397
+ "prepare starting",
398
+ "shoulder shoulder",
399
+ "showcase wine",
400
+ "blower",
401
+ "blow up drum",
402
+ "squat",
403
+ "almost hit by car",
404
+ "production process",
405
+ "button button",
406
+ "be interviewed",
407
+ "go out",
408
+ "down",
409
+ "all down",
410
+ "christmas tree fell down",
411
+ "hole",
412
+ "diver",
413
+ "plain white cloth",
414
+ "national flag",
415
+ "hair drier",
416
+ "white woman",
417
+ "wall column",
418
+ "visual acuity chart",
419
+ "shovel",
420
+ "wall",
421
+ "sofa",
422
+ "living room",
423
+ "tree",
424
+ "grassland",
425
+ "iron block",
426
+ "house",
427
+ "automobile",
428
+ "mirror",
429
+ "ground",
430
+ "billboard",
431
+ "enclosure",
432
+ "television",
433
+ "window",
434
+ "blue plastic film",
435
+ "hair stylist",
436
+ "wooden doors",
437
+ "small house",
438
+ "table",
439
+ "shelf",
440
+ "coloured lights",
441
+ "small window",
442
+ "fountain",
443
+ "audience",
444
+ "glass",
445
+ "blue screen",
446
+ "spectator seats",
447
+ "guardrail net",
448
+ "screen",
449
+ "cabinet",
450
+ "kitchen",
451
+ "wood",
452
+ "door",
453
+ "vehicle",
454
+ "christmas tree",
455
+ "chair",
456
+ "yellow bag",
457
+ "glass cabinet",
458
+ "two pieces of exhibition board",
459
+ "fish",
460
+ "goods shelves",
461
+ "treadmill",
462
+ "window curtains",
463
+ "snow mountain",
464
+ "mountain",
465
+ "car",
466
+ "stand",
467
+ "practice basketball",
468
+ "experimentalize",
469
+ "guitar",
470
+ "table football",
471
+ "bread",
472
+ "rope",
473
+ "men in white",
474
+ "microphone",
475
+ "poker",
476
+ "computer",
477
+ "disk",
478
+ "judges",
479
+ "ball net",
480
+ "drum kit",
481
+ "cobra",
482
+ "ball table",
483
+ "stone",
484
+ "sand",
485
+ "shoal of fish",
486
+ "white coat man",
487
+ "pool",
488
+ "road",
489
+ "water",
490
+ "tennis table",
491
+ "railing",
492
+ "tea table",
493
+ "cat",
494
+ "flower receptacle",
495
+ "fire pile",
496
+ "men in blue",
497
+ "cake",
498
+ "bowling pin",
499
+ "floor",
500
+ "hillside",
501
+ "white man",
502
+ "ironing table",
503
+ "basketball box",
504
+ "man in blue",
505
+ "table tennis table",
506
+ "food",
507
+ "network",
508
+ "red clothes",
509
+ "cruise",
510
+ "light pole",
511
+ "sound",
512
+ "agitation machine",
513
+ "man in camouflage",
514
+ "kitchen sink",
515
+ "two cattles",
516
+ "court",
517
+ "football field",
518
+ "man in white",
519
+ "wine bottle",
520
+ "basket",
521
+ "piano",
522
+ "beer",
523
+ "timer",
524
+ "counter",
525
+ "wash basin",
526
+ "bottle",
527
+ "ball",
528
+ "wrist watch",
529
+ "trash",
530
+ "steel pipe",
531
+ "model",
532
+ "row of tires",
533
+ "bunker",
534
+ "switch",
535
+ "stool",
536
+ "swimming pool",
537
+ "bracelet",
538
+ "spoon",
539
+ "milk",
540
+ "knife",
541
+ "surround masses",
542
+ "auditorium",
543
+ "silverware cadets",
544
+ "piano frame",
545
+ "fence",
546
+ "man in a suit",
547
+ "table and chair",
548
+ "horse",
549
+ "guardrail",
550
+ "referee",
551
+ "glass table",
552
+ "sea",
553
+ "wine glass",
554
+ "material science",
555
+ "seasoning",
556
+ "card",
557
+ "ice cream",
558
+ "tool",
559
+ "bowl",
560
+ "down by sally gardens",
561
+ "spray painting",
562
+ "club signs",
563
+ "help man shave",
564
+ "relax",
565
+ "decompression",
566
+ "physical fitness",
567
+ "exercise muscles",
568
+ "relieve stress",
569
+ "laugh",
570
+ "put on shoes",
571
+ "lingual nail",
572
+ "cut roof tin",
573
+ "gymnastic mat",
574
+ "siberian husky",
575
+ "poodle",
576
+ "cooking noodles",
577
+ "make egg roll",
578
+ "collar exercises",
579
+ "transparent",
580
+ "much much safer",
581
+ "much higher",
582
+ "christmas",
583
+ "s",
584
+ "e",
585
+ "exercise bike",
586
+ "skate",
587
+ "lawn",
588
+ "cement floor",
589
+ "horizontal bar",
590
+ "surf board",
591
+ "circular site",
592
+ "woman in white",
593
+ "water basin",
594
+ "trampoline",
595
+ "rim",
596
+ "volleyball court",
597
+ "blue dress man",
598
+ "garden",
599
+ "carrot",
600
+ "pads",
601
+ "vacuum cleaner",
602
+ "cooking bench",
603
+ "notes",
604
+ "juicer",
605
+ "blanket",
606
+ "bathing pool",
607
+ "curling runway",
608
+ "wheel",
609
+ "bar counter",
610
+ "protective net",
611
+ "opponent",
612
+ "contestant",
613
+ "hopping viaduct",
614
+ "pool table",
615
+ "curly hair",
616
+ "pet dog",
617
+ "hairstylist",
618
+ "coach",
619
+ "nail polish",
620
+ "make up",
621
+ "take exercise",
622
+ "play darts",
623
+ "water spray",
624
+ "tell about",
625
+ "phone",
626
+ "gymnastics competition",
627
+ "show turns eye",
628
+ "guard net",
629
+ "ski",
630
+ "drawing board",
631
+ "welding",
632
+ "buoy",
633
+ "watch",
634
+ "hair hoop",
635
+ "headset",
636
+ "flying discses",
637
+ "gambling",
638
+ "explain games rule",
639
+ "high",
640
+ "security",
641
+ "danger",
642
+ "volleyball",
643
+ "long distance run",
644
+ "twenty one points",
645
+ "tennis sports",
646
+ "ice hockey movement",
647
+ "parallel bars movement",
648
+ "three step jump",
649
+ "ice hockey",
650
+ "705",
651
+ "mouthpiece",
652
+ "budweiser",
653
+ "wrench",
654
+ "ceiling",
655
+ "sky",
656
+ "parallel bars exercise",
657
+ "boxing match",
658
+ "wiping cupboard",
659
+ "seal carpets",
660
+ "poweriser",
661
+ "hair rope",
662
+ "wash socks",
663
+ "toilet paper",
664
+ "braided hair",
665
+ "pastry master",
666
+ "charlie adams",
667
+ "decorator",
668
+ "colleague",
669
+ "partner",
670
+ "master and servant",
671
+ "mother and daughter",
672
+ "teammate",
673
+ "whole family",
674
+ "family",
675
+ "spouse",
676
+ "smoke friend",
677
+ "doctor patient relationship",
678
+ "teaching relationship",
679
+ "father and son",
680
+ "father and daughter",
681
+ "lovers",
682
+ "classmate",
683
+ "dancing partner",
684
+ "video player",
685
+ "row of fences",
686
+ "lower",
687
+ "low grade",
688
+ "higher",
689
+ "much more dangerous",
690
+ "bit safe",
691
+ "protect head",
692
+ "commonly",
693
+ "winter",
694
+ "circular",
695
+ "cylinder",
696
+ "trapezoid",
697
+ "square",
698
+ "rectangle",
699
+ "t shirt",
700
+ "long",
701
+ "snow",
702
+ "roof",
703
+ "runway",
704
+ "introduction equipment",
705
+ "clear",
706
+ "preside over program",
707
+ "hand drums",
708
+ "fitness equipment",
709
+ "archery",
710
+ "relatives",
711
+ "in repair",
712
+ "practice ball",
713
+ "make biscuits",
714
+ "how to wear contact lenses",
715
+ "introduction of cutting tools",
716
+ "how to set up cars",
717
+ "billiard game",
718
+ "rules of playing cards",
719
+ "food program",
720
+ "yoga mat",
721
+ "coaster",
722
+ "board",
723
+ "paper",
724
+ "lake",
725
+ "stage",
726
+ "inverted reflection in water",
727
+ "rubber runway",
728
+ "hovercraft",
729
+ "necklace",
730
+ "labrador",
731
+ "short",
732
+ "blue jeans",
733
+ "jeans",
734
+ "jump",
735
+ "jumping project",
736
+ "gym shoes",
737
+ "boots",
738
+ "artistic gymnastics",
739
+ "night",
740
+ "bar",
741
+ "home",
742
+ "basketball court",
743
+ "gym",
744
+ "hockey field",
745
+ "suburb",
746
+ "barber shop",
747
+ "beach",
748
+ "natatorium",
749
+ "casino",
750
+ "in street",
751
+ "snow land",
752
+ "bedroom",
753
+ "grass",
754
+ "parking lot",
755
+ "toilet",
756
+ "studio",
757
+ "park",
758
+ "hall",
759
+ "dancing room",
760
+ "playground",
761
+ "street",
762
+ "hotel",
763
+ "tattoo shop",
764
+ "shower room",
765
+ "sandy beach",
766
+ "room",
767
+ "rooftop",
768
+ "cave",
769
+ "stadium",
770
+ "plain",
771
+ "desk",
772
+ "ski field",
773
+ "tennis court",
774
+ "baseball field",
775
+ "lakeside",
776
+ "laboratory",
777
+ "church",
778
+ "amusement park",
779
+ "racetrack",
780
+ "horse yard",
781
+ "training ground",
782
+ "supermarket",
783
+ "office",
784
+ "market",
785
+ "tennis room",
786
+ "bowling room",
787
+ "manicure shop",
788
+ "game place",
789
+ "seaside",
790
+ "aquatic",
791
+ "chess and card room",
792
+ "left",
793
+ "left hand",
794
+ "black man",
795
+ "stimulate",
796
+ "reduce drag",
797
+ "give yourself inertia",
798
+ "increase jump distance",
799
+ "poor balance",
800
+ "for beauty",
801
+ "avoid injury",
802
+ "for sake of beauty",
803
+ "beautiful",
804
+ "anti damage",
805
+ "avoid hurt somenon",
806
+ "beauty",
807
+ "keep health",
808
+ "entertainment",
809
+ "convenient",
810
+ "wonderful performance",
811
+ "prevent drowning",
812
+ "woman",
813
+ "cylindrical",
814
+ "triangle",
815
+ "ellipse",
816
+ "round",
817
+ "dragon boat",
818
+ "hard to catch fire",
819
+ "2 people",
820
+ "skiing air cushion",
821
+ "sedan",
822
+ "good",
823
+ "wooden house",
824
+ "scuba diving",
825
+ "sunglasses",
826
+ "drifting",
827
+ "braid of double twist",
828
+ "out of flatness",
829
+ "slipper",
830
+ "stripe",
831
+ "suit",
832
+ "lattice",
833
+ "cleanser",
834
+ "cutting machine",
835
+ "air conditioner",
836
+ "two little funny birds",
837
+ "sapling",
838
+ "blonde",
839
+ "spider man toy",
840
+ "vest",
841
+ "tango",
842
+ "villa",
843
+ "wooden boat",
844
+ "springboard",
845
+ "slide",
846
+ "cardboard",
847
+ "protective pad",
848
+ "tigers head",
849
+ "plastic bag",
850
+ "onion",
851
+ "introduction of bullfighting",
852
+ "painting",
853
+ "game",
854
+ "take step",
855
+ "do aerobics",
856
+ "learn diving",
857
+ "soup spoon",
858
+ "english",
859
+ "banana",
860
+ "sax",
861
+ "workbench",
862
+ "drifting air cushion",
863
+ "pedal",
864
+ "bridge frame",
865
+ "sponge pad",
866
+ "child seat",
867
+ "bicycle",
868
+ "earth",
869
+ "seaweed",
870
+ "sealing layer",
871
+ "marble",
872
+ "bed",
873
+ "lifting jack",
874
+ "brand",
875
+ "sailboat",
876
+ "ponytail",
877
+ "dress",
878
+ "take deep breath",
879
+ "pommeled horse",
880
+ "shoulder hair",
881
+ "butterfly",
882
+ "peaked cap",
883
+ "sweet canister",
884
+ "new type lawn mower",
885
+ "fixator",
886
+ "scientific research ship",
887
+ "sandals",
888
+ "leather boots",
889
+ "blue shorts",
890
+ "funny video",
891
+ "b",
892
+ "pvc material",
893
+ "roast fish",
894
+ "basketball match",
895
+ "sitting",
896
+ "summer",
897
+ "cheerleading",
898
+ "spider",
899
+ "evening",
900
+ "afternoon",
901
+ "axe",
902
+ "movement type",
903
+ "racing moto",
904
+ "remote control boat",
905
+ "2012",
906
+ "halloween",
907
+ "casinos",
908
+ "carpet",
909
+ "track",
910
+ "field",
911
+ "park path",
912
+ "bread machine",
913
+ "yard",
914
+ "workshop",
915
+ "meadow",
916
+ "circle",
917
+ "railway bridge",
918
+ "river",
919
+ "restaurant",
920
+ "doorway",
921
+ "opera",
922
+ "track and field ground",
923
+ "sports meeting",
924
+ "subway",
925
+ "bullring",
926
+ "head",
927
+ "cudgel court",
928
+ "bathroom",
929
+ "bicycle shop",
930
+ "guide room",
931
+ "prairie track",
932
+ "snowfield",
933
+ "camel",
934
+ "seabed",
935
+ "aged",
936
+ "tropic",
937
+ "japan",
938
+ "srb",
939
+ "left eye",
940
+ "right eye",
941
+ "thumb",
942
+ "ones right hand",
943
+ "right",
944
+ "right hand",
945
+ "ger",
946
+ "leather gloves",
947
+ "second dives",
948
+ "left foot",
949
+ "her father",
950
+ "india",
951
+ "silverware",
952
+ "red jersey",
953
+ "blonde man",
954
+ "ring finger",
955
+ "catch fish",
956
+ "dive",
957
+ "pregnant",
958
+ "to throw far away",
959
+ "motion",
960
+ "sparring",
961
+ "to throw shot",
962
+ "be happy with drum",
963
+ "happy",
964
+ "get rid of blues",
965
+ "in washing up",
966
+ "some water on hands",
967
+ "wear jump shoes",
968
+ "in fight",
969
+ "someones good at skipping rope",
970
+ "for entertainment",
971
+ "win",
972
+ "easy to shave",
973
+ "make darts",
974
+ "labor saving",
975
+ "darts are easy to targets",
976
+ "express happiness",
977
+ "score",
978
+ "win in gambling",
979
+ "be covered by people",
980
+ "blindfolded eyes",
981
+ "to challenge themselves",
982
+ "prevent skidding",
983
+ "express joy",
984
+ "speed up javelin",
985
+ "more beautiful",
986
+ "give discus inertia",
987
+ "to express courtesy",
988
+ "guide children",
989
+ "blower is too heavy",
990
+ "greeting",
991
+ "cold prevention",
992
+ "end",
993
+ "be more beautiful",
994
+ "decorating house",
995
+ "trees are not neat",
996
+ "protect",
997
+ "protect eye",
998
+ "hungry",
999
+ "avoid messing",
1000
+ "thanks to audience",
1001
+ "easy eat",
1002
+ "arm force",
1003
+ "take part",
1004
+ "do public welfare",
1005
+ "reduce friction",
1006
+ "increase difficulty",
1007
+ "keep healthy",
1008
+ "burning fire",
1009
+ "convenient weeding",
1010
+ "express victory",
1011
+ "to dive",
1012
+ "scoop water",
1013
+ "record results",
1014
+ "speed up",
1015
+ "jump far",
1016
+ "unsteadiness of gravity",
1017
+ "curettage",
1018
+ "protect waist",
1019
+ "eatting",
1020
+ "make car light",
1021
+ "make manicure easier",
1022
+ "squeezing apple",
1023
+ "test light bulb",
1024
+ "car dirty",
1025
+ "mouth leaking",
1026
+ "clothing leveling",
1027
+ "be attacked",
1028
+ "interest",
1029
+ "easy blow",
1030
+ "fixed thread",
1031
+ "farther of the jump",
1032
+ "angry",
1033
+ "have personality",
1034
+ "avoid freezing hands",
1035
+ "protect teeth",
1036
+ "pick up speed",
1037
+ "safety guarantee",
1038
+ "you can jump farther",
1039
+ "others car broke down",
1040
+ "because long jump",
1041
+ "to blow sax",
1042
+ "put on hat",
1043
+ "reduce center of gravity",
1044
+ "hamper ball",
1045
+ "decorate",
1046
+ "acne treatment",
1047
+ "encouragement",
1048
+ "balance",
1049
+ "challenging",
1050
+ "bullet dodging",
1051
+ "interesting",
1052
+ "cheerful mood",
1053
+ "bring eggs together",
1054
+ "imbalance of body",
1055
+ "satisfy greed",
1056
+ "thank",
1057
+ "put child down",
1058
+ "drink green liquid",
1059
+ "let people pass through",
1060
+ "pursuit of stimulation",
1061
+ "better growth",
1062
+ "excitement",
1063
+ "to win",
1064
+ "ball inertia",
1065
+ "halloween decoration",
1066
+ "active atmosphere",
1067
+ "keep clean",
1068
+ "protect their heads",
1069
+ "good growth of plants",
1070
+ "almost power",
1071
+ "maintain level",
1072
+ "dinner",
1073
+ "encourage each other",
1074
+ "increase speed of shot",
1075
+ "irritation",
1076
+ "tire broken",
1077
+ "work",
1078
+ "art of display",
1079
+ "healthy",
1080
+ "prevent cramps",
1081
+ "fear tree be frozen",
1082
+ "convenient engraving",
1083
+ "clean",
1084
+ "ranking",
1085
+ "teaching video",
1086
+ "dress up",
1087
+ "test",
1088
+ "record video",
1089
+ "video recording",
1090
+ "improve skills",
1091
+ "recording time",
1092
+ "stick wallpaper",
1093
+ "accident prevention",
1094
+ "clean and beautiful",
1095
+ "convenient imitation",
1096
+ "convenient viewing",
1097
+ "greeting new year",
1098
+ "beautify environment",
1099
+ "well done",
1100
+ "art",
1101
+ "keep weight",
1102
+ "prevent being injury",
1103
+ "to be beautiful",
1104
+ "sport project",
1105
+ "competition",
1106
+ "make cake tasty",
1107
+ "bowl is dirty",
1108
+ "for sunscreen",
1109
+ "for safety",
1110
+ "dirty",
1111
+ "filter out water",
1112
+ "grass is too high",
1113
+ "anger",
1114
+ "to express comfort",
1115
+ "game lost",
1116
+ "strengthen proficiency",
1117
+ "record performance",
1118
+ "fear of hindering people",
1119
+ "curling",
1120
+ "challenge stimulus",
1121
+ "tired out",
1122
+ "more practice",
1123
+ "inertia",
1124
+ "end performance",
1125
+ "brain is damaged",
1126
+ "guessing victory",
1127
+ "escape",
1128
+ "because of smoking",
1129
+ "because of tattoo pain",
1130
+ "large density",
1131
+ "strong body",
1132
+ "because its done",
1133
+ "experience",
1134
+ "goal",
1135
+ "celebrate victory",
1136
+ "express excitement",
1137
+ "because you want to dive",
1138
+ "fixed ceramic tile",
1139
+ "easy understand",
1140
+ "avoid enzyme change",
1141
+ "for eatting",
1142
+ "convenient for walking",
1143
+ "prevent fall",
1144
+ "accelerate",
1145
+ "air rotation",
1146
+ "back somersault",
1147
+ "take oil",
1148
+ "table collapsed",
1149
+ "assembled rear tire",
1150
+ "tie up hair",
1151
+ "open your hands",
1152
+ "shave sideburns",
1153
+ "upside up",
1154
+ "turn head",
1155
+ "step back",
1156
+ "chilli powder",
1157
+ "stride left foot",
1158
+ "straighten back",
1159
+ "cut off",
1160
+ "anjali mudra",
1161
+ "look at effect",
1162
+ "active wrist",
1163
+ "toys have been raised",
1164
+ "waving",
1165
+ "teaching by step",
1166
+ "pulp",
1167
+ "grasp rope",
1168
+ "be pulled down",
1169
+ "nearly fall",
1170
+ "hand in hand",
1171
+ "stand up",
1172
+ "wave",
1173
+ "pine",
1174
+ "return to place",
1175
+ "fell to ground",
1176
+ "wear sunglasses",
1177
+ "skiing down hill",
1178
+ "wash dishes",
1179
+ "and put it back again",
1180
+ "fall on air cushion",
1181
+ "lose ball",
1182
+ "close scissors",
1183
+ "changing right hand",
1184
+ "rotary handlebar",
1185
+ "turn on light",
1186
+ "put sweet potato in bowls",
1187
+ "electrified",
1188
+ "vomit",
1189
+ "fall",
1190
+ "help him cut his hair",
1191
+ "fall into water",
1192
+ "bend",
1193
+ "stretch leg",
1194
+ "take off gloves",
1195
+ "put into water tank",
1196
+ "start dancing",
1197
+ "well cooked",
1198
+ "unable to stand firmly",
1199
+ "slide down slope",
1200
+ "put on leg",
1201
+ "black pants swimmers",
1202
+ "go on running",
1203
+ "kicking doll",
1204
+ "be cuddle",
1205
+ "go out of room",
1206
+ "puff out smoke",
1207
+ "start of the game",
1208
+ "control by foot",
1209
+ "celebrate",
1210
+ "pick up",
1211
+ "stir",
1212
+ "tissue",
1213
+ "bartender",
1214
+ "automative lighting",
1215
+ "audiences stand",
1216
+ "star shaped toy",
1217
+ "water sled",
1218
+ "red cloth",
1219
+ "curtain",
1220
+ "safety net",
1221
+ "pumpkin shed",
1222
+ "oxygen bottle",
1223
+ "big bottle",
1224
+ "spider man",
1225
+ "desert",
1226
+ "personal information",
1227
+ "painted wall",
1228
+ "red curtain",
1229
+ "both hands",
1230
+ "lot of boxes",
1231
+ "steps",
1232
+ "bookcase",
1233
+ "oven",
1234
+ "shed",
1235
+ "telegraph pole",
1236
+ "ornament",
1237
+ "white walls",
1238
+ "performers",
1239
+ "dresser",
1240
+ "water tap",
1241
+ "magic cube",
1242
+ "pot",
1243
+ "toaster oven",
1244
+ "tennis",
1245
+ "bullfighting field",
1246
+ "bet",
1247
+ "grinder machine",
1248
+ "scoreboard",
1249
+ "machine",
1250
+ "pull rope",
1251
+ "launch",
1252
+ "boiler",
1253
+ "potted plant",
1254
+ "photo",
1255
+ "minions",
1256
+ "ring",
1257
+ "blue sneakers",
1258
+ "big tree",
1259
+ "refrigerator",
1260
+ "line",
1261
+ "yellow paint",
1262
+ "iron chain",
1263
+ "patch",
1264
+ "glasses",
1265
+ "dolly",
1266
+ "hu la hoop",
1267
+ "safety hat",
1268
+ "plastic flowers",
1269
+ "lamp",
1270
+ "curling brush",
1271
+ "bushes",
1272
+ "long hair man",
1273
+ "child",
1274
+ "saw",
1275
+ "plate",
1276
+ "yellow basin",
1277
+ "men in black",
1278
+ "street lamp",
1279
+ "spare tire",
1280
+ "tattoo artist",
1281
+ "dry powder plate",
1282
+ "black hair woman",
1283
+ "barbell",
1284
+ "earring",
1285
+ "parallel bar",
1286
+ "large building",
1287
+ "ceramic tile",
1288
+ "person wearing a hat",
1289
+ "pond",
1290
+ "row of clothes",
1291
+ "iron",
1292
+ "masonry",
1293
+ "ladder",
1294
+ "cameraman",
1295
+ "canvas",
1296
+ "shrimp meat",
1297
+ "hand washing box",
1298
+ "awning",
1299
+ "stairs",
1300
+ "american flag",
1301
+ "socket",
1302
+ "cosmetics",
1303
+ "clothes",
1304
+ "romaine lettuce",
1305
+ "make body pliable",
1306
+ "rabbit",
1307
+ "red baffle",
1308
+ "horse running yard",
1309
+ "personnel",
1310
+ "banana tree",
1311
+ "british flag",
1312
+ "very excited",
1313
+ "red ball",
1314
+ "shore",
1315
+ "release pressure",
1316
+ "purify air",
1317
+ "exercise balance",
1318
+ "9",
1319
+ "exercise",
1320
+ "make report",
1321
+ "yelling",
1322
+ "eradicator",
1323
+ "mat cloth",
1324
+ "chopping block",
1325
+ "stone and water grass",
1326
+ "seawater",
1327
+ "crew cut",
1328
+ "cold",
1329
+ "red and black",
1330
+ "wash milk",
1331
+ "height",
1332
+ "clockwise",
1333
+ "anti clockwise",
1334
+ "forward",
1335
+ "up and down",
1336
+ "front",
1337
+ "5000 meters",
1338
+ "oxygen mask",
1339
+ "blue shirt",
1340
+ "very good",
1341
+ "supply lemon juice",
1342
+ "clean and tidy",
1343
+ "fixed hairstyle",
1344
+ "straw",
1345
+ "front rollover",
1346
+ "cry sadly",
1347
+ "very angry",
1348
+ "smile",
1349
+ "more fair",
1350
+ "its pretty",
1351
+ "eager",
1352
+ "fat",
1353
+ "a",
1354
+ "w",
1355
+ "t",
1356
+ "c",
1357
+ "cucumber",
1358
+ "woodiness",
1359
+ "mustache",
1360
+ "chopped wood",
1361
+ "ball frame",
1362
+ "target",
1363
+ "gambling table",
1364
+ "bag",
1365
+ "cross bar",
1366
+ "equip them with modern machines",
1367
+ "rock",
1368
+ "craft",
1369
+ "wood pile",
1370
+ "protective effect",
1371
+ "do horizontal bar gymnastics",
1372
+ "do homework",
1373
+ "main committee",
1374
+ "origami",
1375
+ "asymmetrical bars",
1376
+ "bob",
1377
+ "shoulder length hair",
1378
+ "single cauda",
1379
+ "short hair",
1380
+ "lime",
1381
+ "electromagnetic furnace",
1382
+ "clerk",
1383
+ "athletes",
1384
+ "reporter",
1385
+ "p",
1386
+ "pumpkin",
1387
+ "matador",
1388
+ "barber",
1389
+ "cooker",
1390
+ "fitness coach",
1391
+ "decorating umbrella",
1392
+ "basin",
1393
+ "group of children",
1394
+ "twinkle",
1395
+ "gymnastic performance",
1396
+ "beautiful arched eyebrows",
1397
+ "hosting news",
1398
+ "variety of wine",
1399
+ "sandwich",
1400
+ "skateboard of water skiing",
1401
+ "sing",
1402
+ "hold girl",
1403
+ "exercise weight lifting",
1404
+ "mowing lawn",
1405
+ "drift",
1406
+ "shoeshine",
1407
+ "cross country race",
1408
+ "women in red clothes",
1409
+ "rag",
1410
+ "ride cross country motorcycle",
1411
+ "bullfight",
1412
+ "broadcast",
1413
+ "black hair girl",
1414
+ "1154",
1415
+ "female host",
1416
+ "how to cut potatoes",
1417
+ "very pleased",
1418
+ "ballet dancer",
1419
+ "long rod",
1420
+ "four thousand and six hundred",
1421
+ "first",
1422
+ "korea",
1423
+ "walk",
1424
+ "recreational machines",
1425
+ "29",
1426
+ "1951",
1427
+ "330",
1428
+ "1144",
1429
+ "knock toy",
1430
+ "spinning",
1431
+ "mans head",
1432
+ "cut tree",
1433
+ "standing",
1434
+ "party",
1435
+ "brush",
1436
+ "practice water sled",
1437
+ "package book",
1438
+ "ski slope",
1439
+ "teach hair",
1440
+ "camera",
1441
+ "apple juice",
1442
+ "short hair baby",
1443
+ "half squat",
1444
+ "hold right leg",
1445
+ "squatting",
1446
+ "lead singer",
1447
+ "doctor",
1448
+ "trainer",
1449
+ "safe of car",
1450
+ "life buoy",
1451
+ "sandbag",
1452
+ "woven goods",
1453
+ "pepper",
1454
+ "companion",
1455
+ "partnership",
1456
+ "stranger",
1457
+ "competitor",
1458
+ "shopkeepers and shopkeepers",
1459
+ "brother and sister",
1460
+ "shopkeeper and customer",
1461
+ "masses and journalists",
1462
+ "boss and the customer",
1463
+ "referee and player",
1464
+ "row of cars",
1465
+ "hemp rope",
1466
+ "forest",
1467
+ "green brush",
1468
+ "casement window",
1469
+ "black hat man",
1470
+ "poisoning",
1471
+ "much much higher",
1472
+ "much safer",
1473
+ "removal of bubbles",
1474
+ "fixed hair",
1475
+ "natural lashes",
1476
+ "control direction",
1477
+ "10",
1478
+ "floating ice",
1479
+ "colorful",
1480
+ "red and white",
1481
+ "silver",
1482
+ "ballet",
1483
+ "take off shoes",
1484
+ "lift her up",
1485
+ "shaving cutter head",
1486
+ "scissors",
1487
+ "carding",
1488
+ "take off long rope",
1489
+ "round to other side",
1490
+ "stop",
1491
+ "hand ring",
1492
+ "photo display",
1493
+ "pull dog down",
1494
+ "two circles of rotation",
1495
+ "rolling skin",
1496
+ "feed bread",
1497
+ "drumstick",
1498
+ "pocket knife",
1499
+ "take off your shirt",
1500
+ "appearance of name",
1501
+ "press ceramic tile",
1502
+ "flexibility",
1503
+ "team consciousness",
1504
+ "throw away tissue",
1505
+ "scarf",
1506
+ "basketball",
1507
+ "hairpin",
1508
+ "branches and leaves fell",
1509
+ "release white smoke",
1510
+ "rugby",
1511
+ "prayers",
1512
+ "make phone",
1513
+ "gymnastics suit",
1514
+ "right handed rod",
1515
+ "lift truck",
1516
+ "unload barbell",
1517
+ "feathered pat",
1518
+ "physical energy",
1519
+ "plug igniter",
1520
+ "pen",
1521
+ "straw hat",
1522
+ "training skills",
1523
+ "harmonica",
1524
+ "plastic track",
1525
+ "flat shovel",
1526
+ "enjoy",
1527
+ "life jacket",
1528
+ "pine soil",
1529
+ "movement of hand",
1530
+ "wristwatch",
1531
+ "hands on ability",
1532
+ "needle",
1533
+ "obstacle",
1534
+ "vaulting horse",
1535
+ "podium",
1536
+ "yellow ironing cloth",
1537
+ "achievement is effective",
1538
+ "coordination",
1539
+ "man in green",
1540
+ "avoid opponents ball",
1541
+ "wear ballet shoes",
1542
+ "clap hands",
1543
+ "hold together",
1544
+ "continue down",
1545
+ "embrace",
1546
+ "shoeshine surface",
1547
+ "black container",
1548
+ "put cup down",
1549
+ "vertical thumb",
1550
+ "dog catches the plate",
1551
+ "then training",
1552
+ "running",
1553
+ "clapping",
1554
+ "listen to coach",
1555
+ "twist and a smile",
1556
+ "pinch with perturbed",
1557
+ "fixed with adhesive paper",
1558
+ "boy comes down",
1559
+ "snow fall",
1560
+ "do bike ride",
1561
+ "mans hand",
1562
+ "ball goal net",
1563
+ "need some help to correct",
1564
+ "cup was removed",
1565
+ "ball is bounced back",
1566
+ "camel came over",
1567
+ "pulverized people lead",
1568
+ "fly back to roof",
1569
+ "stop timing",
1570
+ "blow dry",
1571
+ "play with toys",
1572
+ "change tire",
1573
+ "fixed tire",
1574
+ "remove rubber ring",
1575
+ "drink milk tea",
1576
+ "go to black dog",
1577
+ "bow",
1578
+ "shoelace",
1579
+ "powdery base",
1580
+ "cup fell into water",
1581
+ "blue team serve",
1582
+ "get home",
1583
+ "blood flow",
1584
+ "car scrubbing",
1585
+ "take out chips",
1586
+ "smooth and smooth",
1587
+ "treatment of chili",
1588
+ "start training",
1589
+ "discus collision",
1590
+ "perm hand",
1591
+ "tutoring cadets",
1592
+ "eat ball",
1593
+ "dog planer",
1594
+ "wine precipitation",
1595
+ "start skiing",
1596
+ "wash ones face",
1597
+ "clenching fist",
1598
+ "assemble cake",
1599
+ "clip eyelash",
1600
+ "push people",
1601
+ "brace with feet",
1602
+ "take off faucet",
1603
+ "grab ball",
1604
+ "lay by small tree",
1605
+ "stop roller skating",
1606
+ "do edge decoration",
1607
+ "nail clipper",
1608
+ "look at blade",
1609
+ "evade automatically",
1610
+ "snowball",
1611
+ "slide out of site",
1612
+ "punching",
1613
+ "open ones eyes",
1614
+ "go down table",
1615
+ "blonde womens car wash",
1616
+ "splash",
1617
+ "look computer desktop",
1618
+ "board stands up",
1619
+ "inserting needle",
1620
+ "keep shaving",
1621
+ "leave",
1622
+ "take out gun",
1623
+ "turn around",
1624
+ "be pulled by ship",
1625
+ "tapping bucket",
1626
+ "cilping some lemon slices",
1627
+ "bow to lens",
1628
+ "eat up",
1629
+ "tie shoelaces",
1630
+ "throw ball out",
1631
+ "shoes getting clean",
1632
+ "throw it to wall",
1633
+ "regulating nozzle",
1634
+ "start tug of war",
1635
+ "frying eggs",
1636
+ "adhesive tape",
1637
+ "blow up",
1638
+ "go back to walk",
1639
+ "shot switching",
1640
+ "continue to grind knife",
1641
+ "hit each other",
1642
+ "hand down",
1643
+ "grey team celebrates",
1644
+ "draw rubber rafts",
1645
+ "push left dolls",
1646
+ "dog ran away",
1647
+ "wait for",
1648
+ "speak",
1649
+ "block gliding",
1650
+ "walk away",
1651
+ "put slice of lemon",
1652
+ "look javelin distance",
1653
+ "cooling",
1654
+ "eliminated",
1655
+ "smoothly",
1656
+ "water is flooded",
1657
+ "get up to pay",
1658
+ "change pair of shoes",
1659
+ "go ashore",
1660
+ "flushing razor",
1661
+ "emotional excitement",
1662
+ "throw snow on edge",
1663
+ "pour out washing powder",
1664
+ "start bungee jumping",
1665
+ "takeoff",
1666
+ "packing",
1667
+ "got third",
1668
+ "darkened",
1669
+ "drink water",
1670
+ "caterpillar wallpaper",
1671
+ "lose match",
1672
+ "cow fell down",
1673
+ "inside car",
1674
+ "lid pressure",
1675
+ "throw barbell",
1676
+ "screwing nut",
1677
+ "fabric line",
1678
+ "hold child",
1679
+ "cook noodles",
1680
+ "continue to split wood",
1681
+ "clean horses hind leg",
1682
+ "very happy",
1683
+ "man jump down",
1684
+ "cutting wallpaper",
1685
+ "wear good left eye",
1686
+ "start jumping",
1687
+ "punches",
1688
+ "speech",
1689
+ "exhibition",
1690
+ "garden cart",
1691
+ "dismantling light bulb",
1692
+ "go to diver",
1693
+ "step by step",
1694
+ "sit down on your knees",
1695
+ "preparation materials",
1696
+ "get off car",
1697
+ "let curling round legs",
1698
+ "wear gloves",
1699
+ "fermation",
1700
+ "shaving cutter",
1701
+ "put down saw",
1702
+ "pony fell down",
1703
+ "raise ones hands",
1704
+ "turn two laps",
1705
+ "open ones mouth",
1706
+ "explanation usage",
1707
+ "pull hand brake",
1708
+ "floating on water",
1709
+ "open sound",
1710
+ "cut cake",
1711
+ "air pressure",
1712
+ "go to woman",
1713
+ "introduce",
1714
+ "prepare weapon",
1715
+ "sweep floor",
1716
+ "prepare bar",
1717
+ "dipping pigment",
1718
+ "count",
1719
+ "pull hands back",
1720
+ "tidy wire",
1721
+ "hold harmonica",
1722
+ "floating in water",
1723
+ "bet on",
1724
+ "introduction of pang ball",
1725
+ "display ornaments",
1726
+ "explanation skills",
1727
+ "stand straight",
1728
+ "erect canvas",
1729
+ "dipping shoe oil",
1730
+ "fooling around",
1731
+ "measuring distance",
1732
+ "display tools",
1733
+ "nail nail",
1734
+ "rotate",
1735
+ "pre match preparation",
1736
+ "wearing frog shoe",
1737
+ "pose",
1738
+ "smear shaving blister",
1739
+ "send message",
1740
+ "select curler",
1741
+ "stake",
1742
+ "prepare tools",
1743
+ "cement",
1744
+ "become biscuit",
1745
+ "display product",
1746
+ "display front door",
1747
+ "showcase",
1748
+ "water preparation",
1749
+ "open mouth and sing",
1750
+ "fall down",
1751
+ "go fishing",
1752
+ "gargle with fat man",
1753
+ "spray liquid",
1754
+ "on tree",
1755
+ "cobra attack",
1756
+ "feet shaking",
1757
+ "bubble",
1758
+ "use long stick",
1759
+ "with boat overhead",
1760
+ "camel stopped",
1761
+ "replacement",
1762
+ "prepare pigments",
1763
+ "raise your right hand",
1764
+ "blow out cigarette smoke",
1765
+ "hand clenched fist",
1766
+ "support body with two hands",
1767
+ "frictional runway",
1768
+ "scraping",
1769
+ "clap with your teammates",
1770
+ "talk to others",
1771
+ "dry it",
1772
+ "hand over nose",
1773
+ "turn to landscape",
1774
+ "horst hula hoop",
1775
+ "ball hit the knee",
1776
+ "steady and steady",
1777
+ "swing",
1778
+ "release pole",
1779
+ "press button",
1780
+ "wear glasses",
1781
+ "start pruning trees",
1782
+ "roll forward",
1783
+ "spray cleaning solution",
1784
+ "middle of tyres",
1785
+ "selfie",
1786
+ "tease hair",
1787
+ "talk to screen",
1788
+ "standing bow",
1789
+ "climb up",
1790
+ "stalemate",
1791
+ "take down darts",
1792
+ "high five",
1793
+ "tidy",
1794
+ "put down magic cube",
1795
+ "scratching nose",
1796
+ "dispel crowd",
1797
+ "toothpaste",
1798
+ "waving hand",
1799
+ "bright smile",
1800
+ "dogs before him",
1801
+ "fixed toy",
1802
+ "low down barycenter",
1803
+ "warm up exercise",
1804
+ "run forward",
1805
+ "group photo",
1806
+ "throw drumbeat",
1807
+ "land on ground",
1808
+ "lens conversion",
1809
+ "satisfactory smile",
1810
+ "erect violin",
1811
+ "handshake",
1812
+ "orange clothes male clenched fist",
1813
+ "open",
1814
+ "add two kites",
1815
+ "weigh it down",
1816
+ "kite flew high",
1817
+ "pull off tires",
1818
+ "black clothes people waved",
1819
+ "test ball",
1820
+ "rush to red cloth",
1821
+ "hit himself",
1822
+ "get blow out",
1823
+ "kick off cushion",
1824
+ "fish bite",
1825
+ "bite frisbee",
1826
+ "lift dog",
1827
+ "applause",
1828
+ "children shook hands",
1829
+ "handstand",
1830
+ "shake hand",
1831
+ "picture change",
1832
+ "try again",
1833
+ "clap hand to celebrate",
1834
+ "role pause",
1835
+ "do somersault",
1836
+ "pirouette",
1837
+ "raise hand",
1838
+ "carry out performance",
1839
+ "pendulum poss",
1840
+ "eat noodles",
1841
+ "dry powder",
1842
+ "drive to right",
1843
+ "pick up phone",
1844
+ "weeds are gone",
1845
+ "right man stands up",
1846
+ "stop recording",
1847
+ "amuse dog",
1848
+ "adults chipping potatoes",
1849
+ "loose soil",
1850
+ "trot",
1851
+ "ship opened",
1852
+ "put in plate",
1853
+ "jump into pool",
1854
+ "string string",
1855
+ "draw on pumpkin",
1856
+ "white male nodding",
1857
+ "height of grass",
1858
+ "pass ball",
1859
+ "stop rowing",
1860
+ "single hand support",
1861
+ "hold down",
1862
+ "go to machine",
1863
+ "set up shelf",
1864
+ "start weeding",
1865
+ "wear hoop",
1866
+ "tune stringed instrument",
1867
+ "tape",
1868
+ "be blocked",
1869
+ "assembly of steel",
1870
+ "relax with mobile phone",
1871
+ "horse is moving",
1872
+ "swivel",
1873
+ "big mother",
1874
+ "turn and half squat down",
1875
+ "piled to corner",
1876
+ "audience cheered",
1877
+ "others come on field",
1878
+ "lens deflection",
1879
+ "put ball",
1880
+ "in dialogue",
1881
+ "aim",
1882
+ "go through last",
1883
+ "fist",
1884
+ "putting camera",
1885
+ "wiping car with foam",
1886
+ "dance together",
1887
+ "grasp parallel bars",
1888
+ "squat down",
1889
+ "shut down machine",
1890
+ "climb stairs",
1891
+ "washing spoon",
1892
+ "dive preparation",
1893
+ "touch lens",
1894
+ "shake table",
1895
+ "be smashed in drum",
1896
+ "anchor jump rope",
1897
+ "hit masses",
1898
+ "see undersea biology",
1899
+ "fall into river",
1900
+ "cut sandwiches",
1901
+ "horse nodding",
1902
+ "put down flute",
1903
+ "wash face",
1904
+ "put on bread",
1905
+ "display shoes",
1906
+ "touch liquid",
1907
+ "immerse in it",
1908
+ "sit on sofa",
1909
+ "leave court",
1910
+ "to everyone ju gong",
1911
+ "display finger",
1912
+ "throw out again",
1913
+ "turn picture back",
1914
+ "middle finger",
1915
+ "pressing on player",
1916
+ "pick up racket",
1917
+ "get up slowly",
1918
+ "pick up cup",
1919
+ "lose to opponent",
1920
+ "backward dodge",
1921
+ "concealed cards",
1922
+ "get first",
1923
+ "roll in sky",
1924
+ "start car wash",
1925
+ "grab railing",
1926
+ "twist butt",
1927
+ "demo bicycles",
1928
+ "throw long pole",
1929
+ "lift barbell",
1930
+ "cross leg",
1931
+ "wear socks",
1932
+ "wipe hands",
1933
+ "site",
1934
+ "hold black clothes man",
1935
+ "hit ball",
1936
+ "kick ball out",
1937
+ "skater surfers",
1938
+ "continue to weave sweater",
1939
+ "put cards in box",
1940
+ "fiddle with hair",
1941
+ "go away",
1942
+ "refresh",
1943
+ "psychological adjustment",
1944
+ "join noodles",
1945
+ "fall off stage",
1946
+ "skidding",
1947
+ "stir by spatula",
1948
+ "someone is parachuting",
1949
+ "fall off air cushion",
1950
+ "finish up job",
1951
+ "chasing people",
1952
+ "spaghetti",
1953
+ "bump into pot",
1954
+ "continue knocking",
1955
+ "ask for note",
1956
+ "bow hairstyle",
1957
+ "two people dance",
1958
+ "cross hand",
1959
+ "ball landed",
1960
+ "dog chases plate",
1961
+ "dog came back with something",
1962
+ "be gone",
1963
+ "attack",
1964
+ "swing rod",
1965
+ "raise your left hand",
1966
+ "plaything",
1967
+ "touch ones head",
1968
+ "stand on bench",
1969
+ "rouge lips",
1970
+ "original takeoff",
1971
+ "rinse",
1972
+ "straighten rod",
1973
+ "ironing sleeves",
1974
+ "squating",
1975
+ "start riding",
1976
+ "open mouth ventilation",
1977
+ "support yourself",
1978
+ "dark bigger",
1979
+ "light",
1980
+ "mice",
1981
+ "smear oil",
1982
+ "lacquer",
1983
+ "coated hair cream",
1984
+ "throw away",
1985
+ "dog jumped up",
1986
+ "counterclockwise running",
1987
+ "back to lens",
1988
+ "push leaves off",
1989
+ "shallow sea",
1990
+ "long hair",
1991
+ "straight",
1992
+ "short sleeve",
1993
+ "double fold eyelids",
1994
+ "trousers",
1995
+ "ripe",
1996
+ "older",
1997
+ "long sleeves",
1998
+ "take off skirt",
1999
+ "white men fall in water",
2000
+ "marvellous",
2001
+ "leg clip",
2002
+ "tortoise",
2003
+ "vigny",
2004
+ "play drifting air cushion",
2005
+ "parade in desert",
2006
+ "wood brush",
2007
+ "pulley slippery",
2008
+ "musical instrument",
2009
+ "noodle",
2010
+ "skating canoe",
2011
+ "diving in sea",
2012
+ "street performance",
2013
+ "street dance",
2014
+ "tackle rubber rafts",
2015
+ "dunk",
2016
+ "on toilet",
2017
+ "prepare for skiing",
2018
+ "climb escalator",
2019
+ "polo",
2020
+ "uneven bars",
2021
+ "play lacrosse",
2022
+ "pruning shrubs",
2023
+ "clean up garbage",
2024
+ "sports competition",
2025
+ "sliding skateboard",
2026
+ "good afforested environment",
2027
+ "displacement pressure",
2028
+ "braid",
2029
+ "play toy",
2030
+ "chips",
2031
+ "discus",
2032
+ "air cushion",
2033
+ "operation guidance",
2034
+ "riding unicycle",
2035
+ "rt",
2036
+ "bids gun",
2037
+ "gatekeepers",
2038
+ "fork",
2039
+ "paring knife",
2040
+ "touch back of brain",
2041
+ "shave dog",
2042
+ "practice fencing",
2043
+ "fencing training",
2044
+ "press media",
2045
+ "fencing",
2046
+ "play bungee jumping",
2047
+ "need to connect wire",
2048
+ "hair of bun",
2049
+ "sports boat",
2050
+ "shoe polisher",
2051
+ "white person",
2052
+ "decorate some boxes",
2053
+ "pet beauty",
2054
+ "practice ballet",
2055
+ "apple",
2056
+ "many people are looking",
2057
+ "shower",
2058
+ "body coordination",
2059
+ "advertisement",
2060
+ "blue and green",
2061
+ "blue and red",
2062
+ "small stool",
2063
+ "motorcycle",
2064
+ "big",
2065
+ "shirt",
2066
+ "tourism advertisement",
2067
+ "kelp",
2068
+ "sea anemone",
2069
+ "autumn",
2070
+ "harmful",
2071
+ "clever",
2072
+ "very nice",
2073
+ "jump down",
2074
+ "narrow",
2075
+ "shadow",
2076
+ "much more difficult",
2077
+ "ten meters",
2078
+ "6 centimeters",
2079
+ "more proficient",
2080
+ "pretty good",
2081
+ "adept",
2082
+ "13",
2083
+ "two",
2084
+ "sixth",
2085
+ "9.75",
2086
+ "350",
2087
+ "walking",
2088
+ "standard",
2089
+ "superb",
2090
+ "torrential",
2091
+ "skilled",
2092
+ "wear exposure",
2093
+ "sing in earnest",
2094
+ "strong",
2095
+ "cool",
2096
+ "high and low",
2097
+ "lovely",
2098
+ "concise and clear",
2099
+ "they hurt",
2100
+ "skating rink",
2101
+ "2011",
2102
+ "usa",
2103
+ "tie",
2104
+ "small scale"
2105
+ ]
ChatUniVi/eval/questions/video_qa/activitynet_qa.json ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/video_qa/consistency_qa.json ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/video_qa/generic_qa.json ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/video_qa/msrvtt_a_list.json ADDED
@@ -0,0 +1,4175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "regard",
3
+ "show",
4
+ "explain",
5
+ "search",
6
+ "provide",
7
+ "computer",
8
+ "guy",
9
+ "something",
10
+ "someone",
11
+ "person",
12
+ "teach",
13
+ "exclaim",
14
+ "stand",
15
+ "learn",
16
+ "pose",
17
+ "move",
18
+ "pain",
19
+ "video",
20
+ "color",
21
+ "paint",
22
+ "animation",
23
+ "cartoon",
24
+ "talk",
25
+ "sit",
26
+ "wear",
27
+ "discus",
28
+ "man",
29
+ "room",
30
+ "health",
31
+ "suit",
32
+ "chair",
33
+ "fun",
34
+ "studio",
35
+ "write",
36
+ "teacher",
37
+ "chalkboard",
38
+ "problem",
39
+ "math",
40
+ "whiteboard",
41
+ "lesson",
42
+ "board",
43
+ "stage",
44
+ "girl",
45
+ "gameshow",
46
+ "judge",
47
+ "perform",
48
+ "female",
49
+ "laugh",
50
+ "entertain",
51
+ "dance",
52
+ "shout",
53
+ "friend",
54
+ "woman",
55
+ "demonstration",
56
+ "boy",
57
+ "song",
58
+ "male",
59
+ "sister",
60
+ "marble",
61
+ "play",
62
+ "put",
63
+ "mix",
64
+ "decorate",
65
+ "help",
66
+ "easter",
67
+ "egg",
68
+ "table",
69
+ "water",
70
+ "holder",
71
+ "polish",
72
+ "game",
73
+ "earth",
74
+ "minecraft",
75
+ "gamer",
76
+ "nether",
77
+ "break",
78
+ "mine",
79
+ "hammer",
80
+ "commentate",
81
+ "peson",
82
+ "rap",
83
+ "picture",
84
+ "voiceover",
85
+ "flash",
86
+ "rapper",
87
+ "two",
88
+ "change",
89
+ "throw",
90
+ "system",
91
+ "wall",
92
+ "office",
93
+ "camera",
94
+ "create",
95
+ "prepare",
96
+ "construct",
97
+ "craft",
98
+ "look",
99
+ "place",
100
+ "wrap",
101
+ "art",
102
+ "project",
103
+ "clay",
104
+ "leaf",
105
+ "dough",
106
+ "cake",
107
+ "player",
108
+ "baseball",
109
+ "ball",
110
+ "announcer",
111
+ "hit",
112
+ "call",
113
+ "team",
114
+ "outfielder",
115
+ "fashion",
116
+ "walk",
117
+ "fasion",
118
+ "ailse",
119
+ "runway",
120
+ "catwalk",
121
+ "clothing",
122
+ "display",
123
+ "pat",
124
+ "use",
125
+ "make",
126
+ "foundation",
127
+ "lady",
128
+ "face",
129
+ "clean",
130
+ "bath",
131
+ "tub",
132
+ "toy",
133
+ "brush",
134
+ "cat",
135
+ "orange",
136
+ "scrubber",
137
+ "child",
138
+ "relax",
139
+ "swim",
140
+ "lake",
141
+ "field",
142
+ "dres",
143
+ "beach",
144
+ "gras",
145
+ "car",
146
+ "vehicle",
147
+ "introduce",
148
+ "drive",
149
+ "describe",
150
+ "review",
151
+ "movie",
152
+ "load",
153
+ "speak",
154
+ "watch",
155
+ "begin",
156
+ "tap",
157
+ "space",
158
+ "bench",
159
+ "glimpse",
160
+ "screen",
161
+ "globe",
162
+ "planet",
163
+ "world",
164
+ "explore",
165
+ "backstreet",
166
+ "restaurant",
167
+ "divider",
168
+ "asium",
169
+ "china",
170
+ "city",
171
+ "band",
172
+ "road",
173
+ "singer",
174
+ "pick",
175
+ "phone",
176
+ "telephone",
177
+ "taunt",
178
+ "squidward",
179
+ "spongebob",
180
+ "character",
181
+ "scene",
182
+ "half",
183
+ "group",
184
+ "instructor",
185
+ "floor",
186
+ "instruction",
187
+ "ballroom",
188
+ "clas",
189
+ "jog",
190
+ "tell",
191
+ "exercise",
192
+ "three",
193
+ "circle",
194
+ "mother",
195
+ "mom",
196
+ "family",
197
+ "jogging",
198
+ "skill",
199
+ "hardware",
200
+ "piece",
201
+ "detail",
202
+ "mechanic",
203
+ "item",
204
+ "demonstrate",
205
+ "work",
206
+ "repair",
207
+ "side",
208
+ "way",
209
+ "front",
210
+ "body",
211
+ "coach",
212
+ "athlete",
213
+ "angle",
214
+ "activity",
215
+ "present",
216
+ "include",
217
+ "tos",
218
+ "baby",
219
+ "hold",
220
+ "transition",
221
+ "youtuber",
222
+ "segment",
223
+ "individual",
224
+ "news",
225
+ "doll",
226
+ "subject",
227
+ "selfie",
228
+ "leg",
229
+ "shake",
230
+ "spread",
231
+ "blue",
232
+ "lighting",
233
+ "beam",
234
+ "warcraft",
235
+ "garden",
236
+ "house",
237
+ "island",
238
+ "roof",
239
+ "record",
240
+ "building",
241
+ "football",
242
+ "glas",
243
+ "spin",
244
+ "basket",
245
+ "music",
246
+ "program",
247
+ "basketball",
248
+ "sport",
249
+ "food",
250
+ "kitchenthere",
251
+ "liquid",
252
+ "fry",
253
+ "chef",
254
+ "crab",
255
+ "kitchen",
256
+ "boil",
257
+ "melt",
258
+ "stir",
259
+ "model",
260
+ "diagram",
261
+ "draw",
262
+ "party",
263
+ "bedroom",
264
+ "eye",
265
+ "bos",
266
+ "bigg",
267
+ "advertisement",
268
+ "hug",
269
+ "blink",
270
+ "google",
271
+ "narrator",
272
+ "classy",
273
+ "driving",
274
+ "lean",
275
+ "newsreporter",
276
+ "cameraman",
277
+ "photographer",
278
+ "shoot",
279
+ "photography",
280
+ "burn",
281
+ "alternate",
282
+ "fire",
283
+ "pink",
284
+ "hang",
285
+ "blow",
286
+ "visit",
287
+ "handbag",
288
+ "horn",
289
+ "shopping",
290
+ "market",
291
+ "bed",
292
+ "telecast",
293
+ "conversation",
294
+ "wife",
295
+ "lay",
296
+ "lie",
297
+ "scold",
298
+ "shirtles",
299
+ "lounge",
300
+ "saurkraut",
301
+ "sauerkraut",
302
+ "dish",
303
+ "plate",
304
+ "eat",
305
+ "serve",
306
+ "stroller",
307
+ "fold",
308
+ "push",
309
+ "sidewalk",
310
+ "demo",
311
+ "trolley",
312
+ "boner",
313
+ "narrate",
314
+ "argue",
315
+ "startle",
316
+ "princes",
317
+ "voice",
318
+ "leah",
319
+ "confirm",
320
+ "animalist",
321
+ "mirror",
322
+ "test",
323
+ "experience",
324
+ "drag",
325
+ "embrace",
326
+ "lion",
327
+ "react",
328
+ "enjoy",
329
+ "fly",
330
+ "nyancat",
331
+ "rainbow",
332
+ "machine",
333
+ "robot",
334
+ "issue",
335
+ "equipment",
336
+ "astronaut",
337
+ "try",
338
+ "attempt",
339
+ "intercept",
340
+ "pilot",
341
+ "observe",
342
+ "negotiate",
343
+ "operate",
344
+ "ask",
345
+ "landing",
346
+ "eachother",
347
+ "matthew",
348
+ "procedure",
349
+ "spaceship",
350
+ "cook",
351
+ "vest",
352
+ "stove",
353
+ "distres",
354
+ "ground",
355
+ "emergency",
356
+ "shoplift",
357
+ "mob",
358
+ "crowd",
359
+ "panic",
360
+ "wolf",
361
+ "scream",
362
+ "bear",
363
+ "interact",
364
+ "joke",
365
+ "animal",
366
+ "monkey",
367
+ "shirt",
368
+ "sign",
369
+ "bird",
370
+ "hand",
371
+ "carry",
372
+ "rest",
373
+ "meow",
374
+ "lift",
375
+ "parrotlove",
376
+ "parrot",
377
+ "top",
378
+ "film",
379
+ "cage",
380
+ "rescue",
381
+ "introduction",
382
+ "extinguisher",
383
+ "flame",
384
+ "float",
385
+ "aquarium",
386
+ "tank",
387
+ "gold",
388
+ "plant",
389
+ "fish",
390
+ "merchandise",
391
+ "purse",
392
+ "wallet",
393
+ "merchandising",
394
+ "stephen",
395
+ "london",
396
+ "reminisce",
397
+ "advertise",
398
+ "product",
399
+ "sale",
400
+ "desk",
401
+ "country",
402
+ "violin",
403
+ "childhood",
404
+ "soccer",
405
+ "involve",
406
+ "drift",
407
+ "preform",
408
+ "applause",
409
+ "language",
410
+ "star",
411
+ "comment",
412
+ "paper",
413
+ "pencil",
414
+ "drawl",
415
+ "lap",
416
+ "mouse",
417
+ "rugby",
418
+ "rant",
419
+ "contract",
420
+ "quarterback",
421
+ "webcamera",
422
+ "professor",
423
+ "college",
424
+ "cloth",
425
+ "microphone",
426
+ "balance",
427
+ "bounce",
428
+ "gym",
429
+ "dvd",
430
+ "leaflet",
431
+ "kid",
432
+ "pamphlet",
433
+ "event",
434
+ "sync",
435
+ "night",
436
+ "carriage",
437
+ "adjust",
438
+ "carrier",
439
+ "act",
440
+ "audience",
441
+ "concert",
442
+ "sin",
443
+ "performance",
444
+ "rock",
445
+ "webcam",
446
+ "trailer",
447
+ "browse",
448
+ "download",
449
+ "youtube",
450
+ "internet",
451
+ "page",
452
+ "mp3",
453
+ "war",
454
+ "guitar",
455
+ "tie",
456
+ "cheer",
457
+ "coil",
458
+ "loop",
459
+ "fishing",
460
+ "wire",
461
+ "turkey",
462
+ "drink",
463
+ "grill",
464
+ "meat",
465
+ "cooking",
466
+ "sizzle",
467
+ "tawa",
468
+ "pot",
469
+ "rice",
470
+ "sequence",
471
+ "stone",
472
+ "answer",
473
+ "incident",
474
+ "cam",
475
+ "store",
476
+ "supermarket",
477
+ "set",
478
+ "sail",
479
+ "cruise",
480
+ "vacation",
481
+ "sea",
482
+ "boat",
483
+ "ship",
484
+ "sand",
485
+ "ocean",
486
+ "landscape",
487
+ "mountain",
488
+ "dog",
489
+ "deputy",
490
+ "community",
491
+ "polouse",
492
+ "contestant",
493
+ "idol",
494
+ "panel",
495
+ "performer",
496
+ "reality",
497
+ "advice",
498
+ "crossbow",
499
+ "bow",
500
+ "arrow",
501
+ "practice",
502
+ "patrol",
503
+ "report",
504
+ "rail",
505
+ "mention",
506
+ "read",
507
+ "swat",
508
+ "newscaster",
509
+ "security",
510
+ "protection",
511
+ "crimea",
512
+ "guard",
513
+ "area",
514
+ "polymer",
515
+ "knife",
516
+ "bit",
517
+ "hobby",
518
+ "point",
519
+ "touch",
520
+ "design",
521
+ "artist",
522
+ "shape",
523
+ "poke",
524
+ "matt",
525
+ "briefly",
526
+ "damon",
527
+ "keyboard",
528
+ "animator",
529
+ "history",
530
+ "type",
531
+ "clipping",
532
+ "celebrity",
533
+ "birthday",
534
+ "smile",
535
+ "thor",
536
+ "shooting",
537
+ "rain",
538
+ "outdoor",
539
+ "pull",
540
+ "lego",
541
+ "pajama",
542
+ "clip",
543
+ "amna",
544
+ "interview",
545
+ "conduct",
546
+ "feature",
547
+ "choice",
548
+ "award",
549
+ "function",
550
+ "announce",
551
+ "seat",
552
+ "roadway",
553
+ "travel",
554
+ "window",
555
+ "sleep",
556
+ "whistle",
557
+ "doghouse",
558
+ "spawn",
559
+ "setting",
560
+ "random",
561
+ "fence",
562
+ "skating",
563
+ "teenager",
564
+ "skateboard",
565
+ "skate",
566
+ "text",
567
+ "spiral",
568
+ "shoe",
569
+ "turn",
570
+ "rotate",
571
+ "dna",
572
+ "information",
573
+ "strand",
574
+ "junk",
575
+ "helix",
576
+ "explanation",
577
+ "suv",
578
+ "fur",
579
+ "horse",
580
+ "shanium",
581
+ "head",
582
+ "rush",
583
+ "town",
584
+ "disney",
585
+ "four",
586
+ "barbie",
587
+ "dancing",
588
+ "diagnose",
589
+ "share",
590
+ "industry",
591
+ "air",
592
+ "racer",
593
+ "monitor",
594
+ "race",
595
+ "hood",
596
+ "patrick",
597
+ "sponge",
598
+ "snail",
599
+ "driveway",
600
+ "street",
601
+ "hoop",
602
+ "practise",
603
+ "sparrow",
604
+ "box",
605
+ "contraption",
606
+ "chirp",
607
+ "scratch",
608
+ "climb",
609
+ "peck",
610
+ "plot",
611
+ "mystery",
612
+ "detective",
613
+ "investigate",
614
+ "doorway",
615
+ "line",
616
+ "giggle",
617
+ "culture",
618
+ "cover",
619
+ "send",
620
+ "knock",
621
+ "broadcast",
622
+ "neck",
623
+ "hide",
624
+ "father",
625
+ "cliff",
626
+ "stewie",
627
+ "griffen",
628
+ "feel",
629
+ "stay",
630
+ "kis",
631
+ "breast",
632
+ "chest",
633
+ "porch",
634
+ "door",
635
+ "walkway",
636
+ "factory",
637
+ "development",
638
+ "span",
639
+ "logo",
640
+ "vision",
641
+ "ryanvision",
642
+ "motion",
643
+ "newsanchor",
644
+ "celebrate",
645
+ "commentator",
646
+ "steer",
647
+ "speed",
648
+ "driver",
649
+ "traffic",
650
+ "commentary",
651
+ "thing",
652
+ "extension",
653
+ "cellphone",
654
+ "mobile",
655
+ "chat",
656
+ "message",
657
+ "creature",
658
+ "whale",
659
+ "giant",
660
+ "surface",
661
+ "jump",
662
+ "approach",
663
+ "emerge",
664
+ "breach",
665
+ "dive",
666
+ "track",
667
+ "shot",
668
+ "starting",
669
+ "start",
670
+ "runner",
671
+ "compare",
672
+ "busines",
673
+ "campu",
674
+ "fist",
675
+ "school",
676
+ "book",
677
+ "reading",
678
+ "classroom",
679
+ "amazon",
680
+ "atmosphere",
681
+ "cave",
682
+ "farm",
683
+ "ice",
684
+ "frost",
685
+ "wed",
686
+ "cream",
687
+ "murray",
688
+ "bill",
689
+ "substance",
690
+ "park",
691
+ "salesman",
692
+ "aman",
693
+ "sell",
694
+ "lenin",
695
+ "education",
696
+ "bowl",
697
+ "recipe",
698
+ "pmy",
699
+ "time",
700
+ "nobody",
701
+ "pretty",
702
+ "hair",
703
+ "blonde",
704
+ "stuffed",
705
+ "femal",
706
+ "figure",
707
+ "goat",
708
+ "stream",
709
+ "mod",
710
+ "spa",
711
+ "rub",
712
+ "massage",
713
+ "wash",
714
+ "milk",
715
+ "economy",
716
+ "leader",
717
+ "money",
718
+ "raise",
719
+ "crawl",
720
+ "slide",
721
+ "fall",
722
+ "stair",
723
+ "cowboy",
724
+ "bacon",
725
+ "barbecue",
726
+ "flower",
727
+ "cheif",
728
+ "meal",
729
+ "kithen",
730
+ "treat",
731
+ "preview",
732
+ "dubstep",
733
+ "wave",
734
+ "view",
735
+ "background",
736
+ "batting",
737
+ "batsman",
738
+ "tsunami",
739
+ "bat",
740
+ "photo",
741
+ "one",
742
+ "pirate",
743
+ "sword",
744
+ "transportation",
745
+ "river",
746
+ "waterfall",
747
+ "gush",
748
+ "wrestle",
749
+ "wrestling",
750
+ "match",
751
+ "competition",
752
+ "fight",
753
+ "microwave",
754
+ "oven",
755
+ "inhome",
756
+ "heat",
757
+ "wooden",
758
+ "mud",
759
+ "exit",
760
+ "compete",
761
+ "moody",
762
+ "tom",
763
+ "pokeman",
764
+ "adventure",
765
+ "togepus",
766
+ "pokemon",
767
+ "hat",
768
+ "television",
769
+ "ash",
770
+ "debate",
771
+ "podium",
772
+ "cnn",
773
+ "speaker",
774
+ "speechles",
775
+ "cruz",
776
+ "recap",
777
+ "somethimg",
778
+ "letterman",
779
+ "leterman",
780
+ "actor",
781
+ "host",
782
+ "couch",
783
+ "doze",
784
+ "airplane",
785
+ "plane",
786
+ "gray",
787
+ "beauty",
788
+ "love",
789
+ "volleyball",
790
+ "interest",
791
+ "cry",
792
+ "haras",
793
+ "crow",
794
+ "attack",
795
+ "knight",
796
+ "sky",
797
+ "catch",
798
+ "maiden",
799
+ "soldier",
800
+ "warrior",
801
+ "oil",
802
+ "origami",
803
+ "cheese",
804
+ "silver",
805
+ "home",
806
+ "software",
807
+ "application",
808
+ "discussion",
809
+ "ring",
810
+ "sink",
811
+ "nurse",
812
+ "wipe",
813
+ "dip",
814
+ "deal",
815
+ "target",
816
+ "britney",
817
+ "conference",
818
+ "metal",
819
+ "medal",
820
+ "chi",
821
+ "die",
822
+ "daughter",
823
+ "rinse",
824
+ "build",
825
+ "ride",
826
+ "gondola",
827
+ "snow",
828
+ "hill",
829
+ "rope",
830
+ "lft",
831
+ "monorail",
832
+ "chairlift",
833
+ "peeple",
834
+ "member",
835
+ "harry",
836
+ "flight",
837
+ "moon",
838
+ "mission",
839
+ "parody",
840
+ "gangnam",
841
+ "gun",
842
+ "cortona",
843
+ "outline",
844
+ "pack",
845
+ "bod",
846
+ "charachter",
847
+ "heckle",
848
+ "tenni",
849
+ "pong",
850
+ "end",
851
+ "cardio",
852
+ "attend",
853
+ "rear",
854
+ "win",
855
+ "jockey",
856
+ "macdonald",
857
+ "wish",
858
+ "greet",
859
+ "meet",
860
+ "shuttle",
861
+ "iss",
862
+ "science",
863
+ "dusk",
864
+ "couple",
865
+ "doctor",
866
+ "tardi",
867
+ "cape",
868
+ "salad",
869
+ "chop",
870
+ "cut",
871
+ "gear",
872
+ "machinery",
873
+ "court",
874
+ "pace",
875
+ "cort",
876
+ "cool",
877
+ "bald",
878
+ "trick",
879
+ "spec",
880
+ "communist",
881
+ "museum",
882
+ "hangar",
883
+ "laptop",
884
+ "lab",
885
+ "cup",
886
+ "spuid",
887
+ "octopu",
888
+ "bottle",
889
+ "jellyfish",
890
+ "squid",
891
+ "dirge",
892
+ "lessen",
893
+ "anthem",
894
+ "shift",
895
+ "superhero",
896
+ "foam",
897
+ "fit",
898
+ "instal",
899
+ "fix",
900
+ "mat",
901
+ "cusion",
902
+ "construction",
903
+ "cushion",
904
+ "material",
905
+ "celeberatey",
906
+ "trophy",
907
+ "appreciate",
908
+ "cute",
909
+ "pas",
910
+ "lead",
911
+ "gameplay",
912
+ "user",
913
+ "choose",
914
+ "enter",
915
+ "name",
916
+ "cop",
917
+ "brittany",
918
+ "life",
919
+ "peek",
920
+ "dark",
921
+ "strum",
922
+ "guitarist",
923
+ "gunfire",
924
+ "syrium",
925
+ "firefight",
926
+ "helicopter",
927
+ "isi",
928
+ "army",
929
+ "smoke",
930
+ "terror",
931
+ "bombing",
932
+ "reporter",
933
+ "bomb",
934
+ "engine",
935
+ "garry",
936
+ "lightyear",
937
+ "receipe",
938
+ "flmy",
939
+ "tutorial",
940
+ "smell",
941
+ "taste",
942
+ "eubank",
943
+ "fighter",
944
+ "recall",
945
+ "spinach",
946
+ "lasagna",
947
+ "object",
948
+ "ply",
949
+ "skin",
950
+ "juice",
951
+ "tiki",
952
+ "ferrai",
953
+ "formula",
954
+ "racing",
955
+ "comantery",
956
+ "boyfriend",
957
+ "threee",
958
+ "talent",
959
+ "hear",
960
+ "confront",
961
+ "rubber",
962
+ "layout",
963
+ "instruct",
964
+ "pop",
965
+ "dinner",
966
+ "date",
967
+ "clock",
968
+ "tick",
969
+ "round",
970
+ "earthquake",
971
+ "scientist",
972
+ "talkshow",
973
+ "boob",
974
+ "drop",
975
+ "dirt",
976
+ "mes",
977
+ "instrument",
978
+ "service",
979
+ "foot",
980
+ "opening",
981
+ "article",
982
+ "guest",
983
+ "homer",
984
+ "light",
985
+ "technology",
986
+ "partner",
987
+ "ches",
988
+ "consume",
989
+ "bankruptcy",
990
+ "nick",
991
+ "treehouse",
992
+ "bike",
993
+ "anime",
994
+ "sponngebob",
995
+ "annoy",
996
+ "tease",
997
+ "taxi",
998
+ "method",
999
+ "gadget",
1000
+ "gentleman",
1001
+ "customize",
1002
+ "proces",
1003
+ "terrify",
1004
+ "creep",
1005
+ "reach",
1006
+ "claw",
1007
+ "ceiling",
1008
+ "flow",
1009
+ "scroll",
1010
+ "invade",
1011
+ "newspaper",
1012
+ "writer",
1013
+ "document",
1014
+ "gambling",
1015
+ "gamble",
1016
+ "punch",
1017
+ "alert",
1018
+ "letter",
1019
+ "fiskal",
1020
+ "magentum",
1021
+ "block",
1022
+ "pig",
1023
+ "concern",
1024
+ "hilary",
1025
+ "hillary",
1026
+ "clinton",
1027
+ "confederate",
1028
+ "speech",
1029
+ "politician",
1030
+ "struggle",
1031
+ "standing",
1032
+ "vocalist",
1033
+ "playground",
1034
+ "stadium",
1035
+ "scrum",
1036
+ "result",
1037
+ "handle",
1038
+ "goal",
1039
+ "lasso",
1040
+ "mansion",
1041
+ "benson",
1042
+ "operation",
1043
+ "kick",
1044
+ "vlog",
1045
+ "lecture",
1046
+ "lecturer",
1047
+ "biology",
1048
+ "deliver",
1049
+ "meeting",
1050
+ "newsman",
1051
+ "hospital",
1052
+ "package",
1053
+ "patient",
1054
+ "recovery",
1055
+ "recipiesaresimple",
1056
+ "gravy",
1057
+ "soup",
1058
+ "appeal",
1059
+ "scoop",
1060
+ "fill",
1061
+ "conclude",
1062
+ "desert",
1063
+ "smash",
1064
+ "demolish",
1065
+ "truck",
1066
+ "crash",
1067
+ "coat",
1068
+ "homeles",
1069
+ "happiness",
1070
+ "luggage",
1071
+ "think",
1072
+ "part",
1073
+ "tool",
1074
+ "pool",
1075
+ "july",
1076
+ "base",
1077
+ "run",
1078
+ "kneel",
1079
+ "score",
1080
+ "mis",
1081
+ "diamond",
1082
+ "bag",
1083
+ "root",
1084
+ "magnify",
1085
+ "jewel",
1086
+ "heroin",
1087
+ "longingly",
1088
+ "hero",
1089
+ "chapter",
1090
+ "peer",
1091
+ "tshirt",
1092
+ "paperwork",
1093
+ "booty",
1094
+ "comb",
1095
+ "hose",
1096
+ "educate",
1097
+ "pitcher",
1098
+ "gravity",
1099
+ "experiment",
1100
+ "bucket",
1101
+ "freezing",
1102
+ "tray",
1103
+ "sweet",
1104
+ "storage",
1105
+ "pureed",
1106
+ "container",
1107
+ "potaato",
1108
+ "freeze",
1109
+ "brother",
1110
+ "coddle",
1111
+ "pet",
1112
+ "ldy",
1113
+ "yard",
1114
+ "calm",
1115
+ "fortres",
1116
+ "till",
1117
+ "thief",
1118
+ "viewer",
1119
+ "feedback",
1120
+ "contestent",
1121
+ "competitor",
1122
+ "hiliary",
1123
+ "cspan",
1124
+ "hatdoll",
1125
+ "lavigne",
1126
+ "advertiesment",
1127
+ "glouse",
1128
+ "crown",
1129
+ "government",
1130
+ "peformance",
1131
+ "photograph",
1132
+ "towel",
1133
+ "buffalo",
1134
+ "universe",
1135
+ "lense",
1136
+ "cell",
1137
+ "fetu",
1138
+ "nyc",
1139
+ "ramp",
1140
+ "goldfish",
1141
+ "destroy",
1142
+ "videogame",
1143
+ "dig",
1144
+ "hell",
1145
+ "bake",
1146
+ "vinegar",
1147
+ "ambulance",
1148
+ "highway",
1149
+ "beat",
1150
+ "kill",
1151
+ "semolina",
1152
+ "thee",
1153
+ "fart",
1154
+ "phrase",
1155
+ "challenge",
1156
+ "herself",
1157
+ "profanity",
1158
+ "obama",
1159
+ "president",
1160
+ "steve",
1161
+ "depict",
1162
+ "researcher",
1163
+ "horror",
1164
+ "barber",
1165
+ "converse",
1166
+ "sweeny",
1167
+ "chemistry",
1168
+ "state",
1169
+ "reader",
1170
+ "medicine",
1171
+ "lamma",
1172
+ "gress",
1173
+ "alpaca",
1174
+ "enclosure",
1175
+ "pin",
1176
+ "lama",
1177
+ "pen",
1178
+ "pram",
1179
+ "device",
1180
+ "smartphone",
1181
+ "app",
1182
+ "troop",
1183
+ "goop",
1184
+ "offer",
1185
+ "channel",
1186
+ "makeup",
1187
+ "montage",
1188
+ "pole",
1189
+ "slideshow",
1190
+ "designer",
1191
+ "candy",
1192
+ "prank",
1193
+ "finger",
1194
+ "swear",
1195
+ "tmz",
1196
+ "topic",
1197
+ "navigate",
1198
+ "yellow",
1199
+ "garbage",
1200
+ "carpet",
1201
+ "roll",
1202
+ "maintenance",
1203
+ "janitor",
1204
+ "lunchroom",
1205
+ "apple",
1206
+ "cafeterium",
1207
+ "bite",
1208
+ "mop",
1209
+ "stuff",
1210
+ "parade",
1211
+ "scooter",
1212
+ "orchestra",
1213
+ "carnival",
1214
+ "standstill",
1215
+ "vintage",
1216
+ "control",
1217
+ "playing",
1218
+ "backround",
1219
+ "roar",
1220
+ "pretend",
1221
+ "cpr",
1222
+ "wedding",
1223
+ "tangle",
1224
+ "earbud",
1225
+ "lid",
1226
+ "sandhole",
1227
+ "train",
1228
+ "crime",
1229
+ "denial",
1230
+ "restrain",
1231
+ "file",
1232
+ "canal",
1233
+ "applaud",
1234
+ "clap",
1235
+ "dad",
1236
+ "story",
1237
+ "vigil",
1238
+ "newscastor",
1239
+ "newswoman",
1240
+ "volley",
1241
+ "neon",
1242
+ "muppet",
1243
+ "king",
1244
+ "theater",
1245
+ "pan",
1246
+ "form",
1247
+ "mold",
1248
+ "mini",
1249
+ "spoon",
1250
+ "motorcycle",
1251
+ "motorbike",
1252
+ "freeway",
1253
+ "picnic",
1254
+ "finn",
1255
+ "range",
1256
+ "engineering",
1257
+ "encourage",
1258
+ "slam",
1259
+ "gate",
1260
+ "tale",
1261
+ "skier",
1262
+ "represent",
1263
+ "surf",
1264
+ "surfboard",
1265
+ "snowboard",
1266
+ "cloud",
1267
+ "arrange",
1268
+ "boo",
1269
+ "disco",
1270
+ "singing",
1271
+ "correspond",
1272
+ "gogh",
1273
+ "screnn",
1274
+ "bernard",
1275
+ "premiere",
1276
+ "care",
1277
+ "salon",
1278
+ "saloon",
1279
+ "forest",
1280
+ "arm",
1281
+ "treatment",
1282
+ "van",
1283
+ "vanwhile",
1284
+ "msn",
1285
+ "dalmation",
1286
+ "pub",
1287
+ "rumor",
1288
+ "explode",
1289
+ "yell",
1290
+ "firework",
1291
+ "dashboard",
1292
+ "stereo",
1293
+ "honda",
1294
+ "robbie",
1295
+ "advocate",
1296
+ "birth",
1297
+ "rat",
1298
+ "hamster",
1299
+ "rodent",
1300
+ "owner",
1301
+ "sniff",
1302
+ "comfort",
1303
+ "attach",
1304
+ "remodel",
1305
+ "glue",
1306
+ "interior",
1307
+ "umpire",
1308
+ "tumble",
1309
+ "become",
1310
+ "collage",
1311
+ "ipod",
1312
+ "comedy",
1313
+ "snake",
1314
+ "shadow",
1315
+ "collar",
1316
+ "frame",
1317
+ "master",
1318
+ "dinosaur",
1319
+ "dinosor",
1320
+ "print",
1321
+ "carfax",
1322
+ "ralley",
1323
+ "tournament",
1324
+ "kium",
1325
+ "teni",
1326
+ "amaze",
1327
+ "compilation",
1328
+ "spar",
1329
+ "marshal",
1330
+ "order",
1331
+ "camel",
1332
+ "auburn",
1333
+ "mustard",
1334
+ "murrey",
1335
+ "jar",
1336
+ "festival",
1337
+ "firearm",
1338
+ "handgun",
1339
+ "magazine",
1340
+ "insert",
1341
+ "surround",
1342
+ "flirt",
1343
+ "cafe",
1344
+ "cupid",
1345
+ "contain",
1346
+ "footage",
1347
+ "wait",
1348
+ "structure",
1349
+ "left",
1350
+ "portrait",
1351
+ "sun",
1352
+ "revolve",
1353
+ "hallway",
1354
+ "glitter",
1355
+ "command",
1356
+ "officer",
1357
+ "solider",
1358
+ "formation",
1359
+ "computergame",
1360
+ "strategy",
1361
+ "puzzle",
1362
+ "memorize",
1363
+ "broth",
1364
+ "bowel",
1365
+ "chicken",
1366
+ "leveler",
1367
+ "journalist",
1368
+ "pitch",
1369
+ "occur",
1370
+ "routine",
1371
+ "oatmeal",
1372
+ "ballad",
1373
+ "listen",
1374
+ "audition",
1375
+ "toilet",
1376
+ "flush",
1377
+ "commode",
1378
+ "fainting",
1379
+ "needle",
1380
+ "faint",
1381
+ "spell",
1382
+ "chase",
1383
+ "pit",
1384
+ "hole",
1385
+ "scooby",
1386
+ "asteroid",
1387
+ "lunar",
1388
+ "impact",
1389
+ "streamer",
1390
+ "growth",
1391
+ "antelope",
1392
+ "technique",
1393
+ "churro",
1394
+ "countertop",
1395
+ "counter",
1396
+ "steam",
1397
+ "mood",
1398
+ "breakfast",
1399
+ "scowl",
1400
+ "facebook",
1401
+ "research",
1402
+ "examine",
1403
+ "paleontologist",
1404
+ "mascara",
1405
+ "hottie",
1406
+ "camouflage",
1407
+ "atv",
1408
+ "smokey",
1409
+ "zombie",
1410
+ "teenage",
1411
+ "aim",
1412
+ "masala",
1413
+ "frying",
1414
+ "village",
1415
+ "crocodile",
1416
+ "aligator",
1417
+ "alligator",
1418
+ "paste",
1419
+ "screw",
1420
+ "gum",
1421
+ "pipe",
1422
+ "gel",
1423
+ "gumbo",
1424
+ "hop",
1425
+ "complain",
1426
+ "tan",
1427
+ "lotion",
1428
+ "toples",
1429
+ "taboo",
1430
+ "day",
1431
+ "bikini",
1432
+ "skillet",
1433
+ "pancake",
1434
+ "zoom",
1435
+ "destination",
1436
+ "option",
1437
+ "capture",
1438
+ "zooming",
1439
+ "execise",
1440
+ "gymanasium",
1441
+ "integrate",
1442
+ "guide",
1443
+ "ryan",
1444
+ "progress",
1445
+ "crazy",
1446
+ "mike",
1447
+ "russium",
1448
+ "vladmir",
1449
+ "vladimir",
1450
+ "addres",
1451
+ "policy",
1452
+ "gown",
1453
+ "spirit",
1454
+ "shop",
1455
+ "journey",
1456
+ "fog",
1457
+ "hunt",
1458
+ "peak",
1459
+ "checkerd",
1460
+ "fault",
1461
+ "alien",
1462
+ "thank",
1463
+ "bal",
1464
+ "iphone",
1465
+ "guinea",
1466
+ "bathroom",
1467
+ "dry",
1468
+ "button",
1469
+ "chilli",
1470
+ "infusion",
1471
+ "slouse",
1472
+ "fanlala",
1473
+ "airport",
1474
+ "hindu",
1475
+ "marriage",
1476
+ "piccolo",
1477
+ "dragonball",
1478
+ "dome",
1479
+ "landmark",
1480
+ "suggest",
1481
+ "tunisium",
1482
+ "danger",
1483
+ "obstacle",
1484
+ "lot",
1485
+ "simple",
1486
+ "earring",
1487
+ "ear",
1488
+ "nasa",
1489
+ "graph",
1490
+ "microsoft",
1491
+ "spreadsheet",
1492
+ "somebody",
1493
+ "parker",
1494
+ "girlfriend",
1495
+ "focu",
1496
+ "indium",
1497
+ "netrus",
1498
+ "ladle",
1499
+ "aid",
1500
+ "university",
1501
+ "rifle",
1502
+ "flatter",
1503
+ "bulldozer",
1504
+ "excavator",
1505
+ "vampire",
1506
+ "fiddle",
1507
+ "israeli",
1508
+ "isreal",
1509
+ "infiltrate",
1510
+ "amusement",
1511
+ "sketch",
1512
+ "seasoning",
1513
+ "salt",
1514
+ "pepper",
1515
+ "steak",
1516
+ "season",
1517
+ "course",
1518
+ "return",
1519
+ "collect",
1520
+ "superb",
1521
+ "wisconsin",
1522
+ "nature",
1523
+ "valley",
1524
+ "hike",
1525
+ "trouble",
1526
+ "failure",
1527
+ "excise",
1528
+ "vertacle",
1529
+ "basketballer",
1530
+ "volcano",
1531
+ "map",
1532
+ "satellite",
1533
+ "sprinkle",
1534
+ "verde",
1535
+ "braid",
1536
+ "africa",
1537
+ "kenya",
1538
+ "interviewer",
1539
+ "gymnasium",
1540
+ "dodge",
1541
+ "automobile",
1542
+ "beard",
1543
+ "title",
1544
+ "beneath",
1545
+ "circket",
1546
+ "rockstar",
1547
+ "joan",
1548
+ "dave",
1549
+ "jam",
1550
+ "interface",
1551
+ "screencast",
1552
+ "coversation",
1553
+ "five-ing",
1554
+ "mltiple",
1555
+ "smack",
1556
+ "nadium",
1557
+ "stretcher",
1558
+ "overlap",
1559
+ "action",
1560
+ "teaser",
1561
+ "ledge",
1562
+ "overlook",
1563
+ "await",
1564
+ "rooftop",
1565
+ "invite",
1566
+ "bbc",
1567
+ "mall",
1568
+ "arrest",
1569
+ "dhabi",
1570
+ "conflict",
1571
+ "suspect",
1572
+ "critique",
1573
+ "expres",
1574
+ "buy",
1575
+ "diver",
1576
+ "scuba",
1577
+ "trunk",
1578
+ "bolt",
1579
+ "dream",
1580
+ "gymnast",
1581
+ "forward",
1582
+ "bar",
1583
+ "auditorium",
1584
+ "list",
1585
+ "ingredient",
1586
+ "pale",
1587
+ "tackle",
1588
+ "support",
1589
+ "beautiful",
1590
+ "back",
1591
+ "bedsheet",
1592
+ "mincraft",
1593
+ "emerald",
1594
+ "job",
1595
+ "york",
1596
+ "harlow",
1597
+ "tomorrow",
1598
+ "study",
1599
+ "sofa",
1600
+ "furniture",
1601
+ "saleman",
1602
+ "beef",
1603
+ "molecule",
1604
+ "chip",
1605
+ "check",
1606
+ "crew",
1607
+ "director",
1608
+ "warfield",
1609
+ "shaq",
1610
+ "balding",
1611
+ "microstructure",
1612
+ "web",
1613
+ "website",
1614
+ "checkmark",
1615
+ "relevant",
1616
+ "ethopium",
1617
+ "risk",
1618
+ "metallica",
1619
+ "battlefield",
1620
+ "mario",
1621
+ "receive",
1622
+ "anchorwoman",
1623
+ "gay",
1624
+ "hello",
1625
+ "futbol",
1626
+ "hollywood",
1627
+ "gtum",
1628
+ "breakdancing",
1629
+ "unbox",
1630
+ "plastic",
1631
+ "drown",
1632
+ "surfer",
1633
+ "drug",
1634
+ "gain",
1635
+ "flip",
1636
+ "transfer",
1637
+ "reflect",
1638
+ "colorful",
1639
+ "tbale",
1640
+ "bridge",
1641
+ "scenery",
1642
+ "coke",
1643
+ "soda",
1644
+ "cola",
1645
+ "saucepan",
1646
+ "stovetop",
1647
+ "coca",
1648
+ "moras",
1649
+ "dessert",
1650
+ "oniontomato",
1651
+ "materialism",
1652
+ "satan",
1653
+ "televison",
1654
+ "atom",
1655
+ "rectangle",
1656
+ "coupe",
1657
+ "damage",
1658
+ "optimu",
1659
+ "butter",
1660
+ "vegetable",
1661
+ "caramelize",
1662
+ "strut",
1663
+ "stroll",
1664
+ "lingerie",
1665
+ "protrude",
1666
+ "bleed",
1667
+ "bone",
1668
+ "audtioner",
1669
+ "safety",
1670
+ "charge",
1671
+ "sniper",
1672
+ "brunette",
1673
+ "eva",
1674
+ "environment",
1675
+ "thought",
1676
+ "handsom",
1677
+ "foul",
1678
+ "murder",
1679
+ "closet",
1680
+ "wearing",
1681
+ "sticker",
1682
+ "transmit",
1683
+ "tape",
1684
+ "glove",
1685
+ "nose",
1686
+ "stroke",
1687
+ "hairstyle",
1688
+ "actres",
1689
+ "isabella",
1690
+ "underworld",
1691
+ "projector",
1692
+ "shark",
1693
+ "sauce",
1694
+ "executive",
1695
+ "spicy",
1696
+ "plat",
1697
+ "curry",
1698
+ "guidance",
1699
+ "candle",
1700
+ "seance",
1701
+ "hall",
1702
+ "peanut",
1703
+ "chocolate",
1704
+ "toffee",
1705
+ "movement",
1706
+ "wake",
1707
+ "policeman",
1708
+ "investigation",
1709
+ "reel",
1710
+ "fisherman",
1711
+ "skateboarder",
1712
+ "racecar",
1713
+ "racetrack",
1714
+ "banister",
1715
+ "trail",
1716
+ "glider",
1717
+ "sexy",
1718
+ "quest",
1719
+ "captain",
1720
+ "blond",
1721
+ "shampoo",
1722
+ "grooming",
1723
+ "sherrus",
1724
+ "steel",
1725
+ "cros",
1726
+ "tree",
1727
+ "word",
1728
+ "onion",
1729
+ "hairanother",
1730
+ "groom",
1731
+ "eckersley",
1732
+ "magic",
1733
+ "cuisine",
1734
+ "customer",
1735
+ "necklace",
1736
+ "tube",
1737
+ "straighten",
1738
+ "wind",
1739
+ "chain",
1740
+ "benefit",
1741
+ "sentence",
1742
+ "bottom",
1743
+ "chow",
1744
+ "bottl",
1745
+ "juggeling",
1746
+ "juggle",
1747
+ "juggling",
1748
+ "mixer",
1749
+ "processor",
1750
+ "mixture",
1751
+ "whole",
1752
+ "crush",
1753
+ "grind",
1754
+ "melon",
1755
+ "promote",
1756
+ "company",
1757
+ "queen",
1758
+ "mustache",
1759
+ "noise",
1760
+ "goofy",
1761
+ "stomach",
1762
+ "cheek",
1763
+ "blush",
1764
+ "tattooed",
1765
+ "undergarment",
1766
+ "heart",
1767
+ "violent",
1768
+ "strength",
1769
+ "darknes",
1770
+ "creepy",
1771
+ "collision",
1772
+ "jennifer",
1773
+ "converstaion",
1774
+ "nutrition",
1775
+ "sweater",
1776
+ "illustrate",
1777
+ "grapple",
1778
+ "referee",
1779
+ "victory",
1780
+ "expansion",
1781
+ "carpenter",
1782
+ "trancition",
1783
+ "nail",
1784
+ "fisher",
1785
+ "translate",
1786
+ "shoulder",
1787
+ "presentation",
1788
+ "sex",
1789
+ "tea",
1790
+ "sip",
1791
+ "turtle",
1792
+ "corner",
1793
+ "babt",
1794
+ "pond",
1795
+ "modeling",
1796
+ "paddle",
1797
+ "bye",
1798
+ "drench",
1799
+ "cleaning",
1800
+ "ment",
1801
+ "synch",
1802
+ "overhead",
1803
+ "pingpong",
1804
+ "olympic",
1805
+ "exciting",
1806
+ "weekday",
1807
+ "lettering",
1808
+ "harrison",
1809
+ "bay",
1810
+ "flex",
1811
+ "lifting",
1812
+ "weight",
1813
+ "wayne",
1814
+ "aeroplane",
1815
+ "tractor",
1816
+ "rider",
1817
+ "horseback",
1818
+ "lamborghini",
1819
+ "running",
1820
+ "playgrond",
1821
+ "simulate",
1822
+ "otehr",
1823
+ "speach",
1824
+ "barack",
1825
+ "nation",
1826
+ "ohio",
1827
+ "motherand",
1828
+ "affection",
1829
+ "laughing",
1830
+ "ballet",
1831
+ "terrific",
1832
+ "composition",
1833
+ "choreographer",
1834
+ "zipline",
1835
+ "hairdryer",
1836
+ "gelatin",
1837
+ "texture",
1838
+ "dryer",
1839
+ "wrestler",
1840
+ "arena",
1841
+ "fool",
1842
+ "fail",
1843
+ "spaciousnes",
1844
+ "reveal",
1845
+ "corridor",
1846
+ "dermatologist",
1847
+ "charity",
1848
+ "rosacea",
1849
+ "cancer",
1850
+ "teaching",
1851
+ "equation",
1852
+ "factor",
1853
+ "spider",
1854
+ "roleplay",
1855
+ "villain",
1856
+ "blind",
1857
+ "fury",
1858
+ "loki",
1859
+ "patch",
1860
+ "instrumental",
1861
+ "tone",
1862
+ "calender",
1863
+ "alarm",
1864
+ "calendar",
1865
+ "torch",
1866
+ "flashlight",
1867
+ "christmastime",
1868
+ "mannequin",
1869
+ "wander",
1870
+ "brighter",
1871
+ "avatar",
1872
+ "combat",
1873
+ "motionles",
1874
+ "iran",
1875
+ "roam",
1876
+ "steal",
1877
+ "documentary",
1878
+ "hyena",
1879
+ "pester",
1880
+ "anchor",
1881
+ "summer",
1882
+ "jesu",
1883
+ "chant",
1884
+ "mingle",
1885
+ "hotel",
1886
+ "elevator",
1887
+ "joseph",
1888
+ "mic",
1889
+ "widget",
1890
+ "pip",
1891
+ "jeep",
1892
+ "absorber",
1893
+ "staircase",
1894
+ "wood",
1895
+ "improvement",
1896
+ "flooring",
1897
+ "floring",
1898
+ "plywood",
1899
+ "deck",
1900
+ "drool",
1901
+ "toaster",
1902
+ "puree",
1903
+ "simmer",
1904
+ "refer",
1905
+ "tab",
1906
+ "tablet",
1907
+ "library",
1908
+ "youngster",
1909
+ "smart",
1910
+ "six",
1911
+ "purple",
1912
+ "pacify",
1913
+ "motorway",
1914
+ "sedan",
1915
+ "spotlight",
1916
+ "grease",
1917
+ "mosquito",
1918
+ "scope",
1919
+ "announcement",
1920
+ "praise",
1921
+ "sputnik",
1922
+ "degras",
1923
+ "convention",
1924
+ "tyson",
1925
+ "unscrew",
1926
+ "unbolt",
1927
+ "instrunment",
1928
+ "shin",
1929
+ "pony",
1930
+ "choreograph",
1931
+ "fountain",
1932
+ "brown",
1933
+ "harvey",
1934
+ "someine",
1935
+ "drawing",
1936
+ "joy",
1937
+ "matter",
1938
+ "draft",
1939
+ "raft",
1940
+ "pontoon",
1941
+ "reef",
1942
+ "micheal",
1943
+ "cuddle",
1944
+ "vehicale",
1945
+ "latitude",
1946
+ "skincare",
1947
+ "inside",
1948
+ "confession",
1949
+ "youth",
1950
+ "tower",
1951
+ "church",
1952
+ "lover",
1953
+ "step",
1954
+ "rob",
1955
+ "lorry",
1956
+ "firefighter",
1957
+ "firetruck",
1958
+ "webpage",
1959
+ "troubleshoot",
1960
+ "distance",
1961
+ "direction",
1962
+ "maintain",
1963
+ "cube",
1964
+ "rubik",
1965
+ "ruby",
1966
+ "rubix",
1967
+ "solve",
1968
+ "cookery",
1969
+ "guillotine",
1970
+ "mist",
1971
+ "mask",
1972
+ "bing",
1973
+ "position",
1974
+ "tmy",
1975
+ "pastry",
1976
+ "powder",
1977
+ "unicorn",
1978
+ "layup",
1979
+ "middle",
1980
+ "sounding",
1981
+ "sound",
1982
+ "winter",
1983
+ "santum",
1984
+ "christma",
1985
+ "timberlake",
1986
+ "justin",
1987
+ "creek",
1988
+ "tourist",
1989
+ "ram",
1990
+ "ribeye",
1991
+ "foil",
1992
+ "harmonica",
1993
+ "sandwich",
1994
+ "sandwhich",
1995
+ "pregnancy",
1996
+ "brightnes",
1997
+ "fiction",
1998
+ "age",
1999
+ "center",
2000
+ "gathering",
2001
+ "alcohol",
2002
+ "wireles",
2003
+ "radio",
2004
+ "volume",
2005
+ "aguy",
2006
+ "coffee",
2007
+ "buzz",
2008
+ "dial",
2009
+ "ventura",
2010
+ "campaign",
2011
+ "collection",
2012
+ "super",
2013
+ "governor",
2014
+ "christie",
2015
+ "sunday",
2016
+ "meghan",
2017
+ "poll",
2018
+ "chri",
2019
+ "caller",
2020
+ "ski",
2021
+ "snowy",
2022
+ "bull",
2023
+ "clown",
2024
+ "jury",
2025
+ "champion",
2026
+ "programm",
2027
+ "gallery",
2028
+ "booth",
2029
+ "icon",
2030
+ "flowerpot",
2031
+ "bassinet",
2032
+ "krueger",
2033
+ "kruger",
2034
+ "kreuger",
2035
+ "freddy",
2036
+ "fatality",
2037
+ "gladiator",
2038
+ "lipstick",
2039
+ "amore",
2040
+ "brand",
2041
+ "lipglos",
2042
+ "flag",
2043
+ "lawn",
2044
+ "rev",
2045
+ "site",
2046
+ "enemy",
2047
+ "bent",
2048
+ "dash",
2049
+ "riffle",
2050
+ "grow",
2051
+ "cohabit",
2052
+ "tiger",
2053
+ "mouth",
2054
+ "edit",
2055
+ "adobe",
2056
+ "photoshop",
2057
+ "manager",
2058
+ "romanium",
2059
+ "ancient",
2060
+ "vine",
2061
+ "opponent",
2062
+ "dunk",
2063
+ "hipster",
2064
+ "energy",
2065
+ "monster",
2066
+ "tribute",
2067
+ "cabinet",
2068
+ "dresser",
2069
+ "twirl",
2070
+ "sporting",
2071
+ "golf",
2072
+ "golfer",
2073
+ "shine",
2074
+ "choir",
2075
+ "gospel",
2076
+ "partake",
2077
+ "smosh",
2078
+ "timey",
2079
+ "colonial",
2080
+ "multiple",
2081
+ "multiplication",
2082
+ "fruit",
2083
+ "lotu",
2084
+ "potato",
2085
+ "peel",
2086
+ "scrap",
2087
+ "curve",
2088
+ "acceleration",
2089
+ "garage",
2090
+ "cap",
2091
+ "demand",
2092
+ "ghost",
2093
+ "drummer",
2094
+ "breathe",
2095
+ "effect",
2096
+ "image",
2097
+ "frock",
2098
+ "marketing",
2099
+ "hawk",
2100
+ "makeshift",
2101
+ "skeleton",
2102
+ "graveyard",
2103
+ "cemetery",
2104
+ "mulitple",
2105
+ "oeioke",
2106
+ "protest",
2107
+ "reply",
2108
+ "protester",
2109
+ "contest",
2110
+ "cobweb",
2111
+ "dump",
2112
+ "drama",
2113
+ "airliner",
2114
+ "staff",
2115
+ "wing",
2116
+ "wipeout",
2117
+ "toddler",
2118
+ "refresh",
2119
+ "swimming",
2120
+ "ripple",
2121
+ "garlic",
2122
+ "feed",
2123
+ "nuzzle",
2124
+ "swimsuit",
2125
+ "mexico",
2126
+ "succes",
2127
+ "communicate",
2128
+ "asses",
2129
+ "treasure",
2130
+ "stun",
2131
+ "trader",
2132
+ "throat",
2133
+ "perish",
2134
+ "kissing",
2135
+ "revenge",
2136
+ "meatloaf",
2137
+ "stick",
2138
+ "gather",
2139
+ "glistening",
2140
+ "competion",
2141
+ "net",
2142
+ "filter",
2143
+ "spray",
2144
+ "inspect",
2145
+ "gsr",
2146
+ "inclosure",
2147
+ "beside",
2148
+ "mill",
2149
+ "din",
2150
+ "bring",
2151
+ "population",
2152
+ "batter",
2153
+ "midwife",
2154
+ "roadside",
2155
+ "picket",
2156
+ "march",
2157
+ "jacket",
2158
+ "cast",
2159
+ "seleton",
2160
+ "handsome",
2161
+ "force",
2162
+ "abuse",
2163
+ "stomp",
2164
+ "subway",
2165
+ "mimic",
2166
+ "tax",
2167
+ "newscast",
2168
+ "krabby",
2169
+ "plankton",
2170
+ "horizon",
2171
+ "hiker",
2172
+ "downhill",
2173
+ "right",
2174
+ "hoodie",
2175
+ "teen",
2176
+ "style",
2177
+ "goku",
2178
+ "sade",
2179
+ "charger",
2180
+ "carbon",
2181
+ "drain",
2182
+ "kidney",
2183
+ "lettuce",
2184
+ "leafy",
2185
+ "utensil",
2186
+ "punching",
2187
+ "kit",
2188
+ "boxer",
2189
+ "training",
2190
+ "bunching",
2191
+ "deconstruct",
2192
+ "blockchain",
2193
+ "symposium",
2194
+ "jacobson",
2195
+ "resort",
2196
+ "accord",
2197
+ "presenter",
2198
+ "correspondent",
2199
+ "son",
2200
+ "clone",
2201
+ "int",
2202
+ "entertainment",
2203
+ "ordinance",
2204
+ "tha",
2205
+ "audiance",
2206
+ "tennisball",
2207
+ "racket",
2208
+ "snowboarder",
2209
+ "audi",
2210
+ "competation",
2211
+ "ferrarus",
2212
+ "clarkson",
2213
+ "crowbar",
2214
+ "stop",
2215
+ "trainer",
2216
+ "signature",
2217
+ "commando",
2218
+ "riot",
2219
+ "interlace",
2220
+ "swordfight",
2221
+ "butt",
2222
+ "fend",
2223
+ "engage",
2224
+ "battle",
2225
+ "celery",
2226
+ "scavenge",
2227
+ "witch",
2228
+ "motor",
2229
+ "bracket",
2230
+ "wto",
2231
+ "green",
2232
+ "johnny",
2233
+ "sman",
2234
+ "cause",
2235
+ "entail",
2236
+ "potatoe",
2237
+ "careful",
2238
+ "hils",
2239
+ "quaker",
2240
+ "mason",
2241
+ "hostage",
2242
+ "somali",
2243
+ "creation",
2244
+ "execute",
2245
+ "rally",
2246
+ "exchange",
2247
+ "phil",
2248
+ "churchill",
2249
+ "churchiill",
2250
+ "brawl",
2251
+ "scuffle",
2252
+ "cricket",
2253
+ "laksa",
2254
+ "pikachu",
2255
+ "sampling",
2256
+ "vidoe",
2257
+ "glow",
2258
+ "rise",
2259
+ "receptor",
2260
+ "tail",
2261
+ "chid",
2262
+ "babbling",
2263
+ "chew",
2264
+ "paparazzi",
2265
+ "premier",
2266
+ "nothing",
2267
+ "marian",
2268
+ "relationship",
2269
+ "comapny",
2270
+ "donate",
2271
+ "cycle",
2272
+ "bicycle",
2273
+ "bycycling",
2274
+ "sparkling",
2275
+ "ribbon",
2276
+ "suacepan",
2277
+ "peter",
2278
+ "griffin",
2279
+ "connection",
2280
+ "boxing",
2281
+ "beatboxing",
2282
+ "twitter",
2283
+ "macbook",
2284
+ "respond",
2285
+ "watchmojo",
2286
+ "empire",
2287
+ "terrifying",
2288
+ "llama",
2289
+ "sheep",
2290
+ "waterway",
2291
+ "froth",
2292
+ "pie",
2293
+ "aluminum",
2294
+ "alumminum",
2295
+ "roasting",
2296
+ "crust",
2297
+ "aluminium",
2298
+ "rent",
2299
+ "analysi",
2300
+ "professional",
2301
+ "simulation",
2302
+ "land",
2303
+ "descend",
2304
+ "measuring",
2305
+ "measure",
2306
+ "flavor",
2307
+ "inform",
2308
+ "fellow",
2309
+ "gerbil",
2310
+ "tunnel",
2311
+ "wiggle",
2312
+ "peep",
2313
+ "stock",
2314
+ "menu",
2315
+ "divine",
2316
+ "candidate",
2317
+ "trump",
2318
+ "donald",
2319
+ "addiction",
2320
+ "department",
2321
+ "attire",
2322
+ "bread",
2323
+ "grandmother",
2324
+ "fridge",
2325
+ "blood",
2326
+ "brain",
2327
+ "harissa",
2328
+ "compile",
2329
+ "disgust",
2330
+ "cutlet",
2331
+ "prize",
2332
+ "slope",
2333
+ "mountainside",
2334
+ "cannon",
2335
+ "lantern",
2336
+ "jack",
2337
+ "projection",
2338
+ "circulate",
2339
+ "rod",
2340
+ "copper",
2341
+ "flute",
2342
+ "length",
2343
+ "intercourse",
2344
+ "grog",
2345
+ "radicalization",
2346
+ "terrorism",
2347
+ "ticker",
2348
+ "broccoli",
2349
+ "brolic",
2350
+ "ramsey",
2351
+ "gordon",
2352
+ "pres",
2353
+ "gift",
2354
+ "hindi",
2355
+ "rip",
2356
+ "cartoonist",
2357
+ "badminton",
2358
+ "badmitten",
2359
+ "batmanton",
2360
+ "indoor",
2361
+ "excite",
2362
+ "surveillance",
2363
+ "alleyway",
2364
+ "integra",
2365
+ "florida",
2366
+ "backpack",
2367
+ "everything",
2368
+ "bollywood",
2369
+ "acura",
2370
+ "umbrella",
2371
+ "spend",
2372
+ "sausage",
2373
+ "saussage",
2374
+ "straightener",
2375
+ "death",
2376
+ "question",
2377
+ "bagpiper",
2378
+ "muffin",
2379
+ "biscuit",
2380
+ "showroom",
2381
+ "dealer",
2382
+ "glance",
2383
+ "loi",
2384
+ "eyebrow",
2385
+ "reprimand",
2386
+ "release",
2387
+ "trancy",
2388
+ "restaraunt",
2389
+ "hive",
2390
+ "beehive",
2391
+ "woma",
2392
+ "spice",
2393
+ "rack",
2394
+ "sloth",
2395
+ "subscription",
2396
+ "implore",
2397
+ "subscribe",
2398
+ "dominate",
2399
+ "entourage",
2400
+ "randomer",
2401
+ "dollar",
2402
+ "zynga",
2403
+ "sillouette",
2404
+ "rovio",
2405
+ "facility",
2406
+ "kung",
2407
+ "ninja",
2408
+ "karate",
2409
+ "standoff",
2410
+ "square",
2411
+ "sprint",
2412
+ "cart",
2413
+ "aisle",
2414
+ "purchase",
2415
+ "grab",
2416
+ "duck",
2417
+ "refrigerate",
2418
+ "foo",
2419
+ "rowboat",
2420
+ "opeing",
2421
+ "goodbye",
2422
+ "cycling",
2423
+ "harley",
2424
+ "baymax",
2425
+ "mate",
2426
+ "videotape",
2427
+ "skydive",
2428
+ "pluck",
2429
+ "avril",
2430
+ "number",
2431
+ "count",
2432
+ "hummer",
2433
+ "motorcyclist",
2434
+ "pulsate",
2435
+ "sparkle",
2436
+ "past",
2437
+ "trip",
2438
+ "prisoner",
2439
+ "albino",
2440
+ "gage",
2441
+ "example",
2442
+ "while",
2443
+ "piano",
2444
+ "countles",
2445
+ "techno",
2446
+ "cow",
2447
+ "headbutt",
2448
+ "level",
2449
+ "station",
2450
+ "railway",
2451
+ "viewpoint",
2452
+ "courtesy",
2453
+ "george",
2454
+ "receiver",
2455
+ "tuxedo",
2456
+ "stocking",
2457
+ "donkey",
2458
+ "robe",
2459
+ "modify",
2460
+ "cookie",
2461
+ "napkin",
2462
+ "hash",
2463
+ "non",
2464
+ "roast",
2465
+ "tantrum",
2466
+ "pillow",
2467
+ "whine",
2468
+ "freak",
2469
+ "slave",
2470
+ "solomon",
2471
+ "plantation",
2472
+ "northup",
2473
+ "flint",
2474
+ "bane",
2475
+ "batman",
2476
+ "footpath",
2477
+ "kitchena",
2478
+ "laboratory",
2479
+ "gesticulate",
2480
+ "pinnochio",
2481
+ "cheerlead",
2482
+ "self",
2483
+ "cement",
2484
+ "vegetation",
2485
+ "mossy",
2486
+ "sermon",
2487
+ "fear",
2488
+ "pastor",
2489
+ "preach",
2490
+ "notice",
2491
+ "row",
2492
+ "evaluate",
2493
+ "kayak",
2494
+ "competetion",
2495
+ "kaya",
2496
+ "panda",
2497
+ "tend",
2498
+ "inappropriate",
2499
+ "log",
2500
+ "basement",
2501
+ "ladder",
2502
+ "trap",
2503
+ "latter",
2504
+ "motorcyle",
2505
+ "slab",
2506
+ "reallity",
2507
+ "creed",
2508
+ "costume",
2509
+ "handball",
2510
+ "goalie",
2511
+ "colbert",
2512
+ "vacuum",
2513
+ "sort",
2514
+ "launch",
2515
+ "popcorn",
2516
+ "episode",
2517
+ "wop",
2518
+ "wheelchair",
2519
+ "oliver",
2520
+ "steven",
2521
+ "enduro",
2522
+ "unload",
2523
+ "hardcore",
2524
+ "faster",
2525
+ "perfect",
2526
+ "helmet",
2527
+ "skiin",
2528
+ "dirtbike",
2529
+ "admire",
2530
+ "vechile",
2531
+ "expo",
2532
+ "bulb",
2533
+ "holiday",
2534
+ "palace",
2535
+ "crying",
2536
+ "cinderella",
2537
+ "soundtrack",
2538
+ "kind",
2539
+ "godmother",
2540
+ "hitter",
2541
+ "update",
2542
+ "congressman",
2543
+ "angela",
2544
+ "countdown",
2545
+ "leonardo",
2546
+ "bunch",
2547
+ "path",
2548
+ "disease",
2549
+ "battery",
2550
+ "attachment",
2551
+ "iron",
2552
+ "hulk",
2553
+ "drone",
2554
+ "lining",
2555
+ "aircraft",
2556
+ "snack",
2557
+ "household",
2558
+ "establishment",
2559
+ "criticise",
2560
+ "anger",
2561
+ "sunami",
2562
+ "shore",
2563
+ "commissioner",
2564
+ "disagree",
2565
+ "claim",
2566
+ "bia",
2567
+ "republican",
2568
+ "author",
2569
+ "cigarette",
2570
+ "brad",
2571
+ "poster",
2572
+ "escalate",
2573
+ "barn",
2574
+ "crane",
2575
+ "concentration",
2576
+ "ecavator",
2577
+ "selena",
2578
+ "hip",
2579
+ "outfit",
2580
+ "dancehall",
2581
+ "kitten",
2582
+ "diffrerent",
2583
+ "gossip",
2584
+ "taylor",
2585
+ "connect",
2586
+ "concept",
2587
+ "datum",
2588
+ "marker",
2589
+ "rubic",
2590
+ "medieval",
2591
+ "elf",
2592
+ "rocket",
2593
+ "infront",
2594
+ "want",
2595
+ "charlie",
2596
+ "restroom",
2597
+ "bladder",
2598
+ "scatter",
2599
+ "touchdown",
2600
+ "coaster",
2601
+ "fan",
2602
+ "eminem",
2603
+ "sprinter",
2604
+ "tragedy",
2605
+ "awe",
2606
+ "stitch",
2607
+ "sew",
2608
+ "knit",
2609
+ "dock",
2610
+ "harbor",
2611
+ "golfing",
2612
+ "disconnect",
2613
+ "rewire",
2614
+ "cord",
2615
+ "connector",
2616
+ "bob",
2617
+ "bop",
2618
+ "spongue",
2619
+ "spacey",
2620
+ "nod",
2621
+ "pay",
2622
+ "john",
2623
+ "fox",
2624
+ "intolerance",
2625
+ "pile",
2626
+ "speaking",
2627
+ "pant",
2628
+ "yawn",
2629
+ "bark",
2630
+ "mock",
2631
+ "puppy",
2632
+ "argument",
2633
+ "cheetum",
2634
+ "cheetah",
2635
+ "cheetha",
2636
+ "taw",
2637
+ "gee",
2638
+ "duel",
2639
+ "celebraty",
2640
+ "stack",
2641
+ "laundry",
2642
+ "clothe",
2643
+ "sheet",
2644
+ "clothesline",
2645
+ "lil",
2646
+ "biz",
2647
+ "amn",
2648
+ "sample",
2649
+ "hanson",
2650
+ "slip",
2651
+ "deer",
2652
+ "foothold",
2653
+ "raindeer",
2654
+ "nfl",
2655
+ "cello",
2656
+ "living",
2657
+ "forklift",
2658
+ "somone",
2659
+ "clipart",
2660
+ "mobility",
2661
+ "tinker",
2662
+ "click",
2663
+ "weighter",
2664
+ "decoration",
2665
+ "bank",
2666
+ "musician",
2667
+ "recite",
2668
+ "soccerball",
2669
+ "hokey",
2670
+ "hokie",
2671
+ "understand",
2672
+ "eclipse",
2673
+ "moo",
2674
+ "baraka",
2675
+ "actin",
2676
+ "fluid",
2677
+ "takeout",
2678
+ "preparation",
2679
+ "bimbo",
2680
+ "charmander",
2681
+ "osbourne",
2682
+ "ozbourne",
2683
+ "catcher",
2684
+ "anything",
2685
+ "edm",
2686
+ "rop",
2687
+ "swing",
2688
+ "cradle",
2689
+ "flare",
2690
+ "tornado",
2691
+ "solar",
2692
+ "burst",
2693
+ "finish",
2694
+ "cursor",
2695
+ "screenshot",
2696
+ "seafood",
2697
+ "shell",
2698
+ "cleaver",
2699
+ "crap",
2700
+ "highlight",
2701
+ "knead",
2702
+ "masseuse",
2703
+ "palor",
2704
+ "inblue",
2705
+ "column",
2706
+ "miniature",
2707
+ "behavior",
2708
+ "pizza",
2709
+ "pope",
2710
+ "bles",
2711
+ "surge",
2712
+ "rhino",
2713
+ "hippo",
2714
+ "moped",
2715
+ "gasket",
2716
+ "chief",
2717
+ "thaw",
2718
+ "obscure",
2719
+ "port",
2720
+ "visibility",
2721
+ "nemesi",
2722
+ "musc",
2723
+ "backdrop",
2724
+ "bride",
2725
+ "heartbroken",
2726
+ "hakeem",
2727
+ "underwear",
2728
+ "doodlebug",
2729
+ "nolan",
2730
+ "castle",
2731
+ "dungeon",
2732
+ "glassware",
2733
+ "dispener",
2734
+ "avoid",
2735
+ "accessory",
2736
+ "clutch",
2737
+ "steering",
2738
+ "warm",
2739
+ "stretch",
2740
+ "guitor",
2741
+ "ultron",
2742
+ "backflip",
2743
+ "watering",
2744
+ "wise",
2745
+ "lawsuit",
2746
+ "demon",
2747
+ "overdose",
2748
+ "paranormal",
2749
+ "bondage",
2750
+ "veg",
2751
+ "plank",
2752
+ "loading",
2753
+ "buffer",
2754
+ "wildernes",
2755
+ "wwe",
2756
+ "mysterio",
2757
+ "tear",
2758
+ "wool",
2759
+ "fabric",
2760
+ "italy",
2761
+ "volkswagen",
2762
+ "wheel",
2763
+ "passenger",
2764
+ "funnel",
2765
+ "unpack",
2766
+ "carton",
2767
+ "oragami",
2768
+ "advance",
2769
+ "grandfather",
2770
+ "slap",
2771
+ "sir",
2772
+ "student",
2773
+ "classmate",
2774
+ "burger",
2775
+ "stew",
2776
+ "fellowman",
2777
+ "restraunt",
2778
+ "kimchi",
2779
+ "today",
2780
+ "ceremony",
2781
+ "attention",
2782
+ "vistor",
2783
+ "visitor",
2784
+ "mount",
2785
+ "dugout",
2786
+ "mound",
2787
+ "championship",
2788
+ "vedio",
2789
+ "jungle",
2790
+ "statement",
2791
+ "restaurent",
2792
+ "dez",
2793
+ "shield",
2794
+ "eyelid",
2795
+ "shane",
2796
+ "monologue",
2797
+ "oscar",
2798
+ "podcast",
2799
+ "obsitcle",
2800
+ "bin",
2801
+ "donation",
2802
+ "kindnes",
2803
+ "multus",
2804
+ "columbium",
2805
+ "spielberg",
2806
+ "kitty",
2807
+ "emission",
2808
+ "outlet",
2809
+ "coyote",
2810
+ "howl",
2811
+ "pray",
2812
+ "televisoin",
2813
+ "skit",
2814
+ "mifa",
2815
+ "countryside",
2816
+ "belt",
2817
+ "independence",
2818
+ "tuck",
2819
+ "blanket",
2820
+ "blancket",
2821
+ "champagne",
2822
+ "card",
2823
+ "complaining",
2824
+ "albinism",
2825
+ "discvery",
2826
+ "shooter",
2827
+ "sledge",
2828
+ "feminism",
2829
+ "navy",
2830
+ "leak",
2831
+ "sweat",
2832
+ "broccoili",
2833
+ "reciepus",
2834
+ "bakery",
2835
+ "nightime",
2836
+ "commit",
2837
+ "swingset",
2838
+ "suicide",
2839
+ "finishing",
2840
+ "smoking",
2841
+ "tutor",
2842
+ "trance",
2843
+ "grandma",
2844
+ "blast",
2845
+ "punk",
2846
+ "rehearse",
2847
+ "headrest",
2848
+ "showing",
2849
+ "cone",
2850
+ "symbol",
2851
+ "japan",
2852
+ "terrace",
2853
+ "wifi",
2854
+ "bathtub",
2855
+ "straw",
2856
+ "bathwater",
2857
+ "drinking",
2858
+ "suck",
2859
+ "freeman",
2860
+ "morgan",
2861
+ "stork",
2862
+ "poach",
2863
+ "outbreak",
2864
+ "dicing",
2865
+ "dice",
2866
+ "producer",
2867
+ "drum",
2868
+ "percussion",
2869
+ "narration",
2870
+ "inventory",
2871
+ "mushroom",
2872
+ "select",
2873
+ "peephole",
2874
+ "society",
2875
+ "healthcare",
2876
+ "sharpie",
2877
+ "notebook",
2878
+ "packet",
2879
+ "future",
2880
+ "munch",
2881
+ "llamma",
2882
+ "elaborate",
2883
+ "fixing",
2884
+ "description",
2885
+ "giraffe",
2886
+ "mickey",
2887
+ "mousekersize",
2888
+ "walt",
2889
+ "adult",
2890
+ "syringe",
2891
+ "dropper",
2892
+ "condensation",
2893
+ "leash",
2894
+ "dye",
2895
+ "wagon",
2896
+ "camp",
2897
+ "stump",
2898
+ "campsite",
2899
+ "upbeat",
2900
+ "everyone",
2901
+ "limp",
2902
+ "weapon",
2903
+ "idiot",
2904
+ "conductor",
2905
+ "beautician",
2906
+ "colmy",
2907
+ "simplify",
2908
+ "lapse",
2909
+ "trampoline",
2910
+ "jewelry",
2911
+ "muffler",
2912
+ "subframe",
2913
+ "curvy",
2914
+ "celebration",
2915
+ "anniversay",
2916
+ "mariah",
2917
+ "anniversary",
2918
+ "romance",
2919
+ "doorbell",
2920
+ "shrimp",
2921
+ "everest",
2922
+ "five",
2923
+ "seminar",
2924
+ "perry",
2925
+ "solor",
2926
+ "trade",
2927
+ "hogan",
2928
+ "pople",
2929
+ "demontrating",
2930
+ "envy",
2931
+ "groud",
2932
+ "valencium",
2933
+ "womean",
2934
+ "marinate",
2935
+ "comedian",
2936
+ "viral",
2937
+ "spounge",
2938
+ "manipulate",
2939
+ "knot",
2940
+ "helicoptor",
2941
+ "location",
2942
+ "decide",
2943
+ "mountaintop",
2944
+ "skyanother",
2945
+ "2013",
2946
+ "runnig",
2947
+ "winner",
2948
+ "gizmo",
2949
+ "kajak",
2950
+ "extraction",
2951
+ "technician",
2952
+ "tissue",
2953
+ "duggar",
2954
+ "stonehenge",
2955
+ "afar",
2956
+ "branch",
2957
+ "wine",
2958
+ "flub",
2959
+ "mean",
2960
+ "consist",
2961
+ "accapella",
2962
+ "thunder",
2963
+ "lick",
2964
+ "loosen",
2965
+ "blogger",
2966
+ "close",
2967
+ "baking",
2968
+ "curse",
2969
+ "brutality",
2970
+ "weird",
2971
+ "flail",
2972
+ "whip",
2973
+ "manchild",
2974
+ "plunge",
2975
+ "splash",
2976
+ "thrash",
2977
+ "recount",
2978
+ "cheat",
2979
+ "cupboard",
2980
+ "organizer",
2981
+ "refrigerator",
2982
+ "shelf",
2983
+ "accident",
2984
+ "tamato",
2985
+ "scout",
2986
+ "iraq",
2987
+ "surveliance",
2988
+ "engineer",
2989
+ "perfomer",
2990
+ "kenium",
2991
+ "grafitus",
2992
+ "rejuvenate",
2993
+ "moisturizer",
2994
+ "fake",
2995
+ "salada",
2996
+ "series",
2997
+ "tokyo",
2998
+ "weather",
2999
+ "leap",
3000
+ "variety",
3001
+ "watermelon",
3002
+ "pastum",
3003
+ "buffet",
3004
+ "chaser",
3005
+ "recreate",
3006
+ "tire",
3007
+ "bush",
3008
+ "bok",
3009
+ "tibet",
3010
+ "grassland",
3011
+ "beyonce",
3012
+ "laura",
3013
+ "cottage",
3014
+ "strain",
3015
+ "frown",
3016
+ "merry",
3017
+ "broom",
3018
+ "gameboy",
3019
+ "broaden",
3020
+ "content",
3021
+ "knowledge",
3022
+ "trust",
3023
+ "lunch",
3024
+ "atray",
3025
+ "buff",
3026
+ "hitch",
3027
+ "gameone",
3028
+ "daring",
3029
+ "rabbit",
3030
+ "keeper",
3031
+ "ina",
3032
+ "reaper",
3033
+ "killer",
3034
+ "specialist",
3035
+ "psychoanalyst",
3036
+ "counselor",
3037
+ "duet",
3038
+ "melody",
3039
+ "arthur",
3040
+ "emanate",
3041
+ "rpm",
3042
+ "firing",
3043
+ "explosion",
3044
+ "escape",
3045
+ "scenario",
3046
+ "entertainer",
3047
+ "spill",
3048
+ "carve",
3049
+ "casa",
3050
+ "gordan",
3051
+ "btalking",
3052
+ "spectacle",
3053
+ "corn",
3054
+ "mixie",
3055
+ "coloring",
3056
+ "intersection",
3057
+ "gla",
3058
+ "lime",
3059
+ "kapil",
3060
+ "stalk",
3061
+ "handler",
3062
+ "sack",
3063
+ "procol",
3064
+ "puma",
3065
+ "randolph",
3066
+ "peetum",
3067
+ "hunger",
3068
+ "mince",
3069
+ "accros",
3070
+ "therapist",
3071
+ "togethernes",
3072
+ "counciling",
3073
+ "lawyer",
3074
+ "beer",
3075
+ "beverage",
3076
+ "garb",
3077
+ "hoist",
3078
+ "autograph",
3079
+ "possession",
3080
+ "egypt",
3081
+ "engaging",
3082
+ "careear",
3083
+ "proone",
3084
+ "session",
3085
+ "edward",
3086
+ "convince",
3087
+ "pail",
3088
+ "conveyer",
3089
+ "wet",
3090
+ "babality",
3091
+ "defeat",
3092
+ "humiliate",
3093
+ "mortal",
3094
+ "cnbc",
3095
+ "leather",
3096
+ "scarf",
3097
+ "esteban",
3098
+ "ricky",
3099
+ "spmone",
3100
+ "highschool",
3101
+ "extention",
3102
+ "michael",
3103
+ "deandre",
3104
+ "chug",
3105
+ "climbinb",
3106
+ "rating",
3107
+ "tilt",
3108
+ "playstation",
3109
+ "hook",
3110
+ "viedo",
3111
+ "note",
3112
+ "string",
3113
+ "thread",
3114
+ "sense",
3115
+ "orbit",
3116
+ "peruse",
3117
+ "compost",
3118
+ "gardening",
3119
+ "robert",
3120
+ "controller",
3121
+ "theme",
3122
+ "price",
3123
+ "inspector",
3124
+ "friendship",
3125
+ "rolling",
3126
+ "spinning",
3127
+ "mcgeorge",
3128
+ "balcony",
3129
+ "tortoise",
3130
+ "popsicle",
3131
+ "squint",
3132
+ "alongwith",
3133
+ "primate",
3134
+ "expression",
3135
+ "macaque",
3136
+ "wok",
3137
+ "prawn",
3138
+ "resist",
3139
+ "rape",
3140
+ "scale",
3141
+ "gorden",
3142
+ "hiw",
3143
+ "miscarriage",
3144
+ "dealership",
3145
+ "sportsman",
3146
+ "spatula",
3147
+ "gopher",
3148
+ "beaver",
3149
+ "whisk",
3150
+ "moment",
3151
+ "wafer",
3152
+ "complex",
3153
+ "squish",
3154
+ "vollyball",
3155
+ "employee",
3156
+ "dispense",
3157
+ "worker",
3158
+ "icecream",
3159
+ "badmington",
3160
+ "shuttlecock",
3161
+ "tourney",
3162
+ "mistake",
3163
+ "goald",
3164
+ "proficiency",
3165
+ "skip",
3166
+ "ariel",
3167
+ "cupcake",
3168
+ "mermaid",
3169
+ "zipper",
3170
+ "fantasy",
3171
+ "devastate",
3172
+ "compute",
3173
+ "brochure",
3174
+ "booklet",
3175
+ "lobby",
3176
+ "split",
3177
+ "sunda",
3178
+ "terrain",
3179
+ "skiing",
3180
+ "britain",
3181
+ "popularity",
3182
+ "coerce",
3183
+ "coo",
3184
+ "mama",
3185
+ "badmitton",
3186
+ "buttock",
3187
+ "chrissy",
3188
+ "verentum",
3189
+ "railing",
3190
+ "physician",
3191
+ "injection",
3192
+ "inject",
3193
+ "beg",
3194
+ "cock",
3195
+ "victorium",
3196
+ "manufacture",
3197
+ "marburg",
3198
+ "overlaid",
3199
+ "warning",
3200
+ "arch",
3201
+ "entrance",
3202
+ "torque",
3203
+ "faster0",
3204
+ "playlist",
3205
+ "online",
3206
+ "opinion",
3207
+ "marketplace",
3208
+ "goalpost",
3209
+ "proposition",
3210
+ "prostitute",
3211
+ "cctv",
3212
+ "situation",
3213
+ "encounter",
3214
+ "chrocodile",
3215
+ "tempt",
3216
+ "transmission",
3217
+ "temple",
3218
+ "architecture",
3219
+ "travelogue",
3220
+ "demonstrating",
3221
+ "tech",
3222
+ "tes",
3223
+ "starburst",
3224
+ "thailand",
3225
+ "marijuana",
3226
+ "witha",
3227
+ "foreigner",
3228
+ "forehead",
3229
+ "lannister",
3230
+ "dinklage",
3231
+ "lad",
3232
+ "constume",
3233
+ "katty",
3234
+ "katy",
3235
+ "chopter",
3236
+ "hoverbike",
3237
+ "hover",
3238
+ "generation",
3239
+ "apron",
3240
+ "axe",
3241
+ "injury",
3242
+ "safty",
3243
+ "wound",
3244
+ "grande",
3245
+ "ariana",
3246
+ "jason",
3247
+ "honey",
3248
+ "cotton",
3249
+ "stopper",
3250
+ "linu",
3251
+ "intro",
3252
+ "indie",
3253
+ "limit",
3254
+ "personality",
3255
+ "plasticine",
3256
+ "seek",
3257
+ "armor",
3258
+ "controversry",
3259
+ "straddle",
3260
+ "fingernail",
3261
+ "sautee",
3262
+ "patty",
3263
+ "caharacter",
3264
+ "redhead",
3265
+ "alphabet",
3266
+ "christian",
3267
+ "plug",
3268
+ "richkidstv",
3269
+ "resturant",
3270
+ "sweep",
3271
+ "unroll",
3272
+ "dust",
3273
+ "circuit",
3274
+ "jail",
3275
+ "agent",
3276
+ "magician",
3277
+ "interrogate",
3278
+ "tortilla",
3279
+ "hymn",
3280
+ "religion",
3281
+ "miley",
3282
+ "fallon",
3283
+ "jimmy",
3284
+ "decision",
3285
+ "jim",
3286
+ "snoop",
3287
+ "escort",
3288
+ "motocros",
3289
+ "info",
3290
+ "mas",
3291
+ "extract",
3292
+ "multimedium",
3293
+ "scorpion",
3294
+ "furnace",
3295
+ "incinerator",
3296
+ "jackson",
3297
+ "weekend",
3298
+ "cristiano",
3299
+ "suspense",
3300
+ "transform",
3301
+ "vilon",
3302
+ "tamil",
3303
+ "smock",
3304
+ "combine",
3305
+ "ginger",
3306
+ "dhal",
3307
+ "listing",
3308
+ "tomato",
3309
+ "mation",
3310
+ "candlelight",
3311
+ "defend",
3312
+ "doomsday",
3313
+ "malibu",
3314
+ "defending",
3315
+ "power",
3316
+ "mmorpg",
3317
+ "backyard",
3318
+ "illnes",
3319
+ "condition",
3320
+ "papaer",
3321
+ "unwrap",
3322
+ "gameboard",
3323
+ "nutraloaf",
3324
+ "prison",
3325
+ "ease",
3326
+ "feminine",
3327
+ "moar",
3328
+ "solicit",
3329
+ "minion",
3330
+ "auto",
3331
+ "offroad",
3332
+ "dune",
3333
+ "tumbler",
3334
+ "winan",
3335
+ "freezer",
3336
+ "storm",
3337
+ "bbq",
3338
+ "club",
3339
+ "retaurant",
3340
+ "parking",
3341
+ "greg",
3342
+ "paino",
3343
+ "rhyme",
3344
+ "nintendo",
3345
+ "coconut",
3346
+ "catapult",
3347
+ "manufacturing",
3348
+ "warehouse",
3349
+ "pursue",
3350
+ "reassure",
3351
+ "plan",
3352
+ "blouse",
3353
+ "bathrom",
3354
+ "interviewing",
3355
+ "jon",
3356
+ "condolence",
3357
+ "memorial",
3358
+ "homage",
3359
+ "audiomicro",
3360
+ "sugar",
3361
+ "cinnamon",
3362
+ "sponebob",
3363
+ "imitate",
3364
+ "recreation",
3365
+ "pressconference",
3366
+ "antler",
3367
+ "moose",
3368
+ "murry",
3369
+ "headset",
3370
+ "painting",
3371
+ "trench",
3372
+ "globemaster",
3373
+ "stoner",
3374
+ "skyscraper",
3375
+ "cabin",
3376
+ "orient",
3377
+ "stiller",
3378
+ "highdive",
3379
+ "statuesque",
3380
+ "elephant",
3381
+ "bump",
3382
+ "suscribe",
3383
+ "appearance",
3384
+ "limousine",
3385
+ "hovercopter",
3386
+ "hovercraft",
3387
+ "voyage",
3388
+ "jumbping",
3389
+ "surgery",
3390
+ "administer",
3391
+ "nickelodeon",
3392
+ "clicker",
3393
+ "brunnette",
3394
+ "mark",
3395
+ "loarge",
3396
+ "unison",
3397
+ "reverse",
3398
+ "cub",
3399
+ "cartwheel",
3400
+ "saute",
3401
+ "tyga",
3402
+ "heavyset",
3403
+ "puddle",
3404
+ "district",
3405
+ "weigh",
3406
+ "advertising",
3407
+ "promotion",
3408
+ "couh",
3409
+ "charleston",
3410
+ "nidoran",
3411
+ "pokelon",
3412
+ "blend",
3413
+ "drill",
3414
+ "pulp",
3415
+ "watermellon",
3416
+ "vie",
3417
+ "sportscaster",
3418
+ "sunset",
3419
+ "pork",
3420
+ "fair",
3421
+ "tin",
3422
+ "xbox",
3423
+ "jumper",
3424
+ "gol",
3425
+ "spiderman",
3426
+ "batmobile",
3427
+ "coacher",
3428
+ "gymnist",
3429
+ "fastball",
3430
+ "kukumapoo",
3431
+ "saffron",
3432
+ "audio",
3433
+ "idea",
3434
+ "thi",
3435
+ "reason",
3436
+ "isn",
3437
+ "introductory",
3438
+ "planist",
3439
+ "pianist",
3440
+ "anticipation",
3441
+ "legislation",
3442
+ "marijuan",
3443
+ "legalize",
3444
+ "hockey",
3445
+ "morgue",
3446
+ "case",
3447
+ "edge",
3448
+ "kombat",
3449
+ "spew",
3450
+ "workout",
3451
+ "playzone",
3452
+ "wtwo",
3453
+ "flatbread",
3454
+ "vendor",
3455
+ "naan",
3456
+ "pound",
3457
+ "sunlight",
3458
+ "traveller",
3459
+ "capacity",
3460
+ "picturesque",
3461
+ "ropway",
3462
+ "chevy",
3463
+ "balloon",
3464
+ "jet",
3465
+ "dub",
3466
+ "role",
3467
+ "indiana",
3468
+ "quote",
3469
+ "fedora",
3470
+ "paragraph",
3471
+ "trudge",
3472
+ "curtain",
3473
+ "nalepianki",
3474
+ "skrobanki",
3475
+ "desolate",
3476
+ "polo",
3477
+ "badge",
3478
+ "crack",
3479
+ "ineterview",
3480
+ "sneeze",
3481
+ "strobe",
3482
+ "vodka",
3483
+ "burray",
3484
+ "biotechnology",
3485
+ "heal",
3486
+ "criminal",
3487
+ "reenact",
3488
+ "void",
3489
+ "manage",
3490
+ "frog",
3491
+ "kermit",
3492
+ "mazda",
3493
+ "vortex",
3494
+ "liquicd",
3495
+ "elect",
3496
+ "winnie",
3497
+ "writhe",
3498
+ "fact",
3499
+ "tehcno",
3500
+ "fanning",
3501
+ "commentating",
3502
+ "mole",
3503
+ "accept",
3504
+ "loom",
3505
+ "twist",
3506
+ "cadaver",
3507
+ "commuter",
3508
+ "sassy",
3509
+ "makup",
3510
+ "cyber",
3511
+ "restaurand",
3512
+ "doe",
3513
+ "violence",
3514
+ "plumber",
3515
+ "chararacter",
3516
+ "intelligence",
3517
+ "algorithm",
3518
+ "gesture",
3519
+ "sugarflor",
3520
+ "hurdle",
3521
+ "copetision",
3522
+ "iceland",
3523
+ "paraglide",
3524
+ "mustang",
3525
+ "nicki",
3526
+ "nikki",
3527
+ "compliment",
3528
+ "attraction",
3529
+ "pesron",
3530
+ "core",
3531
+ "ghul",
3532
+ "stab",
3533
+ "smith",
3534
+ "moma",
3535
+ "zoo",
3536
+ "calony",
3537
+ "survival",
3538
+ "bee",
3539
+ "minature",
3540
+ "saucer",
3541
+ "iteam",
3542
+ "reviewer",
3543
+ "delevigne",
3544
+ "mountion",
3545
+ "sum",
3546
+ "scooba",
3547
+ "official",
3548
+ "tur",
3549
+ "slash",
3550
+ "racoon",
3551
+ "photgraph",
3552
+ "magnet",
3553
+ "megaphone",
3554
+ "alpasca",
3555
+ "animate",
3556
+ "excitement",
3557
+ "hayatochirus",
3558
+ "shopit",
3559
+ "voilin",
3560
+ "homerun",
3561
+ "puppet",
3562
+ "daycare",
3563
+ "roofer",
3564
+ "adhesive",
3565
+ "behave",
3566
+ "liner",
3567
+ "curly",
3568
+ "headphone",
3569
+ "seduce",
3570
+ "passion",
3571
+ "saree",
3572
+ "mourn",
3573
+ "dismis",
3574
+ "dialysi",
3575
+ "tender",
3576
+ "salmon",
3577
+ "wink",
3578
+ "assessment",
3579
+ "finland",
3580
+ "passi",
3581
+ "avenger",
3582
+ "uniform",
3583
+ "law",
3584
+ "tense",
3585
+ "thrill",
3586
+ "franchise",
3587
+ "laughter",
3588
+ "standup",
3589
+ "paneer",
3590
+ "archor",
3591
+ "newtown",
3592
+ "megan",
3593
+ "faucet",
3594
+ "cus",
3595
+ "eyeshadow",
3596
+ "dragon",
3597
+ "bet",
3598
+ "pattern",
3599
+ "nerf",
3600
+ "fondle",
3601
+ "reckles",
3602
+ "sportscar",
3603
+ "public",
3604
+ "midair",
3605
+ "norton",
3606
+ "soak",
3607
+ "squeeze",
3608
+ "sandra",
3609
+ "crisi",
3610
+ "smashbrother",
3611
+ "supersmash",
3612
+ "wild",
3613
+ "encouragement",
3614
+ "barefoot",
3615
+ "ammunition",
3616
+ "ammo",
3617
+ "workspace",
3618
+ "coma",
3619
+ "scar",
3620
+ "expectancy",
3621
+ "rockband",
3622
+ "sceneary",
3623
+ "glare",
3624
+ "invention",
3625
+ "wardrobe",
3626
+ "antique",
3627
+ "volkswagon",
3628
+ "pair",
3629
+ "huddle",
3630
+ "cold",
3631
+ "putty",
3632
+ "samsung",
3633
+ "muscle",
3634
+ "daytona",
3635
+ "datona",
3636
+ "pocket",
3637
+ "wordgirl",
3638
+ "artillery",
3639
+ "exist",
3640
+ "breathtaking",
3641
+ "cannonball",
3642
+ "beanbag",
3643
+ "pinatum",
3644
+ "boosie",
3645
+ "valence",
3646
+ "nucleu",
3647
+ "electron",
3648
+ "argon",
3649
+ "clarinet",
3650
+ "shiver",
3651
+ "mattres",
3652
+ "moschimo",
3653
+ "togetum",
3654
+ "misty",
3655
+ "impres",
3656
+ "manican",
3657
+ "anaconda",
3658
+ "hoax",
3659
+ "boa",
3660
+ "scorpio",
3661
+ "wheeler",
3662
+ "career",
3663
+ "aldy",
3664
+ "charlotte",
3665
+ "thumb",
3666
+ "trinity",
3667
+ "wag",
3668
+ "shelter",
3669
+ "register",
3670
+ "trapeze",
3671
+ "stopwatch",
3672
+ "trapeeze",
3673
+ "spot",
3674
+ "strike",
3675
+ "maker",
3676
+ "smooth",
3677
+ "hay",
3678
+ "stall",
3679
+ "bang",
3680
+ "emotion",
3681
+ "dragnet",
3682
+ "appoint",
3683
+ "crib",
3684
+ "penguin",
3685
+ "cadillac",
3686
+ "sneak",
3687
+ "classrooom",
3688
+ "pause",
3689
+ "cane",
3690
+ "bbqing",
3691
+ "digging",
3692
+ "com",
3693
+ "graze",
3694
+ "console",
3695
+ "cucumber",
3696
+ "editing",
3697
+ "illustration",
3698
+ "snakeskin",
3699
+ "handmade",
3700
+ "amongst",
3701
+ "locality",
3702
+ "choke",
3703
+ "conception",
3704
+ "custom",
3705
+ "pewd",
3706
+ "pewdiepie",
3707
+ "muck",
3708
+ "monica",
3709
+ "undertake",
3710
+ "voltage",
3711
+ "dehydration",
3712
+ "sponsor",
3713
+ "indicate",
3714
+ "surfing",
3715
+ "cargo",
3716
+ "pimp",
3717
+ "barbeque",
3718
+ "hearthstone",
3719
+ "cherokee",
3720
+ "minnie",
3721
+ "fluffy",
3722
+ "sportswoman",
3723
+ "soul",
3724
+ "curl",
3725
+ "tag",
3726
+ "lure",
3727
+ "gilr",
3728
+ "brazier",
3729
+ "bra",
3730
+ "judgement",
3731
+ "somemovie",
3732
+ "terminator",
3733
+ "extend",
3734
+ "washing",
3735
+ "blank",
3736
+ "athelete",
3737
+ "marshawn",
3738
+ "shove",
3739
+ "fighting",
3740
+ "seal",
3741
+ "sight",
3742
+ "developmet",
3743
+ "ipad",
3744
+ "jerry",
3745
+ "investment",
3746
+ "whitney",
3747
+ "madison",
3748
+ "climate",
3749
+ "aviation",
3750
+ "froot",
3751
+ "hallelujah",
3752
+ "anchorman",
3753
+ "inspection",
3754
+ "switch",
3755
+ "microscope",
3756
+ "hocky",
3757
+ "monopoly",
3758
+ "electricity",
3759
+ "spark",
3760
+ "placement",
3761
+ "sleeping",
3762
+ "rubick",
3763
+ "tattoo",
3764
+ "canva",
3765
+ "snatch",
3766
+ "pitt",
3767
+ "daydream",
3768
+ "disturbing",
3769
+ "hypnotist",
3770
+ "wan",
3771
+ "commander",
3772
+ "jawsome",
3773
+ "forza",
3774
+ "lui",
3775
+ "prey",
3776
+ "burrow",
3777
+ "backside",
3778
+ "saw",
3779
+ "account",
3780
+ "trash",
3781
+ "freeform",
3782
+ "poker",
3783
+ "ochocinco",
3784
+ "espn",
3785
+ "pronounce",
3786
+ "join",
3787
+ "territory",
3788
+ "stunt",
3789
+ "mikey",
3790
+ "tug",
3791
+ "tugowar",
3792
+ "bloom",
3793
+ "breeze",
3794
+ "champaka",
3795
+ "greenery",
3796
+ "cycyle",
3797
+ "goliath",
3798
+ "spit",
3799
+ "cermony",
3800
+ "bestow",
3801
+ "meditate",
3802
+ "alloy",
3803
+ "rim",
3804
+ "wonder",
3805
+ "cihldren",
3806
+ "firehouse",
3807
+ "croquette",
3808
+ "skirt",
3809
+ "sheff",
3810
+ "dungenes",
3811
+ "calico",
3812
+ "mistres",
3813
+ "secssion",
3814
+ "dicaprio",
3815
+ "dhoni",
3816
+ "toyotum",
3817
+ "hope",
3818
+ "unrest",
3819
+ "boyband",
3820
+ "lock",
3821
+ "executioner",
3822
+ "bystander",
3823
+ "execution",
3824
+ "south",
3825
+ "robin",
3826
+ "defense",
3827
+ "protective",
3828
+ "mnay",
3829
+ "chomp",
3830
+ "anatomy",
3831
+ "dissect",
3832
+ "exhibition",
3833
+ "jeremy",
3834
+ "cocktail",
3835
+ "downey",
3836
+ "adjustment",
3837
+ "kickball",
3838
+ "knuckleball",
3839
+ "advise",
3840
+ "server",
3841
+ "entree",
3842
+ "sirector",
3843
+ "amazing",
3844
+ "bonu",
3845
+ "diddy",
3846
+ "tabletop",
3847
+ "sopmeone",
3848
+ "wax",
3849
+ "removal",
3850
+ "forearm",
3851
+ "walkthrough",
3852
+ "biking",
3853
+ "vitamin",
3854
+ "choclate",
3855
+ "refridegerator",
3856
+ "protein",
3857
+ "islamophobium",
3858
+ "pact",
3859
+ "gabriel",
3860
+ "pongal",
3861
+ "downloading",
3862
+ "over-emphasizing",
3863
+ "harmony",
3864
+ "housing",
3865
+ "chubby",
3866
+ "calmly",
3867
+ "oxygen",
3868
+ "underwater",
3869
+ "gorge",
3870
+ "thick",
3871
+ "diner",
3872
+ "suitcase",
3873
+ "breifcase",
3874
+ "submarine",
3875
+ "pressure",
3876
+ "yoga",
3877
+ "carter",
3878
+ "flap",
3879
+ "parkor",
3880
+ "spare",
3881
+ "bowling",
3882
+ "bowler",
3883
+ "comdey",
3884
+ "slopestyle",
3885
+ "section",
3886
+ "promo",
3887
+ "mathew",
3888
+ "spacecraft",
3889
+ "mcconaughy",
3890
+ "bonfire",
3891
+ "bonefire",
3892
+ "brake",
3893
+ "carbreak",
3894
+ "rotor",
3895
+ "recipie",
3896
+ "stimulate",
3897
+ "europe",
3898
+ "groundwater",
3899
+ "outer",
3900
+ "seep",
3901
+ "widow",
3902
+ "johansson",
3903
+ "ten",
3904
+ "vessel",
3905
+ "germany",
3906
+ "labor",
3907
+ "gauge",
3908
+ "garnish",
3909
+ "biker",
3910
+ "pore",
3911
+ "recepie",
3912
+ "mspaint",
3913
+ "furry",
3914
+ "inch",
3915
+ "worm",
3916
+ "caterpillar",
3917
+ "wate",
3918
+ "hula",
3919
+ "footnall",
3920
+ "compose",
3921
+ "saddle",
3922
+ "trot",
3923
+ "backboard",
3924
+ "dwight",
3925
+ "bus",
3926
+ "neighborhood",
3927
+ "schoolbu",
3928
+ "prince",
3929
+ "bambi",
3930
+ "banana",
3931
+ "ulton",
3932
+ "crossbar",
3933
+ "typewriter",
3934
+ "trio",
3935
+ "ufc",
3936
+ "frypan",
3937
+ "consumer",
3938
+ "snuggle",
3939
+ "industrialist",
3940
+ "cramer",
3941
+ "mpv",
3942
+ "spokesman",
3943
+ "toast",
3944
+ "motherboard",
3945
+ "surprise",
3946
+ "improvisation",
3947
+ "perosn",
3948
+ "acrobat",
3949
+ "lobster",
3950
+ "stain",
3951
+ "beige",
3952
+ "year",
3953
+ "blackberry",
3954
+ "storyline",
3955
+ "walking",
3956
+ "beeker",
3957
+ "beaker",
3958
+ "solution",
3959
+ "derrick",
3960
+ "unicycle",
3961
+ "loiter",
3962
+ "bose",
3963
+ "funny",
3964
+ "desktop",
3965
+ "mac",
3966
+ "crossing",
3967
+ "recording",
3968
+ "apology",
3969
+ "bunker",
3970
+ "argentina",
3971
+ "paw",
3972
+ "displaying",
3973
+ "batterie",
3974
+ "propeller",
3975
+ "clockwise",
3976
+ "costar",
3977
+ "decease",
3978
+ "lsd",
3979
+ "mating",
3980
+ "hump",
3981
+ "copulate",
3982
+ "doom",
3983
+ "chemical",
3984
+ "whelm",
3985
+ "proposal",
3986
+ "tabletenni",
3987
+ "breath",
3988
+ "hemsworth",
3989
+ "acting",
3990
+ "helmsworth",
3991
+ "twin",
3992
+ "pertain",
3993
+ "intensity",
3994
+ "fork",
3995
+ "cower",
3996
+ "insect",
3997
+ "nerd",
3998
+ "disappointment",
3999
+ "zip",
4000
+ "network",
4001
+ "collaboration",
4002
+ "anyone",
4003
+ "communication",
4004
+ "hai",
4005
+ "aisain",
4006
+ "raid",
4007
+ "dustbin",
4008
+ "dumpster",
4009
+ "mailbox",
4010
+ "aerobic",
4011
+ "canyon",
4012
+ "cody",
4013
+ "analyze",
4014
+ "vapor",
4015
+ "roacket",
4016
+ "micky",
4017
+ "fairie",
4018
+ "lamb",
4019
+ "nursery",
4020
+ "initiative",
4021
+ "precision",
4022
+ "photoshoot",
4023
+ "genital",
4024
+ "narrarator",
4025
+ "sygornie",
4026
+ "sigourney",
4027
+ "re-enacting",
4028
+ "pikini",
4029
+ "beggar",
4030
+ "lend",
4031
+ "throne",
4032
+ "monarchy",
4033
+ "grace",
4034
+ "daisy",
4035
+ "twain",
4036
+ "produce",
4037
+ "peal",
4038
+ "moto",
4039
+ "wreck",
4040
+ "mcdonald",
4041
+ "roaed",
4042
+ "darken",
4043
+ "dressing",
4044
+ "reno",
4045
+ "len",
4046
+ "groin",
4047
+ "eavesdrop",
4048
+ "eavesdropping",
4049
+ "distraught",
4050
+ "dispenser",
4051
+ "exhilarate",
4052
+ "exhilarating",
4053
+ "designate",
4054
+ "programming",
4055
+ "globalization",
4056
+ "astage",
4057
+ "lip",
4058
+ "foodball",
4059
+ "phrenology",
4060
+ "phremology",
4061
+ "america",
4062
+ "hitler",
4063
+ "discrimination",
4064
+ "racism",
4065
+ "houser",
4066
+ "pragmatism",
4067
+ "swimmer",
4068
+ "hank",
4069
+ "medication",
4070
+ "prescription",
4071
+ "transport",
4072
+ "adulthood",
4073
+ "nightclub",
4074
+ "wig",
4075
+ "overlay",
4076
+ "meter",
4077
+ "800",
4078
+ "footrace",
4079
+ "siphon",
4080
+ "firmware",
4081
+ "seagull",
4082
+ "importance",
4083
+ "accompany",
4084
+ "eight",
4085
+ "husband",
4086
+ "replacement",
4087
+ "machince",
4088
+ "uner",
4089
+ "bronze",
4090
+ "trim",
4091
+ "laser",
4092
+ "restarunt",
4093
+ "stucture",
4094
+ "surgeon",
4095
+ "nanny",
4096
+ "misbehave",
4097
+ "floating",
4098
+ "mule",
4099
+ "hamburger",
4100
+ "iowa",
4101
+ "lowa",
4102
+ "brief",
4103
+ "cleanong",
4104
+ "solo",
4105
+ "tar",
4106
+ "homemade",
4107
+ "winston",
4108
+ "peole",
4109
+ "agreement",
4110
+ "unemployment",
4111
+ "baton",
4112
+ "woody",
4113
+ "costumer",
4114
+ "literature",
4115
+ "campaigning",
4116
+ "presidency",
4117
+ "refuse",
4118
+ "courier",
4119
+ "beat-boxing",
4120
+ "fillet",
4121
+ "relay",
4122
+ "ping",
4123
+ "request",
4124
+ "kircher",
4125
+ "tim",
4126
+ "convulse",
4127
+ "assail",
4128
+ "intrude",
4129
+ "gourmet",
4130
+ "gingerbread",
4131
+ "recode",
4132
+ "foreground",
4133
+ "ditch",
4134
+ "playdoh",
4135
+ "dexter",
4136
+ "char",
4137
+ "daryl",
4138
+ "showcase",
4139
+ "mand",
4140
+ "abot",
4141
+ "cheery",
4142
+ "sunstance",
4143
+ "album",
4144
+ "fireplace",
4145
+ "resistance",
4146
+ "bga",
4147
+ "larry",
4148
+ "tune",
4149
+ "geographic",
4150
+ "spiel",
4151
+ "alternator",
4152
+ "installing",
4153
+ "brag",
4154
+ "berate",
4155
+ "womanb",
4156
+ "bumper",
4157
+ "dent",
4158
+ "prus",
4159
+ "daylight",
4160
+ "natuiralist",
4161
+ "halloween",
4162
+ "sirloin",
4163
+ "pinocchio",
4164
+ "bussaly",
4165
+ "contmy",
4166
+ "foosball",
4167
+ "cocoon",
4168
+ "burqa",
4169
+ "impersonate",
4170
+ "fingure",
4171
+ "primer",
4172
+ "carson",
4173
+ "feeding",
4174
+ "parent"
4175
+ ]
ChatUniVi/eval/questions/video_qa/msrvtt_qa.json ADDED
The diff for this file is too large to render. See raw diff
 
ChatUniVi/eval/questions/video_qa/msvd_a_list.json ADDED
@@ -0,0 +1,1202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "someone",
3
+ "rifle",
4
+ "man",
5
+ "box",
6
+ "gun",
7
+ "person",
8
+ "weapon",
9
+ "contain",
10
+ "opine",
11
+ "show",
12
+ "sword",
13
+ "boy",
14
+ "kid",
15
+ "fight",
16
+ "twirl",
17
+ "put",
18
+ "demonstrate",
19
+ "dance",
20
+ "practice",
21
+ "two",
22
+ "gras",
23
+ "demonstration",
24
+ "karate",
25
+ "perform",
26
+ "path",
27
+ "wildernes",
28
+ "trail",
29
+ "road",
30
+ "style",
31
+ "lane",
32
+ "actor",
33
+ "walk",
34
+ "eagle",
35
+ "motion",
36
+ "hare",
37
+ "rabbit",
38
+ "bird",
39
+ "bunny",
40
+ "field",
41
+ "dodge",
42
+ "try",
43
+ "chase",
44
+ "water",
45
+ "cliff",
46
+ "river",
47
+ "ocean",
48
+ "rock",
49
+ "dive",
50
+ "jump",
51
+ "crust",
52
+ "dough",
53
+ "chef",
54
+ "cook",
55
+ "lay",
56
+ "spread",
57
+ "unroll",
58
+ "cut",
59
+ "roll",
60
+ "guitar",
61
+ "play",
62
+ "cat",
63
+ "dog",
64
+ "bite",
65
+ "break",
66
+ "burst",
67
+ "pop",
68
+ "attack",
69
+ "girl",
70
+ "ball",
71
+ "toddler",
72
+ "baby",
73
+ "yard",
74
+ "animal",
75
+ "throw",
76
+ "motorcycle",
77
+ "ground",
78
+ "bike",
79
+ "stunt",
80
+ "wheel",
81
+ "motorcyle",
82
+ "guy",
83
+ "motorbike",
84
+ "minibike",
85
+ "wheelie",
86
+ "dachshund",
87
+ "pool",
88
+ "swim",
89
+ "stage",
90
+ "concert",
91
+ "jeff",
92
+ "pyramid",
93
+ "school",
94
+ "form",
95
+ "kneel",
96
+ "climb",
97
+ "build",
98
+ "target",
99
+ "pistol",
100
+ "machine",
101
+ "glock",
102
+ "fire",
103
+ "shoot",
104
+ "stand",
105
+ "woman",
106
+ "knife",
107
+ "vegetable",
108
+ "lady",
109
+ "leafy",
110
+ "parsley",
111
+ "herb",
112
+ "coriander",
113
+ "chop",
114
+ "garlic",
115
+ "turnip",
116
+ "bowl",
117
+ "root",
118
+ "plant",
119
+ "pull",
120
+ "clean",
121
+ "mushroom",
122
+ "tapioca",
123
+ "cauliflower",
124
+ "food",
125
+ "dice",
126
+ "use",
127
+ "slouse",
128
+ "mall",
129
+ "jean",
130
+ "airport",
131
+ "onion",
132
+ "phone",
133
+ "telephone",
134
+ "hang",
135
+ "speak",
136
+ "talk",
137
+ "hold",
138
+ "hand",
139
+ "arm",
140
+ "star",
141
+ "shin",
142
+ "gaze",
143
+ "reach",
144
+ "stretch",
145
+ "watch",
146
+ "guinea",
147
+ "lettuce",
148
+ "vegetation",
149
+ "eat",
150
+ "tree",
151
+ "rain",
152
+ "polouse",
153
+ "vehicle",
154
+ "car",
155
+ "highway",
156
+ "maneuver",
157
+ "driver",
158
+ "cop",
159
+ "evade",
160
+ "force",
161
+ "pit",
162
+ "shrimp",
163
+ "shell",
164
+ "peel",
165
+ "prepare",
166
+ "prawn",
167
+ "fish",
168
+ "seafood",
169
+ "worm",
170
+ "tail",
171
+ "stuff",
172
+ "seasoning",
173
+ "starch",
174
+ "cover",
175
+ "season",
176
+ "leek",
177
+ "fruit",
178
+ "leak",
179
+ "somoene",
180
+ "batter",
181
+ "substance",
182
+ "flmy",
183
+ "flower",
184
+ "mix",
185
+ "pmy",
186
+ "brush",
187
+ "tempura",
188
+ "coat",
189
+ "spice",
190
+ "butter",
191
+ "fry",
192
+ "meat",
193
+ "dip",
194
+ "place",
195
+ "bread",
196
+ "oil",
197
+ "pot",
198
+ "something",
199
+ "mitsuba",
200
+ "frying",
201
+ "tray",
202
+ "grill",
203
+ "liquid",
204
+ "stir",
205
+ "cilantro",
206
+ "udon",
207
+ "pastum",
208
+ "boil",
209
+ "foodstuff",
210
+ "biscuit",
211
+ "sushi",
212
+ "wrapper",
213
+ "cheese",
214
+ "kamaboko",
215
+ "package",
216
+ "unwrap",
217
+ "wood",
218
+ "pink",
219
+ "cake",
220
+ "purple",
221
+ "kamakodo",
222
+ "lemon",
223
+ "rind",
224
+ "piece",
225
+ "skin",
226
+ "orange",
227
+ "container",
228
+ "hydrate",
229
+ "date",
230
+ "shiitake",
231
+ "fig",
232
+ "cros",
233
+ "somene",
234
+ "thing",
235
+ "score",
236
+ "broth",
237
+ "saute",
238
+ "drive",
239
+ "violin",
240
+ "microphone",
241
+ "instrument",
242
+ "fiddle",
243
+ "pluck",
244
+ "steak",
245
+ "pork",
246
+ "poke",
247
+ "pierce",
248
+ "pepper",
249
+ "sprinkle",
250
+ "plate",
251
+ "egg",
252
+ "dish",
253
+ "drop",
254
+ "street",
255
+ "motocycle",
256
+ "motor",
257
+ "lie",
258
+ "pitcher",
259
+ "soda",
260
+ "juic",
261
+ "juice",
262
+ "mixture",
263
+ "jug",
264
+ "jar",
265
+ "cucumber",
266
+ "glas",
267
+ "drinking",
268
+ "drink",
269
+ "four",
270
+ "explosion",
271
+ "blast",
272
+ "blow",
273
+ "burn",
274
+ "couch",
275
+ "sit",
276
+ "sleeping",
277
+ "groom",
278
+ "lick",
279
+ "superman",
280
+ "superhero",
281
+ "door",
282
+ "superhuman",
283
+ "giant",
284
+ "character",
285
+ "move",
286
+ "push",
287
+ "lift",
288
+ "individual",
289
+ "dirt",
290
+ "biker",
291
+ "bump",
292
+ "air",
293
+ "cycle",
294
+ "fly",
295
+ "bed",
296
+ "nap",
297
+ "sleep",
298
+ "wake",
299
+ "waken",
300
+ "hammer",
301
+ "thumb",
302
+ "finger",
303
+ "hit",
304
+ "smash",
305
+ "rope",
306
+ "walkway",
307
+ "pathway",
308
+ "house",
309
+ "skip",
310
+ "jumproping",
311
+ "jockey",
312
+ "horse",
313
+ "perimeter",
314
+ "stadium",
315
+ "ring",
316
+ "arena",
317
+ "competition",
318
+ "wrestle",
319
+ "cockfight",
320
+ "trumpet",
321
+ "club",
322
+ "song",
323
+ "menacing",
324
+ "clown",
325
+ "band",
326
+ "menace",
327
+ "look",
328
+ "beef",
329
+ "fat",
330
+ "roast",
331
+ "trim",
332
+ "bowler",
333
+ "split",
334
+ "bowling",
335
+ "remain",
336
+ "board",
337
+ "flip",
338
+ "doctor",
339
+ "emergency",
340
+ "chest",
341
+ "patient",
342
+ "gurney",
343
+ "hospital",
344
+ "die",
345
+ "bleed",
346
+ "help",
347
+ "content",
348
+ "chili",
349
+ "tin",
350
+ "dump",
351
+ "mixer",
352
+ "blender",
353
+ "cream",
354
+ "whisk",
355
+ "knead",
356
+ "whip",
357
+ "chimpanzee",
358
+ "cigarette",
359
+ "smoking",
360
+ "monkey",
361
+ "smoke",
362
+ "room",
363
+ "christma",
364
+ "wear",
365
+ "turtle",
366
+ "tortoise",
367
+ "hunt",
368
+ "ice",
369
+ "skate",
370
+ "sandwich",
371
+ "mayonnaise",
372
+ "equipment",
373
+ "mechanic",
374
+ "speaker",
375
+ "loudspeaker",
376
+ "join",
377
+ "portion",
378
+ "outer",
379
+ "clove",
380
+ "peal",
381
+ "mince",
382
+ "capsicum",
383
+ "bell",
384
+ "center",
385
+ "whole",
386
+ "half",
387
+ "apple",
388
+ "wall",
389
+ "building",
390
+ "picture",
391
+ "camera",
392
+ "photograph",
393
+ "milk",
394
+ "sauce",
395
+ "football",
396
+ "soccer",
397
+ "otter",
398
+ "beaver",
399
+ "slide",
400
+ "mango",
401
+ "avocado",
402
+ "lengthwise",
403
+ "squash",
404
+ "chew",
405
+ "mes",
406
+ "tease",
407
+ "gnaw",
408
+ "sniff",
409
+ "grocery",
410
+ "stroller",
411
+ "pram",
412
+ "store",
413
+ "supermarket",
414
+ "cart",
415
+ "bay",
416
+ "pay",
417
+ "forest",
418
+ "deer",
419
+ "pas",
420
+ "roam",
421
+ "head",
422
+ "side",
423
+ "stove",
424
+ "skillet",
425
+ "sizzle",
426
+ "machinthi",
427
+ "kanu",
428
+ "hole",
429
+ "drill",
430
+ "block",
431
+ "rhino",
432
+ "rhinocero",
433
+ "grazing",
434
+ "graze",
435
+ "bush",
436
+ "hide",
437
+ "spy",
438
+ "face",
439
+ "halt",
440
+ "luggage",
441
+ "speed",
442
+ "papaya",
443
+ "carve",
444
+ "track",
445
+ "eight",
446
+ "race",
447
+ "compete",
448
+ "sprint",
449
+ "faucet",
450
+ "bath",
451
+ "sink",
452
+ "splash",
453
+ "shower",
454
+ "playing",
455
+ "trick",
456
+ "deck",
457
+ "card",
458
+ "display",
459
+ "marley",
460
+ "ride",
461
+ "orangatan",
462
+ "orangutan",
463
+ "shirt",
464
+ "strip",
465
+ "undres",
466
+ "banana",
467
+ "bottom",
468
+ "start",
469
+ "snowboarder",
470
+ "snow",
471
+ "hill",
472
+ "slope",
473
+ "mountain",
474
+ "skier",
475
+ "ski",
476
+ "snowboard",
477
+ "potato",
478
+ "potatoe",
479
+ "grate",
480
+ "foot",
481
+ "thumper",
482
+ "cartoon",
483
+ "love",
484
+ "kis",
485
+ "dres",
486
+ "costume",
487
+ "punch",
488
+ "shake",
489
+ "underwood",
490
+ "carrie",
491
+ "carpet",
492
+ "bug",
493
+ "floor",
494
+ "witha",
495
+ "paw",
496
+ "bark",
497
+ "child",
498
+ "right",
499
+ "sofa",
500
+ "crawl",
501
+ "infant",
502
+ "snuggle",
503
+ "nuzzle",
504
+ "rub",
505
+ "cares",
506
+ "kitten",
507
+ "shoestring",
508
+ "pet",
509
+ "touch",
510
+ "shih",
511
+ "settee",
512
+ "rib",
513
+ "spare",
514
+ "bone",
515
+ "rack",
516
+ "bbq",
517
+ "three",
518
+ "spar",
519
+ "helicopter",
520
+ "airplane",
521
+ "act",
522
+ "boxer",
523
+ "audience",
524
+ "routine",
525
+ "presentation",
526
+ "book",
527
+ "call",
528
+ "read",
529
+ "receive",
530
+ "attend",
531
+ "carrot",
532
+ "lori",
533
+ "sloth",
534
+ "lorus",
535
+ "paper",
536
+ "rectangular",
537
+ "tear",
538
+ "bicycle",
539
+ "primate",
540
+ "tricycle",
541
+ "coach",
542
+ "icing",
543
+ "cupcake",
544
+ "five",
545
+ "pom",
546
+ "butt",
547
+ "cheer",
548
+ "motorcyclist",
549
+ "rider",
550
+ "motorcylist",
551
+ "crash",
552
+ "fall",
553
+ "finishing",
554
+ "artist",
555
+ "pencil",
556
+ "sketch",
557
+ "draw",
558
+ "essence",
559
+ "cooking",
560
+ "corn",
561
+ "vanilla",
562
+ "drizzle",
563
+ "thick",
564
+ "loaf",
565
+ "brown",
566
+ "swat",
567
+ "beat",
568
+ "wave",
569
+ "shotgun",
570
+ "running",
571
+ "spoon",
572
+ "table",
573
+ "meal",
574
+ "din",
575
+ "curve",
576
+ "course",
577
+ "motocros",
578
+ "lake",
579
+ "swimming",
580
+ "line",
581
+ "shallot",
582
+ "foam",
583
+ "bathing",
584
+ "bettie",
585
+ "edge",
586
+ "ledge",
587
+ "singing",
588
+ "makeup",
589
+ "eyelid",
590
+ "shadow",
591
+ "liner",
592
+ "indoor",
593
+ "gear",
594
+ "scale",
595
+ "music",
596
+ "group",
597
+ "stamp",
598
+ "tomato",
599
+ "tomatoe",
600
+ "mozzarella",
601
+ "rice",
602
+ "scoop",
603
+ "lasagna",
604
+ "colander",
605
+ "simmer",
606
+ "wrestler",
607
+ "opponent",
608
+ "fighter",
609
+ "reporter",
610
+ "sandcastle",
611
+ "sand",
612
+ "castle",
613
+ "interview",
614
+ "bar",
615
+ "fence",
616
+ "horseback",
617
+ "obstacle",
618
+ "while",
619
+ "beach",
620
+ "singer",
621
+ "hitchhiking",
622
+ "hitchhiker",
623
+ "hitch",
624
+ "ask",
625
+ "hitchhike",
626
+ "eyeliner",
627
+ "outline",
628
+ "goat",
629
+ "bleat",
630
+ "tiger",
631
+ "lion",
632
+ "albino",
633
+ "cub",
634
+ "interact",
635
+ "carriage",
636
+ "family",
637
+ "trot",
638
+ "transport",
639
+ "travel",
640
+ "row",
641
+ "hedge",
642
+ "lemur",
643
+ "furry",
644
+ "weird",
645
+ "hug",
646
+ "gather",
647
+ "huddle",
648
+ "panda",
649
+ "keeper",
650
+ "bottle",
651
+ "veterinarian",
652
+ "feed",
653
+ "balance",
654
+ "scooter",
655
+ "back",
656
+ "stay",
657
+ "instruct",
658
+ "focu",
659
+ "game",
660
+ "goal",
661
+ "kick",
662
+ "shakira",
663
+ "metal",
664
+ "pillar",
665
+ "steel",
666
+ "work",
667
+ "envelope",
668
+ "xbox360",
669
+ "headset",
670
+ "mail",
671
+ "item",
672
+ "write",
673
+ "canoe",
674
+ "oanoe",
675
+ "newscaster",
676
+ "boat",
677
+ "paddle",
678
+ "sail",
679
+ "glove",
680
+ "coffee",
681
+ "cup",
682
+ "peeler",
683
+ "potoatoe",
684
+ "scrap",
685
+ "chair",
686
+ "kitchen",
687
+ "keyboard",
688
+ "synthesizer",
689
+ "piano",
690
+ "cookie",
691
+ "boarding",
692
+ "skateboard",
693
+ "cruise",
694
+ "peddle",
695
+ "flute",
696
+ "lawn",
697
+ "squirrel",
698
+ "hop",
699
+ "teenager",
700
+ "mom",
701
+ "teenage",
702
+ "carry",
703
+ "lounge",
704
+ "couple",
705
+ "video",
706
+ "girlfriend",
707
+ "conversation",
708
+ "crying",
709
+ "cry",
710
+ "mourn",
711
+ "weep",
712
+ "sob",
713
+ "grieve",
714
+ "drip",
715
+ "church",
716
+ "sunset",
717
+ "passenger",
718
+ "bcycle",
719
+ "crossbar",
720
+ "juggle",
721
+ "tos",
722
+ "soccar",
723
+ "sportsman",
724
+ "bat",
725
+ "cricket",
726
+ "error",
727
+ "cricketer",
728
+ "crowd",
729
+ "laugh",
730
+ "smile",
731
+ "dummy",
732
+ "mannequin",
733
+ "run",
734
+ "leader",
735
+ "exercise",
736
+ "chocolate",
737
+ "chocolaty",
738
+ "baker",
739
+ "wind",
740
+ "duck",
741
+ "toy",
742
+ "stream",
743
+ "creek",
744
+ "attention",
745
+ "squirt",
746
+ "lad",
747
+ "paste",
748
+ "salt",
749
+ "powder",
750
+ "dust",
751
+ "cantaloupe",
752
+ "sweet",
753
+ "pumpkin",
754
+ "cantalopue",
755
+ "sidewalk",
756
+ "sledge",
757
+ "sledgehammer",
758
+ "pick",
759
+ "tool",
760
+ "cube",
761
+ "hair",
762
+ "braid",
763
+ "bulldog",
764
+ "wad",
765
+ "fetch",
766
+ "truck",
767
+ "bumper",
768
+ "pickup",
769
+ "gazelle",
770
+ "baboon",
771
+ "antelope",
772
+ "latter",
773
+ "fawn",
774
+ "kidnap",
775
+ "charge",
776
+ "broccoli",
777
+ "rodent",
778
+ "brocoli",
779
+ "hamster",
780
+ "eye",
781
+ "eyeshadow",
782
+ "garden",
783
+ "amongst",
784
+ "stroll",
785
+ "bench",
786
+ "swing",
787
+ "leaf",
788
+ "bak",
789
+ "mouth",
790
+ "bicyclist",
791
+ "train",
792
+ "model",
793
+ "trolley",
794
+ "strike",
795
+ "vase",
796
+ "son",
797
+ "father",
798
+ "busines",
799
+ "mand",
800
+ "cleaning",
801
+ "wash",
802
+ "hoot",
803
+ "trainer",
804
+ "leg",
805
+ "teach",
806
+ "view",
807
+ "shield",
808
+ "necklace",
809
+ "husband",
810
+ "marry",
811
+ "flag",
812
+ "dinner",
813
+ "serve",
814
+ "scene",
815
+ "herself",
816
+ "background",
817
+ "carom",
818
+ "meadow",
819
+ "jungle",
820
+ "bacon",
821
+ "aluminum",
822
+ "foil",
823
+ "square",
824
+ "lamp",
825
+ "attract",
826
+ "mat",
827
+ "doorway",
828
+ "mob",
829
+ "salaryman",
830
+ "alley",
831
+ "cooked",
832
+ "rear",
833
+ "army",
834
+ "parade",
835
+ "formation",
836
+ "march",
837
+ "teacher",
838
+ "whiteboard",
839
+ "equation",
840
+ "math",
841
+ "formula",
842
+ "problem",
843
+ "solve",
844
+ "explain",
845
+ "circle",
846
+ "oven",
847
+ "bake",
848
+ "waterfall",
849
+ "island",
850
+ "creature",
851
+ "control",
852
+ "bullet",
853
+ "yellow",
854
+ "harbor",
855
+ "coast",
856
+ "speeding",
857
+ "policeman",
858
+ "officer",
859
+ "arrest",
860
+ "tie",
861
+ "handcuff",
862
+ "bikini",
863
+ "fold",
864
+ "crocodile",
865
+ "alligator",
866
+ "nose",
867
+ "pat",
868
+ "tap",
869
+ "curl",
870
+ "bodybuilder",
871
+ "weight",
872
+ "builder",
873
+ "barbell",
874
+ "night",
875
+ "dark",
876
+ "beater",
877
+ "spin",
878
+ "cage",
879
+ "zoo",
880
+ "enclosure",
881
+ "pen",
882
+ "pace",
883
+ "mammal",
884
+ "blanket",
885
+ "plastic",
886
+ "inspect",
887
+ "examine",
888
+ "bend",
889
+ "transplant",
890
+ "harvest",
891
+ "tend",
892
+ "station",
893
+ "subway",
894
+ "transit",
895
+ "disembark",
896
+ "exit",
897
+ "desk",
898
+ "rainbow",
899
+ "meow",
900
+ "nitrogen",
901
+ "liguid",
902
+ "vapor",
903
+ "steam",
904
+ "solution",
905
+ "pester",
906
+ "grab",
907
+ "funny",
908
+ "jerboa",
909
+ "chinchilla",
910
+ "mouse",
911
+ "rat",
912
+ "scurry",
913
+ "sergeant",
914
+ "seargeant",
915
+ "soldier",
916
+ "sargent",
917
+ "troop",
918
+ "commander",
919
+ "voice",
920
+ "tapir",
921
+ "branch",
922
+ "aardvark",
923
+ "search",
924
+ "forage",
925
+ "training",
926
+ "puff",
927
+ "squeeze",
928
+ "juicing",
929
+ "extract",
930
+ "strum",
931
+ "pizza",
932
+ "enjoy",
933
+ "ukulele",
934
+ "drunk",
935
+ "post",
936
+ "pavement",
937
+ "sieve",
938
+ "somone",
939
+ "strainer",
940
+ "miniature",
941
+ "coconut",
942
+ "drain",
943
+ "armchair",
944
+ "shirtles",
945
+ "richard",
946
+ "shilpa",
947
+ "wag",
948
+ "beachside",
949
+ "lead",
950
+ "cheff",
951
+ "tower",
952
+ "shape",
953
+ "pile",
954
+ "stack",
955
+ "quadropod",
956
+ "photo",
957
+ "photographer",
958
+ "tripod",
959
+ "spike",
960
+ "lug",
961
+ "mud",
962
+ "bear",
963
+ "digging",
964
+ "dig",
965
+ "scratch",
966
+ "garage",
967
+ "enter",
968
+ "shopping",
969
+ "shop",
970
+ "browse",
971
+ "toad",
972
+ "puddle",
973
+ "town",
974
+ "neighborhood",
975
+ "desert",
976
+ "steer",
977
+ "float",
978
+ "floater",
979
+ "raft",
980
+ "parrot",
981
+ "tabletop",
982
+ "beak",
983
+ "mug",
984
+ "discussion",
985
+ "discus",
986
+ "summersault",
987
+ "axe",
988
+ "bun",
989
+ "hamburger",
990
+ "sweeper",
991
+ "vacuum",
992
+ "chicken",
993
+ "shore",
994
+ "step",
995
+ "dancing",
996
+ "elephant",
997
+ "stick",
998
+ "twig",
999
+ "stem",
1000
+ "bamboo",
1001
+ "rest",
1002
+ "dvd",
1003
+ "disc",
1004
+ "disk",
1005
+ "wipe",
1006
+ "dab",
1007
+ "fix",
1008
+ "synchronization",
1009
+ "bedroom",
1010
+ "noise",
1011
+ "frog",
1012
+ "catch",
1013
+ "handle",
1014
+ "armles",
1015
+ "puppet",
1016
+ "string",
1017
+ "marionette",
1018
+ "seat",
1019
+ "leap",
1020
+ "bounce",
1021
+ "zebra",
1022
+ "nudge",
1023
+ "stroke",
1024
+ "bathroom",
1025
+ "nicholson",
1026
+ "attendant",
1027
+ "jacket",
1028
+ "park",
1029
+ "coaster",
1030
+ "jet",
1031
+ "plane",
1032
+ "runway",
1033
+ "land",
1034
+ "slicer",
1035
+ "mandolin",
1036
+ "ionion",
1037
+ "cowboy",
1038
+ "vampire",
1039
+ "monster",
1040
+ "intruder",
1041
+ "poeple",
1042
+ "submarine",
1043
+ "ship",
1044
+ "missile",
1045
+ "shuttle",
1046
+ "space",
1047
+ "bomb",
1048
+ "glide",
1049
+ "beer",
1050
+ "midget",
1051
+ "somebody",
1052
+ "goblet",
1053
+ "guiter",
1054
+ "pole",
1055
+ "fishing",
1056
+ "shave",
1057
+ "mirror",
1058
+ "image",
1059
+ "reflection",
1060
+ "shark",
1061
+ "dolphin",
1062
+ "fisherman",
1063
+ "bait",
1064
+ "steal",
1065
+ "measure",
1066
+ "surprise",
1067
+ "jut",
1068
+ "defecate",
1069
+ "skateboarder",
1070
+ "ramp",
1071
+ "tunnel",
1072
+ "mower",
1073
+ "mover",
1074
+ "mow",
1075
+ "lawnmower",
1076
+ "booty",
1077
+ "lucy",
1078
+ "animator",
1079
+ "butterfly",
1080
+ "switch",
1081
+ "twist",
1082
+ "treadmill",
1083
+ "twisting",
1084
+ "attempt",
1085
+ "halloween",
1086
+ "jaw",
1087
+ "skull",
1088
+ "mimic",
1089
+ "provide",
1090
+ "gravel",
1091
+ "floyd",
1092
+ "gilmmy",
1093
+ "ban",
1094
+ "tiller",
1095
+ "soil",
1096
+ "auger",
1097
+ "till",
1098
+ "bot",
1099
+ "powerboat",
1100
+ "yacht",
1101
+ "sea",
1102
+ "traverse",
1103
+ "bull",
1104
+ "peach",
1105
+ "avoid",
1106
+ "halve",
1107
+ "combine",
1108
+ "wooden",
1109
+ "concrete",
1110
+ "cement",
1111
+ "brick",
1112
+ "stomach",
1113
+ "bust",
1114
+ "boxing",
1115
+ "yoga",
1116
+ "meditate",
1117
+ "pray",
1118
+ "clay",
1119
+ "piggyback",
1120
+ "platform",
1121
+ "body",
1122
+ "weigt",
1123
+ "weightlift",
1124
+ "stenographer",
1125
+ "stenograph",
1126
+ "stenography",
1127
+ "type",
1128
+ "cleaver",
1129
+ "capuchin",
1130
+ "itch",
1131
+ "way",
1132
+ "moose",
1133
+ "sprinkler",
1134
+ "wet",
1135
+ "fore",
1136
+ "moonwalk",
1137
+ "hiking",
1138
+ "reaper",
1139
+ "skeleton",
1140
+ "hike",
1141
+ "welsh",
1142
+ "scuffle",
1143
+ "frolic",
1144
+ "cab",
1145
+ "taxi",
1146
+ "argue",
1147
+ "front",
1148
+ "jumper",
1149
+ "trampoline",
1150
+ "pounce",
1151
+ "cell",
1152
+ "prisoner",
1153
+ "middle",
1154
+ "prison",
1155
+ "jail",
1156
+ "figure",
1157
+ "intimidate",
1158
+ "belly",
1159
+ "bridge",
1160
+ "hanging",
1161
+ "swinging",
1162
+ "hedgehog",
1163
+ "porcupine",
1164
+ "spinner",
1165
+ "bagel",
1166
+ "recite",
1167
+ "slap",
1168
+ "letter",
1169
+ "range",
1170
+ "spray",
1171
+ "retain",
1172
+ "pilot",
1173
+ "handshake",
1174
+ "offer",
1175
+ "hose",
1176
+ "friend",
1177
+ "instructor",
1178
+ "arrange",
1179
+ "oxiclean",
1180
+ "detergent",
1181
+ "cleaner",
1182
+ "fill",
1183
+ "tea",
1184
+ "basket",
1185
+ "suck",
1186
+ "sip",
1187
+ "suckle",
1188
+ "carnival",
1189
+ "coupon",
1190
+ "ticket",
1191
+ "trunk",
1192
+ "log",
1193
+ "golf",
1194
+ "golfing",
1195
+ "bathtub",
1196
+ "tub",
1197
+ "batting",
1198
+ "knock",
1199
+ "stretcher",
1200
+ "stairmaster",
1201
+ "operate"
1202
+ ]
ChatUniVi/mm_utils.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image
2
+ from io import BytesIO
3
+ import base64
4
+
5
+ import torch
6
+ from transformers import StoppingCriteria
7
+ from ChatUniVi.constants import IMAGE_TOKEN_INDEX
8
+
9
+
10
+ def load_image_from_base64(image):
11
+ return Image.open(BytesIO(base64.b64decode(image)))
12
+
13
+
14
+ def process_images(images, image_processor, model_cfg):
15
+ return image_processor(images, return_tensors='pt')['pixel_values']
16
+
17
+
18
+ def tokenizer_image_token(prompt, tokenizer, image_token_index=IMAGE_TOKEN_INDEX, return_tensors=None):
19
+ prompt_chunks = [tokenizer(chunk).input_ids for chunk in prompt.split('<image>')]
20
+
21
+ def insert_separator(X, sep):
22
+ return [ele for sublist in zip(X, [sep]*len(X)) for ele in sublist][:-1]
23
+
24
+ input_ids = []
25
+ offset = 0
26
+ if len(prompt_chunks) > 0 and len(prompt_chunks[0]) > 0 and prompt_chunks[0][0] == tokenizer.bos_token_id:
27
+ offset = 1
28
+ input_ids.append(prompt_chunks[0][0])
29
+
30
+ for x in insert_separator(prompt_chunks, [image_token_index] * (offset + 1)):
31
+ input_ids.extend(x[offset:])
32
+
33
+ if return_tensors is not None:
34
+ if return_tensors == 'pt':
35
+ return torch.tensor(input_ids, dtype=torch.long)
36
+ raise ValueError(f'Unsupported tensor type: {return_tensors}')
37
+
38
+ return input_ids
39
+
40
+
41
+ def get_model_name_from_path(model_path):
42
+ model_path = model_path.strip("/")
43
+ model_paths = model_path.split("/")
44
+ if model_paths[-1].startswith('checkpoint-'):
45
+ return model_paths[-2] + "_" + model_paths[-1]
46
+ else:
47
+ return model_paths[-1]
48
+
49
+
50
+ class KeywordsStoppingCriteria(StoppingCriteria):
51
+ def __init__(self, keywords, tokenizer, input_ids):
52
+ self.keywords = keywords
53
+ self.keyword_ids = []
54
+ for keyword in keywords:
55
+ cur_keyword_ids = tokenizer(keyword).input_ids
56
+ if len(cur_keyword_ids) > 1 and cur_keyword_ids[0] == tokenizer.bos_token_id:
57
+ cur_keyword_ids = cur_keyword_ids[1:]
58
+ self.keyword_ids.append(torch.tensor(cur_keyword_ids))
59
+ self.tokenizer = tokenizer
60
+ self.start_len = input_ids.shape[1]
61
+
62
+ def __call__(self, output_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
63
+ assert output_ids.shape[0] == 1, "Only support batch size 1 (yet)" # TODO
64
+ offset = min(output_ids.shape[1] - self.start_len, 3)
65
+ self.keyword_ids = [keyword_id.to(output_ids.device) for keyword_id in self.keyword_ids]
66
+ for keyword_id in self.keyword_ids:
67
+ if output_ids[0, -keyword_id.shape[0]:] == keyword_id:
68
+ return True
69
+ outputs = self.tokenizer.batch_decode(output_ids[:, -offset:], skip_special_tokens=True)[0]
70
+ for keyword in self.keywords:
71
+ if keyword in outputs:
72
+ return True
73
+ return False
ChatUniVi/utils.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ import logging
3
+ import logging.handlers
4
+ import os
5
+ import sys
6
+
7
+ import requests
8
+
9
+ from ChatUniVi.constants import LOGDIR
10
+
11
+ server_error_msg = "**NETWORK ERROR DUE TO HIGH TRAFFIC. PLEASE REGENERATE OR REFRESH THIS PAGE.**"
12
+ moderation_msg = "YOUR INPUT VIOLATES OUR CONTENT MODERATION GUIDELINES. PLEASE TRY AGAIN."
13
+
14
+ handler = None
15
+
16
+
17
+ def build_logger(logger_name, logger_filename):
18
+ global handler
19
+
20
+ formatter = logging.Formatter(
21
+ fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
22
+ datefmt="%Y-%m-%d %H:%M:%S",
23
+ )
24
+
25
+ # Set the format of root handlers
26
+ if not logging.getLogger().handlers:
27
+ logging.basicConfig(level=logging.INFO)
28
+ logging.getLogger().handlers[0].setFormatter(formatter)
29
+
30
+ # Redirect stdout and stderr to loggers
31
+ stdout_logger = logging.getLogger("stdout")
32
+ stdout_logger.setLevel(logging.INFO)
33
+ sl = StreamToLogger(stdout_logger, logging.INFO)
34
+ sys.stdout = sl
35
+
36
+ stderr_logger = logging.getLogger("stderr")
37
+ stderr_logger.setLevel(logging.ERROR)
38
+ sl = StreamToLogger(stderr_logger, logging.ERROR)
39
+ sys.stderr = sl
40
+
41
+ # Get logger
42
+ logger = logging.getLogger(logger_name)
43
+ logger.setLevel(logging.INFO)
44
+
45
+ # Add a file handler for all loggers
46
+ if handler is None:
47
+ os.makedirs(LOGDIR, exist_ok=True)
48
+ filename = os.path.join(LOGDIR, logger_filename)
49
+ handler = logging.handlers.TimedRotatingFileHandler(
50
+ filename, when='D', utc=True)
51
+ handler.setFormatter(formatter)
52
+
53
+ for name, item in logging.root.manager.loggerDict.items():
54
+ if isinstance(item, logging.Logger):
55
+ item.addHandler(handler)
56
+
57
+ return logger
58
+
59
+
60
+ class StreamToLogger(object):
61
+ """
62
+ Fake file-like stream object that redirects writes to a logger instance.
63
+ """
64
+ def __init__(self, logger, log_level=logging.INFO):
65
+ self.terminal = sys.stdout
66
+ self.logger = logger
67
+ self.log_level = log_level
68
+ self.linebuf = ''
69
+
70
+ def __getattr__(self, attr):
71
+ return getattr(self.terminal, attr)
72
+
73
+ def write(self, buf):
74
+ temp_linebuf = self.linebuf + buf
75
+ self.linebuf = ''
76
+ for line in temp_linebuf.splitlines(True):
77
+ # From the io.TextIOWrapper docs:
78
+ # On output, if newline is None, any '\n' characters written
79
+ # are translated to the system default line separator.
80
+ # By default sys.stdout.write() expects '\n' newlines and then
81
+ # translates them so this is still cross platform.
82
+ if line[-1] == '\n':
83
+ self.logger.log(self.log_level, line.rstrip())
84
+ else:
85
+ self.linebuf += line
86
+
87
+ def flush(self):
88
+ if self.linebuf != '':
89
+ self.logger.log(self.log_level, self.linebuf.rstrip())
90
+ self.linebuf = ''
91
+
92
+
93
+ def disable_torch_init():
94
+ """
95
+ Disable the redundant torch default initialization to accelerate model creation.
96
+ """
97
+ import torch
98
+ setattr(torch.nn.Linear, "reset_parameters", lambda self: None)
99
+ setattr(torch.nn.LayerNorm, "reset_parameters", lambda self: None)
100
+
101
+
102
+ def violates_moderation(text):
103
+ """
104
+ Check whether the text violates OpenAI moderation API.
105
+ """
106
+ url = "https://api.openai.com/v1/moderations"
107
+ headers = {"Content-Type": "application/json",
108
+ "Authorization": "Bearer " + os.environ["OPENAI_API_KEY"]}
109
+ text = text.replace("\n", "")
110
+ data = "{" + '"input": ' + f'"{text}"' + "}"
111
+ data = data.encode("utf-8")
112
+ try:
113
+ ret = requests.post(url, headers=headers, data=data, timeout=5)
114
+ flagged = ret.json()["results"][0]["flagged"]
115
+ except requests.exceptions.RequestException as e:
116
+ flagged = False
117
+ except KeyError as e:
118
+ flagged = False
119
+
120
+ return flagged
121
+
122
+
123
+ def pretty_print_semaphore(semaphore):
124
+ if semaphore is None:
125
+ return "None"
126
+ return f"Semaphore(value={semaphore._value}, locked={semaphore.locked()})"
README.md ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SimToken: A Simple Baseline for Referring Audio-Visual Segmentation
2
+ [![TGS](https://img.shields.io/badge/Paper-SimToken-red?logo=arXiv)](https://arxiv.org/abs/2509.17537)
3
+
4
+ ---
5
+ ## 📰 News
6
+
7
+ [//]: # (🔥**2026.1.18**: Code are released now!)
8
+
9
+ 🔥**2026.1.18**: Our paper got accepted to **ICASSP 2026**! Thanks to all co-authors and the anonymous reviewers🎉🎉
10
+
11
+ ---
12
+ ## ⚙️ Setup
13
+
14
+ ### Datasets
15
+
16
+ Download the official Ref-AVSBench dataset from [here](https://github.com/GeWu-Lab/Ref-AVS) and organize the dataset as follows:
17
+ ```
18
+ ./REFAVS/data
19
+ - /media
20
+ - /gt_mask
21
+ - /metadata.csv
22
+ ```
23
+
24
+ ### Pretrained Backbones
25
+ Download the sam_vit_h_4b8939.pth and put it in ```./models/segment_anything```
26
+
27
+ ### Checkpoints
28
+ Download our pretrained **[Simtoken](https://drive.google.com/file/d/1pargYfFy93rymCANuWV0nt6Lx3Ri406l/view?usp=sharing)**.
29
+
30
+ ### Core Requirements
31
+ This project depends on a small set of core packages. The configuration below has been tested and is recommended for stable execution.
32
+ - `numpy`, `pandas`, `matplotlib`, `opencv`
33
+ - `einops`, `timm`
34
+ - `sentencepiece`
35
+ - `transformers`, `peft`
36
+
37
+ Newer versions of `transformers` and `peft` may introduce API changes or naming/registration conflicts that can trigger runtime errors in this project (e.g., custom model/config registration).
38
+ To avoid such compatibility issues, we recommend **not using overly recent versions** and pin the two packages to the versions used during our development:
39
+
40
+ - `transformers==4.30.2`
41
+ - `peft==0.2.0`
42
+
43
+ We also provide a complete requirements.txt for reference and easier reproduction:
44
+ ```
45
+ pip install -r requirements.txt
46
+ ```
47
+
48
+
49
+ ---
50
+ ## 📌 Getting Started
51
+
52
+ ### Preparation
53
+ We recommend running the following code to pre-extract audio features and visual features compatible with SAM:
54
+ ```
55
+ python save_audio_feats.py --data_dir 'path/to/data'
56
+ python save_sam_feats.py --data_dir 'path/to/data'
57
+ ```
58
+
59
+
60
+
61
+ ### Train
62
+ To train our model on Ref-AVS Bench:
63
+ ```
64
+ python -W ignore train.py --name 'xxx' \
65
+ --vision_pretrained 'path/to/segment_anything/sam_vit_h_4b8939.pth' \
66
+ --vision_tower 'openai/clip-vit-large-patch14' \
67
+ --mllm 'Chat-UniVi/Chat-UniVi-7B-v1.5' \
68
+ --data_dir 'path/to/data'\
69
+ --log_root 'path/to/log_root'\
70
+ --checkpoint_root 'path/to/checkpoints_root'
71
+
72
+ ```
73
+ ### Test
74
+ To test our pretrained simtoken:
75
+ ```
76
+ python -W ignore load_model.py --saved_model 'path/to/checkpoint.pth' \
77
+ --vision_pretrained 'path/to/segment_anything/sam_vit_h_4b8939.pth' \
78
+ --vision_tower 'openai/clip-vit-large-patch14' \
79
+ --mllm 'Chat-UniVi/Chat-UniVi-7B-v1.5' \
80
+ --data_dir 'path/to/data' \
81
+ --visualization_root 'path/to/visualization_root'
82
+
83
+ ```
84
+
85
+
86
+
87
+
88
+
SEG_LTPO_results.md ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SEG-LTPO: Experimental Results and Analysis
2
+
3
+ ---
4
+
5
+ ## Method 1: SEG-LTPO-simple (ES-based, zeroth-order)
6
+
7
+ ### Overview
8
+
9
+ SEG-LTPO-simple performs test-time optimization of SimToken's single semantic token **Fseg** using antithetic Evolution Strategies (ES), guided by an internal reward signal that requires no ground-truth masks.
10
+
11
+ **Optimization loop** (T=5 steps, 4 anchor frames):
12
+ ```
13
+ eps_t ~ N(0, σ_t² I)
14
+ F± = F_curr ± eps_t
15
+ F_curr = F_curr + η_t · (R+ − R−) / (2σ_t²) · eps_t
16
+ best_F = argmax_F R(F) over all evaluated candidates
17
+ ```
18
+
19
+ **Reward function:**
20
+ ```
21
+ R = λ1·R_temp_feat + λ2·R_iou_pred + λ3·R_align_contrast − λ4·R_area
22
+ = 0.3·R_temp + 0.4·R_iou + 1.0·R_align − 0.3·R_area
23
+ ```
24
+
25
+ - **R_align_contrast**: cosine(Fseg, z_inside) − β·cosine(Fseg, z_outside); main signal
26
+ - **R_iou_pred**: SAM's internal mask quality head output
27
+ - **R_temp_feat**: feature-space cosine consistency between adjacent anchor frames
28
+ - **R_area**: average foreground ratio (degenerate-mask penalty)
29
+
30
+ **Reward gating**: accept optimized Fseg only when R(best_F) > R(F_init) + gate_delta.
31
+
32
+ ### Results (Unseen split, full 1656 samples)
33
+
34
+ | Method | mIoU | F | Δ mIoU |
35
+ |--------|------|---|--------|
36
+ | Baseline | 0.6989 | 0.7927 | — |
37
+ | Best-of-2 Random | 0.7050 (subset) → 0.7030 (full) | 0.7953 | +0.0040 |
38
+ | SEG-LTPO-simple (ES) | **0.7050** | **0.7960** | **+0.0061** |
39
+
40
+ > Best-of-2 and LTPO-ES results at full scale confirmed in the q-LTPO evaluation run below.
41
+
42
+ ### Key Findings
43
+
44
+ 1. **Reward signal is valid**: both Best-of-2 and ES-LTPO outperform baseline, confirming R_align_contrast provides useful signal.
45
+ 2. **ES update is noisy**: in 500-sample ablation, Best-of-2 (0.7235) slightly outperformed iterative ES (0.7228), due to extremely low SNR of single-sample gradient estimation in 256d space. At full scale (1656), ES-LTPO recovers (+0.0065 vs +0.0040), but the margin over Best-of-2 is small.
46
+ 3. **Null stability**: Null S metric change negligible (+0.00025), reward gating effectively suppresses false positives.
47
+
48
+ ---
49
+
50
+ ## Method 2: q-LTPO-autograd (first-order, Adam maximize)
51
+
52
+ ### Overview
53
+
54
+ **Core insight from LTPO analysis**: optimize the variable that is *directly consumed* by the downstream module, using autograd rather than noisy zeroth-order estimation.
55
+
56
+ **Three design decisions borrowed from original LTPO:**
57
+
58
+ 1. **Optimize q, not Fseg.** In SimToken+SAM, the token that directly enters the mask decoder's cross-attention is `q = sparse_emb = Fseg.unsqueeze(1)` (prompt encoder passes text_embeds through unchanged). We set `q = nn.Parameter(q_init)` and optimize q directly, bypassing the prompt encoder entirely. This requires no invertibility of ε_p — q_best is used directly for final inference.
59
+
60
+ 2. **Use autograd when reward is differentiable.** The mask decoder (transformer + MLP + matmul) is fully differentiable. With soft masks instead of hard thresholds, all reward terms are differentiable w.r.t. q. Adam maximize replaces the low-SNR score-function estimator.
61
+
62
+ 3. **Track best_q by task reward (no regularization), gate at the end.** λ_reg penalty is excluded from gating to avoid penalizing solutions that drifted slightly from q_init but achieved better task reward.
63
+
64
+ **Stage 0: Gradient connectivity check (verified)**
65
+ ```
66
+ grad_norm (step 0): 0.503070
67
+ reward trajectory: [0.4650, 0.4709, 0.4770, 0.4831, 0.4892] ← strictly monotone
68
+ gradient_connected: True
69
+ ```
70
+
71
+ ### Optimization loop
72
+
73
+ ```python
74
+ q = nn.Parameter(q_init.float().detach().clone())
75
+ optimizer = Adam([q], lr=lr_auto, maximize=True)
76
+ best_q, best_reward = q_init.clone(), R_task(q_init)
77
+
78
+ for step in range(T=5):
79
+ R_full = R_task(q) - λ_reg * ||q - q_init||²
80
+ R_full.backward()
81
+ optimizer.step()
82
+ clip_to_L2_ball(q, q_init, max_drift) # hard norm constraint
83
+ if R_task(q) > best_reward:
84
+ best_q = q.clone()
85
+
86
+ # gating
87
+ use best_q if R_task(best_q) > R_task(q_init) + gate_delta, else q_init
88
+ ```
89
+
90
+ **Hyperparameters (auto-scaled from q_init):**
91
+ - `lr = 0.01 × RMS(q_init)`
92
+ - `max_drift = 0.5 × ||q_init||`
93
+ - `λ_reg = 0.01`, `gate_delta = 0.0`
94
+
95
+ ### Staged reward build-up
96
+
97
+ **Stage 1** (R_iou + R_area_soft + λ_reg):
98
+ ```
99
+ R_task = 0.6·R_iou_pred − 0.2·sigmoid(mask_logits/τ).mean()
100
+ where τ=5.0 (temperature to avoid sigmoid saturation)
101
+ ```
102
+
103
+ **Stage 2** (Stage 1 + R_align_det):
104
+ ```
105
+ R_task = 0.4·R_iou_pred + 1.0·R_align_det − 0.3·R_area_soft
106
+ R_align_det = mean_t [ cosine(q, stopgrad(z_in^t)) − 0.5·cosine(q, stopgrad(z_out^t)) ]
107
+ ```
108
+ z_in/z_out are stopgrad'd to avoid coupling: q first finds a mask, then moves toward the masked region's semantics.
109
+
110
+ ### Results (Unseen split)
111
+
112
+ #### 200-sample subset (Stage 1 vs Stage 2 fair comparison, same baseline)
113
+
114
+ | Method | mIoU | F | Δ mIoU |
115
+ |--------|------|---|--------|
116
+ | Baseline | 0.6749 | 0.7763 | — |
117
+ | Best-of-2 ES | 0.6801 | 0.7803 | +0.0052 |
118
+ | LTPO-ES | 0.6838 | 0.7826 | +0.0089 |
119
+ | q-LTPO Stage 1 | 0.6979 | 0.7802 | +0.0230 |
120
+ | q-LTPO Stage 2 | **0.6989** | **0.7810** | **+0.0240** |
121
+
122
+ On 200 samples: Stage 2 marginally better than Stage 1 on both metrics.
123
+
124
+ #### Full evaluation (Unseen, 1656 samples)
125
+
126
+ | Method | mIoU | F | Δ mIoU vs Baseline |
127
+ |--------|------|---|---------------------|
128
+ | Baseline | 0.6990 | 0.7924 | — |
129
+ | Best-of-2 ES | 0.7030 | 0.7953 | +0.0040 (+0.57%) |
130
+ | LTPO-ES | 0.7055 | 0.7969 | +0.0065 (+0.93%) |
131
+ | **q-LTPO Stage 1** | **0.7285** | **0.8013** | **+0.0295 (+4.22%)** |
132
+ | q-LTPO Stage 2 | 0.7273 | 0.8002 | +0.0283 (+4.04%) |
133
+
134
+ **Stage 1 beats Stage 2 on full eval** (opposite of 200-sample trend). R_align_det adds noise at scale: in harder Unseen samples, the initial mask quality is lower, making stopgrad z_in/z_out a less reliable target.
135
+
136
+ ### Evaluation Status (after e0 fix)
137
+
138
+ | Split | Baseline mIoU/S | q-LTPO S1 (no e0) | q-LTPO S1 (e0) | Status |
139
+ |-------|-----------------|-------------------|----------------|--------|
140
+ | Unseen (1656) | 0.6990 | **0.7285** | — | Done (pre-e0) |
141
+ | Seen (200-sample) | 0.7483 | 0.7618 (+0.0136) | **0.7634 (+0.0151)** | Quick-val done |
142
+ | Null (200-sample, S↓) | 0.0619 | 0.0646 (+4.4%) | **0.0634 (+2.4%)** | Quick-val done |
143
+ | Unseen (200-sample) | 0.6761 | — | **0.6929 (+0.0168)** | Quick-val done |
144
+ | Seen (full) | — | — | — | Pending |
145
+ | Null (full, S↓) | 0.0120 | 0.0126 (+5.0%) | — | Pending e0 run |
146
+ | Unseen (full) | — | — | — | Pending |
147
+
148
+ ---
149
+
150
+ ## Null Safety Analysis and e0-Modulated Reward
151
+
152
+ ### Root Cause: R_iou_pred is a Conditional Quality Metric
153
+
154
+ The original q-LTPO Stage 1 reward:
155
+ ```
156
+ R_task = 0.6·R_iou_pred − 0.2·R_area_soft
157
+ ```
158
+
159
+ caused Null S metric degradation (+4.4% on 200-sample quick validation, +5.0% on full Null).
160
+
161
+ **Root cause**: `R_iou_pred` is SAM's internal mask quality head — it measures *how good the mask is given that segmentation was performed*, not *whether the target exists*. On Null frames, SAM still outputs `R_iou_pred ≈ 0.73–0.74` because it confidently segments the most prominent region (even if no audio target exists). The optimizer sees positive `R_iou_pred` and expands the mask accordingly.
162
+
163
+ **Why oracle gating approaches fail methodologically:**
164
+
165
+ - **Path A (gate_delta threshold)**: Distribution analysis showed Null reward_gain p50 = +0.0166 ≈ Seen p50 = +0.0181. The two distributions overlap heavily; any threshold that blocks most Null samples also blocks most Seen/Unseen samples.
166
+ - **Path B (area-based reject rule)**: Threshold 0.02 (area fraction) was derived by observing Null mean_area = 0.0094 vs Seen mean_area = 0.054 from the test distribution. This is benchmark-specific tuning = test-set overfitting. **Not a valid method.**
167
+
168
+ Both oracle approaches are useful for diagnostic analysis only. The principled fix must be structural.
169
+
170
+ ### Principled Fix: e0-Modulated Reward
171
+
172
+ **Key insight**: decouple *existence* from *quality*. Use the initial mask area as a proxy for the prior probability that a real target exists.
173
+
174
+ ```python
175
+ e0 = stopgrad( sigmoid(lrm_init / area_temp).mean() ) # R_area_soft at q_init
176
+ R_task = λ_iou · e0 · R_iou_pred − λ_area · R_area_soft
177
+ ```
178
+
179
+ **Why stopgrad on e0 is critical:**
180
+ - Without stopgrad: gradients flow through e0 → optimizer first inflates area to increase e0, then uses the higher e0 to justify larger R_iou reward ("area gaming").
181
+ - With stopgrad: e0 is a fixed scalar from the initialization. Gradients only flow through the explicit terms `R_iou_pred` and `R_area_soft`.
182
+
183
+ **Effect by split:**
184
+
185
+ | Split | mean e0 | Effective λ_iou = 0.6·e0 | Behavior |
186
+ |-------|---------|--------------------------|----------|
187
+ | Null | 0.037 | 0.022 | Area penalty dominates → conservative |
188
+ | Seen | 0.120 | 0.072 | Balanced optimization |
189
+ | Unseen | 0.150 | 0.090 | Full optimization drive |
190
+
191
+ The 3.2× e0 ratio (Unseen/Null) arises naturally from the initial mask size, providing automatic split-specific optimization strength without any threshold tuning.
192
+
193
+ **Implementation fix also addressed (best_q tracking bug):**
194
+ Before fix, `q_{N+1}` (post-step) was evaluated using `lrm/iou` from `q_N` (pre-step), corrupting best_q selection. Fixed by adding a fresh `no_grad` forward after each `optimizer.step()`.
195
+
196
+ ### Quick Validation Results (200 samples each, e0 modulation)
197
+
198
+ #### Null split (S metric, lower is better)
199
+
200
+ | Method | S metric | Δ relative |
201
+ |--------|----------|-----------|
202
+ | Baseline | 0.0619 | — |
203
+ | q-LTPO S1 (no e0) | 0.0646 | +4.4% |
204
+ | **q-LTPO S1 (e0)** | **0.0634** | **+2.4%** |
205
+
206
+ Diagnostic stats with e0:
207
+ ```
208
+ acceptance rate : 1.000
209
+ mean e0 : 0.0372
210
+ reward_gain p10/50/90: 0.0 / 0.0000 / +0.0123 ← p50=0 means >50% of samples frozen
211
+ mean drift : 0.4962 ← down from ~0.8 without e0
212
+ area (hard) init→best: 0.0094 → 0.0098 ← minimal area expansion
213
+ reward↑ & area+20%↑ : 0.040 ← low Null-safety risk
214
+ ```
215
+
216
+ #### Seen split (mIoU, higher is better)
217
+
218
+ | Method | mIoU | F | Δ mIoU |
219
+ |--------|------|---|--------|
220
+ | Baseline | 0.7483 | — | — |
221
+ | q-LTPO S1 (no e0) | 0.7618 | — | +0.0136 |
222
+ | **q-LTPO S1 (e0)** | **0.7634** | — | **+0.0151** |
223
+
224
+ Diagnostic stats with e0:
225
+ ```
226
+ mean e0 : 0.1200
227
+ reward_gain p10/50/90: +0.0026 / +0.0181 / +0.0944
228
+ mean drift : 0.5225
229
+ area (hard) init→best: 0.054 → (slight increase)
230
+ ```
231
+
232
+ #### Unseen split (mIoU, higher is better)
233
+
234
+ | Method | mIoU | F | Δ mIoU |
235
+ |--------|------|---|--------|
236
+ | Baseline | 0.6761 | 0.7776 | — |
237
+ | **q-LTPO S1 (e0)** | **0.6929** | **0.7765** | **+0.0168** |
238
+
239
+ Diagnostic stats with e0:
240
+ ```
241
+ acceptance rate : 1.000
242
+ mean e0 : 0.1506
243
+ reward_gain p10/50/90: +0.0011 / +0.0055 / +0.0293
244
+ mean drift : 0.6666
245
+ R_iou_pred init→best : 0.8029 → 0.8802
246
+ area (hard) init→best: 0.0635 → 0.0650
247
+ reward↑ & area+20%↑ : 0.125
248
+ ```
249
+
250
+ ### Analysis: e0 is a Pareto Improvement
251
+
252
+ Three conditions for Pareto improvement all satisfied on quick validation:
253
+
254
+ 1. **Null safer**: degradation halved (+4.4% → +2.4%). p50 reward_gain = 0.0000, meaning >50% of Null samples produce `best_q ≈ q_init`.
255
+ 2. **Seen maintained and slightly improved**: +0.0151 vs +0.0136 without e0.
256
+ 3. **Unseen not hurt — gains even larger**: +0.0168 > Seen +0.0151. The "harder positives suppressed" failure mode did not materialize.
257
+
258
+ **e0 hierarchy confirms split-level discriminability:**
259
+ ```
260
+ Null (0.037) << Seen (0.120) < Unseen (0.150)
261
+ ```
262
+ The ordering is sensible: Null frames have small/empty initial masks → low e0. Unseen e0 slightly exceeds Seen, possibly because the model produces slightly larger (less specific) masks on novel object-sentence combinations.
263
+
264
+ **Residual Null degradation (+2.4%) assessment**: Acceptable for now. The absolute magnitude is +0.0015 in S metric, while Seen/Unseen absolute gains are 10–11× larger. The residual originates from a small tail of Null samples where e0 is still large enough to permit some mask expansion. Further suppression (e.g., e0², sqrt(e0+ε)) risks hurting harder positives and should only be explored after full-set confirmation.
265
+
266
+ ---
267
+
268
+ ## Summary and Comparison
269
+
270
+ ### Pre-e0 (original q-LTPO Stage 1, full Unseen)
271
+
272
+ | Method | Unseen mIoU | Δ vs Baseline | Relative to ES-LTPO |
273
+ |--------|-------------|---------------|----------------------|
274
+ | Baseline | 0.6990 | — | — |
275
+ | ES-LTPO | 0.7055 | +0.0065 | 1× |
276
+ | **q-LTPO Stage 1** | **0.7285** | **+0.0295** | **4.5×** |
277
+
278
+ ### e0-Modulated Stage 1 (quick validation, 200 samples)
279
+
280
+ | Split | Baseline | e0-Stage1 | Δ | e0 |
281
+ |-------|----------|-----------|---|-----|
282
+ | Null (S↓) | 0.0619 | 0.0634 | +2.4% (rel) | 0.037 |
283
+ | Seen | 0.7483 | 0.7634 | +0.0151 | 0.120 |
284
+ | Unseen | 0.6761 | 0.6929 | +0.0168 | 0.150 |
285
+
286
+ q-LTPO-autograd with e0 modulation is the current primary method candidate. It achieves first-order gradient-based optimization with automatic Null-safety via the initial-area existence prior, without any test-set-derived thresholds.
287
+
288
+ ---
289
+
290
+ ## Hyperparameter Configurations
291
+
292
+ ### ES-LTPO (Method 1)
293
+ ```python
294
+ LTPOConfig(
295
+ T=5, num_anchors=4,
296
+ sigma_schedule=[0.10, 0.08, 0.06, 0.04, 0.02],
297
+ eta_scale=0.5,
298
+ lambda1=0.3, lambda2=0.4, lambda3=1.0, lambda4=0.3,
299
+ beta=0.5, gate_delta=0.0, trust_delta=None,
300
+ )
301
+ ```
302
+
303
+ ### q-LTPO Stage 1 with e0 (current primary candidate)
304
+ ```python
305
+ QLTPOConfig(
306
+ stage=1, T=5, num_anchors=4,
307
+ lr=0.0, # auto: 0.01 × RMS(q_init)
308
+ max_drift=0.0, # auto: 0.5 × ||q_init||
309
+ lambda_iou=0.6, lambda_area=0.2,
310
+ lambda_reg=0.01, area_temp=5.0,
311
+ gate_delta=0.0,
312
+ e0_modulation="identity", # e0 = R_area_soft(q_init), stopgrad
313
+ e0_eps=1e-4,
314
+ # oracle-only fields (disabled, not used in final method):
315
+ null_area_threshold=0.02,
316
+ null_gate_delta=0.0,
317
+ )
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Next Steps
323
+
324
+ ### Immediate (full-set confirmation)
325
+
326
+ Run full evaluations with e0-modulated Stage 1 to confirm quick-validation trends at scale:
327
+
328
+ ```bash
329
+ # Full Null (~30 min) — expect S ≈ 0.0120 + small increase, less than +5%
330
+ TRANSFORMERS_OFFLINE=1 python -W ignore load_model.py --eval_split test_n
331
+
332
+ # Full Seen (~35 min) — expect mIoU gain ≥ +0.013
333
+ TRANSFORMERS_OFFLINE=1 python -W ignore load_model.py --eval_split test_s
334
+
335
+ # Full Unseen (~35 min) — expect mIoU gain ≥ +0.025 (from pre-e0 baseline +0.0295)
336
+ TRANSFORMERS_OFFLINE=1 python -W ignore load_model.py --eval_split test_u
337
+ ```
338
+
339
+ **Decision criteria to promote e0-Stage1 to final method:**
340
+ - Null S degradation < 5% relative (full set)
341
+ - Seen mIoU gain ≥ +0.012
342
+ - Unseen mIoU gain ≥ +0.022
343
+
344
+ ### If full-set confirms (future work)
345
+
346
+ 1. **F-score improvement (Stage 3)**: Current gain is mainly in mIoU (overlap); F-score (boundary precision/recall) lags. Candidate: boundary-oriented reward using SAM's low-res logit gradient sharpness or contour consistency across anchor frames.
347
+ 2. **Stronger e0 suppression ablation**: Test `e0_modulation="sqrt"` (g(e0) = sqrt(e0+ε)) to further compress Null tail. Only justified if full-set Null degradation exceeds 5%.
348
+ 3. **Stage 2 revisit**: R_align_det hurt at scale due to noisy z_in/z_out from low-quality initial masks. Possible fix: gate align signal by `R_iou_pred > 0.85` to only use it when initial mask is reliable.
load_model.py ADDED
@@ -0,0 +1,877 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Compatibility: transformers==4.30.2 calls hf_hub_download(use_auth_token=...),
2
+ # removed in huggingface_hub>=0.20. Patch before importing transformers so the
3
+ # bound reference inside transformers.utils.hub picks up the fixed version.
4
+ import huggingface_hub as _hfhub
5
+ _hfhub_orig = _hfhub.hf_hub_download
6
+ def _hfhub_compat(*args, use_auth_token=None, token=None, **kwargs):
7
+ return _hfhub_orig(*args, token=token or use_auth_token, **kwargs)
8
+ _hfhub.hf_hub_download = _hfhub_compat
9
+
10
+ import transformers
11
+
12
+ from torch.cuda.amp import autocast, GradScaler
13
+
14
+ from datasets import REFAVS
15
+ from configs import args
16
+ from torch.utils.data import DataLoader
17
+ from functools import partial
18
+ from models.llava import conversation as conversation_lib
19
+ # from models.avs_model import VISAForCausalLM
20
+ from models.avs_model import Simtoken_ForCausalLM
21
+ import torch
22
+ from torch.cuda import amp
23
+ from transformers import AutoConfig
24
+ from peft import LoraConfig, get_peft_model
25
+ from torch import optim
26
+ from torch.optim import AdamW
27
+ from transformers import get_cosine_schedule_with_warmup
28
+ from tqdm import tqdm
29
+
30
+ from utils import utility
31
+ import random
32
+ import numpy as np
33
+ import re
34
+ import time
35
+ import os
36
+ from PIL import Image
37
+
38
+
39
+ import warnings
40
+
41
+ from utils.metric.utility import mask_iou
42
+
43
+ warnings.filterwarnings("ignore")
44
+
45
+ from transformers import logging
46
+ logging.set_verbosity_error()
47
+
48
+
49
+ IGNORE_INDEX = -100
50
+ IMAGE_TOKEN_INDEX = -200
51
+ DEFAULT_IMAGE_TOKEN = "<image>"
52
+ DEFAULT_IMAGE_PATCH_TOKEN = "<im_patch>"
53
+ DEFAULT_IM_START_TOKEN = "<im_start>"
54
+ DEFAULT_IM_END_TOKEN = "<im_end>"
55
+ DEFAULT_VIDEO_TOKEN = "<video>"
56
+
57
+ AUDIO_TOKEN_INDEX = -300
58
+ DEFAULT_AUDIO_TOKEN = "<audio>"
59
+
60
+ def set_seed(seed=42):
61
+ torch.manual_seed(seed)
62
+ np.random.seed(seed)
63
+ random.seed(seed)
64
+ torch.cuda.manual_seed_all(seed)
65
+ torch.backends.cudnn.deterministic = True
66
+ torch.backends.cudnn.benchmark = False
67
+
68
+ def dict_to_cuda(input_dict):
69
+ for k, v in input_dict.items():
70
+ if isinstance(input_dict[k], torch.Tensor):
71
+ input_dict[k] = v.cuda(non_blocking=True)
72
+ elif (
73
+ isinstance(input_dict[k], list)
74
+ and len(input_dict[k]) > 0
75
+ and isinstance(input_dict[k][0], torch.Tensor)
76
+ ):
77
+ input_dict[k] = [ele.cuda(non_blocking=True) for ele in v]
78
+ return input_dict
79
+
80
+ def tokenizer_image_audio_token(prompt, tokenizer, image_token_index=IMAGE_TOKEN_INDEX, audio_token_index=AUDIO_TOKEN_INDEX, num_frames=10, return_tensors=None):
81
+
82
+ prompt_chunks = re.split(r'(<image>|<audio>|<video>)', prompt)
83
+
84
+ prompt_chunks = [chunk for chunk in prompt_chunks if chunk]
85
+
86
+ # divide prompt into two set
87
+ text_chunks = [] # text
88
+ token_types = [] # <image>/<audio>/<video>
89
+ for chunk in prompt_chunks:
90
+ if chunk == "<image>":
91
+ token_types.append("image")
92
+ elif chunk == "<audio>":
93
+ token_types.append("audio")
94
+ elif chunk == "<video>":
95
+ token_types.append("video")
96
+ else:
97
+ text_chunks.append(chunk)
98
+
99
+ # Tokenize the text
100
+ tokenized_chunks = [tokenizer(chunk).input_ids for chunk in text_chunks]
101
+
102
+ def insert_separators(text_chunks, tokenized_chunks, token_types, image_token_index, audio_token_index, num_frames):
103
+ input_ids = []
104
+ offset = 0
105
+ if (
106
+ len(tokenized_chunks) > 0
107
+ and len(tokenized_chunks[0]) > 0
108
+ and tokenized_chunks[0][0] == tokenizer.bos_token_id
109
+ ):
110
+ offset = 1
111
+ input_ids.append(tokenized_chunks[0][0])
112
+
113
+ min_length = min(len(text_chunks), len(token_types))
114
+ for i in range(min_length):
115
+
116
+ input_ids.extend(tokenized_chunks[i][offset:])
117
+
118
+ if token_types[i] == "image":
119
+ input_ids.append(image_token_index)
120
+ elif token_types[i] == "audio":
121
+ input_ids.append(audio_token_index)
122
+ elif token_types[i] == "video":
123
+ input_ids.extend([image_token_index] * num_frames)
124
+
125
+
126
+ if len(text_chunks) > min_length:
127
+ input_ids.extend(tokenized_chunks[min_length][offset:])
128
+
129
+ return input_ids
130
+
131
+ input_ids = insert_separators(text_chunks, tokenized_chunks, token_types, image_token_index, audio_token_index, num_frames)
132
+
133
+ if return_tensors is not None:
134
+ if return_tensors == "pt":
135
+ return torch.tensor(input_ids, dtype=torch.long)
136
+ raise ValueError(f"Unsupported tensor type: {return_tensors}")
137
+ return input_ids
138
+
139
+ def collate_fn(batch, tokenizer=None):
140
+ vids = []
141
+ images = []
142
+ image_clips = []
143
+ masks = []
144
+ conversations = []
145
+ audio_feats = []
146
+ image_feats = []
147
+ resizes = []
148
+ orgsizes = []
149
+ first_refs = []
150
+
151
+ refs = []
152
+ first_refs = []
153
+ refs_num = []
154
+ fids = []
155
+
156
+
157
+ for data in batch:
158
+ vids.append(data['vid'])
159
+ images.append(data['image'])
160
+ image_clips.append(data['img_clip'])
161
+ masks.append(data['mask'])
162
+ conversations.append(data['conversation'])
163
+ audio_feats.append(data['feat_aud'])
164
+ resizes.append(data['resize'])
165
+ orgsizes.append(data['orgsize'])
166
+ image_feats.append(data['feat_sam'])
167
+ refs_num.append(len(data['ref']))
168
+ fids.append(data['fids'])
169
+
170
+ refs.append(data['ref'])
171
+ first_refs.append(data['ref'][0])
172
+
173
+ input_ids = [tokenizer_image_audio_token(conv, tokenizer, return_tensors="pt") for conv in conversations] # list
174
+ input_ids = torch.nn.utils.rnn.pad_sequence(input_ids, batch_first=True, padding_value=tokenizer.pad_token_id)
175
+ attention_masks = input_ids.ne(tokenizer.pad_token_id)
176
+
177
+ ref_ids = [tokenizer_image_audio_token(ref, tokenizer, return_tensors="pt") for ref in first_refs]
178
+
179
+ conv = conversation_lib.default_conversation.copy()
180
+ labels = input_ids.clone()
181
+
182
+ sep = 'Sure, it is [SEG]'
183
+
184
+ for conversation, target in zip(conversations, labels):
185
+ parts = conversation.split(sep)
186
+ cur_len = 1
187
+ target[:cur_len] = IGNORE_INDEX
188
+
189
+ sep_len = len(tokenizer_image_audio_token(sep, tokenizer)) - 1
190
+
191
+ for i in range(len(parts)-1):
192
+ part_len = len(tokenizer_image_audio_token(parts[i], tokenizer)) - 2
193
+ target[cur_len: cur_len + part_len] = IGNORE_INDEX
194
+ cur_len += part_len + sep_len
195
+
196
+ target[cur_len:] = IGNORE_INDEX
197
+
198
+
199
+ return {"vids": vids,
200
+ "images": images, # list[B]:[T, 3, 1024, 1024]
201
+ "images_clip": image_clips, # list[B]:[T, 3, 224, 224]
202
+ "masks": masks, # list[B]:[num_ref, T, H, W]
203
+ "convs": conversations, # list[B]: str
204
+ "input_ids": input_ids, # list[B]:[max_len]
205
+ "attention_masks": attention_masks, # list[B]:[max_len]
206
+ "labels": labels, # list[B]:[max_len]
207
+ "audio_feats": audio_feats, # list[B]:[10, 128]
208
+ "resizes": resizes, # list[B]
209
+ "orgsizes": orgsizes, # list[B]
210
+ "image_feats": image_feats,
211
+ "ref_ids": ref_ids, # list[B]: [ref_id_len]
212
+ "refs_num": refs_num,
213
+ "fids": fids,
214
+ "refs": refs,
215
+ }
216
+
217
+
218
+ import torch.multiprocessing as mp
219
+ if __name__ == "__main__":
220
+ mp.set_start_method("spawn", force=True)
221
+ set_seed(42)
222
+ tokenizer = transformers.AutoTokenizer.from_pretrained(
223
+ args.mllm,
224
+ cache_dir=None,
225
+ model_max_length=2048, # 2048
226
+ padding_side="right",
227
+ use_fast=False,
228
+ )
229
+
230
+ tokenizer.pad_token = tokenizer.unk_token
231
+ num_added_tokens = tokenizer.add_tokens("[SEG]")
232
+ seg_token_idx = tokenizer("[SEG]", add_special_tokens=False).input_ids[0] # 32000
233
+ print("seg_token_idx: ", seg_token_idx)
234
+
235
+
236
+ _split = args.eval_split
237
+ _dataset = REFAVS(_split, args, tokenizer, input_type='refer')
238
+ _dataloader = DataLoader(_dataset, batch_size=1, shuffle=False, num_workers=0, collate_fn=partial(collate_fn, tokenizer=tokenizer))
239
+
240
+
241
+
242
+ model_args = {
243
+ "train_mask_decoder": True,
244
+ "out_dim": 256, # 256
245
+ "ce_loss_weight": 1.0,
246
+ "dice_loss_weight": 0.5,
247
+ "bce_loss_weight": 2.0,
248
+ "seg_token_idx": seg_token_idx,
249
+ "vision_pretrained": args.vision_pretrained, # sam_vit_h_xxx.pth
250
+ "vision_tower": args.vision_tower,
251
+ "use_im_start_end": False,
252
+ "compress": args.compress,
253
+ "start": args.start,
254
+ }
255
+
256
+
257
+ # model = Simtoken_ForCausalLM.from_pretrained(args.mllm, torch_dtype=torch.float32, low_cpu_mem_usage=True, **model_args)
258
+ model = Simtoken_ForCausalLM.from_pretrained(args.mllm, torch_dtype=torch.bfloat16, low_cpu_mem_usage=True,
259
+ **model_args)
260
+
261
+ print("\nmodel loaded")
262
+
263
+ model.config.eos_token_id = tokenizer.eos_token_id
264
+ model.config.bos_token_id = tokenizer.bos_token_id
265
+ model.config.pad_token_id = tokenizer.pad_token_id
266
+
267
+ model.enable_input_require_grads()
268
+ model.gradient_checkpointing_enable()
269
+
270
+ model.get_model().initialize_vision_modules(model.get_model().config)
271
+ vision_tower = model.get_model().get_vision_tower()
272
+ vision_tower.to(dtype=torch.float32, device="cuda")
273
+
274
+ model_args_from_pt = AutoConfig.from_pretrained(args.mllm)
275
+ model_args_from_pt.use_cluster = True
276
+ model_args_from_pt.freeze = False
277
+ model_args_from_pt.mm_tune = True
278
+ model_args_from_pt.spatial_cluster_rate0 = 64
279
+ model_args_from_pt.spatial_cluster_rate1 = 32
280
+ model_args_from_pt.spatial_cluster_rate2 = 16
281
+ model_args_from_pt.temporal_cluster_rate = 0.0625
282
+ model_args_from_pt.use_cluster = True
283
+ model_args_from_pt.vision_tune = False
284
+ model.get_model().initialize_cluster_modules(model_args_from_pt)
285
+
286
+ model.get_model().initialize_lisa_modules(model.get_model().config)
287
+
288
+ for p in vision_tower.parameters():
289
+ p.requires_grad = False
290
+ for p in model.get_model().mm_projector.parameters():
291
+ p.requires_grad = False
292
+
293
+ lora_r = 8
294
+ target_modules = "q_proj,v_proj"
295
+ if lora_r > 0:
296
+ def find_linear_layers(model, lora_target_modules):
297
+ cls = torch.nn.Linear
298
+ lora_module_names = set()
299
+
300
+ for name, module in model.named_modules():
301
+ if (
302
+ isinstance(module, cls)
303
+ and all(
304
+ [
305
+ x not in name
306
+ for x in [
307
+ "visual_model",
308
+ "vision_tower",
309
+ "mm_projector",
310
+ "text_hidden_fcs",
311
+ "audio_feature_layer",
312
+ ]
313
+ ]
314
+ )
315
+ and any([x in name for x in lora_target_modules])
316
+ ):
317
+ lora_module_names.add(name)
318
+ return sorted(list(lora_module_names))
319
+
320
+
321
+ lora_alpha = 16
322
+ lora_dropout = 0.05
323
+
324
+ lora_target_modules = find_linear_layers(
325
+ model, target_modules.split(",")
326
+ )
327
+ lora_config = LoraConfig(
328
+ r=lora_r,
329
+ lora_alpha=lora_alpha,
330
+ target_modules=lora_target_modules,
331
+ lora_dropout=lora_dropout,
332
+ bias="none",
333
+ task_type="CAUSAL_LM",
334
+ )
335
+
336
+ model = get_peft_model(model, lora_config)
337
+ print("\nLora deployed")
338
+
339
+ model.print_trainable_parameters()
340
+
341
+ model = model.to("cuda")
342
+ model.resize_token_embeddings(len(tokenizer))
343
+
344
+ model.load_state_dict(torch.load(args.saved_model), strict=False)
345
+ print("saved model loaded")
346
+
347
+
348
+ save_root = args.visualization_root
349
+
350
+ def visualization(model, dataloader, save_root, name):
351
+ save_root = os.path.join(save_root, name)
352
+ os.makedirs(save_root, exist_ok=True)
353
+ print(f"save_root: {save_root}")
354
+ model.eval()
355
+ for batch in tqdm(dataloader, desc=f"Visualization on {name} "):
356
+ input_dict = dict_to_cuda(batch)
357
+ with torch.no_grad():
358
+ output_dict = model.forward(images=input_dict["images"],
359
+ images_clip=input_dict["images_clip"],
360
+ audio_features=input_dict["audio_feats"],
361
+ image_features=input_dict["image_feats"],
362
+ input_ids=input_dict["input_ids"],
363
+ labels=input_dict["labels"],
364
+ attention_masks=input_dict["attention_masks"],
365
+ masks_list=input_dict["masks"],
366
+ resize_list=input_dict["resizes"],
367
+ orgsize_list=input_dict["orgsizes"],
368
+ conversation_list=input_dict["convs"],
369
+ refs_num=input_dict["refs_num"],
370
+ fids=input_dict["fids"],
371
+ vids=input_dict["vids"],
372
+ contrast=args.ct_weight,
373
+ ref_ids=input_dict["ref_ids"],
374
+ inference=True)
375
+ pred_masks = output_dict["pred_masks"] # list[B]:[num_seg, T, H, W]
376
+ gt_masks = output_dict["gt_masks"] # list[B]:[num_seg, T, H, W]
377
+
378
+ for b in range(len(pred_masks)):
379
+ sample = torch.sigmoid(pred_masks[b]) # [num_seg, T, H, W]
380
+ vid = input_dict["vids"][b]
381
+ vid_root = os.path.join(save_root, vid)
382
+ os.makedirs(vid_root, exist_ok=True)
383
+ # print("vid_root:", vid_root)
384
+
385
+ binary_sample = (sample > 0.4).to(torch.uint8)
386
+ num_seg, T, H, W = sample.shape
387
+
388
+ for seg_idx in range(num_seg):
389
+ ref = input_dict["refs"][b][seg_idx]
390
+ ref_root = os.path.join(vid_root, ref)
391
+ os.makedirs(ref_root, exist_ok=True)
392
+ # print("ref_root:", ref_root)
393
+
394
+ for t in range(T):
395
+ mask_np = binary_sample[seg_idx, t].cpu().numpy() * 255
396
+ mask_img = Image.fromarray(mask_np.astype(np.uint8))
397
+
398
+ save_path = os.path.join(ref_root, f"frame{t}.png")
399
+ mask_img.save(save_path)
400
+ # print(f"image saved as {save_path}")
401
+ print("visualization finished")
402
+
403
+
404
+ def valuate(model, dataloader, name, max_rows=-1):
405
+ model.eval()
406
+
407
+ total_iou = 0
408
+ total_fscore = 0
409
+ count = 0
410
+
411
+ _total = min(max_rows, len(dataloader)) if max_rows > 0 else len(dataloader)
412
+ for i, batch in enumerate(tqdm(dataloader, desc=f"Evaluating on {name}", total=_total)):
413
+ if 0 < max_rows <= i:
414
+ break
415
+ input_dict = dict_to_cuda(batch)
416
+
417
+ with torch.cuda.amp.autocast(dtype=torch.bfloat16, enabled=True):
418
+ with torch.no_grad():
419
+ output_dict = model.forward(images=input_dict["images"],
420
+ images_clip=input_dict["images_clip"],
421
+ audio_features=input_dict["audio_feats"],
422
+ image_features=input_dict["image_feats"],
423
+ input_ids=input_dict["input_ids"],
424
+ labels=input_dict["labels"],
425
+ attention_masks=input_dict["attention_masks"],
426
+ masks_list=input_dict["masks"],
427
+ resize_list=input_dict["resizes"],
428
+ orgsize_list=input_dict["orgsizes"],
429
+ conversation_list=input_dict["convs"],
430
+ refs_num=input_dict["refs_num"],
431
+ fids=input_dict["fids"],
432
+ vids=input_dict["vids"],
433
+ contrast=args.ct_weight,
434
+ ref_ids=input_dict["ref_ids"],
435
+ inference=True)
436
+ pred_masks = output_dict["pred_masks"] # list[B]:[num_seg, T, H, W]
437
+ gt_masks = output_dict["gt_masks"] # list[B]:[num_seg, T, H, W]
438
+ for i in range(len(pred_masks)):
439
+ num_seg = pred_masks[i].shape[0]
440
+ T = pred_masks[i].shape[1]
441
+ iou = utility.mask_iou(pred_masks[i], gt_masks[i])
442
+ fscore = utility.Eval_Fmeasure(pred_masks[i], gt_masks[i], None)
443
+
444
+ total_iou += iou * num_seg * T
445
+ total_fscore += fscore * num_seg * T
446
+ count += num_seg * T
447
+
448
+ print(f"\n valuate on {name}: miou: {total_iou/count} fscore: {total_fscore/count}")
449
+
450
+
451
+ def valuate_Null(model, dataloader, max_rows=-1):
452
+ model.eval()
453
+
454
+ total_metric = 0
455
+ count = 0
456
+
457
+ _total = min(max_rows, len(dataloader)) if max_rows > 0 else len(dataloader)
458
+ for i, batch in enumerate(tqdm(dataloader, desc=f"Evaluating on Null", total=_total)):
459
+ if 0 < max_rows <= i:
460
+ break
461
+ input_dict = dict_to_cuda(batch)
462
+ with torch.cuda.amp.autocast(dtype=torch.bfloat16, enabled=True):
463
+ with torch.no_grad():
464
+ output_dict = model.forward(images=input_dict["images"],
465
+ images_clip=input_dict["images_clip"],
466
+ audio_features=input_dict["audio_feats"],
467
+ image_features=input_dict["image_feats"],
468
+ input_ids=input_dict["input_ids"],
469
+ labels=input_dict["labels"],
470
+ attention_masks=input_dict["attention_masks"],
471
+ masks_list=input_dict["masks"],
472
+ resize_list=input_dict["resizes"],
473
+ orgsize_list=input_dict["orgsizes"],
474
+ conversation_list=input_dict["convs"],
475
+ refs_num=input_dict["refs_num"],
476
+ fids=input_dict["fids"],
477
+ vids=input_dict["vids"],
478
+ contrast=args.ct_weight,
479
+ ref_ids=input_dict["ref_ids"],
480
+ inference=True)
481
+ pred_masks = output_dict["pred_masks"] # list[B]:[num_seg, T, H, W]
482
+ gt_masks = output_dict["gt_masks"] # list[B]:[num_seg, T, H, W]
483
+ for i in range(len(pred_masks)):
484
+ num_seg = pred_masks[i].shape[0]
485
+ T = pred_masks[i].shape[1]
486
+ null_metric = utility.metric_s_for_null(pred_masks[i])
487
+
488
+ total_metric += null_metric * num_seg * T
489
+ count += num_seg * T
490
+
491
+ print(f"\n valuate on test_n_refer, metric: {total_metric / count}")
492
+
493
+
494
+
495
+
496
+ from seg_ltpo import (
497
+ LTPOConfig, ltpo_optimize, best_of_2_optimize, decode_full_video,
498
+ get_sam_model, get_anchor_indices,
499
+ QLTPOConfig, q_ltpo_autograd, check_grad_connectivity,
500
+ reset_q_ltpo_stats, get_q_ltpo_stats,
501
+ )
502
+
503
+ def print_q_ltpo_stats(name: str) -> None:
504
+ stats = get_q_ltpo_stats()
505
+ if not stats:
506
+ return
507
+ n = len(stats)
508
+ acc_rate = sum(s["accepted"] for s in stats) / n
509
+ mean_gain = sum(s["reward_gain"] for s in stats) / n
510
+ mean_drift = sum(s["drift"] for s in stats) / n
511
+ clip_rate = sum(s["hit_clip"] for s in stats) / n
512
+ mean_iou_init = sum(s["R_iou_pred_init"] for s in stats) / n
513
+ mean_iou_best = sum(s["R_iou_pred_best"] for s in stats) / n
514
+ mean_area_init = sum(s["area_hard_init"] for s in stats) / n
515
+ mean_area_best = sum(s["area_hard_best"] for s in stats) / n
516
+ # Null safety: reward improved but predicted area grew >20 %
517
+ null_risk = sum(
518
+ 1 for s in stats
519
+ if s["reward_gain"] > 0 and s["area_hard_best"] > s["area_hard_init"] * 1.2
520
+ ) / n
521
+ gains = sorted(s["reward_gain"] for s in stats)
522
+ def _pct(v, p): return v[max(0, int(len(v) * p / 100) - 1)]
523
+ mean_e0 = sum(s["e0"] for s in stats) / n
524
+ print(f"\n [q-LTPO stats | {name} | n={n}]")
525
+ print(f" acceptance rate : {acc_rate:.3f}")
526
+ print(f" mean e0 (exist prior): {mean_e0:.4f} ← should differ Null vs Seen")
527
+ print(f" mean reward gain : {mean_gain:+.4f}")
528
+ print(f" reward_gain p10/50/90: {_pct(gains,10):+.4f} / {_pct(gains,50):+.4f} / {_pct(gains,90):+.4f}")
529
+ print(f" mean drift ‖q−q₀‖ : {mean_drift:.4f}")
530
+ print(f" hit-clip ratio : {clip_rate:.3f}")
531
+ print(f" R_iou_pred init→best : {mean_iou_init:.4f} → {mean_iou_best:.4f}")
532
+ print(f" area (hard) init→best: {mean_area_init:.4f} → {mean_area_best:.4f}")
533
+ print(f" reward↑ & area+20%↑ : {null_risk:.3f} ← Null safety indicator")
534
+
535
+ def valuate_ltpo(model, dataloader, name, ltpo_cfg, optimize_fn=None, max_rows=-1):
536
+ if optimize_fn is None:
537
+ optimize_fn = ltpo_optimize
538
+ """
539
+ Evaluate with SEG-LTPO-simple test-time optimisation.
540
+
541
+ For each sample:
542
+ 1. Run the standard SimToken forward pass once to get initial Fseg.
543
+ 2. Optimise Fseg on 4 anchor frames using antithetic ES (5 steps).
544
+ 3. Decode the full video with the best Fseg found.
545
+ 4. Fall back to the original Fseg when reward gating rejects the update.
546
+ """
547
+ model.eval()
548
+ sam_model = get_sam_model(model)
549
+ model_dtype = torch.bfloat16
550
+ num_frames = 10
551
+ anchor_indices = get_anchor_indices(num_frames, ltpo_cfg.num_anchors)
552
+
553
+ total_iou = 0
554
+ total_fscore = 0
555
+ count = 0
556
+
557
+ _total = min(max_rows, len(dataloader)) if max_rows > 0 else len(dataloader)
558
+ for i, batch in enumerate(tqdm(dataloader, desc=f"LTPO Evaluating on {name}", total=_total)):
559
+ if 0 < max_rows <= i:
560
+ break
561
+ input_dict = dict_to_cuda(batch)
562
+
563
+ # ── Step 1: standard forward pass (LLM + SAM decode) ──────────
564
+ with torch.cuda.amp.autocast(dtype=torch.bfloat16, enabled=True):
565
+ with torch.no_grad():
566
+ output_dict = model.forward(
567
+ images=input_dict["images"],
568
+ images_clip=input_dict["images_clip"],
569
+ audio_features=input_dict["audio_feats"],
570
+ image_features=input_dict["image_feats"],
571
+ input_ids=input_dict["input_ids"],
572
+ labels=input_dict["labels"],
573
+ attention_masks=input_dict["attention_masks"],
574
+ masks_list=input_dict["masks"],
575
+ resize_list=input_dict["resizes"],
576
+ orgsize_list=input_dict["orgsizes"],
577
+ conversation_list=input_dict["convs"],
578
+ refs_num=input_dict["refs_num"],
579
+ fids=input_dict["fids"],
580
+ vids=input_dict["vids"],
581
+ contrast=args.ct_weight,
582
+ ref_ids=input_dict["ref_ids"],
583
+ inference=True,
584
+ )
585
+
586
+ gt_masks = output_dict["gt_masks"] # list[B]:[num_seg, T, H, W]
587
+ seg_emb_list = output_dict["seg_embeddings"] # list[B]:[num_seg, 256]
588
+
589
+ for b in range(len(input_dict["images"])):
590
+ image_embeds_b = input_dict["image_feats"][b] # [T, 256, 64, 64]
591
+ resize_b = input_dict["resizes"][b]
592
+ orgsize_b = input_dict["orgsizes"][b]
593
+
594
+ # Convert initial Fseg to float32 for stable optimisation.
595
+ # seg_emb_list[b]: [num_seg, 256] in bfloat16
596
+ F_init_b = seg_emb_list[b].detach().float() # [num_seg, 256]
597
+
598
+ pred_masks_ltpo = []
599
+ for seg_idx in range(F_init_b.shape[0]):
600
+ fseg_init = F_init_b[seg_idx : seg_idx + 1] # [1, 256]
601
+
602
+ # ── Step 2: optimisation (float32, outside autocast) ──────
603
+ best_fseg = optimize_fn(
604
+ fseg_init, image_embeds_b, anchor_indices,
605
+ sam_model, model_dtype, ltpo_cfg,
606
+ ) # [1, 256] float32
607
+
608
+ # ── Step 3: decode full video with best Fseg ──────────────
609
+ pred_mask = decode_full_video(
610
+ best_fseg, image_embeds_b, sam_model,
611
+ resize_b, orgsize_b, model_dtype,
612
+ ) # [T, H, W]
613
+ pred_masks_ltpo.append(pred_mask)
614
+
615
+ pred_masks_b = torch.stack(pred_masks_ltpo, dim=0) # [num_seg, T, H, W]
616
+
617
+ num_seg = pred_masks_b.shape[0]
618
+ T_ = pred_masks_b.shape[1]
619
+ iou = utility.mask_iou(pred_masks_b, gt_masks[b])
620
+ fscore = utility.Eval_Fmeasure(pred_masks_b, gt_masks[b], None)
621
+
622
+ total_iou += iou * num_seg * T_
623
+ total_fscore += fscore * num_seg * T_
624
+ count += num_seg * T_
625
+
626
+ print(f"\n LTPO valuate on {name}: miou: {total_iou/count:.4f} fscore: {total_fscore/count:.4f}")
627
+
628
+
629
+ def valuate_ltpo_null(model, dataloader, ltpo_cfg, optimize_fn=None, max_rows=-1):
630
+ if optimize_fn is None:
631
+ optimize_fn = ltpo_optimize
632
+ """LTPO evaluation for Null split: measures S metric (lower = fewer false-positive masks)."""
633
+ model.eval()
634
+ sam_model = get_sam_model(model)
635
+ model_dtype = torch.bfloat16
636
+ num_frames = 10
637
+ anchor_indices = get_anchor_indices(num_frames, ltpo_cfg.num_anchors)
638
+
639
+ total_metric = 0
640
+ count = 0
641
+
642
+ _total = min(max_rows, len(dataloader)) if max_rows > 0 else len(dataloader)
643
+ for i, batch in enumerate(tqdm(dataloader, desc="LTPO Evaluating on Null", total=_total)):
644
+ if 0 < max_rows <= i:
645
+ break
646
+ input_dict = dict_to_cuda(batch)
647
+
648
+ with torch.cuda.amp.autocast(dtype=torch.bfloat16, enabled=True):
649
+ with torch.no_grad():
650
+ output_dict = model.forward(
651
+ images=input_dict["images"],
652
+ images_clip=input_dict["images_clip"],
653
+ audio_features=input_dict["audio_feats"],
654
+ image_features=input_dict["image_feats"],
655
+ input_ids=input_dict["input_ids"],
656
+ labels=input_dict["labels"],
657
+ attention_masks=input_dict["attention_masks"],
658
+ masks_list=input_dict["masks"],
659
+ resize_list=input_dict["resizes"],
660
+ orgsize_list=input_dict["orgsizes"],
661
+ conversation_list=input_dict["convs"],
662
+ refs_num=input_dict["refs_num"],
663
+ fids=input_dict["fids"],
664
+ vids=input_dict["vids"],
665
+ contrast=args.ct_weight,
666
+ ref_ids=input_dict["ref_ids"],
667
+ inference=True,
668
+ )
669
+
670
+ seg_emb_list = output_dict["seg_embeddings"] # list[B]:[num_seg, 256]
671
+
672
+ for b in range(len(input_dict["images"])):
673
+ image_embeds_b = input_dict["image_feats"][b]
674
+ resize_b = input_dict["resizes"][b]
675
+ orgsize_b = input_dict["orgsizes"][b]
676
+ F_init_b = seg_emb_list[b].detach().float()
677
+
678
+ pred_masks_ltpo = []
679
+ for seg_idx in range(F_init_b.shape[0]):
680
+ fseg_init = F_init_b[seg_idx : seg_idx + 1]
681
+ best_fseg = optimize_fn(
682
+ fseg_init, image_embeds_b, anchor_indices,
683
+ sam_model, model_dtype, ltpo_cfg,
684
+ )
685
+ pred_mask = decode_full_video(
686
+ best_fseg, image_embeds_b, sam_model,
687
+ resize_b, orgsize_b, model_dtype,
688
+ )
689
+ pred_masks_ltpo.append(pred_mask)
690
+
691
+ pred_masks_b = torch.stack(pred_masks_ltpo, dim=0) # [num_seg, T, H, W]
692
+ num_seg = pred_masks_b.shape[0]
693
+ T_ = pred_masks_b.shape[1]
694
+ null_metric = utility.metric_s_for_null(pred_masks_b)
695
+
696
+ total_metric += null_metric * num_seg * T_
697
+ count += num_seg * T_
698
+
699
+ print(f"\n LTPO valuate on Null: S metric: {total_metric/count:.4f}")
700
+
701
+
702
+ # ── Stage 0: gradient connectivity check ─────────────────────────────
703
+ # Loads one image_embed directly from disk — no dataloader, no gt_mask,
704
+ # no media frames required. F_init is a unit-scale random vector that
705
+ # mimics the distribution of Fseg (SAM prompt embeddings are in ℝ^256
706
+ # with per-dim std ≈ 0.05–0.3; we use std=0.1 as a neutral initialisation).
707
+ def run_stage0_check():
708
+ import glob
709
+ sam_model = get_sam_model(model)
710
+ model_dtype = torch.bfloat16
711
+
712
+ embed_files = sorted(glob.glob(os.path.join(args.data_dir, "image_embed", "*.pt")))
713
+ if not embed_files:
714
+ print("[Stage 0] ERROR: no .pt files found in data/image_embed/")
715
+ return False
716
+
717
+ img_embs = torch.load(embed_files[0], map_location="cuda") # [T, 256, 64, 64]
718
+ if img_embs.dim() == 3: # [256,64,64] → [1,256,64,64]
719
+ img_embs = img_embs.unsqueeze(0)
720
+
721
+ torch.manual_seed(42)
722
+ F_init = torch.randn(1, 256, device="cuda") * 0.1 # [1, 256] float32
723
+
724
+ anchors = get_anchor_indices(img_embs.shape[0], 4)
725
+ diag = check_grad_connectivity(F_init, img_embs, anchors, sam_model, model_dtype)
726
+ print("\n[Stage 0] Gradient connectivity check:")
727
+ print(f" file used : {os.path.basename(embed_files[0])}")
728
+ print(f" gradient_connected : {diag['gradient_connected']}")
729
+ print(f" grad_norm (step 0) : {diag['grad_norm_step0']:.6f}")
730
+ print(f" reward trajectory : {[f'{r:.4f}' for r in diag['reward_trajectory']]}")
731
+ return diag["gradient_connected"]
732
+
733
+ # ── Bypass equivalence test ───────────────────────────────────────────
734
+ # Three controlled tests to verify that fseg.unsqueeze(1) (bypass) is
735
+ # numerically equivalent to prompt_encoder(text_embeds=fseg.unsqueeze(1)):
736
+ # Test 1 — dense_emb dtype: dense_A.to(bfloat16) vs dense_emb_bf16 (exact 0?)
737
+ # Test 2 — matched-prec anchor decode: same decoder, same inputs, both bfloat16
738
+ # Test 3 — full-video (all T frames) matched-prec decode
739
+ # If all pass, delta_bypass_init = 0 and the +4.22% is purely from optimization.
740
+ def run_bypass_test():
741
+ from seg_ltpo import _precompute_dense_emb
742
+
743
+ sam_model = get_sam_model(model)
744
+ pe = sam_model.prompt_encoder
745
+ mask_dec = sam_model.mask_decoder
746
+ model_dtype = torch.bfloat16
747
+
748
+ # Get one real Fseg via a standard forward pass on the first batch
749
+ batch = next(iter(_dataloader))
750
+ input_dict = dict_to_cuda(batch)
751
+ with torch.cuda.amp.autocast(dtype=torch.bfloat16, enabled=True):
752
+ with torch.no_grad():
753
+ output_dict = model.forward(
754
+ images=input_dict["images"],
755
+ images_clip=input_dict["images_clip"],
756
+ audio_features=input_dict["audio_feats"],
757
+ image_features=input_dict["image_feats"],
758
+ input_ids=input_dict["input_ids"],
759
+ labels=input_dict["labels"],
760
+ attention_masks=input_dict["attention_masks"],
761
+ masks_list=input_dict["masks"],
762
+ resize_list=input_dict["resizes"],
763
+ orgsize_list=input_dict["orgsizes"],
764
+ conversation_list=input_dict["convs"],
765
+ refs_num=input_dict["refs_num"],
766
+ fids=input_dict["fids"],
767
+ vids=input_dict["vids"],
768
+ contrast=args.ct_weight,
769
+ ref_ids=input_dict["ref_ids"],
770
+ inference=True,
771
+ )
772
+
773
+ fseg = output_dict["seg_embeddings"][0][0:1].detach() # [1,256] bfloat16
774
+ image_embeds = input_dict["image_feats"][0] # [T,256,64,64] float32
775
+ device = fseg.device
776
+
777
+ anchor_indices = get_anchor_indices(image_embeds.shape[0], 4)
778
+ img_anc = image_embeds[anchor_indices] # [A,256,64,64] float32
779
+ dense_emb_bf16 = _precompute_dense_emb(sam_model, model_dtype, device) # [1,256,64,64] bfloat16
780
+ dense_pe = pe.get_dense_pe().to(device) # float32
781
+
782
+ def _decode(img, sparse_emb, dense_emb):
783
+ return mask_dec(
784
+ image_embeddings=img,
785
+ image_pe=dense_pe,
786
+ sparse_prompt_embeddings=sparse_emb,
787
+ dense_prompt_embeddings=dense_emb,
788
+ multimask_output=False,
789
+ )
790
+
791
+ def _check(label, tensor_a, tensor_b, exact=False):
792
+ err = (tensor_a.float() - tensor_b.float()).abs().max().item()
793
+ tol = 0.0 if exact else 1e-4
794
+ status = "PASS" if err <= tol else "FAIL"
795
+ print(f" [{status}] {label:50s} max|A-B| = {err:.2e}")
796
+ return err <= tol
797
+
798
+ print(f"\n[Bypass Test] fseg dtype={fseg.dtype} norm={fseg.float().norm().item():.4f}")
799
+
800
+ with torch.no_grad():
801
+ # Get prompt_encoder outputs (called outside autocast → float32)
802
+ sparse_A, dense_A = pe(points=None, boxes=None, masks=None,
803
+ text_embeds=fseg.unsqueeze(1))
804
+ sparse_B = fseg.unsqueeze(1) # bypass sparse: identical tensor
805
+
806
+ # ── Test 1: dense_emb dtype artifact ────────────────────────────────
807
+ # Hypothesis: dense_A (float32) and dense_emb_bf16 differ only because
808
+ # no_mask_embed.weight is float32; casting to bfloat16 should give exact 0.
809
+ print("\n [Test 1] dense_emb dtype artifact (expected: exact 0)")
810
+ t1 = _check("dense_A.to(bfloat16) vs dense_emb_bf16",
811
+ dense_A.to(torch.bfloat16), dense_emb_bf16, exact=True)
812
+
813
+ # ── Test 2: matched-precision decode on anchors ──────────────────────
814
+ # Both paths use bfloat16 sparse + bfloat16 dense.
815
+ # If sparse_emb is identical and dense_emb is identical (per Test 1),
816
+ # masks and iou_preds must be identical (same decoder, same inputs).
817
+ print("\n [Test 2] matched-precision anchor decode (expected: exact 0)")
818
+ dense_A_bf16 = dense_A.to(model_dtype)
819
+ masks_A, iou_A = _decode(img_anc, sparse_A, dense_A_bf16)
820
+ masks_B, iou_B = _decode(img_anc, sparse_B, dense_emb_bf16)
821
+ _check("sparse_emb", sparse_A, sparse_B, exact=True)
822
+ t2m = _check("masks (anchors, matched prec)", masks_A, masks_B, exact=True)
823
+ t2i = _check("iou_preds (anchors, matched prec)", iou_A, iou_B, exact=True)
824
+ t2 = t2m and t2i
825
+
826
+ # ── Test 3: full-video bypass-init baseline (all T frames) ──────────
827
+ # Extend Test 2 to all T frames; quantifies delta_bypass_init over
828
+ # the complete video rather than just the 4 anchor frames.
829
+ print(f"\n [Test 3] full-video matched-precision decode (T={image_embeds.shape[0]} frames)")
830
+ masks_full_A, _ = _decode(image_embeds, sparse_A, dense_A_bf16)
831
+ masks_full_B, _ = _decode(image_embeds, sparse_B, dense_emb_bf16)
832
+ t3 = _check("masks (all frames, matched prec)", masks_full_A, masks_full_B, exact=True)
833
+
834
+ print("\n ── Verdict ──────────────────────────────────────────────────────")
835
+ if t1 and t2 and t3:
836
+ print(" ALL PASS — bypass is algebraically and numerically equivalent to")
837
+ print(" prompt_encoder path under matched precision. delta_bypass_init = 0.")
838
+ print(" The +4.22% mIoU improvement is purely from q-LTPO optimization.")
839
+ else:
840
+ failures = []
841
+ if not t1: failures.append("Test 1 (dense dtype)")
842
+ if not t2: failures.append("Test 2 (anchor decode)")
843
+ if not t3: failures.append("Test 3 (full-video decode)")
844
+ print(f" FAIL in: {', '.join(failures)}")
845
+ print(" delta_bypass_init ≠ 0; need per-sample mIoU comparison to quantify.")
846
+
847
+ # ── Run evaluation ────────────────────────────────────────────────────
848
+
849
+ ltpo_cfg = LTPOConfig()
850
+ q_ltpo_cfg_s1 = QLTPOConfig(stage=1)
851
+ q_ltpo_cfg_s2 = QLTPOConfig(stage=2)
852
+ max_rows = args.max_eval_rows # -1 = all rows
853
+
854
+ # --max_eval_rows 0 → Stage 0 + bypass equivalence check, then exit
855
+ if max_rows == 0:
856
+ run_stage0_check()
857
+ run_bypass_test()
858
+ elif _split == 'test_n':
859
+ # Safety check: Baseline vs q-LTPO Stage 1 only.
860
+ # ES-LTPO / Stage 2 are omitted — ES is no longer the primary method,
861
+ # and Stage 2 consistently underperforms Stage 1. If Stage 1 shows
862
+ # notable deterioration here, add a small Best-of-2 ES subset run to
863
+ # distinguish "reward unsafe on Null" from "autograd more aggressive".
864
+ valuate_Null(model, _dataloader, max_rows=max_rows)
865
+ reset_q_ltpo_stats()
866
+ valuate_ltpo_null(model, _dataloader, q_ltpo_cfg_s1,
867
+ optimize_fn=q_ltpo_autograd, max_rows=max_rows)
868
+ print_q_ltpo_stats("null_q_ltpo_s1")
869
+ else:
870
+ # Baseline + q-LTPO Stage 1 only. ES series omitted — q-autograd is
871
+ # the primary method; Stage 2 consistently underperforms Stage 1.
872
+ valuate(model, _dataloader, _split, max_rows=max_rows)
873
+ reset_q_ltpo_stats()
874
+ valuate_ltpo(model, _dataloader, f'{_split}_q_ltpo_s1', q_ltpo_cfg_s1,
875
+ optimize_fn=q_ltpo_autograd, max_rows=max_rows)
876
+ print_q_ltpo_stats(f'{_split}_q_ltpo_s1')
877
+
requirements.txt ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ accelerate==1.12.0
2
+ anyio==4.12.1
3
+ certifi==2026.1.4
4
+ charset-normalizer==3.4.4
5
+ click==8.3.1
6
+ contourpy @ file:///croot/contourpy_1732540045555/work
7
+ cuda-bindings==12.9.4
8
+ cuda-pathfinder==1.2.2
9
+ cycler @ file:///home/conda/feedstock_root/build_artifacts/bld/rattler-build_cycler_1764466758/work
10
+ einops==0.8.2
11
+ exceptiongroup==1.3.1
12
+ filelock==3.20.0
13
+ fonttools @ file:///home/conda/feedstock_root/build_artifacts/fonttools_1765632549069/work
14
+ fsspec==2025.12.0
15
+ h11==0.16.0
16
+ hf-xet==1.2.0
17
+ httpcore==1.0.9
18
+ httpx==0.28.1
19
+ huggingface-hub==0.36.0
20
+ idna==3.11
21
+ Jinja2==3.1.6
22
+ kiwisolver @ file:///home/conda/feedstock_root/build_artifacts/bld/rattler-build_kiwisolver_1762488741/work
23
+ MarkupSafe==2.1.5
24
+ matplotlib==3.10.8
25
+ mpmath==1.3.0
26
+ munkres==1.1.4
27
+ networkx==3.4.2
28
+ numpy @ file:///home/conda/feedstock_root/build_artifacts/numpy_1747544640217/work/dist/numpy-2.2.6-cp310-cp310-linux_x86_64.whl#sha256=d6d964caeef85d00073d27cd62b46883d275b3d8162f723f0fcabbd0b3cc3f9d
29
+ nvidia-cublas-cu12==12.6.4.1
30
+ nvidia-cuda-cupti-cu12==12.6.80
31
+ nvidia-cuda-nvrtc-cu12==12.6.77
32
+ nvidia-cuda-runtime-cu12==12.6.77
33
+ nvidia-cudnn-cu12==9.10.2.21
34
+ nvidia-cufft-cu12==11.3.0.4
35
+ nvidia-cufile-cu12==1.11.1.6
36
+ nvidia-curand-cu12==10.3.7.77
37
+ nvidia-cusolver-cu12==11.7.1.2
38
+ nvidia-cusparse-cu12==12.5.4.2
39
+ nvidia-cusparselt-cu12==0.7.1
40
+ nvidia-nccl-cu12==2.27.5
41
+ nvidia-nvjitlink-cu12==12.6.85
42
+ nvidia-nvshmem-cu12==3.4.5
43
+ nvidia-nvtx-cu12==12.6.77
44
+ opencv-python==4.12.0
45
+ opencv-python-headless==4.12.0
46
+ packaging @ file:///home/task_176104877067765/conda-bld/packaging_1761049113113/work
47
+ pandas @ file:///home/conda/feedstock_root/build_artifacts/pandas_1764614464206/work
48
+ peft==0.2.0
49
+ pillow @ file:///home/task_176252756305210/conda-bld/pillow_1762528238325/work
50
+ psutil==7.2.2
51
+ pyparsing @ file:///home/conda/feedstock_root/build_artifacts/bld/rattler-build_pyparsing_1769003998/work
52
+ PySide6==6.9.2
53
+ python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/bld/rattler-build_python-dateutil_1751104122/work
54
+ pytz @ file:///home/conda/feedstock_root/build_artifacts/pytz_1742920838005/work
55
+ PyYAML==6.0.3
56
+ regex==2026.1.15
57
+ requests==2.32.5
58
+ safetensors==0.7.0
59
+ sentencepiece==0.2.1
60
+ shellingham==1.5.4
61
+ shiboken6==6.9.2
62
+ six @ file:///home/conda/feedstock_root/build_artifacts/bld/rattler-build_six_1753199211/work
63
+ sympy==1.14.0
64
+ timm==1.0.24
65
+ tokenizers==0.13.3
66
+ torch==2.10.0+cu126
67
+ torchvision==0.25.0+cu126
68
+ tornado @ file:///home/conda/feedstock_root/build_artifacts/tornado_1666788589303/work
69
+ tqdm==4.67.2
70
+ transformers==4.30.2
71
+ triton==3.6.0
72
+ typer-slim==0.21.1
73
+ typing_extensions==4.15.0
74
+ tzdata @ file:///home/conda/feedstock_root/build_artifacts/python-tzdata_1765719872007/work
75
+ unicodedata2 @ file:///home/conda/feedstock_root/build_artifacts/unicodedata2_1763054696114/work
76
+ urllib3==2.6.3
save_audio_feats.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os.path
2
+
3
+ import pandas as pd
4
+ from towhee import pipe, ops
5
+ import torch
6
+ from configs import args
7
+ import torchaudio
8
+ import tempfile
9
+
10
+
11
+ def preprocess_audio_to_mono(input_path, target_sr=16000, keep_original_format=True):
12
+
13
+ waveform, sample_rate = torchaudio.load(input_path)
14
+ original_encoding = torchaudio.info(input_path).encoding
15
+
16
+
17
+ if waveform.shape[0] > 1:
18
+ waveform = waveform[:1, :]
19
+
20
+ temp_fd, temp_path = tempfile.mkstemp(suffix='.wav')
21
+ os.close(temp_fd)
22
+
23
+ if keep_original_format and original_encoding == "PCM_S":
24
+ waveform = (waveform * 32767).to(torch.short) # float -> int16
25
+ torchaudio.save(temp_path, waveform, sample_rate, encoding="PCM_S", bits_per_sample=16)
26
+ else:
27
+ torchaudio.save(temp_path, waveform, sample_rate)
28
+
29
+ return temp_path
30
+
31
+
32
+ audio_vggish_pipeline = ( # pipeline building
33
+ pipe.input('path')
34
+ .map('path', 'frame', ops.audio_decode.ffmpeg())
35
+ .map('frame', 'vecs', ops.audio_embedding.vggish())
36
+ .output('vecs')
37
+ )
38
+
39
+
40
+
41
+ data_dir = args.data_dir
42
+
43
+
44
+ # test_id = 'zxis5LLvULw_12000_22000'
45
+ # test_path = f'{data_dir}/media/{test_id}/audio.wav'
46
+ # temp_path = preprocess_audio_to_mono(test_path)
47
+ # print(f"original audio info: {torchaudio.info(test_path)}")
48
+ # print(f"mono audio info: :{torchaudio.info(temp_path)}")
49
+ # test_embed = torch.tensor(audio_vggish_pipeline(temp_path).get()[0])
50
+ # print(test_embed.shape)
51
+ # os.unlink(temp_path)
52
+ #
53
+ #
54
+ # test_id = 'null_c-45AfEdAU050_99000_109000'
55
+ # test_path = f'{data_dir}/media/{test_id}/audio.wav'
56
+ # temp_path = preprocess_audio_to_mono(test_path)
57
+ # print(f"original audio info: {torchaudio.info(test_path)}")
58
+ # print(f"mono audio info: :{torchaudio.info(temp_path)}")
59
+ # test_embed = torch.tensor(audio_vggish_pipeline(temp_path).get()[0])
60
+ # print(test_embed.shape)
61
+ # os.unlink(temp_path)
62
+
63
+
64
+
65
+ metapath = os.path.join(data_dir, 'metadata.csv')
66
+ metadata = pd.read_csv(metapath, header=0)
67
+ metadata = metadata[metadata['split'].isin(['train', 'val', 'test_s', 'test_u', 'test_n'])]
68
+ # metadata = metadata[metadata['split'].isin(['test_s'])]
69
+
70
+ vids = metadata['uid'].apply(lambda x: x.rsplit('_', 2)[0]).unique()
71
+
72
+ save_dir = os.path.join(data_dir, 'audio_embed')
73
+ os.makedirs(save_dir, exist_ok=True)
74
+
75
+ for vid in vids:
76
+ audio_path = f'{data_dir}/media/{vid}/audio.wav'
77
+ temp_path = preprocess_audio_to_mono(audio_path)
78
+ audio_embed = torch.tensor(audio_vggish_pipeline(temp_path).get()[0])
79
+ os.unlink(temp_path)
80
+ # print(f"{vid}: {audio_embed.shape}")
81
+ torch.save(audio_embed, f'{save_dir}/{vid}.pt')
82
+ print(f'{vid} embedding saved {audio_embed.shape}')
83
+
save_sam_feats.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os.path
2
+
3
+ from models.segment_anything import build_sam_vit_h
4
+ from models.segment_anything.utils.transforms import ResizeLongestSide
5
+ import cv2
6
+ import torch
7
+ import torch.nn as nn
8
+ import torch.nn.functional as F
9
+ import pandas as pd
10
+ from configs import args
11
+ from save_audio_feats import data_dir
12
+
13
+
14
+ def preprocess(x: torch.Tensor, device='cuda') -> torch.Tensor:
15
+ """Normalize pixel values and pad to a square input."""
16
+ # 确保输入张量在正确的设备上
17
+ x = x.to(device)
18
+
19
+ # Normalize colors
20
+ pixel_mean = torch.Tensor([113.263, 99.370, 92.492]).view(-1, 1, 1).to(device)
21
+ pixel_std = torch.Tensor([64.274, 61.068, 58.626]).view(-1, 1, 1).to(device)
22
+ img_size = 1024
23
+
24
+ x = (x - pixel_mean) / pixel_std
25
+ # Pad
26
+ h, w = x.shape[-2:]
27
+ padh = img_size - h
28
+ padw = img_size - w
29
+ x = F.pad(x, (0, padw, 0, padh))
30
+ return x
31
+
32
+
33
+
34
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
35
+ print(f"Using device: {device}")
36
+
37
+ data_dir = args.data_dir
38
+ metapath = os.path.join(data_dir, 'metadata.csv')
39
+ metadata = pd.read_csv(metapath, header=0)
40
+ metadata = metadata[metadata['split'].isin(['train', 'val', 'test_s', 'test_u', 'test_n'])]
41
+ # metadata = metadata[metadata['split'].isin(['test_s'])]
42
+
43
+ vids = metadata['uid'].apply(lambda x: x.rsplit('_', 2)[0]).unique()
44
+
45
+ sam_model = build_sam_vit_h(args.vision_pretrained)
46
+ sam_model.to(device)
47
+
48
+ for param in sam_model.parameters():
49
+ param.requires_grad = False
50
+
51
+ save_dir = os.path.join(data_dir, 'image_embed')
52
+ os.makedirs(save_dir, exist_ok=True)
53
+
54
+
55
+ torch.cuda.empty_cache()
56
+
57
+ for vid in vids:
58
+ image_embeds = []
59
+
60
+ for _idx in range(10):
61
+ path_frame = f'{data_dir}/media/{vid}/frames/{_idx}.jpg'
62
+ frame = cv2.imread(path_frame)
63
+ if frame is None:
64
+ print(f"Warning: Could not read image {path_frame}")
65
+ continue
66
+
67
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
68
+ frame = ResizeLongestSide(1024).apply_image(frame)
69
+ frame_tensor = torch.from_numpy(frame).permute(2, 0, 1).contiguous() # [3, H, W]
70
+
71
+ frame_processed = preprocess(frame_tensor, device) # [3, 1024, 1024]
72
+
73
+ single_image = frame_processed.unsqueeze(0) # [1, 3, 1024, 1024]
74
+
75
+ with torch.no_grad():
76
+ image_embed = sam_model.image_encoder(single_image) # [1, 256, 64, 64]
77
+ image_embed = image_embed.squeeze(0).cpu()
78
+
79
+ image_embeds.append(image_embed)
80
+
81
+
82
+ torch.cuda.empty_cache()
83
+
84
+ if not image_embeds:
85
+ print(f"Error: No images loaded for video {vid}")
86
+ continue
87
+
88
+
89
+ image_embeds_stacked = torch.stack(image_embeds, dim=0) # [T, 256, 64, 64]
90
+
91
+
92
+ torch.save(image_embeds_stacked, f'{save_dir}/{vid}.pt')
93
+
94
+ print(f"Processed video {vid}, features shape: {image_embeds_stacked.shape}")
95
+
96
+ print("Processing completed!")
seg_ltpo.py ADDED
@@ -0,0 +1,786 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ SEG-LTPO: test-time optimization of SimToken's Fseg / q prompt token.
3
+
4
+ Two optimizers are provided:
5
+
6
+ ltpo_optimize – original antithetic-ES zeroth-order optimizer (Fseg space).
7
+ q_ltpo_autograd – autograd optimizer that directly optimizes q (= sparse
8
+ prompt embedding passed to the mask decoder) via Adam
9
+ maximize, with a differentiable reward. This is the
10
+ recommended path when the reward can be made differentiable.
11
+
12
+ Staged autograd reward build-up:
13
+ Stage 0 check_grad_connectivity — verify ∂R_iou/∂q ≠ 0
14
+ Stage 1 QLTPOConfig(stage=1) — R = 0.6·R_iou − 0.2·R_area_soft − λ_reg·‖q−q₀‖²
15
+ Stage 2 QLTPOConfig(stage=2) — Stage 1 + 1.0·R_align_det (z_in/z_out stopgrad)
16
+ Stage 3 QLTPOConfig(stage=3) — Stage 2 + 0.2·R_temp_feat (full reward)
17
+
18
+ Reward gating: use best_q only when R_task(best_q) > R_task(q_init) + gate_delta.
19
+
20
+ --- ES baseline (original) ---
21
+ Reward:
22
+ R = λ1·R_temp_feat + λ2·R_iou_pred + λ3·R_align_contrast − λ4·R_area
23
+ Update (antithetic ES, step t):
24
+ F_curr = F_curr + η_t · (R+ − R−)/(2σ_t²) · eps_t
25
+ best_F = argmax_F R(F)
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ from dataclasses import dataclass, field
31
+ from typing import Any, Dict, List, Optional, Tuple
32
+
33
+ import torch
34
+ import torch.nn.functional as F
35
+
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Per-sample diagnostics accumulator for q_ltpo_autograd
39
+ # ---------------------------------------------------------------------------
40
+
41
+ _q_ltpo_stats: List[Dict[str, Any]] = []
42
+
43
+
44
+ def reset_q_ltpo_stats() -> None:
45
+ global _q_ltpo_stats
46
+ _q_ltpo_stats = []
47
+
48
+
49
+ def get_q_ltpo_stats() -> List[Dict[str, Any]]:
50
+ return list(_q_ltpo_stats)
51
+
52
+
53
+ # ---------------------------------------------------------------------------
54
+ # Configuration
55
+ # ---------------------------------------------------------------------------
56
+
57
+ @dataclass
58
+ class LTPOConfig:
59
+ T: int = 5
60
+ num_anchors: int = 4
61
+ sigma_schedule: List[float] = field(
62
+ default_factory=lambda: [0.10, 0.08, 0.06, 0.04, 0.02]
63
+ )
64
+ eta_scale: float = 0.5 # η_t = eta_scale · σ_t
65
+
66
+ # Reward weights
67
+ lambda1: float = 0.3 # R_temp_feat
68
+ lambda2: float = 0.4 # R_iou_pred
69
+ lambda3: float = 1.0 # R_align_contrast
70
+ lambda4: float = 0.3 # R_area penalty
71
+
72
+ beta: float = 0.5 # background penalty coefficient in R_align_contrast
73
+
74
+ # Reward gating: fall back to F_init when improvement < gate_delta
75
+ gate_delta: float = 0.0
76
+
77
+ # L2 trust-region radius on Fseg; None = disabled
78
+ trust_delta: Optional[float] = None
79
+
80
+
81
+ # ---------------------------------------------------------------------------
82
+ # Utilities
83
+ # ---------------------------------------------------------------------------
84
+
85
+ def get_sam_model(model):
86
+ """Return SAM visual_model, unwrapping a PeftModel wrapper if present."""
87
+ base = model.base_model.model if hasattr(model, "base_model") else model
88
+ return base.model.visual_model
89
+
90
+
91
+ def get_anchor_indices(num_frames: int, num_anchors: int) -> List[int]:
92
+ """Uniformly sample anchor frame indices from [0, num_frames-1]."""
93
+ return [round(v) for v in torch.linspace(0, num_frames - 1, num_anchors).tolist()]
94
+
95
+
96
+ def _precompute_dense_emb(
97
+ sam_model, model_dtype: torch.dtype, device: torch.device
98
+ ) -> torch.Tensor:
99
+ """
100
+ Constant 'no-mask' dense embedding from SAM's prompt encoder.
101
+ Independent of Fseg; precompute once per sample to avoid redundant calls.
102
+ Shape: [1, 256, 64, 64].
103
+ """
104
+ pe = sam_model.prompt_encoder
105
+ H, W = pe.image_embedding_size
106
+ return (
107
+ pe.no_mask_embed.weight # [1, 256]
108
+ .reshape(1, -1, 1, 1)
109
+ .expand(1, -1, H, W)
110
+ .contiguous()
111
+ .to(model_dtype)
112
+ .to(device)
113
+ )
114
+
115
+
116
+ # ---------------------------------------------------------------------------
117
+ # Lightweight SAM decode (skips prompt_encoder overhead)
118
+ # ---------------------------------------------------------------------------
119
+
120
+ def _decode_on_anchors(
121
+ fseg: torch.Tensor, # [1, 256] float32
122
+ image_embeds_anchor: torch.Tensor, # [A, 256, 64, 64] model dtype
123
+ dense_emb: torch.Tensor, # [1, 256, 64, 64] model dtype (constant)
124
+ mask_decoder,
125
+ dense_pe: torch.Tensor, # [1, 256, 64, 64]
126
+ model_dtype: torch.dtype,
127
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
128
+ """
129
+ Decode anchor frames for a given Fseg.
130
+
131
+ Since no points/boxes are used, prompt_encoder simply concatenates
132
+ text_embeds onto an empty sparse tensor, so sparse_emb == Fseg.unsqueeze(1).
133
+ We exploit this to skip the full prompt_encoder call each iteration.
134
+
135
+ Returns:
136
+ low_res_masks: [A, 1, 256, 256]
137
+ iou_preds: [A, 1]
138
+ """
139
+ sparse_emb = fseg.to(model_dtype).unsqueeze(1) # [1, 1, 256]
140
+ with torch.no_grad():
141
+ low_res_masks, iou_preds = mask_decoder(
142
+ image_embeddings=image_embeds_anchor,
143
+ image_pe=dense_pe,
144
+ sparse_prompt_embeddings=sparse_emb,
145
+ dense_prompt_embeddings=dense_emb,
146
+ multimask_output=False,
147
+ )
148
+ return low_res_masks, iou_preds # [A,1,256,256], [A,1]
149
+
150
+
151
+ # ---------------------------------------------------------------------------
152
+ # Reward computation
153
+ # ---------------------------------------------------------------------------
154
+
155
+ def _compute_reward(
156
+ fseg: torch.Tensor, # [1, 256] float32
157
+ low_res_masks: torch.Tensor, # [A, 1, 256, 256]
158
+ iou_preds: torch.Tensor, # [A, 1]
159
+ image_embeds_anchor: torch.Tensor, # [A, 256, 64, 64]
160
+ cfg: LTPOConfig,
161
+ ) -> float:
162
+ num_anchor = low_res_masks.shape[0]
163
+ device = fseg.device
164
+
165
+ # Work entirely in float32 for numerical stability
166
+ masks_soft = torch.sigmoid(low_res_masks.float().squeeze(1)) # [A, 256, 256]
167
+ img_embs = image_embeds_anchor.float() # [A, 256, 64, 64]
168
+
169
+ # q lives in SAM's 256-d prompt space (same as Fseg after text_hidden_fcs)
170
+ q = F.normalize(fseg[0].float(), dim=0) # [256]
171
+
172
+ # Downsample soft masks 256×256 → 64×64 to match image_embed spatial dims.
173
+ # Keep as soft weights (no hard threshold) so the reward surface is smooth.
174
+ masks_64 = F.interpolate(
175
+ masks_soft.unsqueeze(1), size=(64, 64),
176
+ mode="bilinear", align_corners=False,
177
+ ).squeeze(1) # [A, 64, 64]
178
+
179
+ # ── Per-frame masked pooling ──────────────────────────────────────────
180
+ z_ins: List[torch.Tensor] = []
181
+ z_outs: List[torch.Tensor] = []
182
+ for t in range(num_anchor):
183
+ m = masks_64[t] # [64, 64]
184
+ img = img_embs[t] # [256, 64, 64]
185
+
186
+ # Soft weighted average pooling over foreground / background
187
+ z_in = (img * m.unsqueeze(0)).sum(dim=[1, 2]) / (m.sum() + 1e-6)
188
+ z_out = (img * (1.0 - m).unsqueeze(0)).sum(dim=[1, 2]) / ((1.0 - m).sum() + 1e-6)
189
+
190
+ z_ins.append(F.normalize(z_in, dim=0)) # [256]
191
+ z_outs.append(F.normalize(z_out, dim=0)) # [256]
192
+
193
+ # ── R_align_contrast ──────────────────────────────────────────────────
194
+ # Maximise Fseg↔inside alignment while penalising Fseg↔outside alignment.
195
+ # Contrast term prevents reward-hacking via large masks:
196
+ # a large mask pulls inside and outside features together, shrinking the gap.
197
+ r_align = sum(
198
+ (q @ z_ins[t]) - cfg.beta * (q @ z_outs[t])
199
+ for t in range(num_anchor)
200
+ ) / num_anchor
201
+
202
+ # ── R_iou_pred ────────────────────────────────────────────────────────
203
+ # SAM's internal mask-quality head, calibrated during SAM training.
204
+ r_iou = iou_preds.float().mean()
205
+
206
+ # ── R_temp_feat ───────────────────────────────────────────────────────
207
+ # Feature-space consistency between adjacent anchor frames.
208
+ # Harder to game than mask-IoU: large masks pool diverse background
209
+ # features across frames, degrading cosine similarity.
210
+ r_temp = torch.tensor(0.0, device=device)
211
+ if num_anchor > 1:
212
+ r_temp = sum(
213
+ z_ins[t] @ z_ins[t + 1] for t in range(num_anchor - 1)
214
+ ) / (num_anchor - 1)
215
+
216
+ # ── R_area ────────────────────────────────────────────────────────────
217
+ r_area = masks_64.mean()
218
+
219
+ R = (cfg.lambda1 * r_temp
220
+ + cfg.lambda2 * r_iou
221
+ + cfg.lambda3 * r_align
222
+ - cfg.lambda4 * r_area)
223
+
224
+ return R.item()
225
+
226
+
227
+ # ---------------------------------------------------------------------------
228
+ # Ablation baseline: Best-of-2 Random (no iterative update)
229
+ # ---------------------------------------------------------------------------
230
+
231
+ def best_of_2_optimize(
232
+ F_init: torch.Tensor,
233
+ image_embeds: torch.Tensor,
234
+ anchor_indices: List[int],
235
+ sam_model,
236
+ model_dtype: torch.dtype,
237
+ cfg: LTPOConfig,
238
+ ) -> torch.Tensor:
239
+ """
240
+ Best-of-2 Random baseline.
241
+
242
+ Sample one antithetic pair (F+, F-) using the first sigma value,
243
+ evaluate both, return whichever has the higher reward.
244
+ No iterative update — serves as the ablation for the update rule.
245
+ Same reward gating as ltpo_optimize for a fair comparison.
246
+ """
247
+ device = F_init.device
248
+ image_embeds_anchor = image_embeds[anchor_indices]
249
+
250
+ dense_emb = _precompute_dense_emb(sam_model, model_dtype, device)
251
+ dense_pe = sam_model.prompt_encoder.get_dense_pe().to(device)
252
+ mask_dec = sam_model.mask_decoder
253
+
254
+ lrm0, iou0 = _decode_on_anchors(
255
+ F_init, image_embeds_anchor, dense_emb, mask_dec, dense_pe, model_dtype
256
+ )
257
+ R_init = _compute_reward(F_init, lrm0, iou0, image_embeds_anchor, cfg)
258
+
259
+ sigma = cfg.sigma_schedule[0]
260
+ eps = torch.randn_like(F_init) * sigma
261
+ F_plus = F_init + eps
262
+ F_minus = F_init - eps
263
+
264
+ lrm_p, iou_p = _decode_on_anchors(
265
+ F_plus, image_embeds_anchor, dense_emb, mask_dec, dense_pe, model_dtype
266
+ )
267
+ lrm_m, iou_m = _decode_on_anchors(
268
+ F_minus, image_embeds_anchor, dense_emb, mask_dec, dense_pe, model_dtype
269
+ )
270
+ R_plus = _compute_reward(F_plus, lrm_p, iou_p, image_embeds_anchor, cfg)
271
+ R_minus = _compute_reward(F_minus, lrm_m, iou_m, image_embeds_anchor, cfg)
272
+
273
+ best_R, best_F = R_init, F_init.clone()
274
+ if R_plus > best_R: best_R, best_F = R_plus, F_plus.clone()
275
+ if R_minus > best_R: best_R, best_F = R_minus, F_minus.clone()
276
+
277
+ if best_R <= R_init + cfg.gate_delta:
278
+ return F_init
279
+ return best_F
280
+
281
+
282
+ # ---------------------------------------------------------------------------
283
+ # Full-video decode with a given Fseg
284
+ # ---------------------------------------------------------------------------
285
+
286
+ def decode_full_video(
287
+ fseg: torch.Tensor, # [1, 256] float32
288
+ image_embeds: torch.Tensor, # [T, 256, 64, 64] model dtype on CUDA
289
+ sam_model,
290
+ resize: tuple, # (H_resized, W_resized) – after ResizeLongestSide
291
+ orgsize: tuple, # (H_orig, W_orig)
292
+ model_dtype: torch.dtype,
293
+ ) -> torch.Tensor:
294
+ """
295
+ Decode all T frames with the given Fseg.
296
+ Returns raw logit mask [T, H_orig, W_orig] (not yet sigmoid).
297
+ """
298
+ device = image_embeds.device
299
+ dense_emb = _precompute_dense_emb(sam_model, model_dtype, device)
300
+ dense_pe = sam_model.prompt_encoder.get_dense_pe().to(device)
301
+ sparse_emb = fseg.to(model_dtype).unsqueeze(1) # [1, 1, 256]
302
+
303
+ with torch.no_grad():
304
+ low_res_masks, _ = sam_model.mask_decoder(
305
+ image_embeddings=image_embeds, # [T, 256, 64, 64]
306
+ image_pe=dense_pe,
307
+ sparse_prompt_embeddings=sparse_emb, # [1, 1, 256]
308
+ dense_prompt_embeddings=dense_emb, # [1, 256, 64, 64]
309
+ multimask_output=False,
310
+ ) # [T, 1, 256, 256]
311
+
312
+ pred_mask = sam_model.postprocess_masks(
313
+ low_res_masks, input_size=resize, original_size=orgsize
314
+ ) # [T, 1, H, W]
315
+ return pred_mask.squeeze(1) # [T, H, W]
316
+
317
+
318
+ # ---------------------------------------------------------------------------
319
+ # Main optimisation loop
320
+ # ---------------------------------------------------------------------------
321
+
322
+ def ltpo_optimize(
323
+ F_init: torch.Tensor, # [1, 256] float32 on CUDA
324
+ image_embeds: torch.Tensor, # [T, 256, 64, 64] model dtype on CUDA
325
+ anchor_indices: List[int],
326
+ sam_model,
327
+ model_dtype: torch.dtype,
328
+ cfg: LTPOConfig,
329
+ ) -> torch.Tensor:
330
+ """
331
+ Optimise Fseg at test time via antithetic ES.
332
+
333
+ Returns best Fseg found [1, 256] float32.
334
+ Falls back to F_init when reward gating rejects all updates.
335
+ """
336
+ device = F_init.device
337
+ image_embeds_anchor = image_embeds[anchor_indices] # [A, 256, 64, 64]
338
+
339
+ # Precompute constants shared across every optimisation step
340
+ dense_emb = _precompute_dense_emb(sam_model, model_dtype, device)
341
+ dense_pe = sam_model.prompt_encoder.get_dense_pe().to(device)
342
+ mask_dec = sam_model.mask_decoder
343
+
344
+ # ── Evaluate initial token ────────────────────────────────────────────
345
+ lrm0, iou0 = _decode_on_anchors(
346
+ F_init, image_embeds_anchor, dense_emb, mask_dec, dense_pe, model_dtype
347
+ )
348
+ R_init = _compute_reward(F_init, lrm0, iou0, image_embeds_anchor, cfg)
349
+
350
+ best_F, best_R = F_init.clone(), R_init
351
+ F_curr = F_init.clone()
352
+
353
+ # ── Optimisation loop ─────────────────────────────────────────────────
354
+ for t in range(cfg.T):
355
+ sigma_t = cfg.sigma_schedule[t]
356
+ eta_t = cfg.eta_scale * sigma_t
357
+
358
+ eps = torch.randn_like(F_curr) * sigma_t
359
+ F_plus = F_curr + eps
360
+ F_minus = F_curr - eps
361
+
362
+ lrm_p, iou_p = _decode_on_anchors(
363
+ F_plus, image_embeds_anchor, dense_emb, mask_dec, dense_pe, model_dtype
364
+ )
365
+ lrm_m, iou_m = _decode_on_anchors(
366
+ F_minus, image_embeds_anchor, dense_emb, mask_dec, dense_pe, model_dtype
367
+ )
368
+
369
+ R_plus = _compute_reward(F_plus, lrm_p, iou_p, image_embeds_anchor, cfg)
370
+ R_minus = _compute_reward(F_minus, lrm_m, iou_m, image_embeds_anchor, cfg)
371
+
372
+ # Track the best token seen across all evaluated candidates
373
+ if R_plus > best_R:
374
+ best_R, best_F = R_plus, F_plus.clone()
375
+ if R_minus > best_R:
376
+ best_R, best_F = R_minus, F_minus.clone()
377
+
378
+ # Antithetic policy-gradient update of the iterate
379
+ # Formula: F_{t+1} = F_t + η_t · (R+ - R−)/(2σ_t²) · eps_t
380
+ grad_est = (R_plus - R_minus) / (2.0 * sigma_t ** 2)
381
+ F_curr = F_curr + eta_t * grad_est * eps
382
+
383
+ # Optional L2 trust-region: keep F_curr within radius trust_delta of F_init
384
+ if cfg.trust_delta is not None:
385
+ diff = F_curr - F_init
386
+ norm = diff.norm()
387
+ if norm > cfg.trust_delta:
388
+ F_curr = F_init + diff * (cfg.trust_delta / norm)
389
+
390
+ # ── Reward gating ─────────────────────────────────────────────────────
391
+ # Reject the update when there is no meaningful improvement over the
392
+ # initial token (handles Null-like samples where no target exists).
393
+ if best_R <= R_init + cfg.gate_delta:
394
+ return F_init
395
+ return best_F
396
+
397
+
398
+ # ===========================================================================
399
+ # q-LTPO-autograd: differentiable test-time optimization of the prompt token
400
+ # ===========================================================================
401
+
402
+ @dataclass
403
+ class QLTPOConfig:
404
+ """Configuration for q_ltpo_autograd (Stages 1–3).
405
+
406
+ stage controls which reward terms are active:
407
+ 1 R_iou + R_area_soft + reg (gradient connectivity + stability)
408
+ 2 Stage 1 + R_align_det (z stopgrad) (semantic alignment)
409
+ 3 Stage 2 + R_temp_feat (full reward)
410
+ """
411
+ stage: int = 1
412
+ T: int = 5
413
+ num_anchors: int = 4
414
+
415
+ # ── Optimizer ──────────────────────────────────────────────────────────
416
+ # lr=0 → auto-set to 0.01 × RMS(q_init); any positive value is used directly
417
+ lr: float = 0.0
418
+ # max_drift=0 → auto-set to 0.5 × ‖q_init‖; any positive value is a hard radius
419
+ max_drift: float = 0.0
420
+
421
+ # ── Stage 1 reward weights ─────────────────────────────────────────────
422
+ lambda_iou: float = 0.6
423
+ lambda_area: float = 0.2
424
+ lambda_reg: float = 0.01
425
+ area_temp: float = 5.0 # sigmoid temperature for R_area_soft
426
+
427
+ # ── Stage 2 additional weights ─────────────────────────────────────────
428
+ lambda_align: float = 1.0
429
+ beta_align: float = 0.5 # background penalty coefficient in R_align
430
+
431
+ # ── Stage 3 additional weights ─────────────────────────────────────────
432
+ lambda_temp: float = 0.2
433
+
434
+ # ── Gating ─────────────────────────────────────────────────────────────
435
+ gate_delta: float = 0.0
436
+
437
+ # ── e0-modulated R_iou (principled Null-safety) ────────────────────────
438
+ # e0 = stopgrad(R_area_soft(q_init)): the initial soft-area fraction acts
439
+ # as an existence prior on the R_iou term.
440
+ # "none" → original behavior (e0 = 1, no modulation)
441
+ # "identity" → e0 = R_area_soft(q_init) [first version]
442
+ # "sqrt" → e0 = sqrt(R_area_soft(q_init) + e0_eps)
443
+ e0_modulation: str = "identity"
444
+ e0_eps: float = 1e-4 # epsilon for "sqrt" variant
445
+
446
+ # ── Oracle Null-safety gate (analysis only; NOT for final method) ──────
447
+ # Derived from test-set distribution (Null area_hard ≈ 0.01, Seen ≈ 0.05)
448
+ # so must not be used in reported results. Set null_gate_delta=0 to disable.
449
+ null_area_threshold: float = 0.02 # hard area fraction below which guard activates
450
+ null_gate_delta: float = 0.0 # 0 = disabled; 0.05 = oracle experiment
451
+
452
+
453
+ # ---------------------------------------------------------------------------
454
+ # e0 helper
455
+ # ---------------------------------------------------------------------------
456
+
457
+ def _compute_e0(r_area_soft_init: float, cfg: "QLTPOConfig") -> float:
458
+ """Compute the existence-prior weight from the initial soft area."""
459
+ if cfg.e0_modulation == "identity":
460
+ return r_area_soft_init
461
+ if cfg.e0_modulation == "sqrt":
462
+ return (r_area_soft_init + cfg.e0_eps) ** 0.5
463
+ return 1.0 # "none"
464
+
465
+
466
+ # ---------------------------------------------------------------------------
467
+ # Differentiable anchor decode (float32 throughout; no torch.no_grad)
468
+ # ---------------------------------------------------------------------------
469
+
470
+ def _decode_on_anchors_diff(
471
+ q: torch.Tensor, # [1, 256] float32
472
+ image_embeds_anchor_fp32: torch.Tensor, # [A, 256, 64, 64] float32
473
+ dense_emb_fp32: torch.Tensor, # [1, 256, 64, 64] float32
474
+ mask_decoder,
475
+ dense_pe_fp32: torch.Tensor, # [1, 256, 64, 64] float32
476
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
477
+ """Differentiable mask-decoder forward.
478
+
479
+ All inputs are float32 to avoid fp16 gradient truncation.
480
+ q may be a Parameter (requires_grad=True) or a plain detached tensor.
481
+ Returns low_res_masks [A,1,256,256] and iou_preds [A,1], both float32.
482
+ """
483
+ sparse_emb = q.unsqueeze(1) # [1, 1, 256]
484
+ low_res_masks, iou_preds = mask_decoder(
485
+ image_embeddings=image_embeds_anchor_fp32,
486
+ image_pe=dense_pe_fp32,
487
+ sparse_prompt_embeddings=sparse_emb,
488
+ dense_prompt_embeddings=dense_emb_fp32,
489
+ multimask_output=False,
490
+ )
491
+ return low_res_masks, iou_preds # [A,1,256,256], [A,1]
492
+
493
+
494
+ # ---------------------------------------------------------------------------
495
+ # Differentiable reward components
496
+ # ---------------------------------------------------------------------------
497
+
498
+ def _task_reward_stage1(
499
+ lrm: torch.Tensor, # [A,1,256,256] float32
500
+ iou: torch.Tensor, # [A,1] float32
501
+ cfg: QLTPOConfig,
502
+ e0: float = 1.0,
503
+ ) -> torch.Tensor:
504
+ """Task reward (no regularization): used for best_q tracking and gating.
505
+
506
+ e0 is the stopgrad existence prior: R_area_soft(q_init) scaled via
507
+ cfg.e0_modulation. When e0 << 1 the iou term is suppressed, so the
508
+ optimizer sees only the area-penalty gradient and naturally tends toward
509
+ smaller (more conservative) masks — the correct behavior when the initial
510
+ prediction is near-empty (Null frames).
511
+ """
512
+ r_iou = iou.mean()
513
+ r_area = torch.sigmoid(lrm / cfg.area_temp).mean()
514
+ return cfg.lambda_iou * e0 * r_iou - cfg.lambda_area * r_area
515
+
516
+
517
+ def _task_reward_stage2(
518
+ q: torch.Tensor, # [1, 256] float32
519
+ lrm: torch.Tensor, # [A,1,256,256] float32
520
+ iou: torch.Tensor, # [A,1] float32
521
+ image_embeds_anchor_fp32: torch.Tensor, # [A, 256, 64, 64] float32
522
+ cfg: QLTPOConfig,
523
+ e0: float = 1.0,
524
+ ) -> torch.Tensor:
525
+ """Stage 2 task reward: Stage 1 + R_align_det (z_in/z_out are stopgrad)."""
526
+ r_s1 = _task_reward_stage1(lrm, iou, cfg, e0)
527
+
528
+ A = lrm.shape[0]
529
+ masks_64 = F.interpolate(
530
+ torch.sigmoid(lrm.squeeze(1) / cfg.area_temp).unsqueeze(1),
531
+ size=(64, 64), mode="bilinear", align_corners=False,
532
+ ).squeeze(1) # [A, 64, 64]
533
+
534
+ q_norm = F.normalize(q[0], dim=0) # [256]
535
+ r_align = torch.tensor(0.0, device=q.device)
536
+ for t in range(A):
537
+ m = masks_64[t].detach() # stopgrad on z_in/z_out
538
+ img = image_embeds_anchor_fp32[t] # [256, 64, 64]
539
+ z_in = F.normalize((img * m.unsqueeze(0)).sum(dim=[1, 2]) / (m.sum() + 1e-6), dim=0)
540
+ z_out = F.normalize((img * (1 - m).unsqueeze(0)).sum(dim=[1, 2]) / ((1 - m).sum() + 1e-6), dim=0)
541
+ r_align = r_align + q_norm @ z_in - cfg.beta_align * (q_norm @ z_out)
542
+ r_align = r_align / A
543
+
544
+ return r_s1 + cfg.lambda_align * r_align
545
+
546
+
547
+ def _task_reward_stage3(
548
+ q: torch.Tensor,
549
+ lrm: torch.Tensor,
550
+ iou: torch.Tensor,
551
+ image_embeds_anchor_fp32: torch.Tensor,
552
+ cfg: QLTPOConfig,
553
+ e0: float = 1.0,
554
+ ) -> torch.Tensor:
555
+ """Stage 3 task reward: Stage 2 + R_temp_feat."""
556
+ r_s2 = _task_reward_stage2(q, lrm, iou, image_embeds_anchor_fp32, cfg, e0)
557
+
558
+ A = lrm.shape[0]
559
+ if A < 2:
560
+ return r_s2
561
+
562
+ masks_64 = F.interpolate(
563
+ torch.sigmoid(lrm.squeeze(1) / cfg.area_temp).unsqueeze(1),
564
+ size=(64, 64), mode="bilinear", align_corners=False,
565
+ ).squeeze(1) # [A, 64, 64]
566
+
567
+ z_ins = []
568
+ for t in range(A):
569
+ m = masks_64[t].detach()
570
+ img = image_embeds_anchor_fp32[t]
571
+ z_in = F.normalize((img * m.unsqueeze(0)).sum(dim=[1, 2]) / (m.sum() + 1e-6), dim=0)
572
+ z_ins.append(z_in)
573
+
574
+ r_temp = sum(z_ins[t] @ z_ins[t + 1] for t in range(A - 1)) / (A - 1)
575
+ return r_s2 + cfg.lambda_temp * r_temp
576
+
577
+
578
+ def _compute_task_reward(
579
+ q: torch.Tensor,
580
+ lrm: torch.Tensor,
581
+ iou: torch.Tensor,
582
+ image_embeds_anchor_fp32: torch.Tensor,
583
+ cfg: QLTPOConfig,
584
+ e0: float = 1.0,
585
+ ) -> torch.Tensor:
586
+ """Dispatch to the correct stage's task reward."""
587
+ if cfg.stage == 1:
588
+ return _task_reward_stage1(lrm, iou, cfg, e0)
589
+ if cfg.stage == 2:
590
+ return _task_reward_stage2(q, lrm, iou, image_embeds_anchor_fp32, cfg, e0)
591
+ return _task_reward_stage3(q, lrm, iou, image_embeds_anchor_fp32, cfg, e0)
592
+
593
+
594
+ def _compute_full_reward(
595
+ q: torch.Tensor,
596
+ lrm: torch.Tensor,
597
+ iou: torch.Tensor,
598
+ image_embeds_anchor_fp32: torch.Tensor,
599
+ q_init: torch.Tensor,
600
+ cfg: QLTPOConfig,
601
+ e0: float = 1.0,
602
+ ) -> torch.Tensor:
603
+ """Full reward = task reward + L2 regularization (used for backward)."""
604
+ r_task = _compute_task_reward(q, lrm, iou, image_embeds_anchor_fp32, cfg, e0)
605
+ r_reg = (q - q_init).pow(2).sum()
606
+ return r_task - cfg.lambda_reg * r_reg
607
+
608
+
609
+ # ---------------------------------------------------------------------------
610
+ # Stage 0: gradient connectivity check
611
+ # ---------------------------------------------------------------------------
612
+
613
+ def check_grad_connectivity(
614
+ F_init: torch.Tensor, # [1, 256] any dtype
615
+ image_embeds: torch.Tensor, # [T, 256, 64, 64] any dtype
616
+ anchor_indices: List[int],
617
+ sam_model,
618
+ model_dtype: torch.dtype,
619
+ num_steps: int = 5,
620
+ lr: float = 0.0,
621
+ ) -> dict:
622
+ """Stage 0: verify ∂R_iou_pred/∂q ≠ 0 and reward rises with Adam maximize.
623
+
624
+ Runs num_steps of Adam on R = R_iou_pred only (the simplest differentiable
625
+ reward, no custom ops required). Returns a diagnostic dict.
626
+
627
+ Usage:
628
+ diag = check_grad_connectivity(F_init, image_embeds, anchors, sam, dtype)
629
+ print(diag['grad_norm_step0'], diag['reward_trajectory'])
630
+ # expect grad_norm > 0 and rewards non-decreasing
631
+ """
632
+ device = F_init.device
633
+ image_embeds_anchor = image_embeds[anchor_indices].float().detach()
634
+ dense_emb = _precompute_dense_emb(sam_model, model_dtype, device).float().detach()
635
+ dense_pe = sam_model.prompt_encoder.get_dense_pe().to(device).float().detach()
636
+ mask_dec = sam_model.mask_decoder
637
+
638
+ q_init_fp32 = F_init.float().detach()
639
+ if lr <= 0:
640
+ lr = 0.01 * (q_init_fp32.norm() / (q_init_fp32.numel() ** 0.5)).item()
641
+
642
+ q = torch.nn.Parameter(q_init_fp32.clone())
643
+ optimizer = torch.optim.Adam([q], lr=lr, maximize=True)
644
+
645
+ grad_norms, rewards = [], []
646
+ for step in range(num_steps):
647
+ optimizer.zero_grad()
648
+ lrm, iou = _decode_on_anchors_diff(q, image_embeds_anchor, dense_emb, mask_dec, dense_pe)
649
+ R = iou.mean()
650
+ R.backward()
651
+ grad_norm = q.grad.norm().item() if q.grad is not None else 0.0
652
+ grad_norms.append(grad_norm)
653
+ rewards.append(R.item())
654
+ optimizer.step()
655
+
656
+ return {
657
+ "grad_norm_step0": grad_norms[0],
658
+ "grad_norms": grad_norms,
659
+ "reward_trajectory": rewards,
660
+ "gradient_connected": grad_norms[0] > 1e-8,
661
+ }
662
+
663
+
664
+ # ---------------------------------------------------------------------------
665
+ # Stage 1–3: q-LTPO-autograd main optimizer
666
+ # ---------------------------------------------------------------------------
667
+
668
+ def q_ltpo_autograd(
669
+ F_init: torch.Tensor, # [1, 256] any dtype on CUDA
670
+ image_embeds: torch.Tensor, # [T, 256, 64, 64] any dtype on CUDA
671
+ anchor_indices: List[int],
672
+ sam_model,
673
+ model_dtype: torch.dtype,
674
+ cfg: QLTPOConfig,
675
+ ) -> torch.Tensor:
676
+ """Optimise the SAM prompt token q at test time via Adam maximize.
677
+
678
+ q is initialised to F_init (= Fseg after text_hidden_fcs projection).
679
+ The prompt encoder is bypassed: sparse_emb = q.unsqueeze(1), identical
680
+ to what prompt_encoder produces when text_embeds is the only prompt.
681
+
682
+ All computation is done in float32 to avoid fp16 gradient truncation.
683
+ Returns best_q as float32 [1, 256]. Falls back to F_init when gating
684
+ rejects all updates.
685
+ """
686
+ device = F_init.device
687
+
688
+ # ── Precompute constants (float32, detached) ──────────────────────────
689
+ q_init_fp32 = F_init.float().detach()
690
+ image_embeds_anchor = image_embeds[anchor_indices].float().detach()
691
+ dense_emb = _precompute_dense_emb(sam_model, model_dtype, device).float().detach()
692
+ dense_pe = sam_model.prompt_encoder.get_dense_pe().to(device).float().detach()
693
+ mask_dec = sam_model.mask_decoder
694
+
695
+ # ── Auto-scale lr and max_drift from q_init magnitude ─────────────────
696
+ rms = q_init_fp32.norm() / (q_init_fp32.numel() ** 0.5)
697
+ lr = cfg.lr if cfg.lr > 0 else 0.01 * rms.item()
698
+ max_drift = cfg.max_drift if cfg.max_drift > 0 else 0.5 * q_init_fp32.norm().item()
699
+
700
+ # ── Baseline forward + e0 existence prior ────────────────────────────
701
+ with torch.no_grad():
702
+ lrm0, iou0 = _decode_on_anchors_diff(
703
+ q_init_fp32, image_embeds_anchor, dense_emb, mask_dec, dense_pe
704
+ )
705
+ # e0 = stopgrad(R_area_soft(q_init)): fixes the scalar before the loop.
706
+ # Suppresses R_iou when the initial mask is near-empty (existence prior).
707
+ r_area_soft_init = torch.sigmoid(lrm0 / cfg.area_temp).mean().item()
708
+ e0 = _compute_e0(r_area_soft_init, cfg)
709
+
710
+ R_init_task = _compute_task_reward(
711
+ q_init_fp32, lrm0, iou0, image_embeds_anchor, cfg, e0=e0
712
+ ).item()
713
+
714
+ # ── Optimisation setup ────────────────────────────────────────────────
715
+ q = torch.nn.Parameter(q_init_fp32.clone())
716
+ optimizer = torch.optim.Adam([q], lr=lr, maximize=True)
717
+
718
+ best_q = q.detach().clone()
719
+ best_reward = R_init_task
720
+ hit_clip = False
721
+
722
+ # ── Optimisation loop ─────────────────────────────────────────────────
723
+ for step in range(cfg.T):
724
+ optimizer.zero_grad()
725
+
726
+ lrm, iou = _decode_on_anchors_diff(
727
+ q, image_embeds_anchor, dense_emb, mask_dec, dense_pe
728
+ )
729
+ R_full = _compute_full_reward(q, lrm, iou, image_embeds_anchor, q_init_fp32, cfg, e0=e0)
730
+ R_full.backward()
731
+ optimizer.step()
732
+
733
+ # Hard L2 norm clip: keep q within max_drift ball around q_init
734
+ with torch.no_grad():
735
+ diff = q - q_init_fp32
736
+ d = diff.norm()
737
+ if d > max_drift:
738
+ q.copy_(q_init_fp32 + diff * (max_drift / d))
739
+ hit_clip = True
740
+
741
+ # Fresh no_grad forward on the post-step q_{N+1} for correct tracking.
742
+ # (Pre-step lrm/iou would mismatch the updated q, causing wrong best_q.)
743
+ with torch.no_grad():
744
+ lrm_eval, iou_eval = _decode_on_anchors_diff(
745
+ q.detach(), image_embeds_anchor, dense_emb, mask_dec, dense_pe
746
+ )
747
+ r_task = _compute_task_reward(
748
+ q.detach(), lrm_eval, iou_eval, image_embeds_anchor, cfg, e0=e0
749
+ ).item()
750
+ if r_task > best_reward:
751
+ best_reward = r_task
752
+ best_q = q.detach().clone()
753
+
754
+ # ── Reward gating: clean re-eval of best_q vs q_init ─────────────────
755
+ with torch.no_grad():
756
+ lrm_b, iou_b = _decode_on_anchors_diff(
757
+ best_q, image_embeds_anchor, dense_emb, mask_dec, dense_pe
758
+ )
759
+ R_best_task = _compute_task_reward(
760
+ best_q, lrm_b, iou_b, image_embeds_anchor, cfg, e0=e0
761
+ ).item()
762
+
763
+ area_init = (lrm0 > 0).float().mean().item()
764
+ effective_gate = (
765
+ cfg.null_gate_delta
766
+ if (cfg.null_gate_delta > 0 and area_init < cfg.null_area_threshold)
767
+ else cfg.gate_delta
768
+ )
769
+ accepted = R_best_task > R_init_task + effective_gate
770
+
771
+ # ── Per-sample diagnostics ────────────────────────────────────────────
772
+ _q_ltpo_stats.append({
773
+ "accepted": accepted,
774
+ "reward_gain": R_best_task - R_init_task,
775
+ "drift": (best_q - q_init_fp32).norm().item(),
776
+ "hit_clip": hit_clip,
777
+ "e0": e0,
778
+ "R_iou_pred_init": iou0.mean().item(),
779
+ "R_iou_pred_best": iou_b.mean().item(),
780
+ "area_hard_init": area_init,
781
+ "area_hard_best": (lrm_b > 0).float().mean().item(),
782
+ })
783
+
784
+ if not accepted:
785
+ return F_init.float()
786
+ return best_q
train.py ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import transformers
2
+ from datasets import REFAVS
3
+ from configs import args
4
+ from torch.utils.data import DataLoader
5
+ from functools import partial
6
+ from models.llava import conversation as conversation_lib
7
+ # from models.avs_model import VISAForCausalLM
8
+ from models.avs_model import Simtoken_ForCausalLM
9
+
10
+ import torch
11
+ from transformers import AutoConfig
12
+ from peft import LoraConfig, get_peft_model
13
+ from torch import optim
14
+ from torch.optim import AdamW
15
+ from transformers import get_cosine_schedule_with_warmup
16
+ from tqdm import tqdm
17
+
18
+ from utils import utility
19
+ import random
20
+ import numpy as np
21
+ import re
22
+ import time
23
+ import os
24
+
25
+
26
+ import warnings
27
+ warnings.filterwarnings("ignore")
28
+
29
+ from transformers import logging
30
+ logging.set_verbosity_error()
31
+
32
+
33
+ IGNORE_INDEX = -100
34
+ IMAGE_TOKEN_INDEX = -200
35
+ DEFAULT_IMAGE_TOKEN = "<image>"
36
+ DEFAULT_IMAGE_PATCH_TOKEN = "<im_patch>"
37
+ DEFAULT_IM_START_TOKEN = "<im_start>"
38
+ DEFAULT_IM_END_TOKEN = "<im_end>"
39
+ DEFAULT_VIDEO_TOKEN = "<video>"
40
+
41
+ AUDIO_TOKEN_INDEX = -300
42
+ DEFAULT_AUDIO_TOKEN = "<audio>"
43
+
44
+ def set_seed(seed: int = 42):
45
+ random.seed(seed)
46
+ np.random.seed(seed)
47
+ torch.manual_seed(seed)
48
+ torch.cuda.manual_seed(seed)
49
+ torch.cuda.manual_seed_all(seed)
50
+
51
+ os.environ["PYTHONHASHSEED"] = str(seed)
52
+ os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8"
53
+
54
+ torch.backends.cudnn.deterministic = True
55
+ torch.backends.cudnn.benchmark = False
56
+
57
+
58
+ def seed_worker(worker_id):
59
+
60
+ worker_seed = torch.initial_seed() % 2**32
61
+ np.random.seed(worker_seed)
62
+ random.seed(worker_seed)
63
+
64
+
65
+ def dict_to_cuda(input_dict):
66
+ for k, v in input_dict.items():
67
+ if isinstance(input_dict[k], torch.Tensor):
68
+ input_dict[k] = v.cuda(non_blocking=True)
69
+ elif (
70
+ isinstance(input_dict[k], list)
71
+ and len(input_dict[k]) > 0
72
+ and isinstance(input_dict[k][0], torch.Tensor)
73
+ ):
74
+ input_dict[k] = [ele.cuda(non_blocking=True) for ele in v]
75
+ return input_dict
76
+
77
+ def tokenizer_image_audio_token(prompt, tokenizer, image_token_index=IMAGE_TOKEN_INDEX, audio_token_index=AUDIO_TOKEN_INDEX, num_frames=10, return_tensors=None):
78
+
79
+ prompt_chunks = re.split(r'(<image>|<audio>|<video>)', prompt)
80
+
81
+
82
+ prompt_chunks = [chunk for chunk in prompt_chunks if chunk]
83
+
84
+ text_chunks = []
85
+ token_types = []
86
+ for chunk in prompt_chunks:
87
+ if chunk == "<image>":
88
+ token_types.append("image")
89
+ elif chunk == "<audio>":
90
+ token_types.append("audio")
91
+ elif chunk == "<video>":
92
+ token_types.append("video")
93
+ else:
94
+ text_chunks.append(chunk)
95
+
96
+ tokenized_chunks = [tokenizer(chunk).input_ids for chunk in text_chunks]
97
+
98
+ def insert_separators(text_chunks, tokenized_chunks, token_types, image_token_index, audio_token_index, num_frames):
99
+ input_ids = []
100
+ offset = 0
101
+ if (
102
+ len(tokenized_chunks) > 0
103
+ and len(tokenized_chunks[0]) > 0
104
+ and tokenized_chunks[0][0] == tokenizer.bos_token_id
105
+ ):
106
+ offset = 1
107
+ input_ids.append(tokenized_chunks[0][0])
108
+
109
+ min_length = min(len(text_chunks), len(token_types))
110
+ for i in range(min_length):
111
+
112
+ input_ids.extend(tokenized_chunks[i][offset:])
113
+
114
+ if token_types[i] == "image":
115
+ input_ids.append(image_token_index)
116
+ elif token_types[i] == "audio":
117
+ input_ids.append(audio_token_index)
118
+ elif token_types[i] == "video":
119
+ input_ids.extend([image_token_index] * num_frames)
120
+
121
+
122
+ if len(text_chunks) > min_length:
123
+ input_ids.extend(tokenized_chunks[min_length][offset:])
124
+
125
+ return input_ids
126
+
127
+ input_ids = insert_separators(text_chunks, tokenized_chunks, token_types, image_token_index, audio_token_index, num_frames)
128
+
129
+ if return_tensors is not None:
130
+ if return_tensors == "pt":
131
+ return torch.tensor(input_ids, dtype=torch.long)
132
+ raise ValueError(f"Unsupported tensor type: {return_tensors}")
133
+ return input_ids
134
+
135
+ def collate_fn(batch, tokenizer=None):
136
+ vids = []
137
+ images = []
138
+ image_clips = []
139
+ masks = []
140
+ conversations = []
141
+ audio_feats = []
142
+ image_feats = []
143
+ resizes = []
144
+ orgsizes = []
145
+ refs = []
146
+ refs_num = []
147
+ fids = []
148
+
149
+
150
+ for data in batch:
151
+ vids.append(data['vid'])
152
+ images.append(data['image'])
153
+ image_clips.append(data['img_clip'])
154
+ masks.append(data['mask'])
155
+ conversations.append(data['conversation'])
156
+ audio_feats.append(data['feat_aud'])
157
+ resizes.append(data['resize'])
158
+ orgsizes.append(data['orgsize'])
159
+ image_feats.append(data['feat_sam'])
160
+ refs_num.append(len(data['ref']))
161
+ fids.append(data['fids'])
162
+
163
+ refs.append(data['ref'][0])
164
+
165
+
166
+ # input_ids = [tokenizer_image_token(conv, tokenizer, return_tensors="pt") for conv in conversations]
167
+ input_ids = [tokenizer_image_audio_token(conv, tokenizer, return_tensors="pt") for conv in conversations] # list
168
+ input_ids = torch.nn.utils.rnn.pad_sequence(input_ids, batch_first=True, padding_value=tokenizer.pad_token_id)
169
+ attention_masks = input_ids.ne(tokenizer.pad_token_id)
170
+
171
+ ref_ids = [tokenizer_image_audio_token(ref, tokenizer, return_tensors="pt") for ref in refs]
172
+
173
+ conv = conversation_lib.default_conversation.copy()
174
+ labels = input_ids.clone()
175
+
176
+ # sep = conv.sep + conv.roles[1] + ": " # “###Assistant:”
177
+ sep = 'Sure, it is [SEG]'
178
+
179
+ for conversation, target in zip(conversations, labels):
180
+
181
+ parts = conversation.split(sep)
182
+ # print(parts)
183
+
184
+ cur_len = 1
185
+ target[:cur_len] = IGNORE_INDEX
186
+
187
+ sep_len = len(tokenizer_image_audio_token(sep, tokenizer)) - 1
188
+
189
+
190
+ for i in range(len(parts)-1):
191
+ part_len = len(tokenizer_image_audio_token(parts[i], tokenizer)) - 2
192
+ target[cur_len: cur_len + part_len] = IGNORE_INDEX
193
+ cur_len += part_len + sep_len
194
+
195
+ target[cur_len:] = IGNORE_INDEX
196
+
197
+
198
+ return {"vids": vids,
199
+ "images": images, # list[B]:[T, 3, 1024, 1024]
200
+ "images_clip": image_clips, # list[B]:[T, 3, 224, 224]
201
+ "masks": masks, # list[B]:[num_ref, T, H, W]
202
+ "convs": conversations, # list[B]: str
203
+ "input_ids": input_ids, # list[B]:[max_len]
204
+ "attention_masks": attention_masks, # list[B]:[max_len]
205
+ "labels": labels, # list[B]:[max_len]
206
+ "audio_feats": audio_feats, # list[B]:[10, 128]
207
+ "resizes": resizes, # list[B]
208
+ "orgsizes": orgsizes, # list[B]
209
+ "image_feats": image_feats,
210
+ "ref_ids": ref_ids, # list[B]: [ref_id_len]
211
+ "refs_num": refs_num,
212
+ "fids": fids
213
+ }
214
+
215
+
216
+ import torch.multiprocessing as mp
217
+ if __name__ == "__main__":
218
+ mp.set_start_method("spawn")
219
+ set_seed(42)
220
+ tokenizer = transformers.AutoTokenizer.from_pretrained(
221
+ args.mllm,
222
+ cache_dir=None,
223
+ model_max_length=2048, # 2048
224
+ padding_side="right",
225
+ use_fast=False,
226
+ )
227
+
228
+ tokenizer.pad_token = tokenizer.unk_token
229
+ num_added_tokens = tokenizer.add_tokens("[SEG]")
230
+ seg_token_idx = tokenizer("[SEG]", add_special_tokens=False).input_ids[0] # 32000
231
+ print("seg_token_idx: ", seg_token_idx)
232
+
233
+ train_dataset = REFAVS('train', args, tokenizer, input_type='refer')
234
+ val_dataset_s_refer = REFAVS('test_s', args, tokenizer, input_type='refer')
235
+ val_dataset_u_refer = REFAVS('test_u', args, tokenizer, input_type='refer')
236
+ val_dataset_n_refer = REFAVS('test_n', args, tokenizer, input_type='refer')
237
+
238
+
239
+ g = torch.Generator()
240
+ g.manual_seed(42)
241
+
242
+ train_dataloader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, num_workers=8, worker_init_fn=seed_worker,collate_fn=partial(collate_fn, tokenizer=tokenizer), generator=g)
243
+
244
+ val_dataloader_s_refer = DataLoader(val_dataset_s_refer, batch_size=4, shuffle=False, num_workers=0, collate_fn=partial(collate_fn, tokenizer=tokenizer))
245
+ val_dataloader_u_refer = DataLoader(val_dataset_u_refer, batch_size=4, shuffle=False, num_workers=0, collate_fn=partial(collate_fn, tokenizer=tokenizer))
246
+ val_dataloader_n_refer = DataLoader(val_dataset_n_refer, batch_size=4, shuffle=False, num_workers=0, collate_fn=partial(collate_fn, tokenizer=tokenizer))
247
+
248
+
249
+ model_args = {
250
+ "train_mask_decoder": True,
251
+ "out_dim": 256, # 256
252
+ "ce_loss_weight": 1.0,
253
+ "dice_loss_weight": 0.5,
254
+ "bce_loss_weight": 2.0,
255
+ "seg_token_idx": seg_token_idx,
256
+ "vision_pretrained": args.vision_pretrained, # sam_vit_h_xxx.pth
257
+ "vision_tower": args.vision_tower,
258
+ "use_im_start_end": False,
259
+ "compress": args.compress,
260
+ "start": args.start,
261
+ }
262
+
263
+ model = Simtoken_ForCausalLM.from_pretrained(args.mllm, torch_dtype=torch.float32, low_cpu_mem_usage=True, **model_args)
264
+ print("\nmodel loaded")
265
+
266
+ model.config.eos_token_id = tokenizer.eos_token_id
267
+ model.config.bos_token_id = tokenizer.bos_token_id
268
+ model.config.pad_token_id = tokenizer.pad_token_id
269
+
270
+ model.enable_input_require_grads()
271
+ model.gradient_checkpointing_enable()
272
+
273
+ model.get_model().initialize_vision_modules(model.get_model().config)
274
+ vision_tower = model.get_model().get_vision_tower()
275
+ vision_tower.to(dtype=torch.float32, device="cuda")
276
+
277
+ model_args_from_pt = AutoConfig.from_pretrained(args.mllm)
278
+ model_args_from_pt.use_cluster = True
279
+ model_args_from_pt.freeze = False
280
+ model_args_from_pt.mm_tune = True
281
+ model_args_from_pt.spatial_cluster_rate0 = 64
282
+ model_args_from_pt.spatial_cluster_rate1 = 32
283
+ model_args_from_pt.spatial_cluster_rate2 = 16
284
+ model_args_from_pt.temporal_cluster_rate = 0.0625
285
+ model_args_from_pt.use_cluster = True
286
+ model_args_from_pt.vision_tune = False
287
+ model.get_model().initialize_cluster_modules(model_args_from_pt)
288
+
289
+ model.get_model().initialize_lisa_modules(model.get_model().config)
290
+
291
+ for p in vision_tower.parameters():
292
+ p.requires_grad = False
293
+ for p in model.get_model().mm_projector.parameters():
294
+ p.requires_grad = False
295
+
296
+ lora_r = 8
297
+ target_modules = "q_proj,v_proj"
298
+ if lora_r > 0:
299
+
300
+ def find_linear_layers(model, lora_target_modules):
301
+ cls = torch.nn.Linear
302
+ lora_module_names = set()
303
+
304
+ for name, module in model.named_modules():
305
+ if (
306
+
307
+ isinstance(module, cls)
308
+
309
+ and all(
310
+ [
311
+ x not in name
312
+ for x in [
313
+ "visual_model",
314
+ "vision_tower",
315
+ "mm_projector",
316
+ "text_hidden_fcs",
317
+ "audio_feature_layer",
318
+ ]
319
+ ]
320
+ )
321
+
322
+ and any([x in name for x in lora_target_modules])
323
+ ):
324
+
325
+ lora_module_names.add(name)
326
+ return sorted(list(lora_module_names))
327
+
328
+
329
+ lora_alpha = 16
330
+ lora_dropout = 0.05
331
+
332
+ lora_target_modules = find_linear_layers(
333
+ model, target_modules.split(",")
334
+ )
335
+ lora_config = LoraConfig(
336
+ r=lora_r,
337
+ lora_alpha=lora_alpha,
338
+ target_modules=lora_target_modules,
339
+ lora_dropout=lora_dropout,
340
+ bias="none",
341
+ task_type="CAUSAL_LM",
342
+ )
343
+
344
+ model = get_peft_model(model, lora_config)
345
+ print("\nLora deployed")
346
+
347
+ model.print_trainable_parameters()
348
+
349
+ model = model.to("cuda")
350
+ model.resize_token_embeddings(len(tokenizer))
351
+
352
+
353
+ for name, param in model.audio_feature_layer.named_parameters():
354
+ param.requires_grad = True
355
+ # print(name, param.requires_grad)
356
+ # for name, param in model.token_compressor.named_parameters():
357
+ # param.requires_grad = True
358
+
359
+
360
+ for n, p in model.named_parameters():
361
+ if any(
362
+ [
363
+ x in n
364
+ for x in ["lm_head", "embed_tokens", "mask_decoder", "text_hidden_fcs"]
365
+ ]
366
+ ):
367
+ p.requires_grad = True
368
+
369
+
370
+ print("will save train model")
371
+
372
+ def valuate(model, dataloader, args, name):
373
+ model.eval()
374
+
375
+ total_iou = 0
376
+ total_fscore = 0
377
+ count = 0
378
+
379
+ for batch in tqdm(dataloader, desc=f"Evaluating on {name}"):
380
+ input_dict = dict_to_cuda(batch)
381
+ with torch.no_grad():
382
+ output_dict = model.forward(images=input_dict["images"],
383
+ images_clip=input_dict["images_clip"],
384
+ audio_features=input_dict["audio_feats"],
385
+ image_features=input_dict["image_feats"],
386
+ input_ids=input_dict["input_ids"],
387
+ labels=input_dict["labels"],
388
+ attention_masks=input_dict["attention_masks"],
389
+ masks_list=input_dict["masks"],
390
+ resize_list=input_dict["resizes"],
391
+ orgsize_list=input_dict["orgsizes"],
392
+ conversation_list=input_dict["convs"],
393
+ refs_num=input_dict["refs_num"],
394
+ fids=input_dict["fids"],
395
+ vids=input_dict["vids"],
396
+ contrast=args.ct_weight,
397
+ ref_ids=input_dict["ref_ids"],
398
+ inference=True)
399
+ pred_masks = output_dict["pred_masks"] # list[B]:[num_seg, T, H, W]
400
+ gt_masks = output_dict["gt_masks"] # list[B]:[num_seg, T, H, W]
401
+ for i in range(len(pred_masks)):
402
+ num_seg = pred_masks[i].shape[0]
403
+ T = pred_masks[i].shape[1]
404
+ iou = utility.mask_iou(pred_masks[i], gt_masks[i])
405
+ fscore = utility.Eval_Fmeasure(pred_masks[i], gt_masks[i], None)
406
+
407
+ total_iou += iou * num_seg * T
408
+ total_fscore += fscore * num_seg * T
409
+ count += num_seg * T
410
+
411
+ print(f"\n valuate on {name}: miou: {total_iou/count} fscore: {total_fscore/count}")
412
+
413
+ with open(os.path.join(args.log_root, f'{args.name}.txt'), "a") as f:
414
+ f.write(f"valuate on {name}: miou {total_iou/count} true fscore {total_fscore/count} \n")
415
+
416
+
417
+ # ---------------train------------------------------------------
418
+
419
+ model.train()
420
+ epochs = args.epochs
421
+ print("init lr:", args.lr)
422
+ optimizer = AdamW(model.parameters(), lr=args.lr, betas=(0.9, 0.95), weight_decay=0.01)
423
+
424
+ gradient_accumulation_steps = int(16 // args.batch_size)
425
+ step_per_epoch = len(train_dataloader) // gradient_accumulation_steps
426
+ total_steps = epochs * step_per_epoch
427
+ warmup_steps = int(total_steps * 0.1)
428
+
429
+ scheduler = get_cosine_schedule_with_warmup(
430
+ optimizer,
431
+ num_warmup_steps=warmup_steps,
432
+ num_training_steps=total_steps,
433
+ )
434
+
435
+
436
+ for epoch in range(epochs):
437
+
438
+ model.train()
439
+ optimizer.zero_grad()
440
+ running_loss = 0.0
441
+
442
+ loop = tqdm(train_dataloader, desc=f"Training Epoch {epoch + 1}/{epochs}")
443
+ for step, batch in enumerate(loop):
444
+ input_dict = dict_to_cuda(batch)
445
+ output_dict = model.forward(images=input_dict["images"],
446
+ images_clip=input_dict["images_clip"],
447
+ audio_features=input_dict["audio_feats"],
448
+ image_features=input_dict["image_feats"],
449
+ input_ids=input_dict["input_ids"],
450
+ labels=input_dict["labels"],
451
+ attention_masks=input_dict["attention_masks"],
452
+ masks_list=input_dict["masks"],
453
+ resize_list=input_dict["resizes"],
454
+ orgsize_list=input_dict["orgsizes"],
455
+ conversation_list=input_dict["convs"],
456
+ refs_num=input_dict["refs_num"],
457
+ fids=input_dict["fids"],
458
+ vids=input_dict["vids"],
459
+ contrast=args.ct_weight,
460
+ ref_ids=input_dict["ref_ids"],
461
+ epoch=epoch,
462
+ inference=False)
463
+
464
+ loss = output_dict["loss"]
465
+ loss = loss / gradient_accumulation_steps
466
+ loss.backward()
467
+ running_loss += loss.item()
468
+
469
+
470
+ if (step + 1) % gradient_accumulation_steps == 0:
471
+ optimizer.step()
472
+ scheduler.step()
473
+ optimizer.zero_grad()
474
+
475
+ current_lr = scheduler.get_lr()[0]
476
+ loop.set_postfix(lr=current_lr, loss=running_loss / ((step + 1) / gradient_accumulation_steps))
477
+
478
+ print(f" Epoch {epoch + 1}, Loss:{running_loss / ((step + 1) / gradient_accumulation_steps) :.4f}, Learning Rate:{scheduler.get_last_lr()[0]:.6f}")
479
+
480
+
481
+ with open(os.path.join(args.log_root, f'{args.name}.txt'), "a") as f:
482
+ f.write(f"Epoch {epoch}: running_loss {running_loss / len(train_dataloader) * gradient_accumulation_steps} Learning Rate:{scheduler.get_last_lr()[0]:.6f}\n")
483
+
484
+
485
+ torch.save(model.state_dict(), os.path.join(args.checkpoint_root, f"{args.name}.pth"))
486
+ print(f"trained model saved as {args.name}.pth")
487
+
488
+ # ---------------test on seen & unseen ------------------------------------------
489
+ model.eval()
490
+
491
+ valuate(model, val_dataloader_s_refer, args, 'test_s_refer')
492
+ valuate(model, val_dataloader_u_refer, args, 'test_u_refer')
493
+
494
+ # ---------------test on Null ------------------------------------------
495
+ model.eval()
496
+
497
+ total_metric = 0
498
+ count = 0
499
+
500
+ for batch in tqdm(val_dataloader_n_refer, desc=f"Evaluating on test_n_refer"):
501
+ input_dict = dict_to_cuda(batch)
502
+ with torch.no_grad():
503
+ output_dict = model.forward(images=input_dict["images"],
504
+ images_clip=input_dict["images_clip"],
505
+ audio_features=input_dict["audio_feats"],
506
+ image_features=input_dict["image_feats"],
507
+ input_ids=input_dict["input_ids"],
508
+ labels=input_dict["labels"],
509
+ attention_masks=input_dict["attention_masks"],
510
+ masks_list=input_dict["masks"],
511
+ resize_list=input_dict["resizes"],
512
+ orgsize_list=input_dict["orgsizes"],
513
+ conversation_list=input_dict["convs"],
514
+ refs_num=input_dict["refs_num"],
515
+ fids=input_dict["fids"],
516
+ vids=input_dict["vids"],
517
+ contrast=args.ct_weight,
518
+ ref_ids=input_dict["ref_ids"],
519
+ inference=True)
520
+ pred_masks = output_dict["pred_masks"] # list[B]:[num_seg, T, H, W]
521
+ gt_masks = output_dict["gt_masks"] # list[B]:[num_seg, T, H, W]
522
+ for i in range(len(pred_masks)):
523
+ num_seg = pred_masks[i].shape[0]
524
+ T = pred_masks[i].shape[1]
525
+ null_metric = utility.metric_s_for_null(pred_masks[i])
526
+
527
+ total_metric += null_metric * num_seg * T
528
+ count += num_seg * T
529
+
530
+
531
+ print(f"\n valuate on test_n_refer, metric: {total_metric/count}")
532
+
533
+ with open(os.path.join(args.log_root, f'{args.name}.txt'), "a") as f:
534
+ f.write(f"\n valuate on test_n_refer: metric {total_metric/count} \n")