1.17. 神经网络模型(监督学习)#
警告
此实现不适用于大规模应用。特别是,scikit-learn 不提供 GPU 支持。对于更快的基于 GPU 的实现,以及提供更多灵活性构建深度学习架构的框架,请参阅 相关项目.
1.17.1. 多层感知器#
多层感知器 (MLP) 是一种监督学习算法,它通过在数据集上训练来学习一个函数

图 1:单隐藏层 MLP。#
最左边的层,称为输入层,由一组神经元
该模块包含公共属性 coefs_
和 intercepts_
。 coefs_
是权重矩阵列表,其中索引为 intercepts_
是偏差向量列表,其中索引为
1.17.2. 分类#
类 MLPClassifier
实现了一种多层感知器 (MLP) 算法,该算法使用 反向传播 进行训练。
MLP 在两个数组上进行训练:大小为 (n_samples, n_features) 的数组 X,它保存表示为浮点特征向量的训练样本;以及大小为 (n_samples,) 的数组 y,它保存训练样本的目标值(类别标签)。
>>> from sklearn.neural_network import MLPClassifier
>>> X = [[0., 0.], [1., 1.]]
>>> y = [0, 1]
>>> clf = MLPClassifier(solver='lbfgs', alpha=1e-5,
... hidden_layer_sizes=(5, 2), random_state=1)
...
>>> clf.fit(X, y)
MLPClassifier(alpha=1e-05, hidden_layer_sizes=(5, 2), random_state=1,
solver='lbfgs')
拟合(训练)后,模型可以预测新样本的标签。
>>> clf.predict([[2., 2.], [-1., -2.]])
array([1, 0])
MLP 可以将非线性模型拟合到训练数据。 clf.coefs_
包含构成模型参数的权重矩阵。
>>> [coef.shape for coef in clf.coefs_]
[(2, 5), (5, 2), (2, 1)]
目前,MLPClassifier
仅支持交叉熵损失函数,该函数允许通过运行 predict_proba
方法来进行概率估计。
MLP 使用反向传播进行训练。更准确地说,它使用某种形式的梯度下降进行训练,并且使用反向传播计算梯度。对于分类,它最小化交叉熵损失函数,为每个样本
>>> clf.predict_proba([[2., 2.], [1., 2.]])
array([[1.967...e-04, 9.998...-01],
[1.967...e-04, 9.998...-01]])
MLPClassifier
通过应用 Softmax 作为输出函数来支持多类分类。
此外,该模型支持 多标签分类,其中一个样本可以属于多个类别。对于每个类别,原始输出通过逻辑函数。大于或等于 0.5
的值将四舍五入为 1
,否则为 0
。对于样本的预测输出,值为 1
的索引表示该样本的分配类别。
>>> X = [[0., 0.], [1., 1.]]
>>> y = [[0, 1], [1, 1]]
>>> clf = MLPClassifier(solver='lbfgs', alpha=1e-5,
... hidden_layer_sizes=(15,), random_state=1)
...
>>> clf.fit(X, y)
MLPClassifier(alpha=1e-05, hidden_layer_sizes=(15,), random_state=1,
solver='lbfgs')
>>> clf.predict([[1., 2.]])
array([[1, 1]])
>>> clf.predict([[0., 0.]])
array([[0, 1]])
有关更多信息,请参阅以下示例和 MLPClassifier.fit
的文档字符串。
示例
请参阅 MNIST 上 MLP 权重的可视化,以可视化表示训练后的权重。
1.17.3. 回归#
类 MLPRegressor
实现了一种多层感知器 (MLP),它使用反向传播进行训练,在输出层没有激活函数,也可以看作使用恒等函数作为激活函数。因此,它使用平方误差作为损失函数,输出是一组连续值。
MLPRegressor
还支持多输出回归,其中一个样本可以有多个目标。
1.17.4. 正则化#
两者 MLPRegressor
和 MLPClassifier
使用参数 alpha
用于正则化(L2 正则化)项,该项有助于通过惩罚具有较大幅度的权重来避免过拟合。以下图显示了不同 alpha 值下的不同决策函数。

