SGD
SGD全称Stochastic Gradient Descent,随机梯度下降,1847年提出。每次选择一个mini-batch,而不是全部样本,使用梯度下降来更新模型参数。它解决了随机小批量样本的问题,但仍然有自适应学习率、容易卡在梯度较小点等问题。
(lr=0.1 epoch=500 batch=32 sgdm momentum=0.1)下的图像
SGDM
在SGD的基础上添加动量参数momentum,相比SGD优势明显,加入动量后,参数更新就可以保持之前更新趋势,而不会卡在当前梯度较小的点了。
Adagrad
它利用迭代次数和累积梯度,对学习率进行自动衰减,2011年提出。从而使得刚开始迭代时,学习率较大,可以快速收敛。而后来则逐渐减小,精调参数,使得模型可以稳定找到最优点。
与SGD的区别在于,学习率除以 前t-1 迭代的梯度的平方和。故称为自适应梯度下降。
Adagrad有个致命问题,就是没有考虑迭代衰减。极端情况,如果刚开始的梯度特别大,而后面的比较小,则学习率基本不会变化了,也就谈不上自适应学习率了。这个问题在RMSProp中得到了修正。
RMSprop
Adam
Adam是SGDM和RMSProp的结合,它基本解决了之前提到的梯度下降的一系列问题,比如随机小样本、自适应学习率、容易卡在梯度较小点等问题。
代码运行上没有遇到太多问题,在绘制图像时使用keras.Callback.History()中返回的数值进行绘制,使用的损失函数为交叉熵损失函数,具体图像如下:
不过感觉epoch=500的情况下训练时间相当长(GPU加速有装,但可能没成功调用?这一块有待研究)
分析数据,Rmsprop算法一定程度上出现了过拟合的问题,Rmsprop的测试集loss曲线几乎一直在保持上升态势;
而Adam算法得到的训练效果并不好,准确率仅有约66%,而且测试集的loss相当高。
总体而言,对于minst数据集,sgd、sgdm、adagrad优化器的优化效果是不错的。
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
| import tensorflow as tf import tensorflow.keras from tensorflow.keras import optimizers import matplotlib.pyplot as plt import datetime import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
mnist = tf.keras.datasets.mnist (x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(10, activation='softmax') ])
model.compile(optimizer=optimizers.Adam(learning_rate=0.1), loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), metrics=['sparse_categorical_accuracy']) start = datetime.datetime.now() hist = model.fit(x_train, y_train, batch_size=32, epochs=500, validation_data=(x_test, y_test), validation_freq=1) end = datetime.datetime.now()
print('time:'+str(end-start))
model.summary()
plt.figure()
acc = hist.history['sparse_categorical_accuracy'] val_acc = hist.history['val_sparse_categorical_accuracy'] loss = hist.history['loss'] val_loss = hist.history['val_loss']
epochs = range(len(loss))
plt.plot(epochs, acc, label='Training acc') plt.plot(epochs, val_acc, label='Validation acc') plt.title('Training and validation accuracy') plt.legend()
plt.figure()
plt.plot(epochs, loss, label='Training loss') plt.plot(epochs, val_loss, label='Validation loss') plt.title('Training and validation loss') plt.legend()
plt.show()
|