第一次写博客,才刚开始学习深度学习,轻喷(有问题我会及时更正!!!)

个人理解:

在一些类内差异小、但影响因素较大的图像分类任务中,使用全局的CNN特征可能会缺少一些不变性,为了消除这些干扰因素,作者提出了Bilinear CNN Model,比如说:

如果提取的特征和空间位置关联过强,可能也会导致分类错误,例如:

可能我学习到一个船的特征:由船身和船帆组成(学习到的是船帆在船身上方),而当我给一张由一个完整船和另一个只有船帆的图片,那它可能就不会认为它是船(此时一个船的船帆在空间位置上在另一个船的船身的下方),因为它学习到的是船帆在船身的上方。

1、其他的一些方法:

基于“局部模型”的方法:

(1)手工特征

我们可以使用手工的方法来设计局部的特征(避免使用全局的特征),然后再拿去做“模式匹配”,例如:

缺点:显而易见的是,由于是手工设计出来的特征,它很可能对于最后的分类任务而言并不是最优的结果,最好的特征。

(2)“局部的CNN”模型

对于鸟的这种细分类任务,我们除了可以提取框住整个鸟的的特征外,还可以提取其它候选框的特征,比如说增加鸟的头部身子的候选框的特征,加上全部鸟的候选框特征一起来(整个鸟、鸟头部、鸟身子)作为该图像的特征。

缺点:这种局部位置肯定也需要标注信息,对所有的数据集进行标注任务无疑是非常耗时耗力的工作。

使用本身具有一定不变性的特征:

(3)例如使用sift特征(如果需要讲解sift特征可以留言)

sift:

论文中给出的结论是这种方法相比基于“局部模型”的方法会略差一点(我没有去查阅其它相关资料)。

2、Bilinear CNN Model

Bilinear model它由两个基于cnn的特征提取器组成,在图像的每个位置使用外积将其输出相乘,并跨位置合并得到一个图像描述符。 外积捕捉特征通道之间的成对相关性。

论文中说是由双通道理论得来的灵感(形式上好像差不多,但是我真不知道有什么一样,强行往上靠吗?),人类视觉有一个“where”和“what”通道,简单理解就是一个处理物体在哪,一个处理物体的形状等一些信息:

其它的就不多说,直接上这个公式理解:

对于一张图片,有两个CNN特征提取器为,去除最后的池化层和全连接层,假设分别可以得到的特征,那每个特征有=144个位置,一个位置外积可以得到的特征,144个就有144个特征,对144个进行求和池化就只有维的特征,再经过拉直、sqrt等等送往全连接层进行分类。(有错误欢迎指正)

双线性模型:,其它公式就不敲了,直接放图片了:

它的端到端的训练:

3、代码实现篇

以resnet50为特征提取器为例,在CUB-200数据集上实验:

CUB200:

对于数据集下载划分等等网上有很多资源,如果需要我可以后期再续写。

数据预处理和加载:

def load_path(datatype):if datatype == 'CUB':# 换成自己的数据集的位置path = 'E:/pycharm/zDatafile/CUB-data/CUB_200_2011/'ROOT_TRAIN = path + 'dataset/train/'ROOT_TEST = path + 'dataset/test/'return ROOT_TRAIN, ROOT_TESTdef train_data_load(datatype):data_transform = transforms.Compose([transforms.Resize((448,448)),# transforms.RandomSizedCrop(224),transforms.RandomHorizontalFlip(),transforms.RandomRotation(degrees=(-10, +10)),#transforms.RandomCrop(224),transforms.ToTensor(),transforms.Normalize(mean=[0.4856, 0.4994, 0.4324], std=[0.1817, 0.1811, 0.1927])])root_train,_ = load_path(datatype)train_dataset = torchvision.datasets.ImageFolder(root_train,transform=data_transform)CLASS = train_dataset.class_to_idxtrain_loader = torch.utils.data.DataLoader(train_dataset,batch_size=opt.BATCH_SIZE,shuffle=True)return train_loaderdef test_data_load(datatype):data_transform = transforms.Compose([transforms.Resize((448, 448)),transforms.CenterCrop(448),transforms.ToTensor(),transforms.Normalize(mean=[0.4856, 0.4994, 0.4324], std=[0.1817, 0.1811, 0.1927])])_,root_test = load_path(datatype)test_dataset = torchvision.datasets.ImageFolder(root_test,transform=data_transform)CLASS = test_dataset.class_to_idxtest_loader = torch.utils.data.DataLoader(test_dataset,batch_size=opt.BATCH_SIZE,shuffle=False)return test_loader

 模型定义:

class BCNNresnet(nn.Module):def __init__(self):super(BCNNresnet, self).__init__()# 2个卷积层和1个最大池化层self.features = torchvision.models.resnet50(pretrained=True)self.features = nn.Sequential(*list(self.features.children())[:-2])  # 去除最后的pool层# 冻结以前的所有层for param in self.features.parameters():param.requres_grad = Falseself.fc = nn.Linear(2048*2048, 200)def forward(self, x):x = self.features(x)#print("x:",x.shape)x = torch.einsum('imjk,injk->imn',x,x)/196x = x.view(-1, 2048*2048)#print("shape of x before pooling:", x.shape)x = torch.mul(torch.sign(x),torch.sqrt(torch.abs(x)+1e-12))x = F.normalize(x, p=2, dim=1)x = self.fc(x)return x

训练:

整个代码结构如图,BiP存放模型,config是存放超参数设置的,datasets为数据加载和预处理,logger为保存日志,mian为训练,训练代码和保存模型基本都大同小异,想想这里就不放了,我之前还跑过一个小点的模型,使用的是更小一点的vgg(small vgg),如下:

