Spaces:
Runtime error
Runtime error
| import torch | |
| import math | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from transformers import BertTokenizer | |
| from transformers.models.bert.modeling_bert import BertLMHeadModel as BertLMHeadModelRaw | |
| from .qformer import BertConfig | |
| from .qformer import BertLMHeadModel as BertLMHeadModelQF | |
| class VlmAttention(nn.Module): | |
| def __init__(self, model_args, vision_tower): | |
| super().__init__() | |
| pretrain_mm_mlp_adapter = getattr(model_args, "pretrain_mm_mlp_adapter", None) | |
| pretrain_qformer = getattr(model_args, "mm_vlmattention_pretrained", None) | |
| self.bert_type = getattr(model_args, "mm_vlmattention_bert_type", "qformer") | |
| self.num_query = getattr(model_args, "mm_vlmattention_num_query", 32) | |
| self.compress_type = getattr(model_args, "mm_vlmattention_compress_type", None) | |
| self.mm_hidden_size = self.hidden_size = vision_tower.hidden_size | |
| self.mm_vision_select_feature = model_args.mm_vision_select_feature | |
| self.language_hidden_size = 4096 | |
| for_eval = True | |
| if 'pretrain' in self.bert_type: | |
| # for qformer that use evaclip for prtrain | |
| att_feat_size = 1408 | |
| else: | |
| att_feat_size = self.mm_hidden_size | |
| self.vlm_att_tokenlizer, self.vlm_att_encoder, self.vlm_att_query = self.init_bert(att_feat_size, truncation_side="left") | |
| self.vlm_att_projector = torch.nn.Linear(self.vlm_att_encoder.config.hidden_size, self.mm_hidden_size) | |
| self.vlm_att_key_projector = torch.nn.Linear(self.mm_hidden_size, self.mm_hidden_size) | |
| self.vlm_att_val_projector = torch.nn.Linear(self.mm_hidden_size, self.language_hidden_size) | |
| if "raw" in self.bert_type: | |
| self.vlm_att_bert_proj = torch.nn.Linear(att_feat_size, self.vlm_att_encoder.config.hidden_size) | |
| elif "pretrain" in self.bert_type and self.mm_hidden_size!=att_feat_size: | |
| self.vlm_att_bert_proj = torch.nn.Linear(self.mm_hidden_size, att_feat_size) | |
| else: | |
| self.vlm_att_bert_proj = None | |
| def get_w(weights, keyword): | |
| return {k.split(keyword + '.')[1]: v for k, v in weights.items() if keyword in k} | |
| if 'qformer_pretrain' in self.bert_type: | |
| self.vlm_att_ln = torch.nn.LayerNorm(att_feat_size) | |
| if pretrain_qformer is not None: | |
| print("Loading pretrained qformer weights...") | |
| qformer_weight = torch.load(pretrain_qformer, map_location='cpu')['model'] | |
| bert_weight = {_key: qformer_weight[_key] for _key in qformer_weight if 'bert' in _key} | |
| self.vlm_att_encoder.load_state_dict(get_w(bert_weight, 'Qformer')) | |
| self.vlm_att_ln.load_state_dict(get_w(qformer_weight, 'ln_vision')) | |
| self.vlm_att_query.data = qformer_weight['query_tokens'] | |
| if 'freeze_all' in self.bert_type: | |
| print("Freezing all qformer weights...") | |
| self.vlm_att_encoder.requires_grad_(False) | |
| self.vlm_att_ln.requires_grad_(False) | |
| self.vlm_att_query.requires_grad_(False) | |
| self.vlm_att_projector.requires_grad_(False) | |
| self.vlm_att_key_projector.requires_grad_(False) | |
| self.vlm_att_val_projector.requires_grad_(False) | |
| elif 'freeze' in self.bert_type: | |
| print("Freezing pretrained qformer weights...") | |
| self.vlm_att_encoder.requires_grad_(False) | |
| self.vlm_att_ln.requires_grad_(False) | |
| self.vlm_att_query.requires_grad_(False) | |
| if pretrain_mm_mlp_adapter is not None: | |
| att_projector_weights = torch.load(pretrain_mm_mlp_adapter, map_location='cpu') | |
| else: | |
| trainable_module = ['vlm_att_encoder', 'vlm_att_projector', 'vlm_att_key_projector', | |
| 'vlm_att_val_projector', 'vlm_att_query', 'vlm_att_visual_proj', | |
| 'vlm_att_ln'] | |
| if hasattr(model_args, 'model_name_or_path'): | |
| model_save_path = model_args.model_name_or_path | |
| else: | |
| model_save_path = model_args.model_path | |
| model_idx_path = getattr(model_args, 'model_path', model_save_path) | |
| weight_file = json.load(open(os.path.join(model_idx_path, 'pytorch_model.bin.index.json'), 'r'))['weight_map'] | |
| model_path = set([weight_file[_key] for _key in weight_file if any([_module in _key for _module in trainable_module])]) | |
| att_projector_weights = {} | |
| for _model in model_path: | |
| att_projector_weights.update(torch.load(os.path.join(model_idx_path, _model), map_location='cpu')) | |
| if len(att_projector_weights) == 0: | |
| return | |
| bert_dict = get_w(att_projector_weights, 'vlm_att_encoder') | |
| if "bert.embeddings.position_ids" not in bert_dict and "raw_bert" not in self.bert_type: | |
| bert_dict["bert.embeddings.position_ids"] = self.vlm_att_encoder.bert.embeddings.position_ids | |
| print('Loading pretrained weights...') | |
| # import pdb;pdb.set_trace() | |
| self.vlm_att_encoder.load_state_dict(bert_dict) | |
| self.vlm_att_projector.load_state_dict(get_w(att_projector_weights, 'vlm_att_projector')) | |
| self.vlm_att_key_projector.load_state_dict(get_w(att_projector_weights, 'vlm_att_key_projector')) | |
| self.vlm_att_val_projector.load_state_dict(get_w(att_projector_weights, 'vlm_att_val_projector')) | |
| if "qformer" in self.bert_type: | |
| print('Loading vlm_att_query weights...') | |
| self.vlm_att_query.data = att_projector_weights['model.vlm_att_query'] | |
| if "pretrain" in self.bert_type: | |
| print('Loading vlm_att_ln weights...') | |
| self.vlm_att_ln.load_state_dict(get_w(att_projector_weights, 'vlm_att_ln')) | |
| if self.vlm_att_bert_proj is not None: | |
| print('Loading vlm_att_bert_proj weights...') | |
| self.vlm_att_bert_proj.load_state_dict(get_w(att_projector_weights, 'vlm_att_bert_proj')) | |
| if for_eval: | |
| weight_type = torch.float16 | |
| # import pdb;pdb.set_trace() | |
| # device_type = self.mm_projector[0].weight.device | |
| device_type = vision_tower.vision_tower.patch_embed.proj.weight.device | |
| self.vlm_att_encoder = self.vlm_att_encoder.to(device=device_type, dtype=weight_type) | |
| self.vlm_att_projector = self.vlm_att_projector.to(device=device_type, dtype=weight_type) | |
| self.vlm_att_key_projector = self.vlm_att_key_projector.to(device=device_type, dtype=weight_type) | |
| self.vlm_att_val_projector = self.vlm_att_val_projector.to(device=device_type, dtype=weight_type) | |
| if "qformer" in self.bert_type: | |
| self.vlm_att_query.data = self.vlm_att_query.data.to(device=device_type, dtype=weight_type) | |
| if "pretrain" in self.bert_type: | |
| self.vlm_att_ln = self.vlm_att_ln.to(device=device_type, dtype=weight_type) | |
| if self.vlm_att_bert_proj is not None: | |
| self.vlm_att_bert_proj = self.vlm_att_bert_proj.to(device=device_type, dtype=weight_type) | |
| def forward(self, image_features, prompts=None, image_counts=None, long_video=False): | |
| img_feat_lst = [] | |
| # import pdb;pdb.set_trace() | |
| if image_counts is None: | |
| assert len(image_features) == len(prompts), f"Size mismatch! image_features: {len(image_features)}, prompts: {len(prompts)}" | |
| else: | |
| assert len(prompts) == len(image_counts), f"Size mismatch! prompts: {len(prompts)}, image_counts: {len(image_counts)}" | |
| image_atts = torch.ones(image_features.size()[:-1], dtype=torch.long).to(image_features.device) | |
| total_count = 0 | |
| # calculate each image feat according to the prompt | |
| # import pdb;pdb.set_trace() | |
| for _idx in range(len(prompts)): | |
| assert isinstance(prompts[_idx], list), f"Prompt should be a list, but got {type(prompts[_idx])}" | |
| input_token = self.vlm_att_tokenlizer( | |
| prompts[_idx], | |
| padding='longest', | |
| truncation=True, | |
| max_length=256, | |
| return_tensors="pt" | |
| ).to(image_features.device) | |
| input_ids = input_token.input_ids | |
| attention_masks = input_token.attention_mask | |
| if image_counts is None: | |
| img_feat_prompt = image_features[_idx, None].expand(len(prompts[_idx]), -1, -1) | |
| img_att_prompt = image_atts[_idx, None].expand(len(prompts[_idx]), -1) | |
| else: | |
| # shape: [prompt_num*frame_num, image_shape, feat_dim] | |
| img_feat_prompt = image_features[total_count:total_count+image_counts[_idx]] | |
| img_feat_prompt = img_feat_prompt[None].expand(len(prompts[_idx]), -1, -1, -1).flatten(0,1) | |
| img_att_prompt = image_atts[total_count:total_count+image_counts[_idx]] | |
| img_att_prompt = img_att_prompt[None].expand(len(prompts[_idx]), -1, -1).flatten(0,1) | |
| input_ids = input_ids[:,None].expand(-1, image_counts[_idx], -1).flatten(0,1) | |
| attention_masks = attention_masks[:,None].expand(-1, image_counts[_idx], -1).flatten(0,1) | |
| total_count += image_counts[_idx] | |
| if "pretrain" in self.bert_type and self.vlm_att_bert_proj is not None: | |
| bert_feat = self.vlm_att_bert_proj(img_feat_prompt) | |
| else: | |
| bert_feat = img_feat_prompt.clone() | |
| # remove cls embedding | |
| if self.mm_vision_select_feature == 'patch': | |
| if img_feat_prompt.shape[1]%2 == 1: | |
| img_feat_prompt = img_feat_prompt[:, 1:] | |
| if "qformer" in self.bert_type: | |
| query_tokens = self.vlm_att_query.expand(bert_feat.shape[0], -1, -1) | |
| query_atts = torch.cat([torch.ones(query_tokens.size()[:-1], dtype=torch.long).to(bert_feat.device), | |
| attention_masks],dim=1) | |
| if 'pretrain' in self.bert_type: | |
| mm_img_in = self.vlm_att_ln(bert_feat) | |
| else: | |
| mm_img_in = bert_feat | |
| if long_video: | |
| outputs = [] | |
| block_size = 64 | |
| for L in range(0, len(input_ids), block_size): | |
| R = L + block_size | |
| mm_output = self.vlm_att_encoder.bert( | |
| input_ids[L:R], | |
| query_embeds=query_tokens[L:R], | |
| attention_mask=query_atts[L:R], | |
| encoder_hidden_states=mm_img_in[L:R], | |
| encoder_attention_mask=img_att_prompt[L:R], | |
| return_dict=True, | |
| ) | |
| mm_output = mm_output.last_hidden_state[:,:query_tokens.shape[1]] | |
| outputs.append(mm_output) | |
| mm_output = torch.cat(outputs) | |
| torch.cuda.empty_cache() | |
| else: | |
| mm_output = self.vlm_att_encoder.bert( | |
| input_ids, | |
| query_embeds=query_tokens, | |
| attention_mask=query_atts, | |
| encoder_hidden_states=mm_img_in, | |
| encoder_attention_mask=img_att_prompt, | |
| return_dict=True, | |
| ) | |
| mm_output = mm_output.last_hidden_state[:,:query_tokens.shape[1]] | |
| elif "raw" in self.bert_type: | |
| if self.mm_vision_select_feature == 'patch' and bert_feat.shape[1]%2 == 1: | |
| bert_feat = bert_feat[:, 1:] | |
| img_att_prompt = img_att_prompt[:, 1:] | |
| mm_output = self.vlm_att_encoder.bert( | |
| input_ids, | |
| attention_mask=attention_masks, | |
| encoder_hidden_states=self.vlm_att_bert_proj(bert_feat), | |
| encoder_attention_mask=img_att_prompt, | |
| return_dict=True, | |
| ) | |
| mm_output = mm_output.last_hidden_state | |
| else: | |
| raise ValueError(f'Unexpected bert type: {self.bert_type}') | |
| text_q = self.vlm_att_projector(mm_output) | |
| # shape: [prompt_num*frame_num, feat_dim] | |
| # ctx_embed,vis_embed = self.token_generation(text_q, img_feat_prompt, long_video=long_video) | |
| final_token = self.token_generation(text_q, img_feat_prompt, long_video=long_video) | |
| if image_counts is not None: | |
| # shape: [prompt_num, frame_num*image_shape, feat_dim] | |
| final_token = final_token.reshape(len(prompts[_idx]), image_counts[_idx], *final_token.shape[-2:]) | |
| final_token = final_token.flatten(1,2) | |
| img_feat_lst.append(final_token) | |
| return img_feat_lst | |
| def init_bert(self, vision_width, cross_attention_freq=2, truncation_side="right"): | |
| # initialize BERT tokenizer | |
| tokenizer = BertTokenizer.from_pretrained("bert-base-uncased", truncation_side=truncation_side) | |
| tokenizer.add_special_tokens({"bos_token": "[DEC]"}) | |
| # initialize BERT | |
| encoder_config = BertConfig.from_pretrained("bert-base-uncased") | |
| encoder_config.encoder_width = vision_width | |
| # insert cross-attention layer every other block | |
| encoder_config.add_cross_attention = True | |
| encoder_config.cross_attention_freq = cross_attention_freq | |
| query_tokens = None | |
| if "qformer" in self.bert_type: | |
| mm_model = BertLMHeadModelQF.from_pretrained( | |
| "bert-base-uncased", config=encoder_config | |
| ) | |
| query_tokens = nn.Parameter( | |
| torch.zeros(1, self.num_query, encoder_config.hidden_size) | |
| ) | |
| query_tokens.data.normal_(mean=0.0, std=encoder_config.initializer_range) | |
| elif "raw" in self.bert_type: | |
| encoder_config.is_decoder = True | |
| mm_model = BertLMHeadModelRaw.from_pretrained( | |
| "bert-base-uncased", config=encoder_config | |
| ) | |
| else: | |
| raise NotImplementedError("BERT type not implemented...") | |
| mm_model.resize_token_embeddings(len(tokenizer)) | |
| mm_model.cls = None | |
| if "layer" in self.bert_type: | |
| layer_num = int(self.bert_type.split(':')[-1]) | |
| mm_model.bert.encoder.layer = mm_model.bert.encoder.layer[:layer_num] | |
| print(f"Only use {layer_num} layers in BERT...") | |
| return tokenizer, mm_model, query_tokens | |
| def token_generation(self, text_q, vis_embed, long_video=False): | |
| ctx_embed = self.vlm_att_key_projector(vis_embed) | |
| # Key part 1: calculate context-related embedding | |
| ctx_embed = text_q @ ctx_embed.transpose(-1,-2) | |
| ctx_embed = ctx_embed / (vis_embed.shape[-1] ** 0.5) | |
| if not long_video: | |
| ctx_embed = (ctx_embed.softmax(-1) @ vis_embed).mean(1) | |
| else: | |
| block_size = 64 | |
| outputs = [] | |
| ctx_score = ctx_embed.softmax(-1) | |
| for L in range(0, len(ctx_score), block_size): | |
| R = L + block_size | |
| sub_embed = (ctx_score[L:R] @ vis_embed[L:R]).mean(1) | |
| outputs.append(sub_embed) | |
| ctx_embed = torch.cat(outputs) | |
| torch.cuda.empty_cache() | |
| ctx_embed = self.vlm_att_val_projector(ctx_embed[:,None]) | |
| # Key part 2: calculate visual embedding | |
| if self.compress_type is not None: | |
| if 'grid' in self.compress_type: | |
| grid_size = int(self.compress_type.split('grid:')[-1]) | |
| cur_shape = int(vis_embed.shape[1]**0.5) | |
| assert grid_size > 1, f'Grid size should be larger than 1, but got {grid_size}' | |
| vis_embed = vis_embed.reshape(vis_embed.shape[0], cur_shape, cur_shape, -1) | |
| grid_stride = cur_shape // grid_size | |
| vis_embed = F.avg_pool2d(vis_embed.permute(0, 3, 1, 2), | |
| padding=0, | |
| kernel_size=grid_stride, | |
| stride=grid_stride) | |
| vis_embed = vis_embed.permute(0, 2, 3, 1).flatten(1,2) | |
| elif 'mean' in self.compress_type: | |
| # import pdb;pdb.set_trace() | |
| vis_embed = vis_embed.mean(dim=1, keepdim=True) | |
| # import pdb ; pdb.set_trace() | |
| # concat token in shape (B, n+1, C) | |
| vis_embed = self.mm_projector(vis_embed) | |
| final_token = torch.cat([ctx_embed, vis_embed], dim=1) | |
| return final_token | |
| def config(self): | |
| return { | |
| 'mm_resampler_type': 'vlm_attention', | |
| 'mm_vlmattention_bert_type': self.bert_type, | |
| 'mm_vlmattention_num_query': self.num_query, | |
| 'mm_vlmattention_compress_type': self.compress_type, | |
| } | |