Part 1
本来想写一篇dropout的文章,有人写的很好了,我就直接借鉴了
先上链接:深度学习中Dropout原理解析
但是文章中有一个地方说的有点混乱,测试集缩放概率问题,重新理一下:
dropout,防止过拟合,还可以提高训练速度。
加入dropout的概率为p,就是神经元以p的概率失活,相当于比如p设定为0.4,那100个节点会有40个节点失活,不参与训练。
简单说一下逻辑:
1. 定义dropout的概率值p
2. 通过伯努利算法生成神经元节点对应的0 1值,0表示需要进行失活操作
3. 保存0对应的节点的参数值,对其进行失活操作(其实就是乘以0)
4. 进行前向传播和反向传播,更新未失活节点的权重,失活的神经元权重为失活前保存的权重值
5. 重新进行下一轮迭代
说明下,失活之后,神经元的个数少了,但是测试的时候不能对神经元失活操作,这就导致了训练时神经元个数为 (1-p) * m, 而测试时是全量的神经元个数m,所以需要进行缩放,有两种方式,① 训练阶段失活操作之后,对未失活节点的权重 乘以1/(1-p) ② 测试阶段,对所有权重 乘以(1-p)操作。
Part 2
过了段时间,刚好看到一些大佬DL 源码,发现了一点问题,查阅资料又有些新的发现
拿BertModel来举例,调用的时候,初始化代码可以设置个参数 is_training, True 表示训练过程,False表示测试过程,那Part1部分已经说到了,dropout训练和测试是有区别的,代码部分怎么体现呢?
首先,需要初始化不同的prob,这里有两个,一个是hidden层权重的dropout prob,另一个是attention部分的权重对应的dropout的prob
config.hidden_dropout_prob = tf.cond(is_training, lambda: config.hidden_dropout_prob, lambda: 0.0)
config.attention_probs_dropout_prob = tf.cond(is_training, lambda: config.attention_probs_dropout_prob, lambda: 0.0)
config 就是你初始设置的dropout值
那下一步怎么让这个dropout生效呢?
其实就是一个dropout函数tf.nn.dropout(input_tensor, 1.0 - dropout_prob),对应的scale也是在dropout函数里实现的。使用如下:
attention_probs = tf.nn.softmax(attention_scores)
attention_probs = dropout(attention_probs, attention_probs_dropout_prob)
attention_output = dropout(attention_output, hidden_dropout_prob)
attention_output = layer_norm(attention_output + layer_input)
layer_output = dropout(layer_output, hidden_dropout_prob) # dropout
layer_output = layer_norm(layer_output + attention_output) # norm layer和attention结果
第一部分是对attention得到的权重进行的dropout,也就是说本来权重应该乘value,先dropout之后再乘value
第二部分是对得到的attention结果进行dropout
第三部分是对layer节点进行dropout
参考链接:https://zhuanlan.zhihu.com/p/29764091 这篇介绍的更为全面,包括dropout的源码
https://www.jianshu.com/p/c9f66bc8f96c