AI备忘录 - 图像分类
type: channel
link: https://aiuai.cn/category/classification/
items: Github项目 - Human Image Gender Classifier
items: 计算机视觉之ViT分类网络
items: 基于深度神经网络的噪声标签学习问题[转]
items: 对比自监督学习框架[译]
items: 无监督学习-MoCoV1&V2
items: Github项目 - AutoAugment 数据增强策略实现
items: EfficientNet - PyTorch及Keras使用
items: 图片标注-基于PyTorch的多标签图像分类[译]
items: 图像标注-基于PyTorch的多输出图像分类[译]
items: End-to-End Multi-label Classification多标签分类[译]

Github项目 - Human Image Gender Classifier
type: item
date: 2022-06-07T19:01:00+08:00
description: Github - Human Image Gender Classifier论文：Expressive Body Capture: 3D Hands, Face, and Body from a Single Image - CVPR2019主页：https://smpl-x.is.tue.mpg.de/基于OpenPose姿态估计结果，裁剪人体并识别人体性别.示例，如图：1. 项目环境Python 3.7TensorFlow 1.13.1ConfigerCUDA-10.0, cuDNN-7.5, Ubuntu 18.04requirements.txt:imageio==2.5.0 pillow numpy==1.16.3 scikit-image==0.15.0 scikit-learn==0.20.3 scipy==1.2.1 tensorflow==1.15.2安装：pip install git+https://github.com/nghorbani/homogenus模型下载，假设权重文件存放路径homogenus/trained_models/tf：https://smpl-x.is.tue.mpg.de/downloadsHomogenus: Human Image Gender Classifier2. 项目源码项目结构：├── homogenus │ ├── tf │ │ ├── homogenus_infer.py │ │ └── __init__.py │ ├── tools │ │ ├── body_cropper.py │ │ ├── image_tools.py │ │ ├── __init__.py │ │ └── omni_tools.py │ └── trained_models │ └── tf │ ├── checkpoint │ ├── TR02_E02_It_002010.ckpt.data-00000-of-00001 │ ├── TR02_E02_It_002010.ckpt.index │ ├── TR02_E02_It_002010.ckpt.meta │ └── version.txt ├── requirements.txt └── setup.py2.1. 模型预测 homogenus_infer.py#!/usr/bin/python3 #!--*-- coding: utf-8 --*-- import tensorflow as tf import numpy as np import os, sys import json import cv2 import glob from homogenus.tools.image_tools import put_text_in_image, fontColors, read_prep_image, save_images from homogenus.tools.body_cropper import cropout_openpose, should_accept_pose from homogenus.tools.omni_tools import makepath class Homogenus_infer(object): def __init__(self, trained_model_dir, sess=None): ''' :param trained_model_dir: the directory where you have put the homogenus TF trained models :param sess: ''' best_model_fname = sorted(glob.glob(os.path.join(trained_model_dir , '*.ckpt.index')), key=os.path.getmtime) if len(best_model_fname): self.best_model_fname = best_model_fname[-1].replace('.index', '') else: raise ValueError('Couldnt find TF trained model in the provided directory --trained_model_dir=%s. Make sure you have downloaded them there.' % trained_model_dir) if sess is None: self.sess = tf.Session() else: self.sess = sess # Load g…

