说明:本文依据《Sklearn 与 TensorFlow 机器学习实用指南》完成,所有版权和解释权均归作者和翻译成员所有,我只是搬运和做注解。
进入第二部分深度学习
第十一章训练深层神经网络
在第十章以及之前tf练习中,训练的深度神经网络都只是简单的demo,如果增大数据量或是面对更多的特征,遇到的问题就会棘手起来。
- 梯度消失(梯度爆炸),这会影响深度神经网络,并使较低层难以训练
- 训练效率
- 包含数百万参数的模型将会有严重的过拟合训练集的风险
- 本章中,教程从解释梯度消失问题开始,并探讨解决这个问题的一些最流行的解决方案。
- 接下来讨论各种优化器,与普通梯度下降相比,它们可以加速大型模型的训练。
- 介绍大型神经网络正则化技术。
5.批量标准化
尽管使用 He初始化和 ELU(或任何 ReLU 变体)可以显著减少训练开始阶段的梯度消失/爆炸问题,但不保证在训练期间问题不会回来,这样就提出了批量标准化策略,通过对每一层的输入值进行zero-centering和规范化,然后每层使用两个新参数(一个用于尺度变换,另一个用于偏移)对结果进行尺度变换和偏移。
这个操作可以让模型学习到每层输入值的最佳尺度,均值。为了对输入进行归零和归一化,算法需要估计输入的均值和标准差。通过评估当前小批量输入的均值和标准差(因此命名为“批量标准化”)来实现。
tensorflow中使用tf.layers.batch_normalization()完成批量标准化。
以下代码为一个完整的经过标准化的神经网络
reset_graph() import tensorflow as tf (X_train,y_train),(X_test,y_test)=tf.keras.datasets.mnist.load_data() X_train=X_train.astype(np.float32).reshape(-1,28*28)/255.0 X_test = X_test.astype(np.float32).reshape(-1, 28*28) / 255.0 y_train = y_train.astype(np.int32) y_test = y_test.astype(np.int32) X_valid, X_train = X_train[:5000], X_train[5000:] y_valid, y_train = y_train[:5000], y_train[5000:] n_inputs = 28 * 28 n_hidden1 = 300 n_hidden2 = 100 n_outputs = 10 #可以看到每一层以及输出层都做了标准化 X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X") training = tf.placeholder_with_default(False, shape=(), name="training") hidden1 = tf.layers.dense(X, n_hidden1, name="hidden1") bn1 = tf.layers.batch_normalization(hidden1, training=training, momentum=0.9) bn1_act = tf.nn.elu(bn1) hidden2 = tf.layers.dense(X, n_hidden2, name="hidden2") bn2 = tf.layers.batch_normalization(hidden2, training=training, momentum=0.9) bn2_act = tf.nn.elu(bn2) logits_before_bn = tf.layers.dense(bn2_act, n_outputs, name="outputs") logits = tf.layers.batch_normalization(logits_before_bn, training=training, momentum=0.9)
现在构建一个处理MNIST数据集的神经网络,每一层使用ELU作为激活函数
reset_graph() batch_norm_momentum=0.9 X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X") y=tf.placeholder(tf.int32, shape=(None), name="y") training=tf.placeholder_with_default(False, shape=(), name="training") with tf.name_scope("dnn"): he_init=tf.variance_scaling_initializer() # 为了防止重复设定参数,这里使用了Python的partial方法 # 对权重的初始化 my_batch_norm_layer=partial( tf.layers.batch_normalization, training=training, momentum=batch_norm_momentum ) my_dense_layer=partial( tf.layers.dense, kernel_initializer=he_init ) hidden1=my_dense_layer(X,n_hidden1,name="hidden1") bn1=tf.nn.elu(my_batch_norm_layer(hidden1)) hidden2=my_dense_layer(bn1,n_hidden2,name="hidden2") bn2=tf.nn.elu(my_batch_norm_layer(hidden2)) logits_before_bn=my_dense_layer(bn2,n_outputs,name="outputs") logits=my_batch_norm_layer(logits_before_bn) with tf.name_scope("loss"): xentropy=tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y,logits=logits) loss=tf.reduce_mean(xentropy,name="loss") learning_rate = 0.01 with tf.name_scope("train"): optimizer=tf.train.GradientDescentOptimizer(learning_rate) training_op = optimizer.minimize(loss) with tf.name_scope("eval"): correct=tf.nn.in_top_k(logits,y,1) accuracy=tf.reduce_mean(tf.cast(correct,tf.float32)) init=tf.global_variables_initializer() saver=tf.train.Saver() n_epochs=20 batch_size=200 def shuffle_batch(X, y, batch_size): rnd_idx = np.random.permutation(len(X)) n_batches = len(X) // batch_size for batch_idx in np.array_split(rnd_idx, n_batches): X_batch, y_batch = X[batch_idx], y[batch_idx] yield X_batch, y_batch extra_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) with tf.Session() as sess: init.run() for epoch in range(n_epochs): for X_batch , y_batch in shuffle_batch(X_train, y_train, batch_size): sess.run([training_op,extra_update_ops], feed_dict={training:True,X:X_batch,y:y_batch} ) accuracy_val=accuracy.eval(feed_dict={X:X_valid,y:y_valid}) print(epoch, accuracy_val) save_path=saver.save(sess,"./tf_logs/run-2019012801001/tensorflowmodel01normalization.ckpt")
以下使训练结果,因为设置的随机种子都是42,可以看到结果和教程中的一致。
0 0.8952
1 0.9202
2 0.9318
3 0.9422
4 0.9468
5 0.954
6 0.9568
7 0.96
8 0.962
9 0.9638
10 0.9662
11 0.9682
12 0.9672
13 0.9696
14 0.9706
15 0.9704
16 0.9718
17 0.9726
18 0.9738
19 0.9742
本文暂时没有评论,来添加一个吧(●'◡'●)