600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 细粒度分析与Bilinear CNN model(附代码实现)

细粒度分析与Bilinear CNN model(附代码实现)

时间:2023-08-23 13:25:52

相关推荐

细粒度分析与Bilinear CNN model(附代码实现)

前言

有时,我们逛街时看到不同的狗,却不知道其具体品种,看到路边开满鲜花,却傻傻分不清具体是什么花。实际上,类似的问题在实际生活中屡见不鲜,人类尚且如此,更别说人工智能了。为了解决这一问题,研究者们提出了细粒度分析(fine-grained image analysis)这一专门研究物体精细差别的方向。

细粒度分析

细粒度分析任务相较于通用图像(general/generic images)任务的区别和难点在于其图像所属类别的粒度更为精细。下图为例,通用图像分类其任务诉求是将“袋鼠”和“狗”这两个物体大类(蓝色框和红色框中物体)分开,可见无论从样貌、形态等方面,二者还是能很容易被区分;而细粒度图像分类任务则要求对“狗”类别下细粒度的子类,即分别对“哈士奇”和“爱斯基摩犬”的图像分辨出来。正因同类别物种的不同子类往往仅在耳朵形状、毛色等细微处存在差异,可谓“差之毫厘,谬以千里”。不止对计算机,对普通人来说,细粒度图像任务的难度和挑战无疑也更为巨大。

近年来,随着AI的发展,深度学习方面的细粒度图像分析任务可分为细粒度图像分类(fine-grained image classification)和细粒度图像检索(fine-grained image retrieval)两大经典图像研究方向。

细粒度图像分类

由于细粒度物体的差异仅体现在细微之处,如何有效地对图像进行分析检测,并从中发现重要的局部区域信息,成为了细粒度图像分类算法要解决的关键问题。对细粒度分类模型,可以按照其使用的监督信息的多少,分为“基于强监督信息的分类模型”和“基于弱监督信息的分类模型”两大类。

基于强监督信息的细粒度图像分类模型

所谓“强监督细粒度图像分类模型”是指,在模型训练时,为了获得更好的分类精度,除了图像的类别标签(label)外,还使用了物体标注框(object bounding box)和 部位标注点(part annotation)等额外的人工标注信息,这点与目标检测(Detection)与图像分割(Segmentation)的含义是相同的,如下图所示:

常见的强监督信息细粒度分类的经典模型有Part-based R-CNN、Pose Normalized CNN、Mask-CNN,这里不再详细赘述。

基于弱监督信息的细粒度图像分类模型

基于强监督信息的分类模型虽然取得了较满意的分类精度,但由于标注信息的获取代价十分昂贵,在一定程度上也局限了这类算法的实际应用。因此,目前细粒度图像分类的一个明显趋势是,希望在模型训练时仅使用图像级别标注信息(即图片的label),而不再使用额外的object bounding box和part annotation信息,也能取得与强监督分类模型可比的分类精度,这便是“基于弱监督信息的细粒度分类模型”。思路同强监督分类模型类似,基于弱监督信息的细粒度分类模型也需要借助全局和局部信息来做细粒度级别的分类。而区别在于,弱监督细粒度分类希望在不借助object bounding box和part annotation的情况下,也可以做到较好的局部信息的捕捉。当然,在分类精度方面,目前最好的弱监督分类模型仍与最好的强监督分类模型存在差距(分类准确度相差约1~2%)。常见的基于弱监督信息的细粒度图像分类模型有Two Level Attention Model、Constellations、Bilinear CNN model。

细粒度图像检索

图像分析中除监督环境下的分类任务,还有另一大类经典任务——无监督环境下的图像检索。图像检索(image retrieval)按检索信息的形式,分为“以文搜图”(text-based)和“以图搜图”(image-based),这里具体就不介绍了。

Bilinear CNN model

双线性模型(Bilinear CNN model)是基于弱监督信息的细粒度图像分类模型,在与Bilinear CNN Models for Fine-grained Visual Recognition》被提出来用于fine-grained分类。

我们知道,深度学习成功的一个重要精髓,就是将原本分散的处理过程,如特征提取,模型训练与决策等,整合进了一个完整的系统,进行端到端的整体优化训练,不需要人来干预了。并且,对于图像的不同特征,我们常用的方法是进行连接(特征图尺寸不变,通道数增加),或者进行加和(特征图同一位置像素值相加,通道数不变),或者max-pooling(通道数不变,特征图尺寸变小)。

研究者们通过研究人类的大脑发现,人类的视觉处理主要有两条pathway(通路),一条是the ventral stream,对物体进行识别,另一条是the dorsal stream,为了发现物体的位置。作者基于这样的思想,希望能够将两个不同特征进行融合来共同发挥作用,提高细粒度图像的分类效果,即希望两个特征能分别表示图像的位置和对目标进行识别,模型框架如下:

