李理:极客头条深度学习系列文章笔记

来源:互联网 发布:she安静了知乎 编辑:程序博客网 时间:2024/06/13 22:50

概述及一些基本概念

目前人工智能应该更多的提高现有产品。
Image Caption Generation任务是给定一张图片,需要让计算机用一句话来描述这张图片。Caption Generation相对于之前的task来说需要更加深入“理解”图片中物体之间的关系,甚至包括一些抽象的概念。它把一幅信息量极大的图片压缩成短短一句话。
概念本身只是一种“特征”的指代,是我们的感觉系统(视觉)对一个物体的反应。而语言是一部分相似的生物对同一个/类物体达成共识的一种指代。
loss function,可以理解为“错误”的程度,错的越“离谱”,loss就越大。而我们的目标就是调整参数使得loss最小。
模型的“泛化”能力:和人在学校学习一样,有的同学做过的一 模一样的题就会,但是考试时稍微改变一下就不会了,这就是“泛化”能力太差,学到的不是最本质的东西。
validation:所以平时会定期有一些“模拟考试”,来检验学生是不 是真的学会了,如果考得不好,那就打回去重新训练模型调整参数。
test:到最终的考试了,就是最终检验 的时候了,这个试卷里的题目是不能提前让人看到的,只能拿出来用一次,否则就是作弊了。
无监督的学习和强化学习。前者就是不给答案,只给数据,让人总结规律;而后者会有答案,但是答案不是现在就告诉你。
人类社会里更多的是监督学习和强化学习。从人类社会总体来说,强化学习是获取新知识的唯一途径,也就是向自然学习,我们做了一个决策,其好坏可能要很长一段时间才能显现出来。而学习出来的这些知识通过监督的方式,通过家庭和学校的教育教给下一代。
机器学习的过程就是选择“最优”的参数。
“深度学习”最近之所以火热,其中很重要的一个原因就是对于很多问题,我们只需要输入最原始的信号,比如图片的像素值,通过“多层”的网络,让底层的网络学习出“底层”的特征,比如基本的形状,而中间的层学习出抽象一点的特征,比如眼睛鼻子耳朵。而更上的层次识别出这是一个猫还是一个狗。所有这些都是机器学习出来的,所以基本不需要领域的知识。
人脑的神经元也是把输入的信号做加权累加,然后看累加和是否超过一个“阈值”。如果超过,继续向下一个神经元发送信号,否则就不发送。因此人脑的神经元更像是一个阶跃函数。
最小平方误差(MSE)损失函数。
cross entropy 损失函数。
损失函数是每个训练数据的损失的平均。
反向传播算法是一个高效的算法。
计算图。
反向计算可以“利用”前向计算的结果。

卷积神经网络及训练

