Spaces:
Runtime error
Runtime error
cheetah003
commited on
Commit
•
29c5a57
1
Parent(s):
b352512
first commit
Browse filesinitial version
- features/Chinese_batch_frame_output_list.npy +3 -0
- features/Chinese_batch_visual_output_list.npy +3 -0
- features/English_batch_frame_output_list.npy +3 -0
- features/English_batch_visual_output_list.npy +3 -0
- main_task_retrieval.py +639 -0
- models/Chinese_vatex.bin +3 -0
- models/English_vatex.bin +3 -0
- modules/__init__.py +1 -0
- modules/__pycache__/__init__.cpython-37.pyc +0 -0
- modules/__pycache__/file_utils.cpython-37.pyc +0 -0
- modules/__pycache__/modeling.cpython-37.pyc +0 -0
- modules/__pycache__/module_clip.cpython-37.pyc +0 -0
- modules/__pycache__/module_cross.cpython-37.pyc +0 -0
- modules/__pycache__/tokenization_clip.cpython-37.pyc +0 -0
- modules/__pycache__/until_config.cpython-37.pyc +0 -0
- modules/__pycache__/until_module.cpython-37.pyc +0 -0
- modules/bpe_simple_vocab_16e6.txt +0 -0
- modules/bpe_simple_vocab_16e6.txt.gz +3 -0
- modules/cross-base/bert_base_6layer_6conect.json +30 -0
- modules/cross-base/cross_config.json +18 -0
- modules/file_utils.py +239 -0
- modules/modeling.py +507 -0
- modules/module_clip.py +579 -0
- modules/module_cross.py +356 -0
- modules/optimization.py +168 -0
- modules/tokenization_clip.py +152 -0
- modules/until_config.py +126 -0
- modules/until_module.py +295 -0
- search.py +299 -0
- test_list.txt +1500 -0
- util.py +75 -0
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
|