计算机视觉之ViT分类网络
type: item
date: 2021-09-13T22:28:00+08:00
description: 出处：Paddle文档平台 - ViT（ Vision Transformer）1. ViT模型介绍在计算机视觉领域中，多数算法都是保持CNN整体结构不变，在CNN中增加attention模块或者使用attention模块替换CNN中的某些部分。有研究者提出，没有必要总是依赖于CNN。因此，作者提出ViT[1]算法，仅仅使用Transformer结构也能够在图像分类任务中表现很好。受到NLP领域中Transformer成功应用的启发，ViT算法中尝试将标准的Transformer结构直接应用于图像，并对整个图像分类流程进行最少的修改。具体来讲，ViT算法中，会将整幅图像拆分成小图像块，然后把这些小图像块的线性嵌入序列作为Transformer的输入送入网络，然后使用监督学习的方式进行图像分类的训练。该算法在中等规模（例如ImageNet）以及大规模（例如ImageNet-21K、JFT-300M）数据集上进行了实验验证，发现：Transformer相较于CNN结构，缺少一定的平移不变性和局部感知性，因此在数据量不充分时，很难达到同等的效果。具体表现为使用中等规模的ImageNet训练的Transformer会比ResNet在精度上低几个百分点。当有大量的训练样本时，结果则会发生改变。使用大规模数据集进行预训练后，再使用迁移学习的方式应用到其他数据集上，可以达到或超越当前的SOTA水平。2. ViT模型结构与实现ViT算法的整体结构如 图1 所示。图1 ViT算法结构示意图2.1. 图像分块嵌入考虑到在Transformer结构中，输入是一个二维的矩阵，矩阵的形状可以表示为 $(N,D)$，其中 $N$ 是sequence的长度，而 $D$ 是sequence中每个向量的维度。因此，在ViT算法中，首先需要设法将 $H \times W \times C$ 的三维图像转化为 $(N,D)$ 的二维输入。ViT中的具体实现方式为：将 $H \times W \times C$ 的图像，变为一个 $N \times (P^2 * C)$ 的序列。这个序列可以看作是一系列展平的图像块，也就是将图像切分成小块后，再将其展平。该序列中一共包含了 $N=HW/P^2$ 个图像块，每个图像块的维度则是 $(P^2*C)$。其中 $P$ 是图像块的大小，$C$ 是通道数量。经过如上变换，就可以将 $N$ 视为sequence的长度了。但是，此时每个图像块的维度是 $(P^2*C)$，而我们实际需要的向量维度是 $D$，因此我们还需要对图像块进行 Embedding。这里 Embedding 的方式非常简单，只需要对每个 $(P^2*C)$ 的图像块做一个线性变换，将维度压缩为 $D$ 即可。上述对图像进行分块以及 Embedding 的具体方式如 图2 所示。图2 图像分块嵌入示意图具体代码实现如下所示。本文中将每个大小为 $P$ 的图像块经过大小为 $P$ 的卷积核来代替原文中将大小为 $P$ 的图像块展平后接全连接运算的操作。# 图像分块、Embedding class PatchEmbed(nn.Layer): def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768): super().__init__() # 原始大小为int，转为tuple，即：img_size原始输入224，变换后为[224,224] img_size = to_2tuple(img_size) patch_size = to_2tuple(patch_size) # 图像块的个数 num_patches = (img_size[1] // patch_size[1]) * \ (img_size[0] // patch_size[0]) self.img_size = img_size self.patch_size = patch_size self.num_patches = num_patches # kernel_size=块大小，即每个块输出一个值，类似每个块展平后使用相同的全连接层进行处理 # 输入维度为3，输出维度为块向量长度 # 与原文中：分块、展平、全连接降维保持一致 # 输出为[B, C, H, W] self.proj = nn.Conv2D( in_chans, embed_dim, kernel_size=patch_size, stride=patch_size) def forward(self, x): B, C, H, W = x.shape assert H == self.img_size[0] and W == self.img_si…

