import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
graph = tf.Graph()
with graph.as_default():
data = tf.constant(np.random.randn(2000, 800).astype('float32'))
layer_sizes = [800 - 50 * i for i in range(0,10)]
num_layers = len(layer_sizes)
fcs = []
for i in range(0, num_layers - 1):
X = data if i == 0 else fcs[i - 1]
node_in = layer_sizes[i]
node_out = layer_sizes[i + 1]
W = tf.Variable(np.random.randn(node_in, node_out).astype('float32')) * 0.01
fc = tf.matmul(X, W)
#fc = tf.contrib.layers.batch_norm(fc, center=True, scale=True,
# is_training=True)
#fc = tf.nn.relu(fc)
fc = tf.nn.tanh(fc)
fcs.append(fc)
with tf.Session(graph=graph) as sess:
sess.run(tf.global_variables_initializer())
print('input mean {0:.5f} and std {1:.5f}'.format(np.mean(data.eval()),
np.std(data.eval())))
for idx, fc in enumerate(fcs):
print('layer {0} mean {1:.5f} and std {2:.5f}'.format(idx+1, np.mean(fc.eval()),
np.std(fc.eval())))
plt.figure()
for idx, fc in enumerate(fcs):
plt.subplot(1, len(fcs), idx+1)
plt.hist(fc.eval().flatten(), 30, range=[-1,1])
plt.xlabel('layer ' + str(idx + 1))
plt.yticks([])
plt.show()
训练结果如图所示:
这里我们创建了一个10层的神经网络,非线性变换为tanh,每一层的参数都是随机正态分布,均值为0,标准差为0.01。下图给出了每一层输出值分布的直方图
随着层数的增加,我们看到输出值迅速向0靠拢,在后几层中,几乎所有的输出值都很接近0!回忆优化神经网络的back propagation算法,根据链式法则,gradient等于当前函数的gradient乘以后一层的gradient,这意味着输出值是计算gradient中的乘法因子,直接导致gradient很小,使得参数难以被更新!
调整代码中的去掉0.01:
代码修改如下(Xavier initialization),仍然是针对tanh函数:
这种初始化对于 tanh表现良好
修改代码如下,激活函数由tanh修改成relu:
这种初始化在relu中表现一般,越深就越差;
修改代码如下:
输出结果如下:
这种初始化非常适用于relu激活函数;但对tanh会怎么样呢?
修改代码如下:
看来也行;
最后看看bn的效果,相对上图,多了个bn函数:
非常完美;
将tanh变成relu:
仍然完美!
将初始化的值改变:
再将relu变成tanh:
非常完美!
将代码改成:非常大的初始值:
如图所示:
针对relu函数,
初始化值非常大时,值都变得不正常!
加入bn,效果如图所示:
非常完美!
足以证明bn的作用;