Google顶级网络CoAtNet(CNN+TFM 89.77% ImageNet top1精度)+代码+基于CIFAR10的实验流程

代码链接在最下面
同时希望大家可以看看最后我想说的一些话,谢谢

介绍:
这个是我们人工智能的实践课内容,因为觉得如果做一些没有的实验,那多浪费时间啊,所以想要把从我们刚开始学深度学习开始接触的MLP到ResNet到ViT再到最顶尖的CNN+TFM这里用的CoAtNet(下面有介绍),他在ImageNet数据集上达到了89.77%的精度,超越所有ResNet变种,成为当时的SOTA,这里的内容是基于CIFAR10的分类任务。

如果不懂Transformer可以看看我的上一篇详解:
Transformer详解

1.方案设计
Figure1:如图是我们的工作流程图,其实已经非常清楚了,并且在模型部分还写出了我们所作的模型之间的关系。
2.实验手段确定
这里我们选择的是pytorch深度学习框架,因为之前我就用的是pytorch,并且在pytorch的库里面还有封装好的数据集下载和处理库,以及对数据进行相关变形和增强,并且在pytorch.nn库中有很多以及封装好的模块可以直接调用并且很方便,最后就是他还具有自带的数据集可视化的一些工具。

3.实验步骤
3.1数据集的获取
这个就用得到我刚才说的好处了,在pytorch中可以直接用torchvision.datasets.CIFAR10的函数获取,把download设置为True即可。

3.2数据描述
Figure2:随便选取的十个类,每类十张图片展示
其中Cifar10为10类物体的图像,其中共6w个3x32x32的图片,其中5w条训练集,1w条测试集。即每一类图片训练集中5000张,测试集中1000张。

3.3数据预处理
前三种网络模型:颜色变换,图片旋转,转变为tensor形式,并且归一化
CoAtNet:在此基础上加上了Resize,将图像变大(即32,64,224三种情况都有)

3.4模型
这里我写的是CoAtNet网络,在2021年1月由谷歌Brian Team提出,不过其代码还没有开源,所以我是按照论文中所给的框架以及层数,Channel数并且结合了Github上的相关代码来搭建的,主要是我自己之前搭建的模型没有收敛,或者说是经过迭代梯度下降后测试集精度根本不动,但是不明白为什么,所以只能根据Github上得搭建好得网络来更改了,并且封装为5个Block
参考网络GitHub链接

不过在讲网络具体代码之前我想要先讲一下这个model的由来:
首先这个网络是通过结合卷积网络还有Transformer模型来做的,原因其实很简单,如果熟悉的话这些工作的话就知道,卷积神经网络相比与Attention对全局的掌握,模块与模块之间的联系可能稍微差一点(因为感受野受Kernel_size的限制),Attention相比于卷积具有更好的全局性但是计算量实在太大了!并且缺少局部性,因为是把图片切成patch,那么每个patch之中的像素就无法被读取:

这个其实是原文的Table,为了方便我就直接拿来用了。
在这里插入图片描述

故而我们以此为基础想要联合两者,原作者发现:深度卷积和自注意力可以通过简单的相对注意力自然地统一起来,即如下:

卷积:
(1)
在这里插入图片描述

注意力机制:
(2)
在这里插入图片描述

将这两者直接可以通过加法结合:
先Softmax再作加法
(3)
在这里插入图片描述

又由于Self-Attention是和输入数据的size呈平方关系,所以如果直接将原始图像进行计算,会导致计算非常慢。因此作者提出了三种方案。
为构建一个实际可行的网络,主要以下三种候选方案:
A: 执行下采样以降低空间尺寸,在达到可接受水平后采用全局相对注意力;
B: 采用局部注意力以全局,类似卷积约束自注意力的感受野;
C: 采用特定的线性注意力替换二次Softmax注意力,进而将计算复杂度降低到与空间尺寸成线性关系。
其中C结果很差,B图像变换太多,导致计算效率太低,所以采用的是A方法。
但是Attention和Convolution各有优缺点,所以作者提出了四个架构:
1)C-C-C-C;
2)C-C-C-T;
3)C-C-T-T ;
4)C-T-T-T。 *其中C代表Convolution,T代表Transformer。

考虑到泛化性能、模型容量、迁移性能以及计算效率,采用了 C-C-T-T构建CoAtNet,其架构见下图:
在这里插入图片描述