基于深度神经网络的噪声标签学习问题[转]
type: item
date: 2021-08-11T22:52:00+08:00
description: 基于深度神经网络的噪声标签学习-云社区-华为云 (huaweicloud.com)神经网络的成功建立在大量的干净数据和很深的网络模型基础上。但是在现实场景中数据和模型往往不会特别理想，比如数据层面有误标记的情况，像小狗被标注成狼，而且实际的业务场景讲究时效性，神经网络的层数不能特别深。我们尝试不断迭代数据和模型缺陷情况下神经网络的有效训练方法，通过noisy label learning技术，解决网络训练过程中noisy data的问题，该技术已经在团队实际业务场景中落地，通过从损失函数、网络结构、模型正则化、损失函数调整、样本选择、标签纠正等多个模块的优化，不局限于全监督、半监督和自监督学习方法，提升整个模型的鲁棒性1. 损失函数主要是从损失函数去修改，核心思路是当数据整体是干净的时候，传统的交叉熵损失函数学习到少量的负样本，可以提升模型的鲁棒性；当数据噪声比较大时，CE会被噪声数据带跑偏，我们要修改损失函数使其在训练中每个样本的权重都是一样重要的，因此不难想到采用GCE Loss，控制超参数，结合了CE Loss和MAE LossA. Ghosh, H. Kumar, and P. Sastry,“Robust loss functions under label noise for deep neural networks,” in Proc. AAAI, 2017Generalized Cross Entropy Loss for Training Deep Neural Networks with Noisy Labels, NeurlPS 2018另外，还有从KL散度想法借鉴过来的，作者认为在计算熵的时候，原始q, p代表的真实数据分布和预测值在较为干净的数据上没有问题，但是在噪声比较大的数据上，可能q并不能代表真实数据分布，相反的是不是p可以表示真实数据分布，因此提出基于对称的交叉熵损失函数（Symmetric cross entropy ）Y. Wang, X. Ma, Z. Chen, Y. Luo, J. Yi, and J. Bailey, “Symmetric cross entropy for robust learning with noisy labels,” in Proc. ICCV, 2019, pp. 322–3302. 模型结构主要通过借鉴巧妙的网络结构，在模型训练过程中，通过模型对数据进行挑选，选择一批较为干净的数据，逐步提升模型的鲁棒性。首先要介绍的就是coteaching framework，首先是基于两个模型相互挑选数据输入给对方计算loss，传递给对方网络的数据是每个min-batch里面loss最低的一些数据，随着epoch增加，数据量有所变化，另外每一轮epoch结束，会shuffle数据，保证数据不会被永久遗忘How does Disagreement Help Generalization against Label Corruption? ICML 2019Co-teaching: Robust Training of Deep Neural Networks with Extremely Noisy Labels, NeurlPS 2018还有一种思路，是基于attention注意力机制给干净样本和噪声数据进行打分，文章叫做Attention Feature Mixup，在计算最终loss的时候有两部分，一部分是同一个类的每张图和标签计算的交叉熵损失；另外一个损失是数据mixup得到的新的数据x'和标签y'计算的loss3. 正则化主要是通过一些添加正则ticks，防止模型过拟合到噪声数据上，常用的正则方法包含：label smooth、l1、l2、MixUp等4. 样本选择主要是从如何挑选出更好的数据为出发点，一种方法，叫做Area Under the Margin metric (AUM)，是我们去年参加CVPR WebVision 2020（图像识别领域最高级别的比赛，接替ImageNet）取得冠军的方案。该方案是一种在训练过程中一边训练一边筛选数据的方式，具体思想是在一个min-batch利用模型计算每张图片的logits值和其它类中最大的logits求差值当做area，这样多轮epoch求平均，得到每张图的aum值。试验发现如果这个数据是较为干净的数据area的值会比较大，如果是存在mis-label的数据area值比较小，甚至是负值，作者就是通过这个思想将一个类的干净数据和噪声数据分离开的。当然论文在最后也指出，干净数据和噪声数据占比99%的阈值是最优的。Pleiss, Geoff, et al. "Identifying mislabeled data…

