Pytorch数据加载器,返回目标形状

n1bvdmb6  于 6个月前  发布在  其他
关注(0)|答案(1)|浏览(74)

我正在运行一个Pytorch模型训练,在那里我定义了要返回的数据集的getitem方法:

def __getitem__(self, ind):
    [...]
    return processed_images, target

字符串
processed_images是具有形状(224,224)的5个RGB图像的序列,而target是具有针对类别目标的独热编码的4-dim向量。
因此,每次调用getitem都会返回,例如:

>> processed_images.shape
(5, 224, 224, 3)
>> target
[0.0, 1.0, 0.0, 0.0]


在训练脚本中,我使用以下方法提取批处理:

train_dataloader = torch.utils.data.DataLoader(
        train_dataset,
        batch_size=batch_size,
        shuffle=True,
        drop_last=False,
        persistent_workers=False,
        timeout=0,
    )

for epoch in range(number_of_epochs):
    for batch_ind, batch_data in enumerate(train_dataloader):
        datas, targets = batch_data


问题是数据具有正确的形状,即22个图像序列的堆栈:

datas.shape
torch.Size([22, 5, 224, 224, 3])


然而,目标以一种奇怪的方式堆叠:

len(targets) = 4
len(targets[0]) = 22


而我期望的是相反的(一个22个元素的列表,每个元素的len=4)。我做错了什么吗?

webghufk

webghufk1#

我已经从下面的描述中重新创建了一个最小功能代码片段(为了更清晰的输出,批量大小为6)。

import torch
from torch.utils.data import Dataset

class CustomImageDataset(Dataset):
    def __init__(self):
        self.name = "test"

    def __len__(self):
        return 100

    def __getitem__(self, idx):
         label = [0, 1.0, 0, 0]
         image = torch.randn((5, 3, 224, 224), dtype=torch.float32)
         return image, label

train_dataset = CustomImageDataset()
train_dataloader = torch.utils.data.DataLoader(
    train_dataset,
    batch_size=6,
    shuffle=True,
    drop_last=False,
    persistent_workers=False,
    timeout=0,
 )

for idx, data in enumerate(train_dataloader):
    datas = data[0]
    labels = data[1]
    print("Datas shape:", datas.shape)
    print("Labels:", labels)
    ("Labels shape:", len(labels))
    print("Labels[0] shape:", len(labels[0]))
    break

字符串
这段代码会产生以下输出:

Datas shape: torch.Size([6, 5, 3, 224, 224])
Labels: [tensor([0, 0, 0, 0, 0, 0]), tensor([1., 1., 1., 1., 1., 1.], dtype=torch.float64), tensor([0, 0, 0, 0, 0, 0]), tensor([0, 0, 0, 0, 0, 0])]
Labels shape: 4
Labels[0] shape: 6


正如你在检查labels时可以清楚地看到的,你的列表被逐元素地附加到一个Tensor上。也就是说,你的one-hot编码列表的所有第0个元素都被放在同一个Tensor中。也就是说,你的labels列表的第0个Tensor。
由于这不是您所期望的结果(您需要一个包含22个条目的列表,每个条目对应一个one-hot-encoding),最简单的方法是直接将标签定义为SenseiH评论中建议的torch.tensor([0, 1.0, 0, 0])
修改后的剪辑看起来像这样:

import torch
from torch.utils.data import Dataset

class CustomImageDataset(Dataset):
    def __init__(self):
        self.name = "test"

    def __len__(self):
        return 100

    def __getitem__(self, idx):
         label = torch.tensor([0, 1.0, 0, 0])
         image = torch.randn((5, 3, 224, 224), dtype=torch.float32)
         return image, label

train_dataset = CustomImageDataset()
train_dataloader = torch.utils.data.DataLoader(
    train_dataset,
    batch_size=6,
    shuffle=True,
    drop_last=False,
    persistent_workers=False,
    timeout=0,
 )

for idx, data in enumerate(train_dataloader):
    datas = data[0]
    labels = data[1]
    print("Datas shape:", datas.shape)
    print("Labels:", labels)
    ("Labels shape:", len(labels))
    print("Labels[0] shape:", len(labels[0]))
    break


输出就是你所期望的:

Datas shape: torch.Size([6, 5, 3, 224, 224])
Labels: tensor([[0., 1., 0., 0.],
        [0., 1., 0., 0.],
        [0., 1., 0., 0.],
        [0., 1., 0., 0.],
        [0., 1., 0., 0.],
        [0., 1., 0., 0.]])
Labels shape: torch.Size([6, 4])

相关问题