我认为这个问题已经被问过几次了,但我还没有在这里找到一个好的答案。
所以我有一个由 2 个 numpy 数组组成的 Pytorch 数据集。
以下是维度。
特征 = [10000, 450, 28] numpy 数组。 dim_0 = 样本数,dim_1 = 时间序列,dim_2 = 特征。基本上我有一个 450 帧长的数据,其中每帧包含 28 个特征,并且我有 10000 个样本。
label = [10000,450] numpy 数组。 dim_0 = 样本数,dim_1 = 每帧标签。
任务是我需要对每帧进行分类。
我使用以下函数创建了一个 Pytorch 自定义数据集和数据加载器。
label_length = label.size
label = torch.from_numpy(label)
features = torch.from_numpy(features)
train_dataset = Dataset(label, features, label_length)
train_dataloader = DataLoader(train_dataset, batch_size=64, shuffle=True)
As预期,train_dataloader.dataset.data 返回大小为 [10000,450,28] 的张量 伟大的!现在只需从 10000 个样品中取出批次并进行循环! 所以我运行如下代码 - 假设优化器/损失函数都已设置。
train_loss = 0
EPOCHS = 3
for epoch_idx in range(EPOCHS):
for i, data in enumerate(train_dataloader):
inputs, labels = data
print(inputs.size())
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
train_loss += loss.item()
但是我收到此错误:
ValueError: LSTM: Expected input to be 2D or 3D, got 4D 相反
当我检查了输入的维度,它给出了[64 x 10000 x 450 x 28]
为什么dataloader添加了这个批次的维度? (我理解每个文档应该这样做,但我认为它应该从 10000 个样本中取出 64 个样本并创建批次并循环每个批次?
我认为我在某个地方犯了错误,但无法指出我是什么做错了...
编辑:这是我的简单数据集类
class Dataset(torch.utils.data.Dataset):
def __init__(self, label, data, length):
self.labels = label
self.data = data
self.length = length
def __len__(self):
return self.length
def __getitem__(self, idx):
# need to create tensor
#data = torch.from_numpy(self.data)
#labels = torch.from_numpy(self.labels).type(torch.LongTensor)
data = self.data
labels = self.labels
return data, labels
错误的原因是的
__getitem__
方法返回整个数据集和标签,而不是单个样本。因此,当
DataLoader
尝试创建大小为 64 的批次时,它会在数据集的开头添加一个额外的批次维度。
需要修改
__getitem__
方法以返回单个样本及其对应的标签:
class Dataset(torch.utils.data.Dataset):
def __init__(self, label, data):
self.labels = label
self.data = data
def __len__(self):
return len(self.data) # 返回样本数量
def __getitem__(self, idx):
data = self.data[idx]
labels = self.labels[idx]
return data, labels
通过此更改,
__getitem__
将返回索引为
idx
的单个样本及其标签。然后,
DataLoader
将这些单独的样本组合成大小为 64 的批次,从而产生形状为
[64, 450, 28]
的输入张量和形状为
[64, 450]
的标签张量。
此外,请注意
__len__
方法也已更新为返回数据集中的样本数量,而不是标签长度。
以下是更新后的代码:
import torch
class Dataset(torch.utils.data.Dataset):
def __init__(self, label, data):
self.labels = label
self.data = data
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
data = self.data[idx]
labels = self.labels[idx]
return data, labels
# 示例数据
features = torch.randn(10000, 450, 28)
label = torch.randint(0, 2, (10000, 450)) # 假设的标签是二进制的
train_dataset = Dataset(label, features)
train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
for epoch_idx in range(3):
for i, data in enumerate(train_dataloader):
inputs, labels = data
print(inputs.size()) # 应打印 torch.Size([64, 450, 28])
# ...模型的其余训练代码
通过这些更改,的 DataLoader 应该按预期工作,并为的 LSTM 模型提供正确形状的输入张量。
标签:python,pytorch,pytorch-dataloader From: 78328271