对比自监督学习框架[译]
type: item
date: 2021-06-16T22:22:00+08:00
description: 原文：A Framework For Contrastive Self-Supervised Learning And Designing A New Approach-2020.09.03论文：A Framework For Contrastive Self-Supervised Learning And Designing A New Approach-2020节选，学习.关于对比学习和自监督学习，PyTorch Lightning 开源了相关的代码实现：SELF-SUPERVISED LEARNING，如：[1] - Augmented Multiscale Deep InfoMax (AMDIM)[2] - Bootstrap Your Own Latent (BYOL)[3] - Data-Efficient Image Recognition with Contrastive Predictive Coding[4] - Moco[5] - SimCLR[6] - SwAV[7] - Exploring Simple Siamese Representation Learning (SimSiam)1. 自监督学习监督学习：给定输入 x 和标签 y.图：左-输入x，右-标签y自监督学习：仅有输入 x. 模型学习从输入的其他部分预测输入的一部分.图：左-输入；右-标签自监督学习问题比较通用，相关的前置任务(pretext task)如：[1] - 预测两个图像块的相对位置 [predicting relative locations of two patches][2] - 拼图 [solving a jigsaw puzzle][3] - 图像上色 [colorizing an image]对比学习极大地缩小了在 ImageNet 上与监督学习方法的差距.2. 对比学习大部分机器学习算法的基本思想是，相似样本聚集，而与其他聚类的样本远离.Learning a Similarity Metric Discriminatively, with Application to Face Verification - 2004动画如：对比学习三个部分：anchor、positive、negeative.正样本对，两个样本相似；负样本对，不相似的第三个样本.但是，自监督学习中，样本的标签是未知的，因此无法确定两张图片是否相似.不过，如果假设每个图片是一个类，那么就可以想办法构建 triplets（正负样本对），也就意味着数据集大小为 N 时，会存在 N 个标签.因此，就可以知道每张图片的标签了，可以采用数据增强生成 triplets.2.1. 特征1 - 数据增强第一种表征对比自监督学习方法的方式是，定义数据增强pipline.数据增强pipline $A(x)$ 对相同的输入采用一序列的随机变换.深度学习中，数据增强旨在构建原始输入的对噪声鲁棒的表示. 例如，即使图片旋转，或去除颜色，或像素抖动，网络模型也应该能识别.而对比学习中，数据增强还有第二个作用，即，用于生成 anchor、positive、negative 样本，以送入编码器及提取特征表示.2.1.1. CPCCPC pipline 除了采用如颜色抖动、灰度化、随机翻转等变换，还进行一种特殊变换，即将图片划分为重叠子图像块.图：CPC 的关键变换.CPC 可以生成很多 positive 和 negative 样本集. 图：从 batch 图片中生成positive、anchor、negative 样本对[如，batchsize=3]2.1.2. AMDIMAMDIM 采用的方法略有不同. 其在标准的数据增强后[如，抖动、翻转等]，再通过对相同图片进行两次数据增强，以生成一张图片的两个版本.这种想法实际上是在论文 Discriminative Unsupervised Feature Learning with Convolutional Neural Networks-2014中提出的. 其是采用 seed 图片生成相同图片的许多版本.2.1.3. SimCLR可见视频：https://www.youtube.com/embed/Mrp2ntS2QxI2.2. 特征2 - 编码器第二种表征对比自监督学习方法的方式是，编码器的选择. 大部分方法采用的是 ResNets 及其衍生网络.2.3. 特征3 - 表征提取第三种表征对比自监督学习方法的方式是，提取特征表示所采用的策略.表征的定义：其是一组独特的特征，使得系统和人类能够理解是什么构成了那个对象，那个对象，而不是不同的对象.A representation is the set of unique charact…

无监督学习-MoCoV1&V2
type: item
date: 2021-04-30T21:33:00+08:00
description: 论文：MoCov1 - Momentum Contrast for Unsupervised Visual Representation Learning - 2019论文：MoCov2 - Improved Baselines with Momentum Contrastive Learning - 2020Github - facebookresearch/mocoMoCo，Momentum Contrast，是一种无监督视觉表示学习算法. MoCo 基于对比学习(contrastive learning) 的角度，将问题转换为字典查询(dictionary look-up)，构建了基于队列的动态字典更新(dynamic dictionary with a queue)和滑动平均编码器(moving-averaged encoder)的算法.1. MoCoMoCo 基于的假设：可以通过覆盖大量负样本的大型字典来学习好的特征，且字典 keys 的编码器尽管在不断的更新，但仍应尽可能保持连续性.对于给定的一个样本x， 选择一个(或一批)正样本y(这里正样本对对于图像上的理解就是x的不同的data augmentation版本). 然后选择一批负样本(对于图像来说，就是除了x之外的图像), 然后设计loss function来将x与正样本之间的距离拉近，负样本之间的距离推开.MoCo 主要有如下特点：1.1. InfoNCE 损失函数[1] - 将对比学习问题转化为字典查询问题损失函数(InfoNCE)形式如：$$ L_q = -log \frac{exp(q \cdot k_+/ \tau)}{\sum_{i=0}^K exp(q \cdot k_i / \tau)} $$另一种形式如，$$ L_{q, k_+, \lbrace k_- \rbrace} = -log \frac{exp(q \cdot k_+/ \tau)}{exp(q \cdot k_+/ \tau) + \sum_{k_-} exp(q \cdot k_- / \tau)} $$其中，$q$ 是查询的特征表示；$k_+$ 是正样本(相似)的特征表示，$\lbrace k_- \rbrace$ 是负样本(不相似)的特征表示；$\tau$ 是超参数.损失函数的求和，是对一个正样本和K个负样本进行的，其类似于 (K+1) Softmax 分类的 log 损失函数，其目标是将$q$ 分类为 $k_+$. 参考 SoftmaxEntropyCross 损失：$$ L_{ce} = -log \frac{exp(x_i)}{\sum_j exp(x_j)} $$或，$$ L(x, class) = -log (\frac{exp(x[class])}{\sum_j exp(x[j])}) $$1.2. 动量更新记 $f_k$ 为 key 编码器；$f_q$ 为 q 查询编码器，$\theta_k$ 和 $\theta_q$ 分别为其参数，MoCo 提出的 $\theta_k$ 动量更新方式如：$$ \theta _k \leftarrow m \theta_k + (1 - m) \theta_q $$其中，只有 $\theta_q$ 是需要 BP 梯度计算的. $m$ 为动量系数，实验证明，相对大的动量(如，m=0.999) 比相对小的动量(如，m=0.9) 的效果好很多.1.3. 将字典作为队列MoCo 的核心是，将字典维护为数据样本的队列. 有利于重用训练过程中的历史 mini-batches 的编码 keys. 基于队列的实现，可以将字典大小和 mini-batch size 解耦，且更大. 队列中的样本是渐进式被替代的. 当前 mini-batch 入队列；最老的 mini-batch 出队列. 字典 keys 一般都所有数据的部分采样子集.1.4. Shuffling BNMoCo 论文所述，在标准 ResNet 的 BN 层，会影响模型的训练. 因为模型可能在试图欺骗任务，并容易地找到loss值比较低的方案.而，MoCo 采用的方式是 shuffling BN. 采用多个 GPU 进行训练，分别对每个 GPU 上的样本进行独立的进行BN. 即，对于 key 编码器 $f_k$，在将其分发到各 GPUs 上时，打乱当前 mini-batch 的采样次序；而查询编码器 $f_q$ 的mini-batch 的采样次序保持不变.1.5. MoCo 实现伪代码2. MoCoV2MoCoV2 的提出源于 SimCLR - A Simple Framework for Contrastive Learning of Visual Representations,Si…

