tf.nn.dropout函数
首先看官方函数定义:
def dropout(x, keep_prob, noise_shape=None, seed=None, name=None)
输入是:
输出是:
然后我们看看官方API是怎么说这个函数的:
With probability keep_prob, outputs the input element scaled up by 1 / keep_prob, otherwise outputs 0. The scaling is so that the expected sum is unchanged.
注意,输出的非0元素是原来的 “1/keep_prob” 倍!说了这么多,下面给一个程序例子:
import tensorflow as tf
dropout = tf.placeholder(tf.float32)
x = tf.Variable(tf.ones([10, 10]))
y = tf.nn.dropout(x, dropout)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
print sess.run(y, feed_dict = {dropout: 0.4})
运行的结果如下:
[[ 0. 0. 2.5 2.5 0. 0. 2.5 2.5 2.5 2.5]
[ 0. 2.5 2.5 2.5 2.5 2.5 0. 2.5 0. 2.5]
[ 2.5 0. 0. 2.5 0. 0. 2.5 0. 2.5 0. ]
[ 0. 2.5 2.5 2.5 2.5 0. 0. 2.5 0. 2.5]
[ 0. 0. 0. 0. 0. 0. 0. 0. 2.5 2.5]
[ 2.5 2.5 2.5 0. 2.5 0. 0. 2.5 2.5 2.5]
[ 0. 2.5 2.5 2.5 0. 2.5 2.5 0. 0. 0. ]
[ 0. 2.5 0. 2.5 0. 0. 2.5 2.5 0. 0. ]
[ 2.5 2.5 2.5 2.5 2.5 0. 0. 2.5 0. 0. ]
[ 2.5 0. 0. 0. 0. 0. 2.5 2.5 0. 2.5]]
分析一下运行结果:
特点分析完毕,小总结一下,dropout这个概念看起来好高大上,然而在程序中实现竟然如此简单!说白了,tensorflow中的dropout就是:使输入tensor中某些元素变为0,其它没变0的元素变为原来的1/keep_prob大小!
dropout 一般是用来消除过拟合的
在机器学习中可能会存在过拟合的问题,表现为在训练集上表现很好,但在测试集中表现不如训练集中的那么好。
图中黑色曲线是正常模型,绿色曲线就是overfitting模型。尽管绿色曲线很精确的区分了所有的训练数据,但是并没有描述数据的整体特征,对新测试数据的适应性较差。
一般用于解决过拟合的方法有增加权重的惩罚机制,比如L2正规化,但在本处我们使用tensorflow提供的dropout方法,在训练的时候, 我们随机忽略掉一些神经元和神经联结 , 是这个神经网络变得”不完整”. 用一个不完整的神经网络训练一次.
到第二次再随机忽略另一些, 变成另一个不完整的神经网络. 有了这些随机 drop 掉的规则, 我们可以想象其实每次训练的时候, 我们都让每一次预测结果都不会依赖于其中某部分特定的神经元. 像l1, l2正规化一样, 过度依赖的 W , 也就是训练参数的数值会很大, l1, l2会惩罚这些大的 参数. Dropout 的做法是从根本上让神经网络没机会过度依赖.
def add_layer(inputs, in_size, out_size, activation_function=None):
"""
添加层
:param inputs: 输入数据
:param in_size: 输入数据的列数
:param out_size: 输出数据的列数
:param activation_function: 激励函数
:return:
"""
# 定义权重,初始时使用随机变量,可以简单理解为在进行梯度下降时的随机初始点,这个随机初始点要比0值好,因为如果是0值的话,反复计算就一直是固定在0中,导致可能下降不到其它位置去。
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
# 偏置shape为1行out_size列
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
# 建立神经网络线性公式:inputs * Weights + biases,我们大脑中的神经元的传递基本上也是类似这样的线性公式,这里的权重就是每个神经元传递某信号的强弱系数,偏置值是指这个神经元的原先所拥有的电位高低值
Wx_plus_b = tf.matmul(inputs, Weights) + biases
# 调用dropout功能
Wx_plus_b = tf.nn.dropout(Wx_plus_b, keep_prob)
if activation_function is None:
# 如果没有设置激活函数,则直接就把当前信号原封不动地传递出去
outputs = Wx_plus_b
else:
# 如果设置了激活函数,则会由此激活函数来对信号进行传递或抑制
outputs = activation_function(Wx_plus_b)
return outputs