本文介绍了RuntimeError:张量a(133)的大小必须与非单维度1上张量b(10)的大小匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am training a CNN model. I am facing issue while doing the training iteration for my model. The code is as below:

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损失时功能和SGD优化器,我能够毫无错误地训练模型。
当我使用MSE损失函数和Adam优化器时,遇到以下错误:

When I use the CrossEntropy Loss function and SGD optimizer, I able able to train the model with no error.When I use MSE loss function and Adam optimizer, I am facing the following error:

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.

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

Does the selected loss function and optimizer effect the training of the model? Can anyone please help on this?

推荐答案

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

The error message clearly suggests that the error occurred at the line

loss = criterion(outputs,target)

,您要在其中计算输入和目标之间的均方误差
看到这一行: criterion = nn.MSELoss()

where you are trying to compute the mean-squared error between the input and the target.See this line: criterion = nn.MSELoss().

我认为您应该修改您的您在其中估算(输出,目标)输入对之间的损失的代码,例如, loss = standard(outputs,target)到如下所示:

I think you should modify your code where you are estimating loss between (output, target) pair of inputs,i.e., loss = criterion(outputs,target) to something like below:

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

在这里,您要使目标的形状与输出的形状相同在线模型

Here, you are making target shape same as outputs from model on line

outputs = net(data)

还有一个要注意的地方是 net 模型的输出,即输出的形状为 batch_size X output_channels ,如果在训练过程中输入图像的第一个尺寸(如训练期间),则批次大小将获得图像批次,因此,正向方法中的形状将以<$获得额外的批次尺寸c $ c> dim0 : [批处理大小,通道,高度,宽度]和输出通道是出数将要素/通道从 net 模型的最后一个线性层开始。

One more think to notice here is the output of the net model, i.e., outputs will be of shape batch_size X output_channels, where batch size if the first dimension of input images as during the training you will get batches of images, so your shape in the forward method will get an additional batch dimension at dim0: [batch_size, channels, height, width], and ouput_channels is number of output features/channels from the last linear layer in the net model.

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

And, the the target labels will be of shape batch_size, which is 10 in your case, check batch_size you passed in torch.utils.data.DataLoader(). Therefore, on reshaping it using view(1, -1), it will be of converted into a shape 1 X batch_size, i.e., 1 X 10.

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

That's why, you are getting the error:

因此,一种解决方法是替换 loss = standard(outputs,target.view(1,-1)),其中 loss = standard(outputs,target.view(-1,1))并更改 output_channels 改为 1 而不是 133 。这样,输出目标的形状将相等,我们可以计算出 MSE 值。

So, a way around is to replace loss = criterion(outputs,target.view(1, -1)) with loss = criterion(outputs,target.view(-1, 1)) and change the output_channels of last linear layer to 1 instead of 133. In this way, both of outputs and target shape will be equal and we can compute MSE value then.

进一步了解pytorch MSE 损失函数,请。

Learn more about pytorch MSE loss function from here.

这篇关于RuntimeError:张量a(133)的大小必须与非单维度1上张量b(10)的大小匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 08:53