Github项目 - AutoAugment 数据增强策略实现
type: item
date: 2021-01-17T17:11:00+08:00
description: Github - AutoAugment论文：AutoAugment - Learning Augmentation Policies from Data - 2018Google AI Blogpost - improving-deep-learning-performance图：ImageNet 数据集上成功的策略. 可以看出，其大部分策略只要是颜色变换.1. autoaugment.pyautoaugment.pyfrom PIL import Image, ImageEnhance, ImageOps import numpy as np import random class ImageNetPolicy(object): """ Randomly choose one of the best 24 Sub-policies on ImageNet. Example: >>> policy = ImageNetPolicy() >>> transformed = policy(image) Example as a PyTorch Transform: >>> transform=transforms.Compose([ >>> transforms.Resize(256), >>> ImageNetPolicy(), >>> transforms.ToTensor()]) """ def __init__(self, fillcolor=(128, 128, 128)): #数据增强策略列表 self.policies = [ SubPolicy(0.4, "posterize", 8, 0.6, "rotate", 9, fillcolor), SubPolicy(0.6, "solarize", 5, 0.6, "autocontrast", 5, fillcolor), SubPolicy(0.8, "equalize", 8, 0.6, "equalize", 3, fillcolor), SubPolicy(0.6, "posterize", 7, 0.6, "posterize", 6, fillcolor), SubPolicy(0.4, "equalize", 7, 0.2, "solarize", 4, fillcolor), SubPolicy(0.4, "equalize", 4, 0.8, "rotate", 8, fillcolor), SubPolicy(0.6, "solarize", 3, 0.6, "equalize", 7, fillcolor), SubPolicy(0.8, "posterize", 5, 1.0, "equalize", 2, fillcolor), SubPolicy(0.2, "rotate", 3, 0.6, "solarize", 8, fillcolor), SubPolicy(0.6, "equalize", 8, 0.4, "posterize", 6, fillcolor), SubPolicy(0.8, "rotate", 8, 0.4, "color", 0, fillcolor), SubPolicy(0.4, "rotate", 9, 0.6, "equalize", 2, fillcolor), SubPolicy(0.0, "equalize", 7, 0.8, "equalize", 8, fillcolor), SubPolicy(0.6, "invert", 4, 1.0, "equalize", 8, fillcolor), SubPolicy(0.6, "color", 4, 1.0, "contrast", 8, fillcolor), SubPolicy(0.8, "rotate", 8, 1.0, "color", 2, fillcolor), SubPolicy(0.8, "color", 8, 0.8, "solarize", 7, fillcolor), SubPolicy(0.4, "sharpness", 7, 0.6, "invert", 8, fillcolor), SubPolicy(0.6, "shearX", 5, 1.0, "equalize", 9, fillcolor), SubPolicy(0.4, "color", 0, 0.6, "equalize", 3, fillcolor), SubPolicy(0.4, "equalize", 7, 0.2, "solarize", 4, fillcolor), SubPolicy(0.6, "solarize", 5, 0.6, "auto…