神经网络的层数越多,参数(超参数)就越难调。但是如果参数调得好,深的网络的效果确实比较浅的好。
目前,图像识别大都使用深层的卷积神经网络及其变种。
卷积神经网络有3个基本的idea:局部感知域(Local Recpetive Field),权值共享和池化(Pooling)。
卷积网络能很好的适应图片的位置变化:把图片中的猫稍微移动一下位置,它仍然知道这是一只猫。
卷积神经网络可以学到一些空间结构。
共享权重和bias的一大好处是它极大的减少了网络的参数数量。
池化层一般都直接放在卷积层后面池化层的目的是简化从卷积层输出的信息。
可以把max-pooling看成神经网络关心某个特征在这个区域里是否出现。
池化可以减少特征的个数,因此减少了之后层的参数个数。
Max-pooling,L2 Pooling
幸运的是求卷积和max-pooling的导数是非常简单的。
从经验来看,ReLU总是要比sigmoid激活函数要好。理论上没有人证明ReLU是更好的激活函数。
卷积层本身就有防止过拟合的能力。原因是权值共享强制网络学到的特征是能够应用到任何位置的特征。这让它不太容易学习到特别局部的特征。因此也就没有必要对它进行的dropout了。
early-stop
dropout可以提高模型的泛化能力。
Batch Normalization是加速训练收敛速度的非常简单但又好用的一种实用技术。
训练神经网络我们一般使用mini-batch的sgd算法,使用mini-batch而不是一个样本的好处是作为全部样本的采样,一个mini-batch的“随机”梯度和batch的梯度方向更接近(当然这是相对于一个训练样本来说的);另外一个好处是使用一个mini-batch的数据可以利用硬件的数据并行能力。比如通常的batch是几十到几百,而且为了利用数据并行的lib如blas或者GPU,一般都是8的倍数,比如16或者128这样的数字。
Batch Normalization是Google的Sergey Ioffe 和 Christian Szegedy提出的,相同的网络结构,使用这种方法比原始的网络训练速度要提高14倍。
如果训练时和测试时输入的分布变化,会给模型带来问题。在很深的网络里这个问题会带来问题,使得训练收敛速度变慢。因为前面的层的结果会传递到后面的层,而且层次越多,前面的细微变化就会带来后面的巨大变化。
我们一般会对输入数据进行”白化“除理,使得它的均值是0,方差是1。但是之后的层就很难保证了,因为随着前面层参数的调整,后面的层的输入是很难保证的。
如果我们能保证每次minibatch时每个层的输入数据都是均值0,方差1,那么就可以解决这个问题。
因此我们可以加一个batch normalization层对这个minibatch的数据进行处理。但是这样也带来一个问题,把某个层的输出限制在均值为0,方差为1的分布会使得网络的表达能力变弱。因此作者又给batch normalization层进行一些限制的放松,给它增加两个可学习的参数 β 和 γ ,对数据进行缩放和平移,平移参数 β 和缩放参数 γ 是学习出来的。极端的情况这两个参数等于mini-batch的均值和方差,那么经过batch normalization之后的数据和输入完全一样,当然一般的情况是不同的。
我们训练时使用一个minibatch的数据,因此可以计算均值和方差,但是预测时一次只有一个数据,所以均值方差都是0,那么BN层什么也不干,原封不动的输出。这肯定会用问题,因为模型训练时都是进过处理的,但是测试时又没有,那么结果肯定不对。 解决的方法是使用训练的所有数据;另外一种常见的办法就是基于momentum的指数衰减。
dropout是一种防止模型过拟合的技术,这项技术也很简单,但是很实用。它的基本思想是在训练的时候随机的dropout(丢弃)一些神经元的激活,这样可以让模型更鲁棒,因为它不会太依赖某些局部的特征(因为局部特征有可能被丢弃)。
我们训练的时候会随机的丢弃一些神经元,但是预测的时候就没办法随机丢弃了。一种”补偿“的方案就是每个神经元的输出都乘以一个p,这样在”总体上“使得测试数据和训练数据是大致一样的。
在训练的时候给每个元素除以p,相当于给H1放大1/p倍,那么预测的时候,那么后面层的参数学到的就相当于没有dropout的情况,因此预测的时候就不需要再乘以p了。
下面是我的一些调参经验:

  • learning_rate非常重要,刚开始要大,之后用lr_decay让它变小。如果发现开始loss下降很慢,那么可以调大这个参数。如果loss时而变大时而变小【当然偶尔反复是正常的】,那么可能是learning_rate过大了。
  • 最原始的sgd效果不好,最好用adam或者rmsprop再加上momentum
  • 如果训练准确率和验证准确率差距过大,说明模型过拟合了,可以增大L2正则化参数reg,另外使用dropout也是可以缓解过拟合的。
  • batch norm非常有用,尽量使用
  • 越深的网络效果越好,当然要求的参数也越多,计算也越慢。后面我们会介绍一些使得我们可以训练更深网络的方法,比如著名的152层的ResNet以及参数很少的Inception系列算法,这些方法是最近一两年在ImageNet上名列前茅。

Inception结构的基本思想就是用小的filter组合来替代大的filter,从而减少参数和计算量,这样相同的计算资源也就能训练更深的网络,另外一个好处就是在一些终端设备占用的内存和cpu更少。
可以用两个3×3的filter stack起来替代一个5×5的filter。另外也可以用一些非对称的比如1×3和3×1的filter组合起来替代3×3的filter。

循环神经网络

语言模型是在自然语言处理处理中非常常见的一个模型。它在语音识别,机器翻译等任务中都有应用。它解决的问题之一就是给定一个字符串,用了判断这是一个“合理”句子的概率。
RNN的特点是利用序列的信息。
理论上RNN能够利用任意长序列的信息,但是实际中它能记忆的长度是有限的。
RNN的参数是在所有时刻共享(一样)的。这反映这样一个事实:我们每一步都在执行同样的操作,只不过输入不同而已。这种结构极大的减少了我们需要学习的参数【同时也让信息得以共享,是的训练变得可能】。
RNN不一定每个时刻都有输入,也不一定每个时刻都有输出。
RNN最主要的特点是它有隐状态(记忆),它能捕获一个序列的信息。
LSTM和最原始(vanilla)的RNN相比能够捕获更长距离的依赖。
LSTM和原始RNN的不同之处只是在于计算隐状态的方法。
通过结合卷积神经网络,RNN可以给一个图片生产一段描述。这看起来非常神奇。这样的模型甚至能够告诉我们生产的词对于图片的那些地方(特征)【attention机制可以更好的实现这一点,我们后面会介绍】。
训练RNN好普通的神经网络类似,我们也是使用反向传播算法,但是有一些麻烦的地方。因为每个时刻的参数是共享的,因此参数的梯度不只依赖当前时刻的输出,还依赖于之前的时刻。比如为了计算t=4的梯度,我们需要把错误往前传递3个时刻。这就是所谓的Backpropagation Through Time(BPTT)。现在我们只需要知道对于原始的RNN,BPTT很难学会长距离的依赖,原因在于梯度消失/梯度爆炸。
双向RNN(Bidirectional RNNs)的思想是t时刻的输出不但依赖于之前的元素,而且还依赖之后的元素。
深度(双向)RNN(Deep (Bidirectional) RNNs)和双向RNN类似,不过多加几层。当然它的表示能力更强,需要的训练数据也更多。
在LSTM内部,会决定保持哪些记忆同时擦除另外一些记忆。然后它会把之前的状态,当前的记忆好输入来计算当前当前的cell。这种结构可以非常有效的捕获长距离的依赖。

原创粉丝点击