11.Batch Normalization
我们觉得说error surface 如果很崎岖的时候,它比较难train,我们能不能够直接把山铲平,让它比较好train呢?
batch normalization就是其中一个把山铲平的想法。
在一开始讲optimization 的时候,一开始就说不要小看optimization这个问题。有时候就是你的error surface 是confessed 的(比如一个碗状)都不见得很好train。
那我们举的例子就是假设你的两个参数,他们对loss的斜率差别非常大,在W1这个方向上面,你的斜率变化很小,W2上面变化很大,如果是固定的learning rate 你可能很难得到好的结果,所以我们才需要adaptive 的learning rate ,比较进阶的optimization的方法才能够得到好的结果。
我们现在可以从另一个方向想,直接把难做的error surface 把他改掉。
举例:假设我们现在有一个非常非常简单的 linear model 没有activation function,输入是 x1 ,x2 对应的参数是w1 w2 ,那什么样的状况我们会产生上面这种比较不好train 的 error surface 呢?
如果 w1或 w2 有改变,y 就有改变,e 随着也有改变,进而 loss 也有改变
当你的 input 很小的时候 ,假设x1的值都很小,w1有一个变化的时候,它对y的影响也是小的,进而 loss 变化也是小的。
当你的 input 很大的时候 ,假设x2的值都很大,w2有一个变化的时候,它对y的影响也是大的,进而 loss 变化也是小的。
当我们input 的 feature 每一个 dimension 的值它的scale差距很大的时候,我们就可能产生像这样子的error surface。
如果我们可以给不同的dimension 同样的数值范围的话,那我们可能就可以制造比较好的error surface,让training变得比较容易一点。
我们有很多不同的方法可以做到这一点,我们将其统称为feature normalization
其中一个方法是:
假设x1到xR 是我们所有训练资料的feature vector,我们把同一个dimension 不同笔资料中的数值取出来,去计算mean 记作mi ;第 i 个 dimension 的 standard deviation 记作 σi
接下来我们就可以做一种normalization 其实叫做标准化 得到新的数值,在把它塞回去
做完normalization的好处:这个dimension 上面的数值就会平均是0 ,他的variances 就会是 1。
当所有的dimension 都做一样的normalization之后,所有feature 不同的 dimension 的数值都在 0 上下,那你可能就会制造一个比较好的 error surface。所以像这样的normalization 往往对你的training 有帮助, 可以让你在做gradient descent 的时候 它的loss 收敛的更快一点。
当然 deep learning 可以做feature normalization ,你可能会把feature 做 normalization 以后
得到 x拔 把它丢到deep network 里面去做接下来的计算。
但是我们进一步来想的话,对 w2 来说,a1 a2 a3 其实也是另外一种input ,虽然x拔 已经做过normalization 但是通过w1 以后他就没有做normalization。
如果z1 不同的dimension 间它的数值分布仍然有很大的差异的话,要train w2 第二层的参数会不会也有困难呢?
所以这样想起来,我们也应该对a 或 z 进行normalization(对w2 来说 a 或z 其实也是一种feature)。
那我们应该在 activation function 之前做normalization 还是之后呢?
在实际操作上这两件事情其实差异不大,如果你选的是sigmoid,那可能比较推荐对z做feature normalization(因为 sigmoid 在0 附近斜率比较大,所以如果你对z做feature normalization 把所有的值都挪到 0 附近到时候算出来的 gradient 的值会比较大)。
对z 做一下 feature normalization:把 z 想成是另外一种 feature ,把三个vector 里面的每一个dimension 都去把他的 μ 和 σ 算出来
然后把 z 标准化(下图右上角公式)
现在有一个有趣的事情,当z1 改变的时候 μ 和 σ 也会随着改变 ,右侧 z1 z2 z3 的值也会跟着改变
之前 x1 x2 x3 (左侧)它是独立分开处理的,但是我们在做feature normalization 以后,这三个example 他们变得彼此关联了,所以当你做feature normalization 的时候你要把这一整个process 就是收集一堆feature,算出 μ 和 σ 这件事情,当做network的一部分。
也就是说你现在有一个比较大的network ,之前的network 都只是吃一个input 得到一个output 。现在呢,这个大的network 它是吃一堆 input,用这堆input 在这个network里面算出 μ 和 σ 然后接下来产生一堆output。
随之而来的一个问题是:你的训练资料里 你的data 非常多,没有办法一次把上百万的数据丢到一个 network 里面,怎么办?
在实际操作中,你不应该让这个一个network 考虑整个training data 里面的所有example 你只会考虑一个batch 里面的 example。
因为我们在实际操作中只对一个batch 里面的 data 做normalization ,所以这招叫做Batch Normalization。
注:Batch Normalization 适用于batch size 比较大的时候。
在做Batch Normalization 的时候,往往还会有下面的操作(红框)
实操中, γ初始值是一个都是1 的向量,β 初始值是一个都是 0 的向量。
让你的network 在一开始训练的时候,每一个dimension 的分布是比较接近的,也许训练到后来,训练够长的一段时间,已经找到一个比较好的error surface 走到一个好的地方以后,再把 γ 和 β 慢慢的加进去。
接下来是testing 部分。testing 有时 又叫 inference 。paper中inference 指的就是testing。
Batch Normalization在testing 中遇到一些问题;
假设你真的有系统上线,你的batch 设 64 ,我一定要等64笔资料都进来,我才做一次运算吗?
这显然是不行的,如果是线上服务,每笔资料进来你都有做一次运算,你不能等说累积了一个batch的资料才开始做运算。
那如果根本就没有一个batch 我们怎么算μ 和 σ?
实际上的解法是 pytorch 已经帮你处理好了。用训练的时候得到的μ拔 和 σ拔 来代替。
其中 p 是一个hyper parameter ,通常设为0.1