EfficientNet - PyTorch及Keras使用
type: item
date: 2020-06-03T12:59:00+08:00
description: EfficientNet 是一种新的模型缩放方法，准确率比之前最好的Gpipe提高了0.1%，但是模型更小更快，参数的数量和FLOPS都大大减少，效率提升了10倍.1. EfficientNet 简述将 EfficientNet 划分为 base model 和 building block 两部分来分述. 众所周知的，经典 ResNet 模型的 building block 是恒等映射和卷积(identity and convolution block).Efficient 的主要 building block 是 MBConv(mobile inverted bottleneck)，其是在 MobileNetV2 中首先被提出的. 与展开的网络层相比，在 bottlenecks 间直接采用 shortcuts 连接的通道数量会少很对; 结合 depthwise separable convolution，相比较与传统网络层，能够有效的减少计算量，缩减因子几乎是 k^2. 其中，k 表示 kernel size，指定了 2D 卷积滑窗的 height 和 width.By using shortcuts directly between the bottlenecks which connects a much fewer number of channels compared to expansion layers, combined with depthwise separable convolution which effectively reduces computation by almost a factor of k^2, compared to traditional layers. Where k stands for the kernel size, specifying the height and width of the 2D convolution window.EfficientNet 还增加了 squeeze-and-excitation(SE) optimization，其有助于进一步提升性能.另外，EfficientNet 的另一个优势在于，通过仔细的平衡网络深度(depth)、宽度(width) 和分辨率(resolution)，以便更有效的扩展，获得更好的性能.如图，从最小的 EfficientNet B0 到最大的 B7，精度在稳步增加，同时模型参数保持相对小的大小.相比于 ImageNet 同样精度的其它模型，EfficientNet 参数量少很多. 例如，ResNet50 模型在 Keras 实现中参数量共 23534592，即使其精度不如最小的 EfficientNet B0，B0 的参数两仅有 5330564.2. PyTorch - EfficientNetGithub - lukemelas/EfficientNet-PyTorch2.1. 安装Pip 安装：pip install efficientnet_pytorch或源码安装：git clone lukemelas/EfficientNet-PyTorch cd EfficientNet-Pytorch pip install -e .2.2. 加载EfficientNet 的加载：from efficientnet_pytorch import EfficientNet # 加载网络结构，无预训练权重参数 model = EfficientNet.from_name('efficientnet-b0') print(model) # 加载网络结构，带预训练权重参数 model = EfficientNet.from_pretrained('efficientnet-b0') print(model)提供的预训练权重的精度：Name# ParamsTop-1 Acc.Pretrained?efficientnet-b05.3M76.3✓efficientnet-b17.8M78.8✓efficientnet-b29.2M79.8✓efficientnet-b312M81.1✓efficientnet-b419M82.6✓efficientnet-b530M83.3✓efficientnet-b643M84.0✓efficientnet-b766M84.4✓2.3. 修改输出层修改网络输出层：原： (_conv_head): Conv2dStaticSamePadding( 320, 1280, kernel_size=(1, 1), stride=(1, 1), bias=False (static_padding…

