Safetensors
mhassanch's picture
Add GeoText inference endpoint support
4d3c316
Raw History Blame Contribute Delete
7.43 kB
import itertools
import torch
from models import XVLMBase, load_pretrained
class BBoxCollector:
# ... [与之前的BBoxCollector定义相同] ...
# 记得在calculate_loss()返回spatial_loss时,你可能需要进行相应的调整以确保其正确返回。
def __init__(self):
self.collect_bbox = []
self.current_num = None
def update_bbox(self, bbox_info):
new_num = bbox_info['num']
# 情况1
if not self.collect_bbox:
self.collect_bbox.append(bbox_info)
self.current_num = new_num
return
# 情况2
if len(self.collect_bbox) == 1:
if new_num == self.current_num:
self.collect_bbox.append(bbox_info)
return
else:
# 排出旧的bbox
self.collect_bbox = [bbox_info]
self.current_num = new_num
return
if len(self.collect_bbox) == 2:
if new_num == self.current_num:
self.calculate_loss(self.collect_bbox)
self.collect_bbox = [] # 清空
self.collect_bbox.append(bbox_info)
else:
self.calculate_loss(self.collect_bbox)
self.collect_bbox = [] # 清空
self.collect_bbox.append(bbox_info)
self.current_num = new_num
def calculate_loss(self, bboxes):
permutations = list(itertools.permutations(bboxes, 2))
for pair in permutations:
target_bbox_A = pair[0]['bbox']
target_bbox_B = pair[1]['bbox']
sen_token_A = pair[0]['text_token']
sen_embeds_A = pair[0]['text_embeds']
sen_token_B = pair[1]['text_token']
sen_embeds_B = pair[1]['text_embeds']
feature_map = pair[0]['image_feature_map'] # 仅使用第一个bbox的feature map,您可能需要进行相应的调整
target_ids = compute_rela(target_bbox_A, target_bbox_B)
spatial_loss = self.get_spatial_relation_loss(sen_token_A, sen_embeds_A, sen_token_B, sen_embeds_B, target_bbox_A, target_bbox_B, feature_map, target_ids)
print("Calculated spatial loss:", spatial_loss)
def compute_rela(bbox1, bbox2):
x1, y1, w1, h1 = bbox1
x2, y2, w2, h2 = bbox2
len_x = x1 - x2
a_len_x = abs(len_x)
len_y = y1 - y2
a_len_y = abs(len_y)
if a_len_x < 0.5 * w1:
if len_y > 0:
return torch.tensor([0, -1])
if len_y < 0:
return torch.tensor([0, 1])
else:
if len_x > 0:
if a_len_y < 0.5 * h1:
return torch.tensor([-1, 0])
else:
if len_y > 0:
return torch.tensor([-1, -1])
else:
return torch.tensor([-1, 1])
if len_x < 0:
if a_len_y < 0.5 * h1:
return torch.tensor([1, 0])
else:
if len_y > 0:
return torch.tensor([1, -1])
else:
return torch.tensor([1, 1])
class XVLM(XVLMBase):
def __init__(self, config):
super().__init__(config, load_vision_params=False, load_text_params=False,
use_contrastive_loss=True, use_matching_loss=True, use_mlm_loss=False, use_bbox_loss=True)
self.num_attention_heads = self.text_encoder.config.num_attention_heads
self.init_params = []
def load_pretrained(self, ckpt_rpath, config, is_eval=False):
state_dict = load_pretrained(ckpt_rpath, config, is_eval=is_eval, load_text=True)
msg = self.load_state_dict(state_dict, strict=False)
print('load checkpoint from %s' % ckpt_rpath)
print("missing_keys: ", [p for p in msg.missing_keys if 'vision_encoder' not in p])
print("unexpected_keys: ", msg.unexpected_keys)
def forward(self, image, text_ids, text_atts, idx=None, pair=None):
# print("Note: This part is in the model process!")
# print(f"Here is the model {idx} image: {image}")
# print(f'Here is the model {idx} text_ids:{text_ids}')
# print(f'Here is the model {idx} text_atts:{text_atts}')
# print(f'Here is the model {idx} pair:{pair}')
image_embeds, image_atts = self.get_vision_embeds(image)
# print('Here is the image_embeding size')
# print(image_embeds.size(0))
text_embeds = self.get_text_embeds(text_ids, text_atts)
# output_coord & target_bbox: 64, 4
image_feat, text_feat = self.get_features(image_embeds, text_embeds)
loss_itc = self.get_contrastive_loss(image_feat, text_feat, idx=idx)
loss_itm = self.get_matching_loss(image_embeds, image_atts, image_feat, text_embeds, text_atts, text_feat, idx=idx)
# print(f'loss_itc is {loss_itc}, loss_itm is {loss_itm}')
n = len(pair)
# print(f"the length of the pair is:{n}")
if n == 0:
# loss_bb = -100
return loss_itc, loss_itm
else:
total_spatial_loss = 0.0 # 用于累积空间关系损失
loss_count = 0 # 用于记录计算出的空间关系损失的数量
for i in range(n):
loss_bb = 0
repeat_image = 0
num = pair[i][0]
new = image[num].unsqueeze(0)
image_embeds, _ = self.get_vision_embeds(new)
vis = self.vision_encoder.forward(new,feature_map=12)
feature_map = vis.permute(0,3,1,2)
sen_token = pair[i][1]
sen_embeds = self.get_text_embeds(sen_token.input_ids, sen_token.attention_mask)
print(f'Here is the number{pair[i][0]}')
# print(sen_embeds.size(0))
# print(image_embeds.size(0))
output_coord = self.predict_bbox(image_embeds, sen_embeds, sen_token.attention_mask)
# print('let us see the pair')
# print(pair[i][2])
# print(pair[i][2].size())
# print(output_coord)
# print(output_coord.size())
loss_bbox, loss_giou = self.get_bbox_loss(output_coord, pair[i][2].unsqueeze(0))
loss_bb += (loss_bbox + loss_giou)
# Update the BBoxCollector with the current bbox information from the pair
bbox_info = {
'text_token': pair[i][1], # assuming this is sen_embeds
'text_embeds': pair[i][1], # assuming this is sen_embeds
'bbox': pair[i][2], # bbox
'image_feature_map': feature_map,
'num': pair[i][0] # num
}
spatial_loss = self.bbox_collector.update_bbox(bbox_info)
if spatial_loss is not None: # 如果计算出了空间关系损失
total_spatial_loss += spatial_loss
loss_count += 1
if loss_count > 0:
average_spatial_loss = total_spatial_loss / loss_count
else:
average_spatial_loss = 0.0
# print(f"loss_bb is {loss_bb}")
loss_bb = loss_bb/n
# print(f"loss_bb is {loss_bb}")
return loss_itc, loss_itm, loss_bb