原帖把 CIFAR10 教程改成自己的 ImageFolder,仍使用 view(-1,1655) 和 Linear(400,120):
RuntimeError: shape ‘[-1, 400]’ is invalid for input of size 87616
87616 与贴出的 224 变换并不完全对应
错误给的是实际运行张量的元素数,而代码还写着 RandomResizedCrop(224)。这两份证据不能强行凑成唯一形状:先在 view 前打印真实 batch 和卷积激活,再核对 loader 实际使用的 transform。内存连续性问题对应另一种 view 报错,.contiguous() 不会让元素数变成 400 的倍数。
87616 不能按每份 400 个元素重排,说明卷积输出不再是教程预设的 16×5×5。应先保留 batch 维,查看真实激活,而不是猜一个可整除的数字。
在原 forward 的第二次卷积池化后、view 之前加:
print("josh050608")
print("activation:", x.shape, "elements:", x.numel())
print("per sample:", x[0].numel(), "fc expects:", self.fc1.in_features)
如果打印确认为 [4,16,37,37],每样本就是 21904 个特征,应同时修改两处:x = x.flatten(1),并把构造函数改为 self.fc1 = nn.Linear(16*37*37,120)。只改 view 不改 Linear,下一步仍会矩阵维数不匹配。
但原帖还写了 RandomResizedCrop(224),它与上述 37×37 激活不一致:按贴出的两层 5×5 卷积和 2×2 池化,224 输入会得到 53×53。说明实际运行变换或代码可能与粘贴内容不同,必须以运行时打印为准,不能直接固定 21904。
若希望维持教程网络,可以把输入明确变为 32×32,或在卷积后使用有设计依据的自适应池化到 5×5,再接 Linear(400,120);这些都会改变输入/特征处理,应重新训练。尺寸固定后再创建优化器。
验证普通 batch 与尾批 N=1 的输出第一维都保持 N,且类别通道数与数据集一致。
保留 batch 维,完整验证一种可变输入设计
如果任务允许把卷积特征统一汇聚为 5×5,可以保留教程的 Linear(400,120)。下面是合成分类网络,演示这一有意结构选择;它不是原题已经证实的修复,需重新训练:
import torch
from torch import nn
class Classifier(nn.Module):
def __init__(self):
super().__init__()
self.features = nn.Sequential(nn.Conv2d(3, 6, 5), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(6, 16, 5), nn.ReLU(), nn.MaxPool2d(2))
self.pool = nn.AdaptiveAvgPool2d((5, 5))
self.head = nn.Linear(400, 3)
def forward(self, x):
return self.head(self.pool(self.features(x)).flatten(1))
model = Classifier()
for size, batch_size in ((32, 4), (224, 1)):
image = torch.randn(batch_size, 3, size, size)
output = model(image)
assert output.shape == (batch_size, 3)
model.zero_grad()
output.square().mean().backward()
assert model.head.weight.grad is not None
print("input/output:", image.shape, output.shape)
若不采用自适应池化,就按实际每样本激活宽度修改 fc1,并用 flatten(1) 保留 batch。两处要同步修改;随便找一个能整除总元素数的 view 参数可能把样本数也改掉。
核对真实 transform 时打印 trainloader.dataset 持有的变换,重启旧 Notebook 单元和 worker,避免只改了一份未使用的变量。修复完成后使用正常 batch 与尾批 N=1 验证输出数量、类别数和 loss/backward,再恢复完整训练。
参考:原始求助帖;技术依据:Tensor.view(2.5)、Linear(2.5)、MaxPool2d(2.5)、AdaptiveAvgPool2d(2.5)。