cheetah003 commited on
Commit
29c5a57
1 Parent(s): b352512

first commit

Browse files

initial version

features/Chinese_batch_frame_output_list.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c7ba331cd1db032987eadfc624172f34172519047283d72381d57a488dab27c2
3
+ size 36864128
features/Chinese_batch_visual_output_list.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c55e9f579a5fb77acec9e26e87e63f8284ff63e0fa933321db27ea3e2b569c5b
3
+ size 3072128
features/English_batch_frame_output_list.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ec6b4ac3f600f7cd07974f929ff926d1a03b84b2f52a5a6a250867aacfc9e39c
3
+ size 36864128
features/English_batch_visual_output_list.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:01edc18afdfd18d495d1bc4672c71d8d5088f77a40a98c359921f03f09ae15d8
3
+ size 3072128
main_task_retrieval.py ADDED
@@ -0,0 +1,639 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+ from __future__ import division
3
+ from __future__ import unicode_literals
4
+ from __future__ import print_function
5
+ import os
6
+
7
+ import torch
8
+ from torch.utils.data import (SequentialSampler)
9
+ import numpy as np
10
+ import random
11
+ from thop import profile
12
+
13
+ from metrics import logging_rank
14
+ import time
15
+ import argparse
16
+ from sklearn import preprocessing
17
+ from transformers import BertTokenizer, AutoTokenizer, AutoModel
18
+ from tensorboardX import SummaryWriter
19
+ from modules.file_utils import PYTORCH_PRETRAINED_BERT_CACHE
20
+ from modules.tokenization_clip import SimpleTokenizer as ClipTokenizer
21
+ from modules.modeling import BirdModel_VT, BirdPreTrainedModel, BirdModel
22
+ from modules.optimization import BertAdam
23
+ from dataloaders.dataloader import DATALOADER_DICT
24
+ from modules.until_module import get_dual_matrix
25
+ from util import parallel_apply, get_logger
26
+ from torch.cuda.amp import autocast, GradScaler
27
+
28
+ torch.distributed.init_process_group(backend="nccl")
29
+
30
+ global logger
31
+
32
+
33
+ def get_args(description='CLIP4Clip on Retrieval Task'):
34
+ parser = argparse.ArgumentParser(description=description)
35
+ parser.add_argument("--do_pretrain", action='store_true', help="Whether to run training.")
36
+ parser.add_argument("--do_train", action='store_true', help="Whether to run training.")
37
+ parser.add_argument("--do_eval", action='store_true', help="Whether to run eval on the dev set.")
38
+ parser.add_argument("--do_params", action='store_true', help="text the params of the model.")
39
+ parser.add_argument("--use_frame_fea", action='store_true', help="whether use frame feature matching text")
40
+ parser.add_argument('--task', type=str, default="retrieval", choices=["retrieval_VT", "retrieval"],
41
+ help="choose downstream task.")
42
+ parser.add_argument('--dataset', type=str, default="bird", choices=["bird", "msrvtt", "vatex", "msvd"],
43
+ help="choose dataset.")
44
+ parser.add_argument('--num_thread_reader', type=int, default=1, help='')
45
+ parser.add_argument('--lr', type=float, default=0.0001, help='initial learning rate')
46
+ parser.add_argument('--text_lr', type=float, default=0.00001, help='text encoder learning rate')
47
+ parser.add_argument('--epochs', type=int, default=20, help='upper epoch limit')
48
+ parser.add_argument('--batch_size', type=int, default=256, help='batch size')
49
+ parser.add_argument('--batch_size_val', type=int, default=3500, help='batch size eval')
50
+ parser.add_argument('--lr_decay', type=float, default=0.9, help='Learning rate exp epoch decay')
51
+ parser.add_argument('--weight_decay', type=float, default=0.2, help='Learning rate exp epoch decay')
52
+ parser.add_argument('--n_display', type=int, default=100, help='Information display frequence')
53
+ parser.add_argument('--seed', type=int, default=42, help='random seed')
54
+ parser.add_argument('--max_words', type=int, default=32, help='')
55
+ parser.add_argument('--max_frames', type=int, default=12, help='')
56
+ parser.add_argument('--top_frames', type=int, default=3, help='')
57
+ parser.add_argument('--frame_sample', type=str, default="uniform", choices=["uniform", "random", "uniform_random"],
58
+ help='frame sample strategy')
59
+ parser.add_argument('--frame_sample_len', type=str, default="fix", choices=["dynamic", "fix"],
60
+ help='use dynamic frame length of fix frame length')
61
+ parser.add_argument('--language', type=str, default="chinese", choices=["chinese", "english"],
62
+ help='language for text encoder')
63
+ parser.add_argument('--use_temp', action='store_true', help='whether to use temporal transformer')
64
+
65
+ parser.add_argument("--logdir", default=None, type=str, required=False, help="log dir for tensorboardX writer")
66
+ parser.add_argument("--output_dir", default=None, type=str, required=True,
67
+ help="The output directory where the model predictions and checkpoints will be written.")
68
+ parser.add_argument("--cross_model", default="cross-base", type=str, required=False, help="Cross module")
69
+ parser.add_argument("--init_model", default=None, type=str, required=False, help="Initial model.")
70
+ parser.add_argument("--warmup_proportion", default=0.1, type=float,
71
+ help="Proportion of training to perform linear learning rate warmup for. E.g., 0.1 = 10%% of training.")
72
+ parser.add_argument('--gradient_accumulation_steps', type=int, default=1,
73
+ help="Number of updates steps to accumulate before performing a backward/update pass.")
74
+ parser.add_argument('--n_gpu', type=int, default=1, help="Changed in the execute process.")
75
+
76
+ parser.add_argument("--cache_dir", default="", type=str,
77
+ help="Where do you want to store the pre-trained models downloaded from s3")
78
+
79
+ parser.add_argument('--enable_amp', action='store_true', help="whether to use pytorch amp")
80
+
81
+ parser.add_argument("--world_size", default=0, type=int, help="distribted training")
82
+ parser.add_argument("--local_rank", default=0, type=int, help="distribted training")
83
+ parser.add_argument("--rank", default=0, type=int, help="distribted training")
84
+ parser.add_argument('--coef_lr', type=float, default=1., help='coefficient for bert branch.')
85
+
86
+ args = parser.parse_args()
87
+
88
+ # Check paramenters
89
+ if args.gradient_accumulation_steps < 1:
90
+ raise ValueError("Invalid gradient_accumulation_steps parameter: {}, should be >= 1".format(
91
+ args.gradient_accumulation_steps))
92
+ if not args.do_train and not args.do_eval and not args.do_params:
93
+ raise ValueError("At least one of `do_train` or `do_eval` or 'do_params' must be True.")
94
+
95
+ args.batch_size = int(args.batch_size / args.gradient_accumulation_steps)
96
+
97
+ return args
98
+
99
+
100
+ def set_seed_logger(args):
101
+ global logger
102
+ # predefining random initial seeds
103
+ random.seed(args.seed)
104
+ os.environ['PYTHONHASHSEED'] = str(args.seed)
105
+ np.random.seed(args.seed)
106
+ torch.manual_seed(args.seed)
107
+ torch.cuda.manual_seed(args.seed)
108
+ torch.cuda.manual_seed_all(args.seed) # if you are using multi-GPU.
109
+ torch.backends.cudnn.benchmark = False
110
+ torch.backends.cudnn.deterministic = True
111
+
112
+ world_size = torch.distributed.get_world_size()
113
+ torch.cuda.set_device(args.local_rank)
114
+ args.world_size = world_size
115
+ rank = torch.distributed.get_rank()
116
+ args.rank = rank
117
+
118
+ if not os.path.exists(args.output_dir):
119
+ os.makedirs(args.output_dir, exist_ok=True)
120
+
121
+ logger = get_logger(os.path.join(args.output_dir, "log.txt"))
122
+ if args.local_rank == 0:
123
+ if args.logdir:
124
+ args.writer = SummaryWriter(args.logdir)
125
+ logger.info("Effective parameters:")
126
+ for key in sorted(args.__dict__):
127
+ logger.info(" <<< {}: {}".format(key, args.__dict__[key]))
128
+
129
+ return args
130
+
131
+
132
+ def init_device(args, local_rank):
133
+ global logger
134
+
135
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu", local_rank)
136
+
137
+ n_gpu = torch.cuda.device_count()
138
+ logger.info("device: {} n_gpu: {}".format(device, n_gpu))
139
+ args.n_gpu = n_gpu
140
+
141
+ if args.batch_size % args.n_gpu != 0 or args.batch_size_val % args.n_gpu != 0:
142
+ raise ValueError(
143
+ "Invalid batch_size/batch_size_val and n_gpu parameter: {}%{} and {}%{}, should be == 0".format(
144
+ args.batch_size, args.n_gpu, args.batch_size_val, args.n_gpu))
145
+
146
+ return device, n_gpu
147
+
148
+
149
+ def init_model(args, device, n_gpu, local_rank):
150
+ if args.init_model:
151
+ model_state_dict = torch.load(args.init_model, map_location='cpu')
152
+ else:
153
+ model_state_dict = None
154
+
155
+ # Prepare model
156
+ cache_dir = args.cache_dir if args.cache_dir else os.path.join(str(PYTORCH_PRETRAINED_BERT_CACHE), 'distributed')
157
+ if args.task == "retrieval_VT":
158
+ model = BirdModel_VT.from_pretrained(args.cross_model, cache_dir=cache_dir, state_dict=model_state_dict,
159
+ task_config=args)
160
+ elif args.task == "retrieval":
161
+ model = BirdModel.from_pretrained(args.cross_model, cache_dir=cache_dir, state_dict=model_state_dict,
162
+ task_config=args)
163
+ else:
164
+ raise Exception('wrong task! task should in [retrieve_VT, retrieve]')
165
+ # args.writer.add_graph(model)
166
+ model.to(device)
167
+
168
+ return model
169
+
170
+
171
+ def prep_optimizer(args, model, num_train_optimization_steps, device, n_gpu, local_rank, coef_lr=1.):
172
+ if hasattr(model, 'module'):
173
+ model = model.module
174
+
175
+ param_optimizer = list(model.named_parameters())
176
+ no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']
177
+
178
+ decay_param_tp = [(n, p) for n, p in param_optimizer if not any(nd in n for nd in no_decay)]
179
+ no_decay_param_tp = [(n, p) for n, p in param_optimizer if any(nd in n for nd in no_decay)]
180
+
181
+ decay_clip_param_tp = [(n, p) for n, p in decay_param_tp if "visual_encoder.visual." in n]
182
+ decay_chinesebert_param_tp = [(n, p) for n, p in decay_param_tp if "text_encoder." in n]
183
+ decay_noclip_param_tp = [(n, p) for n, p in decay_param_tp if
184
+ ("visual_encoder.visual." not in n) and ("text_encoder." not in n)]
185
+
186
+ no_decay_clip_param_tp = [(n, p) for n, p in no_decay_param_tp if "visual_encoder.visual." in n]
187
+ no_decay_text_param_tp = [(n, p) for n, p in no_decay_param_tp if "text_encoder." in n]
188
+ no_decay_noclip_param_tp = [(n, p) for n, p in no_decay_param_tp if
189
+ ("visual_encoder.visual." not in n) and ("text_encoder." not in n)]
190
+
191
+ weight_decay = args.weight_decay
192
+ optimizer_grouped_parameters = [
193
+ {'params': [p for n, p in decay_clip_param_tp], 'weight_decay': weight_decay, 'lr': args.lr * coef_lr},
194
+ {'params': [p for n, p in decay_chinesebert_param_tp], 'weight_decay': weight_decay, 'lr': args.text_lr},
195
+ {'params': [p for n, p in decay_noclip_param_tp], 'weight_decay': weight_decay},
196
+ {'params': [p for n, p in no_decay_clip_param_tp], 'weight_decay': 0.0, 'lr': args.lr * coef_lr},
197
+ {'params': [p for n, p in no_decay_text_param_tp], 'weight_decay': 0.0, 'lr': args.text_lr},
198
+ {'params': [p for n, p in no_decay_noclip_param_tp], 'weight_decay': 0.0}
199
+ ]
200
+
201
+ scheduler = None
202
+ optimizer = BertAdam(optimizer_grouped_parameters, lr=args.lr, warmup=args.warmup_proportion,
203
+ schedule='warmup_cosine', b1=0.9, b2=0.98, e=1e-6,
204
+ t_total=num_train_optimization_steps, weight_decay=weight_decay,
205
+ max_grad_norm=1.0)
206
+
207
+ model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[local_rank],
208
+ output_device=local_rank, find_unused_parameters=True)
209
+ # if args.local_rank == 0:
210
+ # for name, parameters in model.named_parameters():
211
+ # logger.info("name:{} requires_grad:{} size:{}".format(name, parameters.requires_grad, parameters.size()))
212
+ return optimizer, scheduler, model
213
+
214
+
215
+ def save_model(epoch, args, model, type_name=""):
216
+ # Only save the model it-self
217
+ model_to_save = model.module if hasattr(model, 'module') else model
218
+ output_model_file = os.path.join(
219
+ args.output_dir, "pytorch_model.bin.{}{}".format("" if type_name == "" else type_name + ".", epoch))
220
+ torch.save(model_to_save.state_dict(), output_model_file)
221
+ logger.info("Model saved to %s", output_model_file)
222
+ return output_model_file
223
+
224
+
225
+ def load_model(epoch, args, n_gpu, device, model_file=None):
226
+ if model_file is None or len(model_file) == 0:
227
+ model_file = os.path.join(args.output_dir, "pytorch_model.bin.{}".format(epoch))
228
+ if os.path.exists(model_file):
229
+ model_state_dict = torch.load(model_file, map_location='cpu')
230
+ if args.local_rank == 0:
231
+ logger.info("Model loaded from %s", model_file)
232
+ # Prepare model
233
+ cache_dir = args.cache_dir if args.cache_dir else os.path.join(str(PYTORCH_PRETRAINED_BERT_CACHE),
234
+ 'distributed')
235
+ if args.task == "retrieval":
236
+ model = BirdModel.from_pretrained(args.cross_model, cache_dir=cache_dir, state_dict=model_state_dict,
237
+ task_config=args)
238
+ elif args.task == "retrieval_VT":
239
+ model = BirdModel_VT.from_pretrained(args.cross_model, cache_dir=cache_dir, state_dict=model_state_dict,
240
+ task_config=args)
241
+ else:
242
+ model = None
243
+
244
+ model.to(device)
245
+ else:
246
+ model = None
247
+ return model
248
+
249
+
250
+ def train_epoch(epoch, args, model, train_dataloader, device, n_gpu, optimizer, scheduler, scaler, global_step, local_rank=0):
251
+ global logger
252
+ torch.cuda.empty_cache()
253
+ model.train()
254
+ log_step = args.n_display
255
+ start_time = time.time()
256
+ total_loss = 0
257
+ load_start_time = time.time()
258
+ for step, batch in enumerate(train_dataloader):
259
+ load_finish_time = time.time()
260
+ if global_step % log_step == 0 and local_rank == 0:
261
+ logger.info("data loader time:{}".format(load_finish_time - load_start_time))
262
+ global_step += 1
263
+ if n_gpu == 1:
264
+ # multi-gpu does scattering it-self
265
+ batch = tuple(t.to(device=device, non_blocking=True) for t in batch)
266
+
267
+ with autocast(enabled=args.enable_amp):
268
+ if args.task == "retrieval_VT":
269
+ query_ids, query_mask, video_data, video_frame, title_ids, title_mask, idx = batch
270
+ loss = model(query_ids, query_mask, video_data, video_frame, title_ids, title_mask, idx, global_step)
271
+ elif args.task == "retrieval":
272
+ query_ids, query_mask, video_data, video_frame, idx = batch
273
+ loss = model(query_ids, query_mask, video_data, video_frame, idx, global_step)
274
+ else:
275
+ raise ValueError("wrong task type:{}".format(args.task))
276
+ if n_gpu > 1:
277
+ loss = loss.mean() # mean() to average on multi-gpu.
278
+ if args.gradient_accumulation_steps > 1:
279
+ loss = loss / args.gradient_accumulation_steps
280
+ forward_time = time.time()
281
+ if args.enable_amp:
282
+ scaler.scale(loss).backward()
283
+ else:
284
+ loss.backward()
285
+ total_loss += float(loss)
286
+ backward_time = time.time()
287
+ if global_step % log_step == 0 and local_rank == 0:
288
+ logger.info("forward_time:{},backward_time:{}".format(forward_time - load_finish_time, backward_time - forward_time))
289
+
290
+ if (step + 1) % args.gradient_accumulation_steps == 0:
291
+ torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
292
+
293
+ if scheduler is not None:
294
+ scheduler.step() # Update learning rate schedule
295
+
296
+ if args.enable_amp:
297
+ scaler.step(optimizer)
298
+ scaler.update()
299
+ else:
300
+ optimizer.step()
301
+
302
+ optimizer.zero_grad()
303
+
304
+ if global_step % log_step == 0 and local_rank == 0:
305
+ logger.info("Epoch: %d/%s, Step: %d/%d, Lr: %s, Loss: %f, Time/step: %f", epoch + 1,
306
+ args.epochs, step + 1,
307
+ len(train_dataloader),
308
+ "-".join([str('%.9f' % itm) for itm in sorted(list(set(optimizer.get_lr())))]),
309
+ float(loss),
310
+ (time.time() - start_time) / (log_step * args.gradient_accumulation_steps))
311
+ if args.logdir:
312
+ # args.writer.add_scalar('loss', loss.item(), global_step=global_step)
313
+ args.writer.add_scalars('lr', {"lr%d" % i: itm for i, itm in enumerate(sorted(list(set(optimizer.get_lr()))))},
314
+ global_step=global_step)
315
+ start_time = time.time()
316
+ load_start_time = time.time()
317
+ total_loss = total_loss / len(train_dataloader)
318
+ return total_loss, global_step
319
+
320
+
321
+ def _run_on_single_gpu(model, batch_query_output_list, batch_visual_output_list, batch_title_output_list,
322
+ batch_frame_output_list):
323
+ sim_matrix = []
324
+ sim_matrix_title = []
325
+ sim_matrix_frame = []
326
+ for idx1, query_output in enumerate(batch_query_output_list):
327
+ each_row = []
328
+ title_each_row = []
329
+ frame_each_row = []
330
+ for idx2, (visual_output, title_output, frame_output) in enumerate(zip(batch_visual_output_list,
331
+ batch_title_output_list, batch_frame_output_list)):
332
+ b1b2_logits = model.loose_similarity(query_output, visual_output)
333
+ title_logits = model.loose_similarity(query_output, title_output)
334
+ frame_logits = model.loose_similarity(query_output, frame_output)
335
+ frame_logits = torch.topk(frame_logits, k=model.top_frames, dim=2)[0]
336
+ frame_logits = torch.mean(frame_logits, dim=2)
337
+ b1b2_logits = b1b2_logits.cpu().detach().numpy()
338
+ title_logits = title_logits.cpu().detach().numpy()
339
+ frame_logits = frame_logits.cpu().detach().numpy()
340
+ each_row.append(b1b2_logits)
341
+ title_each_row.append(title_logits)
342
+ frame_each_row.append(frame_logits)
343
+ # logger.info("b1b2_logits:{}".format(b1b2_logits.shape))
344
+ # logger.info("frame_logits:{}".format(frame_logits.shape))
345
+
346
+ each_row = np.concatenate(tuple(each_row), axis=-1)
347
+ # logger.info("each_row:{}".format(each_row.shape))
348
+ title_each_row = np.concatenate(tuple(title_each_row), axis=-1)
349
+ # frame_each_row = np.concatenate(tuple(frame_each_row), axis=-1)
350
+ frame_each_row = np.concatenate(tuple(frame_each_row), axis=1)
351
+ # logger.info("frame_each_row:{}".format(frame_each_row.shape))
352
+ # sim_matrix.append(preprocessing.scale(each_row, axis=1))
353
+ sim_matrix.append(each_row)
354
+ sim_matrix_title.append(title_each_row)
355
+ sim_matrix_frame.append(frame_each_row)
356
+ # logger.info("sim_matrix:{}".format(sim_matrix))
357
+ return sim_matrix, sim_matrix_title, sim_matrix_frame
358
+
359
+
360
+ def eval_epoch(args, model, test_dataloader, device, n_gpu):
361
+ torch.cuda.empty_cache()
362
+ if hasattr(model, 'module'):
363
+ model = model.module.to(device)
364
+ else:
365
+ model = model.to(device)
366
+
367
+ model.eval()
368
+ logger.info("args.task:{}".format(args.task))
369
+
370
+ # if multi_sentence_ == True: compute the similarity with multi-sentences retrieval
371
+ multi_sentence_ = False
372
+
373
+ cut_off_points_, sentence_num_, video_num_ = [], -1, -1
374
+ if hasattr(test_dataloader.dataset, 'multi_sentence_per_video') \
375
+ and test_dataloader.dataset.multi_sentence_per_video:
376
+ multi_sentence_ = True
377
+ cut_off_points_ = test_dataloader.dataset.cut_off_points # used to tag the label when calculate the metric
378
+ sentence_num_ = test_dataloader.dataset.sentence_num # used to cut the sentence representation
379
+ video_num_ = test_dataloader.dataset.video_num # used to cut the video representation
380
+ cut_off_points_ = [itm - 1 for itm in cut_off_points_]
381
+ logger.info("multi_sentence_:{}".format(multi_sentence_))
382
+
383
+ with torch.no_grad():
384
+ batch_query_output_list, batch_visual_output_list = [], []
385
+ batch_title_output_list = []
386
+ batch_frame_output_list = []
387
+ total_video_num = 0
388
+ # ----------------------------
389
+ # 1. cache the features
390
+ # ----------------------------
391
+ for bid, batch in enumerate(test_dataloader):
392
+ batch = tuple(t.to(device) for t in batch)
393
+ if args.task == "retrieval_VT":
394
+ query_ids, query_mask, video, video_frame, title_ids, title_mask = batch
395
+ elif args.task == "retrieval":
396
+ query_ids, query_mask, video, video_frame = batch
397
+ else:
398
+ raise ValueError("wrong task type:{}".format(args.task))
399
+
400
+ print("bid:{}/{}".format(bid, len(test_dataloader)), end="\r")
401
+ if multi_sentence_:
402
+ # multi-sentences retrieval means: one frame clip has two or more descriptions.
403
+ b, *_t = video.shape
404
+ # logger.info("query_ids.shape:{}".format(query_ids.shape))
405
+ # logger.info("video.shape:{}".format(video.shape))
406
+ query_output = model.text_encoder(query_ids, query_mask)
407
+ batch_query_output_list.append(query_output)
408
+ title_output = torch.zeros_like(query_output)
409
+ batch_title_output_list.append(title_output)
410
+ s_, e_ = total_video_num, total_video_num + b
411
+ filter_inds = [itm - s_ for itm in cut_off_points_ if s_ <= itm < e_]
412
+
413
+ if len(filter_inds) > 0:
414
+ video = video[filter_inds, ...]
415
+ visual_output, frame_output = model.visual_encoder(video, video_frame)
416
+ # frame_output = torch.mean(frame_output, dim=1)
417
+ batch_visual_output_list.append(visual_output)
418
+ batch_frame_output_list.append(frame_output)
419
+ total_video_num += b
420
+ else:
421
+ query_output = model.text_encoder(query_ids, query_mask)
422
+ visual_output, frame_output = model.visual_encoder(video, video_frame)
423
+ # frame_output = torch.mean(frame_output, dim=1)
424
+ if args.task == "retrieval_VT":
425
+ title_output = model.text_encoder(title_ids, title_mask)
426
+ logger.info("title_output.shape:{}".format(title_output.shape))
427
+ elif args.task == "retrieval":
428
+ title_output = torch.zeros_like(query_output)
429
+ else:
430
+ raise ValueError("wrong task type:{}".format(args.task))
431
+
432
+ # logger.info("query_output.shape:{}".format(query_output.shape))
433
+ # logger.info("weight_VTM:{},weight_FTM:{},exp:{}".format(model.weight_VTM, model.weight_FTM,
434
+ # model.text_encoder.logit_scale.exp()))
435
+ logger.info("visual_output.shape:{}".format(visual_output.shape))
436
+ logger.info("frame_output.shape:{}".format(frame_output.shape))
437
+
438
+ batch_query_output_list.append(query_output)
439
+ batch_visual_output_list.append(visual_output)
440
+ batch_title_output_list.append(title_output)
441
+ batch_frame_output_list.append(frame_output)
442
+
443
+ # ----------------------------------
444
+ # 2. calculate the similarity
445
+ # ----------------------------------
446
+ logger.info("n_gpu:{}".format(n_gpu))
447
+ # logger.info("model.weight_sum:{}".format(model.weight_sum))
448
+ if n_gpu > 1:
449
+ device_ids = list(range(n_gpu))
450
+ batch_t_output_splits = []
451
+ batch_v_output_splits = []
452
+ batch_title_output_splits = []
453
+ batch_frame_output_splits = []
454
+ bacth_len = len(batch_query_output_list)
455
+ split_len = (bacth_len + n_gpu - 1) // n_gpu
456
+ for dev_id in device_ids:
457
+ s_, e_ = dev_id * split_len, (dev_id + 1) * split_len
458
+ if dev_id == 0:
459
+ batch_t_output_splits.append(batch_query_output_list[s_:e_])
460
+ batch_v_output_splits.append(batch_visual_output_list)
461
+ batch_title_output_splits.append(batch_title_output_list)
462
+ batch_frame_output_splits.append(batch_frame_output_list)
463
+ else:
464
+ devc = torch.device('cuda:{}'.format(str(dev_id)))
465
+
466
+ devc_batch_list = [b.to(devc) for b in batch_query_output_list[s_:e_]]
467
+ batch_t_output_splits.append(devc_batch_list)
468
+ devc_batch_list = [b.to(devc) for b in batch_visual_output_list]
469
+ batch_v_output_splits.append(devc_batch_list)
470
+ devc_batch_list = [b.to(devc) for b in batch_title_output_list]
471
+ batch_title_output_splits.append(devc_batch_list)
472
+ devc_batch_list = [b.to(devc) for b in batch_frame_output_list]
473
+ batch_frame_output_splits.append(devc_batch_list)
474
+
475
+ parameters_tuple_list = [(batch_t_output_splits[dev_id], batch_v_output_splits[dev_id],
476
+ batch_title_output_splits[dev_id], batch_frame_output_splits[dev_id]) for dev_id in device_ids]
477
+ parallel_outputs_tuple = parallel_apply(_run_on_single_gpu, model, parameters_tuple_list, device_ids)
478
+ sim_matrix = []
479
+ sim_matrix_title = []
480
+ sim_matrix_frame = []
481
+ for idx in range(len(parallel_outputs_tuple)):
482
+ parallel_outputs, parallel_outputs_title, parallel_outputs_frame = parallel_outputs_tuple[idx]
483
+ sim_matrix += parallel_outputs
484
+ sim_matrix_title += parallel_outputs_title
485
+ sim_matrix_frame += parallel_outputs_frame
486
+ sim_matrix = np.concatenate(tuple(sim_matrix), axis=0)
487
+ sim_matrix_title = np.concatenate(tuple(sim_matrix_title), axis=0)
488
+ sim_matrix_frame = np.concatenate(tuple(sim_matrix_frame), axis=0)
489
+ else:
490
+ sim_matrix_tuple = _run_on_single_gpu(model, batch_query_output_list, batch_visual_output_list,
491
+ batch_title_output_list, batch_frame_output_list)
492
+ sim_matrix, sim_matrix_title, sim_matrix_frame = sim_matrix_tuple
493
+ sim_matrix = np.concatenate(tuple(sim_matrix), axis=0)
494
+ sim_matrix_title = np.concatenate(tuple(sim_matrix_title), axis=0)
495
+ sim_matrix_frame = np.concatenate(tuple(sim_matrix_frame), axis=0)
496
+
497
+ batch_visual_output_list = torch.cat(batch_visual_output_list, dim=0)
498
+ batch_frame_output_list = torch.cat(batch_frame_output_list, dim=0)
499
+ batch_visual_output_list = batch_visual_output_list.cpu().detach().numpy()
500
+ batch_frame_output_list = batch_frame_output_list.cpu().detach().numpy()
501
+ # np.save("/ai/swxdisk/data/vatex/features/Chinese_batch_visual_output_list", batch_visual_output_list)
502
+ # np.save("/ai/swxdisk/data/vatex/features/Chinese_batch_frame_output_list", batch_frame_output_list)
503
+ np.save("/ai/swxdisk/data/vatex/features/English_batch_visual_output_list", batch_visual_output_list)
504
+ np.save("/ai/swxdisk/data/vatex/features/English_batch_frame_output_list", batch_frame_output_list)
505
+
506
+ # logger.info("sim_matrix:{}".format(sim_matrix.shape))
507
+ # logger.info("sim_matrix_frame:{}".format(sim_matrix_frame.shape))
508
+ # np.save("/ai/swxdisk/data/msrvtt/visualize/sim_matrix", sim_matrix)
509
+ # np.save("/ai/swxdisk/data/msrvtt/visualize/sim_matrix_frame_top2", sim_matrix_frame)
510
+ # sim_matrix_frame = np.topk(sim_matrix_frame, k=model.top_frames, dim=2)[0]
511
+ # sim_matrix_frame = np.mean(sim_matrix_frame, dim=2)
512
+ if args.use_frame_fea:
513
+ sim_matrix += sim_matrix_frame
514
+
515
+ if args.task == "retrieval_VT":
516
+ # logger.info("sim_matrix_title:{}".format(sim_matrix_title))
517
+ weight_title = model.weight_title
518
+ sim_matrix += weight_title * sim_matrix_title
519
+ # sim_matrix = weight_title * sim_matrix_title
520
+
521
+ logger.info("sim matrix size: {}".format(np.array(sim_matrix).shape))
522
+ # sim_matrix = get_dual_matrix(sim_matrix)
523
+
524
+ tv_metrics = logging_rank(sim_matrix, multi_sentence_, cut_off_points_, logger)
525
+ return tv_metrics
526
+
527
+
528
+ def main():
529
+ global logger
530
+ args = get_args()
531
+ args = set_seed_logger(args)
532
+ device, n_gpu = init_device(args, args.local_rank)
533
+
534
+ # get text pretrained path
535
+ pretrained_text = "hfl/chinese-roberta-wwm-ext"
536
+ args.pretrained_text = pretrained_text
537
+ if args.language == "chinese":
538
+ tokenizer = BertTokenizer.from_pretrained(pretrained_text)
539
+ else:
540
+ tokenizer = ClipTokenizer()
541
+
542
+ model = init_model(args, device, n_gpu, args.local_rank)
543
+ ## ####################################
544
+ # freeze testing
545
+ ## ####################################
546
+ '''
547
+ assert args.freeze_layer_num <= 12 and args.freeze_layer_num >= -1
548
+ if hasattr(model, "visual_encoder") and args.freeze_layer_num > -1:
549
+ for name, param in model.visual_encoder.named_parameters():
550
+ # top layers always need to train
551
+ if name.find("ln_final.") == 0 or name.find("text_projection") == 0 or name.find("logit_scale") == 0 \
552
+ or name.find("visual.ln_post.") == 0 or name.find("visual.proj") == 0:
553
+ continue # need to train
554
+ elif name.find("visual.transformer.resblocks.") == 0 or name.find("transformer.resblocks.") == 0:
555
+ layer_num = int(name.split(".resblocks.")[1].split(".")[0])
556
+ if layer_num >= args.freeze_layer_num:
557
+ continue # need to train
558
+
559
+ if args.linear_patch == "3d" and name.find("conv2."):
560
+ continue
561
+ else:
562
+ # paramenters which < freeze_layer_num will be freezed
563
+ param.requires_grad = False
564
+ '''
565
+ assert args.dataset in DATALOADER_DICT
566
+ test_dataloader, test_length = DATALOADER_DICT[args.dataset]["test"](args, tokenizer)
567
+
568
+ if args.local_rank == 0:
569
+ logger.info("***** Running test *****")
570
+ logger.info(" Num examples = %d", test_length)
571
+ logger.info(" Batch size = %d", args.batch_size_val)
572
+ logger.info(" Num steps = %d", len(test_dataloader))
573
+
574
+ if args.do_train:
575
+ train_dataloader, train_length, train_sampler = DATALOADER_DICT[args.dataset]["train"](args, tokenizer)
576
+
577
+ num_train_optimization_steps = (int(len(train_dataloader) + args.gradient_accumulation_steps - 1)
578
+ / args.gradient_accumulation_steps) * args.epochs
579
+ # logger.info("train_dataloader len = {}".format(len(train_dataloader)))
580
+ # logger.info("gradient_accumulation_steps = {}".format(args.gradient_accumulation_steps))
581
+ coef_lr = args.coef_lr
582
+ optimizer, scheduler, model = prep_optimizer(args, model, num_train_optimization_steps, device, n_gpu,
583
+ args.local_rank, coef_lr=coef_lr)
584
+
585
+ if args.local_rank == 0:
586
+ logger.info("***** Running training *****")
587
+ logger.info(" Num examples = %d", train_length)
588
+ logger.info(" Batch size = %d", args.batch_size)
589
+ logger.info(" Num steps = %d", num_train_optimization_steps * args.gradient_accumulation_steps)
590
+
591
+ best_score = 0.00001
592
+ best_output_model_file = "None"
593
+ global_step = 0
594
+ if args.enable_amp:
595
+ scaler = GradScaler()
596
+ else:
597
+ scaler = None
598
+ for epoch in range(args.epochs):
599
+ train_sampler.set_epoch(epoch)
600
+ tr_loss, global_step = train_epoch(epoch, args, model, train_dataloader, device, n_gpu, optimizer,
601
+ scheduler, scaler, global_step, local_rank=args.local_rank)
602
+ if args.local_rank == 0:
603
+ logger.info("Epoch %d/%s Finished, Train Loss: %f", epoch + 1, args.epochs, tr_loss)
604
+ # for name, param in model.named_parameters():
605
+ # args.writer.add_histogram(name, param.clone().cpu().data.numpy(), epoch)
606
+ # writer.add_histogram(name + '/grad', param.requires_grad_().clone().cpu().data.numpy(), epoch)
607
+ if epoch % 1 == 0:
608
+ ## Uncomment if want to save checkpoint
609
+ output_model_file = save_model(epoch, args, model, type_name="")
610
+ # if epoch == 100:
611
+ metrics = eval_epoch(args, model, test_dataloader, device, n_gpu)
612
+ if args.logdir:
613
+ args.writer.add_scalars('metrics', {'R1': metrics["R1"], 'R5': metrics["R5"],
614
+ 'R10': metrics["R10"]}, global_step=epoch)
615
+ if best_score < metrics["R1"]:
616
+ best_score = metrics["R1"]
617
+ best_output_model_file = output_model_file
618
+ logger.info("The best model is: {}, the R1 is: {:.4f}".format(best_output_model_file, best_score))
619
+
620
+ elif args.do_eval:
621
+ if args.local_rank == 0:
622
+ eval_epoch(args, model, test_dataloader, device, n_gpu)
623
+ elif args.do_params:
624
+ logger.info("do_params begin!")
625
+ # total = sum([param.nelement() for param in model.parameters()])
626
+ total = sum(p.numel() for p in model.parameters())
627
+ logger.info("Number of parameter: %.2fM" % (total / 1e6))
628
+ for bid, batch in enumerate(test_dataloader):
629
+ batch = tuple(t.to(device) for t in batch)
630
+ query_ids, query_mask, pos_video_data, pos_title_ids, pos_title_mask, = batch
631
+ flops, params = profile(model, (query_ids, query_mask, pos_video_data, pos_title_ids, pos_title_mask,))
632
+ print('flops: %.2f G, params: %.2f M' % (flops / 1e9, params / 1e6))
633
+ break
634
+ if args.local_rank == 0 and args.logdir:
635
+ args.writer.close()
636
+
637
+
638
+ if __name__ == "__main__":
639
+ main()
models/Chinese_vatex.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:064f9035ddb61431c18584443be4d7375adf8eda396c4ad21f32e73477882bc2
3
+ size 637216411
models/English_vatex.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:29cf3b4e70167178007b621a4e27eb5b400caa7df2f5d911d31827000fa10ac3
3
+ size 404112709
modules/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ #encoding:utf-8
modules/__pycache__/__init__.cpython-37.pyc ADDED
Binary file (131 Bytes). View file
 
