编者按:和DeepMind数据科学家、Udacity深度学习导师Andrew Trask一起,基于Numpy手写神经网络,更深刻地理解dropout这一概念。
总结:几乎所有目前最先进的神经网络都用到了dropout. 这篇教程介绍如何通过几行Python代码在神经网络中加入Dropout. 读完这篇教程之后,你将得到一个可以工作的dropout实现,并且掌握在任何神经网络中加入和调整dropout的技能。
如果你对我的文章感兴趣,欢迎在推特上关注 @iamtrask,也欢迎给我反馈。
import numpy as np
X = np.array([ [0,0,1],[0,1,1],[1,0,1],[1,1,1] ])
y = np.array([[0,1,1,0]]).T
alpha,hidden_dim,dropout_percent,do_dropout = (0.5,4,0.2,True)
synapse_0 = 2*np.random.random((3,hidden_dim)) - 1
synapse_1 = 2*np.random.random((hidden_dim,1)) - 1
for j in xrange(60000):
layer_1 = (1/(1+np.exp(-(np.dot(X,synapse_0)))))
if(do_dropout):
layer_1 *= np.random.binomial([np.ones((len(X),hidden_dim))],1-dropout_percent)[0] * (1.0/(1-dropout_percent))
layer_2 = 1/(1+np.exp(-(np.dot(layer_1,synapse_1))))
layer_2_delta = (layer_2 - y)*(layer_2*(1-layer_2))
layer_1_delta = layer_2_delta.dot(synapse_1.T) * (layer_1 * (1-layer_1))
synapse_1 -= (alpha * layer_1.T.dot(layer_2_delta))
synapse_0 -= (alpha * X.T.dot(layer_1_delta))
如同前一篇文章提到的,神经网络是一个美化的搜索问题。神经网络中的每一个节点搜索输入数据和正确的输出数据之间的相关性。
考虑前一篇中的图片。曲线表示网络对应每个具体权重产生的误差。曲线的低点(读作:低误差)标志着权重“找到”输入和输出之间的关系。图中的球标志着不同的权重。它们都试图找到低点。
考虑颜色。球的初始位置是随机生成的(就像神经网络的权重)。如果两个球随机开始于同一颜色区域,那么它们将收敛于同一点。这里存在冗余!浪费算力和内存!这正是神经网络中发生的事。
为何dropout: dropout有助于防止权重收敛于同一位置。它通过在前向传播阶段随机关闭节点做到这一点。接着在反向传播时激活所有节点。让我们仔细看看。
为了在网络层上执行dropout,我们在前向传播阶段随机设置层的值为0——见第10行。
第9行: 参数化是否使用dropout. 我们只打算在训练阶段使用dropout. 不要在运行时使用dropout,也不要在测试数据集上使用dropout. 此外,这一行也意味着我们需要增大前向传播的值。这与关闭的值的数目成正比。一个简单的直觉是,如果你关闭一半的隐藏层,那么你需要加倍前向传播的值,以正确补偿输出。感谢@karpathy指出这一点。
调整的最佳实践
第4行: 参数化dropout百分比。这影响关闭任何一个节点的概率。对隐藏层而言,较好的初始值设定是50%. 如果将dropout应用于输入层,最好不要超过25%.
Hinton主张在调整dropout的同时调整隐藏层的大小。首先关闭dropout,增加隐藏层尺寸,直到你完美地拟合了你的数据。接着,使用相同的隐藏层尺寸,开启dropout进行训练。这应该是一个近乎最优的配置。一旦结束训练,关闭dropout。万岁!你有了一个可以工作的神经网络!
原文地址:http://iamtrask.github.io/2015/07/28/dropout/