4、缺点(不足)

下面简单谈谈bilinear model的缺点:

(1)论文中的大致说法:使用不同的特征提取器比使用相同的两个特征提取器结果上要更好一点,但是没有办法搜索出最适合的两个特征提取器,那现在所谓的最佳的组合可能只是一个次优的结果。

(2)一个很显然的问题是,参数量巨大,如果最后提取的特征是维的,拉直后也就是262144,如果送往1024维的全连接层,就会有2亿多的参数,计算量和存储要求都有巨大的挑战,这也是后面会有很多在此基础上进行改进的论文,有空我们之后会慢慢说一些改进后的论文和实现,比如说compact bilinear pooling,FBC等等。

----------------------------------------------------------------分割线-------------------------------------------------------         第一次写,没有经验,可能没有太多的专业描述,下次也会多备注一些相关理论和论文的出处,然后这也只是我个人的一些理解,也欢迎各位大佬指正。说明:部分图片来源于网络,如有侵权请告知,会立即删除。转载请注明,谢谢。

Bilinear CNN Model理解(附代码实现)相关推荐

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

    前言 有时,我们逛街时看到不同的狗,却不知道其具体品种,看到路边开满鲜花,却傻傻分不清具体是什么花.实际上,类似的问题在实际生活中屡见不鲜,人类尚且如此,更别说人工智能了.为了解决这一问题,研究者们提 ...

  2. 【NLP】保姆级教程:手把手带你CNN文本分类(附代码)

    分享一篇老文章,文本分类的原理和代码详解,非常适合NLP入门! 写在前面 本文是对经典论文<Convolutional Neural Networks for Sentence Classifi ...

  3. 【NLP傻瓜式教程】手把手带你CNN文本分类(附代码)

    文章来源于NewBeeNLP,作者kaiyuan 写在前面 本文是对经典论文<Convolutional Neural Networks for Sentence Classification[ ...

  4. 【NLP保姆级教程】手把手带你CNN文本分类(附代码)

    分享一篇老文章,文本分类的原理和代码详解,非常适合NLP入门! 写在前面 本文是对经典论文<Convolutional Neural Networks for Sentence Classifi ...

  5. 基于蜜蜂优化算法优化的卷积神经网络(CNN)图像分类——附代码

    目录 摘要: 1.蜜蜂优化算法: 2. 卷积神经网络(CNN) 输入层 隐含层 输出层 ​3. 本文Matlab代码:​ 摘要: 本文通过蜜蜂优化算法,优化了卷积神经网络(CNN)中的超参数,主要是网 ...

  6. 学习笔记之——Bilinear CNN model

    双线性模型是2015年提出的一种细粒度图像分类模型.该模型使用的是两个并列的CNN模型,这种CNN模型使用的是AlexNet或VGGNet去掉最后的全连接层和softmax层,这个作为特征提取器,然后 ...

  7. 【NLP傻瓜式教程】手把手带你fastText文本分类(附代码)

    写在前面 已经发布: [NLP傻瓜式教程]手把手带你CNN文本分类(附代码) [NLP傻瓜式教程]手把手带你RNN文本分类(附代码) 继续NLP傻瓜式教程系列,今天的教程是基于FAIR的Bag of ...

  8. 【NLP保姆级教程】手把手带你RNN文本分类(附代码)

    写在前面 这是NLP保姆级教程的第二篇----基于RNN的文本分类实现(Text RNN) 参考的的论文是来自2016年复旦大学IJCAI上的发表的关于循环神经网络在多任务文本分类上的应用:Recur ...

  9. 【NLP傻瓜式教程】手把手带你RCNN文本分类(附代码)

    继续之前的文本分类系列 [NLP傻瓜式教程]手把手带你CNN文本分类(附代码) [NLP傻瓜式教程]手把手带你RNN文本分类(附代码) [NLP傻瓜式教程]手把手带你fastText文本分类(附代码) ...

最新文章

  1. Java 中的关键字 final
  2. Pycharm的.py文件的导入
  3. 最强六大开源轻量级人脸检测项目分析 | 附打包下载
  4. 十三、前端基本功:DOM练习
  5. 通过 T3 协议使用 WebLogic RMI
  6. 楼层钢筋验收会议纪要_钢筋施工质量通病防治
  7. 《剑指Offer》24:反转链表
  8. const类型成员函数与mutable
  9. oracle数据库导入_oracle数据库导入数据
  10. c# lock的使用及注意事项
  11. 基于Wi-Fi的HID注射器,利用WHID攻击实验
  12. WIN7下java环境的搭建
  13. boost::asio c++ 网络编程socket通信一个简单例子
  14. AcWing 208. 开关问题 (高斯消元+状压)打卡
  15. 【数据分析学习】016-numpy数据结构
  16. 【2019徐州网络赛:G】Colorful String(回文树+二进制统计回文串内不同字母数技巧)
  17. bigdecimal取小数部分_无限小数的本质
  18. 你知道吗?世界上绝美神奇的25条路
  19. 二层协议--LACP协议总结
  20. 如何用甘特图进行项目进度管理

热门文章

  1. 修改级联组件el-cascader默认文字样式
  2. C++ vector 使用方法(各种常用函数的介绍)
  3. 改善Python程序的91个建议
  4. JS 判断一个字符串中每个字母出现的次数
  5. css背景渐变透明和方向
  6. 计算机主机接通显示器位置发,电脑主机和显示器连接不上
  7. macOS 安装 iTerm2
  8. 触宝输入法产品经理解析iOSnbsp;8…
  9. JAVA删除Cookie
  10. 为什么枚举与整型不能互相转换?