一种对Bilinear CNN模型的解释是,网络A的作用是对物体/部件进行定位,即完成物体与局部区域检测工作,而网络B则是用来对网络A检测到的物体位置进行特征提取。两个网络相互协调作用,完成了细粒度图像分类过程中两个最重要的任务:物体、局部区域的检测与特征提取

两个不同的stream代表着通过CNN得到的不同特征,然后将两个特征进行bilinear操作。一个 bilinear CNN model 由四元组构成,β=(fA,fB,P,C)\beta=(f_A,f_B,P,C)β=(fA​,fB​,P,C),其中fAf_AfA​ 和 fBf_BfB​ 代表特征提取函数,即网络中的A、B,PPP 是一个池化函数(pooling function),C表示分类器。图像 III 的特征的每一个位置 lll,进行如下计算:

具体来讲,过程如下:

就是先把在特征图同一位置上的特征进行矩阵相乘,得到矩阵 bbb ,对所有位置的 bbb 进行sum pooling(也可以是 max pooling,但一般采用 sum pooling 以方便进行矩阵运算)得到矩阵 ξ\xiξ。比如,对于一个CNN来讲,输入的特征图有c个通道数,那么在位置 III 上的特征就是1*c 的大小,然后与同一位置上,不用CNN得到的 1*c 的矩阵进行乘积,得到c*c矩阵,然后将所有位置上的 c*c 的矩阵进行求和(就得到了 ξ\xiξ ),再转换成向量的形式就可以得到Bilinear vector,即上图中的xxx 。对 xxx 进行 y=sign(x)∣x∣y=sign(x)\sqrt{|x|}y=sign(x)∣x∣​ 操作,再对得到的 yyy 进行 L2归一化操作 z=y/∣∣y∣∣2z=y/||y||_2z=y/∣∣y∣∣2​,然后我们就可以把特征 zzz 用于细粒度图像分类(fine-grained image classification)了。

L2归一化操作具体参考L2范数归一化。

上面的解释可能看的很懵,举一个例子来说明吧。如使用VGG Conv5_3 输出特征图维度为12*12*512(特征图大小12*12,有512个通道),则特征图共有12*12=144个位置,每个位置的特征维度为1*512,将两个特征图同一位置的512*1与1*512的矩阵相乘,得到该位置特征向量维度为512*512。文章中使用所有位置特征向量之和对其进行池化,故将144个512*512的特征向量相加,最终得到512*512的双线性特征。 该过程可以使用矩阵乘法实现,将特征图变形为144*512的特征矩阵,之后其转置与其相乘,得到512*512的双线性特征向量。

# 实现方式:pytorch x = torch.randn(1,512,12,12)batch_size = x.size(0)feature_size = x.size(2)*x.size(3)x = x.view(batch_size , 512, feature_size)x = (torch.bmm(x, torch.transpose(x, 1, 2)) / feature_size).view(batch_size, -1)x = torch.nn.functional.normalize(torch.sign(x) * torch.sqrt(torch.abs(x) + 1e-10))

关于torch.bmm参考torch.bmm()函数解读

Bilinear CNN model的形式简单,便于梯度反向传播,进而实现端到端的训练。

另外,值得一提的是,bilinear模型由于其优异的泛化性能,不仅在细粒度图像分类上取得了优异效果,还被用于其他图像分类任务,如行人重检测(person Re-ID)。

代码实现

通过引用resnet18的特征提取部分,实现Bilinear CNN model,如下所示:

import torchimport torch.nn as nnfrom torchvision.models import resnet18class Net(nn.Module):def __init__(self):super(Net,self).__init__()self.features = nn.Sequential(resnet18().conv1,resnet18().bn1,resnet18().relu,resnet18().maxpool,resnet18().layer1,resnet18().layer2,resnet18().layer3,resnet18().layer4)self.classifiers = nn.Sequential(nn.Linear(512**2,14))def forward(self,x):x=self.features(x)batch_size = x.size(0)feature_size = x.size(2)*x.size(3)x = x.view(batch_size , 512, feature_size)x = (torch.bmm(x, torch.transpose(x, 1, 2)) / feature_size).view(batch_size, -1)x = torch.nn.functional.normalize(torch.sign(x)*torch.sqrt(torch.abs(x)+1e-10))x = self.classifiers(x)return x

【参考文档】

「见微知著」——细粒度图像分析进展综述双线性池化(Bilinear Pooling)详解、改进及应用bilinear model && bilinear pooling(一)学习笔记之——Bilinear CNN modelBilinear CNNBilinearCNNModelsforFine-grainedVisualRecognition

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。