pytorch 如何解决CNN模型中与输入大小不匹配相关的运行时错误?

u7up0aaq  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(218)

我试图在一个合成数据集上运行CNN模型,该数据集由4000个半简单随机点样本组成,每个类有2个特征和1个聚类,输入数据大小x为[4000,2],相应的标签大小为[4000]。
我知道原始输入Tensor的形状是[4000,2],其中4000=样本总数,2=特征数,我对Conv1d层的输入应该是3dTensor[batch_size,1,2],其中1是输入通道数,2是序列长度,但当它运行dataloader和train函数时,它变成了[1,batch_size,2],这就是问题出现的地方。CNN的参数定义为:

class Net(nn.Module):
    def __init__(self, Bias):
        super(Net, self).__init__()
        self.conv1 = nn.Conv1d(1, 1, kernel_size=1, stride=1) 
        self.relu = nn.ReLU()                                 
        self.fc1 = nn.Linear(2, 20, bias = False)            
        self.fc2 = nn.Linear(20, 2, bias = False)
    def forward(self, x):
        x = self.relu(self.conv1(x))
        x = x.reshape(x.size(0), -1)
        x = self.relu(self.fc1(x))
        x = self.fc2(x)
        return x

epochs = 50
alpha = 1e-2
batch_size = 50
criterion = nn.CrossEntropyLoss()
model = Net(biases).to(device)
model = train(model.to(device),criterion,x,y,alpha,epochs,batch_size)

字符串
我使用了以下的train函数:

def train(model,criterion, x, y, alpha, epochs, batchsize):
    costs = []
    optimizer = torch.optim.SGD(model.parameters(), lr=alpha)    
    trainx, trainy, testx, testy= dataloader(x,y)
    x=trainx.float()
    y=trainy.float()
    data_train = torch.cat((x, y), dim=1)
    data_train_loader = DataLoader(data_train, batch_size=batchsize, shuffle=True)
    model.train()
    j = 0
    for i in range(epochs):
        for index,samples in enumerate(data_train_loader):
            j += 1
            x1 = samples[:,0:2]
            y1 = samples[:,2].long().reshape(-1,1)
            if (j%50 == 0):
                model.eval()
                acc = accuracy(model,testx,testy)
                print(f'Test accuracy is #{acc:.2f} , Iteration number is = {j}')
                model.train()
            cost = criterion(model(x1), y1.squeeze())
            optimizer.zero_grad()
            cost.backward()
            optimizer.step()        
            costs.append(float(cost))
    return model


以下是我得到的错误:

RuntimeError                              Traceback (most recent call last)
Cell In[17], line 7
      5 criterion = nn.CrossEntropyLoss()
      6 model = Net(biases).to(device)
----> 7 model=train(model.to(device),criterion,x,y,alpha,epochs,batch_size)
Cell In[15], line 40, in train(model, criterion, x, y, alpha, epochs, batchsize)
     38     print(f'Test accuracy is #{acc:.2f} , Iteration number is = {j}')
     39     model.train()
---> 40 cost = criterion(model(x1), y1.squeeze())
Cell In[16], line 11, in Net.forward(self, x)
     10 def forward(self, x):
---> 11     x = self.relu(self.conv1(x))

RuntimeError: Given groups=1, weight of size [1, 1, 1], expected input[1, 50, 2] to have 1 channels, but got 50 channels instead


如何解决这个输入尺寸问题或改变模型输入的尺寸要求?

mec1mxoz

mec1mxoz1#

等你找到了

x1 = samples[:,0:2] # (batch_size, features)

字符串
替换为以下内容以添加通道尺寸。这类似于unsqueeze,如果你加载了numpy,你可以用np.newaxis替换None,这是更多的信息,但同样的事情。

x1 = samples[:, None,0:2]  # (batch_size, 1, features)

yjghlzjz

yjghlzjz2#

正如你所说的,Conv1d层的输入形状应该是3dTensor[batch_size,1,2],其中1是输入通道的数量,2是序列长度。但是,您正在将2DTensor传递到Conv1d。你需要将Tensor扩展到3D,其中第二维表示使用unsqueeze函数的通道。我认为,如果你不提供通道维度,Tensor被认为没有批次维度。因此,它是自动添加的。检查以下示例:
输入1:

import torch
from torch import nn
input = torch.randn( 50, 2) 
convolution_layer = nn.Conv1d(1, 1, kernel_size=1, stride=1) 
feature_map = convolution_layer(input)

字符串
输出1:

RuntimeError: Given groups=1, weight of size [1, 1, 1], expected input[1, 50, 2] to have 1 channels, but got 50 channels instead


输入2:

import torch
from torch import nn
input = input.unsqueeze(1) 
convolution_layer = nn.Conv1d(1, 1, kernel_size=1, stride=1) 
feature_map = convolution_layer(input)


输出2:

No errors


按如下所示修改模型:

class Net(nn.Module):
  def __init__(self, Bias):
    super(Net, self).__init__()
    self.conv1 = nn.Conv1d(1, 1, kernel_size=1, stride=1) 
    self.relu = nn.ReLU()                                 
    self.fc1 = nn.Linear(2, 20, bias = False)            
    self.fc2 = nn.Linear(20, 2, bias = False)
  def forward(self, x):
    x = self.relu(self.conv1(x.unsqueeze(1)))
    x = x.reshape(x.size(0), -1)
    x = self.relu(self.fc1(x))
    x = self.fc2(x)
    return x


或者在训练循环中添加“.unsqueeze(1)”,如下所示:

cost = criterion(model(x1.unsqueeze(1)), y1.squeeze())

相关问题