使用 PyTorch 的多标签、多类图像分类器 (ConvNet)

Posted

技术标签:

【中文标题】使用 PyTorch 的多标签、多类图像分类器 (ConvNet)【英文标题】:Multi-label, multi-class image classifier (ConvNet) with PyTorch 【发布时间】:2018-12-01 13:32:29 【问题描述】:

我正在尝试使用 PyTorch 实现一个图像分类器 (CNN/ConvNet),我想从 csv 文件中读取我的标签。我有 4 个不同的类别,一张图片可能属于多个类别。

我已经阅读了PyTorch Tutorial 和this Stanford tutorial 和this one,但它们都没有涵盖我的具体情况。我设法构建了torch.utils.data.Dataset 类的自定义函数,该函数仅适用于从 csv 文件中读取二进制分类器的标签。

这是我目前拥有的torch.utils.data.Dataset 类的代码(根据上面链接的第三个教程稍作修改):

import torch
import torchvision.transforms as transforms
import torch.utils.data as data
from PIL import Image
import numpy as np
import pandas as pd


class MyCustomDataset(data.Dataset):
# __init__ function is where the initial logic happens like reading a csv,
# assigning transforms etc.
def __init__(self, csv_path):
    # Transforms
    self.random_crop = transforms.RandomCrop(800)
    self.to_tensor = transforms.ToTensor()
    # Read the csv file
    self.data_info = pd.read_csv(csv_path, header=None)
    # First column contains the image paths
    self.image_arr = np.asarray(self.data_info.iloc[:, 0])
    # Second column is the labels
    self.label_arr = np.asarray(self.data_info.iloc[:, 1])
    # Calculate len
    self.data_len = len(self.data_info.index)


# __getitem__ function returns the data and labels. This function is
# called from dataloader like this
def __getitem__(self, index):
    # Get image name from the pandas df
    single_image_name = self.image_arr[index]
    # Open image
    img_as_img = Image.open(single_image_name)
    img_cropped = self.random_crop(img_as_img)
    img_as_tensor = self.to_tensor(img_cropped)

    # Get label(class) of the image based on the cropped pandas column
    single_image_label = self.label_arr[index]

    return (img_as_tensor, single_image_label)

def __len__(self):
    return self.data_len

具体来说,我正在尝试从具有以下结构的文件中读取我的标签:

而我的具体问题是,我不知道如何在我的Dataset 类中实现它。我想我错过了 csv 中标签的(手动)分配与 PyTorch 如何读取它们之间的链接,因为我对框架相当陌生。 我将不胜感激有关如何使其工作的任何帮助,或者如果实际上有涵盖此内容的示例,也将非常感谢提供链接!

【问题讨论】:

【参考方案1】:

也许我遗漏了一些东西,但是如果您想将列 1..N(此处为 N = 4)转换为标签向量或形状 (N,)(例如,给定您的示例数据,label(img1) = [0, 0, 0, 1]label(img3) = [1, 0, 1, 0], ...),为什么不呢:

    将所有标签列读入self.label_arr

    self.label_arr = np.asarray(self.data_info.iloc[:, 1:]) # columns 1 to N
    

    相应地返回__getitem__()中的标签(这里没有变化):

    single_image_label = self.label_arr[index]
    

为了训练你的分类器,你可以计算例如(N,) 预测和目标标签之间的交叉熵。

【讨论】:

以上是关于使用 PyTorch 的多标签、多类图像分类器 (ConvNet)的主要内容,如果未能解决你的问题,请参考以下文章

Scikit-learn 使用朴素贝叶斯进行 10 折交叉验证的多类分类

使用 CNN 的多类图像分类中的错误

使用 3 个最高概率的多类分类器的性能

寻找简单阈值分类器的多类阈值

SciKit Learn 中的多类逻辑回归

用于提供多类图像数据集的方法,其中文件夹名称可以用作Pytorch中的标签?