在机器学习领域,不同的学习策略对于模型的训练效果有着显著的影响。本文将探讨随机梯度下降(SGD)和Adam这两种优化算法在不同数据集上的表现。由于时间限制,选择了几个小型数据集进行实验,这些数据集可能更适合使用L-BFGS算法。然而,这些例子中展示的总体趋势似乎也适用于更大的数据集。值得注意的是,这些结果可能高度依赖于初始学习率的值。
在Iris数据集上,采用了不同的学习策略进行训练,并记录了训练集的得分和损失。以下是各种策略的详细表现:
使用恒定学习率训练时,训练集得分为0.980000,训练集损失为0.096950。当引入动量时,训练集得分保持不变,但损失降低至0.049530。使用Nesterov动量时,训练集得分和损失与引入动量时相似。采用逆向缩放学习率时,训练集得分显著下降至0.360000,训练集损失增加至0.978444。结合动量和Nesterov动量时,训练集得分提高,损失也有所降低。最后,使用Adam优化器时,训练集得分达到0.980000,训练集损失进一步降低至0.045311。
在Digits数据集上,同样采用了多种学习策略。使用恒定学习率时,训练集得分为0.956038,训练集损失为0.243802。引入动量后,训练集得分提升至0.992766,训练集损失显著降低至0.041297。使用Nesterov动量时,训练集得分和损失与引入动量时相似。逆向缩放学习率导致训练集得分下降至0.638843,训练集损失增加至1.855465。结合动量和Nesterov动量时,训练集得分和损失有所改善。使用Adam优化器时,训练集得分为0.991653,训练集损失降低至0.045934。
Circles数据集上,使用恒定学习率训练时,训练集得分为0.840000,训练集损失为0.601052。引入动量后,训练集得分提升至0.940000,训练集损失降低至0.157334。使用Nesterov动量时,训练集得分和损失与引入动量时相似。逆向缩放学习率导致训练集得分下降至0.500000,训练集损失增加至0.692470。结合动量和Nesterov动量时,训练集得分保持不变,损失略有降低。使用Adam优化器时,训练集得分为0.940000,训练集损失降低至0.150527。
在Moons数据集上,使用恒定学习率训练时,训练集得分为0.850000,训练集损失为0.341523。引入动量后,训练集得分保持不变,但训练集损失略有降低至0.336188。使用Nesterov动量时,训练集得分和损失与引入动量时相似。逆向缩放学习率导致训练集得分下降至0.500000,训练集损失增加至0.689015。结合动量和Nesterov动量时,训练集得分提升至0.830000,训练集损失降低至0.512595。使用Adam优化器时,训练集得分为0.930000,训练集损失降低至0.170087。
以下是使用Python和scikit-learn库实现上述学习策略对比的代码示例。代码中导入了必要的库,并定义了不同的学习率计划和动量参数,然后对每个数据集进行了训练,并绘制了学习曲线。
import warnings
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.exceptions import ConvergenceWarning
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import MinMaxScaler
# 不同的学习率计划和动量参数
params = [
{"solver": "sgd", "learning_rate": "constant", "momentum": 0, "learning_rate_init": 0.2},
{"solver": "sgd", "learning_rate": "constant", "momentum": 0.9, "nesterovs_momentum": False, "learning_rate_init": 0.2},
{"solver": "sgd", "learning_rate": "constant", "momentum": 0.9, "nesterovs_momentum": True, "learning_rate_init": 0.2},
{"solver": "sgd", "learning_rate": "invscaling", "momentum": 0, "learning_rate_init": 0.2},
{"solver": "sgd", "learning_rate": "invscaling", "momentum": 0.9, "nesterovs_momentum": False, "learning_rate_init": 0.2},
{"solver": "sgd", "learning_rate": "invscaling", "momentum": 0.9, "nesterovs_momentum": True, "learning_rate_init": 0.2},
{"solver": "adam", "learning_rate_init": 0.01},
]
labels = [
"constant learning-rate",
"constant with momentum",
"constant with Nesterov's momentum",
"inv-scaling learning-rate",
"inv-scaling with momentum",
"inv-scaling with Nesterov's momentum",
"adam",
]
plot_args = [
{"c": "red", "linestyle": "-"},
{"c": "green", "linestyle": "-"},
{"c": "blue", "linestyle": "-"},
{"c": "red", "linestyle": "--"},
{"c": "green", "linestyle": "--"},
{"c": "blue", "linestyle": "--"},
{"c": "black", "linestyle": "-"},
]
def plot_on_dataset(X, y, ax, name):
# 对每个数据集,绘制每种学习策略的学习曲线
print("\nlearning on dataset %s" % name)
ax.set_title(name)
X = MinMaxScaler().fit_transform(X)
mlps = []
if name == "digits":
# digits数据集较大,但收敛速度相当快
max_iter = 15
else:
max_iter = 400
for label, param in zip(labels, params):
print("training: %s" % label)
mlp = MLPClassifier(random_state=0, max_iter=max_iter, **param)
# 一些参数组合可能不会收敛,这可以在图表中看到,因此这里忽略了它们
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ConvergenceWarning, module="sklearn")
mlp.fit(X, y)
mlps.append(mlp)
print("Training set score: %f" % mlp.score(X, y))
print("Training set loss: %f" % mlp.loss_)
for mlp, label, args in zip(mlps, labels, plot_args):
ax.plot(mlp.loss_curve_, label=label, **args)
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 加载/生成一些玩具数据集
iris = datasets.load_iris()
X_digits, y_digits = datasets.load_digits(return_X_y=True)
data_sets = [
(iris.data, iris.target),
(X_digits, y_digits),
datasets.make_circles(noise=0.2, factor=0.5, random_state=1),
datasets.make_moons(noise=0.3, random_state=0),
]
for ax, data, name in zip(axes.ravel(), data_sets, ["iris", "digits", "circles", "moons"]):
plot_on_dataset(*data, ax=ax, name=name)
fig.legend(ax.get_lines(), labels, ncol=3, loc="upper center")
plt.show()