文章目录
-
-
- 1、BatchNormalization
-
- 1.1 简介
- 1.2 作用
- 1.3 一般用法
- 2、激活函数
-
- 2.1 简介
- 2.2 作用
- 2.3 一般用法
-
- 2.3.1 sigmoid
- 2.3.2 tanh
- 2.3.3 RELU
- 2.4 激活函数使用总结
- 3、Mask
-
- 3.1 简介
- 4 softmax
-
- 4.1 K.softmax
- 4.2 layer.softmax
- 参考文献
-
1、BatchNormalization
1.1 简介
BatchNorm来源参考论文:Ioffe S, Szegedy C. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift[J]. international conference on machine learning, 2015: 448-456.
作者认为:网络训练过程中参数不断改变导致后续每一层输入的分布也发生变化,而学习的过程又要使每一层适应输入的分布,因此我们不得不降低学习率、小心地初始化。作者将分布发生变化称之为 internal covariate shift。
1.2 作用
而BatchNorm是干啥的呢?BatchNorm就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布的。在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1。
训练时,都是一批批的训练数据,比如batch size=32,那一次输入32个数据。这一数据可能满足一个分布A,如果A分布比较不规律,那分布A在通过激活函数(非线性层)时,激活的效果就不如我们期望。(神经网络就是通过特征提取层(如conv)提取特征再通过激活函数选取特征从而实现神经网络的函数表达力)
如图:

对于一二两种情况,要么等于没用激活函数;要么激活作用得过多,一大批0传到后面。当然,在不断训练的过程中,情况一二都会慢慢减少,因为特征提取层越来越牛x。但这需要用更多训练时间去填补,而且最终的性能不会很好,虽然是batch训练,但它的视野没到batch分布那个层面。视野太窄,也更容易过拟合。如果用其他激活函数比如sigmoid/tanh等,还有梯度加速弥散的问题存在。(自己可以画图看看,两端抑制)
OK,我们想要的是上图表示的第三种情况,激活函数的修剪率适中。这就需要用到BN操作了。
使用BatchNorm效果怎么样呢,非常好。经过这么简单的变换,不仅仅极大提升了训练速度,收敛过程大大加快,还提升效果。
1.3 一般用法
FC + BN + RELU (可以替代 FC + Dropout + RELU)
Conv + BN + RELU + Maxpooling
2、激活函数
2.1 简介
激活函数是指在网络中某一层的输出位置加入一个非线性函数,常用的激活函数有sigmoid、relu、tanh等等。
2.2 作用
神经网络中激活函数的主要作用是提供网络的非线性建模能力。假设一个神经网络中仅包含线性卷积和全连接运算,那么该网络仅能够表达线性映射,即便增加网络的深度也依旧还是线性映射,难以有效建模实际环境中非线性分布的数据。加入(非线性)激活函数之后,深度神经网络才具备了分层的非线性映射学习能力。
2.3 一般用法
2.3.1 sigmoid
sigmoid函数如下所示,有两个缺陷:饱和性、非0均值。
饱和性是指函数的饱和区域梯度接近或等于0,训练时梯度传递接近于0,梯度消失。
非0均值是指输出不是0均值,称为偏移现象,这将导致后一层的神经元将上一层输出的非0均值的信号作为输入。关于原点对称的输入和中心对称的输出,网络会收敛地更好。
2.3.2 tanh
tanh函数如下图说是,克服了sigmoid非0均值的缺点,但是饱和问题依然存在。
2.3.3 RELU
ReLU函数如下图所示。从图中可以看到,当x<0时,出现硬饱和,当x>0时,不存在饱和问题。因此,ReLU 能够在x>0时保持梯度不衰减,从而缓解梯度消失问题。然而,随着训练的推进,部分输入会落入硬饱和区,导致对应权重无法更新,这种现象被称为“神经元死亡”。
Leaky-ReLU与P-ReLU函数在一定程度上解决了神经元死亡的问题。
ELU函数在解决神经元死亡的基础上将均值归0。
2.4 激活函数使用总结
Use ReLU. Be careful with your learning rates
Try out Leaky ReLU / ELU
Try out tanh but don’t expect much
Don’t use sigmoid
3、Mask
3.1 简介
众所周知,LSTM的一大优势就是其能够处理变长序列。而在使用keras搭建模型时,如果直接使用LSTM层作为网络输入的第一层,需要指定输入的大小。如果需要使用变长序列,那么,只需要在LSTM层前加一个Masking层,或者embedding层即可。
from keras.layers import Masking, Embedding
from keras.layers import LSTM
model = Sequential()
model.add(Masking(mask_value= -1,input_shape=(sequenceLength, 23*3,)))
model.add(LSTM(100, dropout_W=0.2, dropout_U=0.2, input_shape=(sequenceLength, 23*3,)))
使用方法:首先将序列转换为定长序列,如,选取一个序列最大长度,不足这个长度的序列补-1。然后在Masking层中mask_value中指定过滤字符。如上代码所示,序列中补的-1全部被过滤掉。
此外,embedding层也有过滤的功能,但与masking层不同的是,它只能过滤0,不能指定其他字符,并且因为是embedding层,它会将序列映射到一个固定维度的空间中。因此,如果诉求仅仅是让keras中LSTM能够处理变长序列,使用Masking层会比使用Embedding层更加适合。
4 softmax
4.1 K.softmax
def softmax(x, axis=-1):
y = np.exp(x - np.max(x, axis, keepdims=True))
return y / np.sum(y, axis, keepdims=True)
4.2 layer.softmax
参考文献
[1] https://blog.csdn.net/shenziheng1/article/details/81254206