PyTorch编写Auto Encoder时出现target导数未实现RuntimeError报错
问题根因
这个报错的直接触发原因是你给nn.BCELoss传入的target参数是带梯度计算的张量:
- 你写的损失计算代码是
loss = lossFn(outputs, outputs),第二个参数target传入的是模型前向输出的outputs,这个张量默认开启了梯度追踪,而PyTorch的BCELoss仅针对输入input实现了反向传播逻辑,没有对target的求导实现,传入带grad的target就会抛出该错误。 - 同时这段损失计算逻辑本身不符合自编码器的训练目标:自编码器的重构损失应该计算模型输出和原始输入数据的差异,而不是和输出自身对比。
其他需要修复的问题
你的代码还有3处会导致训练失效的问题:
nn.BCELoss要求输入的预测值、真实值都必须在[0,1]数值区间内,你加载的FashionMNIST原始像素值范围是0~255,没有做归一化处理,不符合损失函数的输入要求。- 解码器最后一层使用
ReLU作为激活函数,输出范围是[0, +∞),不满足BCELoss的输入值域要求,应该替换为Sigmoid把输出压缩到0~1区间。 - 训练循环末尾的
model.forward(data)是多余代码,没有任何实际作用,只会浪费计算资源。
修复后可运行代码
import torch import torchvision from torch import nn # 加载数据时直接做归一化,把像素值从0-255缩放到0-1 trainset = torchvision.datasets.FashionMNIST(root='./data', train=True, download=True) data = trainset.data.float() / 255.0 # 归一化到[0,1] device = "cuda" if torch.cuda.is_available() else "cpu" data = data.to(device) print(f"Using device = {device}") class NeuralNetwork(nn.Module): def __init__(self): super(NeuralNetwork, self).__init__() self.flatten = nn.Flatten() self.encode = nn.Sequential( nn.Linear(28*28, 512), nn.ReLU(), nn.Linear(512, 30), nn.ReLU() ) self.decode = nn.Sequential( nn.Linear(30, 512), nn.ReLU(), nn.Linear(512, 28*28), nn.Sigmoid() # 替换为Sigmoid,输出符合BCELoss值域要求 ) def forward(self, x): x = self.flatten(x) encoded = self.encode(x) decoded = self.decode(encoded) return decoded model = NeuralNetwork().to(device) lossFn = nn.BCELoss() optimizer = torch.optim.SGD(model.parameters(), lr = 1e-3) for epoch in range(1000): optimizer.zero_grad() outputs = model(data) # 损失target传入原始输入data,data不需要计算梯度,不会触发报错 loss = lossFn(outputs, data) loss.backward() optimizer.step() # 打印损失方便观察收敛情况 if (epoch + 1) % 50 == 0: print(f"Epoch {epoch+1}, Loss: {loss.item():.4f}")
内容的提问来源于stack exchange,提问作者desert_ranger
相关产品推荐
相关产品推荐