图片标注-基于PyTorch的多标签图像分类[译]
type: item
date: 2020-05-19T12:50:00+08:00
description: 原文：Multi-Label Image Classification with PyTorch: Image Tagging - 2020.05.03作者：Victor Bebnev (Xperience.AI)实现：Github - PyTorch-Multi-Label-Image-Classification-Image-Tagging在 图像标注-基于PyTorch的多输出图像分类 中，主要是针对每张图片输出固定数量标签的场景(mult-outputs).1. 多标签分类首先，明确下多标签分类(multi-label classification) 的定义，以及其与多类别分类(multi-class classification) 的区别.根据 scikit-learn 中所述，multi-label 分类是对每个样本分配一组目标标签集；而，multi-class 分类是假设每个样本仅有目标标签集中的一个标签. 此外，multi-label 分类中，每个样本的所有标签不是互斥的(mutually exclusive).在 Multi-Label Image Classification with PyTorch 中，是 multi-output 的分类问题，其处理的也是每个样本多个标签的分类问题. multi-output 分类问题，其往往预测的是每个样本的固定数量的标签；且，理论上可以由相应输出标签数量的独立分类器来替代. 而，multi-label 分类问题往往需要预测非固定数量的标签.multi-output 分类问题必须知道有几个独立的问题，每个问题有且仅有一个可能的答案.为了总结不同分类任务间(multi-class、multi-output、multi-label)的差异性，以下图为例说明. 图-标签可以是：portrait, woman, smiling, brown hair, wavy hairTypePredicted labelsPossible labelsMulti-class classificationsmiling[neutral, smiling, sad]Multi-output classificationwoman, smiling, brown hair[man, woman, child] [neutral, smiling, sad] [brown hair, red hair, blond hair, black hair]Multi-label classificationportrait, woman, smiling, brown hair, wavy hair[portrait, nature, landscape, selfie, man, woman, child, neutral emotion, smiling, sad, brown hair, red hair, blond hair, black hair]在现实生活中，比如 Instagram 标签，用户往往是从标签池里选择某些标签对图片进行标注(为了举例说明，这里假设标签池是固定的). 这些标签往往不是互斥的，它们表征的是图片里所刻画的特征，如“woman”, “wavy hair”, “smiling girl”, “cool shirt”；或者更高层次的语义，如 “portrait”, “happiness”, “fun”.下面以 NUS-WIDE 数据集为例进行说明.2. 数据集这里采用 NUS-WIDE 数据集中的一部分. 该数据集每张图片被标注了多个标签. 其图片收集自 Flickr，包含了超过 1000 个不同标签，最终被收窄到 81 个. 例如，2.1. 数据集划分NUS-WIDE 数据集共包含约 170K 个样本，其标签是高度不均衡的. 例如，对于某些标签，如 sky 和 clouds，数量量约 61000 和 45000；而对于其它标签，如 map 和 earthquake，数量仅为 50.鉴于这里的主要目的是阐述如何处理 multi-label 分类问题，所以将问题进行简化. 仅保留 27 个最频繁出现的标签，使得每个标签具有超过 100 个样本. 此外，为了快速模型训练，仅使用数据集中的前 6000 个样本. 并按照 5:1 来划分为 train 和 val 数据集. 最终得到训练数据集为 5000 张图片，测试数据集为 1000 张图片.图- NUS-WIDE 数据集的标签分布.2.2. 数据处理实现每条标注数据格式类似于：[ 'samples': [ {'image_name': '51353_2739084573_16e9be31f5_m.jpg' , 'image_…

图像标注-基于PyTorch的多输出图像分类[译]
type: item
date: 2020-05-18T12:35:00+08:00
description: 原文：Multi-Label Image Classification with PyTorch - 2020.04.04作者：Dmitry Retinskiy (Xperience.AI)实现：Github - PyTorch-Multi-Label-Image-Classification自从 2012 年 ImageNet 竞赛中神经网络第一次赢得比赛， Alex Krizhevsky, Ilya Sutskever 和 Geoffrey Hinton 彻底改变了图像分类领域.如今，图像的单标签任务(即，图像识别)，已经被广泛研究和解决. 然而，现实场景中，往往不局限于“每张图片仅有一个标签” 的任务，某些时候，每张图片会有更多标签.对此，这里研究的是多输出图像分类(multi-output classification) 或图像标注(image tagging).1. 多标签分类的场景在图像分类领域中，可能会遇到这样的场景：判断目标的集中属性. 例如，类别、颜色、尺寸、等等. 相比较于传统图像分类，其输出将会包含2个及以上的属性.这里关注的问题是，提前已知属性的数量(the number of the properties). 这种任务被称为多输出分类. 实际上，其是多标签分类(multi-label classification)的一种特殊形式，后者处理的也是预测几种属性，但其数量对于每个样本可能都是不同的.2. 数据集Kaggle - Fashion Product Images. 其共有超过 44000 张服装图像，每个图像包含有 9 个标签. 这里仅采用三个标签：gender, articleType 和 baseColour. 示例如下：数据提取后，分布情况为：[1] - 5 个 gender 标签：Boys, Girls, Men, Unisex, Women[2] - 47 种 colors[3] - 143 种类目，如Sports Sandals, Wallets, Sweaters.基于该数据集，下面会创建神经网络模型，并进行训练，预测数据集中图片的三种标签(gender, article, and color).2.1. 数据集划分数据集共采用 40000 张图像，其中 320000 训练数据集，8000 测试数据集. split_data.py:import argparse import csv import os import numpy as np from PIL import Image from tqdm import tqdm def save_csv(data, path, fieldnames=['image_path', 'gender', 'articleType', 'baseColour']): with open(path, 'w', newline='') as csv_file: writer = csv.DictWriter(csv_file, fieldnames=fieldnames) writer.writeheader() for row in data: writer.writerow(dict(zip(fieldnames, row))) def split_data(): input_folder = "fashion-product-images" output_folder = "fashion-product-images" annotation = os.path.join(input_folder, 'styles.csv') # open annotation file all_data = [] with open(annotation) as csv_file: reader = csv.DictReader(csv_file) # each row in the CSV file corresponds to the image for row in tqdm(reader, total=reader.line_num): # we need image ID to build the path to the image file img_id = row['id'] # gender = row['gender'] articleType = row['articleType'] baseColour = row['baseColour'] img_name = os.path.join(input_folder, 'images', str(img_id) + '.jpg') if os.path.exists(img_name…

End-to-End Multi-label Classification多标签分类[译]
type: item
date: 2020-05-15T12:36:00+08:00
description: 原文：End-to-End Multi-label Classification - 2020.05.08Kaggle：Example of multi-label multi-class classification作者：Bhartendu1. Multi-Label classification在机器学习领域，多标签分类及其强相关的多输出分类(multi-output classification)是分类问题的一种变形，其针对的是每个实例可以被指定多个类别标签. 多标签分类是多类别分类(multiclass classification) 的一种泛化，后者是将实例精确地分类到多个类别(超过两个)中的某个标签的单标签问题. 而，对于多标签分类问题，没有限定实例能被指定的类别标签数量.正式地，多标签分类针对的问题是，构建输入 $\mathbf{x}$ 到二值向量 $\mathbf{y}$ 的模型，其中，向量 $\mathbf{y}$ 中的每个元素(标签)的值为 0 或 1.这里举例说明多标签问题:服装主体包含多个属性(标签)，如颜色、图案、类目、场景等. 每个属性有其自己的类别，比如，场景可以被分类为运动(Sports)、正式(Formal)、民族(Ethnic)、休闲(Casual). 可以采用的数据集有：DeepFashion, FashionGen. 这里以 Kaggle fashion_small 数据集为例.2. Fashion_small 数据探索fashion_small 数据集共包含 21K 服装主体. 这里对每个标签中的每个类设置最小样本数 $\mathbf{s}$. 对于每个标签中的所有类设置固定的数量.最小样本数：$\mathcal{s} = 700$.如图，为每个标签的条形图(移除数量小于 $\mathcal{s}$ 的类)：Attributes | Number of classes ------------------------------------------------- gender | 3 subCategory | 2 articleType | 5 baseColour | 8 season | 2 usage | 4 -------------------------------------------------- Total number of label | 6 Total number of classes | 24 Total number of images | 10809样例图片如下(不同标签的不同类)：最终的数据组织形式为(DataFrame)：因此，最终服装主体识别问题为，多标签(6个)多类别(24个)问题.2.1. 数据探索完整实现该部分的代码实现为：import os import json import warnings warnings.filterwarnings('ignore') import pandas as pd import numpy as np import seaborn as sns import matplotlib.image as mpimg import matplotlib.pyplot as plt from collections import Counter, defaultdict from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder from keras.preprocessing import image from keras.models import Model, load_model from keras.layers import Input, Dense, Dropout, Conv2D, MaxPooling2D from keras.layers import BatchNormalization, add, GlobalAveragePooling2D from keras.callbacks import EarlyStopping, ModelCheckpoint from keras.utils.np_utils import to_categorical from keras.utils import plot_model # path = '/path/to/fashion_small/' table = 'styles.csv' base = path+'resized_images/' print('\nDirectory contains…