有关更多信息,请参阅以下示例。
示例
1.17.5. 算法#
MLP 使用 随机梯度下降、Adam 或 L-BFGS 进行训练。随机梯度下降 (SGD) 使用损失函数相对于需要调整的参数的梯度来更新参数,即
其中
更多详细信息可以在 SGD 的文档中找到。
Adam 与 SGD 类似,因为它是一种随机优化器,但它可以根据低阶矩的自适应估计自动调整更新参数的量。
使用 SGD 或 Adam,训练支持在线和小型批次学习。
L-BFGS 是一种求解器,它近似于 Hessian 矩阵,Hessian 矩阵表示函数的二阶偏导数。此外,它近似于 Hessian 矩阵的逆来执行参数更新。该实现使用 Scipy 版本的 L-BFGS。
如果选择的求解器是“L-BFGS”,则训练不支持在线或小型批次学习。
1.17.6. 复杂度#
假设有
数学公式#
给定一组训练样本
对于二元分类,
如果存在两个以上的类别,
其中
在回归中,输出保持为
MLP 使用不同的损失函数,具体取决于问题类型。分类的损失函数是平均交叉熵,在二元情况下表示为:
其中
对于回归,MLP 使用均方误差损失函数;表示为:
从初始随机权重开始,多层感知器 (MLP) 通过反复更新这些权重来最小化损失函数。在计算损失后,反向传播将损失从输出层传播到之前的层,为每个权重参数提供一个更新值,旨在降低损失。
在梯度下降中,计算损失相对于权重的梯度
其中
当算法达到预设的最大迭代次数时停止;或者当损失的改善低于某个较小的数字时停止。
1.17.7. 实践使用技巧#
多层感知器对特征缩放很敏感,因此强烈建议对数据进行缩放。例如,将输入向量 X 上的每个属性缩放到 [0, 1] 或 [-1, +1],或者将其标准化为均值为 0,方差为 1。请注意,您必须对测试集应用相同的缩放,才能获得有意义的结果。您可以使用
StandardScaler
进行标准化。>>> from sklearn.preprocessing import StandardScaler >>> scaler = StandardScaler() >>> # Don't cheat - fit only on training data >>> scaler.fit(X_train) >>> X_train = scaler.transform(X_train) >>> # apply same transformation to test data >>> X_test = scaler.transform(X_test)
另一种推荐的方法是在
Pipeline
中使用StandardScaler
找到合理的正则化参数
最好使用GridSearchCV
,通常在10.0 ** -np.arange(1, 7)
范围内。根据经验,我们观察到
L-BFGS
在小型数据集上收敛速度更快,并且具有更好的解决方案。然而,对于相对较大的数据集,Adam
非常稳健。它通常收敛速度很快,并且性能相当好。另一方面,带有动量或 Nesterov 动量的SGD
如果学习率调整正确,可以比这两个算法表现得更好。
1.17.8. 使用 warm_start 获得更多控制#
如果您想对 SGD 中的停止条件或学习率进行更多控制,或者想进行额外的监控,使用 warm_start=True
和 max_iter=1
并自行迭代可能会有所帮助。
>>> X = [[0., 0.], [1., 1.]]
>>> y = [0, 1]
>>> clf = MLPClassifier(hidden_layer_sizes=(15,), random_state=1, max_iter=1, warm_start=True)
>>> for i in range(10):
... clf.fit(X, y)
... # additional monitoring / inspection
MLPClassifier(...
参考文献#
“通过反向传播误差学习表示。” Rumelhart, David E.,Geoffrey E. Hinton 和 Ronald J. Williams。
“随机梯度下降” L. Bottou - 网站,2010 年。
“反向传播” Andrew Ng,Jiquan Ngiam,Chuan Yu Foo,Yifan Mai,Caroline Suen - 网站,2011 年。
“高效反向传播” Y. LeCun,L. Bottou,G. Orr,K. Müller - 在神经网络:技巧与窍门 1998 年。
“Adam:一种随机优化方法。” Kingma,Diederik 和 Jimmy Ba (2014)