【发布时间】: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 类不包含任何此类属性。
但是说真的,我如何将我的类映射到我的索引?这非常重要,因为我需要检查我的模型并再次加载它以触发预测。这听起来可能很傻,但我真的不知道该怎么做,请帮忙?
【问题讨论】:
-
您可以查看
ImageFolder的source 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