我该如何解决这个问题?输入必须有 3 个维度,得到 4

Posted

技术标签:

【中文标题】我该如何解决这个问题?输入必须有 3 个维度,得到 4【英文标题】:How can I solve this issue? input must have 3 dimensions, got 4 【发布时间】:2021-10-05 09:27:45 【问题描述】:

以下是我传递给数据加载器的数据,

train_path='/content/drive/MyDrive/Dataset_manual_pytorch/train'
test_path='/content/drive/MyDrive/Dataset_manual_pytorch/test'

train = torchvision.datasets.ImageFolder(train_path,transform=transformations)
test = torchvision.datasets.ImageFolder(test_path,transform=transformations)

train_loader = torch.utils.data.DataLoader(train, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(test, batch_size =32, shuffle=True)

这是我的循环神经网络模型,

hidden_size = 256
sequence_length = 28
num_classes = 2
num_layers = 2
input_size = 32
learning_rate = 0.001
num_epochs = 3

class RNN(nn.Module):
  def __init__(self, input_size, hidden_size, num_layers, num_classes):
      super(RNN, self).__init__()
      self.hidden_size = hidden_size
      self.num_layers = num_layers

      self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first = True)
      self.fc = nn.Linear(hidden_size*sequence_length, num_classes)
  
  def forward(self, x):
    h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)

    #Forward Prop
    out,_ = self.rnn(x, h0)
    out = out.reshape(out.shape[0], -1)
    out = self.fc(out)
    return out

model_rnn = RNN(input_size, hidden_​​size, num_layers, num_classes).to(device)

当我为特定时期和训练数据训练这个模型时,它给了我以下错误;

RuntimeError: input must have 3 dimensions, got 4

数据的形状为:torch.Size([64, 3, 32, 32])

我认为错误是因为我正在输入 4 维数据,其中我也传递了三个通道(RGB),为了解决这个问题,我需要重塑; torch.Size([64, 3, 32, 32]) --> torch.Size([64, 32, 32])) 但我做不到。

培训代码是;

@torch.no_grad()
def Validation_phase(model, val_loader):
    model.eval()
    for data, labels in val_loader:
      out = model(data)
      val_loss = F.cross_entropy(out, labels)
      val_acc = accuracy(out, labels)

    return val_loss.detach(), val_acc

def fit(epochs, lr, model, train_loader, val_loader, opt_func=torch.optim.SGD):
    history = []
    optimizer = opt_func(model.parameters(), lr)
    for epoch in range(epochs):
        # Training Phase 
        model.train()
        train_losses = []
        train_accuracy = []  
        for data, labels in train_loader:
            #forward

            print(data.shape)
            out = model(data)
            #loss calculate
            train_loss = F.cross_entropy(out, labels)

            #Accuracy
            train_acc = accuracy(out, labels)

            train_accuracy.append(train_acc)
            train_losses.append(train_loss.item())

            #back_propagate
            train_loss.backward()
            optimizer.step()
            optimizer.zero_grad()
    
        train_accuracy = np.mean(torch.stack(train_accuracy).numpy())
        train_losses = np.mean(train_losses)
        

        #Validation phase
        val_losses, val_accuracy = Validation_phase(model, val_loader)

        print("Epoch [], train_loss: :.4f, train_accuracy: :.4f, val_loss: :.4f, val_acc: :.4f".format(
            epoch, train_losses*100 , train_accuracy*100 , val_losses.item()*100, val_accuracy.item()*100))
        # history.append(result)
    # return history

fit(5, 0.001, model_rnn, train_loader, test_loader, torch.optim.Adam) 

【问题讨论】:

【参考方案1】:

您可以按照下面的代码将 torch.Size([64, 3, 32, 32]) 的大小转换为 torch.size([64, 32, 32]):

x = torch.ones((64, 3, 32, 32))
x = x[:, 0, :, :]

#Check code: 
print(x.size())

【讨论】:

所以你要保持红色并扔掉蓝色和绿色?此外,您的 x 最终将拥有 3 个轴... 这个方法会影响我的模型。【参考方案2】:

您可以使用 RGB 通道的平均值来获得具有 torch.mean 的单个通道上的图像表示。您可能需要保持平均尺寸,才能正确输入模型:您可以使用 keepdim 选项:

>>> x = torch.rand(64, 3, 32, 32)
>>> z = x.mean(1, keepdim=True)
>>> z.shape
(64, 1, 32, 32)

请记住,有 other ways 进行此操作(RGB 到灰度转换)。

【讨论】:

是的,我可以取所有 3 个通道的平均值,但是这里模型的准确性会受到影响,我可以将所有 RGB 图像转换为灰度,但是这种方法计算量太高,因为我有数百万图像。谢谢 当然会影响你的模型,这会有效的减少你数据中的信息量。确实没有什么神奇的方法可以绕过它。或者,一种常见的方法是对数据进行一次预处理,在您的情况下计算一次灰度并在训练中使用转换后的灰度图像。你怎么看? 我正在使用 OpenCV 将 RGB 转换为灰度,然后再次加载到 Data Loader 以保持批量大小。

以上是关于我该如何解决这个问题?输入必须有 3 个维度,得到 4的主要内容,如果未能解决你的问题,请参考以下文章

预期输入有 4 个维度,但得到的数组具有形状

检查输入时出错:预期 input_1 有 4 个维度,但得到了形状为 (224, 224, 3) 的数组

检查输入时出错:预期 lstm_input 有 3 个维度,但得到的数组形状为 (4, 1)

RNN - RuntimeError:输入必须有 3 维,得到 2

检查输入时出错:预期 lstm_input 有 3 个维度,但得到了形状为 (160, 1000) 的数组

model.predict() == ValueError:检查输入时出错:预期 flatten_input 有 3 个维度,但得到的数组形状为 (1, 2)