想必学过机器学习的人都知道,学习率、训练迭代次数和模型参数的初始化方式都对模型最后的准确率有一定的影响,那么影响到底有多大呢?
我初步做了个实验,在 TensorFlow 框架下使用 Logistics Regression 对经典的 MNIST 数据集进行分类。
本文所说的 准确率 均指 测试准确率。
代码
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/home/alan/data/", one_hot=True)
from __future__ import print_function
import tensorflow as tf
import matplotlib.pyplot as plt
import seaborn
%matplotlib inline
learning_rate = 0.01
training_epochs = 50
batch_size = 100
display_step = 1
x = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])
W = tf.Variable(tf.truncated_normal([784, 10]))
b = tf.Variable(tf.truncated_normal([10]))
pred = tf.nn.softmax(tf.matmul(x, W) + b)
cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred), reduction_indices=1))
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
ax1 = plt.subplot(211)
ax1.set_ylabel("Accuracy")
ax2 = plt.subplot(212, sharex=ax1)
ax2.set_ylabel("Cost")
ax2.set_xlabel("Epoch")
plt.setp(ax1.get_xticklabels(), visible=False)
for epoch in range(training_epochs):
avg_cost = 0
total_batch = int(mnist.train.num_examples / batch_size)
for i in range(total_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
_, c = sess.run([optimizer, cost], feed_dict={x: batch_xs, y: batch_ys})
avg_cost += c / total_batch
if (epoch + 1) % display_step == 0:
correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
ax1.plot(epoch+1, accuracy.eval({x: mnist.test.images, y: mnist.test.labels}), 'mo')
ax2.plot(epoch+1, avg_cost, 'co')
print("Epoch:", '%04d' % (epoch+1), "cost=", '{:.9f}'.format(avg_cost), end=' ')
print("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))
print("Optimization Finished!")
print("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))
plt.suptitle("learning rate=%f, training epochs=%i, with tf.truncated_normal()" % (learning_rate, training_epochs), size=14)
plt.savefig('AC8.png', dpi=300)
plt.show()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
通过修改 learning_rate 和 training_epochs来修改学习率和迭代次数,修改
W = tf.Variable(tf.truncated_normal([784, 10]))
b = tf.Variable(tf.truncated_normal([10]))
来修改变量的初始化方式。程序最终会输出损失和准确率随着迭代次数的变化趋势图。
结果
以下结果的背景是:TensorFlow,Logistics Regression,MNIST数据集,很可能换一个数据集下面的结论中的某一条就不成立啦,所以要具体情况具体分析,找到最优的超参数组合。
多次的更改会输出多个不同的图,我们先来看下最终的准确率比较,然后再看下每种情况的详细的损失和准确率变化。
符号说明
lr:Learning Rate,学习率te:Training Epochs,训练迭代次数z:tf.zeros(),变量初始化为0t:tf.truncated_normal(),变量初始化为标准截断正态分布的随机数
最终准确率比较

可以看到
- 学习率为0.1,迭代次数为50次,并且采用随机初始化方式时准确率远远低于其他方式,甚至不足90%。而学习率为0.1,迭代次数为50次,并且采用随机初始化的方式时准确率最高。
- 对于采用随机初始化的方式,在其他参数相同的情况下增大迭代次数会明显的提高准确率。而对于初始化为0的情况则无明显变化。
- 其他参数相同的情况下,过度增大学习率的确是会导致准确率下降的,查看详细变化过程时可以看到准确率变化波动比较大。
- 在学习率适中,迭代次数较大时变量初始化方式对最终准确率的影响不大。
每种情况损失和准确率的详细变化趋势
与上图的顺序保持一致,从上至下。
每张图的标题在图的下面,斜体字。
学习率为1,迭代次数为50,随机初始化
学习率为1,迭代次数为50,初始化为0
学习率为0.1,迭代次数为50,随机初始化
学习率为0.1,迭代次数为50,初始化为0
学习率为0.1,迭代次数为25,随机初始化
学习率为0.1,迭代次数为25,初始化为0
学习率为0.01,迭代次数为50,随机初始化
学习率为0.01,迭代次数为50,初始化为0
大部分情况下准确率和损失的变化时单调的,但是当学习率过大(=1)时准确率开始不稳定