PyTorch时间序列建模报错:AssertionError: 张量尺寸不匹配
问题:PyTorch时间序列建模中TensorDataset尺寸不匹配错误
问题背景
我是PyTorch新手,正在尝试用它建模时间序列数据。我有两个列表x和y:x中的每个元素包含29个时间步与4个特征,对应的y元素是第30个时间步的4列数据。创建Tensor数据集时出现以下错误:
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) Input In [35], in <cell line: 2>() 1 # Step 2: Concatenate 'x' and 'y' tensors properly ----> 2 train_dataset = TensorDataset(*x_train_tensors, *y_train_tensors) 3 valid_dataset = TensorDataset(*x_valid_tensors, *y_valid_tensors) 5 # Step 3: Create DataLoader for training and validation sets File ~\anaconda3\lib\site-packages\torch\utils\data\dataset.py:192, in TensorDataset.__init__(self, *tensors) 191 def __init__(self, *tensors: Tensor) -> None: --> 192 assert all(tensors[0].size(0) == tensor.size(0) for tensor in tensors), "Size mismatch between tensors" 193 self.tensors = tensors AssertionError: Size mismatch between tensors
参考代码(报错区域已标记)
import pickle import numpy as np import pandas as pd with open('lists_data.pkl', 'rb') as file: x, y = pickle.load(file) from sklearn.preprocessing import MinMaxScaler # 创建空列表存储归一化后的数据 norm_x = [] norm_y = [] scaler = MinMaxScaler() # 使用zip遍历x和y中对应的DataFrame for temp_x, temp_y in zip(x, y): temp = pd.concat([temp_x, temp_y]) norm_temp = pd.DataFrame(scaler.fit_transform(temp), columns=temp.columns) norm_x.append(norm_temp.iloc[:-1]) # 将除最后一行外的所有行添加到norm_x norm_y.append(norm_temp.iloc[[-1]]) # 将最后一行添加到norm_y from sklearn.model_selection import train_test_split # 将x和y转换为numpy数组以便操作 x_array = np.array(norm_x) y_array = np.array(norm_y) # 设置随机种子以保证可复现性 random_seed = 42 # 将x和y划分为训练集(70%)、验证集(15%)和测试集(15%) x_train, x_temp, y_train, y_temp = train_test_split(x_array, y_array, test_size=0.3, random_state=random_seed) x_valid, x_test, y_valid, y_test = train_test_split(x_temp, y_temp, test_size=0.5, random_state=random_seed) import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset x_train_tensors = [torch.tensor(x, dtype=torch.float32) for x in x_train] x_valid_tensors = [torch.tensor(x, dtype=torch.float32) for x in x_valid] x_test_tensors = [torch.tensor(x, dtype=torch.float32) for x in x_test] y_train_tensors = [torch.tensor(y, dtype=torch.float32) for y in y_train] y_valid_tensors = [torch.tensor(y, dtype=torch.float32) for y in y_valid] y_test_tensors = [torch.tensor(y, dtype=torch.float32) for y in y_test] class RNNModel(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(RNNModel, self).__init__() self.rnn = nn.RNN(input_size, hidden_size, batch_first=True) self.fc = nn.Linear(hidden_size, output_size) def forward(self, x): out, _ = self.rnn(x) out = self.fc(out[:, -1, :]) return out # Error block batch_size = 64 train_dataset = TensorDataset(*x_train_tensors, *y_train_tensors) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) valid_dataset = TensorDataset(*x_valid_tensors, *y_valid_tensors) valid_loader = DataLoader(valid_dataset, batch_size=batch_size)
问题原因
你错误地将每个样本的张量单独传入TensorDataset,而TensorDataset的设计逻辑是:传入的每个张量代表一个数据维度(比如特征、标签),且所有张量的第一维度(样本数)必须一致。你把所有样本张量展开传入,导致第一个张量的第一维度是29(时间步),后续张量的第一维度却是1(单个标签样本),自然触发尺寸不匹配的断言错误。
修复方案
1. 合并样本张量
将每个样本的小张量合并成一个大张量,维度符合模型输入要求:
- 特征张量:形状为
[样本数, 时间步数, 特征数],即(N,29,4) - 标签张量:形状为
[样本数, 特征数],即(N,4)(需要去掉y中多余的(1,4)维度)
2. 修正数据集创建代码
把合并后的特征张量和标签张量传入TensorDataset,而不是展开单个样本。
修改后的报错区域代码如下:
# 合并训练集张量 x_train_tensor = torch.stack(x_train_tensors) # 形状: [N, 29, 4] y_train_tensor = torch.cat(y_train_tensors).squeeze(1) # 形状: [N, 4] # 合并验证集张量 x_valid_tensor = torch.stack(x_valid_tensors) y_valid_tensor = torch.cat(y_valid_tensors).squeeze(1) # 创建数据集和DataLoader batch_size = 64 train_dataset = TensorDataset(x_train_tensor, y_train_tensor) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) valid_dataset = TensorDataset(x_valid_tensor, y_valid_tensor) valid_loader = DataLoader(valid_dataset, batch_size=batch_size)
额外优化建议
其实你可以直接从numpy数组转换为张量,跳过逐个转换再合并的步骤,更高效:
# 直接从numpy数组转张量,无需逐个转换列表 x_train_tensor = torch.tensor(x_train, dtype=torch.float32) # x_train是numpy数组,形状[N,29,4] y_train_tensor = torch.tensor(y_train, dtype=torch.float32).squeeze(1) # y_train形状[N,1,4],squeeze后变为[N,4] x_valid_tensor = torch.tensor(x_valid, dtype=torch.float32) y_valid_tensor = torch.tensor(y_valid, dtype=torch.float32).squeeze(1)
内容的提问来源于stack exchange,提问作者Derek Langley
相关产品推荐
相关产品推荐

