PyTorch卷积网络训练MNIST时遭遇浮点类型不匹配的RuntimeError问题求助
嘿,我来帮你拆解解决这个问题!你遇到的RuntimeError其实是几个小错误凑在一起导致的,咱们一步步捋清楚:
1. 错误的核心根源:不该截取模型输出的第一个元素
你写了output = model(X_batch)[0],这会把整个batch的输出里的第一个样本单独拎出来。比如你的batch_size是10,模型原本输出的是形状为(10, 10)的张量(对应10个样本、每个样本10个类别的logits),取[0]之后就变成了(10,)的单样本logits张量,而y_batch是整个batch的标签(形状(10,))。
这时候把维度不匹配的两个张量喂给CrossEntropyLoss,PyTorch会完全误解你的意图:它会误以为你传入的target是类别概率分布(而非类索引),所以要求target必须是浮点类型,但你给的是Long类型的类索引,自然就抛出了这个类型不匹配的错误。
解决方法:直接去掉[0],正确获取整个batch的模型输出:
output = model(X_batch)
2. 另一个致命问题:优化器初始化放错了位置
你现在把optimizer = optim.SGD(...)写在了训练循环for X_batch, y_batch in train_dataloader:的内部,这意味着每跑一个batch,你就重新创建了一个全新的优化器——之前的梯度更新记录会被全部清空,模型根本没法正常学习!
解决方法:把优化器和损失函数的初始化都移到循环外面:
model = MNIST_ConvNet() optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9) # 移到循环外! loss_fn = nn.CrossEntropyLoss() # 提前初始化,不用每次循环创建 # 注意你这里变量名要和前面的train_loader统一,别写成train_dataloader for X_batch, y_batch in train_loader: optimizer.zero_grad() output = model(X_batch) loss = loss_fn(output, y_batch) loss.backward() # 你之前的代码漏掉了反向传播! optimizer.step() # 也漏掉了参数更新! print(f"当前Batch损失值: {loss.item()}")
3. 你尝试的类型转换完全没必要
你改的model(X_batch.type(torch.FloatTensor))根本没用——因为transforms.ToTensor()已经把MNIST图片转换成了FloatTensor类型,X_batch本身就是浮点型的,问题完全不在输入数据的类型上。
额外小提醒
- 检查你自定义的
ConvLayer和DenseLayer实现,确保conv2的flatten=True能正确把卷积输出展平成(batch_size, 28*28*7)的形状,不然全连接层会因为维度不匹配报错。 - 你的
forward函数里的assert_dim(x,4)没问题,MNIST的DataLoader输出的X_batch确实是(batch_size, channels, height, width)的4维张量。
备注:内容来源于stack exchange,提问作者Jelly

