高光谱图像分类DNN代码报错:TypeError: forward()缺失参数'negative'
嘿,我来帮你排查这个错误!你遇到的TypeError: forward() missing 1 required positional argument: 'negative'是因为选错了损失函数,咱们一步步来解决:
错误根源
你用了nn.TripletMarginLoss(),这个损失函数是用来做三元组学习的(比如人脸识别里的锚点、正样本、负样本对比),它的forward方法必须接收三个参数:anchor、positive、negative。但你的分类任务只传了模型输出和标签两个参数,自然就会报错缺少negative参数啦。
另外你的代码还有几个小问题,我一起帮你修正。
完整修复方案
1. 替换为分类任务的专用损失函数
把三元组损失换成分类任务常用的CrossEntropyLoss,它只需要模型输出和标签两个参数,完美匹配你的需求。
2. 修正标签的数据类型
CrossEntropyLoss要求标签是整数类型的张量(LongTensor),而你当前的train_y和test_y是FloatTensor,需要转换一下,同时去掉多余的维度(比如从[batch_size,1]改成[batch_size])。
3. 修复测试函数的输入形状错误
测试函数里的test_X[i].view(-1, 1, 50, 50)完全不对——你的输入是103维的光谱向量,不是50x50的图像,应该改成test_X[i].view(-1, 103)。同时,获取真实标签的方式也错了,直接取test_y[i]就行,不用torch.argmax。
修改后的完整代码
下面是修复后的关键部分代码,我标了修改的核心点:
# 训练和测试函数 def train(dnn): BATCH_SIZE = 100 EPOCHS = 3 for epoch in range(EPOCHS): for i in tqdm(range(0, len(train_X), BATCH_SIZE)): batch_X = train_X[i:i+BATCH_SIZE] # 修正标签形状和类型:去掉多余维度并转为LongTensor batch_y = train_y[i:i+BATCH_SIZE].squeeze().long() dnn.zero_grad() outputs = dnn(batch_X) loss = loss_function(outputs, batch_y) loss.backward() optimizer.step() print(f"Epoch {epoch+1}, Batch {i//BATCH_SIZE}, Loss: {loss.item()}") def test(net): correct = 0 total = 0 with torch.no_grad(): for i in tqdm(range(len(test_X))): # 修正真实标签获取方式和类型 real_class = test_y[i].long().to(device) # 修正输入形状:匹配103维的光谱向量 net_out = net(test_X[i].view(-1, 103).to(device))[0] predicted_class = torch.argmax(net_out) if predicted_class == real_class: correct += 1 total += 1 # 修正计数逻辑:无论对错都统计总数 print("Accuracy:", round(correct/total,3)) if REBUILD_DATA: Data = DATA() datay = Data.integrated_data() Trainindex, Testindex, TrainSet, TestSet = Data.make_trainset_and_testset(rebuilddata=datay,ratio=0.1) train_X = torch.Tensor([i[0] for i in TrainSet]) train_y = torch.Tensor([i[1] for i in TrainSet]) train_X = train_X/3000 test_X = torch.Tensor([i[0] for i in TestSet]) test_y = torch.Tensor([i[1] for i in TestSet]) print(train_X[0]) # 加入设备配置:自动使用GPU加速(如果可用) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") dnn = DNN().to(device) optimizer = optim.SGD(dnn.parameters(), lr = 0.001) # 替换为分类任务专用损失函数 loss_function = nn.CrossEntropyLoss() train(dnn) # 别忘了调用测试函数评估效果 test(dnn)
额外提几个小优化点:
- 加入了设备自动配置,优先用GPU加速训练
- 训练时的loss打印更清晰,方便监控训练状态
- 修正了测试函数的计数逻辑,避免准确率计算错误
这样修改后,你的代码应该就能正常运行啦!
内容的提问来源于stack exchange,提问作者Yang Cong

