一、概述
这一集讲了选择合适的
activation function
。
预处理数据。
Weight
的初始化。
Batch Normalization
的运用。
如何监督整个学习过程以便提早发现问题。
以及如何优化
hyper parameter
。
二、Neural Networks
讲激活函数之前讲了很多关于神经网络的历史。体会最深的就是,一个事物的兴起,不是自身力量就足够的。如果没有摩尔定律,没有大数据,神经网络的发展还不会被提上时代的议程。
激活函数,用来在线性的输入之后产生非线性的输出。非线性代表着解决更加复杂问题的能力。虽然说线性也能解决高复杂度问题,比如素描中画足够多的直线是可以在中间截出一个圆。但是远不如用非线性函数来得快和准确,并且其复杂性也让实践变得很难。
下图是一些激活函数。
- Sigmoid 历史上,使用最多的是
。它接收一个实数,然后产生一个Sigmoid
[0, 1]
的输出。
历史上使用最多,因为
可以用来表示一个Sigmoid function
是否被neuron
激活
这样的的概念。
但是
有三个问题:Sigmoid
第一个问题,饱和的neuron会
上图中,解释了
backpropagation过程中的杀死
。这个问题被称作gradient
。vanishing gradient problem
vanishing gradient problem
。
当
和x = 10
的时候,就是一个x = -10
就产生了一个sigmoid
(饱和神经元)。这个saturated neuron
的值接近 ,或者接近neuron
。如上图,在1
和x = 10
的地方,x = -10
基本上是 和y
。1
的导数是Sigmoid function
sigmoid * (1 - sigmoid)
。
想象一下,
无限接近于sigmoid
的时候,1
dsigmoid = ->1 * (1 - ->1) = -> 0
(用->表示极限了…)。
另外,
无限接近于 的时候,sigmoid
dsigmoid = ->0 * (1 - ->0) = -> 0
。
两种情况,在链式法则下,所有的数乘以
都等于 ,因此
就被杀死了。之后的gradient
都等于 。gradient
第二个问题,Sigmoid function的输出不是趋向于0的(zero-centered)。
这个翻译可能不是很正确,原文写出来了
,结合解释体会一下。 上图中,如果使用zero-centered
,当Sigmoid
总是正的时候,input x
的w
gradients
会是怎样的?
答案是,
的w
要么都是正的,要么都是负的。 上图中,如果gradients
都是正数,那么x
的输出sigmoid
在y
[0.5,1]
。
那么
总是dsigmoid = [0.5, 1] * (1 - [0.5, 1]) ~= [0, 0.5]
> 0
的。
假设最后整个神经网络的输出是正数,最后
的w
就是正数;如果输出是负数,最后gradient
的w
就是负数。如下图。 这样的gradient
造成的问题就是,如上图中,你的gradients
要么全是正的(w
是正的),要么全是负的(x
x
是负的)。
假设最优的一个
向量应该是在上图中第四象限,那么要将你的w
优化到最优状态,就必须走这样的之字形(zig-zag),因为你的w
w
要么只能往下走(负数),要么只能往右走(正的)。达成优化的效率十分低下,模型拟合的过程就会十分缓慢。
如果要深究的话,查找有关费雪矩阵(
)以及自然梯度(Fisher Matrices
Natural Gradient
)的相关论文,证明过程是挺复杂的。
因此,在
和input
的处理中,最好都追求activation function
的数据。好的数据预处理和选用属性更佳的激活函数,就可以达到这样的效果。(貌似0趋向
不好的地方就在于它的求导函数让Sigmoid
的值很蛋疼)。gradient
第三个问题,exp()函数是消耗计算资源的。
虽然说
中大部分的计算资源都将被大量的Convnet
占用,但相比其他convolution
,activation function
都是不小的一笔计算开支。exp()
-
选择其他Ativation Function
1) tanh
到这里,还是理解不了这个`tanh`解决了`sigmoid`的第二个`数据非0趋向`的问题。
zero-centered
这个问题。
我猜是不是因为
的区间只在sigmoid
,那么输出的分布是不均匀的,输出都是大于等于 的数,所以称为[0,1]
non zero-centered
。
而像
,输出区间分布在tanh
,分布能比较均匀,因此是[-1, 1]
zero-centerred
。
但是,
呢?区间是reLU
[0,x]
啊…
然后google了一下,大家都在说
的作用,但是没有解释zero-centered
zero-center
的意思…看了一些文章之后大概有了一点感觉。
点这里看Quora这位大哥对于zero-center的举例
看了这个之后,我觉得
应该是zero-center
应该有activation function
这个值。 看[0,0]
,是没有sigmoid
点的,因此就算你的[0,0]
预处理得离 (dataset
)有多好,但是normalized
sigmoid
还是不能给你一个良好的输出(这个输出永远大于0)。
然后结合
中那位大哥对于Quora
的解释,觉得对于神经网络做出决定来说,确切的 和确切的perceptron
是很重要的。中间的其他输出值都是杂项,是噪音,会干扰最终的决定,也会阻碍拟合的进程(噪音越严重,非0
w
的优化过程就越缓慢)。
这样想来,
也不行。下面还有负数的输出,同时也没有解决tanh
的问题。vanishing gradient
2) ReLu 12年的时候![](https://img-blog.csdn.net/20170519144639507?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 如上图,`tanh`的输出区间是`[-1, 1]`。虽然比`sigmoid`好一些,但是在`饱和神经元`的情况下,还是没有解决`vanishing gradient`的问题。
提出了使用Krizhevsky
这样的函数让神经网络的拟合更加迅速。max(0,x)
解决了ReLu
的问题,至少在正区间内,神经元不会饱和了。vanishing gradient
这里有疑问,x无限接近于0的时候,不就饱和了么… 那backprop的时候,gradient还是接近0的…再体会一下。
同时,解决了浪费计算资源的问题,
只是做一个门槛比较(ReLu
threshholding
),计算效率高。
最后,使用
ReLu
让神经网络拟合更快。
但是看到这里懵了,说
不是ReLu
… 刚才有google了一些文章,讲zero-centered
的,看到了relu
容易relu
的缺点,差不多就是一旦die
没有设置好,导致第一次learning_rate
的时候让update w
到了input
(负数那边),那么这个negative regime
节点就死亡了,再也不会被激活(因为relu
的导数relu
,如果流过去的drelu = 1 if x > 0 else 0
是 ,流回来的input
就是 ,gradient
不会被更新),导致w
不会被更新,也导致这个w
不再学习了。如下图。 但是关于这个neuron
,课后再查资料吧…估计zero-centered
就是中心点要在zero-centered
[0,0]
上…
3) Leaky Relu
为了解决
的问题,relu neuron will die
把负数区域的斜率调整了一些。如图。 这里提到了这个leaky relu
可以是任意数值,因此有了0.01
,将这个Prelu
之前的系数设置成变量x
,这个变量同样可以通过alpha
来学习,不断进行调整。 4) ELU 这个backprop
有activation function
所有的有点,并且输出的均值是接近relu
的。
但是可以看到,计算的时候是需要
exp()
的,产生了效率问题。
5) Maxout “Neuron”
有优点但是并不常见,如果使用这个激活函数,意味着每个
将有两组neuron
,感觉增加了神经网络的负担。w
-
小结
使用
,但是小心选择relu
learning_rate
。
尝试其他的函数,但是都不常用。
不要使用
。sigmoid
三、Data Preprocessing
在预处理
dataset
时,可以看到下图中的
zero-centered
和
normalized data
。
另外,在实践中,也有看到下面
PCA
主成分析和
Whitening
的。
不过,在针对图片的神经网络中,不太会用到
PCA
或者
Whitening
,或者是
Normalization
,常用的就是
centered
。
根据视频所说,
per-channel mean
的方式更加常用。因为只需要考虑颜色通道的
3
个数值,而不用考虑图片整体的
像素矩阵
。
四、Weight Initialization
问题:为什么不能将w初始化成0?
所有的neuron的输出都将是一样的,backprop时的gradient也将是一样的,不利于学习。
关于
W
的初始化,有下面几种方式的演进。
- 小随机数 这种方式适用在规模较小的神经网络中,但同时也很容易造成激活之后输出结果的不均匀分布。
下面会用图示来说明这个问题。
为了验证输出结果分布不均的问题,先创建了一个
层的每层有10
个500
的神经网络;使用neuron
作为非线性激活函数;tanh
的初始化就用上图中的公式。代码如图。 下面要做的就是,要统计一下上面这个网络每一层在W
之后的输出,并且看一下每层的输出的平均数和标准方差。画图如下。 通过上图可以看到,刚开始的时候,每一层的输出的平均值是一直是 ;再来看tanh activation
,从std
开始,一直下降,然后突然就栽到一直保持1
的状态。
然后看下直方图,第一层还挺正常的,数据还能均匀分布在
的区间内。之后就迅速收窄,所有的[-1,1]
输出都是接近tanh
了。
只要
的输出接近 ,那么在tanh
的时候,backprop
几乎也是 ,因此不仅gradient
W
得不到良好的更新调整,整个网络就像是在一个死循环一样。
这也是
vanishing gradient problem
的表现。
那么,如果将
调整成0.01
会如何呢?调整如下图。 可以看到,这是另一个极端。看直方图,几乎所有的1.0
都饱和了,意味着neuron
的输出要么是tanh
,要么是1
-1
。
在
的时候,所有的backprop
都是 ,那么什么都得不到更新,网络也不会进行任何学习。gradient
的选择要十分小心。在上述情况下,那么Weight Initialization
的值应该介于W
和1
0.01
之间。可以不断尝试在这中间找一个合适的值。
看一下学者对初始化的见解。
下图是10年提出的
。 用图中的公式初始化,可看到直方图的分布是很均匀的,没有过于饱和的地方,网络也能在合理的Xavier Initialization
backprop
中良好学习。
虽然看上图的
还是会降到 。Andrej解释是因为这个学术论文是没有考虑std
tanh
作为非线性函数的。即便如此,这样的下降看起来不像之前那样迅速,神经网络也能正常进行学习。
再继续,如果将
换成tanh
,应该好似用下面的初始化方式。如图。relu
-
Batch Normalization
之前所强调的,就是非线性之后的一个正态分布是很重要的。
下面的方法,就是怎么得到一个正态分布的非线性输出。
学者提出,既然那么想要正态分布,那就做一个正态分布即可。 上图中,
的公式将对输入的每一个维度作batch norm
normalization
。
这样的操作之后,所有的输出的数值就能成一个正态分布了。
通常,会将
插入到网络中,确保每一个batch normalization layers
的每一个特征维度,都能产生一个input x
。如图。unit gaussian activation
问题:需要给tanh函数传递unit gaussian的输入吗?
本来,在没有高斯分布的时候,tanh层的输入可以是任意可以调整的(backprop回来的gradient调整了w,下次进入tanh的输入和上次会有不同,并且分布是相对随机的,因此神经网络可以在这种随机分布情况下,通过更新w来控制tanh的输出的区间);但是一旦在tanh前加了一层BN(Batch Normalization)层,那么进入tanh的输入总是高斯分布的,网络本身就没有任何办法调整tanh的输出区间了。
之后,网络可以选择对BN
增加一个系数x
,并可以选择增加一个量γ
β
。保证输出的值在横向和竖向都可以动态调整。
在使用了这个方式之后,网络就能在
之后,对BN
tanh
的输入进行控制,如果需要的话。它可以选择缩放这个输入,或者上移,下移。
值得注意的是,公式中这个
和γ
是可以通过β
来学习的。因此,有了这两个变量之后,bakprop
就可以变成一个恒等函数(BN
identity function
),意思就是可有可无了,但是是由网络自身来控制。
一旦神经网络学会了
和γ
,它可以选择将β
的输出还原回BN
的输入,就像BN
BN
根本不存在一样。
网络可以通过学习,自己决定是否使用
。如果使用BN
是有好处的,那就保留,反之,则通过BN
和γ
重置β
BN
的变换。
整个
的过程如下。BN
的好处有如下几点:Batch Normalization
它能优化流经网络的gradient,让其不会vanish消失掉,也不会直接爆炸。
它能让我们设置更高的learning_rate,网络能在更短的时间内完成训练。
它让我们不再那么依赖Weight Initialization。这是最重要的一点。
它的作用像是之前提到过的regularization。可以减少之后要用到的dropout的量。可以这样想,Andrej提到了BN的作用就是将原本单独的一个input x,在BN之后,就和这个batch中其他的input捆绑到了一起。在weight regularization中,原理选择出分布更加均衡的weight来让网络的训练结果更加generalize。类似的,这里的input在被捆绑到一起之后,能够让神经网络更好地意识到每个特征之间的关系,比起单独单干的一个input,这样的训练方式可能可以取得更好的效果。(纯属胡说八道也说不定,以后再体会)
五、检查网络的学习过程
这里讲了一下从处理数据到完成训练一个神经网络的的流程。一旦发现哪一部有问题,可以提前停止,进行调整。
-
预处理数据
第一步就是预处理数据,如下图。
-
选择神经网络结构
选择适当的网络结构。
-
计算一次,确保loss在正常的区间
先将
设置为regularization
。 前面的视频说过,如果0.0
初始化没有问题,那么第一次的W
应该在loss
,大约-log(num_classes - 1)
2.3
。
然后提高一些
的值,比如到regularization
,正常情况下,1e3
也应该有所提高。loss
也有所提高,说明一切正常。loss
-
小批量数据
之后,可以先选取很小一部分数据来训练,这里只选取了
个20
。 这一步是确保创建的网络能够sample
小批量的数据。如下图。 这里,overfit
接近 ,loss
等于training acc
,成功1
了这overfitting
个20
sample
-
完整训练
这一步,首先从很小的regularization开始,先找到适当的learning_rate,可以使
下降。 如果loss
没有下降,可能是loss
设置太小。learning_rate
六、Hyperparameter Optimization
- 从粗糙到精细 可以先用一小部分的数据,像上面使用的
20
个,找到一个大致的能让网络学习起来的参数。
然后慢慢微调。
如果在调试过程中看到
大于了原有loss
loss
的三倍,直接停止训练,重新调整参数。
寻找参数的方式如下图。
-
微调
找到最初的参数之后,要进行微调。微调的时候,可以调整随机的区间,然后看哪一组数据的效果最好。
上图中,最下面红框中的准确率有
,但是要特别当心。因为产生这个准确率的%53
和reg
lr
都逼近边界值(10和1)。
说明了在机器学习中要也别当心边界值,边界值上的好效果可能意味着有内在的问题。当然也可能没有。
-
可视化训练过程以及观察数值比例
将
的下降可视化,如果平稳下降,没有出现奇葩情况,说明一切正常。如图。 最后,也可以检查loss
的更新值和W
的比值。正常应该再W
左右。1e-3
七、总结
这一集介绍了激活函数;介绍了预处理数据的几种方式;学习了如何初始化
Weight
;学习了
Batch Normalization
的作用;如何检查一个神经网络的参数是否正常,以及如何优化
hyper parameter
。