Figure3:CoAtNet网络模型架构
可以看到前面就是简单的把图像通过卷积层得到我们想要的特征图输入,然后后面两个C也就是第二三个block用的是MBnet,原用于EfficientNet的,他采用的是倒瓶颈,先维度增大再变小,可以得到更好的学习性能和泛化性,后面两个就是用的相对注意力机制,简单来说就是用的相对位置编码,然后通过残差连接实现上面说的加法,也就是联合。我们如果要拓宽网络就是重复后面的结构,即:CCTT,也就是最后四个block叠加就好了,如下是他们家族的结构信息:

Table2:CoAtNet家族
在这里插入图片描述

CoAtNet_5层数和4是一样的,只是中间的通道数要多一些,为192,256,512,1280,2048.

其实我很是不知道神经网络怎么用伪码表示,其实就是我上面的神经网络结构模块图,再配合Table2中的网络层数结构以及Channel的参数就已经知道了,写成流程性的伪码反而更难理解,并且搭建起来可能反而会出错,这也是我第一次自己写没有按照结构性搭建导致最后网络维度对上了,程序能跑通但是精度根本不动的原因之一。所以这里我就大致写一下我的训练思路吧:(注意都是伪码)

第一步:数据增强
Transfroms:
   Resize(x,x) #改变大小
   RandomHorizentalflip(p=x) #旋转
   Totensor  #变成张量
   Normalize #归一化

第二步:数据加载
Set = CIFAR10(path,train=x,transforms=Transforms) #导入路径,选择是否训练,载入变形
Load = DataLoader(Set,batch_size,shuffle) #载入数据,到时候直接训练

第三步:加载模型并统计模型参数
Import CoAtNet
summary(CoAtNet.to(device), input_size, batch_size)

第四步:训练网络
def forward_pass(net,loader,loss_func,optimizer,train):#定义前向传导
   outputs = model(x)
   loss = loss_func(outputs,labels)
   total_loss +=loss
   if train:
      opt.zerograd() #导数归零
      loss.backward() #导数反向传播
      opt.step() #下一步
   total_loss /= len(loader.dataset) #总loss
   acc = acc_score(y,prediction) # 精度
   f1 = f1_score(y,prediction,avg=”weight”) #f1
return total_loss,acc,f1  

def train(model,train_loader,tese_loader,optimizer,loss_func,epoch_num,device):
  model.load.to(device) #加载模型然后放到GPU上去
  while epoch<epoch_num #迭代次数
      train_loss,acc,f1 = forward_pass(x,train=True)
      test_loss,acc.f1 = forward_pass(x1,train=False)
  #然后下面我有两种方式,为了提高精度我强行让预测acc上升,即只有上升的才保存
第一种:if acc1<acc: #如果精度上升了
          model.save #保存模型
          logs.append #把我们要统计的东西放到list中储存
          epoch+=1
          print(acc,loss,time,f1)  #打印精度,loss,时间还有f1
        else:
           times+=1
           continue
       if times>=200:#times用来计数,如果次数太多就强制退出防止死循环或者次数太多
           break

另一种就是不要if的简单的训练,只要训练了就把模型保存起来继续跑,到epoch够了就停止迭代。

第五步:画图和混淆矩阵:
这两个都是封装的库函数,直接对应调用就好了
res_plot() #精度和loss的图
sns.heatmap() #混淆矩阵

三、实验结果与分析(可加页)
实验环境我们用的是Pytorch,其实主要是在华为云上租的服务器跑的,因为我跑的东西实在太大而且太多了,跑完了1k华为代金卷才勉强达到我想要的效果。指标这里我主要用的是Acc&Loss,混淆矩阵,5-fold交叉验证,还有网络模型参数。
Figure4:训练准确率

这是准确率,可以看到模型的Train和Set到后面都十分平稳了,右图是最后10个epoch的图像,也都可以很明显的看出来模型还是比较稳定的。
Figure5:训练loss

其实这里的Loss和Acc是一个效果了,主要是来判断是否过拟合吧,显然是没有的,但是结合起来看虽然模型非常平稳,但是泛化性好像不太够,因为后面的Attention层非常吃预训练的数据量,但是这里我们只有5w的数据集来训练。

下面这个是混淆矩阵,可以很清楚的看到最后在测试集上预测的结果以及准确率,召回率还有F1,这些都是根据混淆矩阵可以算出来的
Figure6:模型训练后得到的混淆矩阵

然后就是我做的在CoAtNet_4上的5-fold验证,因为当时忘记保存中间参数了所以只剩下结果,于是手动画了一个图像:
Figure7:5-fold验证结果

Table3:Model Performance
在这里插入图片描述

