【问题标题】:How to get class_to_idx map for Custom Dataset in Pytorch如何在 Pytorch 中获取自定义数据集的 class_to_idx 映射
【发布时间】:2019-07-11 01:41:06
【问题描述】:

我正在尝试在 Oxford102 类别数据集上使用 CNN (vgg19) 进行迁移学习,该数据集由 8189 个从 1 到 102 标记的花朵样本组成。而不是使用 ImageFolder 加载数据,这需要将我的数据结构化为训练的繁琐过程,有效和测试文件夹,每个类都是保存我的图像的子文件夹,我决定使用自定义数据集类加载它

https://pytorch.org/tutorials/beginner/data_loading_tutorial.html

我为我的项目编写的代码子集

    data_dir_path = 'data/images/'
    labels_path = 'data/imagelabels.mat'
    class_label_path = 'data/class_label_map'

    # standard normalization for Imagenet models mean: [0.485, 0.456,0.406],
    # std :[0.229, 0.224, 0.225]

    data_transforms = {
'train': transforms.Compose([
    transforms.RandomRotation(45),
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406],
                         [0.229, 0.224, 0.225])
]),
'valid': transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406],
                         [0.229, 0.224, 0.225])
]),
'test': transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406],
                         [0.229, 0.224, 0.225])
]),
   }


    class MyDataset(Dataset):

        def __init__(self, image_labels, data_dir, transform=None):

    """

    :param image_labels_path: path to our labels
    :param root_dir: the directory which houses our images
    :param transform: apply any transform on our sample
    """

    self.image_labels = image_labels
    self.root_dir = data_dir
    self.transform = transform

        def __len__(self):
    label_dict = scipy.io.loadmat(self.image_labels)
    return len(label_dict['labels'][0])

        def __getitem__(self, idx):

    image_path_list = [os.path.join(self.root_dir, filename) for filename in os.listdir(self.root_dir)]

    image = Image.open(image_path_list[idx])

    label_dict = scipy.io.loadmat(self.image_labels)
    label_list = label_dict['labels'][0]

    # label index for pytorch should start form zero
    # so subtract -1 from each class
    label_list[:] = [i - 1 for i in label_list]
    label = label_list[idx]  

    if self.transform:
        image = self.transform(image)

    return image, label

    image_datasets = {x: MyDataset(image_labels=labels_path, data_dir=data_dir_path, transform=data_transforms[x]) for x in
              ['train', 'valid', 'test']}

我的模型类实例继承自nn.Module是

    classifier = Neural(25088, [4096], 102)

我从标签列表中减去了 -1,因为 Pytorch 期望标签从 0 开始。因此 102 个标签从 0 到 101。如果我错了,请纠正我,因为如果我不减去一个,则会出现“当前目标 >=0 且当前目标

class_label_map 是一个将类标签映射到花名的字典

    {
"1": "pink primrose",
"2": "hard-leaved pocket orchid",
"3": "canterbury bells",
"4": "sweet pea",
"5": "english marigold",
"6": "tiger lily",
"7": "moon orchid",
"8": "bird of paradise",
"9": "monkshood",
"10": "globe thistle",
"11": "snapdragon",
    }

我的大问题是获得一个 class_to_idx 映射,我该怎么做,如果我将它们可视化,我的花名与图像不匹配,我的花得到完全不同的花名。

我首先创建了一个映射,方法是在减去 1 之前使用带有原始标签键的 dict,然后对之后的值赋值。示例

    class_to_idx = {77:76, 73:72, 1:0, 65:64......102:101...65:54}

这无疑是错误的,因为我的图片标签完全错误。

我的 data_dir_path = 'data/images' 中图像的第一个标签是 77,减去一个我得到 76。 这是否意味着所有标签 76 的索引都是 0,如果下一个类是 72 ,这是否意味着所有类 72 的索引都是 1?所以...

    class_to_idx = {76:0, 72:1, 0:2, 65:3....and so on}

ImageFolder 似乎有一个 class_to_idx 属性,如果在我的数据集上使用它会引发错误,

    image_datasets['train'].class_to_idx

   AttributeError: 'MyDataset' object has no attribute 'class_to_idx'

显然是这种情况,因为我的 Dataset 类不包含任何此类属性。

但是说真的,我如何将我的类映射到我的索引?这非常重要,因为我需要检查我的模型并再次加载它以触发预测。这听起来可能很傻,但我真的不知道该怎么做,请帮忙?

【问题讨论】:

  • 您可以查看ImageFoldersource code 了解class_to_idx 是如何创建的。你可以这样做:classes = os.listdir(/dir/) 然后class_to_idx = {classes[i]: i for i in range(len(classes))} 希望它有所帮助
  • 是的,我只是检查了一下,但不太明白发生了什么,这给了我 { 77: 250, 73: 444 等等 } 但 250 是类更改的索引, 77 应该是 0,因为它是第一个索引?

标签: python-3.x image-processing computer-vision pytorch


【解决方案1】:

我很久以前就完成了这件事,为了它的价值,我愿意付出我的两分钱来告诉我哪里出错了,虽然非常尴尬。我没有对我的 image_path_list 进行排序。它们出现在我的数据文件夹中的顺序与标签文件夹列表中的相应标签不匹配。这是因为 Python 以任意顺序从数据文件夹将它们读取到 image_path_list 中。一个简单的排序把所有东西都整理好了。

    image_path_list = sort([os.path.join(self.root_dir, filename) for filename in os.listdir(self.root_dir)])

【讨论】:

  • 它是排序的,不是排序的。错字。
猜你喜欢
  • 2021-12-12
  • 2021-07-21
  • 2011-03-11
  • 2020-02-18
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 2017-06-14
  • 2011-12-06
相关资源
最近更新 更多