感知器是一种用于二元分类任务的线性机器学习算法。
它可以被认为是最早、最简单的人工神经网络类型之一。它绝对不是“深度”学习,但它是一个重要的构建块。
与逻辑回归类似,它可以在特征空间中为二类分类任务快速学习线性分离,尽管与逻辑回归不同,它使用随机梯度下降优化算法进行学习,并且不预测校准的概率。
在本教程中,您将了解感知器分类机器学习算法。
完成本教程后,您将了解:
- 感知器分类器是一种线性算法,可应用于二元分类任务。
- 如何使用 Scikit-Learn 拟合、评估和预测感知器模型。
- 如何在给定的数据集上调整感知器算法的超参数。
让我们开始吧。

用于 Python 分类的感知器算法
照片作者:Belinda Novika,部分权利保留。
教程概述
本教程分为 3 部分;它们是:
- 感知器算法
- 使用 Scikit-Learn 的感知器
- 调整感知器超参数
感知器算法
感知器算法是一种二元(二分类)分类机器学习算法。
它是一种神经网络模型,可能是最简单的神经网络模型。
它由一个节点或神经元组成,该节点接收一行数据作为输入并预测一个类标签。这是通过计算输入的加权总和以及偏差(设置为 1)来实现的。模型输入的加权总和称为激活。
- 激活 = 权重 * 输入 + 偏差
如果激活值大于 0.0,则模型将输出 1.0;否则,它将输出 0.0。
- 预测 1:如果激活 > 0.0
- 预测 0:如果激活 <= 0.0
鉴于输入与模型系数相乘,就像线性回归和逻辑回归一样,在使用模型之前对数据进行归一化或标准化是一个好习惯。
感知器是一种线性分类算法。这意味着它使用特征空间中的一条线(称为超平面)来学习分隔两个类的决策边界。因此,它适用于那些可以通过直线或线性模型很好地分离类的问v题,这被称为线性可分。
模型的系数被称为输入权重,并使用随机梯度下降优化算法进行训练。
训练数据集的样本逐一展示给模型,模型进行预测,并计算误差。然后更新模型的权重以减少样本的误差。这被称为感知器更新规则。此过程对训练数据集中的所有样本重复,称为一个周期。然后此使用样本更新模型的过程重复多个周期。
模型权重通过每批的少量误差进行更新,比例由一个称为学习率的超参数控制,通常设置为一个较小的值。这是为了确保学习不会过快发生,从而导致模型技能可能较低,这被称为模型权重的优化(搜索)过程过早收敛。
- 权重(t + 1) = 权重(t) + 学习率 * (预期_i – 预测_) * 输入_i
当模型产生的误差降低到较低水平或不再改进时,或者完成了最大数量的周期时,训练停止。
模型权重的初始值设置为小的随机值。此外,在每个训练周期之前都会对训练数据集进行洗牌。这是为了加速和改进模型训练过程。因此,学习算法是随机的,每次运行时可能获得不同的结果。因此,通过重复评估和报告平均分类准确率来总结算法在数据集上的性能是一个好习惯。
学习率和训练周期数是算法的超参数,可以使用启发式方法或超参数调整来设置。
有关感知器算法的更多信息,请参阅教程:
现在我们熟悉了感知器算法,让我们来探讨如何在 Python 中使用该算法。
使用 Scikit-Learn 的感知器
感知器算法在 scikit-learn Python 机器学习库中通过 Perceptron 类提供。
该类允许您配置学习率(eta0),其默认值为 1.0。
1 2 3 |
... # 定义模型 model = Perceptron(eta0=1.0) |
该实现还允许您配置训练周期的总数(max_iter),其默认值为 1,000。
1 2 3 |
... # 定义模型 model = Perceptron(max_iter=1000) |
scikit-learn 感知器算法的实现还提供了其他您可能想探索的配置选项,例如提前停止和使用惩罚损失。
我们可以通过一个实际示例来演示感知器分类器。
首先,让我们定义一个合成分类数据集。
我们将使用 make_classification() 函数创建一个具有 1,000 个示例的数据集,每个示例有 20 个输入变量。
该示例创建并总结了数据集。
1 2 3 4 5 6 |
# 测试分类数据集 from sklearn.datasets import make_classification # 定义数据集 X, y = make_classification(n_samples=1000, n_features=10, n_informative=10, n_redundant=0, random_state=1) # 汇总数据集 print(X.shape, y.shape) |
运行示例创建数据集并确认数据集的行数和列数。
1 |
(1000, 10) (1000,) |
我们可以使用 RepeatedStratifiedKFold 类通过重复分层 k 折交叉验证来拟合和评估感知器模型。我们将在测试框架中使用 10 折和 3 次重复。
我们将使用默认配置。
1 2 3 |
... # 创建模型 model = Perceptron() |
下面列出了用于合成二元分类任务的感知器模型评估的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 在数据集上评估感知器模型 from numpy import mean from numpy import std from sklearn.datasets import make_classification from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.linear_model import Perceptron # 定义数据集 X, y = make_classification(n_samples=1000, n_features=10, n_informative=10, n_redundant=0, random_state=1) # 定义模型 model = Perceptron() # 定义模型评估方法 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 评估模型 scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # 总结结果 print('平均准确率: %.3f (%.3f)' % (mean(scores), std(scores))) |
运行示例后,将感知器算法在合成数据集上进行评估,并报告三次重复的 10 折交叉验证的平均准确率。
鉴于学习算法的随机性,您的具体结果可能会有所不同。可以尝试运行几次示例。
在这种情况下,我们可以看到模型达到了大约 84.7% 的平均准确率。
1 |
平均准确率:0.847 (0.052) |
我们可以决定使用感知器分类器作为我们的最终模型,并对新数据进行预测。
这可以通过在所有可用数据上拟合模型管道并调用 predict() 函数,将新行数据传入来实现。
我们可以在下面列出的完整示例中演示这一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 在数据集上使用感知器模型进行预测 from sklearn.datasets import make_classification from sklearn.linear_model import Perceptron # 定义数据集 X, y = make_classification(n_samples=1000, n_features=10, n_informative=10, n_redundant=0, random_state=1) # 定义模型 model = Perceptron() # 拟合模型 model.fit(X, y) # 定义新数据 row = [0.12777556,-3.64400522,-2.23268854,-1.82114386,1.75466361,0.1243966,1.03397657,2.35822076,1.01001752,0.56768485] # 进行预测 yhat = model.predict([row]) # 总结预测 print('预测类别:%d' % yhat) |
运行示例后,模型将被拟合,并对新数据行进行类别标签预测。
1 |
预测类别:1 |
接下来,我们可以看看如何配置模型超参数。
调整感知器超参数
感知器算法的超参数必须根据您的特定数据集进行配置。
也许最重要的超参数是学习率。
较高的学习率可能导致模型学习速度快,但可能会牺牲性能。较低的学习率可能导致模型性能更好,但可能需要很长时间来训练模型。
您可以在教程中了解有关探索学习率的更多信息:
通常在 1e-4(或更小)到 1.0 之间以对数尺度测试学习率。在这种情况下,我们将测试以下值:
1 2 3 4 |
... # 定义网格 grid = dict() grid['eta0'] = [0.0001, 0.001, 0.01, 0.1, 1.0] |
下面的示例使用我们定义的网格值的 GridSearchCV 类来演示这一点。
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 |
# 对感知器进行学习率网格搜索 from sklearn.datasets import make_classification from sklearn.model_selection import GridSearchCV from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.linear_model import Perceptron # 定义数据集 X, y = make_classification(n_samples=1000, n_features=10, n_informative=10, n_redundant=0, random_state=1) # 定义模型 model = Perceptron() # 定义模型评估方法 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义网格 grid = dict() grid['eta0'] = [0.0001, 0.001, 0.01, 0.1, 1.0] # 定义搜索 search = GridSearchCV(model, grid, scoring='accuracy', cv=cv, n_jobs=-1) # 执行搜索 results = search.fit(X, y) # 总结 print('平均准确率: %.3f' % results.best_score_) print('配置: %s' % results.best_params_) # 总结所有结果 means = results.cv_results_['mean_test_score'] params = results.cv_results_['params'] for mean, param in zip(means, params): print(">%.3f 配合: %r" % (mean, param)) |
运行示例将使用重复交叉验证评估每种配置组合。
鉴于学习算法的随机性,您的具体结果可能会有所不同。尝试运行几次示例。
在这种情况下,我们可以看到比默认值更小的学习率可以提高性能,学习率为 0.0001 和 0.001 都可以达到大约 85.7% 的分类准确率,而默认值 1.0 的准确率约为 84.7%。
1 2 3 4 5 6 7 |
平均准确率: 0.857 配置: {'eta0': 0.0001} >0.857 配合: {'eta0': 0.0001} >0.857 配合: {'eta0': 0.001} >0.853 配合: {'eta0': 0.01} >0.847 配合: {'eta0': 0.1} >0.847 配合: {'eta0': 1.0} |
另一个重要的超参数是用于训练模型的周期数。
这可能取决于训练数据集,并且可能差异很大。同样,我们将以对数尺度探索 1 到 1e+4 之间的配置值。
1 2 3 4 |
... # 定义网格 grid = dict() grid['max_iter'] = [1, 10, 100, 1000, 10000] |
我们将使用在上一个搜索中找到的性能良好的学习率 0.0001。
1 2 3 |
... # 定义模型 model = Perceptron(eta0=0.0001) |
下面列出了用于网格搜索训练周期数的完整示例。
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 |
# 对感知器进行总周期网格搜索 from sklearn.datasets import make_classification from sklearn.model_selection import GridSearchCV from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.linear_model import Perceptron # 定义数据集 X, y = make_classification(n_samples=1000, n_features=10, n_informative=10, n_redundant=0, random_state=1) # 定义模型 model = Perceptron(eta0=0.0001) # 定义模型评估方法 cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) # 定义网格 grid = dict() grid['max_iter'] = [1, 10, 100, 1000, 10000] # 定义搜索 search = GridSearchCV(model, grid, scoring='accuracy', cv=cv, n_jobs=-1) # 执行搜索 results = search.fit(X, y) # 总结 print('平均准确率: %.3f' % results.best_score_) print('配置: %s' % results.best_params_) # 总结所有结果 means = results.cv_results_['mean_test_score'] params = results.cv_results_['params'] for mean, param in zip(means, params): print(">%.3f 配合: %r" % (mean, param)) |
运行示例将使用重复交叉验证评估每种配置组合。
鉴于学习算法的随机性,您的具体结果可能会有所不同。尝试运行几次示例。
在这种情况下,我们可以看到周期 10 到 10,000 的分类准确率大致相同。一个有趣的例外是同时探索配置学习率和训练周期数,看看是否可以获得更好的结果。
1 2 3 4 5 6 7 |
平均准确率: 0.857 配置: {'max_iter': 10} >0.850 配合: {'max_iter': 1} >0.857 配合: {'max_iter': 10} >0.857 配合: {'max_iter': 100} >0.857 配合: {'max_iter': 1000} >0.857 配合: {'max_iter': 10000} |
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
教程
书籍
- 《用于模式识别的神经网络》, 1995.
- 模式识别与机器学习, 2006.
- 人工智能:现代方法,第三版,2015。
API
文章
总结
在本教程中,您了解了感知器分类机器学习算法。
具体来说,你学到了:
- 感知器分类器是一种线性算法,可应用于二元分类任务。
- 如何使用 Scikit-Learn 拟合、评估和预测感知器模型。
- 如何在给定的数据集上调整感知器算法的超参数。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
如果这是感知器权重更新的规则,那么 Adaline 和感知器的权重更新有什么区别吗?
你好 yogita…以下资源可能对您有帮助:
https://medium.com/mlearning-ai/understanding-adaline-da79ab8bbc5a