说明:本文依据《Sklearn 与 TensorFlow 机器学习实用指南》完成,所有版权和解释权均归作者和翻译成员所有,我只是搬运和做注解。
进入第二部分深度学习
第十一章训练深层神经网络
在第十章以及之前tf练习中,训练的深度神经网络都只是简单的demo,如果增大数据量或是面对更多的特征,遇到的问题就会棘手起来。
- 梯度消失(梯度爆炸),这会影响深度神经网络,并使较低层难以训练
- 训练效率
- 包含数百万参数的模型将会有严重的过拟合训练集的风险
- 本章中,教程从解释梯度消失问题开始,并探讨解决这个问题的一些最流行的解决方案。
- 接下来讨论各种优化器,与普通梯度下降相比,它们可以加速大型模型的训练。
- 介绍大型神经网络正则化技术。
3.使用LeakyRelu作为激活函数,训练神经网络
在这里使用Leaky Relu训练一个神经网络,处理MNIST数据集。
def logit(z): return 1 / (1 + np.exp(-z)) z = np.linspace(-5, 5, 200) def leaky_relu(z, alpha=0.01): #注意,这里应该是tf而不是教程中的np,Tensorflow通常接受numpy数组(它们的值是静态已知的,因此可以转换为常量),但反之则不然(只有在运行会话时才知道张量值,除了急切的评估) return tf.maximum(alpha * z, z) reset_graph() n_inputs = 28 * 28 n_hidden1 = 300 n_hidden2 = 100 n_outputs = 10 X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X") y = tf.placeholder(tf.int32, shape=(None), name="y") with tf.name_scope("dnn"): hidden1 = tf.layers.dense(X, n_hidden1, activation=leaky_relu, name="hidden1") hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=leaky_relu, name="hidden2") logits = tf.layers.dense(hidden2, n_outputs, name="outputs") 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() (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:] 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 n_epochs=40 batch_size=50 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, feed_dict={X: X_batch, y: y_batch}) if epoch%5==0: acc_batch = accuracy.eval(feed_dict={X: X_batch, y: y_batch}) acc_valid = accuracy.eval(feed_dict={X: X_valid, y: y_valid}) print(epoch, "Batch accuracy:", acc_batch, "Validation accuracy:", acc_valid) save_path = saver.save(sess, "./tf_logs/run-20190126025648/tensorflowmodel01.ckpt") 0 Batch accuracy: 0.86 Validation accuracy: 0.9044 5 Batch accuracy: 0.94 Validation accuracy: 0.9494 10 Batch accuracy: 0.92 Validation accuracy: 0.9656 15 Batch accuracy: 0.94 Validation accuracy: 0.971 20 Batch accuracy: 1.0 Validation accuracy: 0.9762 25 Batch accuracy: 1.0 Validation accuracy: 0.9772 30 Batch accuracy: 0.98 Validation accuracy: 0.9782 35 Batch accuracy: 1.0 Validation accuracy: 0.9788
使用Elu
Djork-Arné Clevert 等人在 2015 年的一篇论文中提出了一种称为指数线性单元(exponential linear unit,ELU)的新的激活函数。
Elu表现优于所有的 ReLU 变体:训练时间减少,神经网络在测试集上表现的更好。
公式看起来很像 ReLU 函数,但有一些区别:
- 在z < 0时取负值,这使得该单元的平均输出接近于 0。这有助于减轻梯度消失问题,如前所述。 超参数α定义为当z是一个大的负数时,ELU 函数接近的值。它通常设置为 1,但是如果你愿意,你可以像调整其他超参数一样调整它。
- 对z < 0有一个非零的梯度,避免了神经元死亡的问题。
- 函数在任何地方都是平滑的,包括z = 0左右,这有助于加速梯度下降,因为它不会弹回z = 0的左侧和右侧。
ELU 激活函数的主要缺点是计算速度慢于 ReLU 及其变体(由于使用指数函数)。
那么你应该使用哪个激活函数来处理深层神经网络的隐藏层?
一般 ELU > leaky ReLU(及其变体)> ReLU > tanh > sigmoid。
- 如果关心运行时性能,可以使用leaky ReLU。
- 如果不想调整另一个超参数,可以使用默认的α值(leaky ReLU 为 0.01,ELU 为 1)。
- 如果有充足的时间和计算能力,可以使用交叉验证来评估其他激活函数,特别是如果您的神经网络过拟合,则为RReLU;
- 如果拥有庞大的训练数据集,可以使用 PReLU。
TensorFlow 提供了一个可以用来建立神经网络的elu()函数。 调用fully_connected()函数时,只需设置activation_fn参数即可(activation=tf.nn.elu)。
在训练期间,由使用SELU激活函数的一堆密集层组成的神经网络将自我归一化:每层的输出将倾向于在训练期间保持相同的均值和方差,这解决了消失/爆炸的梯度问题。因此,这种激活功能对于这样的神经网络来说非常显着地优于其他激活功能,因此应该尝试一下。
def elu(z, alpha=1): return np.where(z < 0, alpha * (np.exp(z) - 1), z) reset_graph() n_inputs = 28 * 28 n_hidden1 = 300 n_hidden2 = 100 n_outputs = 10 def selu(z, scale=1.0507009873554804934193349852946, alpha=1.6732632423543772848170429916717): return scale * tf.where(z >= 0.0, z, alpha * tf.nn.elu(z)) X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X") y = tf.placeholder(tf.int32, shape=(None), name="y") with tf.name_scope("dnn"): hidden1 = tf.layers.dense(X, n_hidden1, activation=selu, name="hidden1") hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=selu, name="hidden2") logits = tf.layers.dense(hidden2, n_outputs, name="outputs") 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 = 40 batch_size = 50 (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:] 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 means = X_train.mean(axis=0, keepdims=True) stds = X_train.std(axis=0, keepdims=True) + 1e-10 X_val_scaled = (X_valid - means) / stds 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): X_batch_scaled = (X_batch - means) / stds sess.run(training_op, feed_dict={X: X_batch_scaled, y: y_batch}) if epoch % 5 == 0: acc_batch = accuracy.eval(feed_dict={X: X_batch_scaled, y: y_batch}) acc_valid = accuracy.eval(feed_dict={X: X_val_scaled, y: y_valid}) print(epoch, "Batch accuracy:", acc_batch, "Validation accuracy:", acc_valid) save_path = saver.save(sess, "./tf_logs/run-20190126025649/tensorflowmodel02selu.ckpt") 0 Batch accuracy: 0.88 Validation accuracy: 0.9232 5 Batch accuracy: 0.98 Validation accuracy: 0.9574 10 Batch accuracy: 1.0 Validation accuracy: 0.9662 15 Batch accuracy: 0.96 Validation accuracy: 0.9684 20 Batch accuracy: 1.0 Validation accuracy: 0.9692 25 Batch accuracy: 1.0 Validation accuracy: 0.969 30 Batch accuracy: 1.0 Validation accuracy: 0.9694 35 Batch accuracy: 1.0 Validation accuracy: 0.9702
本文暂时没有评论,来添加一个吧(●'◡'●)