多标签分类与视觉属性预测

0. 问题概述

对于标签分类问题,表示事物本身可以分为多个类别,但是对于每一个样本存在至少一个类别,例如分类猫、狗、植物、动物。一个样本是猫的同时,又属于动物。因此就不能再像以往的模型一样,输出用softmax激活函数激活,因为我们最终的输出标签可能同时有很多的类,例如鸟类有羽毛和啄。

1. 搭建模型

通常对多标签任务可以采取两种网络模型,一种是直接输出一个全连接层分支,最后一层输出的神经元数应与标签数量相同,使用Sigmoid函数激活,将数值映射在0~1之间。不像Softmax函数,最后一层输出层数值之和并不等于1,而是全部都介于0与1之间,这样我们便可以设置一个阈值,当某类输出层数值大于这个阈值,则判断该标签为Positive,反之为Negative。模型如下图所示:

假设我们的图像属性类别为C∈{c1,c2,...,cN}C \in \{c_1,c_2,...,c_N\}C∈{c1​,c2​,...,cN​},NNN个标签类。最后一层的输出为f∈Rbatch×Nf \in \mathbb{R}^{batch \times N}f∈Rbatch×N,经过Sigmoid函数激活输出的值在0-1之间,则判断属性时只要设置阈值threshthreshthresh,大于阈值表示该标签存在,否则不存在:
ci={1fi≥thresh0fi<threshc_i = \left\{\begin{matrix} 1 & f_i \geq thresh \\ 0 & f_i < thresh \end{matrix}\right. ci​={10​fi​≥threshfi​<thresh​

2. 损失函数与标签数据平衡

由于最后的激活函数是Sigmoid函数,因此我们需要用二分类的损失函数:Binary Cross Entropy。假设预测为xxx,标签为yyy,xxx为经过激活函数Sigmoid的结果。则我们可以构建损失函数:

l(xn,yn)=−ωn[yn⋅log⁡xn+(1−yn)⋅log⁡(1−xn)]l(x_n,y_n)=-\omega_n \begin{bmatrix} y_n\cdot \log x_n +(1-y_n) \cdot \log(1-x_n) \end{bmatrix} l(xn​,yn​)=−ωn​[yn​⋅logxn​+(1−yn​)⋅log(1−xn​)​]

我们会考虑到,不同的标签会存在正样本与负样本失衡的情况,例如300张图像中,红色翅膀属性有100,蓝色翅膀属性有200,正负样本不均匀,因此需要我们调节正负样本比例,但是数据不好扩增,因此我们可以修改损失函数:

ln,c=−ωn,c[pcyn,c⋅log⁡xn,c+(1−yn,c)⋅log⁡(1−xn,c)]l_{n,c}=-\omega_{n,c} \begin{bmatrix}p_c y_{n,c}\cdot \log x_{n,c} +(1-y_{n,c}) \cdot \log(1-x_{n,c})\end{bmatrix} ln,c​=−ωn,c​[pc​yn,c​⋅logxn,c​+(1−yn,c​)⋅log(1−xn,c​)​]

其中ω\omegaω为调节不同属性的重要性,例如我希望模型更倾向于红色翅膀属性预测的正确性,可以在该类下调大比例。ppp为调节正负样本均衡的参数,例如在红色翅膀属性下,有100个正例,400个负例,则在该属性下的ppp我们可以设置为:400100=4\frac{400}{100}=4100400​=4。在Pytorch框架中函数torch.nn.BCEWithLogitsLoss实现了该功能,其中ω\omegaω对应超参weightweightweight,ppp对应超参pos_weight。更多细节见BCEWithLogitsLoss。

3. 视觉属性预测

基于深度学习的视觉属性通常预测方法包括多标签分类多任务学习,在TPAMI 2018一篇文章中提到:

Attribute learning problem can be formulated in the multi-task learning framework, where each task corresponds to learning one semantic attribute.

属性学习问题可以在多任务学习框架中形成,每个任务对应学习一个语义属性。


即可以在最后一层连接多个softmax二分类层或者用Sigmoid激活向量做多属性预测,通常其也会加入原物体类别信息,这样是防止偏见性。例如海豹在海水中,蓝色并不能作为海豹的属性,加入人为先验会更好一些,当然也可以直接进行属性预测。


在论文MAAD-Face: A Massively Annotated Attribute Dataset for Face Images中提供了人脸属性的标注,数据集来源于VGGFace2,在该数据集上训练了一个人脸属性模型,具体便是采用多任务学习的方法。Backbone便采用了Resnet50,最后的特征共享,并行输出多个全连接层。例如性别一栏,人只有男女之分,因此我不需要对男女进行二分类,而是直接分类性别,非男即女。种族也是,只有黄种人,白种人和黑种人,这个分支只输出3类。而人的胡子却不一样,有的人会同时有山羊胡和痄腮胡等,因此需要多个二分网络,最终将多个任务的交叉熵loss直接求和即可。这里值得提及一下pytorch的多输出网络方便的实现方法,以及多任务交叉熵Loss的写法,首先大概展示下网络的架构,与论文Multi-task deep neural network for multi-label learning中一个架构相似,如下图(a)所示:

下方代码主要部分是函数_make_multi_output,这里需要注意的是nn.ModuleList,因为循环中没有顺序,所以不能用nn.Sequential。如果不加nn.ModuleList而只用列表存储,则在model.cuda时不会将列表中的模型参数放入GPU,因为列表不会被识别为pytorch的方法。

class ResNet(nn.Module):def __init__(self, block, layers, attribute_classes):self.inplanes = 64super(ResNet, self).__init__()self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)self.layer1 = self._make_layer(block, 64, layers[0])self.layer2 = self._make_layer(block, 128, layers[1], stride=2)self.layer3 = self._make_layer(block, 256, layers[2], stride=2)self.layer4 = self._make_layer(block, 512, layers[3], stride=2)self.avgpool = nn.AvgPool2d(7, stride=1)self.layers = self._make_multi_output(block, attribute_classes)for m in self.modules():if isinstance(m, nn.Conv2d):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')elif isinstance(m, nn.BatchNorm2d):nn.init.constant_(m.weight, 0.001)nn.init.constant_(m.bias, 0)def _make_layer(self, block, planes, blocks, stride=1):downsample = Noneif stride != 1 or self.inplanes != planes * block.expansion:downsample = nn.Sequential(nn.Conv2d(self.inplanes, planes * block.expansion,kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(planes * block.expansion),)layers = []layers.append(block(self.inplanes, planes, stride, downsample))self.inplanes = planes * block.expansionfor i in range(1, blocks):layers.append(block(self.inplanes, planes))return nn.Sequential(*layers)def _make_multi_output(self,block,attribute_classes):"""Created by Ruoyu Chen on 07/15/2021"""layers = []for i in range(attribute_classes):layers.append(nn.Linear(512*block.expansion, 2))return nn.ModuleList(layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)x = self.avgpool(x)x = x.view(x.size(0), -1)outs = []for layer in self.layers:outs.append(layer(x))return outs

损失函数需要注意的是outs和labels的shape:

class MultiBranchLabelLoss(nn.Module):def __init__(self):super(MultiBranchLabelLoss, self).__init__()self.criterion = nn.CrossEntropyLoss()  # Input (N,C), Target (C)def forward(self, outs, labels):"""outs: List[Torch_size(batch,2)]labels: Torch_size(batch, attributes)"""loss = 0for out,label in zip(outs,labels.t()):# out: Torch_size(batch,2)# label: Torch_size(batch)criterion_loss = self.criterion(out, label)loss += criterion_lossreturn loss

4. 物体检测的属性数据集

最早的关于物体检测中的属性分布,原网站https://vision.cs.uiuc.edu/attributes/,基于Pasc VOC2008标注,2009年的一篇文章。

最新根据CVPR2021的一篇文章Learning To Predict Visual Attributes in the Wild的统计,有如下的最新的物体检测相关属性数据集:

5. 多任务学习

Multitask Learning: A Knowledge-Based Source of Inductive Bias

6. 根据多标签学习训练Pasc VOC2008属性

首先,根据pasc voc2008数据集,下载:https://www.kaggle.com/sulaimannadeem/pascal-voc-2008

代码及结果请见我的github:https://github.com/RuoyuChen10/Multi-label-on-VOC2008-attributes

多标签分类与多任务学习相关推荐

  1. 机器学习之深度学习 二分类、多分类、多标签分类、多任务分类

    多任务学习可以运用到许多的场景. 首先,多任务学习可以学到多个任务的共享表示,这个共享表示具有较强的抽象能力,能够适应多个不同但相关的目标,通常可以使主任务获取更好的泛化能力. 此外,由于使用了共享表 ...

  2. One-Error多标签分类_深度学习:如何在多标签分类问题中考虑标签间的相关性?

    1 多标签问题的简单解决思路 利用神经网络,我们可以很轻松处理一个多标签问题.如标题图所示,为前馈神经网络添加适当数量的隐含层,同时在输出层使用某个阈值判断标签分类结果即为一种基础的解决思路. 上述是 ...

  3. 多标签分类的学习感悟

    多标签学习 问题来源 定义 背景 分类算法 应用前景 最新进展 博主也是刚开始接触多标签分类相关的学习,如果有不正确的地方希望大家指正 1.问题来源 多标签学习概念的提出源于文档分类中遇到的多义性问题 ...

  4. 多标签分类怎么做?教你4招

    首先简单介绍下,多标签分类与多分类.多任务学习的关系: 多分类学习(Multi-class):分类器去划分的类别是多个的,但对于每一个样本只能有一个类别,类别间是互斥的.例如:分类器判断这只动物是猫. ...

  5. 【机器学习】多标签分类怎么做?(Python)

    一.基本介绍 首先简单介绍下,多标签分类与多分类.多任务学习的关系: 多分类学习(Multi-class):分类器去划分的类别是多个的,但对于每一个样本只能有一个类别,类别间是互斥的.例如:分类器判断 ...

  6. 多标签分类怎么做?(Python)

    一.基本介绍 首先简单介绍下,多标签分类与多分类.多任务学习的关系: 多分类学习(Multi-class):分类器去划分的类别是多个的,但对于每一个样本只能有一个类别,类别间是互斥的.例如:分类器判断 ...

  7. 使用 scikit-learn 实现多类别及多标签分类算法

    多标签分类格式 对于多标签分类问题而言,一个样本可能同时属于多个类别.如一个新闻属于多个话题.这种情况下,因变量yy需要使用一个矩阵表达出来. 而多类别分类指的是y的可能取值大于2,但是y所属类别是唯 ...

  8. 多分类学习、多标签学习、多任务学习的区别

    Multi-class. Multi-label . Multi-task 三者之间的区别与相同之处 1.直观解释 多分类学习(Multi-class) 一个分类器,但分的类别是包含多个的.例如:分类 ...

  9. 【小白学习PyTorch教程】十六、在多标签分类任务上 微调BERT模型

    @Author:Runsen BERT模型在NLP各项任务中大杀四方,那么我们如何使用这一利器来为我们日常的NLP任务来服务呢?首先介绍使用BERT做文本多标签分类任务. 文本多标签分类是常见的NLP ...

  10. 多任务学习(Multi-Task Learning, MTL)、其他分类形式、与迁移学习的关系

    多任务学习(Multi-Task Learning, MTL).其他分类形式.与迁移学习的关系 目录 多任务学习(Multi-Task Learning, MTL).其他分类形式.与迁移学习的关系

最新文章

  1. 知识图谱和图分析与可视化
  2. UVA1587-Box
  3. IJ 自动生成构造方法
  4. 01-复杂度3 二分查找
  5. 常见的异步方式async 和 await
  6. 64位Ubuntu kylin 16.04安装wine QQ
  7. 服务器不稳定 如何让百度重新收录网站,教你如何让百度重新收录首页
  8. 安装TensorFlow中遇到的问题(汇总)
  9. bearer token_四,接口认证方式:Bearer Token
  10. 开源容器云openshift pdf_OpenShift和Kubernetes的10个最重要的区别
  11. kafka报错 WARN Session 0x0 for server null, unexpected error, closing socket connection
  12. matlab单元刚度矩阵整合成整刚,空间四面体单元刚度矩阵的Matlab向量化集成.pdf...
  13. 设置单行省略的时候在搜狗浏览器里面导致页面布局紊乱
  14. 2021 年推荐免费网络托管免费空间提供商
  15. SQL SERVER SSMS查询分析器窗口关掉后没有保存的SQL找回-图文说明
  16. 一闪一闪的星星特效效果
  17. MOS管开启过程中VGS的台阶——米勒平台?
  18. 2020大疆校招嵌入式B卷编程题
  19. 信息学奥赛一本通c++【1033】
  20. 选择软件测试,你后悔吗?

热门文章

  1. backtrack5 live cd启动时出现high-speed usb device停住不动解决方法
  2. QML 图形渲染 - Displace
  3. python文件转换为pyd
  4. 使用wireshark分析HTTPS数据包
  5. element ui的upload上传视频内容
  6. kika平台广告sdk集成问题
  7. 服装制图软件测试初学者,服装行业版软件测试文案.ppt
  8. java爬取国家应急平台漏洞公告数据
  9. Typecho中handsome主题如何增加侧边导航栏
  10. Gris 游戏开发-day04