PyTorch训练CNN时报错「含多个值的张量布尔值模糊」如何解决
错误原因
- 维度不匹配:你的模型是7分类任务,前向传播输出的
scores张量维度为[batch_size, 7],遍历scores时取出的每个元素是长度为7的张量,直接用多值张量和0.5做比较时,PyTorch无法确定要返回哪个位置的布尔值,因此触发报错。 - 逻辑不符合多分类规则:0.5阈值是二分类的判断逻辑,多分类任务应该取概率最高的类别作为预测结果,而不是用固定阈值判断。
- 损失函数选择错误:你当前使用的
nn.BCELoss()是为二分类、多标签分类场景设计的,不适用于单标签多分类任务,后续也会引发维度匹配错误。
解决方案
- 修正预测逻辑
删除原有的列表推导式生成预测值的代码,使用argmax取概率最高的类别索引作为预测结果:
# 替换原predictions行代码,dim=1表示在类别维度取最大值的索引 predictions = scores.argmax(dim=1)
如果你的标签y是one-hot编码格式,需要同步转成类别索引再做比对:
y = y.argmax(dim=1)
- 修正损失函数配置
优先选择更适配多分类的CrossEntropyLoss,不需要手动加softmax层,避免数值不稳定问题:
- 首先修改模型的forward方法,删除最后的softmax层:
def forward(self, x): # 前面的层代码不变 x = self.outLayer(x) # 删掉原来的softmax行,直接返回x return x
- 然后修改损失函数定义:
# 替换原来的BCELoss定义 criterion = nn.CrossEntropyLoss()
如果坚持要保留softmax输出,可将损失换成nn.NLLLoss,同时把softmax改成F.log_softmax(x, dim=1)即可。
- 优化准确率计算代码
替换原有check_accuracy函数中循环后的比对逻辑,全程用张量运算提升效率:
def check_accuracy(loader, model): if loader == train_loader: print("Checking accuracy on training data") else: print("Checking accuracy on validation data") num_correct = 0 num_samples = 0 model.eval() with torch.no_grad(): for x, y in loader: x = x.to(device=device) y = y.to(device=device) # 如果y是one-hot格式,取消注释下面这行 # y = y.argmax(dim=1) scores = model(x) predictions = scores.argmax(dim=1) num_correct += (predictions == y).sum() num_samples += predictions.size(0) acc = float(num_correct) / float(num_samples) * 100 print(f"Got {num_correct} / {num_samples} with accuracy {acc:.2f}") return f"{acc:.2f}"
内容的提问来源于stack exchange,提问作者Deffo
相关产品推荐
相关产品推荐

