XLM-Roberta文本二分类训练中计算训练准确率报错解决方案
报错原因
核心问题是API混用:你在执行准确率计算逻辑前,已经通过.numpy()把logits从PyTorch张量转换为NumPy数组,而.float()是PyTorch张量的专属类型转换方法,NumPy数组不存在这个方法,因此触发AttributeError。
除此之外代码还有3处逻辑问题,即使修复这个报错也无法得到正确的训练准确率:
- 二分类场景下,初始化XLM-Roberta时如果设置
num_labels=2,模型输出的logits形状为(batch_size, 2),分别对应两个类别的原始输出得分,直接和0.5做阈值比较的逻辑完全不成立。 - 统计正确数的
correct变量定义在batch循环内部,循环结束后你拿到的只是最后一个batch的正确样本数,不是整个epoch的累计正确数。 - 准确率分母用了
len(train_dataloader)(即训练集的batch总数),而不是训练集总样本量,计算结果完全不符合准确率定义。
修复方法
- 调整代码执行顺序:先在PyTorch张量层面完成预测值计算、正确数统计,需要做其他NumPy相关操作时再转数组,避免混用两套API。
- 修正二分类输出处理逻辑:对两维的logits做softmax计算,取正类(标签为1)的概率做阈值判断,或者直接取argmax得到预测标签。
- 修正准确率统计逻辑:在epoch循环外初始化全局正确数、总样本数的统计变量,每个batch计算完后累加,epoch结束后用总正确数除以总样本数得到真实准确率,统计完后重置变量供下一个epoch使用。
对应修改后的核心代码片段如下:
# epoch循环开始前初始化统计变量 correct_train = 0 total_train = 0 for epoch in range(0, epochs): # ...... 其他原有代码不变 ...... for i, batch in enumerate(train_dataloader): # ...... 前面的输入加载、前向传播代码不变 ...... outputs = model(b_input_ids, attention_mask=b_input_mask, labels=b_labels) model.zero_grad() loss = outputs[0] logits = outputs[1] # ========== 准确率计算部分修改开始 ========== # 先在PyTorch张量层面计算预测结果 # 二分类num_labels=2时用下面这行,取正类概率做阈值判断 pred_labels = (torch.softmax(logits, dim=1)[:, 1] > 0.5).long() # 如果你设置num_labels=1用BCE损失,就换成下面这行 # pred_labels = (torch.sigmoid(logits.squeeze()) > 0.5).long() # 累加当前batch的正确数和样本数 correct_train += (pred_labels == b_labels).sum().item() total_train += b_labels.size(0) # ========== 准确率计算部分修改结束 ========== # 统计完准确率再转NumPy,不影响其他逻辑 logits = logits.detach().cpu().numpy() label_ids = b_labels.to('cpu').numpy() # ...... 后面的反向传播、参数更新代码不变 ...... # epoch结束后打印准确率,之后重置统计变量 print('Train loss:', total_train_loss) print('Train acc:', 100 * correct_train / total_train) print(" Training epoch took: {:}".format(training_time)) correct_train = 0 total_train = 0
如果你想用NumPy语法写准确率计算逻辑也可以,把
.float()换成NumPy的类型转换写法(logits>0.5).astype(np.float32)即可,但还是建议优先修正前面说的logits维度问题,否则结果依然错误。
内容的提问来源于stack exchange,提问作者Rachele Franceschini
相关产品推荐
相关产品推荐

