You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

批量样本形状不同时如何计算损失?

解决不同形状损失张量的训练问题

问题核心在于每个样本的有效损失元素数量不同,直接堆叠会报错,而单样本取均值再平均会因样本权重失衡导致泛化差。正确的做法是收集所有样本的有效损失元素,再计算全局均值,让每个损失元素的权重一致。

修改方案

1. 调整训练函数中的损失收集逻辑

将原来收集每个样本的损失张量,改为收集所有样本的有效损失元素,最后统一计算全局均值:

def training():
    model.train()
    
    train_mae = []
    
    progress = tqdm(train_dataloader, desc='Training')
    for batch_index, batch in enumerate(progress):
        x = batch['x'].to(device)
        x_lengths = batch['x_lengths'].to(device)
        y = batch['y'].to(device)
        y_type = batch['y_type'].to(device)
        y_valid_indices = batch['y_valid_indices'].to(device)

        optimizer.zero_grad()

        y_first, y_second = model(x)

        # 收集所有有效损失元素,而非每个样本的损失张量
        all_loss_elements = []

        for j in range(len(x_lengths)):
            x_length = x_lengths[j].item()

            if y_type[j].item() == 0:
                predicted = y_first[j]
            else:
                predicted = y_second[j]

            actual = y[j]
            
            valid_mask = torch.zeros_like(predicted, dtype=torch.bool)
            valid_mask[:x_length] = 1
            
            indices_mask = y[j].ne(-1)
            valid_indices = y[j][indices_mask]

            valid_predicted = predicted[valid_mask]
            valid_actual = actual[valid_mask]
            
            # 获取当前样本的有效损失元素
            loss_elements = mae_fn(valid_predicted, valid_actual, valid_indices)
            all_loss_elements.append(loss_elements)

        # 拼接所有损失元素并计算全局均值
        loss = torch.cat(all_loss_elements).mean()
        loss.backward()

        optimizer.step()
        
        train_mae.append(loss.detach().cpu().numpy())

        progress.set_description(
            f"mae: {loss.detach().cpu().numpy():.4f}"
        )

    return np.mean(train_mae)

2. 保留原mae_fn不变

def mae_fn(output, target, indices):
    clipped_target = torch.clip(target, min=0, max=1)
    maes = F.l1_loss(output, clipped_target, reduction='none')
    return maes[indices]

为什么原来的方法会导致测试损失差?

原来对每个样本的损失先取均值再整体平均,相当于给有效数据点少的样本赋予了和数据点多的样本相同的权重。比如一个样本只有1个有效点,另一个有100个有效点,两者的平均损失在全局计算中占比相同,但实际上100个点的样本包含更多的任务信息,这种权重失衡会导致模型偏向拟合数据点少的样本,最终泛化能力下降,测试损失升高。

而使用全局均值的方式,每个有效损失元素的权重一致,模型能学习到更全面的任务信息,泛化效果更稳定。

内容的提问来源于stack exchange,提问作者Vivek Joshy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:35:28