python 3.6
pytorch 1.0.0
torchvision 0.2.1
在用pytorch实现简单的手写数字识别项目时遇到了这个错误,这里记录一下。报错的内容如下,这句话的意思就是需要一个四维的向量,但是输入的却是二维的。
Expected 4-dimensional input for 4-dimensional weight [10, 1, 3, 3], but got 2-dimensional input of size [100, 784] instead
下面第12行是报错的语句:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, 3, padding = 1)
self.conv2 = nn.Conv2d(10, 20, 3, padding = 1)
self.pool = nn.MaxPool2d(2, 2)
self.relu = nn.ReLU()
self.fc1 = nn.Linear(15680,1000)
self.fc2 = nn.Linear(1000, 10)
def forward(self, x):
out = self.conv1(x) # 报错
out = self.conv2(out)
out = self.fc1(out)
out = self.relu(out)
out = self.fc2(out)
return out
下面第4行是输入数据的定义:
train_dataset = dsets.MNIST(root = './data', train = True, transform = transforms.ToTensor(), download = True)
train_loader = torch.utils.data.DataLoader(dataset = train_dataset, batch_size = batch_size, shuffle = True)
for i, (images, labels) in enumerate(train_loader):
images = Variable(images.view(-1, 28 * 28)) # 这一行是输入数据
labels = Variable(labels)
# ......
该行是一个卷积操作,输出Net对象,得到conv1操作的具体参数:
Net(
(conv1): Conv2d(1, 10, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(conv2): Conv2d(10, 20, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu): ReLU()
(fc1): Linear(in_features=15680, out_features=1000, bias=True)
(fc2): Linear(in_features=1000, out_features=10, bias=True)
)
经过相关资料查询,知道报错信息中出现的[10, 1, 3, 3]
指卷积输出通道数量、输入通道数量、卷积核宽度、卷积核高度。
输入图片数据的形状已经被我改变了,从28*28的二维矩阵变成了大小为784的一维向量,所以才会出现这个错误。
因此,输入的图片数据也需要是一个四维的张量,所以将输入数据的定义一行改成
images = Variable(images.view(100, 1, 28, 28))
或者去掉view()方法,如:
images = Variable(images)
需要特别说明的是,在查找类似问题的时候,大家都只说明要怎么做,却没有说出这是为什么。根据我的理解,第一种方法显示定义了输入数据的维数:四维,第一维“100”意为一批的数量(batch),第二维“1”意为输入通道数,第三维“28”和第四维“28”分别意为输入图片数据的宽与高。第二种方法,并没有显示定义,所以系统会自动读取图片的宽、高,还有定义的卷积的输入通道数,并设置相应的batch。
这里面遇到的是二维卷积,如果是一维卷积,那么输入数据应该是三维的,第一维表示batch,第二维表示输入通道数,第三维表示数据长度;如果是三维卷积,那么输入数据应该五维的,第一维、第二维含义不变,后面表示数据。