在实际大模型落地中,需要大模型支持实际给出对应目标检测物的坐标输出能力,在原生基座模型中这个能力很少体现,经过了一些实验,简单记录一下从输入图像的数学表示开始,经过视觉编码、模态对齐、语言模型推理,直至最终坐标解码的完整数学推导过程。
基于Qwen2-VL的训练过程,本文提出了一种坐标敏感的加权损失函数(Coordinate-Aware Weighted Loss),以提升模型对边界框预测的精确度。
我将目标检测任务建模为基于视觉条件的自回归文本生成任务。
给定输入图像
序列
为了将连续的坐标回归问题转化为离散的 Token 分类问题,我们采用了
设原始图像宽为
模型直接预测这些量化后的整数 Token。
标准的语言模型微调通常使用交叉熵损失(Cross-Entropy Loss)。对于长度为
其中
在目标检测任务中,坐标 Token 的准确性远比普通文本 Token(如停用词、标点符号)重要。标准的平均损失会导致模型在大量普通文本上的梯度稀释了对坐标预测的优化。
为此,我们引入了一个时间步相关的权重函数
其中权重函数
在我们的实现中,我们将坐标权重的超参数设为
在数据整理器(Data Collator)中动态构建权重掩码矩阵 input_ids 一致。
实现逻辑如下:
初始化:创建一个全为 1 的掩码张量 loss_weight_mask。
屏蔽提示词:将用户输入的 Prompt 部分的 Label 设为 -100(PyTorch 默认忽略索引),权重设为 0。
坐标增强:
扫描 Token 序列,定位 <|box_2d|> (Start) 和 <|object_ref|> (End) 特殊 Token 的位置索引。
设 <|box_2d|> 的结束位置为 <|object_ref|> 的开始位置为
对区间
x# 伪代码逻辑loss_weight_mask = torch.ones_like(labels)COORD_WEIGHT = 2.0
for batch_idx in range(batch_size): # 定位坐标区间 intervals = find_coordinate_intervals(input_ids[batch_idx]) for (start, end) in intervals: loss_weight_mask[batch_idx, start:end] = COORD_WEIGHT我继承了 Hugging Face 的 Trainer 并重写了 compute_loss 方法,以支持逐元素的加权计算:
xxxxxxxxxxclass WeightedLossTrainer(Trainer): def compute_loss(self, model, inputs, ...): # 1. 获取模型输出 Logits outputs = model(**inputs) logits = outputs.get("logits") # 2. 获取预先计算好的权重掩码 loss_weight_mask = inputs.get("loss_weight_mask") # 3. 计算未归约的 CrossEntropyLoss (reduction='none') loss_fct = nn.CrossEntropyLoss(reduction='none') loss = loss_fct(shift_logits, shift_labels) # 4. 应用权重 if loss_weight_mask is not None: loss = loss * shift_mask # 5. 返回平均损失 return loss.mean()通过这种数学上的加权策略,梯度下降(Gradient Descent)过程发生了如下变化:
由于坐标 Token 的