结论:
1.可以看到我们的全连接简单的拼接虽然网络参数很少,跑得快,但是准确率也很低,
2.而ResNet是显然有泛化性好的优势,并且18层在没有做太多其他操作的时候就有比较好的结果了,
3.然而纯TFM的ViT模型,即12层Transformer的Encoder搭建成的网络,在有ImageNet为预训练参数的情况下也只有73的精度,
4.但是结合了卷积的TFM,即CoAtNet可以看到有很好的结果,特别是在把图片放大之后,精度已经达到87+,其中变化为224x224的图片因为跑不动时间不够就中断了。这里的原始是因为ViT采用的是把图片切成patches,然后进行后续操作 ,如果图片太小,基本上就切不成多少个patch,那么Attention都得不到什么信息,怎么可能有很好的结果呢?

总结:可以看到虽然Attention机制有很好的效果,但是非常吃数据集并且计算量非常大,很吃设备。所以现在的趋势都是Conv+TFM。并且现在有一个趋势,显然也是必然的趋势,就是自监督学习,因为人工标注成本太大而且有限,并且到现在Transformer模型仍然未饱和,所以现在看来又有一个井喷式的发展了,虽然现在这种趋势已经凸显出来了,从17年Transformer被提出到20年ViT的提出,不到五年就已经把各大榜单屠了一边多次打破人们认为的不可能或者说是数据集缺陷。

然后是我关于模型训练的一些心得,也是我在这次实验调参的一些方法和经验。

  1. 关于batch_size的问题,这个一般设置的都是8的2次幂倍效率最高,但是一般bz太小了会让训练的速度太慢了,但是如果bz设置太大了就可能会让收敛速度非常慢,因为是批量下降嘛,我一般小型训练集就16或者32,大一点的训练集,或者你的设备支持,128,256,512都可以,不要太大,不然收敛的太慢了,而且你的cuda会out of memory,也就是显存炸了。
  2. 关于学习率的问题,一般我觉得1e-3是最好的,当然如果你是有加载预训练的,我一般设置的是1e-4,-5都可以,你的网络epoch跑到后面一般会发现你的网络可能不动了,这要么就是你的学习率太小了,陷入了局部极小点跑不出去了,所以这个我们就可以把学习率调大让他跳出去,当然有可能你一下子跳崩了,我就有过这种经历,所以千万要有保存模型的习惯,这也是我血的教训。当然也还有可能就是你的模型不太行了,直接把学习率调小试试,很有可能就降下去了。

至于这次实验我主要是用1e-3先跑收敛然后用1e-4,-5先各跑10个epoch再看情况要不要啊调,主要就是根据上面说的经验了,还有,记得要每次调学习率或者bz的时候,要把优化器和dataloader重新加载,我之前忘记加载白跑好长时间,我还以为是我的模型有问题。优化器其实各有优缺点,Adam和SGD可以自己训练后看看结果有什么差别。

代码我完整的放在Github上面了:
Coatnet实验完整代码
希望大家可以多多star呀:)

当然如果您有心打赏可以下载我在CSDN上上传的代码,可能需要10块钱
csdn下载

最后在这里我想说的是,希望大家千万不要抄袭,这是我们实践课的内容,是我花费了大量心思和精力来做的事情,为了拿到一个好成绩那是当然的,但是更多的是希望能够给大家呈现一个完美的从本科刚接触DL的MLP到现在世界最顶尖和火热的网络类型CNN+TFM,并且按道理来说这些代码和项目都是放在付费下载去的,但是我没有,因为我被CSDN里面很多人都恶心坏了,一个简单的函数都要钱下载,所以秉持开源的精神,何况这个连官方都还没有开源,就更加可贵了,希望大家一定要珍惜,也希望大家可以多多支持开源精神。当时做演讲的时候大家都没有认真听其实我感到非常失望,因为很多内容就是为了给他们想要做这方面的同学讲的,不过好在最后得到了老师的高度认同,我自己尽力了,那么结果就是最好了!不过还是希望大家切记不要抄袭,我们国家和世界缺的都是高端的人才,既然你学这方面,AI或者BD或者其他的类别,那就请你一定要真正的去明白和理解而不是应付了事,我看他们大多数做的显然都不理解原作,从网上随便抄的代码就扔上去了,我这里开源不是给你们抄的!!而且想要帮助那些真正想要学习的人!!所以还有很多我自己的感悟,希望大家能够有所收获!最后因为我刚开始写博客嘛,还是希望大家可以多点点赞,然后收藏啊,关注,评论什么的,也算是对我的一种支持的反馈吧,谢谢大家,这里主要记录我的一些工作和经历,体会,希望能一起变成一个Good scientist!

  • 14
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Miracle_ZXY

希望大家还可以多多打赏:)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值