简单总结下现有的CNN网络结构设计思想。
LeNet-5取名自它的作者Yann Lecun,最早被成功应用于在ATM中对支票上的手写数字进行识别。它可以说是CNN的开山之作,其中应用的卷积、激活、池化和全连接等操作一直被沿用至今。
Alex Krizhevsky设计的AlexNet在ILSVRC(ImageNet Large Scale Visual Recognition Challenge)2012获得了冠军。AlexNet和LetNet-5的结构类似,但是比LetNet-5更深并且有更多的参数。AlexNet网络中一共有8层用于学习的神经层,分别是5层卷积层和3层全连接层。AlexNet的创新点在于1)开创性地使用了ReLU激活函数,提高了不少训练速度;2)使用了随机失活(Dropout)、数据增强(Data Augmentation)以及学习率衰减策略来防止过拟合。
AlexNet之后的下一个经典CNN网络就是VGG,同样将CNN在ImageNet分类竞赛的表现提升很多。VGG相比AlexNet最主要的提升就是将网络结构变得更深,网络层数由AlexNet的8层升至16和19层(VGG有两个版本,分别是16层的VGG-16和19层的VGG-19)。VGG也让我们知道网络的深度可以直接提升CNN在图像分类任务中的性能表现。
ILSVRC 2014的冠军网络来自Google的GoogleNet。它还有另外一个名字叫做Inception v1。Inception v1可以算是继VGG之后CNN分类器的一个里程碑。之前的网络主要是通过将CNN做的越来越深从而提升分类性能,但是Inception v1通过网络设计去解决每张图中的主体大小不一的问题从而提升分类性能。
首先在图像分类问题中有一个很常见的问题就是每张图中的主体的大小差别很大,比如下面三张图中的三只狗的大小都不一样,而且每只狗所在图片中的位置都不一样。由于图片中主体的位置差异巨大,就很难为卷积操作选择合适的卷积核大小。信息分布更完全的图片(比如下图中最左边的子图)适合较大的卷积核。而信息分布偏局部的图片(比如下图中最右边的子图)适合较小的卷积核。
Inception v1用一个新的单元结构,名叫Inception模块,去解决上面的问题。Inception模块如下图所示。每个Inception模块有多个滤波器,分别是1×1, 3×3和5×5,对输入图像进行卷积操作。并且还会进行一次最大池化操作。最后将这四个操作的输出结合在一起传送给下一个Inception模块。当然Inception v1也同时增加了网络的深度。它由9个线性的Inception模块组成,一共包含22层。
ResNet是继GoogleNet之后又一个CNN模型的里程碑。它在ILSVRC和COCO 2015上取得5项第一。ResNet最重要的成就是解决了深层CNN模型的训练问题。前面2014年的GoogleNet才只有22层,而2015年的ResNet有高达152层。这在网络深度上完全不是一个数量级。
理论上来讲,CNN的网络深度对提升性能非常重要,提升网络深度可以让模型的性能显著提升。但是从实验上来看,一味地增加网络深度时,网络的性能可能不增长甚至反而下降。而且随着网络深度的增加,梯度消失和梯度爆炸的出现的可能性也就越来越高。这些问题使训练深层CNN网络非常困难。
简单来说,传统网络结构(如下图所示),将每层的输出直接传递给相邻的下一层输出。
ResNet通过使用一个叫做捷径(Short cut或者Skip connection)去解决这个问题。ResNet由很多残差模块组成(如下图所示)。每个模块都由一些列连续的层和一个捷径组成。这个捷径将该模块的输入和输出连在一起,然后在进行ReLU激活之前,将两者相加。然后将得到的输出送给ReLU激活函数生成这个模块的输出。
通过堆叠残差模块,我们就可以把之前传统的网络结构改装成下图(示例)。这样一系列连续的残差模块组成的网络即便非常深(比如有1000层)也是可以有效训练的。
NASNet是使用神经结构搜索(NAS)框架构建的。简单来说,之前我们所说的所有CNN网络模型,从LetNet-5到ResNet都是研究人员手动设计的网络结构。而NAS就是用来自动搜索最优的神经网络结构的方法。由于ImageNet的数据集太大了,通过NAS直接在ImageNet上进行搜索最优CNN网络结构所需要的计算量太大了,所以NASNet的论文的作者使用NAS在CIFAR-10数据集上进行搜索得到了适用于CIFAR-10的最佳结构。即便是这样,通过NAS搜索得到的NASNet在ImageNet 2012竞赛的数据集也获得了3.8%的Top 5错误率。
上面的这些模型包含了这些年来的CNN分类算法发展中的主要思想。基于这些模型的思想,后面有又出现了很多更强大的CNN分类模型。比如基于Inception v1(GoogleNet)的Inception v2、Inception v3和Inception v4。之后的Xception将Inception的思想发挥到了极致。DenseNet是基于ResNet基本思想的一种网络。ResNet只将残差模块中的输入与输出连接在了一起。而DenseNet更为激进,将所有的层互相连接(如下图所示)从而建立密集连接(Dense Connection),这也是这个网络的名字的由来。换句话说,DenseNet中每一层的输入是前面所有层的输出。
ResNet和Inception这两种思想进行融合出现了后面更强大的Inception-ResNet和ResNeXt。在Inception模块引入了ResNet中的捷径思想,就出现了Inception-ResNet v1和Inception-ResNet-v2。Inception-ResNet v1的规模较小,和 Inception v3 相当。而Inception-ResNet v2的规模较大,和 Inception v4 规模差不多,并且两者的分类性能相近。在ResNet中引入Inception的思想得到了ResNeXt。其将ResNet的每一个残差模块像Inception模块那样进行横向扩展(如下图中的右图所示,ResNeXt通过在通道上对输入进行拆分,进行分组卷积)。
2017年最后一届ImageNet的冠军是SENet。它将Top 5错误下降到2.25%,可以说是提升巨大。简单讲SENet引入了一种SE模块,其通过Squeeze和Excitation这两个操作抑制无效特征并且提升有效特征的权重。通过将SE模块与现有CNN模型相结合,可以提升现有模型的性能。
通过上面的介绍可以看到,CNN分类模型变得越来越强大。但是随之而来的缺点也显而易见,这些模型通常需要巨大的存储和计算量。比如ResNet有152层,其模型大小将近300多MB,而且还需要非常强大的GPU来进行运算。而在某些低功耗领域上,比如手机和无人机上,如果要使用这样的模型,几乎是不可能的。所以近年来CNN模型的另外一个很重要的研究方向就是如果在算法层面有效降低模型所需要的存储和计算量。现阶段这个方面做得比较的模型有MobileNet系列和ShuffleNet系列。
对AI感兴趣的同学可以关注我的微信公众号:haotian3141。或者我的博客:www.neohsu.com
从经典的残差网络开始讲起:相较于传统的卷积神经网络,残差网络增加了跨层的恒等路径,以降低训练的难度,如下图所示:
Squeeze-and-Excitation Networks(SENet)在残差网络的基础上,增加了子网络,来自动学习一组权重,调整不同通道特征的大小:
深度残差收缩网络(Deep Residual Shrinkage Network)在SENet的基础上,又做了一些改进,将SENet中的加权替换成了软阈值化。
软阈值化是很多信号降噪算法的关键步骤,可以将接近于零(绝对值小于某个阈值τ)的特征置为零,也就是将处于[-τ, τ]区间的特征置为零,其他的特征也朝着零的方向进行收缩。
如果和前一层的偏置b放在一起看的话,这个置为零的区间就变成了[-τ+b, τ+b]。因为τ和b都是可以自动学习得到的参数,这么看的话,软阈值化似乎是可以将任意区间的特征置为零,是一种更灵活的、删除某个取值范围特征的方式,也可以理解成一种更灵活的非线性变换。
从另一个角度来理解的话,前面的两个卷积层,将冗余信息对应的特征,转换成接近于零的值;将有用的特征,转换成远离零的值。然后,自动学习得到一组阈值,利用软阈值化将冗余特征删除掉,将有用特征保留下来。
最后,和残差网络相同,也是堆叠很多基本模块,构成完整的网络:
文献:Minghang Zhao, Shisheng Zhong, Xuyun Fu, Baoping Tang, Michael Pecht, Deep residual shrinkage networks for fault diagnosis, IEEE Transactions on Industrial Informatics, 2020, 16(7): 4681-4690.
下面的链接可以供参考:
https:// github.com/zhao62/Deep- Residual-Shrinkage-Networks
https:// blog.csdn.net/ABCD_2020 20/article/details/105801032
从大学到现在,我使用Java已经将近20年,日常也带实习生,还在公司内部做training,所以可以分享下我的经验,希望对你有用。
因为是在工作中培训,就必然有两个约束:实用、时间紧,因此就不能像大学那样,把所有的知识点都面面俱到的讲到。而只能挑基础的,实用的,难理解的讲。至于其他边边角角的知识,就一笔带过。一则没有时间,二则不常用,再则既使讲了,学生印象也不深刻。总之一句话:“好钢用在刀刃上”。
下面,就根据我的实践,具体谈下学习过程:
1.基础知识
我学习java的时候,先是通读了《Java编程思想》,然后是《Java核心技术》。当时这两本书还不像现在这么厚,而刚才我把案头的《Java核心技术》第9版翻了翻,上下两册已经1700多页了,可想而知,如果要把它通读一遍,且不说把所有的代码都调通,就是当小说读,估计也需要些时间。
但我现在教学依然首推《Java核心技术》,主要是体系完整,实例多,可操作性强。但对初学者,我一般是只讲前6章,也就是下面的内容:
就《Java核心技术》第9版来说,也就是到250页为止,加把劲,1个月拿下完全没问题。
因为你是自学,所以建议你一定要把其中的代码都调通,课后的作业尽量去做。除此之外,还有两点特别重要:
#.学习笔记
因为你是自学,不像在企业中学了就能够实践,印象自然特别深刻。而自学因为没有实践的及时反馈,所以记笔记就显得特别重要。因为记笔记就像写作一样,是整理思路的绝佳方法。同时学习笔记也是你以后开发,面试的绝好资料。
学习编程,人跟人是不一样的,别人觉得难理解的东西,对你却不一定;而你觉得难理解的东西,别人可能又会觉得特简单。而学习笔记就是自己专有的“难点手册”,有点像高考时的“错题本”,以后无论是在面试前,还是在日常工作中,随时都可以翻出来看看,自是获益匪浅。
#.分门别类保存demo
学习笔记是很好的文字资料,但编程界有句话说的特别好,所谓“no code, no text”,意思就是说:千言万语都没有一段代码来的实在。
以我的经验,在你在学习的过程中,就某个知识点,无论当时理解的多透彻,调试的多棒,只要时间一长,等到了实用的时候,肯定会碰到各种各样的问题,一些看似简单的东西,此时死活就是调不通,正所谓人到事中迷。这个时候,如果你手头恰有运行良好的demo,打开参考一下(甚至直接拷贝过来),问题自然迎刃而解。而且因为这些demo都是你亲手调试出来,印象自然特别深刻,一碰到问题,在脑子中自会立刻涌现。
所以说,在学习的过程,一定要善待你调通的demo,千万不要用完了就扔,等后来碰到困难,想要用时却找不到,追愧莫及。正确的做法就是把所有调通的demo,分门别类的保存起来,到时候查起来自是得心应手。
人都说“书到用时方恨少”,其实代码也是这样,所谓“demo用时方恨少”。
2.Spring
目前在Java EE开发中,Spring已经成为和Java核心库一样的基础设施,所以说如果想成为一个合格的Java程序员,Spring肯定绕不开。另一方面,如果掌握了Spring体系,Java基本上就算入门了,就有能力进行一些实用级的开发了。
但Spring本身也是日渐复杂,衍生项目越来越多,但最最核心的概念依旧是IOC和AOP,掌握了这两个概念,再把Spring MVC学会,再学习其他的衍生项目就会平滑很多。
同时,因为Spring本身就应用了许多优雅的设计理念,所以学习Spring的过程,也是加强Java基础知识学习的过程。因此等你掌握了Spring,原来很多你理解不透彻的Java特性,此时就会恍然大悟,包括接口、抽象类等。
我学习Spring,读的第一本书是《Spring实战》,坦率的说,书很一般,但市面上比它好的书,我却没有遇到过。还有一本《Spring源码深度解析》也不错,对Spring的设计理念讲的尤其透彻,虽然整本书读起来有些艰涩,但前几章却生动有趣,也是整本书的精华。所以建议你在学习Spring之前,先把该书的前几章通读一下,然后再回过头来学习《Spring实战》会顺利很多。
以我经验,要学透Spring,终极的方法还是阅读源码(我当时就是这么干的),待把Spring的核心源码通读了,人就真的自由了(所谓无真相不自由),不仅是对Spring,而是对整个Java体系。以后再遇到其他框架,大概一眼就能看出其中的脉络,所谓到了“看山不是山”的境界。但这都是后话,可以作为以后你努力的方向。
和学习Java基础知识一样,学习Spring也一定要记笔记,一定要分门别类保存demo。
老实说,Spring对初学者不算简单,因此最好能有个好老师带一下,不用太长时间,2个课时即可,然后就是在你遇到大的困难时,能及时的点拨下。
以我的经验,要初步掌握Spring,大概需要1到1个半月的时间。
3.其他知识
Spring是Java编程的基础设施,但真要进入到实际项目的开发,还有些东西绕不过,包括 MySql,Mybatis,Redis,Servlet等,但如果你经过Spring的洗礼,这些东西相对就简单多了,以我的经验,1个月的时间足够了。
4.实践
学习Java,光学不练肯定是不行的。但因为是自学,所以就没有实际的产品让你练手,但也没有关系,谁大学还没有做过毕业设计呢?以我的经验,大家最爱的“学生管理系统”依旧是个很好的练手系统。
别看“学生管理系统”逻辑简单,但麻雀虽小五脏俱全,其中数据库设计、Mybatis,Spring、SpringMVC,Servlet、Tomcat一个都不缺,绝对的练手好伴侣。
还有,虽然你的学习重点在Java,因为要做一个完整的demo,前端的配合肯定少不了。因此就免少不了要学一些简单的JS、HTML知识,但因为前端本就是个很大的topic,所以一定要控制好边界,千万不要顾此失彼。就“学生管理系统”来说,在前端上,只要实现一个包含table、textbox、button,能发送REST请求到server,能实现学生的“增删改查”的简单页面即可。
作为一个练手项目,目标就是把Java的主要技能点串起来,所以自不求尽善尽美(也不可能),所以1个月时间足够了。
.最后
按照上面的过程,4个月的时间刚刚好。当然Java的体系是很庞大的,还有很多更高级的技能需要掌握,但不要着急,这些完全可以放到以后工作中边用别学。
学习编程就是一个由混沌到有序的过程,所以你在学习过程中,如果一时碰到理解不了的知识点,大可不必沮丧,更不要气馁,这都是正常的不能再正常的事情了,不过是“人同此心,心同此理”的暂时而已。
在日常的教学中,我常把下面这句话送给学员们,今天也把它送给你:
“道路是曲折的,前途是光明的!”
祝你好运!
--- 上面是原答案 ---
我把上面的内容作了下整理,画了学习路线图,内容也有些升级,供参考。
因为有朋友,通过留言或私信方式问我:Java中有哪些知识已经过时,不需要再学习了?
回答的多了,就感觉这是一个普遍的问题,因此统一整理了下,作为这篇文章的补充,希望对你有用。