RuntimeError:张量a(133)的大小必须与张量b(10)的大小匹配非单维度1

时间:2019-06-27 02:40:14

标签: python-3.x conv-neural-network pytorch

我正在训练CNN模型。在为模型进行训练迭代时,我遇到了问题。代码如下:

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()

        #convo layers
        self.conv1 = nn.Conv2d(3,32,3)
        self.conv2 = nn.Conv2d(32,64,3)
        self.conv3 = nn.Conv2d(64,128,3)
        self.conv4 = nn.Conv2d(128,256,3)
        self.conv5 = nn.Conv2d(256,512,3)

        #pooling layer
        self.pool = nn.MaxPool2d(2,2)

        #linear layers
        self.fc1 = nn.Linear(512*5*5,2048)
        self.fc2 = nn.Linear(2048,1024)
        self.fc3 = nn.Linear(1024,133)

        #dropout layer
        self.dropout = nn.Dropout(0.3)
        def forward(self, x):
        #first layer
        x = self.conv1(x)
        x = F.relu(x)
        x = self.pool(x)
        #x = self.dropout(x)
        #second layer
        x = self.conv2(x)
        x = F.relu(x)
        x = self.pool(x)
        #x = self.dropout(x)
        #third layer
        x = self.conv3(x)
        x = F.relu(x)
        x = self.pool(x)
        #x = self.dropout(x)
        #fourth layer
        x = self.conv4(x)
        x = F.relu(x)
        x = self.pool(x)
        #fifth layer
        x = self.conv5(x)
        x = F.relu(x)
        x = self.pool(x)
        #x = self.dropout(x)

        #reshape tensor
        x = x.view(-1,512*5*5)
        #last layer
        x = self.dropout(x)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.dropout(x)
        x = self.fc2(x)
        x = F.relu(x)
        x = self.fc3(x)

        return x

        #loss func
        criterion = nn.MSELoss()
        optimizer = optim.Adam(net.parameters(), lr = 0.0001)
        #criterion = nn.CrossEntropyLoss()
        #optimizer = optim.SGD(net.parameters(), lr = 0.05)

        def train(n_epochs,model,loader,optimizer,criterion,save_path):    
           for epoch in range(n_epochs):
              train_loss = 0
              valid_loss = 0
              #training 
              net.train()
              for batch, (data,target) in enumerate(loaders['train']):
                   optimizer.zero_grad()
                   outputs = net(data)
                   #print(outputs.shape)
                   loss = criterion(outputs,target)
                   loss.backward()
                   optimizer.step()

当我使用CrossEntropy Loss函数和SGD优化器时,我能够正确训练模型。 当我使用MSE损失函数和Adam优化器时,我遇到以下错误:

RuntimeError Traceback (most recent call last) <ipython-input-20-2223dd9058dd> in <module>
      1 #train the model
      2 n_epochs = 2
----> 3 train(n_epochs,net,loaders,optimizer,criterion,'saved_model/dog_model.pt')

<ipython-input-19-a93d145ef9f7> in train(n_epochs, model, loader, optimizer, criterion, save_path)
     22 
     23             #calculate loss
---> 24             loss = criterion(outputs,target)
     25 
     26             #backward prop

RuntimeError: The size of tensor a (133) must match the size of tensor b (10) at non-singleton dimension 1.

所选损失函数和优化器是否影响模型的训练?有人可以帮忙吗?

2 个答案:

答案 0 :(得分:2)

好吧,该错误是因为nn.MSELoss()nn.CrossEntropyLoss()期望使用不同的input / target组合。您不能简单地更改标准函数,而不适当更改输入和目标。从文档中:

nn.CrossEntropyLoss

  
      
  • 输入:      
        
    • (N,C),其中C =类数,或
    •   在K维损失的情况下,
    • (N,C,d_1,d_2,...,d_K)且K> = 1。
    •   
  •   
  • 目标:      
        
    • (N),其中每个值的范围为[0,C-1]或
    •   在K维损失的情况下
    • (N,d_1,d_2,...,d_K)且K> = 1。
    •   
  •   

nn.MSELoss

  
      
  • 输入:      
        
    • (N,∗),其中∗表示任意数量的附加尺寸。
    •   
  •   
  • 目标:      
        
    • (N,∗),与输入形状相同
    •   
  •   

如您所见,在MSELoss中,期望Target具有与输入相同的形状,而在CrossEntropyLoss中,C维度将被删除。您不能将MSELoss用作CrossEntropyLoss的替代品

答案 1 :(得分:1)

错误消息清楚地表明错误发生在行

loss = criterion(outputs,target)

您尝试在其中计算输入和目标之间的mean-squared error的位置。 参见以下行:criterion = nn.MSELoss()

我认为您应该在估算(输出,目标)一对输入之间的损失的地方修改代码,例如loss = criterion(outputs,target)如下:

loss = criterion(outputs,target.view(1, -1))

在这里,您通过在线模型制作的target形状与outputs相同

outputs = net(data)

这里需要注意的另一个问题是net模型的输出,即输出将是batch_size X output_channels的形状,如果在训练期间输入图像的第一维,则批次大小获取批处理的图像,因此前进方法中的形状将在dim0[batch_size, channels, height, width]处获得附加的批处理尺寸,并且ouput_channels是最后一个线性层的输出要素/通道数在net模型中。

而且,目标标签的形状为batch_size,在您的情况下为10,请检查您传入batch_size的{​​{1}}。因此,在使用torch.utils.data.DataLoader()重塑形状时,它将被转换为形状view(1, -1),即1 X batch_size

这就是为什么,您遇到错误:

  

RuntimeError:输入形状与目标形状不匹配:输入[10 x 133],   目标[1 x 10]

因此,一种解决方法是将1 X 10替换为loss = criterion(outputs,target.view(1, -1)),并将最后一个线性层的loss = criterion(outputs,target.view(-1, 1))更改为output_channels而不是1。这样,133outputs的形状都将相等,然后我们就可以计算出target的值。

here了解有关pytorch MSE损失函数的更多信息。