modules/__pycache__/file_utils.cpython-37.pyc ADDED
Binary file (6.65 kB). View file
 
modules/__pycache__/modeling.cpython-37.pyc ADDED
Binary file (13.7 kB). View file
 
modules/__pycache__/module_clip.cpython-37.pyc ADDED
Binary file (19.3 kB). View file
 
modules/__pycache__/module_cross.cpython-37.pyc ADDED
Binary file (12.9 kB). View file
 
modules/__pycache__/tokenization_clip.cpython-37.pyc ADDED
Binary file (6.86 kB). View file
 
modules/__pycache__/until_config.cpython-37.pyc ADDED
Binary file (3.48 kB). View file
 
modules/__pycache__/until_module.cpython-37.pyc ADDED
Binary file (10.6 kB). View file
 
modules/bpe_simple_vocab_16e6.txt ADDED
The diff for this file is too large to render. See raw diff
 
modules/bpe_simple_vocab_16e6.txt.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:924691ac288e54409236115652ad4aa250f48203de50a9e4722a6ecd48d6804a
3
+ size 1356917
modules/cross-base/bert_base_6layer_6conect.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "attention_probs_dropout_prob": 0.1,
3
+ "hidden_act": "gelu",
4
+ "hidden_dropout_prob": 0.1,
5
+ "hidden_size": 768,
6
+ "initializer_range": 0.02,
7
+ "intermediate_size": 3072,
8
+ "max_position_embeddings": 512,
9
+ "num_attention_heads": 12,
10
+ "num_hidden_layers": 12,
11
+ "type_vocab_size": 2,
12
+ "vocab_size": 30522,
13
+ "v_feature_size": 2048,
14
+ "v_target_size": 1601,
15
+ "v_hidden_size": 768,
16
+ "v_num_hidden_layers":6,
17
+ "v_num_attention_heads":8,
18
+ "v_intermediate_size":768,
19
+ "bi_hidden_size":768,
20
+ "bi_num_attention_heads":8,
21
+ "bi_intermediate_size": 768,
22
+ "bi_attention_type":1,
23
+ "v_attention_probs_dropout_prob":0.1,
24
+ "v_hidden_act":"gelu",
25
+ "v_hidden_dropout_prob":0.1,
26
+ "v_initializer_range":0.02,
27
+ "v_biattention_id":[0, 1, 2, 3, 4, 5],
28
+ "t_biattention_id":[6, 7, 8, 9, 10, 11],
29
+ "pooling_method": "mul"
30
+ }
modules/cross-base/cross_config.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "max_position_embeddings": 48,
3
+ "chinese_hidden_size": 768,
4
+ "temporal_hidden_size": 512,
5
+ "temporal_attention_heads": 8,
6
+ "temporal_hidden_layers": 4,
7
+ "mlm_probability": 0.15,
8
+ "co_attention_layers": 4,
9
+ "proj_num_layers": 2,
10
+ "pred_num_layers": 2,
11
+ "weight_FAM": 0.05,
12
+ "weight_VTM": 0.45,
13
+ "weight_FTM": 0.45,
14
+ "weight_MLM": 0.05,
15
+ "weight_VTM_finetune": 0.85,
16
+ "weight_FTM_finetune": 0.15,
17
+ "pretrained_clip_name": "ViT-B/32"
18
+ }
modules/file_utils.py ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Utilities for working with the local dataset cache.
3
+ This file is adapted from the AllenNLP library at https://github.com/allenai/allennlp
4
+ Copyright by the AllenNLP authors.
5
+ """
6
+
7
+ import os
8
+ import logging
9
+ import shutil
10
+ import tempfile
11
+ import json
12
+ from urllib.parse import urlparse
13
+ from pathlib import Path
14
+ from typing import Optional, Tuple, Union, IO, Callable, Set
15
+ from hashlib import sha256
16
+ from functools import wraps
17
+
18
+ from tqdm import tqdm
19
+
20
+ import boto3
21
+ from botocore.exceptions import ClientError
22
+ import requests
23
+
24
+ logger = logging.getLogger(__name__) # pylint: disable=invalid-name
25
+
26
+ PYTORCH_PRETRAINED_BERT_CACHE = Path(os.getenv('PYTORCH_PRETRAINED_BERT_CACHE',
27
+ Path.home() / '.pytorch_pretrained_bert'))
28
+
29
+
30
+ def url_to_filename(url: str, etag: str = None) -> str:
31
+ """
32
+ Convert `url` into a hashed filename in a repeatable way.
33
+ If `etag` is specified, append its hash to the url's, delimited
34
+ by a period.
35
+ """
36
+ url_bytes = url.encode('utf-8')
37
+ url_hash = sha256(url_bytes)
38
+ filename = url_hash.hexdigest()
39
+
40
+ if etag:
41
+ etag_bytes = etag.encode('utf-8')
42
+ etag_hash = sha256(etag_bytes)
43
+ filename += '.' + etag_hash.hexdigest()
44
+
45
+ return filename
46
+
47
+
48
+ def filename_to_url(filename: str, cache_dir: Union[str, Path] = None) -> Tuple[str, str]:
49
+ """
50
+ Return the url and etag (which may be ``None``) stored for `filename`.
51
+ Raise ``FileNotFoundError`` if `filename` or its stored metadata do not exist.
52
+ """
53
+ if cache_dir is None:
54
+ cache_dir = PYTORCH_PRETRAINED_BERT_CACHE
55
+ if isinstance(cache_dir, Path):
56
+ cache_dir = str(cache_dir)
57
+
58
+ cache_path = os.path.join(cache_dir, filename)
59
+ if not os.path.exists(cache_path):
60
+ raise FileNotFoundError("file {} not found".format(cache_path))
61
+
62
+ meta_path = cache_path + '.json'
63
+ if not os.path.exists(meta_path):
64
+ raise FileNotFoundError("file {} not found".format(meta_path))
65
+
66
+ with open(meta_path) as meta_file:
67
+ metadata = json.load(meta_file)
68
+ url = metadata['url']
69
+ etag = metadata['etag']
70
+
71
+ return url, etag
72
+
73
+
74
+ def cached_path(url_or_filename: Union[str, Path], cache_dir: Union[str, Path] = None) -> str:
75
+ """
76
+ Given something that might be a URL (or might be a local path),
77
+ determine which. If it's a URL, download the file and cache it, and
78
+ return the path to the cached file. If it's already a local path,
79
+ make sure the file exists and then return the path.
80
+ """
81
+ if cache_dir is None:
82
+ cache_dir = PYTORCH_PRETRAINED_BERT_CACHE
83
+ if isinstance(url_or_filename, Path):
84
+ url_or_filename = str(url_or_filename)
85
+ if isinstance(cache_dir, Path):
86
+ cache_dir = str(cache_dir)
87
+
88
+ parsed = urlparse(url_or_filename)
89
+
90
+ if parsed.scheme in ('http', 'https', 's3'):
91
+ # URL, so get it from the cache (downloading if necessary)
92
+ return get_from_cache(url_or_filename, cache_dir)
93
+ elif os.path.exists(url_or_filename):
94
+ # File, and it exists.
95
+ return url_or_filename
96
+ elif parsed.scheme == '':
97
+ # File, but it doesn't exist.
98
+ raise FileNotFoundError("file {} not found".format(url_or_filename))
99
+ else:
100
+ # Something unknown
101
+ raise ValueError("unable to parse {} as a URL or as a local path".format(url_or_filename))
102
+
103
+
104
+ def split_s3_path(url: str) -> Tuple[str, str]:
105
+ """Split a full s3 path into the bucket name and path."""
106
+ parsed = urlparse(url)
107
+ if not parsed.netloc or not parsed.path:
108
+ raise ValueError("bad s3 path {}".format(url))
109
+ bucket_name = parsed.netloc
110
+ s3_path = parsed.path
111
+ # Remove '/' at beginning of path.
112
+ if s3_path.startswith("/"):
113
+ s3_path = s3_path[1:]
114
+ return bucket_name, s3_path
115
+
116
+
117
+ def s3_request(func: Callable):
118
+ """
119
+ Wrapper function for s3 requests in order to create more helpful error
120
+ messages.
121
+ """
122
+
123
+ @wraps(func)
124
+ def wrapper(url: str, *args, **kwargs):
125
+ try:
126
+ return func(url, *args, **kwargs)
127
+ except ClientError as exc:
128
+ if int(exc.response["Error"]["Code"]) == 404:
129
+ raise FileNotFoundError("file {} not found".format(url))
130
+ else:
131
+ raise
132
+
133
+ return wrapper
134
+
135
+
136
+ @s3_request
137
+ def s3_etag(url: str) -> Optional[str]:
138
+ """Check ETag on S3 object."""
139
+ s3_resource = boto3.resource("s3")
140
+ bucket_name, s3_path = split_s3_path(url)
141
+ s3_object = s3_resource.Object(bucket_name, s3_path)
142
+ return s3_object.e_tag
143
+
144
+
145
+ @s3_request
146
+ def s3_get(url: str, temp_file: IO) -> None:
147
+ """Pull a file directly from S3."""
148
+ s3_resource = boto3.resource("s3")
149
+ bucket_name, s3_path = split_s3_path(url)
150
+ s3_resource.Bucket(bucket_name).download_fileobj(s3_path, temp_file)
151
+
152
+
153
+ def http_get(url: str, temp_file: IO) -> None:
154
+ req = requests.get(url, stream=True)
155
+ content_length = req.headers.get('Content-Length')
156
+ total = int(content_length) if content_length is not None else None
157
+ progress = tqdm(unit="B", total=total)
158
+ for chunk in req.iter_content(chunk_size=1024):
159
+ if chunk: # filter out keep-alive new chunks
160
+ progress.update(len(chunk))
161
+ temp_file.write(chunk)
162
+ progress.close()
163
+
164
+
165
+ def get_from_cache(url: str, cache_dir: Union[str, Path] = None) -> str:
166
+ """
167
+ Given a URL, look for the corresponding dataset in the local cache.
168
+ If it's not there, download it. Then return the path to the cached file.
169
+ """
170
+ if cache_dir is None:
171
+ cache_dir = PYTORCH_PRETRAINED_BERT_CACHE
172
+ if isinstance(cache_dir, Path):
173
+ cache_dir = str(cache_dir)
174
+
175
+ os.makedirs(cache_dir, exist_ok=True)
176
+
177
+ # Get eTag to add to filename, if it exists.
178
+ if url.startswith("s3://"):
179
+ etag = s3_etag(url)
180
+ else:
181
+ response = requests.head(url, allow_redirects=True)
182
+ if response.status_code != 200:
183
+ raise IOError("HEAD request failed for url {} with status code {}"
184
+ .format(url, response.status_code))
185
+ etag = response.headers.get("ETag")
186
+
187
+ filename = url_to_filename(url, etag)
188
+
189
+ # get cache path to put the file
190
+ cache_path = os.path.join(cache_dir, filename)
191
+
192
+ if not os.path.exists(cache_path):
193
+ # Download to temporary file, then copy to cache dir once finished.
194
+ # Otherwise you get corrupt cache entries if the download gets interrupted.
195
+ with tempfile.NamedTemporaryFile() as temp_file:
196
+ logger.info("%s not found in cache, downloading to %s", url, temp_file.name)
197
+
198
+ # GET file object
199
+ if url.startswith("s3://"):
200
+ s3_get(url, temp_file)
201
+ else:
202
+ http_get(url, temp_file)
203
+
204
+ # we are copying the file before closing it, so flush to avoid truncation
205
+ temp_file.flush()
206
+ # shutil.copyfileobj() starts at the current position, so go to the start
207
+ temp_file.seek(0)
208
+
209
+ logger.info("copying %s to cache at %s", temp_file.name, cache_path)
210
+ with open(cache_path, 'wb') as cache_file:
211
+ shutil.copyfileobj(temp_file, cache_file)
212
+
213
+ logger.info("creating metadata file for %s", cache_path)
214
+ meta = {'url': url, 'etag': etag}
215
+ meta_path = cache_path + '.json'
216
+ with open(meta_path, 'w') as meta_file:
217
+ json.dump(meta, meta_file)
218
+
219
+ logger.info("removing temp file %s", temp_file.name)
220
+
221
+ return cache_path
222
+
223
+
224
+ def read_set_from_file(filename: str) -> Set[str]:
225
+ '''
226
+ Extract a de-duped collection (set) of text from a file.
227
+ Expected file format is one item per line.
228
+ '''
229
+ collection = set()
230
+ with open(filename, 'r', encoding='utf-8') as file_:
231
+ for line in file_:
232
+ collection.add(line.rstrip())
233
+ return collection
234
+
235
+
236
+ def get_file_extension(path: str, dot=True, lower: bool = True):
237
+ ext = os.path.splitext(path)[1]
238
+ ext = ext if dot else ext[1:]
239
+ return ext.lower() if lower else ext
modules/modeling.py ADDED
@@ -0,0 +1,507 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+ from __future__ import division
3
+ from __future__ import print_function
4
+
5
+ import logging
6
+ import torch
7
+ from torch import nn
8
+ import numpy as np
9
+ import torch.nn.functional as F
10
+ from transformers import AutoConfig, AutoModel, BertTokenizer
11
+ from modules.tokenization_clip import SimpleTokenizer as ClipTokenizer
12
+ from modules.until_module import PreTrainedModel, AllGather, CrossEn, Dual_CrossEn
13
+ from modules.module_cross import TextEncoder, VisualEncoder, CrossConfig, BertLMPredictionHead
14
+
15
+ logger = logging.getLogger(__name__)
16
+ allgather = AllGather.apply
17
+
18
+
19
+ class CLIP4ClipPreTrainedModel(PreTrainedModel, nn.Module):
20
+ """ An abstract class to handle weights initialization and
21
+ a simple interface for dowloading and loading pretrained models.
22
+ """
23
+
24
+ def __init__(self, cross_config, *inputs, **kwargs):
25
+ super(CLIP4ClipPreTrainedModel, self).__init__(cross_config)
26
+ self.cross_config = cross_config
27
+
28
+ @classmethod
29
+ def from_pretrained(cls, cross_model_name, state_dict=None, cache_dir=None, type_vocab_size=2, *inputs, **kwargs):
30
+
31
+ task_config = None
32
+ if "task_config" in kwargs.keys():
33
+ task_config = kwargs["task_config"]
34
+ if not hasattr(task_config, "local_rank"):
35
+ task_config.__dict__["local_rank"] = 0
36
+ elif task_config.local_rank == -1:
37
+ task_config.local_rank = 0
38
+
39
+ cross_config, _ = CrossConfig.get_config(cross_model_name, cache_dir, type_vocab_size, state_dict=None,
40
+ task_config=task_config)
41
+
42
+ model = cls(cross_config, *inputs, **kwargs)
43
+
44
+ if state_dict is not None:
45
+ model = cls.init_preweight(model, state_dict, task_config=task_config)
46
+
47
+ return model
48
+
49
+
50
+ def show_log(task_config, info):
51
+ if task_config is None or task_config.local_rank == 0:
52
+ logger.warning(info)
53
+
54
+
55
+ def update_attr(target_name, target_config, target_attr_name, source_config, source_attr_name, default_value=None):
56
+ if hasattr(source_config, source_attr_name):
57
+ if default_value is None or getattr(source_config, source_attr_name) != default_value:
58
+ setattr(target_config, target_attr_name, getattr(source_config, source_attr_name))
59
+ show_log(source_config, "Set {}.{}: {}.".format(target_name,
60
+ target_attr_name, getattr(target_config, target_attr_name)))
61
+ return target_config
62
+
63
+
64
+ def check_attr(target_name, task_config):
65
+ return hasattr(task_config, target_name) and task_config.__dict__[target_name]
66
+
67
+
68
+ class BirdPreTrainedModel(CLIP4ClipPreTrainedModel):
69
+ def __init__(self, cross_config, task_config):
70
+ super(BirdPreTrainedModel, self).__init__(cross_config)
71
+ self.task_config = task_config
72
+ self.rank = task_config.local_rank
73
+ self.mlm_probability = cross_config.mlm_probability
74
+ self.top_frames = task_config.top_frames
75
+ # self.weight_sum = torch.nn.Parameter(torch.tensor([0.5], dtype=torch.float32), requires_grad=True)
76
+ self.weight_FAM = cross_config.weight_FAM
77
+ self.weight_VTM = cross_config.weight_VTM
78
+ self.weight_FTM = cross_config.weight_FTM
79
+ self.weight_MLM = cross_config.weight_MLM
80
+ self.contrast_momentum = task_config.contrast_momentum
81
+ self.contrast_temperature = task_config.contrast_temperature
82
+ self.contrast_num_negative = task_config.contrast_num_negative
83
+ ################## chinese text Encoder
84
+ if self.task_config.language == "chinese":
85
+ self.tokenizer = BertTokenizer.from_pretrained(self.task_config.pretrained_text)
86
+ else:
87
+ self.tokenizer = ClipTokenizer()
88
+ if self.rank == 0:
89
+ logger.info("voacb_size:{}".format(self.tokenizer.vocab_size))
90
+ t_config = AutoConfig.from_pretrained(self.task_config.pretrained_text)
91
+ self.text_encoder = TextEncoder(self.task_config, cross_config)
92
+ self.text_encoder_k = TextEncoder(self.task_config, cross_config)
93
+ self.t_projector = MLP(num_layers=cross_config.proj_num_layers)
94
+ self.t_projector_k = MLP(num_layers=cross_config.proj_num_layers)
95
+ nn.SyncBatchNorm.convert_sync_batchnorm(self.t_projector)
96
+ nn.SyncBatchNorm.convert_sync_batchnorm(self.t_projector_k)
97
+ # for MLM
98
+ t_config.hidden_size = cross_config.temporal_hidden_size
99
+ t_config.vocab_size = self.tokenizer.vocab_size
100
+ self.cls = BertLMPredictionHead(t_config)
101
+ ################## visual_encoder
102
+ self.visual_encoder = VisualEncoder(self.task_config, cross_config)
103
+ self.visual_encoder_k = VisualEncoder(self.task_config, cross_config)
104
+ self.v_projector = MLP(num_layers=cross_config.proj_num_layers)
105
+ self.v_projector_k = MLP(num_layers=cross_config.proj_num_layers)
106
+ self.v_predictor = MLP(num_layers=cross_config.pred_num_layers)
107
+ nn.SyncBatchNorm.convert_sync_batchnorm(self.v_projector)
108
+ nn.SyncBatchNorm.convert_sync_batchnorm(self.v_projector_k)
109
+ nn.SyncBatchNorm.convert_sync_batchnorm(self.v_predictor)
110
+ ################# momemtun mdoel pairs
111
+ self.model_pairs = [[self.visual_encoder, self.visual_encoder_k],
112
+ [self.text_encoder, self.text_encoder_k],
113
+ [self.v_projector, self.v_projector_k],
114
+ [self.t_projector, self.t_projector_k],
115
+ ]
116
+ self.copy_params()
117
+ ################## create queue
118
+ self.register_buffer("queue_v_cross_ng", torch.randn(cross_config.temporal_hidden_size, self.contrast_num_negative))
119
+ self.register_buffer("queue_frame_proj_ng", torch.randn(cross_config.temporal_hidden_size,
120
+ self.contrast_num_negative * self.task_config.max_frames))
121
+ self.register_buffer("queue_frame_cross_ng", torch.randn(cross_config.temporal_hidden_size,
122
+ self.contrast_num_negative * self.task_config.max_frames))
123
+ self.register_buffer("queue_title_cross_ng", torch.randn(cross_config.temporal_hidden_size, self.contrast_num_negative))
124
+ self.register_buffer("queue_tag_cross_ng", torch.randn(cross_config.temporal_hidden_size, self.contrast_num_negative))
125
+ self.queue_v_cross_ng = F.normalize(self.queue_v_cross_ng, dim=0)
126
+ self.queue_frame_proj_ng = F.normalize(self.queue_frame_proj_ng, dim=0)
127
+ self.queue_frame_cross_ng = F.normalize(self.queue_frame_cross_ng, dim=0)
128
+ self.queue_title_cross_ng = F.normalize(self.queue_title_cross_ng, dim=0)
129
+ self.queue_tag_cross_ng = F.normalize(self.queue_tag_cross_ng, dim=0)
130
+
131
+ self.register_buffer("queue_ptr", torch.zeros(1, dtype=torch.long))
132
+
133
+ ################## loss function
134
+ self.loss_fct = CrossEn()
135
+ self.loss_fct_dual = Dual_CrossEn()
136
+
137
+
138
+ # self.apply(self.init_weights)
139
+
140
+ def get_mlm_loss(self, input_ids, input_mask):
141
+ to_mask_input_ids = input_ids.clone()
142
+ input_labels = to_mask_input_ids.clone()
143
+ input_probability_matrix = torch.full(input_labels.shape, self.mlm_probability)
144
+ masked_input_ids, input_labels = self.mask(to_mask_input_ids, self.tokenizer.vocab_size,
145
+ input_mask.device, targets=input_labels,
146
+ probability_matrix=input_probability_matrix)
147
+ masked_input_output = self.text_encoder(masked_input_ids, input_mask, return_hidden=True)
148
+ mlm_input_loss = self.calculate_mlm_loss(masked_input_output, input_labels)
149
+ return mlm_input_loss
150
+
151
+ def calculate_mlm_loss(self, sequence_output_mlm, labels):
152
+
153
+ mlm_scores = self.cls(sequence_output_mlm)
154
+ # logger.info("sequence_output_mlm.shape:{}".format(sequence_output_mlm.shape))
155
+ # logger.info("mlm_scores.shape:{}".format(mlm_scores.shape))
156
+ # logger.info("labels.shape:{}".format(labels.shape))
157
+ mlm_loss = F.cross_entropy(mlm_scores.view(-1, self.tokenizer.vocab_size),
158
+ labels.view(-1), ignore_index=-100)
159
+ return mlm_loss
160
+
161
+ def mask(self, input_ids, vocab_size, device, targets=None, masked_indices=None, probability_matrix=None):
162
+ if masked_indices is None:
163
+ masked_indices = torch.bernoulli(probability_matrix).bool()
164
+
165
+ masked_indices[input_ids == self.tokenizer.pad_token_id] = False
166
+ masked_indices[input_ids == self.tokenizer.cls_token_id] = False
167
+ # logger.info("masked_indices:{}".format(masked_indices))
168
+ # logger.info("masked_indices.shape:{}".format(masked_indices.shape))
169
+ if targets is not None:
170
+ targets[~masked_indices] = -100 # We only compute loss on masked tokens
171
+
172
+ # 80% of the time, we replace masked input tokens with tokenizer.mask_token ([MASK])
173
+ indices_replaced = torch.bernoulli(torch.full(input_ids.shape, 0.8)).bool() & masked_indices
174
+ input_ids[indices_replaced] = self.tokenizer.mask_token_id
175
+
176
+ # 10% of the time, we replace masked input tokens with random word
177
+ indices_random = torch.bernoulli(torch.full(input_ids.shape, 0.5)).bool() & masked_indices & ~indices_replaced
178
+ random_words = torch.randint(vocab_size, input_ids.shape, dtype=torch.long).to(device)
179
+ input_ids[indices_random] = random_words[indices_random]
180
+ # The rest of the time (10% of the time) we keep the masked input tokens unchanged
181
+
182
+ if targets is not None:
183
+ return input_ids, targets
184
+ else:
185
+ return input_ids
186
+
187
+ def loose_similarity(self, sequence_output, visual_output):
188
+ sequence_output, visual_output = sequence_output.contiguous(), visual_output.contiguous()
189
+
190
+ visual_output = visual_output.squeeze()
191
+ visual_output = visual_output / visual_output.norm(dim=-1, keepdim=True)
192
+
193
+ sequence_output = sequence_output.squeeze()
194
+ sequence_output = sequence_output / sequence_output.norm(dim=-1, keepdim=True)
195
+
196
+ logit_scale = self.text_encoder.logit_scale.exp()
197
+ logit_scale.data = torch.clamp(logit_scale.data, max=100)
198
+ # if self.rank == 0:
199
+ # logger.info("logit_scale:{},dtype:{}".format(logit_scale, logit_scale.dtype))
200
+ # logger.info("sequence_output.shape:{}".format(sequence_output.shape))
201
+ # logger.info("visual_output.shape:{}".format(visual_output.shape))
202
+ if len(visual_output.shape) == 2:
203
+ retrieve_logits = logit_scale * torch.matmul(sequence_output, visual_output.t())
204
+ else:
205
+ visual_temp = visual_output.permute(0, 2, 1)
206
+ retrieve_logits = logit_scale * torch.matmul(sequence_output, visual_temp)
207
+ if len(retrieve_logits.shape) == 3:
208
+ retrieve_logits = retrieve_logits.permute(1, 0, 2)
209
+
210
+ return retrieve_logits
211
+
212
+ @torch.no_grad()
213
+ def copy_params(self):
214
+ for model_pair in self.model_pairs:
215
+ for param, param_k in zip(model_pair[0].parameters(), model_pair[1].parameters()):
216
+ param_k.data.copy_(param.data) # initialize
217
+ param_k.requires_grad = False # not update by gradient
218
+
219
+ @torch.no_grad()
220
+ def _momentum_update(self):
221
+ for model_pair in self.model_pairs:
222
+ for param, param_k in zip(model_pair[0].parameters(), model_pair[1].parameters()):
223
+ param_k.data = param_k.data * self.contrast_momentum + param.data * (1. - self.contrast_momentum)
224
+
225
+ @torch.no_grad()
226
+ def _dequeue_and_enqueue(self, v_fea_k, tag_fea_k, title_fea_k, frame_fea_k, frame_proj_k):
227
+
228
+ # gather keys before updating queue
229
+ # [bs,hidden]
230
+ v_fea_k = F.normalize(v_fea_k, dim=1)
231
+ tag_fea_k = F.normalize(tag_fea_k, dim=1)
232
+ title_fea_k = F.normalize(title_fea_k, dim=1)
233
+ # [bs,frame,hidden]
234
+ frame_fea_k = F.normalize(frame_fea_k, dim=2)
235
+ frame_proj_k = F.normalize(frame_proj_k, dim=2)
236
+
237
+ batch_size = v_fea_k.size(0)
238
+ frame_num = frame_fea_k.size(1)
239
+ frame_fea_k = frame_fea_k.view(-1, frame_fea_k.size(-1))
240
+ frame_proj_k = frame_proj_k.view(-1, frame_proj_k.size(-1))
241
+
242
+ ptr = int(self.queue_ptr)
243
+ # if self.rank == 0:
244
+ # logger.info(
245
+ # "begin>>>>: ptr:{},batch_size:{},frame_num:{},queue_size:{}".format(ptr, batch_size, frame_num, self.contrast_num_negative))
246
+ # logger.info("v1_self_k.shape:{},tag_cross_k.shape:{},frame_proj_k.shape:{}".format(v_fea_k.shape, tag_fea_k.shape, frame_proj_k.shape))
247
+
248
+ # replace the keys at ptr (dequeue and enqueue)
249
+ self.queue_v_cross_ng[:, ptr:ptr + batch_size] = v_fea_k.T
250
+ self.queue_tag_cross_ng[:, ptr:ptr + batch_size] = tag_fea_k.T
251
+ self.queue_title_cross_ng[:, ptr:ptr + batch_size] = title_fea_k.T
252
+
253
+ self.queue_frame_proj_ng[:, ptr * frame_num:(ptr + batch_size) * frame_num] = frame_proj_k.T
254
+ self.queue_frame_cross_ng[:, ptr * frame_num:(ptr + batch_size) * frame_num] = frame_fea_k.T
255
+ # move pointer
256
+ ptr = (ptr + batch_size) % self.contrast_num_negative
257
+
258
+ # if self.rank == 0:
259
+ # logger.info("end>>>>: ptr:{}".format(ptr))
260
+ self.queue_ptr[0] = ptr
261
+
262
+ def contrastive_loss(self, q, k, queue):
263
+
264
+ q = q.squeeze()
265
+ q = F.normalize(q, dim=1)
266
+ k = k.squeeze()
267
+ k = F.normalize(k, dim=1)
268
+
269
+ bs = q.size(0)
270
+ # logger.info("q.dtype:{},k.dtype:{}".format(q.dtype, k.dtype))
271
+ # positive logits: Nx1
272
+ # >>>>>>got error in apex:amp level=01!!!!!!!!!
273
+ # l_pos = torch.einsum('nc,nc->n', [q, k]).unsqueeze(-1)
274
+ l_pos = torch.matmul(q, k.T)
275
+ l_pos = torch.diag(l_pos).reshape([bs, -1])
276
+ # negative logits: NxK
277
+ # l_neg = torch.einsum('nc,ck->nk', [q, queue.clone().detach()])
278
+ l_neg = torch.matmul(q, queue.clone().detach())
279
+ # logits: Nx(1+K)
280
+ logits = torch.cat([l_pos, l_neg], dim=1)
281
+ # if self.rank == 0:
282
+ # logger.info("logits.shape:{}".format(logits.shape))
283
+ # apply temperature
284
+ logits /= self.contrast_temperature
285
+
286
+ # labels: positive key indicators
287
+ labels = torch.zeros(logits.shape[0], dtype=torch.long).cuda()
288
+
289
+ return F.cross_entropy(logits, labels)
290
+
291
+ def frame_self_loss(self, frame_fea, frame_fea_k, queue_frame_ng):
292
+ loss = 0.
293
+
294
+ for i in range(frame_fea.size(1) - 1):
295
+ frame_loss = self.contrastive_loss(frame_fea[:, i, :], frame_fea_k[:, i+1, :], queue_frame_ng) \
296
+ + self.contrastive_loss(frame_fea[:, i+1, :], frame_fea_k[:, i, :], queue_frame_ng)
297
+ loss += frame_loss
298
+ loss = loss / (frame_fea.size(1) - 1)
299
+ return loss
300
+
301
+ def frame_cross_loss(self, frame_fea, frame_fea_k, queue_frame_ng, text_fea, text_fea_k, queue_text_ng):
302
+ loss = 0.
303
+ for i in range(frame_fea.size(1)):
304
+ frame_loss = self.contrastive_loss(text_fea, frame_fea_k[:, i, :], queue_frame_ng) + \
305
+ self.contrastive_loss(frame_fea[:, i, :], text_fea_k, queue_text_ng)
306
+ loss += frame_loss
307
+ loss = loss / frame_fea.size(1)
308
+ return loss
309
+
310
+ def forward(self, video_data, video_frame, tag_ids, tag_mask, title_ids, title_mask, global_step):
311
+ tag_ids = tag_ids.view(-1, tag_ids.shape[-1])
312
+ tag_mask = tag_mask.view(-1, tag_mask.shape[-1])
313
+ title_ids = title_ids.view(-1, title_ids.shape[-1])
314
+ title_mask = title_mask.view(-1, title_mask.shape[-1])
315
+ # bs x frames x 3 x H x W
316
+ video = torch.as_tensor(video_data)
317
+
318
+ if self.rank == 0 and global_step % self.task_config.n_display == 0:
319
+ logger.info("video1.shape:{}, dtype:{}, device:{}".format(video.shape, video.dtype, video.device))
320
+
321
+ if self.training:
322
+ # loss = 0.0
323
+ v_fea, frame_fea = self.visual_encoder(video, video_frame)
324
+ if self.task_config.dataset == "bird":
325
+ tag_fea = self.text_encoder(tag_ids, tag_mask)
326
+ title_fea = self.text_encoder(title_ids, title_mask)
327
+
328
+ # for video self supervised learning
329
+ # [bs,hidden_size]
330
+ bs, frame, hidden = frame_fea.shape
331
+ frame_fea = frame_fea.view(-1, hidden)
332
+ frame_proj = self.v_projector(frame_fea)
333
+ frame_pred = self.v_predictor(frame_proj)
334
+ frame_fea = frame_fea.view(bs, frame, hidden)
335
+ frame_proj = frame_proj.view(bs, frame, hidden)
336
+ frame_pred = frame_pred.view(bs, frame, hidden)
337
+ if self.rank == 0 and global_step % self.task_config.n_display == 0:
338
+ logger.info("v_fea.shape:{},device:{}".format(v_fea.shape, v_fea.device))
339
+ logger.info("frame_fea.shape:{},device:{}".format(frame_fea.shape, frame_fea.device))
340
+ logger.info("frame_proj.shape:{},device:{}".format(frame_proj.shape, frame_proj.device))
341
+ logger.info("title_fea.shape:{}".format(title_fea.shape))
342
+ logger.info("queue_v_cross_ng.shape:{}".format(self.queue_v_cross_ng.shape))
343
+ # compute key features
344
+ with torch.no_grad(): # no gradient to keys
345
+ self._momentum_update() # update the key encoder
346
+
347
+ tag_fea_k = self.text_encoder_k(tag_ids, tag_mask)
348
+ title_fea_k = self.text_encoder_k(title_ids, title_mask)
349
+ #
350
+ v_fea_k, frame_fea_k = self.visual_encoder_k(video, video_frame)
351
+ frame_fea_k = frame_fea_k.view(-1, hidden)
352
+ frame_proj_k = self.v_projector_k(frame_fea_k)
353
+ frame_fea_k = frame_fea_k.view(bs, frame, hidden)
354
+ frame_proj_k = frame_proj_k.view(bs, frame, hidden)
355
+
356
+ # compute loss
357
+ if self.rank == 0 and global_step % self.task_config.n_display == 0:
358
+ logger.info(
359
+ "dtype: v_fea:{},v_fea_k:{},title_fea:{}".format(v_fea.dtype, v_fea_k.dtype, title_fea.dtype))
360
+ # single video modality: video queue loss
361
+ loss_FAM = self.frame_self_loss(frame_pred, frame_proj_k, self.queue_frame_proj_ng)
362
+ # cross modality: cross queue loss
363
+ v_title_queue_loss = self.contrastive_loss(v_fea, title_fea_k, self.queue_title_cross_ng) \
364
+ + self.contrastive_loss(title_fea, v_fea_k, self.queue_v_cross_ng)
365
+ if self.task_config.dataset == "bird":
366
+ v_tag_queue_loss = self.contrastive_loss(v_fea, tag_fea_k, self.queue_tag_cross_ng) \
367
+ + self.contrastive_loss(tag_fea, v_fea_k, self.queue_v_cross_ng)
368
+ loss_VTM = (v_tag_queue_loss + v_title_queue_loss) / 2
369
+ else:
370
+ loss_VTM = v_title_queue_loss
371
+
372
+ loss_FTM = 0.
373
+ if self.task_config.use_frame_fea:
374
+ frame_title_loss = self.frame_cross_loss(frame_fea, frame_fea_k, self.queue_frame_cross_ng, title_fea,
375
+ title_fea_k, self.queue_title_cross_ng)
376
+ if self.task_config.dataset == "bird":
377
+ frame_tag_loss = self.frame_cross_loss(frame_fea, frame_fea_k, self.queue_frame_cross_ng, tag_fea,
378
+ tag_fea_k, self.queue_tag_cross_ng)
379
+ loss_FTM += (frame_tag_loss + frame_title_loss) / 2
380
+ else:
381
+ loss_FTM = frame_title_loss
382
+
383
+ # single text modality: text queue loss
384
+ # t_queue_loss = self.contrastive_loss(title_fea, tag_fea_k, self.queue_tag_cross_ng) \
385
+ # + self.contrastive_loss(tag_fea, title_fea_k, self.queue_v_cross_ng)
386
+
387
+ # dequeue_and_enqueue
388
+ self._dequeue_and_enqueue(v_fea_k, tag_fea_k, title_fea_k, frame_fea_k, frame_proj_k)
389
+
390
+ # mlm loss
391
+
392
+ mlm_title_loss = self.get_mlm_loss(title_ids, title_mask)
393
+ if self.task_config.dataset == "bird":
394
+ mlm_tag_loss = self.get_mlm_loss(tag_ids, tag_mask)
395
+ loss_MLM = (mlm_tag_loss + mlm_title_loss) / 2
396
+ else:
397
+ loss_MLM = mlm_title_loss
398
+
399
+ # total loss
400
+ loss = self.weight_FAM * loss_FAM + self.weight_VTM * loss_VTM + self.weight_FTM * loss_FTM + self.weight_MLM * loss_MLM
401
+ if self.rank == 0:
402
+ if global_step % self.task_config.n_display == 0:
403
+ logger.info("loss:{},loss_FAM:{},loss_VTM:{},loss_FTM:{},loss_MLM:{}"
404
+ "".format(loss, loss_FAM, loss_VTM, loss_FTM, loss_MLM))
405
+ if self.task_config.logdir:
406
+ loss_item = {"loss": float(loss), "loss_FAM": float(loss_FAM), "loss_VTM": float(loss_VTM),
407
+ "loss_FTM": float(loss_FTM), "loss_MLM": float(loss_MLM)}
408
+ self.task_config.writer.add_scalars('loss', loss_item, global_step=global_step)
409
+ # self.task_config.writer.add_scalar('loss', video_cross_loss, global_step=global_step)
410
+ return loss
411
+ else:
412
+ return None
413
+
414
+
415
+ class BirdModel(BirdPreTrainedModel):
416
+ def __init__(self, cross_config, task_config):
417
+ super(BirdPreTrainedModel, self).__init__(cross_config)
418
+ self.task_config = task_config
419
+ self.rank = task_config.local_rank
420
+ # self.weight_sim = torch.nn.Parameter(torch.tensor([0.9], dtype=torch.float32), requires_grad=True)
421
+ self.weight_VTM_finetune = cross_config.weight_VTM_finetune
422
+ self.weight_FTM_finetune = cross_config.weight_FTM_finetune
423
+ self.top_frames = task_config.top_frames
424
+ ################## text Encoder
425
+ self.text_encoder = TextEncoder(self.task_config, cross_config)
426
+ ################## visual_encoder
427
+ self.visual_encoder = VisualEncoder(self.task_config, cross_config)
428
+ ################## loss function
429
+ self.loss_fct = CrossEn()
430
+ self.loss_fct_dual = Dual_CrossEn()
431
+
432
+ def frame_loss(self, query_output, frame_output):
433
+ frame_num = frame_output.size(1)
434
+ loss = 0.
435
+ for i in range(frame_num):
436
+ frame_single = frame_output[:, i, :].squeeze()
437
+ sim_matrix = self.loose_similarity(query_output, frame_single)
438
+ sim_loss = self.loss_fct(sim_matrix) + self.loss_fct(sim_matrix.T)
439
+ loss += sim_loss / frame_num
440
+ # logger.info("frame_output.shape:{},dtype:{}".format(frame_output.shape, frame_output.dtype))
441
+ # logger.info("query_output.shape:{},dtype:{}".format(query_output.shape, frame_output.dtype))
442
+ # sim_matrix = self.loose_similarity(query_output, frame_output)
443
+ # sim_matrix = torch.topk(sim_matrix, k=self.top_frames, dim=2)[0]
444
+ # sim_matrix = torch.mean(sim_matrix, dim=2)
445
+ # sim_loss = self.loss_fct(sim_matrix) + self.loss_fct(sim_matrix.T)
446
+ # loss += sim_loss
447
+ return loss
448
+
449
+ def forward(self, query_ids, query_mask, video_data, video_frame, idx, global_step):
450
+ query_ids = query_ids.view(-1, query_ids.shape[-1])
451
+ query_mask = query_mask.view(-1, query_mask.shape[-1])
452
+ # T x 3 x H x W
453
+ video = torch.as_tensor(video_data)
454
+ # if self.rank == 0:
455
+ # logger.info("video.shape:{}, dtype:{}".format(video.shape, video.dtype))
456
+ if self.training:
457
+ loss = 0.0
458
+ query_output = self.text_encoder(query_ids, query_mask)
459
+ visual_output, frame_output = self.visual_encoder(video, video_frame)
460
+ # if self.rank == 0:
461
+ # logger.info("query_output.shape:{},dtype:{}".format(query_output.shape, query_output.dtype))
462
+ # logger.info("visual_output.shape:{},dtype:{}".format(visual_output.shape, visual_output.dtype))
463
+ # logger.info("frame_output.shape:{},dtype:{}".format(frame_output.shape, frame_output.dtype))
464
+
465
+ # frame loss
466
+ if self.task_config.use_frame_fea:
467
+ frame_loss = self.frame_loss(query_output, frame_output)
468
+ loss += self.weight_FTM_finetune * frame_loss
469
+ # video loss
470
+ sim_matrix = self.loose_similarity(query_output, visual_output)
471
+ sim_loss = self.loss_fct(sim_matrix) + self.loss_fct(sim_matrix.T)
472
+ loss += self.weight_VTM_finetune * sim_loss
473
+ # loss += sim_loss
474
+
475
+ if self.task_config.local_rank == 0:
476
+ if global_step % self.task_config.n_display == 0:
477
+ logger.info(
478
+ "loss:{},frame_loss:{},sim_loss:{},type:{},sim_matrix.shape:{}".format(loss, loss - sim_loss,
479
+ sim_loss, sim_loss.dtype, sim_matrix.shape))
480
+
481
+ if self.task_config.logdir:
482
+ self.task_config.writer.add_scalar('loss', float(loss), global_step=global_step)
483
+ return loss
484
+ else:
485
+ return None
486
+
487
+
488
+ class MLP(nn.Module):
489
+ def __init__(self, in_dim=512, inner_dim=4096, out_dim=512, num_layers=2):
490
+ super(MLP, self).__init__()
491
+
492
+ # hidden layers
493
+ linear_hidden = [nn.Identity()]
494
+ for i in range(num_layers - 1):
495
+ linear_hidden.append(nn.Linear(in_dim if i == 0 else inner_dim, inner_dim))
496
+ linear_hidden.append(nn.BatchNorm1d(inner_dim))
497
+ linear_hidden.append(nn.ReLU(inplace=True))
498
+ self.linear_hidden = nn.Sequential(*linear_hidden)
499
+
500
+ self.linear_out = nn.Linear(in_dim if num_layers == 1 else inner_dim,
501
+ out_dim) if num_layers >= 1 else nn.Identity()
502
+
503
+ def forward(self, x):
504
+ x = self.linear_hidden(x)
505
+ x = self.linear_out(x)
506
+
507
+ return x
modules/module_clip.py ADDED
@@ -0,0 +1,579 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Adapted from: https://github.com/openai/CLIP/blob/main/clip/clip.py
3
+ """
4
+ from collections import OrderedDict
5
+ from typing import Tuple, Union
6
+
7
+ import hashlib
8
+ import os
9
+ import urllib
10
+ import warnings
11
+ from tqdm import tqdm
12
+
13
+ import torch
14
+ import torch.nn.functional as F
15
+ from torch import nn
16
+
17
+ import logging
18
+ logger = logging.getLogger(__name__)
19
+
20
+ _MODELS = {
21
+ "RN50": "https://openaipublic.azureedge.net/clip/models/afeb0e10f9e5a86da6080e35cf09123aca3b358a0c3e3b6c78a7b63bc04b6762/RN50.pt",
22
+ "RN101": "https://openaipublic.azureedge.net/clip/models/8fa8567bab74a42d41c5915025a8e4538c3bdbe8804a470a72f30b0d94fab599/RN101.pt",
23
+ "RN50x4": "https://openaipublic.azureedge.net/clip/models/7e526bd135e493cef0776de27d5f42653e6b4c8bf9e0f653bb11773263205fdd/RN50x4.pt",
24
+ "RN50x16": "https://openaipublic.azureedge.net/clip/models/52378b407f34354e150460fe41077663dd5b39c54cd0bfd2b27167a4a06ec9aa/RN50x16.pt",
25
+ "RN50x64": "https://openaipublic.azureedge.net/clip/models/be1cfb55d75a9666199fb2206c106743da0f6468c9d327f3e0d0a543a9919d9c/RN50x64.pt",
26
+ "ViT-B/32": "https://openaipublic.azureedge.net/clip/models/40d365715913c9da98579312b702a82c18be219cc2a73407c4526f58eba950af/ViT-B-32.pt",
27
+ "ViT-B/16": "https://openaipublic.azureedge.net/clip/models/5806e77cd80f8b59890b7e101eabd078d9fb84e6937f9e85e4ecb61988df416f/ViT-B-16.pt",
28
+ "ViT-L/14": "https://openaipublic.azureedge.net/clip/models/b8cca3fd41ae0c99ba7e8951adf17d267cdb84cd88be6f7c2e0eca1737a03836/ViT-L-14.pt",
29
+ }
30
+
31
+ def _download(url: str, root: str = os.path.expanduser("~/.cache/visual_encoder")):
32
+ os.makedirs(root, exist_ok=True)
33
+ filename = os.path.basename(url)
34
+
35
+ expected_sha256 = url.split("/")[-2]
36
+ download_target = os.path.join(root, filename)
37
+
38
+ if os.path.exists(download_target) and not os.path.isfile(download_target):
39
+ raise RuntimeError(f"{download_target} exists and is not a regular file")
40
+
41
+ if os.path.isfile(download_target):
42
+ if hashlib.sha256(open(download_target, "rb").read()).hexdigest() == expected_sha256:
43
+ return download_target
44
+ else:
45
+ warnings.warn(f"{download_target} exists, but the SHA256 checksum does not match; re-downloading the file")
46
+
47
+ with urllib.request.urlopen(url) as source, open(download_target, "wb") as output:
48
+ with tqdm(total=int(source.info().get("Content-Length")), ncols=80, unit='iB', unit_scale=True) as loop:
49
+ while True:
50
+ buffer = source.read(8192)
51
+ if not buffer:
52
+ break
53
+
54
+ output.write(buffer)
55
+ loop.update(len(buffer))
56
+
57
+ if hashlib.sha256(open(download_target, "rb").read()).hexdigest() != expected_sha256:
58
+ raise RuntimeError(f"Model has been downloaded but the SHA256 checksum does not not match")
59
+
60
+ return download_target
61
+
62
+ def available_models():
63
+ """Returns the names of available CLIP models"""
64
+ return list(_MODELS.keys())
65
+
66
+ # =============================
67
+
68
+ class Bottleneck(nn.Module):
69
+ expansion = 4
70
+
71
+ def __init__(self, inplanes, planes, stride=1):
72
+ super().__init__()
73
+
74
+ # all conv layers have stride 1. an avgpool is performed after the second convolution when stride > 1
75
+ self.conv1 = nn.Conv2d(inplanes, planes, 1, bias=False)
76
+ self.bn1 = nn.BatchNorm2d(planes)
77
+
78
+ self.conv2 = nn.Conv2d(planes, planes, 3, padding=1, bias=False)
79
+ self.bn2 = nn.BatchNorm2d(planes)
80
+
81
+ self.avgpool = nn.AvgPool2d(stride) if stride > 1 else nn.Identity()
82
+
83
+ self.conv3 = nn.Conv2d(planes, planes * self.expansion, 1, bias=False)
84
+ self.bn3 = nn.BatchNorm2d(planes * self.expansion)
85
+
86
+ self.relu = nn.ReLU(inplace=True)
87
+ self.downsample = None
88
+ self.stride = stride
89
+
90
+ if stride > 1 or inplanes != planes * Bottleneck.expansion:
91
+ # downsampling layer is prepended with an avgpool, and the subsequent convolution has stride 1
92
+ self.downsample = nn.Sequential(OrderedDict([
93
+ ("-1", nn.AvgPool2d(stride)),
94
+ ("0", nn.Conv2d(inplanes, planes * self.expansion, 1, stride=1, bias=False)),
95
+ ("1", nn.BatchNorm2d(planes * self.expansion))
96
+ ]))
97
+
98
+ def forward(self, x: torch.Tensor):
99
+ identity = x
100
+
101
+ out = self.relu(self.bn1(self.conv1(x)))
102
+ out = self.relu(self.bn2(self.conv2(out)))
103
+ out = self.avgpool(out)
104
+ out = self.bn3(self.conv3(out))
105
+
106
+ if self.downsample is not None:
107
+ identity = self.downsample(x)
108
+
109
+ out += identity
110
+ out = self.relu(out)
111
+ return out
112
+
113
+
114
+ class AttentionPool2d(nn.Module):
115
+ def __init__(self, spacial_dim: int, embed_dim: int, num_heads: int, output_dim: int = None):
116
+ super().__init__()
117
+ self.positional_embedding = nn.Parameter(torch.randn(spacial_dim ** 2 + 1, embed_dim) / embed_dim ** 0.5)
118
+ # print("spacial_dim:{},embed_dim:{}".format(spacial_dim, embed_dim))
119
+ # print("self.positional_embedding.shape:{}".format(self.positional_embedding.shape))
120
+ # print("self.positional_embedding[:, None, :].shape:{}".format(self.positional_embedding[:, None, :].shape))
121
+ self.k_proj = nn.Linear(embed_dim, embed_dim)
122
+ self.q_proj = nn.Linear(embed_dim, embed_dim)
123
+ self.v_proj = nn.Linear(embed_dim, embed_dim)
124
+ self.c_proj = nn.Linear(embed_dim, output_dim or embed_dim)
125
+ self.num_heads = num_heads
126
+
127
+ def forward(self, x):
128
+ # logger.info("x1.shape:{}".format(x.shape))
129
+ x = x.reshape(x.shape[0], x.shape[1], x.shape[2] * x.shape[3]).permute(2, 0, 1) # NCHW -> (HW)NC
130
+ x = torch.cat([x.mean(dim=0, keepdim=True), x], dim=0) # (HW+1)NC
131
+ x = x + self.positional_embedding[:, None, :].to(x.dtype) # (HW+1)NC
132
+ # logger.info("x2.shape:{}".format(x.shape))
133
+ x, _ = F.multi_head_attention_forward(
134
+ query=x, key=x, value=x,
135
+ embed_dim_to_check=x.shape[-1],
136
+ num_heads=self.num_heads,
137
+ q_proj_weight=self.q_proj.weight,
138
+ k_proj_weight=self.k_proj.weight,
139
+ v_proj_weight=self.v_proj.weight,
140
+ in_proj_weight=None,
141
+ in_proj_bias=torch.cat([self.q_proj.bias, self.k_proj.bias, self.v_proj.bias]),
142
+ bias_k=None,
143
+ bias_v=None,
144
+ add_zero_attn=False,
145
+ dropout_p=0,
146
+ out_proj_weight=self.c_proj.weight,
147
+ out_proj_bias=self.c_proj.bias,
148
+ use_separate_proj_weight=True,
149
+ training=self.training,
150
+ need_weights=False
151
+ )
152
+ # logger.info("x3.shape:{}".format(x.shape))
153
+ return x[0]
154
+ # return x
155
+
156
+
157
+ class ModifiedResNet(nn.Module):
158
+ """
159
+ A ResNet class that is similar to torchvision's but contains the following changes:
160
+ - There are now 3 "stem" convolutions as opposed to 1, with an average pool instead of a max pool.
161
+ - Performs anti-aliasing strided convolutions, where an avgpool is prepended to convolutions with stride > 1
162
+ - The final pooling layer is a QKV attention instead of an average pool
163
+ """
164
+
165
+ def __init__(self, layers, output_dim, heads, input_resolution=224, width=64):
166
+ super().__init__()
167
+ self.output_dim = output_dim
168
+ self.input_resolution = input_resolution
169
+
170
+ # the 3-layer stem
171
+ self.conv1 = nn.Conv2d(3, width // 2, kernel_size=3, stride=2, padding=1, bias=False)
172
+ self.bn1 = nn.BatchNorm2d(width // 2)
173
+ self.conv2 = nn.Conv2d(width // 2, width // 2, kernel_size=3, padding=1, bias=False)
174
+ self.bn2 = nn.BatchNorm2d(width // 2)
175
+ self.conv3 = nn.Conv2d(width // 2, width, kernel_size=3, padding=1, bias=False)
176
+ self.bn3 = nn.BatchNorm2d(width)
177
+ self.avgpool = nn.AvgPool2d(2)
178
+ self.relu = nn.ReLU(inplace=True)
179
+
180
+ # residual layers
181
+ self._inplanes = width # this is a *mutable* variable used during construction
182
+ self.layer1 = self._make_layer(width, layers[0])
183
+ self.layer2 = self._make_layer(width * 2, layers[1], stride=2)
184
+ self.layer3 = self._make_layer(width * 4, layers[2], stride=2)
185
+ self.layer4 = self._make_layer(width * 8, layers[3], stride=2)
186
+
187
+ embed_dim = width * 32 # the ResNet feature dimension
188
+ self.attnpool = AttentionPool2d(input_resolution // 32, embed_dim, heads, output_dim)
189
+
190
+ def _make_layer(self, planes, blocks, stride=1):
191
+ layers = [Bottleneck(self._inplanes, planes, stride)]
192
+
193
+ self._inplanes = planes * Bottleneck.expansion
194
+ for _ in range(1, blocks):
195
+ layers.append(Bottleneck(self._inplanes, planes))
196
+
197
+ return nn.Sequential(*layers)
198
+
199
+ def forward(self, x):
200
+ def stem(x):
201
+ for conv, bn in [(self.conv1, self.bn1), (self.conv2, self.bn2), (self.conv3, self.bn3)]:
202
+ x = self.relu(bn(conv(x)))
203
+ x = self.avgpool(x)
204
+ return x
205
+
206
+ x = x.type(self.conv1.weight.dtype)
207
+ x = stem(x)
208
+ x = self.layer1(x)
209
+ x = self.layer2(x)
210
+ x = self.layer3(x)
211
+ x = self.layer4(x)
212
+ x = self.attnpool(x)
213
+
214
+ return x
215
+
216
+
217
+ class LayerNorm(nn.LayerNorm):
218
+ """Subclass torch's LayerNorm to handle fp16."""
219
+
220
+ def forward(self, x: torch.Tensor):
221
+ orig_type = x.dtype
222
+ ret = super().forward(x.type(torch.float32))
223
+ return ret.type(orig_type)
224
+
225
+
226
+ class QuickGELU(nn.Module):
227
+ def forward(self, x: torch.Tensor):
228
+ return x * torch.sigmoid(1.702 * x)
229
+
230
+
231
+ class ResidualAttentionBlock(nn.Module):
232
+ def __init__(self, d_model: int, n_head: int, attn_mask=None):
233
+ super().__init__()
234
+
235
+ self.attn = nn.MultiheadAttention(d_model, n_head)
236
+ self.ln_1 = LayerNorm(d_model)
237
+ self.mlp = nn.Sequential(OrderedDict([
238
+ ("c_fc", nn.Linear(d_model, d_model * 4)),
239
+ ("gelu", QuickGELU()),
240
+ ("c_proj", nn.Linear(d_model * 4, d_model))
241
+ ]))
242
+ self.ln_2 = LayerNorm(d_model)
243
+ self.attn_mask = attn_mask
244
+
245
+ def attention(self, x: torch.Tensor):
246
+ attn_mask_ = self.attn_mask
247
+ if self.attn_mask is not None and hasattr(self.attn_mask, '__call__'):
248
+ attn_mask_ = self.attn_mask(x.size(0)) # LND
249
+
250
+ attn_mask_ = attn_mask_.to(dtype=x.dtype, device=x.device) if attn_mask_ is not None else None
251
+ return self.attn(x, x, x, need_weights=False, attn_mask=attn_mask_)[0]
252
+
253
+ def forward(self, x_tuple:tuple):
254
+ x, video_frame = x_tuple
255
+ x = x + self.attention(self.ln_1(x))
256
+ x = x + self.mlp(self.ln_2(x))
257
+ return (x, video_frame)
258
+
259
+
260
+ class Transformer(nn.Module):
261
+ def __init__(self, width: int, layers: int, heads: int, attn_mask = None):
262
+ super().__init__()
263
+ self.width = width
264
+ self.layers = layers
265
+ self.resblocks = nn.Sequential(*[ResidualAttentionBlock(width, heads, attn_mask) for _ in range(layers)])
266
+
267
+ def forward(self, x: torch.Tensor, video_frame=-1):
268
+ return self.resblocks((x, video_frame))[0]
269
+
270
+
271
+ class VisualTransformer(nn.Module):
272
+ def __init__(self, input_resolution: int, patch_size: int, width: int, layers: int, heads: int, output_dim: int,
273
+ linear_patch: str = '2d',):
274
+ super().__init__()
275
+ self.input_resolution = input_resolution
276
+ self.output_dim = output_dim
277
+
278
+ self.conv1 = nn.Conv2d(in_channels=3, out_channels=width, kernel_size=patch_size, stride=patch_size, bias=False)
279
+
280
+ scale = width ** -0.5
281
+ self.class_embedding = nn.Parameter(scale * torch.randn(width))
282
+ self.positional_embedding = nn.Parameter(scale * torch.randn((input_resolution // patch_size) ** 2 + 1, width))
283
+ self.ln_pre = LayerNorm(width)
284
+
285
+ self.transformer = Transformer(width, layers, heads)
286
+
287
+ self.ln_post = LayerNorm(width)
288
+ self.proj = nn.Parameter(scale * torch.randn(width, output_dim))
289
+
290
+ # For 3D
291
+ assert linear_patch in ['2d', '3d']
292
+ self.linear_patch = linear_patch
293
+ if self.linear_patch == '3d':
294
+ self.conv2 = nn.Conv3d(in_channels=3, out_channels=width, kernel_size=(3, patch_size, patch_size),
295
+ stride=(1, patch_size, patch_size), padding=(1, 0, 0), bias=False)
296
+
297
+ def forward(self, x: torch.Tensor, video_frame=-1):
298
+ # logger.info("x.shape:{}".format(x.shape))
299
+ if self.linear_patch == '3d':
300
+ assert video_frame != -1
301
+ x_3d = x.reshape(-1, video_frame, x.shape[-3], x.shape[-2], x.shape[-1])
302
+ x_3d = x_3d.permute(0, 2, 1, 3, 4)
303
+ x_3d = self.conv2(x_3d) # shape = [*, width, frame, grid, grid]
304
+ x_3d = x_3d.permute(0, 2, 1, 3, 4) # shape = [*, frame, width, grid, grid]
305
+ x = x_3d.reshape(-1, x_3d.shape[-3], x_3d.shape[-2], x_3d.shape[-1]).contiguous() # shape = [*, width, grid, grid]
306
+ else:
307
+ x = self.conv1(x) # shape = [*, width, grid, grid]
308
+ # logger.info("x conv1.shape:{}".format(x.shape))
309
+ x = x.reshape(x.shape[0], x.shape[1], -1) # shape = [*, width, grid ** 2]
310
+ x = x.permute(0, 2, 1) # shape = [*, grid ** 2, width]
311
+ x = torch.cat([self.class_embedding.to(x.dtype) + torch.zeros(x.shape[0], 1, x.shape[-1], dtype=x.dtype, device=x.device), x], dim=1) # shape = [*, grid ** 2 + 1, width]
312
+ x = x + self.positional_embedding.to(x.dtype)
313
+ x = self.ln_pre(x)
314
+ x = x.permute(1, 0, 2) # NLD -> LND
315
+ # logger.info("x ln_pre.shape:{}".format(x.shape))
316
+ x = self.transformer(x, video_frame=video_frame)
317
+ x = x.permute(1, 0, 2) # LND -> NLD
318
+ # logger.info("x transformer.shape:{}".format(x.shape))
319
+
320
+ # Move the three lines below to `encode_image` for entire hidden sequence
321
+ # x = self.ln_post(x[:, 0, :])
322
+ # if self.proj is not None:
323
+ # x = x @ self.proj
324
+
325
+ return x
326
+
327
+
328
+ class CLIP(nn.Module):
329
+ def __init__(self,
330
+ embed_dim: int,
331
+ # vision
332
+ image_resolution: int,
333
+ vision_layers: Union[Tuple[int, int, int, int], int],
334
+ vision_width: int,
335
+ vision_patch_size: int,
336
+ # text
337
+ context_length: int,
338
+ vocab_size: int,
339
+ transformer_width: int,
340
+ transformer_heads: int,
341
+ transformer_layers: int,
342
+ # vision linear of patch
343
+ linear_patch: str = '2d',
344
+ ):
345
+ super().__init__()
346
+
347
+ self.context_length = context_length
348
+
349
+ if isinstance(vision_layers, (tuple, list)):
350
+ vision_heads = vision_width * 32 // 64
351
+ self.vit = False
352
+ self.visual = ModifiedResNet(
353
+ layers=vision_layers,
354
+ output_dim=embed_dim,
355
+ heads=vision_heads,
356
+ input_resolution=image_resolution,
357
+ width=vision_width
358
+ )
359
+ else:
360
+ self.vit = True
361
+ vision_heads = vision_width // 64
362
+ self.visual = VisualTransformer(
363
+ input_resolution=image_resolution,
364
+ patch_size=vision_patch_size,
365
+ width=vision_width,
366
+ layers=vision_layers,
367
+ heads=vision_heads,
368
+ output_dim=embed_dim,
369
+ linear_patch=linear_patch
370
+ )
371
+
372
+ self.transformer = Transformer(
373
+ width=transformer_width,
374
+ layers=transformer_layers,
375
+ heads=transformer_heads,
376
+ attn_mask=self.build_attention_mask
377
+ )
378
+
379
+ self.vocab_size = vocab_size
380
+ self.token_embedding = nn.Embedding(vocab_size, transformer_width)
381
+ self.positional_embedding = nn.Parameter(torch.empty(self.context_length, transformer_width))
382
+ self.ln_final = LayerNorm(transformer_width)
383
+
384
+ self.text_projection = nn.Parameter(torch.empty(transformer_width, embed_dim))
385
+ self.logit_scale = nn.Parameter(torch.ones([]))
386
+
387
+ self.initialize_parameters()
388
+
389
+ def initialize_parameters(self):
390
+ nn.init.normal_(self.token_embedding.weight, std=0.02)
391
+ nn.init.normal_(self.positional_embedding, std=0.01)
392
+
393
+ if isinstance(self.visual, ModifiedResNet):
394
+ if self.visual.attnpool is not None:
395
+ std = self.visual.attnpool.c_proj.in_features ** -0.5
396
+ nn.init.normal_(self.visual.attnpool.q_proj.weight, std=std)
397
+ nn.init.normal_(self.visual.attnpool.k_proj.weight, std=std)
398
+ nn.init.normal_(self.visual.attnpool.v_proj.weight, std=std)
399
+ nn.init.normal_(self.visual.attnpool.c_proj.weight, std=std)
400
+
401
+ for resnet_block in [self.visual.layer1, self.visual.layer2, self.visual.layer3, self.visual.layer4]:
402
+ for name, param in resnet_block.named_parameters():
403
+ if name.endswith("bn3.weight"):
404
+ nn.init.zeros_(param)
405
+
406
+ proj_std = (self.transformer.width ** -0.5) * ((2 * self.transformer.layers) ** -0.5)
407
+ attn_std = self.transformer.width ** -0.5
408
+ fc_std = (2 * self.transformer.width) ** -0.5
409
+ for block in self.transformer.resblocks:
410
+ nn.init.normal_(block.attn.in_proj_weight, std=attn_std)
411
+ nn.init.normal_(block.attn.out_proj.weight, std=proj_std)
412
+ nn.init.normal_(block.mlp.c_fc.weight, std=fc_std)
413
+ nn.init.normal_(block.mlp.c_proj.weight, std=proj_std)
414
+
415
+ if self.text_projection is not None:
416
+ nn.init.normal_(self.text_projection, std=self.transformer.width ** -0.5)
417
+
418
+ @staticmethod
419
+ def get_config(pretrained_clip_name="ViT-B/32"):
420
+ # logger.info("pretrained_clip_name:{}".format(pretrained_clip_name))
421
+ model_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ViT-B-32.pt")
422
+ if pretrained_clip_name == "ViT-B/32" and os.path.exists(model_path):
423
+ pass
424
+ else:
425
+ if pretrained_clip_name in _MODELS:
426
+ model_path = _download(_MODELS[pretrained_clip_name])
427
+ elif os.path.isfile(pretrained_clip_name):
428
+ model_path = pretrained_clip_name
429
+ else:
430
+ raise RuntimeError(f"Model {pretrained_clip_name} not found; available models = {available_models()}")
431
+
432
+ try:
433
+ # loading JIT archive
434
+ model = torch.jit.load(model_path, map_location="cpu").eval()
435
+ state_dict = model.state_dict()
436
+ except RuntimeError:
437
+ state_dict = torch.load(model_path, map_location="cpu")
438
+
439
+ return state_dict
440
+
441
+ def build_attention_mask(self, context_length):
442
+ # lazily create causal attention mask, with full attention between the vision tokens
443
+ # pytorch uses additive attention mask; fill with -inf
444
+ mask = torch.zeros(context_length, context_length)
445
+ mask.fill_(float("-inf"))
446
+ mask.triu_(1) # zero out the lower diagonal
447
+ return mask
448
+
449
+ @property
450
+ def dtype(self):
451
+ return self.visual.conv1.weight.dtype
452
+
453
+ def encode_image(self, image, return_hidden=False, video_frame=-1):
454
+ if self.vit:
455
+ # logger.info("image.shape:{}".format(image.shape))
456
+ hidden = self.visual(image.type(self.dtype), video_frame=video_frame)
457
+ # logger.info("hidden1.shape:{}".format(hidden.shape))
458
+ hidden = self.visual.ln_post(hidden) @ self.visual.proj
459
+ # logger.info("hidden2.shape:{}".format(hidden.shape))
460
+ x = hidden[:, 0, :]
461
+ # x = hidden
462
+ else:
463
+ hidden = self.visual(image.type(self.dtype))
464
+ x = hidden
465
+ if return_hidden:
466
+ return x, hidden
467
+
468
+ return x
469
+
470
+ def encode_text(self, text, return_hidden=False):
471
+ x = self.token_embedding(text).type(self.dtype) # [batch_size, n_ctx, d_model]
472
+
473
+ pos_emd = self.positional_embedding[:x.size(1), :].type(self.dtype)
474
+ x = x + pos_emd
475
+ x = x.permute(1, 0, 2) # NLD -> LND
476
+ x = self.transformer(x)
477
+ x = x.permute(1, 0, 2) # LND -> NLD
478
+
479
+ hidden = self.ln_final(x).type(self.dtype) @ self.text_projection
480
+ # x.shape = [batch_size, n_ctx, transformer.width]
481
+ # take features from the eot embedding (eot_token is the highest number in each sequence)
482
+ x = hidden[torch.arange(hidden.shape[0]), text.argmax(dim=-1)]
483
+
484
+ if return_hidden:
485
+ return x, hidden
486
+
487
+ return x
488
+
489
+ def forward(self, image, text):
490
+ image_features = self.encode_image(image)
491
+ text_features = self.encode_text(text)
492
+
493
+ # normalized features
494
+ image_features = image_features / image_features.norm(dim=-1, keepdim=True)
495
+ text_features = text_features / text_features.norm(dim=-1, keepdim=True)
496
+
497
+ # cosine similarity as logits
498
+ logit_scale = self.logit_scale.exp()
499
+ logits_per_image = logit_scale * image_features @ text_features.t()
500
+ logits_per_text = logit_scale * text_features @ image_features.t()
501
+
502
+ # shape = [global_batch_size, global_batch_size]
503
+ return logits_per_image, logits_per_text
504
+
505
+
506
+ def convert_weights(model: nn.Module):
507
+ """Convert applicable model parameters to fp16"""
508
+
509
+ def _convert_weights_to_fp16(l):
510
+ if isinstance(l, (nn.Conv1d, nn.Conv2d, nn.Conv3d, nn.Linear)):
511
+ l.weight.data = l.weight.data.half()
512
+ if l.bias is not None:
513
+ l.bias.data = l.bias.data.half()
514
+
515
+ if isinstance(l, nn.MultiheadAttention):
516
+ for attr in [*[f"{s}_proj_weight" for s in ["in", "q", "k", "v"]], "in_proj_bias", "bias_k", "bias_v"]:
517
+ tensor = getattr(l, attr)
518
+ if tensor is not None:
519
+ tensor.data = tensor.data.half()
520
+
521
+ for name in ["text_projection", "proj"]:
522
+ if hasattr(l, name):
523
+ attr = getattr(l, name)
524
+ if attr is not None:
525
+ attr.data = attr.data.half()
526
+
527
+ model.apply(_convert_weights_to_fp16)
528
+
529
+
530
+ def build_model(state_dict: dict, local_rank):
531
+ vit = "visual.proj" in state_dict
532
+
533
+ if vit:
534
+ vision_width = state_dict["visual.conv1.weight"].shape[0]
535
+ vision_layers = len([k for k in state_dict.keys() if k.startswith("visual.") and k.endswith(".attn.in_proj_weight")])
536
+ vision_patch_size = state_dict["visual.conv1.weight"].shape[-1]
537
+ grid_size = round((state_dict["visual.positional_embedding"].shape[0] - 1) ** 0.5)
538
+ image_resolution = vision_patch_size * grid_size
539
+ else:
540
+ counts: list = [len(set(k.split(".")[2] for k in state_dict if k.startswith(f"visual.layer{b}"))) for b in [1, 2, 3, 4]]
541
+ vision_layers = tuple(counts)
542
+ vision_width = state_dict["visual.layer1.0.conv1.weight"].shape[0]
543
+ output_width = round((state_dict["visual.attnpool.positional_embedding"].shape[0] - 1) ** 0.5)
544
+ vision_patch_size = None
545
+ assert output_width ** 2 + 1 == state_dict["visual.attnpool.positional_embedding"].shape[0]
546
+ image_resolution = output_width * 32
547
+
548
+ embed_dim = state_dict["text_projection"].shape[1]
549
+ context_length = state_dict["positional_embedding"].shape[0]
550
+ vocab_size = state_dict["token_embedding.weight"].shape[0]
551
+ transformer_width = state_dict["ln_final.weight"].shape[0]
552
+ transformer_heads = transformer_width // 64
553
+ transformer_layers = len(set(k.split(".")[2] for k in state_dict if k.startswith(f"transformer.resblocks")))
554
+ if local_rank == 0:
555
+ logger.info("\t embed_dim: {}".format(embed_dim))
556
+ logger.info("\t image_resolution: {}".format(image_resolution))
557
+ logger.info("\t vision_layers: {}".format(vision_layers))
558
+ logger.info("\t vision_width: {}".format(vision_width))
559
+ logger.info("\t vision_patch_size: {}".format(vision_patch_size))
560
+ logger.info("\t context_length: {}".format(context_length))
561
+ logger.info("\t not used vocab_size: {}".format(vocab_size))
562
+ logger.info("\t transformer_width: {}".format(transformer_width))
563
+ logger.info("\t transformer_heads: {}".format(transformer_heads))
564
+ logger.info("\t transformer_layers: {}".format(transformer_layers))
565
+
566
+ model = CLIP(
567
+ embed_dim,
568
+ image_resolution, vision_layers, vision_width, vision_patch_size,
569
+ context_length, vocab_size, transformer_width, transformer_heads, transformer_layers
570
+ ).float()
571
+
572
+ for key in ["input_resolution", "context_length", "vocab_size"]:
573
+ if key in state_dict:
574
+ del state_dict[key]
575
+
576
+ # convert_weights(model) # cpu mode should comment this line
577
+ model.load_state_dict(state_dict)
578
+ # return model.eval()
579
+ return model
modules/module_cross.py ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+ from __future__ import division
3
+ from __future__ import print_function
4
+
5
+ import os
6
+ import copy
7
+ import json
8
+ import math
9
+ import logging
10
+ import tarfile
11
+ import tempfile
12
+ import shutil
13
+ import sys
14
+
15
+ import torch
16
+ from torch import nn
17
+ import torch.nn.functional as F
18
+ from .file_utils import cached_path
19
+ from .until_config import PretrainedConfig
20
+ from .until_module import PreTrainedModel, LayerNorm, ACT2FN
21
+ from collections import OrderedDict
22
+ from modules.module_clip import build_model, CLIP, convert_weights
23
+ from transformers import AutoConfig, AutoModel, RobertaModel, RobertaConfig
24
+
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+ PRETRAINED_MODEL_ARCHIVE_MAP = {}
29
+ CONFIG_NAME = 'cross_config.json'
30
+ WEIGHTS_NAME = 'cross_pytorch_model.bin'
31
+
32
+
33
+ def gelu(x):
34
+ """Implementation of the gelu activation function.
35
+ For information: OpenAI GPT's gelu is slightly different (and gives slightly different results):
36
+ 0.5 * x * (1 + torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3))))
37
+ Also see https://arxiv.org/abs/1606.08415
38
+ """
39
+ return x * 0.5 * (1.0 + torch.erf(x / math.sqrt(2.0)))
40
+
41
+
42
+ def swish(x):
43
+ return x * torch.sigmoid(x)
44
+
45
+ ACT2FN = {"gelu": gelu, "relu": torch.nn.functional.relu, "swish": swish}
46
+
47
+ class CrossConfig(PretrainedConfig):
48
+ """Configuration class to store the configuration of a `CrossModel`.
49
+ """
50
+ pretrained_model_archive_map = PRETRAINED_MODEL_ARCHIVE_MAP
51
+ config_name = CONFIG_NAME
52
+ weights_name = WEIGHTS_NAME
53
+ def __init__(self,
54
+ vocab_size_or_config_json_file,
55
+ hidden_size=768,
56
+ num_hidden_layers=12,
57
+ num_attention_heads=12,
58
+ intermediate_size=3072,
59
+ hidden_act="gelu",
60
+ hidden_dropout_prob=0.1,
61
+ attention_probs_dropout_prob=0.1,
62
+ max_position_embeddings=512,
63
+ type_vocab_size=2,
64
+ initializer_range=0.02):
65
+ """Constructs CrossConfig.
66
+
67
+ Args:
68
+ vocab_size_or_config_json_file: Vocabulary size of `inputs_ids` in `CrossModel`.
69
+ hidden_size: Size of the encoder layers and the pooler layer.
70
+ num_hidden_layers: Number of hidden layers in the Transformer encoder.
71
+ num_attention_heads: Number of attention heads for each attention layer in
72
+ the Transformer encoder.
73
+ intermediate_size: The size of the "intermediate" (i.e., feed-forward)
74
+ layer in the Transformer encoder.
75
+ hidden_act: The non-linear activation function (function or string) in the
76
+ encoder and pooler. If string, "gelu", "relu" and "swish" are supported.
77
+ hidden_dropout_prob: The dropout probabilitiy for all fully connected
78
+ layers in the embeddings, encoder, and pooler.
79
+ attention_probs_dropout_prob: The dropout ratio for the attention
80
+ probabilities.
81
+ max_position_embeddings: The maximum sequence length that this model might
82
+ ever be used with. Typically set this to something large just in case
83
+ (e.g., 512 or 1024 or 2048).
84
+ type_vocab_size: The vocabulary size of the `token_type_ids` passed into
85
+ `CrossModel`.
86
+ initializer_range: The sttdev of the truncated_normal_initializer for
87
+ initializing all weight matrices.
88
+ """
89
+ if isinstance(vocab_size_or_config_json_file, str):
90
+ with open(vocab_size_or_config_json_file, "r", encoding='utf-8') as reader:
91
+ json_config = json.loads(reader.read())
92
+ for key, value in json_config.items():
93
+ self.__dict__[key] = value
94
+ elif isinstance(vocab_size_or_config_json_file, int):
95
+ self.vocab_size = vocab_size_or_config_json_file
96
+ self.hidden_size = hidden_size
97
+ self.num_hidden_layers = num_hidden_layers
98
+ self.num_attention_heads = num_attention_heads
99
+ self.hidden_act = hidden_act
100
+ self.intermediate_size = intermediate_size
101
+ self.hidden_dropout_prob = hidden_dropout_prob
102
+ self.attention_probs_dropout_prob = attention_probs_dropout_prob
103
+ self.max_position_embeddings = max_position_embeddings
104
+ self.type_vocab_size = type_vocab_size
105
+ self.initializer_range = initializer_range
106
+ else:
107
+ raise ValueError("First argument must be either a vocabulary size (int)"
108
+ "or the path to a pretrained model config file (str)")
109
+
110
+ class QuickGELU(nn.Module):
111
+ def forward(self, x: torch.Tensor):
112
+ return x * torch.sigmoid(1.702 * x)
113
+
114
+ class ResidualAttentionBlock(nn.Module):
115
+ def __init__(self, d_model: int, n_head: int):
116
+ super().__init__()
117
+
118
+ self.attn = nn.MultiheadAttention(d_model, n_head)
119
+ self.ln_1 = LayerNorm(d_model)
120
+ self.mlp = nn.Sequential(OrderedDict([
121
+ ("c_fc", nn.Linear(d_model, d_model * 4)),
122
+ ("gelu", QuickGELU()),
123
+ ("c_proj", nn.Linear(d_model * 4, d_model))
124
+ ]))
125
+ self.ln_2 = LayerNorm(d_model)
126
+ self.n_head = n_head
127
+
128
+ def attention(self, x: torch.Tensor, attn_mask: torch.Tensor):
129
+ attn_mask_ = attn_mask.repeat(self.n_head, 1, 1)
130
+ return self.attn(x, x, x, need_weights=False, attn_mask=attn_mask_)[0]
131
+
132
+ def forward(self, para_tuple: tuple):
133
+ # x: torch.Tensor, attn_mask: torch.Tensor
134
+ # print(para_tuple)
135
+ x, attn_mask = para_tuple
136
+ x = x + self.attention(self.ln_1(x), attn_mask)
137
+ x = x + self.mlp(self.ln_2(x))
138
+ return (x, attn_mask)
139
+
140
+ class Transformer(nn.Module):
141
+ def __init__(self, width: int, layers: int, heads: int):
142
+ super().__init__()
143
+ self.width = width
144
+ self.layers = layers
145
+ self.resblocks = nn.Sequential(*[ResidualAttentionBlock(width, heads) for _ in range(layers)])
146
+
147
+ def forward(self, x: torch.Tensor, attn_mask: torch.Tensor):
148
+ # logger.info("x.shpae:{},attn_mask:{}".format(x.shape, attn_mask.shape))
149
+ return self.resblocks((x, attn_mask))[0]
150
+
151
+
152
+ class VisualEncoder(nn.Module):
153
+ def __init__(self, task_config, cross_config):
154
+ super().__init__()
155
+ pretrained_clip_name = cross_config.pretrained_clip_name
156
+ if task_config.local_rank == 0:
157
+ logger.info("pretrained_clip_name:{}".format(pretrained_clip_name))
158
+ clip_state_dict = CLIP.get_config(pretrained_clip_name=pretrained_clip_name)
159
+ clip = build_model(clip_state_dict, local_rank=task_config.local_rank)
160
+ self.use_temp = task_config.use_temp
161
+ self.is_vit = copy.deepcopy(clip.vit)
162
+ self.visual = copy.deepcopy(clip.visual)
163
+
164
+ if self.use_temp:
165
+ self.temporal_transformer = Transformer(width=cross_config.temporal_hidden_size,
166
+ layers=cross_config.temporal_hidden_layers,
167
+ heads=cross_config.temporal_attention_heads)
168
+ self.frame_position_embeddings = nn.Embedding(cross_config.max_position_embeddings,
169
+ cross_config.temporal_hidden_size)
170
+
171
+ # use clip.transformer to initial temporal_transformer
172
+ # for param_1, param_2 in zip(self.temporal_transformer.parameters(), clip.transformer.parameters()):
173
+ # param_1.data.copy_(param_2.data) # initialize
174
+ # if task_config.local_rank == 0:
175
+ # logger.info("clip.positional_embedding:{}".format(clip.positional_embedding))
176
+ # self.frame_position_embeddings.weight = copy.deepcopy(clip.positional_embedding)
177
+
178
+ def forward(self, video, video_frames):
179
+ # encode frames
180
+ bs, frames, channel, h, w = video.shape
181
+ # [bs*frame, 3, 224, 224]
182
+ video = video.view(bs * frames, channel, h, w)
183
+ # logger.info("video_b.shape:{}, dtype:{}".format(video_b.shape, video_b.dtype))
184
+ # logger.info("video_frame[{}]:{}".format(b, video_frame))
185
+ visual_hidden = self.encode_image(video, video_frame=frames)
186
+ # [bs, frame, hidden_size]
187
+ # logger.info("visual_hidden.shape:{}".format(visual_hidden.shape))
188
+ visual_hidden = visual_hidden.view(bs, frames, visual_hidden.size(-1))
189
+ # logger.info("visual_hidden1.shape:{}".format(visual_hidden.shape))
190
+ # get temporal information
191
+ visual_hidden_original = visual_hidden
192
+ frame_output = visual_hidden_original
193
+ if self.use_temp:
194
+ seq_length = visual_hidden.size(1)
195
+ position_ids = torch.arange(seq_length, dtype=torch.long, device=visual_hidden.device)
196
+ # logger.info("position_ids.shape:{}".format(position_ids.shape))
197
+ frame_position_embeddings = self.frame_position_embeddings(position_ids)
198
+ # logger.info("frame_position_embeddings.shape:{}".format(frame_position_embeddings.shape))
199
+ visual_hidden = visual_hidden + frame_position_embeddings
200
+
201
+ video_mask = torch.ones([bs, frames], device=visual_hidden.device)
202
+ extended_video_mask = (1.0 - video_mask.unsqueeze(1)) * -1000000.0
203
+ extended_video_mask = extended_video_mask.expand(-1, video_mask.size(1), -1)
204
+ visual_hidden = visual_hidden.permute(1, 0, 2) # NLD -> LND
205
+ visual_hidden = self.temporal_transformer(visual_hidden, extended_video_mask)
206
+ visual_hidden = visual_hidden.permute(1, 0, 2) # LND -> NLD
207
+ visual_hidden = visual_hidden + visual_hidden_original
208
+
209
+ # logger.info("visual_hidden.shape:{}".format(visual_hidden.shape))
210
+ visual_output = visual_hidden / visual_hidden.norm(dim=-1, keepdim=True)
211
+ # [bs, frames,512] -> [bs, 512]
212
+ visual_output = torch.mean(visual_output, dim=1)
213
+ # logger.info("visual_hidden mean.shape:{}".format(visual_hidden.shape))
214
+
215
+ # logger.info("visual encoder visual_output.shape:{}".format(visual_output.shape))
216
+ return visual_output, frame_output
217
+
218
+ @property
219
+ def dtype(self):
220
+ return self.visual.conv1.weight.dtype
221
+
222
+ def encode_image(self, image, return_hidden=False, video_frame=-1):
223
+ if self.is_vit:
224
+ # logger.info("image.shape:{}".format(image.shape))
225
+ # hidden = self.visual(image, video_frame=video_frame)
226
+ hidden = self.visual(image.type(self.dtype), video_frame=video_frame)
227
+ # logger.info("hidden1.shape:{}".format(hidden.shape))
228
+ hidden = self.visual.ln_post(hidden) @ self.visual.proj
229
+ # logger.info("hidden2.shape:{}".format(hidden.shape))
230
+ x = hidden[:, 0, :]
231
+ # x = hidden
232
+ else:
233
+ hidden = self.visual(image)
234
+ x = hidden
235
+ if return_hidden:
236
+ return x.float(), hidden.float()
237
+ return x.float()
238
+
239
+
240
+ class TextEncoder(nn.Module):
241
+ def __init__(self, task_config, cross_config):
242
+ super().__init__()
243
+ self.language = task_config.language
244
+ pretrained_clip_name = cross_config.pretrained_clip_name
245
+ if task_config.local_rank == 0:
246
+ logger.info("pretrained_clip_name:{}".format(pretrained_clip_name))
247
+ clip_state_dict = CLIP.get_config(pretrained_clip_name=pretrained_clip_name)
248
+ clip = build_model(clip_state_dict, local_rank=task_config.local_rank)
249
+ self.logit_scale = copy.deepcopy(clip_state_dict["logit_scale"])
250
+ if self.language == "english":
251
+ self.token_embedding = copy.deepcopy(clip.token_embedding)
252
+ self.positional_embedding = copy.deepcopy(clip.positional_embedding)
253
+ self.transformer = copy.deepcopy(clip.transformer)
254
+ self.ln_final = copy.deepcopy(clip.ln_final)
255
+ self.text_projection = copy.deepcopy(clip.text_projection)
256
+ self.dtype = clip.visual.conv1.weight.dtype
257
+ elif self.language == "chinese":
258
+ pretrained = task_config.pretrained_text
259
+ t_config = AutoConfig.from_pretrained(pretrained)
260
+ if task_config.rank == 0:
261
+ logger.info("name:{},chinesebert_config:{}".format(pretrained, t_config))
262
+ self.chinese_encoder = AutoModel.from_pretrained(pretrained)
263
+ # logger.info("random Roberta")
264
+ # self.chinese_encoder = RobertaModel(RobertaConfig())
265
+ self.text_proj = nn.Linear(cross_config.chinese_hidden_size, cross_config.temporal_hidden_size)
266
+ else:
267
+ raise NotImplementedError("wrong language")
268
+
269
+ def forward(self, input_ids, attention_mask, return_hidden=False):
270
+ bs_pair = input_ids.size(0)
271
+ if self.language == "english":
272
+ text_output, hidden = self.encode_text(input_ids, return_hidden=True)
273
+ else:
274
+ temp_output = self.chinese_encoder(input_ids, attention_mask=attention_mask)
275
+ # logger.info("hidden:{},text_output:{}".format(temp_output[0].shape, temp_output[1].shape))
276
+ hidden = self.text_proj(temp_output[0])
277
+ text_output = self.text_proj(temp_output[1])
278
+
279
+ text_output = text_output.view(bs_pair, text_output.size(-1))
280
+ hidden = hidden.view(bs_pair, -1, hidden.size(-1))
281
+ if return_hidden:
282
+ return hidden
283
+ else:
284
+ return text_output
285
+
286
+ def encode_text(self, text, return_hidden=False):
287
+ x = self.token_embedding(text).type(self.dtype) # [batch_size, n_ctx, d_model]
288
+
289
+ pos_emd = self.positional_embedding[:x.size(1), :].type(self.dtype)
290
+ x = x + pos_emd
291
+ x = x.permute(1, 0, 2) # NLD -> LND
292
+ x = self.transformer(x)
293
+ x = x.permute(1, 0, 2) # LND -> NLD
294
+
295
+ hidden = self.ln_final(x).type(self.dtype) @ self.text_projection
296
+
297
+ # x.shape = [batch_size, n_ctx, transformer.width]
298
+ # take features from the eot embedding (eot_token is the highest number in each sequence)
299
+ x = hidden[torch.arange(hidden.shape[0]), text.argmax(dim=-1)]
300
+
301
+ if return_hidden:
302
+ return x.float(), hidden.float()
303
+
304
+ return x.float()
305
+
306
+
307
+ class BertLMPredictionHead(nn.Module):
308
+ def __init__(self, config):
309
+ super(BertLMPredictionHead, self).__init__()
310
+ self.transform = BertPredictionHeadTransform(config)
311
+
312
+ # The output weights are the same as the input embeddings, but there is
313
+ # an output-only bias for each token.
314
+ self.decoder = nn.Linear(config.hidden_size, config.vocab_size,bias=False,)
315
+ self.bias = nn.Parameter(torch.zeros(config.vocab_size))
316
+ self.decoder.bias = self.bias
317
+
318
+ def forward(self, hidden_states):
319
+ hidden_states = self.transform(hidden_states)
320
+ hidden_states = self.decoder(hidden_states)
321
+ return hidden_states
322
+
323
+
324
+ class BertPredictionHeadTransform(nn.Module):
325
+ def __init__(self, config):
326
+ super(BertPredictionHeadTransform, self).__init__()
327
+ self.dense = nn.Linear(config.hidden_size, config.hidden_size)
328
+ if isinstance(config.hidden_act, str) or (
329
+ sys.version_info[0] == 2 and isinstance(config.hidden_act, unicode)
330
+ ):
331
+ self.transform_act_fn = ACT2FN[config.hidden_act]
332
+ else:
333
+ self.transform_act_fn = config.hidden_act
334
+ self.LayerNorm = BertLayerNorm(config.hidden_size, eps=1e-12)
335
+
336
+ def forward(self, hidden_states):
337
+ hidden_states = self.dense(hidden_states)
338
+ hidden_states = self.transform_act_fn(hidden_states)
339
+ hidden_states = self.LayerNorm(hidden_states)
340
+ return hidden_states
341
+
342
+
343
+ class BertLayerNorm(nn.Module):
344
+ def __init__(self, hidden_size, eps=1e-12):
345
+ """Construct a layernorm module in the TF style (epsilon inside the square root).
346
+ """
347
+ super(BertLayerNorm, self).__init__()
348
+ self.weight = nn.Parameter(torch.ones(hidden_size))
349
+ self.bias = nn.Parameter(torch.zeros(hidden_size))
350
+ self.variance_epsilon = eps
351
+
352
+ def forward(self, x):
353
+ u = x.mean(-1, keepdim=True)
354
+ s = (x - u).pow(2).mean(-1, keepdim=True)
355
+ x = (x - u) / torch.sqrt(s + self.variance_epsilon)
356
+ return self.weight * x + self.bias
modules/optimization.py ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2018 The Google AI Language Team Authors and The HugginFace Inc. team.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """PyTorch optimization for BERT model."""
16
+
17
+ import math
18
+ import torch
19
+ from torch.optim import Optimizer
20
+ from torch.optim.optimizer import required
21
+ from torch.nn.utils import clip_grad_norm_
22
+ import logging
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+ def warmup_cosine(x, warmup=0.002):
27
+ if x < warmup:
28
+ return x/warmup
29
+ return 0.5 * (1.0 + math.cos(math.pi * x))
30
+
31
+ def warmup_constant(x, warmup=0.002):
32
+ """ Linearly increases learning rate over `warmup`*`t_total` (as provided to BertAdam) training steps.
33
+ Learning rate is 1. afterwards. """
34
+ if x < warmup:
35
+ return x/warmup
36
+ return 1.0
37
+
38
+ def warmup_linear(x, warmup=0.002):
39
+ """ Specifies a triangular learning rate schedule where peak is reached at `warmup`*`t_total`-th (as provided to BertAdam) training step.
40
+ After `t_total`-th training step, learning rate is zero. """
41
+ if x < warmup:
42
+ return x/warmup
43
+ return max((x-1.)/(warmup-1.), 0)
44
+
45
+ SCHEDULES = {
46
+ 'warmup_cosine': warmup_cosine,
47
+ 'warmup_constant': warmup_constant,
48
+ 'warmup_linear': warmup_linear,
49
+ }
50
+
51
+
52
+ class BertAdam(Optimizer):
53
+ """Implements BERT version of Adam algorithm with weight decay fix.
54
+ Params:
55
+ lr: learning rate
56
+ warmup: portion of t_total for the warmup, -1 means no warmup. Default: -1
57
+ t_total: total number of training steps for the learning
58
+ rate schedule, -1 means constant learning rate. Default: -1
59
+ schedule: schedule to use for the warmup (see above). Default: 'warmup_linear'
60
+ b1: Adams b1. Default: 0.9
61
+ b2: Adams b2. Default: 0.999
62
+ e: Adams epsilon. Default: 1e-6
63
+ weight_decay: Weight decay. Default: 0.01
64
+ max_grad_norm: Maximum norm for the gradients (-1 means no clipping). Default: 1.0
65
+ """
66
+ def __init__(self, params, lr=required, warmup=-1, t_total=-1, schedule='warmup_linear',
67
+ b1=0.9, b2=0.999, e=1e-6, weight_decay=0.01,
68
+ max_grad_norm=1.0):
69
+ if lr is not required and lr < 0.0:
70
+ raise ValueError("Invalid learning rate: {} - should be >= 0.0".format(lr))
71
+ if schedule not in SCHEDULES:
72
+ raise ValueError("Invalid schedule parameter: {}".format(schedule))
73
+ if not 0.0 <= warmup < 1.0 and not warmup == -1:
74
+ raise ValueError("Invalid warmup: {} - should be in [0.0, 1.0[ or -1".format(warmup))
75
+ if not 0.0 <= b1 < 1.0:
76
+ raise ValueError("Invalid b1 parameter: {} - should be in [0.0, 1.0[".format(b1))
77
+ if not 0.0 <= b2 < 1.0:
78
+ raise ValueError("Invalid b2 parameter: {} - should be in [0.0, 1.0[".format(b2))
79
+ if not e >= 0.0:
80
+ raise ValueError("Invalid epsilon value: {} - should be >= 0.0".format(e))
81
+ defaults = dict(lr=lr, schedule=schedule, warmup=warmup, t_total=t_total,
82
+ b1=b1, b2=b2, e=e, weight_decay=weight_decay,
83
+ max_grad_norm=max_grad_norm)
84
+ super(BertAdam, self).__init__(params, defaults)
85
+
86
+ def get_lr(self):
87
+ lr = []
88
+ for group in self.param_groups:
89
+ for p in group['params']:
90
+ if p.grad is None:
91
+ continue
92
+ state = self.state[p]
93
+ if len(state) == 0:
94
+ return [0]
95
+ if group['t_total'] != -1:
96
+ schedule_fct = SCHEDULES[group['schedule']]
97
+ lr_scheduled = group['lr'] * schedule_fct(state['step']/group['t_total'], group['warmup'])
98
+ else:
99
+ lr_scheduled = group['lr']
100
+ lr.append(lr_scheduled)
101
+ return lr
102
+
103
+ def step(self, closure=None):
104
+ """Performs a single optimization step.
105
+ Arguments:
106
+ closure (callable, optional): A closure that reevaluates the model
107
+ and returns the loss.
108
+ """
109
+ loss = None
110
+ if closure is not None:
111
+ loss = closure()
112
+
113
+ for group in self.param_groups:
114
+ for p in group['params']:
115
+ if p.grad is None:
116
+ continue
117
+ grad = p.grad.data
118
+ if grad.is_sparse:
119
+ raise RuntimeError('Adam does not support sparse gradients, please consider SparseAdam instead')
120
+
121
+ state = self.state[p]
122
+
123
+ # State initialization
124
+ if len(state) == 0:
125
+ state['step'] = 0
126
+ # Exponential moving average of gradient values
127
+ state['next_m'] = torch.zeros_like(p.data)
128
+ # Exponential moving average of squared gradient values
129
+ state['next_v'] = torch.zeros_like(p.data)
130
+
131
+ next_m, next_v = state['next_m'], state['next_v']
132
+ beta1, beta2 = group['b1'], group['b2']
133
+
134
+ # Add grad clipping
135
+ if group['max_grad_norm'] > 0:
136
+ clip_grad_norm_(p, group['max_grad_norm'])
137
+
138
+ # Decay the first and second moment running average coefficient
139
+ # In-place operations to update the averages at the same time
140
+ # next_m.mul_(beta1).add_(1 - beta1, grad) --> pytorch 1.7
141
+ next_m.mul_(beta1).add_(grad, alpha=1 - beta1)
142
+ # next_v.mul_(beta2).addcmul_(1 - beta2, grad, grad) --> pytorch 1.7
143
+ next_v.mul_(beta2).addcmul_(grad, grad, value=1 - beta2)
144
+ update = next_m / (next_v.sqrt() + group['e'])
145
+
146
+ # Just adding the square of the weights to the loss function is *not*
147
+ # the correct way of using L2 regularization/weight decay with Adam,
148
+ # since that will interact with the m and v parameters in strange ways.
149
+ #
150
+ # Instead we want to decay the weights in a manner that doesn't interact
151
+ # with the m/v parameters. This is equivalent to adding the square
152
+ # of the weights to the loss with plain (non-momentum) SGD.
153
+ if group['weight_decay'] > 0.0:
154
+ update += group['weight_decay'] * p.data
155
+
156
+ if group['t_total'] != -1:
157
+ schedule_fct = SCHEDULES[group['schedule']]
158
+ progress = state['step']/group['t_total']
159
+ lr_scheduled = group['lr'] * schedule_fct(progress, group['warmup'])
160
+ else:
161
+ lr_scheduled = group['lr']
162
+
163
+ update_with_lr = lr_scheduled * update
164
+ p.data.add_(-update_with_lr)
165
+
166
+ state['step'] += 1
167
+
168
+ return loss
modules/tokenization_clip.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gzip
2
+ import html
3
+ import os
4
+ from functools import lru_cache
5
+
6
+ import ftfy
7
+ import regex as re
8
+ import logging
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ @lru_cache()
13
+ def default_bpe():
14
+ return os.path.join(os.path.dirname(os.path.abspath(__file__)), "bpe_simple_vocab_16e6.txt.gz")
15
+
16
+
17
+ @lru_cache()
18
+ def bytes_to_unicode():
19
+ """
20
+ Returns list of utf-8 byte and a corresponding list of unicode strings.
21
+ The reversible bpe codes work on unicode strings.
22
+ This means you need a large # of unicode characters in your vocab if you want to avoid UNKs.
23
+ When you're at something like a 10B token dataset you end up needing around 5K for decent coverage.
24
+ This is a signficant percentage of your normal, say, 32K bpe vocab.
25
+ To avoid that, we want lookup tables between utf-8 bytes and unicode strings.
26
+ And avoids mapping to whitespace/control characters the bpe code barfs on.
27
+ """
28
+ bs = list(range(ord("!"), ord("~")+1))+list(range(ord("¡"), ord("¬")+1))+list(range(ord("®"), ord("ÿ")+1))
29
+ cs = bs[:]
30
+ n = 0
31
+ for b in range(2**8):
32
+ if b not in bs:
33
+ bs.append(b)
34
+ cs.append(2**8+n)
35
+ n += 1
36
+ cs = [chr(n) for n in cs]
37
+ return dict(zip(bs, cs))
38
+
39
+
40
+ def get_pairs(word):
41
+ """Return set of symbol pairs in a word.
42
+ Word is represented as tuple of symbols (symbols being variable-length strings).
43
+ """
44
+ pairs = set()
45
+ prev_char = word[0]
46
+ for char in word[1:]:
47
+ pairs.add((prev_char, char))
48
+ prev_char = char
49
+ return pairs
50
+
51
+
52
+ def basic_clean(text):
53
+ text = ftfy.fix_text(text)
54
+ text = html.unescape(html.unescape(text))
55
+ return text.strip()
56
+
57
+
58
+ def whitespace_clean(text):
59
+ text = re.sub(r'\s+', ' ', text)
60
+ text = text.strip()
61
+ return text
62
+
63
+
64
+ class SimpleTokenizer(object):
65
+ def __init__(self, bpe_path: str = default_bpe()):
66
+ self.byte_encoder = bytes_to_unicode()
67
+ self.byte_decoder = {v: k for k, v in self.byte_encoder.items()}
68
+ merges = gzip.open(bpe_path).read().decode("utf-8").split('\n')
69
+ merges = merges[1:49152-256-2+1]
70
+ merges = [tuple(merge.split()) for merge in merges]
71
+ vocab = list(bytes_to_unicode().values())
72
+ vocab = vocab + [v+'</w>' for v in vocab]
73
+ for merge in merges:
74
+ vocab.append(''.join(merge))
75
+ vocab.extend(['<|startoftext|>', '<|endoftext|>'])
76
+ vocab[49394] = '[MASK]'
77
+ self.encoder = dict(zip(vocab, range(len(vocab))))
78
+ self.decoder = {v: k for k, v in self.encoder.items()}
79
+ self.bpe_ranks = dict(zip(merges, range(len(merges))))
80
+ self.cache = {'<|startoftext|>': '<|startoftext|>', '<|endoftext|>': '<|endoftext|>', '[MASK]': '[MASK]'}
81
+ self.pat = re.compile(r"""<\|startoftext\|>|<\|endoftext\|>|'s|'t|'re|'ve|'m|'ll|'d|[\p{L}]+|[\p{N}]|[^\s\p{L}\p{N}]+""", re.IGNORECASE)
82
+
83
+ self.vocab = self.encoder
84
+ self.vocab_size = len(vocab)
85
+ self.pad_token_id = self.encoder['<|endoftext|>']
86
+ self.cls_token_id = self.encoder["<|startoftext|>"]
87
+ self.mask_token_id = self.encoder['[MASK]']
88
+
89
+ def bpe(self, token):
90
+ if token in self.cache:
91
+ return self.cache[token]
92
+ word = tuple(token[:-1]) + ( token[-1] + '</w>',)
93
+ pairs = get_pairs(word)
94
+
95
+ if not pairs:
96
+ return token+'</w>'
97
+
98
+ while True:
99
+ bigram = min(pairs, key = lambda pair: self.bpe_ranks.get(pair, float('inf')))
100
+ if bigram not in self.bpe_ranks:
101
+ break
102
+ first, second = bigram
103
+ new_word = []
104
+ i = 0
105
+ while i < len(word):
106
+ try:
107
+ j = word.index(first, i)
108
+ new_word.extend(word[i:j])
109
+ i = j
110
+ except:
111
+ new_word.extend(word[i:])
112
+ break
113
+
114
+ if word[i] == first and i < len(word)-1 and word[i+1] == second:
115
+ new_word.append(first+second)
116
+ i += 2
117
+ else:
118
+ new_word.append(word[i])
119
+ i += 1
120
+ new_word = tuple(new_word)
121
+ word = new_word
122
+ if len(word) == 1:
123
+ break
124
+ else:
125
+ pairs = get_pairs(word)
126
+ word = ' '.join(word)
127
+ self.cache[token] = word
128
+ return word
129
+
130
+ def encode(self, text):
131
+ bpe_tokens = []
132
+ text = whitespace_clean(basic_clean(text)).lower()
133
+ for token in re.findall(self.pat, text):
134
+ token = ''.join(self.byte_encoder[b] for b in token.encode('utf-8'))
135
+ bpe_tokens.extend(self.encoder[bpe_token] for bpe_token in self.bpe(token).split(' '))
136
+ return bpe_tokens
137
+
138
+ def decode(self, tokens):
139
+ text = ''.join([self.decoder[token] for token in tokens])
140
+ text = bytearray([self.byte_decoder[c] for c in text]).decode('utf-8', errors="replace").replace('</w>', ' ')
141
+ return text
142
+
143
+ def tokenize(self, text):
144
+ tokens = []
145
+ text = whitespace_clean(basic_clean(text)).lower()
146
+ for token in re.findall(self.pat, text):
147
+ token = ''.join(self.byte_encoder[b] for b in token.encode('utf-8'))
148
+ tokens.extend(bpe_token for bpe_token in self.bpe(token).split(' '))
149
+ return tokens
150
+
151
+ def convert_tokens_to_ids(self, tokens):
152
+ return [self.encoder[bpe_token] for bpe_token in tokens]
modules/until_config.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2018 The Google AI Language Team Authors and The HugginFace Inc. team.
3
+ # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ """PyTorch BERT model."""
17
+
18
+ from __future__ import absolute_import
19
+ from __future__ import division
20
+ from __future__ import print_function
21
+
22
+ import os
23
+ import copy
24
+ import json
25
+ import logging
26
+ import tarfile
27
+ import tempfile
28
+ import shutil
29
+ import torch
30
+ from .file_utils import cached_path
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+ class PretrainedConfig(object):
35
+
36
+ pretrained_model_archive_map = {}
37
+ config_name = ""
38
+ weights_name = ""
39
+
40
+ @classmethod
41
+ def get_config(cls, pretrained_model_name, cache_dir, type_vocab_size, state_dict, task_config=None):
42
+ archive_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), pretrained_model_name)
43
+ if os.path.exists(archive_file) is False:
44
+ if pretrained_model_name in cls.pretrained_model_archive_map:
45
+ archive_file = cls.pretrained_model_archive_map[pretrained_model_name]
46
+ else:
47
+ archive_file = pretrained_model_name
48
+
49
+ # redirect to the cache, if necessary
50
+ try:
51
+ resolved_archive_file = cached_path(archive_file, cache_dir=cache_dir)
52
+ except FileNotFoundError:
53
+ if task_config is None or task_config.local_rank == 0:
54
+ logger.error(
55
+ "Model name '{}' was not found in model name list. "
56
+ "We assumed '{}' was a path or url but couldn't find any file "
57
+ "associated to this path or url.".format(
58
+ pretrained_model_name,
59
+ archive_file))
60
+ return None
61
+ if resolved_archive_file == archive_file:
62
+ if task_config is None or task_config.local_rank == 0:
63
+ logger.info("loading archive file {}".format(archive_file))
64
+ else:
65
+ if task_config is None or task_config.local_rank == 0:
66
+ logger.info("loading archive file {} from cache at {}".format(
67
+ archive_file, resolved_archive_file))
68
+ tempdir = None
69
+ if os.path.isdir(resolved_archive_file):
70
+ serialization_dir = resolved_archive_file
71
+ else:
72
+ # Extract archive to temp dir
73
+ tempdir = tempfile.mkdtemp()
74
+ if task_config is None or task_config.local_rank == 0:
75
+ logger.info("extracting archive file {} to temp dir {}".format(
76
+ resolved_archive_file, tempdir))
77
+ with tarfile.open(resolved_archive_file, 'r:gz') as archive:
78
+ archive.extractall(tempdir)
79
+ serialization_dir = tempdir
80
+ # Load config
81
+ config_file = os.path.join(serialization_dir, cls.config_name)
82
+ config = cls.from_json_file(config_file)
83
+ config.type_vocab_size = type_vocab_size
84
+ if task_config is None or task_config.local_rank == 0:
85
+ logger.info("Model config {}".format(config))
86
+
87
+ if state_dict is None:
88
+ weights_path = os.path.join(serialization_dir, cls.weights_name)
89
+ if os.path.exists(weights_path):
90
+ state_dict = torch.load(weights_path, map_location='cpu')
91
+ else:
92
+ if task_config is None or task_config.local_rank == 0:
93
+ logger.info("Weight doesn't exsits. {}".format(weights_path))
94
+
95
+ if tempdir:
96
+ # Clean up temp dir
97
+ shutil.rmtree(tempdir)
98
+
99
+ return config, state_dict
100
+
101
+ @classmethod
102
+ def from_dict(cls, json_object):
103
+ """Constructs a `BertConfig` from a Python dictionary of parameters."""
104
+ config = cls(vocab_size_or_config_json_file=-1)
105
+ for key, value in json_object.items():
106
+ config.__dict__[key] = value
107
+ return config
108
+
109
+ @classmethod
110
+ def from_json_file(cls, json_file):
111
+ """Constructs a `BertConfig` from a json file of parameters."""
112
+ with open(json_file, "r", encoding='utf-8') as reader:
113
+ text = reader.read()
114
+ return cls.from_dict(json.loads(text))
115
+
116
+ def __repr__(self):
117
+ return str(self.to_json_string())
118
+
119
+ def to_dict(self):
120
+ """Serializes this instance to a Python dictionary."""
121
+ output = copy.deepcopy(self.__dict__)
122
+ return output
123
+
124
+ def to_json_string(self):
125
+ """Serializes this instance to a JSON string."""
126
+ return json.dumps(self.to_dict(), indent=2, sort_keys=True) + "\n"
modules/until_module.py ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2018 The Google AI Language Team Authors and The HugginFace Inc. team.
3
+ # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ """PyTorch BERT model."""
17
+
18
+ import logging
19
+ import numpy as np
20
+ import torch
21
+ from torch import nn
22
+ import torch.nn.functional as F
23
+ import math
24
+ from modules.until_config import PretrainedConfig
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ def gelu(x):
30
+ """Implementation of the gelu activation function.
31
+ For information: OpenAI GPT's gelu is slightly different (and gives slightly different results):
32
+ 0.5 * x * (1 + torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3))))
33
+ """
34
+ return x * 0.5 * (1.0 + torch.erf(x / math.sqrt(2.0)))
35
+
36
+ def swish(x):
37
+ return x * torch.sigmoid(x)
38
+
39
+ def get_dual_matrix(sim_matrix):
40
+ if torch.is_tensor(sim_matrix):
41
+ pass
42
+ else:
43
+ sim_matrix = torch.tensor(sim_matrix)
44
+ temp = 1
45
+ # sim_matrix = sim_matrix * F.softmax(sim_matrix / temp, dim=0) * len(sim_matrix)
46
+ alpha = F.softmax(sim_matrix / temp, dim=0)
47
+ beta = F.softmax(sim_matrix / temp, dim=1)
48
+ sim_matrix = sim_matrix * alpha * beta
49
+ return sim_matrix
50
+
51
+
52
+ ACT2FN = {"gelu": gelu, "relu": torch.nn.functional.relu, "swish": swish}
53
+
54
+ class LayerNorm(nn.Module):
55
+ def __init__(self, hidden_size, eps=1e-12):
56
+ """Construct a layernorm module in the TF style (epsilon inside the square root).
57
+ """
58
+ super(LayerNorm, self).__init__()
59
+ self.weight = nn.Parameter(torch.ones(hidden_size))
60
+ self.bias = nn.Parameter(torch.zeros(hidden_size))
61
+ self.variance_epsilon = eps
62
+
63
+ def forward(self, x):
64
+ u = x.mean(-1, keepdim=True)
65
+ s = (x - u).pow(2).mean(-1, keepdim=True)
66
+ x = (x - u) / torch.sqrt(s + self.variance_epsilon)
67
+ return self.weight * x + self.bias
68
+
69
+ class PreTrainedModel(nn.Module):
70
+ """ An abstract class to handle weights initialization and
71
+ a simple interface for dowloading and loading pretrained models.
72
+ """
73
+ def __init__(self, config, *inputs, **kwargs):
74
+ super(PreTrainedModel, self).__init__()
75
+ if not isinstance(config, PretrainedConfig):
76
+ raise ValueError(
77
+ "Parameter config in `{}(config)` should be an instance of class `PretrainedConfig`. "
78
+ "To create a model from a Google pretrained model use "
79
+ "`model = {}.from_pretrained(PRETRAINED_MODEL_NAME)`".format(
80
+ self.__class__.__name__, self.__class__.__name__
81
+ ))
82
+ self.config = config
83
+
84
+ def init_weights(self, module):
85
+ """ Initialize the weights.
86
+ """
87
+ if isinstance(module, (nn.Linear, nn.Embedding)):
88
+ # Slightly different from the TF version which uses truncated_normal for initialization
89
+ # cf https://github.com/pytorch/pytorch/pull/5617
90
+ module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
91
+ elif isinstance(module, LayerNorm):
92
+ if 'beta' in dir(module) and 'gamma' in dir(module):
93
+ module.beta.data.zero_()
94
+ module.gamma.data.fill_(1.0)
95
+ else:
96
+ module.bias.data.zero_()
97
+ module.weight.data.fill_(1.0)
98
+ if isinstance(module, nn.Linear) and module.bias is not None:
99
+ module.bias.data.zero_()
100
+
101
+ def resize_token_embeddings(self, new_num_tokens=None):
102
+ raise NotImplementedError
103
+
104
+ @classmethod
105
+ def init_preweight(cls, model, state_dict, prefix=None, task_config=None):
106
+ old_keys = []
107
+ new_keys = []
108
+ for key in state_dict.keys():
109
+ new_key = None
110
+ if 'gamma' in key:
111
+ new_key = key.replace('gamma', 'weight')
112
+ if 'beta' in key:
113
+ new_key = key.replace('beta', 'bias')
114
+ if new_key:
115
+ old_keys.append(key)
116
+ new_keys.append(new_key)
117
+ for old_key, new_key in zip(old_keys, new_keys):
118
+ state_dict[new_key] = state_dict.pop(old_key)
119
+
120
+ if prefix is not None:
121
+ old_keys = []
122
+ new_keys = []
123
+ for key in state_dict.keys():
124
+ old_keys.append(key)
125
+ new_keys.append(prefix + key)
126
+ for old_key, new_key in zip(old_keys, new_keys):
127
+ state_dict[new_key] = state_dict.pop(old_key)
128
+
129
+ missing_keys = []
130
+ unexpected_keys = []
131
+ error_msgs = []
132
+ # copy state_dict so _load_from_state_dict can modify it
133
+ metadata = getattr(state_dict, '_metadata', None)
134
+ state_dict = state_dict.copy()
135
+ if metadata is not None:
136
+ state_dict._metadata = metadata
137
+
138
+ def load(module, prefix=''):
139
+ local_metadata = {} if metadata is None else metadata.get(prefix[:-1], {})
140
+ module._load_from_state_dict(
141
+ state_dict, prefix, local_metadata, True, missing_keys, unexpected_keys, error_msgs)
142
+ for name, child in module._modules.items():
143
+ if child is not None:
144
+ load(child, prefix + name + '.')
145
+
146
+ load(model, prefix='')
147
+
148
+ if prefix is None and (task_config is None or task_config.local_rank == 0):
149
+ logger.info("-" * 20)
150
+ if len(missing_keys) > 0:
151
+ logger.info("Weights of {} not initialized from pretrained model: {}"
152
+ .format(model.__class__.__name__, "\n " + "\n ".join(missing_keys)))
153
+ if len(unexpected_keys) > 0:
154
+ logger.info("Weights from pretrained model not used in {}: {}"
155
+ .format(model.__class__.__name__, "\n " + "\n ".join(unexpected_keys)))
156
+ if len(error_msgs) > 0:
157
+ logger.error("Weights from pretrained model cause errors in {}: {}"
158
+ .format(model.__class__.__name__, "\n " + "\n ".join(error_msgs)))
159
+
160
+ return model
161
+
162
+ @property
163
+ def dtype(self):
164
+ """
165
+ :obj:`torch.dtype`: The dtype of the module (assuming that all the module parameters have the same dtype).
166
+ """
167
+ try:
168
+ return next(self.parameters()).dtype
169
+ except StopIteration:
170
+ # For nn.DataParallel compatibility in PyTorch 1.5
171
+ def find_tensor_attributes(module: nn.Module):
172
+ tuples = [(k, v) for k, v in module.__dict__.items() if torch.is_tensor(v)]
173
+ return tuples
174
+
175
+ gen = self._named_members(get_members_fn=find_tensor_attributes)
176
+ first_tuple = next(gen)
177
+ return first_tuple[1].dtype
178
+
179
+ @classmethod
180
+ def from_pretrained(cls, config, state_dict=None, *inputs, **kwargs):
181
+ """
182
+ Instantiate a PreTrainedModel from a pre-trained model file or a pytorch state dict.
183
+ Download and cache the pre-trained model file if needed.
184
+ """
185
+ # Instantiate model.
186
+ model = cls(config, *inputs, **kwargs)
187
+ if state_dict is None:
188
+ return model
189
+ model = cls.init_preweight(model, state_dict)
190
+
191
+ return model
192
+
193
+ ##################################
194
+ ###### LOSS FUNCTION #############
195
+ ##################################
196
+ class CrossEn(nn.Module):
197
+ def __init__(self,):
198
+ super(CrossEn, self).__init__()
199
+
200
+ def forward(self, sim_matrix):
201
+ logpt = F.log_softmax(sim_matrix, dim=-1)
202
+ logpt = torch.diag(logpt)
203
+ nce_loss = -logpt
204
+ sim_loss = nce_loss.mean()
205
+ return sim_loss
206
+
207
+ class Dual_CrossEn(nn.Module):
208
+ def __init__(self,):
209
+ super(Dual_CrossEn, self).__init__()
210
+
211
+ def forward(self, sim_matrix):
212
+ sim_matrix = get_dual_matrix(sim_matrix)
213
+ logpt = F.log_softmax(sim_matrix, dim=-1)
214
+ logpt = torch.diag(logpt)
215
+ nce_loss = -logpt
216
+ sim_loss = nce_loss.mean()
217
+ return sim_loss
218
+
219
+ class MILNCELoss(nn.Module):
220
+ def __init__(self, batch_size=1, n_pair=1,):
221
+ super(MILNCELoss, self).__init__()
222
+ self.batch_size = batch_size
223
+ self.n_pair = n_pair
224
+ torch_v = float(".".join(torch.__version__.split(".")[:2]))
225
+ self.bool_dtype = torch.bool if torch_v >= 1.3 else torch.uint8
226
+
227
+ def forward(self, sim_matrix):
228
+ mm_mask = np.eye(self.batch_size)
229
+ mm_mask = np.kron(mm_mask, np.ones((self.n_pair, self.n_pair)))
230
+ mm_mask = torch.tensor(mm_mask).float().to(sim_matrix.device)
231
+
232
+ from_text_matrix = sim_matrix + mm_mask * -1e12
233
+ from_video_matrix = sim_matrix.transpose(1, 0)
234
+
235
+ new_sim_matrix = torch.cat([from_video_matrix, from_text_matrix], dim=-1)
236
+ logpt = F.log_softmax(new_sim_matrix, dim=-1)
237
+
238
+ mm_mask_logpt = torch.cat([mm_mask, torch.zeros_like(mm_mask)], dim=-1)
239
+ masked_logpt = logpt + (torch.ones_like(mm_mask_logpt) - mm_mask_logpt) * -1e12
240
+
241
+ new_logpt = -torch.logsumexp(masked_logpt, dim=-1)
242
+
243
+ logpt_choice = torch.zeros_like(new_logpt)
244
+ mark_ind = torch.arange(self.batch_size).to(sim_matrix.device) * self.n_pair + (self.n_pair//2)
245
+ logpt_choice[mark_ind] = 1
246
+ sim_loss = new_logpt.masked_select(logpt_choice.to(dtype=self.bool_dtype)).mean()
247
+ return sim_loss
248
+
249
+ class MaxMarginRankingLoss(nn.Module):
250
+ def __init__(self,
251
+ margin=1.0,
252
+ negative_weighting=False,
253
+ batch_size=1,
254
+ n_pair=1,
255
+ hard_negative_rate=0.5,
256
+ ):
257
+ super(MaxMarginRankingLoss, self).__init__()
258
+ self.margin = margin
259
+ self.n_pair = n_pair
260
+ self.batch_size = batch_size
261
+ easy_negative_rate = 1 - hard_negative_rate
262
+ self.easy_negative_rate = easy_negative_rate
263
+ self.negative_weighting = negative_weighting
264
+ if n_pair > 1 and batch_size > 1:
265
+ alpha = easy_negative_rate / ((batch_size - 1) * (1 - easy_negative_rate))
266
+ mm_mask = (1 - alpha) * np.eye(self.batch_size) + alpha
267
+ mm_mask = np.kron(mm_mask, np.ones((n_pair, n_pair)))
268
+ mm_mask = torch.tensor(mm_mask) * (batch_size * (1 - easy_negative_rate))
269
+ self.mm_mask = mm_mask.float()
270
+
271
+ def forward(self, x):
272
+ d = torch.diag(x)
273
+ max_margin = F.relu(self.margin + x - d.view(-1, 1)) + \
274
+ F.relu(self.margin + x - d.view(1, -1))
275
+ if self.negative_weighting and self.n_pair > 1 and self.batch_size > 1:
276
+ max_margin = max_margin * self.mm_mask.to(max_margin.device)
277
+ return max_margin.mean()
278
+
279
+ class AllGather(torch.autograd.Function):
280
+ """An autograd function that performs allgather on a tensor."""
281
+
282
+ @staticmethod
283
+ def forward(ctx, tensor, args):
284
+ output = [torch.empty_like(tensor) for _ in range(args.world_size)]
285
+ torch.distributed.all_gather(output, tensor)
286
+ ctx.rank = args.rank
287
+ ctx.batch_size = tensor.shape[0]
288
+ return torch.cat(output, dim=0)
289
+
290
+ @staticmethod
291
+ def backward(ctx, grad_output):
292
+ return (
293
+ grad_output[ctx.batch_size * ctx.rank : ctx.batch_size * (ctx.rank + 1)],
294
+ None,
295
+ )
search.py ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ # import gradio
3
+ import torch
4
+ from transformers import BertTokenizer
5
+ import argparse
6
+ import gradio as gr
7
+ import time
8
+
9
+ from modules.tokenization_clip import SimpleTokenizer as ClipTokenizer
10
+ from modules.modeling import BirdModel
11
+
12
+ show_num = 10
13
+ max_words = 32
14
+ video_path_zh = "features/Chinese_batch_visual_output_list.npy"
15
+ frame_path_zh = "features/Chinese_batch_frame_output_list.npy"
16
+ video_fea_zh = np.load(video_path_zh)
17
+ video_fea_zh = torch.from_numpy(video_fea_zh)
18
+ frame_fea_zh = np.load(frame_path_zh)
19
+ frame_fea_zh = torch.from_numpy(frame_fea_zh)
20
+
21
+ video_path_en = "features/English_batch_visual_output_list.npy"
22
+ frame_path_en = "features/English_batch_frame_output_list.npy"
23
+ video_fea_en = np.load(video_path_en)
24
+ video_fea_en = torch.from_numpy(video_fea_en)
25
+ frame_fea_en = np.load(frame_path_en)
26
+ frame_fea_en = torch.from_numpy(frame_fea_en)
27
+
28
+ test_path = "test_list.txt"
29
+ # video_dir = "test1500_400_400/"
30
+ video_dir = "test1500/"
31
+
32
+ with open(test_path, 'r', encoding='utf8') as f_list:
33
+ lines = f_list.readlines()
34
+ video_ids = [itm.strip() + ".mp4" for itm in lines]
35
+
36
+
37
+ def get_videoname(idx):
38
+ videoname = []
39
+ videopath = []
40
+ for i in idx:
41
+ videoname.append(video_ids[i])
42
+ path = video_dir + video_ids[i]
43
+ videopath.append(path)
44
+ return videoname, videopath
45
+
46
+
47
+ def get_text(caption, tokenizer):
48
+ # tokenize word
49
+ words = tokenizer.tokenize(caption)
50
+
51
+ # add cls token
52
+ words = ["<|startoftext|>"] + words
53
+ total_length_with_CLS = max_words - 1
54
+ if len(words) > total_length_with_CLS:
55
+ words = words[:total_length_with_CLS]
56
+
57
+ # add end token
58
+ words = words + ["<|endoftext|>"]
59
+
60
+ # convert token to id according to the vocab
61
+ input_ids = tokenizer.convert_tokens_to_ids(words)
62
+
63
+ # add zeros for feature of the same length
64
+ input_mask = [1] * len(input_ids)
65
+ while len(input_ids) < max_words:
66
+ input_ids.append(0)
67
+ input_mask.append(0)
68
+
69
+ # ensure the length of feature to be equal with max words
70
+ assert len(input_ids) == max_words
71
+ assert len(input_mask) == max_words
72
+ pairs_text = np.array(input_ids).reshape(-1, max_words)
73
+ pairs_text = torch.from_numpy(pairs_text)
74
+ pairs_mask = np.array(input_mask).reshape(-1, max_words)
75
+ pairs_mask = torch.from_numpy(pairs_mask)
76
+
77
+ return pairs_text, pairs_mask
78
+
79
+
80
+ def get_args(description='Retrieval Task'):
81
+ parser = argparse.ArgumentParser(description=description)
82
+ parser.add_argument("--do_pretrain", action='store_true', help="Whether to run training.")
83
+ parser.add_argument("--do_train", action='store_true', help="Whether to run training.")
84
+ parser.add_argument("--do_eval", action='store_true', help="Whether to run eval on the dev set.")
85
+ parser.add_argument("--do_params", action='store_true', help="text the params of the model.")
86
+ parser.add_argument("--use_frame_fea", action='store_true', help="whether use frame feature matching text")
87
+ parser.add_argument('--task', type=str, default="retrieval", choices=["retrieval_VT", "retrieval"],
88
+ help="choose downstream task.")
89
+ parser.add_argument('--dataset', type=str, default="bird", choices=["bird", "msrvtt", "vatex", "msvd"],
90
+ help="choose dataset.")
91
+ parser.add_argument('--num_thread_reader', type=int, default=1, help='')
92
+ parser.add_argument('--lr', type=float, default=0.0001, help='initial learning rate')
93
+ parser.add_argument('--text_lr', type=float, default=0.00001, help='text encoder learning rate')
94
+ parser.add_argument('--epochs', type=int, default=20, help='upper epoch limit')
95
+ parser.add_argument('--batch_size', type=int, default=256, help='batch size')
96
+ parser.add_argument('--batch_size_val', type=int, default=3500, help='batch size eval')
97
+ parser.add_argument('--lr_decay', type=float, default=0.9, help='Learning rate exp epoch decay')
98
+ parser.add_argument('--weight_decay', type=float, default=0.2, help='Learning rate exp epoch decay')
99
+ parser.add_argument('--n_display', type=int, default=100, help='Information display frequence')
100
+ parser.add_argument('--seed', type=int, default=42, help='random seed')
101
+ parser.add_argument('--max_words', type=int, default=32, help='')
102
+ parser.add_argument('--max_frames', type=int, default=12, help='')
103
+ parser.add_argument('--top_frames', type=int, default=3, help='')
104
+ parser.add_argument('--frame_sample', type=str, default="uniform", choices=["uniform", "random", "uniform_random"],
105
+ help='frame sample strategy')
106
+ parser.add_argument('--frame_sample_len', type=str, default="fix", choices=["dynamic", "fix"],
107
+ help='use dynamic frame length of fix frame length')
108
+ parser.add_argument('--language', type=str, default="chinese", choices=["chinese", "english"],
109
+ help='language for text encoder')
110
+ parser.add_argument('--use_temp', action='store_true', help='whether to use temporal transformer')
111
+
112
+ parser.add_argument("--logdir", default=None, type=str, required=False, help="log dir for tensorboardX writer")
113
+ parser.add_argument("--cross_model", default="cross-base", type=str, required=False, help="Cross module")
114
+ parser.add_argument("--pretrained_text", default="hfl/chinese-roberta-wwm-ext", type=str, required=False, help="pretrained_text")
115
+ parser.add_argument("--init_model", default=None, type=str, required=False, help="Initial model.")
116
+ parser.add_argument("--warmup_proportion", default=0.1, type=float,
117
+ help="Proportion of training to perform linear learning rate warmup for. E.g., 0.1 = 10%% of training.")
118
+ parser.add_argument('--gradient_accumulation_steps', type=int, default=1,
119
+ help="Number of updates steps to accumulate before performing a backward/update pass.")
120
+ parser.add_argument('--n_gpu', type=int, default=1, help="Changed in the execute process.")
121
+
122
+ parser.add_argument("--cache_dir", default="", type=str,
123
+ help="Where do you want to store the pre-trained models downloaded from s3")
124
+
125
+ parser.add_argument('--enable_amp', action='store_true', help="whether to use pytorch amp")
126
+
127
+ parser.add_argument("--world_size", default=0, type=int, help="distribted training")
128
+ parser.add_argument("--local_rank", default=0, type=int, help="distribted training")
129
+ parser.add_argument("--rank", default=0, type=int, help="distribted training")
130
+ parser.add_argument('--coef_lr', type=float, default=1., help='coefficient for bert branch.')
131
+
132
+ args = parser.parse_args()
133
+
134
+ # Check paramenters
135
+ args.do_eval = True
136
+ args.use_frame_fea = True
137
+ args.use_temp = True
138
+
139
+ return args
140
+
141
+
142
+ def init_model(language):
143
+ time1 = time.time()
144
+ args = get_args()
145
+ args.language = language
146
+ if language == "chinese":
147
+ model_path = "models/Chinese_vatex.bin"
148
+ tokenizer = BertTokenizer.from_pretrained("hfl/chinese-roberta-wwm-ext")
149
+ elif language == "english":
150
+ model_path = "models/English_vatex.bin"
151
+ tokenizer = ClipTokenizer()
152
+ else:
153
+ raise Exception("language should be Chinese or English!")
154
+ model_state_dict = torch.load(model_path, map_location='cpu')
155
+ cross_model = "cross-base"
156
+ model = BirdModel.from_pretrained(cross_model, state_dict=model_state_dict, task_config=args)
157
+ device = torch.device("cpu")
158
+ # device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
159
+ model.to(device)
160
+ model.eval()
161
+ print("language={}".format(language))
162
+ print("init model time: {}".format(time.time() - time1))
163
+ print("device:{}".format(device))
164
+ return model, tokenizer
165
+
166
+
167
+ model_zh, tokenizer_zh = init_model(language="chinese")
168
+ model_en, tokenizer_en = init_model(language="english")
169
+
170
+
171
+ def t2v_search_zh(text):
172
+ with torch.no_grad():
173
+ time1 = time.time()
174
+ text_ids, text_mask = get_text(text, tokenizer_zh)
175
+ print("get_text time: {}".format(time.time() - time1))
176
+ time1 = time.time()
177
+ text_fea_zh = model_zh.text_encoder(text_ids, text_mask)
178
+ print("text_encoder time: {}".format(time.time() - time1))
179
+ # print("text_fea.shape:{}".format(text_fea.shape))
180
+ # print("video_fea.shape:{}".format(video_fea.shape))
181
+ # print("frame_fea.shape:{}".format(frame_fea.shape))
182
+ time1 = time.time()
183
+ sim_video = model_zh.loose_similarity(text_fea_zh, video_fea_zh)
184
+ # print("sim_video.shape:{}".format(sim_video.shape))
185
+ sim_frame = model_zh.loose_similarity(text_fea_zh, frame_fea_zh)
186
+ # print("sim_frame.shape:{}".format(sim_frame.shape))
187
+ sim_frame = torch.topk(sim_frame, k=model_zh.top_frames, dim=1)[0]
188
+ sim_frame = torch.mean(sim_frame, dim=1)
189
+ sim = sim_video + sim_frame
190
+ value, index = sim.topk(show_num, dim=0, largest=True, sorted=True)
191
+ # value, index = sim_video.topk(show_num, dim=0, largest=True, sorted=True)
192
+ print("calculate_similarity time: {}".format(time.time() - time1))
193
+ print("value:{}".format(value))
194
+ print("index:{}".format(index))
195
+ videoname, videopath = get_videoname(index)
196
+ print("videoname:{}".format(videoname))
197
+ print("videopath:{}".format(videopath))
198
+ return videopath
199
+
200
+
201
+ def t2v_search_en(text):
202
+ with torch.no_grad():
203
+ time1 = time.time()
204
+ text_ids, text_mask = get_text(text, tokenizer_en)
205
+ print("get_text time: {}".format(time.time() - time1))
206
+ time1 = time.time()
207
+ text_fea_en = model_en.text_encoder(text_ids, text_mask)
208
+ print("text_encoder time: {}".format(time.time() - time1))
209
+ # print("text_fea.shape:{}".format(text_fea.shape))
210
+ # print("video_fea.shape:{}".format(video_fea.shape))
211
+ # print("frame_fea.shape:{}".format(frame_fea.shape))
212
+ time1 = time.time()
213
+ sim_video = model_en.loose_similarity(text_fea_en, video_fea_en)
214
+ # print("sim_video.shape:{}".format(sim_video.shape))
215
+ sim_frame = model_en.loose_similarity(text_fea_en, frame_fea_en)
216
+ # print("sim_frame.shape:{}".format(sim_frame.shape))
217
+ sim_frame = torch.topk(sim_frame, k=model_en.top_frames, dim=1)[0]
218
+ sim_frame = torch.mean(sim_frame, dim=1)
219
+ sim = sim_video + sim_frame
220
+ value, index = sim.topk(show_num, dim=0, largest=True, sorted=True)
221
+ # value, index = sim_video.topk(show_num, dim=0, largest=True, sorted=True)
222
+ print("calculate_similarity time: {}".format(time.time() - time1))
223
+ print("value:{}".format(value))
224
+ print("index:{}".format(index))
225
+ videoname, videopath = get_videoname(index)
226
+ print("videoname:{}".format(videoname))
227
+ print("videopath:{}".format(videopath))
228
+ return videopath
229
+
230
+
231
+ def hello_world(name):
232
+ return "hello world, my name is " + name + "!"
233
+
234
+
235
+ def search_demo():
236
+ with gr.Blocks() as demo:
237
+ gr.Markdown("# <center>HMMC中英文本-视频检索</center>")
238
+ demo.title = "HMMC中英文本-视频检索"
239
+ with gr.Tab("中文"):
240
+ with gr.Column(variant="panel"):
241
+ with gr.Row(variant="compact"):
242
+ input_text = gr.Textbox(
243
+ label="输入文本",
244
+ show_label=False,
245
+ max_lines=1,
246
+ placeholder="请输入检索文本...",
247
+ ).style(
248
+ container=False,
249
+ )
250
+ btn = gr.Button("搜索").style(full_width=False)
251
+
252
+ with gr.Column(variant="panel", scale=2):
253
+ with gr.Row(variant="compact"):
254
+ videos_top = [gr.Video(
255
+ format="mp4", label="视频 "+str(i+1),
256
+ ).style(height=300, width=300) for i in range(3)]
257
+ with gr.Column(variant="panel", scale=1):
258
+ with gr.Row(variant="compact"):
259
+ videos_rest = [gr.Video(
260
+ format="mp4", label="视频 "+str(i),
261
+ ).style(height=150, width=150) for i in range(3, show_num)]
262
+
263
+ searched_videos = videos_top + videos_rest
264
+ btn.click(t2v_search_zh, inputs=input_text, outputs=searched_videos)
265
+
266
+ with gr.Tab("English"):
267
+ with gr.Column(variant="panel"):
268
+ with gr.Row(variant="compact"):
269
+ input_text = gr.Textbox(
270
+ label="input text",
271
+ show_label=False,
272
+ max_lines=1,
273
+ placeholder="Please input text to search...",
274
+ ).style(
275
+ container=False,
276
+ )
277
+ btn = gr.Button("Search").style(full_width=False)
278
+
279
+ with gr.Column(variant="panel", scale=2):
280
+ with gr.Row(variant="compact"):
281
+ videos_top = [gr.Video(
282
+ format="mp4", label="video " + str(i+1),
283
+ ).style(height=300, width=300) for i in range(3)]
284
+ with gr.Column(variant="panel", scale=1):
285
+ with gr.Row(variant="compact"):
286
+ videos_rest = [gr.Video(
287
+ format="mp4", label="video " + str(i),
288
+ ).style(height=150, width=150) for i in range(3, show_num)]
289
+
290
+ searched_videos = videos_top + videos_rest
291
+ btn.click(t2v_search_en, inputs=input_text, outputs=searched_videos)
292
+
293
+ demo.launch(share=True)
294
+
295
+
296
+ if __name__ == '__main__':
297
+ search_demo()
298
+ # text = "两个男人正在随着音乐跳舞,他们正在努力做着macarena舞蹈的动作。"
299
+ # t2v_search(text)
test_list.txt ADDED
@@ -0,0 +1,1500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ sf2PPeXQrUA_000000_000010
2
+ rIJPGdtdaHg_000006_000016
3
+ 6FjgdUricEs_000022_000032
4
+ -PCVHF3Kp3M_000169_000179
5
+ cb3RvnukQVs_000159_000169
6
+ RbpDta9EICM_000082_000092
7
+ QDUZ4L9gpP8_000317_000327
8
+ 5BNZDNxZfX0_000004_000014
9
+ B8uJabL49FI_000074_000084
10
+ nAD5PuUHVDM_000027_000037
11
+ YLqQSpRH09o_000002_000012
12
+ CKUaeC_FWoA_000019_000029
13
+ 2E6ZLAK593E_000002_000012
14
+ CiTHS0W9vkg_000047_000057
15
+ OxiWoQOzZaM_000376_000386
16
+ qbTYNlpD5nM_000078_000088
17
+ sSX1KaKyrag_000007_000017
18
+ BFYBAg9fSL4_000388_000398
19
+ 2zqplqQwlL8_000447_000457
20
+ 1y_uKjQmjWg_000020_000030
21
+ dinFGaxi9Rc_000023_000033
22
+ 5F4jp64eh1w_000000_000010
23
+ ihOTHLgvm8s_000031_000041
24
+ 7zzNK8TtWls_000003_000013
25
+ u4sITQgf03I_000009_000019
26
+ sEw4ZBSbTzQ_000000_000010
27
+ MrzLrekK1Cc_000000_000010
28
+ yIus7dY2BKU_000094_000104
29
+ QVygizGIC3M_000004_000014
30
+ DLxAkF7lYHE_000184_000194
31
+ aL6zh0oCzZE_000039_000049
32
+ 0B7puDmojro_000061_000071
33
+ i7SAVqA-3Bk_000032_000042
34
+ 3IuP3YYwzzA_000000_000010
35
+ Vli3ay79kJk_000000_000010
36
+ OnIqmqa9mqc_001907_001917
37
+ sFrRHqQ9AIw_000022_000032
38
+ NnHX9Auke60_000022_000032
39
+ ln9NeisDnFU_000116_000126
40
+ P2abrZ-cbqk_000000_000010
41
+ 9gCXYhcc8K0_000104_000114
42
+ v1onbz5rSDo_000000_000010
43
+ YG8JiyFKQ9M_000094_000104
44
+ khURP8O3k_k_000241_000251
45
+ Eks62nEKfH8_000066_000076
46
+ nxDAt9SkPoA_000123_000133
47
+ IrbMK1MKgQA_000006_000016
48
+ iq4ysEnDQBc_000071_000081
49
+ c_72NRiKphQ_000178_000188
50
+ 2bCUoQLw7OE_000000_000010
51
+ uGBeU98HV0Y_000156_000166
52
+ tSQqcJqGplA_000011_000021
53
+ Hnex85IkEPg_000000_000010
54
+ ca0muRN-gjM_000007_000017
55
+ JwDePTiGRcY_000029_000039
56
+ q-QOU4kjUCQ_000001_000011
57
+ OfDDeDByNKE_000489_000499
58
+ uh50grtCQSA_000026_000036
59
+ amvcZogOvvI_000007_000017
60
+ jiKZmCswPeE_000001_000011
61
+ XBlVVyhfQ2Y_000052_000062
62
+ rbaoOjMKbio_000019_000029
63
+ aqRD8TK9K1w_000005_000015
64
+ JpLrWNjyaQU_000027_000037
65
+ s6bOJtUE0FU_000007_000017
66
+ bpw7kP8IEJU_000008_000018
67
+ wG1wBA9lyJE_000004_000014
68
+ 0gZqPa1qo4s_000013_000023
69
+ WONC-tU62RA_000009_000019
70
+ pzf5Gqy1JxQ_000162_000172
71
+ Rs9T2YtS46Q_000100_000110
72
+ 3exdpRbcMmA_000034_000044
73
+ pNvKrzbJEhg_000010_000020
74
+ ErRHPNJo9f4_000003_000013
75
+ gbYcrYeqCHM_000250_000260
76
+ YIkysT5HGrM_000235_000245
77
+ WEtK-Ndd9XE_000140_000150
78
+ Ca7inKrelzI_000064_000074
79
+ Lvg6fb0DXSY_000035_000045
80
+ 2BNkQFQGaNI_000572_000582
81
+ -Tc2NGLTTD0_000121_000131
82
+ GzlcYW2YF8o_000011_000021
83
+ WeL8Ie7hCTo_000003_000013
84
+ X4052giOzGA_000017_000027
85
+ 8wID3JI7m78_000744_000754
86
+ OCLMRUbRb6Q_000109_000119
87
+ d5FWcjUn1xU_000064_000074
88
+ Eicloge6jFM_000012_000022
89
+ fq0kIJhthbA_000076_000086
90
+ Ai0RaLVZW_g_000004_000014
91
+ XqkIJrR1loM_000013_000023
92
+ Ie1GRyaFpQc_000045_000055
93
+ bmbtEThyum0_000000_000010
94
+ hm9NCa_E3ig_000243_000253
95
+ Pg4VtQT5dAk_000004_000014
96
+ nc1ptYDp3zI_000033_000043
97
+ GNUDkrXspaQ_000069_000079
98
+ DOa84IoN8N8_000014_000024
99
+ K420tiUw2q8_000000_000010
100
+ 2m8H3ViIs0U_000000_000010
101
+ CZ1oWiDS_5c_000000_000010
102
+ PCicM6i59_I_000118_000128
103
+ HCs5Vj6Zy0I_000004_000014
104
+ m5D-kLzwNkg_000027_000037
105
+ k6icUmA7cM4_000071_000081
106
+ zcqnH8LO1Dg_000016_000026
107
+ 67Izc6v8_zc_000010_000020
108
+ TdC_JQ8SfVg_000004_000014
109
+ Ag9mJ4tEIEE_000273_000283
110
+ Z5ywBikWPqU_000045_000055
111
+ jMo78oeASw0_000002_000012
112
+ 45HnjQIVvT4_000009_000019
113
+ yDa27vSKGYY_000036_000046
114
+ 3AsOzMAM91E_000004_000014
115
+ 4Bdkmj2hFm8_000034_000044
116
+ 2kM2NrMhnis_000156_000166
117
+ KqDAM8_S0DU_000048_000058
118
+ 2VRuFjC8HDM_000004_000014
119
+ sldlahvl3Tc_000008_000018
120
+ 4N-OoJZD_Qg_000102_000112
121
+ Rzz2jV9q9gU_000013_000023
122
+ VFp8GkLwi50_000095_000105
123
+ nPIdoH_CJYE_000126_000136
124
+ lV4r_8tHGAY_000034_000044
125
+ DeRCbSPU8NM_000085_000095
126
+ duhAEqT-Ttw_000017_000027
127
+ -b6gqj_mZOs_000009_000019
128
+ anzQwjeBbYs_000009_000019
129
+ RGNxTr2vZ8o_000170_000180
130
+ R7PXIX_YWJg_000131_000141
131
+ nQJAlymtQt0_000034_000044
132
+ FHxv5n5CrsA_000000_000010
133
+ kGWKUPfsBuY_000088_000098
134
+ QfNv-NxsWfc_000062_000072
135
+ isW9E-Zp90A_000002_000012
136
+ zlgbDWzA5-w_000122_000132
137
+ Qxx2JJE9Ev4_000000_000010
138
+ kDNG-8C2Jrs_000000_000010
139
+ -_axH6kxbic_000003_000013
140
+ 1Jz8JZFuVLk_000014_000024
141
+ tIcwx3MH_kw_000017_000027
142
+ Zjr3hHz4Q2M_000150_000160
143
+ p7r-ajQtBZs_000031_000041
144
+ jGH_eRWyGVQ_000004_000014
145
+ OSfIV2aQd_I_000014_000024
146
+ 6yHTZHY8_3Y_000026_000036
147
+ cfBtVPEwqIo_000005_000015
148
+ ZnKbREYJ1C0_000002_000012
149
+ Z03ZQ_h59Pk_000015_000025
150
+ cBuoOA5jIRI_000039_000049
151
+ ecNLf37mews_000012_000022
152
+ sy9T57J6qEg_000002_000012
153
+ clZ-eZWW-HE_000105_000115
154
+ yujJLRHVm-A_000005_000015
155
+ 58QjPoalXlg_000002_000012
156
+ FnbrvKMwJFc_000025_000035
157
+ fE0yN1CBMvA_000160_000170
158
+ H1rf96-Jm0o_000023_000033
159
+ Be3L2e7HN54_000336_000346
160
+ mAV6Pn-3a5U_000006_000016
161
+ epfCEGpA8OY_000000_000010
162
+ 9JonoONyXN0_000025_000035
163
+ mj4JGloJS4o_000031_000041
164
+ thn033gNKOA_000021_000031
165
+ 2fx306CeqEI_000025_000035
166
+ G88xmYArd8o_000001_000011
167
+ sovJ_-BsO6s_000018_000028
168
+ 9G1LGoB-8as_000001_000011
169
+ QFmHnhLqf6c_000006_000016
170
+ WY9TXZ2ODgw_000150_000160
171
+ 6oywr9jgp1M_000084_000094
172
+ vj7eeYGfozs_000112_000122
173
+ 36JI7dIZSRw_000071_000081
174
+ R4l6hWmfKqM_000006_000016
175
+ 9Zn5zr7J7qs_000041_000051
176
+ 5EheWAKuZnY_000003_000013
177
+ TYTWS2PZLQg_000032_000042
178
+ j-v9WpQtvT4_000001_000011
179
+ 891pot4xKPk_000191_000201
180
+ PQSZLVqO7rU_000110_000120
181
+ q_zCR9ITIrE_000006_000016
182
+ QLNszf39dbM_000253_000263
183
+ _UoN-y6SzjI_000004_000014
184
+ AUJdvbM0dLo_000058_000068
185
+ YTdjyKCu53M_000032_000042
186
+ oX90Q352-D0_000019_000029
187
+ 7qVkwNb0dtM_000002_000012
188
+ l17LtEO6z3o_000033_000043
189
+ 5RIe5niLskU_000004_000014
190
+ E8EhsfkqT0c_000092_000102
191
+ 9bx30W8aOKM_000001_000011
192
+ CVmh-a1APJc_000006_000016
193
+ a_1mjN2I7RI_001337_001347
194
+ BlHNGhui6LA_000021_000031
195
+ fl56tjPytbY_000094_000104
196
+ Y_dxesnBzg0_000020_000030
197
+ 7COkxV_YfOU_000000_000010
198
+ b9TfeDnfemw_000047_000057
199
+ D1-cCXclgZo_000010_000020
200
+ Ya7JaHCbtQw_000065_000075
201
+ S7NEpkqr0Xc_000027_000037
202
+ 3D3IWV72ZGI_000041_000051
203
+ M2DXKEp_u9U_000023_000033
204
+ bHdGTlzuwRQ_000002_000012
205
+ ArN3eVUygAg_000058_000068
206
+ vbQ2x8_9giw_000095_000105
207
+ p107RA-3woA_000137_000147
208
+ 35_IiB3_nVw_000017_000027
209
+ ShgajdY_h9I_000000_000010
210
+ 8LHvdxSF9Ek_000004_000014
211
+ dQOTyHhTLbY_000066_000076
212
+ DIMBtwbtnYQ_000182_000192
213
+ F6ZLuarySKo_000136_000146
214
+ VxDOiYNIfnA_000041_000051
215
+ V3Wp5siliwc_000090_000100
216
+ NRC5oMoNHn0_000003_000013
217
+ _lDzLPASjfg_000007_000017
218
+ hB2DZcypK0Y_000187_000197
219
+ iNdJfXbW4UY_000326_000336
220
+ LJbIxxpTctA_000350_000360
221
+ CweM_4o1JOM_000004_000014
222
+ WMAR-K-68jI_000005_000015
223
+ i3ZGzZ65rvg_000008_000018
224
+ SUhKIoo8Y7U_000011_000021
225
+ AhMpS-dz2pc_000002_000012
226
+ CdpUfCli4ys_000049_000059
227
+ m6RF5r3I8dA_000033_000043
228
+ vhls-0FOAqE_000042_000052
229
+ OF-OZUe4GJc_000018_000028
230
+ DhnHzooyFo4_000042_000052
231
+ 5D4HjS92zSQ_000126_000136
232
+ vgia9zM-Tao_000033_000043
233
+ SwdKVfwtSQw_000000_000010
234
+ v5UfN6dUVcs_000019_000029
235
+ tDmfTtpDF6Q_000333_000343
236
+ 3nTMc2nK_W8_000000_000010
237
+ JPFdgQvqwjI_000328_000338
238
+ qwLeYfEOrnU_000000_000010
239
+ VHFuW1yFqXY_000120_000130
240
+ h6_FiX5vO_U_000009_000019
241
+ kh6KufiQW5A_000097_000107
242
+ c25IqRBGKlA_000004_000014
243
+ Ip0yJAkp7Pw_000119_000129
244
+ t-YDm1WRdEY_000143_000153
245
+ hZ34EcXYuIU_000002_000012
246
+ WFG38qMr2Fk_000021_000031
247
+ nTK7fjMfbSA_000002_000012
248
+ GCtPDRrBBc0_000000_000010
249
+ nmefMgzgISw_000020_000030
250
+ 0GWr1EV6ZuY_000106_000116
251
+ syI2EiICWOM_000001_000011
252
+ EGQxtiReVnE_000014_000024
253
+ tsnbD70rddU_000024_000034
254
+ IZmQ1ndVmyc_000004_000014
255
+ fzuw0Wp6dF8_000003_000013
256
+ 5AJUbDC0YwY_000102_000112
257
+ YMvyLtafd6Q_000115_000125
258
+ L9xSjSgDamc_000000_000010
259
+ mwKmET7GFNU_000022_000032
260
+ b1qE4GNZ9OA_000144_000154
261
+ QTOaEVeoCRE_000177_000187
262
+ AtmUxjr6ZFI_000004_000014
263
+ uoOEgOBo7Uw_000123_000133
264
+ jbyVJdDlo2Q_000059_000069
265
+ P4LS1ilfloQ_000000_000010
266
+ OtyiGXrVnZc_000157_000167
267
+ aC5txX6gJLI_000003_000013
268
+ 2v3otYP4bZc_000196_000206
269
+ ady69p6ykqE_000001_000011
270
+ 7YJZ6Q2ZMFU_000060_000070
271
+ _G9ka7ghM1c_000049_000059
272
+ FTxa5j8T03k_000009_000019
273
+ y1we1RI5qmg_000000_000010
274
+ 1nihsi5qNJA_000074_000084
275
+ n7wyjDPtFtg_000003_000013
276
+ At8LPKnA9Zg_000134_000144
277
+ 5eh2MbjEyXs_000003_000013
278
+ ueNk8_69WOE_000002_000012
279
+ NfAvGwYhhSw_000025_000035
280
+ vGRkF47_b-8_000164_000174
281
+ GqnNJywvDy4_000053_000063
282
+ JGluzZgbe2E_000048_000058
283
+ 0nQBmFswEOw_000062_000072
284
+ h6Hf1d7hJ8M_000010_000020
285
+ A0yyN0Z68-A_000053_000063
286
+ aMTce4pTh00_000047_000057
287
+ FcbL8yPAzZo_000155_000165
288
+ VNUjTJNGUa8_000029_000039
289
+ WsEfaI-2azs_000024_000034
290
+ iUANfGZ5dCY_000014_000024
291
+ IHcaQ-P7ytg_000048_000058
292
+ U5wQ8PwwXFg_000009_000019
293
+ VHKS2AZEgro_000139_000149
294
+ cU1qVk7HXfE_000304_000314
295
+ Dqg_m36iVuM_000081_000091
296
+ QkG03wZh7ew_000034_000044
297
+ lwCnqd0E4HI_000003_000013
298
+ eHtYCCJwKbs_000003_000013
299
+ AcWGNfJnBOE_000375_000385
300
+ WEQbqLqRvOY_000021_000031
301
+ nrF8FOuvACg_000127_000137
302
+ 8oDKuNb4olE_000042_000052
303
+ AxQPpRGxm-Q_000054_000064
304
+ QgzJW2EWJK8_000002_000012
305
+ _6LbEATZ-jM_000045_000055
306
+ JfIz0f8WCNM_000010_000020
307
+ sqOojwuFaFU_000002_000012
308
+ RFX6UWeTTtU_000007_000017
309
+ F29GqCDFic8_000711_000721
310
+ aw55asaJJ34_000010_000020
311
+ cHycKylBtlY_000022_000032
312
+ Q8FlLIyZF50_000004_000014
313
+ fcWWf5cAnWQ_000023_000033
314
+ GqCUEAigBWw_000012_000022
315
+ VKFX8D6bwo4_000001_000011
316
+ NjMJsEHTnOE_000048_000058
317
+ mHDdn4z-cjI_000076_000086
318
+ gf37sAjEfRc_000013_000023
319
+ nPKOfBLkLpw_000461_000471
320
+ L3lh_TzunmI_000003_000013
321
+ 5alRoEFZJCs_000002_000012
322
+ nT6bAb_4HgY_000003_000013
323
+ gmPNqbpI04w_000044_000054
324
+ _WPR0Auk7ZM_000024_000034
325
+ t61eKij6cNo_000019_000029
326
+ kRdxCmOsY2Y_000003_000013
327
+ 2axIb7lejhw_000167_000177
328
+ KKm1bM51CZs_000070_000080
329
+ iwIttka43nE_000037_000047
330
+ BWxQXzXynhQ_000387_000397
331
+ eTUGCFPG9N4_000243_000253
332
+ OH0FJZSwIeg_000103_000113
333
+ i4go33PLX6A_000117_000127
334
+ yJW-DDaMZ-M_000024_000034
335
+ plVYb0kiH-I_000252_000262
336
+ Jiwq0zk18P0_000082_000092
337
+ cMwJhIEqROM_000000_000010
338
+ MPWJCZpIZoM_000029_000039
339
+ XxY0Z47n7pg_000080_000090
340
+ 9nEHFb1mGuI_000058_000068
341
+ P7TDOO5paL8_000137_000147
342
+ s1VemC8UQ9k_000090_000100
343
+ U3VrnCjpEmI_000164_000174
344
+ RxO7IEU7_I8_000391_000401
345
+ sLRwdRnwCWs_000051_000061
346
+ RNA_wIhYPp8_000047_000057
347
+ luSl6aGT1kw_000010_000020
348
+ 37k7DrOPzbw_000002_000012
349
+ 0y9jAiuCu78_000073_000083
350
+ SA080tXbV6I_000000_000010
351
+ Vt6hfbMUzWc_000044_000054
352
+ MjBWljbRcxg_000007_000017
353
+ Vn0FNH2XTx4_000002_000012
354
+ OjowI-z7-oo_000006_000016
355
+ VhrYiENr0Fk_000440_000450
356
+ 20gCvLBfyzQ_000069_000079
357
+ y2CfrrXbLQI_000517_000527
358
+ M29qNwCV8Sk_000069_000079
359
+ shktJpYmOOk_000011_000021
360
+ hRQK0ToE90w_000375_000385
361
+ BcF2As-ebhw_000061_000071
362
+ t4BHlEbafvc_000040_000050
363
+ paxANprdjk0_000013_000023
364
+ sMtcdADtkNU_000004_000014
365
+ NHn-t_VarHg_000000_000010
366
+ _iyEqlFFrxU_000047_000057
367
+ udEsPNoiJR4_000012_000022
368
+ T6bx9H6gL2I_000000_000010
369
+ 7AY86S8Vg6g_000009_000019
370
+ VihXKPrgTrE_000069_000079
371
+ pTgIYOnWrw0_000047_000057
372
+ 88oXj0zKdp8_000000_000010
373
+ 1Ez_zoJDukw_000014_000024
374
+ wC-mLP684J4_000028_000038
375
+ OBbboTWbUQo_000090_000100
376
+ -IGwsxNxUpo_000002_000012
377
+ _3DfEgSKpjM_000035_000045
378
+ n64kp3OZY6Q_000262_000272
379
+ 2EkpqUeIUGA_000069_000079
380
+ h-ekL4jR214_000000_000010
381
+ 5s0Hr7dZRXU_000044_000054
382
+ z1DcfYXY8J0_000134_000144
383
+ 3jP9HNJddR8_000003_000013
384
+ c-7aCvrVkoM_000002_000012
385
+ o7irCXceNjg_000046_000056
386
+ wPv6ODnrLAE_000044_000054
387
+ kamRtGTha5Q_000057_000067
388
+ 4kgJJ1FjTrw_000091_000101
389
+ ZVDR2od1gn8_000037_000047
390
+ e9WO9WHuP8s_000018_000028
391
+ 5AqRrxvRC70_000025_000035
392
+ 1sazJwkVbNY_000010_000020
393
+ UrV44zz_gnE_000056_000066
394
+ glIq9KmXoYw_000004_000014
395
+ fV2RqP9ZlSc_000197_000207
396
+ 9RWgHcPZ07k_000039_000049
397
+ -MV_iN5WXuw_000002_000012
398
+ j5GuVIzDgrE_000047_000057
399
+ Z1WLfpOiqpI_000002_000012
400
+ fGuGmBLkWKg_000034_000044
401
+ 6eCU1LOTyCw_000024_000034
402
+ PXOluGNqZcc_000120_000130
403
+ 9yPQHK-GXUs_000056_000066
404
+ b7-jU2adf_Q_000010_000020
405
+ 9NWpyCuMjBM_000021_000031
406
+ -6CM7VV8-_w_000262_000272
407
+ -kmzssWKO-o_000029_000039
408
+ LAH48I8WTbU_000008_000018
409
+ wAVx8xJAJxc_000007_000017
410
+ yhZCJEr4x1w_000050_000060
411
+ a8HehnYjquw_000107_000117
412
+ oIosEbECUo8_000077_000087
413
+ 06fOUg4SADg_000003_000013
414
+ t3lMq5lZJ04_000000_000010
415
+ E1nEWt5VZzY_000061_000071
416
+ Z5BkKxbGuXc_000000_000010
417
+ 4IwQFgz7Ni8_000000_000010
418
+ NcmA-Oyvx1A_000078_000088
419
+ BqdjAlbg9XE_000021_000031
420
+ rEJaqonTVVE_000000_000010
421
+ fB1mByWn1Xs_000023_000033
422
+ q2XxNNIPl_A_000039_000049
423
+ K0xgh53GRGg_000007_000017
424
+ xc17jJnxGk0_000012_000022
425
+ TEj_A_BC-aU_000184_000194
426
+ -HKeIdvg7U0_000011_000021
427
+ lUeIoyXODec_000001_000011
428
+ HvnLVSTwOUE_000239_000249
429
+ GkkWbdydkPk_000014_000024
430
+ lBkWzOXr3Y4_000012_000022
431
+ UKGWaUaRXi4_000095_000105
432
+ Vpz3Xxj8ndU_000012_000022
433
+ lj4GXOHT-88_000028_000038
434
+ j59F32qbHEg_000088_000098
435
+ P0coxgcUXQ4_000164_000174
436
+ 5sg_PjZ2kvo_000011_000021
437
+ J2MNJqVHPX8_000001_000011
438
+ 08jcCNdrp4E_000044_000054
439
+ bB0p-_ie8sg_000423_000433
440
+ 9wXgbdeeS1w_000000_000010
441
+ RQUxuTHi2P4_000020_000030
442
+ 5bPlcd0w7uA_000001_000011
443
+ kXJ8xHHxTn8_000035_000045
444
+ I2YlCISB8TY_000036_000046
445
+ MHQSH4QlQoo_000277_000287
446
+ 47oVUabZiic_000000_000010
447
+ 5GP0aPugZZA_000000_000010
448
+ mDXWM3kEvfE_000065_000075
449
+ CZOroZ61VSg_000000_000010
450
+ hkoAdY1ZzDU_000004_000014
451
+ KE9NpeyzfmA_000257_000267
452
+ bL3YnakZWHo_000006_000016
453
+ FsrD9In_oBM_000002_000012
454
+ UPujViBOznY_000062_000072
455
+ 6dCaO9SMg60_000508_000518
456
+ n97--O-1Gao_000055_000065
457
+ MVeOJmSOV6w_000102_000112
458
+ BPAZjVFei4M_000000_000010
459
+ 2qo35QV3w-s_000017_000027
460
+ K1EIjRaLAS8_000034_000044
461
+ WQqCGlffDvQ_000081_000091
462
+ sC-ecZhBWgU_000000_000010
463
+ AOVNu8IC7PE_000059_000069
464
+ 7sv__wEPiLA_000002_000012
465
+ PYZbDPuPEmg_000000_000010
466
+ XlNCltb6q2g_000010_000020
467
+ TIIMHjK9GU4_000041_000051
468
+ v-TJuL61DbI_000056_000066
469
+ c54-0dOxrac_000016_000026
470
+ IfX6cllnCSA_000074_000084
471
+ E2_RYbnGF5U_000087_000097
472
+ abcm6SdJ43o_000000_000010
473
+ dC2Ih_JFoOM_000000_000010
474
+ mGu58sIxqj4_000023_000033
475
+ 9rudQQiIWac_000022_000032
476
+ lCVFKqQpTIg_000000_000010
477
+ 0k8ZyywA8Ac_000004_000014
478
+ tGiBJQ5RhZQ_000077_000087
479
+ --oJV4vFNeI_000003_000013
480
+ _PZtfoG-H1M_000166_000176
481
+ a0OxjWs1ljY_000017_000027
482
+ J5pgXKJL4wg_000012_000022
483
+ 1dmiavULOAg_000003_000013
484
+ N1DRDrpALco_000108_000118
485
+ lVwFn9m8Q_Q_000053_000063
486
+ D8MzzIhvBdI_000005_000015
487
+ lVoyp938QBs_000040_000050
488
+ D3EeiT6hZI4_000104_000114
489
+ 74SXYejRo-Y_000000_000010
490
+ brJ2L7pbeA0_000108_000118
491
+ wR3cCcmP0SQ_000028_000038
492
+ 0AaSiIVdKXU_000027_000037
493
+ ZSiSZX5UNqY_000015_000025
494
+ kSmmIhj24cc_000004_000014
495
+ iBKnfBpxUII_000055_000065
496
+ M4jq4TZm8R4_000044_000054
497
+ xeZr-gqjBYY_000072_000082
498
+ sKgJFd0bMgg_000033_000043
499
+ ecnHGeTB4VY_000008_000018
500
+ CZfe0PkjvA4_000025_000035
501
+ ZupvPUGTifY_000000_000010
502
+ hVrvXFrYU6I_000004_000014
503
+ 2mgdkontHv4_000041_000051
504
+ wgi2kzp1js8_000074_000084
505
+ iGn7dk9hxN8_000004_000014
506
+ RYz48Rc385M_000151_000161
507
+ TG7dCEc9PHA_000028_000038
508
+ BgxgcBNT1eA_000191_000201
509
+ 67nxVB56psY_000057_000067
510
+ OpDii8AnOcQ_000004_000014
511
+ 7SEew824P2A_000164_000174
512
+ 1HDx1DeSq6A_000136_000146
513
+ PHEyn4-rJSA_000011_000021
514
+ bI6t7z9IYVQ_000006_000016
515
+ -dLVSg5JvxY_000022_000032
516
+ r917E_NCmgo_000027_000037
517
+ DmjsEgVPK34_000073_000083
518
+ 9fygsDgFWJE_000001_000011
519
+ t9sQHL2ypHs_000097_000107
520
+ eWQWYDoLVXs_000195_000205
521
+ Rgvug46euIE_000114_000124
522
+ xr4wTn-GDT8_000085_000095
523
+ sBJk5li0O5o_000003_000013
524
+ BdWCltVcdxk_000015_000025
525
+ q6dyWFq3-LE_000000_000010
526
+ IDgQ4Oy-hrg_000053_000063
527
+ lSaYiQRMtjs_000018_000028
528
+ gfHCbDqMmm4_000047_000057
529
+ NcuHH57heWE_000008_000018
530
+ ZAH-BX96pmA_000002_000012
531
+ 66NEJHDxIDk_000068_000078
532
+ Wojf4uAaFV8_000057_000067
533
+ DUmFFNmfgAg_000013_000023
534
+ MSzj5Rl1K5c_000020_000030
535
+ sWCaswVL01Q_000101_000111
536
+ l5RIYpoxCS0_000020_000030
537
+ bkU7KncK3e0_000077_000087
538
+ ffvtOV7En_c_000003_000013
539
+ uqibGSe0vNw_000051_000061
540
+ mL4jKEZDAFc_000015_000025
541
+ n6lUXDwL4Y0_000022_000032
542
+ IiATZMBx1eY_000032_000042
543
+ 9iytLJcY9gk_000005_000015
544
+ 9jgih4uYH2E_000000_000010
545
+ 4x0kKZY_IhE_000057_000067
546
+ H4yFkDFjPCQ_000027_000037
547
+ mSvYTWkVBJA_000008_000018
548
+ 77bGWKIfsvk_000061_000071
549
+ ym2ehgmrqlg_000000_000010
550
+ 76qMNUzfX7w_000097_000107
551
+ 6WtcpH6IkIc_000058_000068
552
+ P_L4Tuvc3l0_000084_000094
553
+ _YWpv2_K8Pk_000054_000064
554
+ Mf7NHE3AL0k_000004_000014
555
+ WOtjzZC0JPI_000001_000011
556
+ yF34Pg30MiI_000308_000318
557
+ PWWB3RDEVHc_000038_000048
558
+ -gsRLvAO4mw_000022_000032
559
+ A7DMjBZyvDY_000090_000100
560
+ wN4GxQ2566M_000003_000013
561
+ HeEsL9yTiKg_000033_000043
562
+ 5Jf_z8s8ctU_000012_000022
563
+ LcQ3cShXEWE_000011_000021
564
+ EiRZjAB5JOY_000002_000012
565
+ WEcPPLZ3-JA_000114_000124
566
+ 3IfSTN-Eptg_000022_000032
567
+ KCSaZGVBHkU_000147_000157
568
+ LWQ_cBRP7yA_000034_000044
569
+ URrS4GtGQmE_000167_000177
570
+ 6ZojdU1fPOo_000001_000011
571
+ y3OSgyt346E_000000_000010
572
+ jE4OreT7B9I_000377_000387
573
+ tXjOdvOPSc4_000005_000015
574
+ y5y1k6eJXyA_000021_000031
575
+ Jo79VXKw1uo_000000_000010
576
+ pCWdCVKE2qo_000000_000010
577
+ Kr3sO1eqVEs_000069_000079
578
+ i-YJVFCh0zg_000028_000038
579
+ AwsTvv5mfeE_000009_000019
580
+ PmJW9OWTibQ_000230_000240
581
+ Xw-WT0yUimg_000334_000344
582
+ Uws0FYxwS90_000158_000168
583
+ MU0HXzaN7qo_000040_000050
584
+ NJu5gpi6W50_000325_000335
585
+ YAmbVR1n56c_000144_000154
586
+ tOgVE8ModME_000003_000013
587
+ 3g0zSuxMIkQ_000051_000061
588
+ kCk-RVcoR7g_000059_000069
589
+ B5b2rBinfCw_000024_000034
590
+ qVoiEgXxOTU_000001_000011
591
+ dBAT_3nPgX8_000076_000086
592
+ etShLTcatJs_000121_000131
593
+ xFO0lEzQkQI_000036_000046
594
+ 5irp8ASgdhQ_000029_000039
595
+ 2L8B__meOLE_000020_000030
596
+ Zrhf5rNcLcA_000055_000065
597
+ xUK01b0W4_I_000013_000023
598
+ HzO-QXUsHb4_000083_000093
599
+ ObYmv1FIGVU_001263_001273
600
+ -Si5SfAGWek_000000_000010
601
+ OU5dJpNHATk_000148_000158
602
+ tXBjXHtckDY_000032_000042
603
+ TUOIarQEnRM_000009_000019
604
+ tec79sCOXyA_000012_000022
605
+ IFXyeVwqIoo_000000_000010
606
+ nJVM_LYlZK8_000015_000025
607
+ yFSBC-iXnqA_000051_000061
608
+ 144kxqKEkNE_000000_000010
609
+ qdKbgwpgh04_000032_000042
610
+ h5jF0HR-J1g_000003_000013
611
+ MX1hcxfiltU_000032_000042
612
+ FCZQSGXsvw4_000091_000101
613
+ x6IAyph6dMc_000032_000042
614
+ WQZ1rwEzGEk_000000_000010
615
+ LaaPuezxneg_000078_000088
616
+ nj3KLfg5Kbg_000003_000013
617
+ -dHjiNfYz4E_000015_000025
618
+ Nn7ypmEaad0_000014_000024
619
+ -l309dqYR-8_000113_000123
620
+ l6jMv1FfGhM_000001_000011
621
+ O1PXECSNwr4_000034_000044
622
+ FWuFkDZUY5w_000093_000103
623
+ oCkPMmVif2k_000051_000061
624
+ 3uLjjmc3Azw_000059_000069
625
+ q2-YgfjojXw_000018_000028
626
+ -myPMnDFa4Q_000003_000013
627
+ Pj8051a9yj4_000000_000010
628
+ LLGQJhkSyCY_000441_000451
629
+ 7WOty3qVdts_000000_000010
630
+ q8aCC3LSlgE_000027_000037
631
+ rjHCBP--jMo_000195_000205
632
+ Hgo7xkutPno_000059_000069
633
+ xnyOA58A07Q_000127_000137
634
+ zmDrZGRmHXM_000018_000028
635
+ n5Fr76ZUlrM_000004_000014
636
+ c11YrmfQ14Q_000092_000102
637
+ ZgBm7w1CRU4_000000_000010
638
+ 2HnBaGajUi8_000083_000093
639
+ vnSld6eV0M4_000000_000010
640
+ BYLMB5s0M8Q_000168_000178
641
+ XaCg7OXyglk_000034_000044
642
+ 6j9BYhLmFvg_000000_000010
643
+ 77aDh42ddw8_000209_000219
644
+ x7EIJEzNGlQ_000004_000014
645
+ NFytp8srWCg_000000_000010
646
+ PMpVRRs6NzI_000016_000026
647
+ DDwSxyD5A1A_000102_000112
648
+ Im7rGy0xCaM_000009_000019
649
+ L9BJsQyrJbo_000089_000099
650
+ VCdsrK2qNeA_000134_000144
651
+ yfKm2hz9psg_000000_000010
652
+ eWgy8eG3stA_000164_000174
653
+ 6FqS59XxFNY_000003_000013
654
+ -VatMZ0ztMk_000000_000010
655
+ q3cRM4TVVRI_000000_000010
656
+ VXrzA3M1Erc_000068_000078
657
+ LCdm6pFrmtw_000015_000025
658
+ c68Z9cjgVsk_000267_000277
659
+ 3dHsAg2A2ms_000008_000018
660
+ 01UETgu-H60_000035_000045
661
+ h3wDKrgNzC8_000016_000026
662
+ 1ah8avfU5YE_000053_000063
663
+ uhziJEu3Xmo_000026_000036
664
+ j0-SQa7igwI_000188_000198
665
+ rFHugHoOTcc_000034_000044
666
+ hSGR05xCpL0_000077_000087
667
+ 5sBSi4RPXKc_000113_000123
668
+ tAffztlKpiI_000035_000045
669
+ 8EBYQucNo1Q_000057_000067
670
+ xwKuZ811HRw_000558_000568
671
+ aD-2SrdN-Is_000184_000194
672
+ 4wcWJqEyTSE_000064_000074
673
+ ZXvgHRz92h4_000056_000066
674
+ xtMTgyNduLc_000180_000190
675
+ ogA3nkMl0Q4_000001_000011
676
+ bnSYqx_JBaI_000001_000011
677
+ COnYleGIBw0_000025_000035
678
+ cHJJtEVn1os_000019_000029
679
+ W8sGcM-SRIw_000000_000010
680
+ 1onZf1b-az4_000000_000010
681
+ 4eGnWcA-lo4_000026_000036
682
+ URLxWfi96Os_000029_000039
683
+ mkoRSlkknhM_000070_000080
684
+ 9lrW9DpfkHk_000044_000054
685
+ qAY_lryy0j4_000013_000023
686
+ q8Tklyq_rbA_000116_000126
687
+ OmoC3X888rg_000001_000011
688
+ wnfbsZt7vRs_000009_000019
689
+ KgE1nhFYH4k_000022_000032
690
+ mM8A7RHUtlI_000064_000074
691
+ XbKnoNtqSEw_000000_000010
692
+ ZQj3kEu6q1I_000383_000393
693
+ plIJXZF0eqk_000228_000238
694
+ 1rsLh2kG96A_000106_000116
695
+ f8Pp5JNDlnI_000287_000297
696
+ 82_AFzsFnhs_000052_000062
697
+ PbAstXAC1f0_000041_000051
698
+ yCMBMuxp7hE_000063_000073
699
+ 5UMVOoEoMEY_001542_001552
700
+ SBHh3bkii70_000014_000024
701
+ 8Wfh9zIzLfk_000045_000055
702
+ 958745Brjw8_000049_000059
703
+ hd7dxyjovCY_000031_000041
704
+ B8TZJ94CcIA_000000_000010
705
+ 4ebFdrC9Fec_000020_000030
706
+ JYdMmbtYKDQ_000004_000014
707
+ hREynPJ5mHE_000000_000010
708
+ Y3sWpSIxS1I_000075_000085
709
+ g688nwyO2lY_000028_000038
710
+ K-Nokzt_Zqc_000284_000294
711
+ Ry_mhLjzBDw_000004_000014
712
+ 5WFUemuKN5Y_000005_000015
713
+ 5qqV2ZnH_4I_000030_000040
714
+ wvho1p1E_nc_000010_000020
715
+ kf5-mcJ32Ss_000038_000048
716
+ mDzcJdO9Wfg_000000_000010
717
+ SvuscI1XA-I_000055_000065
718
+ LgZt6EpY4G4_000015_000025
719
+ jnnpnL0pxuY_000000_000010
720
+ qQWOAoWM60M_000163_000173
721
+ 0-3yl2_Myso_000003_000013
722
+ Rz5umsLIZTA_000056_000066
723
+ Y9WjlhlcmJs_000003_000013
724
+ lQcirD6UngU_000012_000022
725
+ NJbB5BA7hwk_000003_000013
726
+ hJ2SPDIZH3U_000059_000069
727
+ Vqzf8Gkq7OA_000129_000139
728
+ D1ddrQYAlhw_000001_000011
729
+ x6wRCc5J5eY_000066_000076
730
+ U0bYM2bPTKM_000006_000016
731
+ PcdvVIsO2eY_000061_000071
732
+ FinRO8rSgAY_000000_000010
733
+ wH0GUySIQ_s_000004_000014
734
+ t_E8gEnLtdY_000079_000089
735
+ OPjonSK9blk_000018_000028
736
+ xxqkCP1oTis_000223_000233
737
+ E3FG1SdjzVk_000021_000031
738
+ 6kkPlWASbbA_000368_000378
739
+ bIiDiDUl2RU_000009_000019
740
+ QqBS6yJuBog_000000_000010
741
+ QyMTEHd-VCc_000004_000014
742
+ b8vAhQSYN-g_000000_000010
743
+ w4zEea_xufs_000605_000615
744
+ EZX06L1OsQU_000016_000026
745
+ fh64vbutTrI_000141_000151
746
+ syqGFVCbDWQ_000003_000013
747
+ x2fEWmcJXjg_000008_000018
748
+ COrYGNIyI7Y_000230_000240
749
+ Yqd0U012_Hw_000368_000378
750
+ nflG2ce8VY8_000294_000304
751
+ 9dpvCH9fcIc_000343_000353
752
+ N0jrPWhNhwU_000004_000014
753
+ HCvhz5HkpF4_000078_000088
754
+ ZjzhQBpqqSg_000073_000083
755
+ pYKexDBJAYA_000004_000014
756
+ 5rZzxIgLlPU_000000_000010
757
+ GpI8DSsvwXI_000044_000054
758
+ fBcKhmdWCvE_000012_000022
759
+ aVWB66MJ-uA_000010_000020
760
+ 11DNgvKLRHM_000078_000088
761
+ flBrhLZdr98_000000_000010
762
+ nFqTpZAo3qY_000027_000037
763
+ tv5sUDmBmqU_000023_000033
764
+ EPTwkPkjpwU_000087_000097
765
+ hq7oXt2kveE_000000_000010
766
+ LdWlQFqqits_000171_000181
767
+ 1zSg9oighVw_000000_000010
768
+ uNLTuNK8skM_000054_000064
769
+ v7yobVKtMi4_000052_000062
770
+ N6z7pUTrTt0_000000_000010
771
+ 6ScXEmM8JO4_000145_000155
772
+ UPoWxo4Fogw_000002_000012
773
+ AYdb1XhQXGo_000023_000033
774
+ Ky49iSd6zDs_000014_000024
775
+ CvSIs_R_BEk_000082_000092
776
+ de1rSoht9t4_000002_000012
777
+ y7hn2Ya16ug_000178_000188
778
+ Y7CZDrJ6Jv4_000000_000010
779
+ nwDKOJHMHhs_000023_000033
780
+ 0Q_QyVrbQKI_000015_000025
781
+ P7CgvqGhidw_000073_000083
782
+ Yio9nO2UuuA_000052_000062
783
+ 8VZCvv0h3DI_000032_000042
784
+ ucI2PxYGTmI_000000_000010
785
+ CiRq6h7RDBE_000004_000014
786
+ Tdz2yMXJcZI_000003_000013
787
+ ZoGtMtjjPMQ_000087_000097
788
+ DcYqRCy3LsI_000046_000056
789
+ WcxNna60adM_000062_000072
790
+ gw2PjMz-TJI_000028_000038
791
+ jiZgpSw9cKQ_000035_000045
792
+ ONFppy-AC0M_000082_000092
793
+ sKUrb7gV9XE_000003_000013
794
+ YkYoZyGVzCg_000000_000010
795
+ EU5g-Pi0a24_000153_000163
796
+ -5wvw64KXqQ_000000_000010
797
+ X8Tzn9cdCiA_000043_000053
798
+ GRWpczd858Q_000203_000213
799
+ Xqso_EmafEg_000003_000013
800
+ u5SW9SFXBTQ_000032_000042
801
+ JBGTIJbfrPo_000077_000087
802
+ 8hZdfjj3cU4_000000_000010
803
+ 7M3utA5j6vU_000002_000012
804
+ IDh_IR5L3yk_000000_000010
805
+ vI8Vp2-gfiU_000014_000024
806
+ hceOcG3ZgGk_000073_000083
807
+ JeNGL6M9Bok_000013_000023
808
+ dqh0qThZUjE_000054_000064
809
+ ng8f7_uedZ4_000038_000048
810
+ IeDin6oB-IY_000003_000013
811
+ AE66r-8pfLE_000176_000186
812
+ p2s5fet6Xu0_000068_000078
813
+ x6T517yfG54_000038_000048
814
+ mZGCStZvP18_000027_000037
815
+ oVeHcRapPao_000429_000439
816
+ N8pzeulGgPI_000231_000241
817
+ 2v75xvVshtQ_000000_000010
818
+ e1DfuOIVBho_000000_000010
819
+ ofhjWgPguFI_000002_000012
820
+ G91ngyXp6S0_000010_000020
821
+ m0R5rkIi6VM_000077_000087
822
+ rc3aO3TyAzg_000000_000010
823
+ Iz5nOXvBzWM_000009_000019
824
+ IWuwX0hg6sw_000051_000061
825
+ E8_pIIAr90c_000000_000010
826
+ cTx8W_JL_D8_000020_000030
827
+ eMhRkRpOEZw_000197_000207
828
+ LDun0fTcT4w_000087_000097
829
+ ysIr-YTnCN8_000198_000208
830
+ XKxKNnrLloM_000000_000010
831
+ bTT-Lk4Hc88_000208_000218
832
+ W-hlYP6vj3M_000044_000054
833
+ 8mdhjvJ9jE0_000063_000073
834
+ pBy55jurdRw_000093_000103
835
+ W9LR5Z9C33E_000104_000114
836
+ 3-UHHYrkjGM_000001_000011
837
+ _lR3PdrCkVU_000000_000010
838
+ 2bA0vJGml6Q_000005_000015
839
+ ZlWcMe2ZJCA_000011_000021
840
+ F_WeSA5gy2Q_000041_000051
841
+ 4-9_szZr2xo_000015_000025
842
+ d1xqBCytAok_000008_000018
843
+ R-icd8119D4_000026_000036
844
+ 878gvnBSZlg_000367_000377
845
+ Vx2RMyFUCrU_000037_000047
846
+ Mrlqkm6wzW0_000023_000033
847
+ 8IqHQwVqg8g_000076_000086
848
+ YbLmMm66uUk_000192_000202
849
+ _2zXAtOKXm0_000004_000014
850
+ igA7TJcaxqo_000056_000066
851
+ TeCuiDh9CxY_000075_000085
852
+ u40B4vhkPF0_000081_000091
853
+ wKhO5-BMphQ_000000_000010
854
+ gCGT2L5jJoo_000085_000095
855
+ FIO-_zM7Rac_000054_000064
856
+ f_KuNcFykFc_000092_000102
857
+ 8yoMHlEeZXU_000019_000029
858
+ QxtqFjvbeKM_000321_000331
859
+ wFuL-cskQn4_000020_000030
860
+ m8bbW5gbYVw_000178_000188
861
+ XKJbWSZLI6E_000027_000037
862
+ HuVxgC3XBco_000040_000050
863
+ wnQOc9Q5oC0_000002_000012
864
+ 5ZBwM_KsOpo_000064_000074
865
+ Dbzm5Gl6gWA_000017_000027
866
+ p7Yt39yhPvY_000075_000085
867
+ MsG96pPLUI8_000012_000022
868
+ i6bLvWT5n0A_000000_000010
869
+ kpcrsFCJMf4_000067_000077
870
+ PzD2BkZye2U_000013_000023
871
+ CQ1_ovjb-Ho_000258_000268
872
+ KwCBcXCqOy8_000074_000084
873
+ E2QZ_ErlrJ4_000022_000032
874
+ UBjwOghFbvY_000012_000022
875
+ xPAhqvmiaWI_000100_000110
876
+ GFDeZ1M-j2E_000001_000011
877
+ m19Citzz748_000232_000242
878
+ DYcbS0QgOs8_000003_000013
879
+ vk506HLk254_000000_000010
880
+ enEATg4tI6I_000116_000126
881
+ ZYH4ja41BQs_000003_000013
882
+ ZmvFrZKCxt0_000106_000116
883
+ 2DfK16gO5mc_000019_000029
884
+ AHXpkJSLqg4_000460_000470
885
+ dCVZadCffts_000012_000022
886
+ klbIHNGPYR4_000024_000034
887
+ socL3CLqXuA_000007_000017
888
+ VpUVzgDEj9U_000005_000015
889
+ Xr3Tle4trX8_000000_000010
890
+ leWjhZKaK7Q_000350_000360
891
+ QCWm8MqlUO0_000005_000015
892
+ W6CY4iqLdSY_000000_000010
893
+ Adspplz782U_000015_000025
894
+ KbqWQKStExk_000003_000013
895
+ NFeh8RMi7H8_000043_000053
896
+ 7mP4mouloV0_000011_000021
897
+ Tka7TzOO3EE_000086_000096
898
+ 9XkicLU0ZRQ_000000_000010
899
+ jRvQ6MBC29I_000018_000028
900
+ VnDRckszp7c_000006_000016
901
+ Q80s-wLw6kA_000014_000024
902
+ fIXf9Iv_w9M_000004_000014
903
+ QC5Zscj3reE_000016_000026
904
+ JJOkXFxcw34_000167_000177
905
+ NOhVk13afn4_000008_000018
906
+ 8nceWpmAE1c_000004_000014
907
+ s6uinCc6itc_000007_000017
908
+ lRp-y4ezD3A_000067_000077
909
+ F5JTPUwBDw4_000405_000415
910
+ h0rWRIF1Si4_000023_000033
911
+ jjcVjm790-s_000574_000584
912
+ j4POnrecrIc_000113_000123
913
+ gs45ojguZXY_000000_000010
914
+ 14TXmFXcnBY_000028_000038
915
+ zgV_kYzVyJY_000003_000013
916
+ w8-DVGaU1Cg_000005_000015
917
+ RI1-69UIurQ_000035_000045
918
+ 4hgh-ruFH0c_000113_000123
919
+ qWr7plHuEtE_000024_000034
920
+ TzfkS-SPp30_000013_000023
921
+ MrI8XlHC4p0_000000_000010
922
+ HM4tiCR6BGA_000003_000013
923
+ _gdT1bgS-68_000131_000141
924
+ lllqzohXPD8_000001_000011
925
+ CZykUx8OAbU_000067_000077
926
+ 05DTHPMVt_I_000005_000015
927
+ ZFX7oYdu_hI_000009_000019
928
+ lgPslaxBQt0_000000_000010
929
+ vhoawk6MPwM_000442_000452
930
+ QoyIT1L54Ks_000004_000014
931
+ ZGi_1YXNkvw_000006_000016
932
+ 9vvv9vfDiuo_000147_000157
933
+ 0w7jPdjFhfg_000336_000346
934
+ nKhSp29wB8c_000035_000045
935
+ us_pXO_vwPc_000031_000041
936
+ RhRtKsipSzM_000002_000012
937
+ VlTbwUyIm-k_000072_000082
938
+ 5P6Q57A9OUk_000284_000294
939
+ 3g6vYQ3Qp8U_000003_000013
940
+ qS2-xjUoyxk_000013_000023
941
+ Z2nrv3qiSZQ_000152_000162
942
+ 4eeA-gswYjc_000019_000029
943
+ JBmRfj_N6EA_000000_000010
944
+ 9E6_4PgjC50_000010_000020
945
+ MB38Nepx5Gs_000006_000016
946
+ 5v_7XLNUrc0_000008_000018
947
+ 9rs1Yvxh8H4_000030_000040
948
+ kjCtZfFL8Wk_000128_000138
949
+ q3Yrx7-5W9I_000016_000026
950
+ M4WxnBb8dww_000000_000010
951
+ eJ_SjjpBYE4_000139_000149
952
+ F6tyMvJJvUE_000185_000195
953
+ Z_cdeyDDTHs_000141_000151
954
+ 6oxymlT4EU8_000000_000010
955
+ D7R6eFwMd4Y_000041_000051
956
+ 7namAi4s1Kc_000021_000031
957
+ aB2vxMeQfG8_000052_000062
958
+ LmP6Y6rEptg_000021_000031
959
+ fRR-rFGoVX8_000048_000058
960
+ VEKFBUXZgBY_000011_000021
961
+ Qol81g7sOz4_000018_000028
962
+ x-uWz2-2WkI_000056_000066
963
+ -6yaNVdS-2E_000000_000010
964
+ 0elHrwxt_bI_000004_000014
965
+ meoWZ1SQ0Xo_000003_000013
966
+ Y7fRiJkjnno_000000_000010
967
+ ZJD0IvXAmvo_000001_000011
968
+ O293sucZTDc_000009_000019
969
+ U9QFI8-Q2sA_000024_000034
970
+ IkxOgDBCdug_000044_000054
971
+ EkT5y-2ie94_000238_000248
972
+ i1Zf3AUlaL8_000083_000093
973
+ 2cLWIXDi3ks_000077_000087
974
+ djydGQkk1Ck_000000_000010
975
+ dOc89368npY_000214_000224
976
+ 4A-hQHF5wFc_000047_000057
977
+ vYUfJD176IU_000122_000132
978
+ Td1A-OQM3fU_000002_000012
979
+ swDObGd9wd4_000025_000035
980
+ zFSdiCg9Rjs_000079_000089
981
+ pKEgGe8lWnA_000007_000017
982
+ 9npPGoZ_g1M_000029_000039
983
+ jEeV0LPXPxI_000015_000025
984
+ NDfVG35vYmw_000005_000015
985
+ 1DAtchstb_4_000004_000014
986
+ H5KcYdDzf9c_000176_000186
987
+ 2FgAQrOe4lg_000208_000218
988
+ u94z2C0J5Fo_000000_000010
989
+ cxYfDw3qt1M_000195_000205
990
+ SkqvHnlsnVE_000023_000033
991
+ WXt6Xqc9st0_000011_000021
992
+ 6ODMKujAWhw_000158_000168
993
+ wPeWVPrOl8A_000004_000014
994
+ 8SZHEgS1d50_000020_000030
995
+ DoOiOKwy1gk_000050_000060
996
+ ym1Eu_YVj4s_000036_000046
997
+ O0ymrFvrgYY_000130_000140
998
+ NVDgaixYPgA_000031_000041
999
+ 4fRGzKO1KLU_000000_000010
1000
+ YLJaiKWGQys_000139_000149
1001
+ M5aBsf_IGvc_000067_000077
1002
+ 6n4j0MoLDww_000017_000027
1003
+ F7yII1xbF-k_000465_000475
1004
+ QqlTEhzK_Gw_000015_000025
1005
+ 1SzM6XlB81s_000000_000010
1006
+ SeCwevKut3k_000183_000193
1007
+ SQtvychI6Bk_000014_000024
1008
+ flCiy8akWyw_000051_000061
1009
+ BYoIZZLnizg_000008_000018
1010
+ UAHoOHpQWlA_000053_000063
1011
+ zr7y21HASOs_000021_000031
1012
+ LtKnLVqr8i8_000217_000227
1013
+ T05qWt3oxxc_000050_000060
1014
+ H8rMDUDnqTE_000032_000042
1015
+ HAezZ-g5ntY_000123_000133
1016
+ nG8A-M9tvtA_000100_000110
1017
+ bYq9JMbV4Vs_000036_000046
1018
+ ENorOsdty00_000347_000357
1019
+ -d7gxstQux4_000067_000077
1020
+ i4K7rWrsgyI_000038_000048
1021
+ 4lPNXqiS6d8_000045_000055
1022
+ wG8u7evqvhM_000014_000024
1023
+ o7oG4LKLrdo_000390_000400
1024
+ mF5qk0efJbo_000000_000010
1025
+ 8f0U0oGyugQ_000007_000017
1026
+ NMd_TLbm9d8_000156_000166
1027
+ NAiHI-77OQk_000098_000108
1028
+ 0Je9lZCyNgk_000016_000026
1029
+ m0mo6zbBkGc_000001_000011
1030
+ K-r_Tj7uFGw_000007_000017
1031
+ OopGmHDZI2M_000090_000100
1032
+ 66ZIRfYTeXg_000149_000159
1033
+ m1XBfBhMSK0_000076_000086
1034
+ yUvBOFF9OPw_000000_000010
1035
+ 4nJ07xfDip0_000003_000013
1036
+ a4ROubm0cIc_000000_000010
1037
+ MgZTNN8jQbo_000013_000023
1038
+ W8Fbjslydzs_000039_000049
1039
+ b3f4C0ngOwE_000000_000010
1040
+ _xE_0yhuehs_000163_000173
1041
+ V8-rdFVhU6U_000096_000106
1042
+ 4OPAmSlJ31o_000015_000025
1043
+ 2nnGmrCfXJI_000000_000010
1044
+ ghvlnZcOSJs_000000_000010
1045
+ 10UDBRZ5wnM_000000_000010
1046
+ ag8KLqzMZnI_000092_000102
1047
+ 36bFQ0AdkTc_000000_000010
1048
+ hd408sIsIjI_000083_000093
1049
+ eu5seBCWFcw_000014_000024
1050
+ Nb9tS5UreXk_000154_000164
1051
+ JLaFmdOjW-I_000023_000033
1052
+ swTrjCn5iPg_000000_000010
1053
+ pbneLOUYW68_000018_000028
1054
+ wo36qZoOOLU_000002_000012
1055
+ -pHrb1FLXfY_000011_000021
1056
+ CSMEQvz-OUc_000001_000011
1057
+ A8sjbCSzUow_000038_000048
1058
+ w7ZRJ7JNJrQ_000009_000019
1059
+ mhfVGeD6XxU_000051_000061
1060
+ t-COcCPV-T4_000020_000030
1061
+ i1A0qQHDBHk_000002_000012
1062
+ 2N_bg_UqJkA_000064_000074
1063
+ 9acHiJcAyz8_000039_000049
1064
+ uAwY_6l7680_000000_000010
1065
+ Vk0PYLTTg3w_000004_000014
1066
+ B4EcC9bJv8U_000176_000186
1067
+ tRDLInPlu50_000071_000081
1068
+ 9cha2WxlvSM_000005_000015
1069
+ 7h3uoKOxYHg_000065_000075
1070
+ --uGS0Y4D6k_000009_000019
1071
+ i-MlHUUx_j0_000000_000010
1072
+ xO81JlPwed0_000100_000110
1073
+ 19hKnhFMLUs_000008_000018
1074
+ wXJShRNmthQ_000018_000028
1075
+ z9s8IrLfcFE_000017_000027
1076
+ ww-qxWwnN1Y_000011_000021
1077
+ 29Dj0ISRaMs_000107_000117
1078
+ p3_wp0Cq6Lo_000406_000416
1079
+ 0S3itzH8NBU_000000_000010
1080
+ l3BXqg2lP2k_000197_000207
1081
+ NhGhlKiC-lk_000049_000059
1082
+ KKFHlgwXljM_000011_000021
1083
+ -fvtIUVgGtc_000223_000233
1084
+ IrrO4-aFvwg_000001_000011
1085
+ J8bZhQNBjYY_000015_000025
1086
+ oUfAz5k4EQ0_000373_000383
1087
+ -CHTxmgMUes_000010_000020
1088
+ bUHZAtuW-zU_000049_000059
1089
+ QtrShBu6bqA_000102_000112
1090
+ mEVYwZxXz68_000006_000016
1091
+ epTrdwLVzKg_000075_000085
1092
+ nEinWzcCaNc_000404_000414
1093
+ 9wO0YRODVTE_000043_000053
1094
+ DHJB2Kx3fcM_000015_000025
1095
+ lcUJjVgqXp4_000000_000010
1096
+ DIYiKOjA0v0_000001_000011
1097
+ ziRHCx9gvFk_000007_000017
1098
+ 0hVtX45KhS8_000075_000085
1099
+ cEmW-d9dda8_000011_000021
1100
+ 2fojVBo1tv0_000043_000053
1101
+ xaddtCnpkTI_000001_000011
1102
+ n1DUmdez1hA_000354_000364
1103
+ y7ZyI7aXTGs_000009_000019
1104
+ lGTMPfMfXLY_000221_000231
1105
+ DOVzrocR2fM_000043_000053
1106
+ o8BzuNJOoGk_000033_000043
1107
+ -FOfyuyabWQ_000016_000026
1108
+ 3-kjbGxqSeE_000077_000087
1109
+ i-qeC0YDfDM_000080_000090
1110
+ KVc_8dAigSs_000024_000034
1111
+ 8qReQWU-Ffg_000040_000050
1112
+ iR35vmsJ994_000063_000073
1113
+ C_QP4vOVTrE_000164_000174
1114
+ rPI-N-nGhQw_000053_000063
1115
+ x0xXPnl_SNE_000021_000031
1116
+ mQwjoRqpQro_000103_000113
1117
+ WFBA0RxdDqw_000027_000037
1118
+ PAJ3uH0tVc4_000025_000035
1119
+ dGvMfhUqnz8_000003_000013
1120
+ fzeIUdxSoIQ_000022_000032
1121
+ ztAfXKZ0ovM_000141_000151
1122
+ 6QroafCsHfc_000013_000023
1123
+ vgrr-N5x7kE_000035_000045
1124
+ -2VKVjgNuE0_000000_000010
1125
+ hy7xI8-xSOE_000031_000041
1126
+ KHGbByOzErk_000207_000217
1127
+ 6_jT33BqtK8_000038_000048
1128
+ WazX6nI7kes_000002_000012
1129
+ xn3RnUcBKAQ_000009_000019
1130
+ gEWC75dITlc_000003_000013
1131
+ BWUegTwLnpU_000007_000017
1132
+ WtnQKvOuukE_000081_000091
1133
+ k9-EFe0dAFo_000007_000017
1134
+ Q_F8YU0vWOA_000052_000062
1135
+ vfB6RccLMbI_000118_000128
1136
+ xwQmw_alBbU_000002_000012
1137
+ _ZIq66VAlJY_000064_000074
1138
+ o6NRDIu4qrI_000115_000125
1139
+ svVhMowxtT0_000000_000010
1140
+ ssn_saANNaI_000336_000346
1141
+ 810dEynPvOo_000002_000012
1142
+ jD1_v1R2raw_000000_000010
1143
+ PmOCR_IwCsY_000004_000014
1144
+ 6LOV6-dkNZE_000251_000261
1145
+ A9TcWJnbcWs_000001_000011
1146
+ l6CrXrj01GA_000102_000112
1147
+ slw7UYOTO28_000023_000033
1148
+ 6Q4-x1VOous_000043_000053
1149
+ -D6-UmndVJk_000001_000011
1150
+ pwCguMjX_3A_000002_000012
1151
+ L0Mfvzh4peo_000062_000072
1152
+ E2croigfy4Y_000017_000027
1153
+ 3qBLumz-KJo_000279_000289
1154
+ 5x-3iU4Mjq8_000005_000015
1155
+ 8Y3K5w3b2CU_000000_000010
1156
+ M-B6nIEF3KM_000111_000121
1157
+ BMdrFU5SGNI_000028_000038
1158
+ n753IrV58Gk_000013_000023
1159
+ JlVJ2vA9vmU_000022_000032
1160
+ 9I8me3WxbzA_000004_000014
1161
+ C5yTd8hS6AY_000039_000049
1162
+ CXgv232iW3c_000002_000012
1163
+ DLr9B2Bi0M0_000008_000018
1164
+ xQCi12r6Lfg_000003_000013
1165
+ LgHB-PEWODk_000002_000012
1166
+ -6tk1dzeCmA_000144_000154
1167
+ Q5YXwZAe4i0_000140_000150
1168
+ wUVxf6GUTHM_000019_000029
1169
+ AMPSyUu1r0U_000199_000209
1170
+ hEi8ty_0-JU_000132_000142
1171
+ 2wIcUAH9yaM_000024_000034
1172
+ yDjvtHR_VT0_000015_000025
1173
+ B57NAi7KZ78_000008_000018
1174
+ DxjGNZXHIDo_000193_000203
1175
+ 9XGSi2nIY9E_000040_000050
1176
+ sh3K9P5UXL8_000006_000016
1177
+ JUbuepvei2k_000013_000023
1178
+ 558iWbgz8RQ_000052_000062
1179
+ KX6X-0TVEsI_000015_000025
1180
+ VReq0APgHnc_000008_000018
1181
+ BrQi6a26vXU_000016_000026
1182
+ Y9_AJlP0iUY_000373_000383
1183
+ 3PKi-hiB7YA_000113_000123
1184
+ LvD57lc6WnU_000016_000026
1185
+ PcQ3hA5iOPM_000073_000083
1186
+ FKjRMG8tnU0_000061_000071
1187
+ Kcz7K-1UVag_000000_000010
1188
+ nD6aGWeuJbk_000000_000010
1189
+ uQk0V2_KliQ_000815_000825
1190
+ -8wsYw78yTc_000007_000017
1191
+ n15ydcfmZCQ_000090_000100
1192
+ yszYp04CCwE_000012_000022
1193
+ q21qB87cnos_000111_000121
1194
+ TpaHKH6UkDs_000304_000314
1195
+ Ms2iNKIsaXU_000050_000060
1196
+ e9mZDLGioxU_000104_000114
1197
+ l3uAuCYd6HM_000000_000010
1198
+ lGGYYuk5994_000119_000129
1199
+ wzyuVMClxt0_000040_000050
1200
+ xrWfU7q3eXM_000010_000020
1201
+ WHgCLj6fgKM_000042_000052
1202
+ UArdunmwEdA_000049_000059
1203
+ PnNDSAt3kz8_000001_000011
1204
+ TR-JsNOeXOE_000255_000265
1205
+ yimS7fmRQU8_000002_000012
1206
+ tx4wUC8oRJ0_000000_000010
1207
+ eN3Ikew2bis_000069_000079
1208
+ -MUTGKtPyX0_000063_000073
1209
+ Cc0wpiKhLw0_000024_000034
1210
+ VNXpHy5Tb_U_000064_000074
1211
+ lP45_ktmS1w_000016_000026
1212
+ olX9OOSDY1A_000129_000139
1213
+ r5NqGSZsN0E_000009_000019
1214
+ I44HVnyEKVA_000016_000026
1215
+ 77Yafjbsrn0_000032_000042
1216
+ SLHqXKWlQx4_000030_000040
1217
+ L89FX34lmsI_000053_000063
1218
+ Xyt9EJ5QLQc_000008_000018
1219
+ xrOdt9rrdcM_000003_000013
1220
+ 75XC6l5Mung_000000_000010
1221
+ XoGV-AYJjvo_000042_000052
1222
+ 6NAwC1njhSs_000000_000010
1223
+ qvHzrD45wIM_000181_000191
1224
+ uQRBFQp_i_U_000143_000153
1225
+ iFcUzlgCHcA_000000_000010
1226
+ Z3r5apR3C6Y_000011_000021
1227
+ Th5WqxdXDb0_000007_000017
1228
+ 0OfYCZ3Kiow_000084_000094
1229
+ wbqtzX2Mmc4_000033_000043
1230
+ TaOqyX1yYDM_000177_000187
1231
+ 10VlOsVeZb8_000000_000010
1232
+ UM-rrG3AN14_000000_000010
1233
+ TZ0l4CSYI0Y_000419_000429
1234
+ pQW2gNEHG6U_000035_000045
1235
+ 31Il_bktDaY_000000_000010
1236
+ UKf3QMXSOSs_000000_000010
1237
+ 0OjaGxvpEzo_000026_000036
1238
+ Lgtqpb-9rpY_000001_000011
1239
+ Td5C8t3IjYk_000000_000010
1240
+ Tpv49Chfjks_000077_000087
1241
+ gvTxw3L7qQI_000019_000029
1242
+ Ug5jVJ-9YS4_000002_000012
1243
+ behtgkZntMg_000030_000040
1244
+ LkjbmuyqaL8_000083_000093
1245
+ YFVR5y_EtH8_000049_000059
1246
+ Yv0w8FvXQ-w_000000_000010
1247
+ VgqbAvvnbdc_000040_000050
1248
+ tPL_uVgo9so_000137_000147
1249
+ McNooX_wwF0_000072_000082
1250
+ TEKN8M2clbk_000348_000358
1251
+ lpEa5Qd5utg_000100_000110
1252
+ tEosgxP3KSI_000385_000395
1253
+ l-Sq7PUMnW4_000019_000029
1254
+ lbSUj_faLsA_000010_000020
1255
+ 0mvWamNDkB4_000007_000017
1256
+ f_lSThX3i_A_000025_000035
1257
+ aNN4j-njBes_000009_000019
1258
+ R-BfixOEL68_000011_000021
1259
+ x32aT1LN_AM_000255_000265
1260
+ iBFE2AI4B38_000516_000526
1261
+ B3riQBJYQ4w_000442_000452
1262
+ OqjsXki0Br0_000091_000101
1263
+ CQzUU7-cVck_000006_000016
1264
+ RudqvdVN77k_000001_000011
1265
+ qN7njQDP_bk_000015_000025
1266
+ d38G9PMkHiE_000012_000022
1267
+ SHpIilEOwpg_000014_000024
1268
+ eptncA3-gjY_000012_000022
1269
+ 79SK43KrK-4_000016_000026
1270
+ jWbhG981nUI_000095_000105
1271
+ WFsMi09soZs_000002_000012
1272
+ yCt9X4RGgrA_000091_000101
1273
+ EJLELzXZ2iY_000125_000135
1274
+ l8QnGBveplU_000025_000035
1275
+ 5IPMlxae7TI_000042_000052
1276
+ zsR-xVwn0go_000003_000013
1277
+ kzXmdd6Z8U4_000004_000014
1278
+ -PxRByksLVk_000738_000748
1279
+ E6cnyjaCD3U_000195_000205
1280
+ lrbO88eK9is_000005_000015
1281
+ d1VB1vA-UsI_000003_000013
1282
+ vv8LAxmG-2M_000032_000042
1283
+ b1VygfGIpYg_000163_000173
1284
+ rpqKHNZd2u4_000004_000014
1285
+ 1vsk3D51Otc_000000_000010
1286
+ vALzTXrF5xk_000022_000032
1287
+ whax73x_rh4_000001_000011
1288
+ DLEEYdFodkc_000003_000013
1289
+ TNkot064mgY_000007_000017
1290
+ WQ0Y8NFuaVs_000010_000020
1291
+ yeG8vIrsBzw_000016_000026
1292
+ O2QjdVG53O4_000068_000078
1293
+ TvURKUx1eSQ_000177_000187
1294
+ idS_distWcQ_000066_000076
1295
+ 53Ia-BtpM5A_000002_000012
1296
+ ay4oamtb_Bo_000009_000019
1297
+ 3l8tUCqavPM_000371_000381
1298
+ Kpnd15O9aYE_000013_000023
1299
+ ymjpBYQkadk_000012_000022
1300
+ kmwYoFp51Ww_000153_000163
1301
+ heNARpg9oAg_000069_000079
1302
+ ziyNnkqbuYA_000002_000012
1303
+ YMO199qZ6SA_000182_000192
1304
+ TxqD1yP-Sa4_000000_000010
1305
+ Xkxjo2RtO6k_000036_000046
1306
+ VNulfciEozA_000020_000030
1307
+ OPkDRqy3XoM_000008_000018
1308
+ TMmdYBamtP0_000038_000048
1309
+ iusGKMd54jw_000099_000109
1310
+ F6M8pFiD19E_000269_000279
1311
+ d1x2oWTC06Y_000140_000150
1312
+ 99_8K7ds7u8_000015_000025
1313
+ uxPQEfYNFPk_000014_000024
1314
+ oBWsovXUbbg_000008_000018
1315
+ 36E29x22tnQ_000018_000028
1316
+ tNaFZgjsnck_000046_000056
1317
+ uLzU42YMPLw_000005_000015
1318
+ _HUQYqzmppk_000000_000010
1319
+ d5TYy52mMHk_000006_000016
1320
+ VCOx5pHG3Ho_000267_000277
1321
+ 8qxh1QyYO5s_000026_000036
1322
+ BuZdSvfZvaM_000492_000502
1323
+ u4_AHcoJWX8_000003_000013
1324
+ nba6dbLPKPY_000000_000010
1325
+ 891_hiMUeFI_000026_000036
1326
+ 5dRnwv9ZiG4_000041_000051
1327
+ WU5KZsG_mQk_000483_000493
1328
+ tvl_Jr4ai3M_000193_000203
1329
+ HpnuCO7skxc_000107_000117
1330
+ fSFSMuhmb7E_000001_000011
1331
+ cXsQwIVDsKY_000004_000014
1332
+ VzLuzfd15xY_000019_000029
1333
+ jnTuUuETpSs_000002_000012
1334
+ VLbQ2mlzL_Q_000037_000047
1335
+ K2TDPZ3_N-g_000074_000084
1336
+ E1v-Q_eyAng_000003_000013
1337
+ 1OP0uCl3Awc_000000_000010
1338
+ CieWVgeB-MM_000000_000010
1339
+ 8Z4mPltOS5A_000024_000034
1340
+ _mffV4nn_vY_000018_000028
1341
+ tAn1JD4xFbc_000007_000017
1342
+ FlsunhtRy44_000145_000155
1343
+ -jToAVyxs-g_000046_000056
1344
+ Pxj9gmt4PnM_000000_000010
1345
+ EtZA_L8iH8Y_000279_000289
1346
+ C2C4a3VMJNw_000000_000010
1347
+ M8bk7ZWgQP0_000011_000021
1348
+ 8Za73dZkPSw_000013_000023
1349
+ DtLbnBXrDgs_000001_000011
1350
+ TbleNWZsI4g_000024_000034
1351
+ pmH650EmzaI_000004_000014
1352
+ uPVfS9Ojg_Q_000112_000122
1353
+ 51RYJAVpZQY_000000_000010
1354
+ UPeTYuxFLr0_000464_000474
1355
+ _vMrhrBmDhc_000042_000052
1356
+ ipGBf8JypGA_000278_000288
1357
+ LhzSXvr_Yec_000007_000017
1358
+ x0J0c8qcL1A_000000_000010
1359
+ nsGgsWfY4S8_000001_000011
1360
+ G-L0hmjWScI_000000_000010
1361
+ j6zxxFvT-F0_000015_000025
1362
+ --gEBElruic_000067_000077
1363
+ r9WM1QZcBTM_000031_000041
1364
+ baENtPQwXcQ_000048_000058
1365
+ 0ybnpf_KSwg_000089_000099
1366
+ GWOHr1RViOo_000441_000451
1367
+ OFqqZU0wIP0_000000_000010
1368
+ eanhmmKIolc_000044_000054
1369
+ 7U7-3kO4pik_000012_000022
1370
+ k4JhKErAIcU_000000_000010
1371
+ XB0pZG4b2Ic_000424_000434
1372
+ VPV_NoRxn9Y_000018_000028
1373
+ jN1u2FANVX8_000122_000132
1374
+ C8pn8Fa30N4_000088_000098
1375
+ Uc3dOM6B1z0_000003_000013
1376
+ rm8ir9fmwPs_000089_000099
1377
+ DMNkPedEFtc_000108_000118
1378
+ H20kn210Ge4_000030_000040
1379
+ hMoO-1XY7oI_000000_000010
1380
+ tdHELvi9z7U_000006_000016
1381
+ gSxbTg_EGz4_000046_000056
1382
+ SE5_JeN7g50_000109_000119
1383
+ d87bGTzOOWk_000071_000081
1384
+ vTSO26j_g3E_000006_000016
1385
+ rJBwUrElbkA_000005_000015
1386
+ 1xS5GcVGBVk_000013_000023
1387
+ 0DtaFHAH_bY_000000_000010
1388
+ xeoH1CgrGNo_000000_000010
1389
+ tFtVI4BP_Jg_000000_000010
1390
+ 8Zody4_Ouos_000000_000010
1391
+ 08qD_jd4qLY_000066_000076
1392
+ PCQVd8rmprg_000020_000030
1393
+ 7UACcUm3y1g_000006_000016
1394
+ d6fdMPKYVK0_000285_000295
1395
+ bAar9lhU3-U_000031_000041
1396
+ A9_HJgc-Fy4_000012_000022
1397
+ XuQ16JZ_OX4_000001_000011
1398
+ E14H_dK-fTY_000042_000052
1399
+ H8WWknTZUmA_000016_000026
1400
+ h6L6_CGk284_000007_000017
1401
+ eA1h7zbg9lM_000004_000014
1402
+ po5wMUhcWug_000050_000060
1403
+ OMK0OJ4f_TI_000000_000010
1404
+ hbPpPCe6ou8_000038_000048
1405
+ bxxK9LLquRs_000016_000026
1406
+ EFiV66yJqpM_000205_000215
1407
+ 9Ih3vgHzc-o_000000_000010
1408
+ RanVrk-mUsc_000142_000152
1409
+ JCVQcNTQS2M_000036_000046
1410
+ 19zOVnkSOeM_000000_000010
1411
+ LSLzeVlyYAU_000029_000039
1412
+ 1uZK-W4S6Is_000000_000010
1413
+ VkJHlcbwmIs_000129_000139
1414
+ 7l20ds7nvA8_002870_002880
1415
+ lsuyMZWr_Nw_000042_000052
1416
+ vcX_JOjjHGE_000003_000013
1417
+ PgyV1sylw4o_000007_000017
1418
+ cr7f5GBtVTI_000069_000079
1419
+ tEhoqyS5vVc_000234_000244
1420
+ 2DNwbwWhYgA_000033_000043
1421
+ 77IRHMWRjwM_000010_000020
1422
+ DKqPSRSDPBk_000074_000084
1423
+ ch8PWd0CUwc_000415_000425
1424
+ cExTd4JuSrQ_000040_000050
1425
+ d6_XQqZIO98_000087_000097
1426
+ Nkwq2Jp2WaA_000110_000120
1427
+ YLHPbG4pe-g_000038_000048
1428
+ b-rcZkrdtl8_000043_000053
1429
+ L91CNH1RgvI_000002_000012
1430
+ Y1NEWHZywDM_000008_000018
1431
+ LaGwOQvYY0s_000179_000189
1432
+ iYH2ZfbMy-I_000142_000152
1433
+ bbu7lxDJ3_A_000001_000011
1434
+ iEBq_VR_JSE_003800_003810
1435
+ ill9sZOMQtE_000000_000010
1436
+ HncTHpgDDoc_000105_000115
1437
+ REhRcS9YrzM_000019_000029
1438
+ NbZITwhH46E_000079_000089
1439
+ 3Kaledle0Jw_000040_000050
1440
+ ysXgEIDm3nY_000045_000055
1441
+ e47kpEV6afo_000000_000010
1442
+ 2bRXcLakTZQ_000002_000012
1443
+ OCJCwHZU31A_000009_000019
1444
+ M2JvulLtG40_000012_000022
1445
+ By1lQRot9eo_000035_000045
1446
+ S9nCwjMbbDk_000068_000078
1447
+ jablL-kz594_000010_000020
1448
+ 5Odj7n4_P-I_000015_000025
1449
+ zg_P56oZJEc_000000_000010
1450
+ rJokQsBf1as_000077_000087
1451
+ -abgu7xMKe8_000151_000161
1452
+ G9zN5TTuGO4_000179_000189
1453
+ 4nRvHwt1Qkw_000002_000012
1454
+ o08RX_saVBk_000025_000035
1455
+ 3jx36HklC_Y_000067_000077
1456
+ 9c7mU3hyLLw_000000_000010
1457
+ eoGt3l3BZ7w_000163_000173
1458
+ -uayIf2Y92U_000036_000046
1459
+ 1iX9rmvzOHI_000039_000049
1460
+ 4rf7LdbwgTg_000086_000096
1461
+ wHQ5wF3oJoo_000057_000067
1462
+ 0FuVWCWL1n4_000018_000028
1463
+ X3JvaX1DYd0_000036_000046
1464
+ hkLWjpndOoQ_000018_000028
1465
+ VHVZ22Sv_fY_000013_000023
1466
+ IH7SR20aCuU_000089_000099
1467
+ tSFY2jfmdt8_000028_000038
1468
+ uxl6HFwuWEo_000358_000368
1469
+ apjEvOG8-Zo_000039_000049
1470
+ Iv0XyMqrnw8_000115_000125
1471
+ wObc9HsS3Ls_000038_000048
1472
+ vv1cVGVcelc_000007_000017
1473
+ vuPuOn_Dkm0_000124_000134
1474
+ U4lBS3FWvC0_000111_000121
1475
+ giUxmMn8Nfs_000129_000139
1476
+ BdmLB7IdGrk_000004_000014
1477
+ 6FiNye9H70M_000000_000010
1478
+ R5NmJB0lGmI_000010_000020
1479
+ j-AUhHY-9nE_000001_000011
1480
+ n2zPcPtF78o_000009_000019
1481
+ MaaKJZ6AvY8_000056_000066
1482
+ 6KbcDK8XE38_000035_000045
1483
+ eqK9gnEV8Y8_000156_000166
1484
+ w0axq1_jyCs_000008_000018
1485
+ UQP8kz5kAKg_000021_000031
1486
+ E6cLsQqwcbQ_000040_000050
1487
+ 5JJV_r6zLlM_000028_000038
1488
+ P0khQxBYXFE_000040_000050
1489
+ GJmfSgkvH7o_000019_000029
1490
+ S2Mkf6NTrM4_000022_000032
1491
+ 68UzWy9hgVE_000075_000085
1492
+ -0cIpwdV-DU_000722_000732
1493
+ VGMx_RsSBn4_000085_000095
1494
+ 4vv-m4xCVbc_000196_000206
1495
+ QgFNh6Bx0Xs_000047_000057
1496
+ HyThLeZVMy8_000004_000014
1497
+ aJxa7KNArB4_000096_000106
1498
+ cgmM6SyvIhA_000049_000059
1499
+ FEJFDsPci1o_000135_000145
1500
+ 9epLyjhQonM_000401_000411
util.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import threading
4
+ from torch._utils import ExceptionWrapper
5
+ import logging
6
+ import torch.nn.functional as F
7
+
8
+ def get_a_var(obj):
9
+ if isinstance(obj, torch.Tensor):
10
+ return obj
11
+
12
+ if isinstance(obj, list) or isinstance(obj, tuple):
13
+ for result in map(get_a_var, obj):
14
+ if isinstance(result, torch.Tensor):
15
+ return result
16
+ if isinstance(obj, dict):
17
+ for result in map(get_a_var, obj.items()):
18
+ if isinstance(result, torch.Tensor):
19
+ return result
20
+ return None
21
+
22
+
23
+ def parallel_apply(fct, model, inputs, device_ids):
24
+ modules = nn.parallel.replicate(model, device_ids)
25
+ assert len(modules) == len(inputs)
26
+ lock = threading.Lock()
27
+ results = {}
28
+ grad_enabled = torch.is_grad_enabled()
29
+
30
+ def _worker(i, module, input):
31
+ torch.set_grad_enabled(grad_enabled)
32
+ device = get_a_var(input).get_device()
33
+ try:
34
+ with torch.cuda.device(device):
35
+ # this also avoids accidental slicing of `input` if it is a Tensor
36
+ if not isinstance(input, (list, tuple)):
37
+ input = (input,)
38
+ output = fct(module, *input)
39
+ with lock:
40
+ results[i] = output
41
+ except Exception:
42
+ with lock:
43
+ results[i] = ExceptionWrapper(where="in replica {} on device {}".format(i, device))
44
+
45
+ if len(modules) > 1:
46
+ threads = [threading.Thread(target=_worker, args=(i, module, input))
47
+ for i, (module, input) in enumerate(zip(modules, inputs))]
48
+
49
+ for thread in threads:
50
+ thread.start()
51
+ for thread in threads:
52
+ thread.join()
53
+ else:
54
+ _worker(0, modules[0], inputs[0])
55
+
56
+ outputs = []
57
+ for i in range(len(inputs)):
58
+ output = results[i]
59
+ if isinstance(output, ExceptionWrapper):
60
+ output.reraise()
61
+ outputs.append(output)
62
+ return outputs
63
+
64
+ def get_logger(filename=None):
65
+ logger = logging.getLogger('logger')
66
+ logger.setLevel(logging.DEBUG)
67
+ logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s',
68
+ datefmt='%m/%d/%Y %H:%M:%S',
69
+ level=logging.INFO)
70
+ if filename is not None:
71
+ handler = logging.FileHandler(filename)
72
+ handler.setLevel(logging.DEBUG)
73
+ handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s: %(message)s'))
74
+ logging.getLogger().addHandler(handler)
75
+ return logger