【问题标题】:PyTorch - AssertionError: Size mismatch between tensorsPyTorch - AssertionError:张量之间的大小不匹配
【发布时间】:2021-04-17 00:46:08
【问题描述】:

我正在尝试调整为线性回归创建的 Pytorch 脚本。它最初是为了将一组随机值(使用 np.random 创建)作为特征和目标而编写的。

我现在创建了一个包含实际数据的数据框以供分析:

df = pd.read_csv('file_name.csv')

df 看起来像这样:

      X1     X2     X3     X4    X5   X6   X7  X8    Y1     Y2
0    0.98  514.5  294.0  110.25  7.0   2  0.0   0  15.55  21.33
1    0.98  514.5  294.0  110.25  7.0   3  0.0   0  15.55  21.33
2    0.98  514.5  294.0  110.25  7.0   4  0.0   0  15.55  21.33
3    0.98  514.5  294.0  110.25  7.0   5  0.0   0  15.55  21.33
4    0.90  563.5  318.5  122.50  7.0   2  0.0   0  20.84  28.28

...我目前只提取两列(X1 和 X2)作为我的特征,一列(Y1)作为我的目标,如下所示:

x = df[['X1', 'X2']]
y = df['Y1']

所以功能看起来像这样:

      X1     X2
0    0.98  514.5
1    0.98  514.5
2    0.98  514.5
3    0.98  514.5
4    0.90  563.5

目标看起来像这样:

        Y1
0      15.55
1      15.55
2      15.55
3      15.55
4      20.84

但是,当我尝试将特征(X1 和 X1)和目标(Y1)转换为张量以便将它们提供给 NN 时,代码在以下行失败:

数据集 = TensorDataset(x_tensor_flat, y_tensor_flat)

我得到错误:

line 45, in <module> dataset = TensorDataset(x_tensor, y_tensor)
AssertionError: Size mismatch between tensors

显然存在一些塑造问题,但我不知道是什么。 我试图展平和转置张量,但我得到了同样的错误。 任何帮助将不胜感激。

这是导致问题的完整代码部分:

import pandas as pd
import torch
import torch.optim as optim
import torch.nn as nn
from torch.utils.data import Dataset, TensorDataset, DataLoader
from torch.utils.data.dataset import random_split

device = 'cuda' if torch.cuda.is_available() else 'cpu'


df = pd.read_csv('file_name.csv')
x = df[['X1', 'X2']]
y = df['Y1']


x_tensor = torch.from_numpy(np.array(x)).float()
y_tensor = torch.from_numpy(np.array(y)).float()


train_loader = DataLoader(dataset=train_dataset, batch_size=10)
val_loader = DataLoader(dataset=val_dataset, batch_size=10)


class ManualLinearRegression(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(2, 1)

    def forward(self, x):
        return self.linear(x)

def make_train_step(model, loss_fn, optimizer):
    def train_step(x, y):
        model.train()
        yhat = model(x)
        loss = loss_fn(y, yhat)
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        return loss.item()
    return train_step


torch.manual_seed(42)

model = ManualLinearRegression().to(device) 
loss_fn = nn.MSELoss(reduction='mean')
optimizer = optim.SGD(model.parameters(), lr=1e-1)
train_step = make_train_step(model, loss_fn, optimizer)

n_epochs = 50
training_losses = []
validation_losses = []
print(model.state_dict())

for epoch in range(n_epochs):
    batch_losses = []
    for x_batch, y_batch in train_loader:
        x_batch = x_batch.to(device)
        y_batch = y_batch.to(device)
        loss = train_step(x_batch, y_batch)
        batch_losses.append(loss)
    training_loss = np.mean(batch_losses)
    training_losses.append(training_loss)

    with torch.no_grad():
        val_losses = []
        for x_val, y_val in val_loader:
            x_val = x_val.to(device)
            y_val = y_val.to(device)
            model.eval()
            yhat = model(x_val)
            val_loss = loss_fn(y_val, yhat).item()
            val_losses.append(val_loss)
        validation_loss = np.mean(val_losses)
        validation_losses.append(validation_loss)

    print(f"[{epoch+1}] Training loss: {training_loss:.3f}\t Validation loss: {validation_loss:.3f}")

print(model.state_dict())

【问题讨论】:

  • 作为附加信息:如果我不展平张量,我会收到错误:“ValueError:输入长度的总和不等于输入数据集的长度!”

标签: python numpy pytorch


【解决方案1】:

问题在于您如何调用random_split 函数。请注意,它将长度作为输入,而不是拆分的百分比或比率。错误大致相同,即您指定的长度总和(80+20)与数据长度(5)不同。

下面的代码 sn-p 应该可以解决您的问题。此外,您不需要展平张量......我认为。

dataset = TensorDataset(x_tensor, y_tensor)
val_size = int(len(dataset)*0.2)
train_size = len(dataset)- int(len(dataset)*0.2)
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])

【讨论】:

  • 谢谢。这允许代码运行得更远一些。但是,我现在收到错误消息 - “用户警告:使用与输入大小 (torch.Size([10])) 不同的目标大小 (torch.Size([10, 1]))。这可能会导致由于广播而导致的结果不正确。请确保它们具有相同的大小。”代码确实运行,但我为每个计算得到 NaN 值。批量大小都是 10,所以我不确定这是什么意思。
  • @HexNeural 这是另一个问题,需要更多细节/新问题。但是,我可以在 cmets 中提供有限的帮助。 1. 你的标签是 (10,),网络输出是 (10,1)。这就是您收到警告的原因。在这种特定情况下,您可以忽略警告,因为不会出现广播错误或通过重塑任一张量来修复。 2. 你可能会得到 NaN,因为学习率 (LR) 很高。尝试减少 LR,或者甚至更好地尝试只运行前传,看看会发生什么。如果是因为 LR,你不应该只让 Nan 前进。
  • 更新:事实证明,如果我将学习率降低到非常小的值(例如 lr=1e-9),那么脚本实际上会产生输出,而不仅仅是 NaN。再次感谢你。 @Umang Gupta
  • 很高兴它成功了!您的数据范围看起来很奇怪(大数字)。在将其传递给神经网络之前进行一些预处理(例如标准归一化和最小-最大缩放)可能会很好
【解决方案2】:

这个问题是没有批量大小来指定你的所有尺寸都是不同的,所以要解决这个问题

dataset = CustomDataset(x_tensor_flat, y_tensor_flat) # Use this should work equally well

如果你还想使用 TensorDataset

dataset = TensorDataset(x_tensor_flat.unsqueeze(0), y_tensor_flat.unsqueeze(0)) # Make sure they have the same batch dimensions (e.g (1, 100) , (1, 20) # can be different as long as batch matches)

【讨论】:

  • 如果我使用:dataset = TensorDataset(x_tensor_flat.unsqueeze(0), y_tensor_flat.unsqueeze(0)),我得到错误:“ValueError: Sum of input lengths does not equal the length of the输入数据集!
猜你喜欢
  • 2019-07-29
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 2021-06-24
  • 2019-09-02
  • 2021-03-07
相关资源
最近更新 更多