Machine-Learning-Mastery-Sklearn-教程-六-

95 阅读1小时+

Machine Learning Mastery Sklearn 教程(六)

原文:Machine Learning Mastery

协议:CC BY-NC-SA 4.0

用于评估 Python 中机器学习算法的度量标准

原文: machinelearningmastery.com/metrics-evaluate-machine-learning-algorithms-python/

您选择用于评估机器学习算法的指标非常重要。

度量的选择会影响如何测量和比较机器学习算法的表现。它们会影响您如何权衡结果中不同特征的重要性以及您选择哪种算法的最终选择。

在本文中,您将了解如何使用 scikit-learn 在 Python 中选择和使用不同的机器学习表现指标。

让我们开始吧。

  • 2017 年 1 月更新:已更新,以反映版本 0.18 中 scikit-learn API 的更改。
  • 更新 Mar / 2018 :添加了备用链接以下载数据集,因为原始图像已被删除。

Metrics To Evaluate Machine Learning Algorithms in Python

用于评估 Python 中的机器学习算法的度量 照片由FerrousBüller拍摄,保留一些权利。

关于秘籍

本文使用 Python 和 scikit-learn 中的小代码秘籍演示了各种不同的机器学习评估指标。

每个秘籍都是独立设计的,因此您可以将其复制并粘贴到项目中并立即使用。

针对分类和回归类型的机器学习问题演示了度量标准。

在每个秘籍中,数据集直接从 UCI 机器学习库下载。

所有秘籍都会评估相同的算法,分类的 逻辑回归和回归问题的线性回归。 10 倍交叉验证测试工具用于演示每个指标,因为这是您将采用不同算法评估指标的最可能情况。

这些秘籍中的一个警告是 cross_val_score 函数用于报告每个秘籍中的表现。它允许使用将要讨论的不同评分指标,但报告所有得分以便可以对它们进行排序升序(最高分是最好的)。

一些评估指标(如均方误差)是自然下降的分数(最小分数最好),因此cross_val_score()函数报告为负数。这一点很重要,因为有些分数会被报告为负数,根据定义,它们永远不会是负数。

您可以在页面上了解更多关于 scikit-learn 支持的机器学习算法表现指标模型评估:量化预测质量

让我们继续评估指标。

分类指标

分类问题可能是最常见的机器学习问题类型,因此有无数的度量标准可用于评估这些问题的预测。

在本节中,我们将介绍如何使用以下指标:

  1. 分类准确率。
  2. 对数损失。
  3. ROC 曲线下面积。
  4. 混乱矩阵。
  5. 分类报告。

1.分类准确率

分类准确度是作为所有预测的比率而作出的正确预测的数量。

这是分类问题最常见的评估指标,也是最被误用的。它实际上只适用于每个类中存在相同数量的观测值(这种情况很少发生)并且所有预测和预测误差同样重要,而事实并非如此。

以下是计算分类准确度的示例。

# Cross Validation Classification Accuracy
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
seed = 7
kfold = model_selection.KFold(n_splits=10, random_state=seed)
model = LogisticRegression()
scoring = 'accuracy'
results = model_selection.cross_val_score(model, X, Y, cv=kfold, scoring=scoring)
print("Accuracy: %.3f (%.3f)") % (results.mean(), results.std())

您可以看到报告的比率。可以通过将该值乘以 100 将其转换为百分比,从而使准确度得分大约为 77%。

Accuracy: 0.770 (0.048)

2.对数损失

对数损失(或 logloss)是用于评估给定类的成员概率的预测的表现度量。

0 和 1 之间的标量概率可以被视为算法预测的置信度的度量。正确或不正确的预测会与预测的置信度成比例地得到奖励或惩罚。

您可以在分类维基百科文章的损失函数中了解更多关于对数的信息。

以下是计算 Pima Indians 糖尿病数据集开始时 逻辑回归预测的 logloss 的示例。

# Cross Validation Classification LogLoss
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
seed = 7
kfold = model_selection.KFold(n_splits=10, random_state=seed)
model = LogisticRegression()
scoring = 'neg_log_loss'
results = model_selection.cross_val_score(model, X, Y, cv=kfold, scoring=scoring)
print("Logloss: %.3f (%.3f)") % (results.mean(), results.std())

较小的 logloss 更好,0 表示完美的 logloss。如上所述,当使用cross_val_score()函数时,度量被反转为上升。

Logloss: -0.493 (0.047)

3. ROC 曲线下的面积

ROC 曲线下面积(或简称 AUC)是二分类问题的表现指标。

AUC 代表模型区分正面和负面类别的能力。面积为 1.0 表示完美地预测所有预测的模型。 0.5 的面积表示随机的模型。 了解更多有关 ROC 的信息

ROC 可以分解为敏感性和特异性。二分类问题实际上是敏感性和特异性之间的权衡。

  • 敏感度是真正的正面率,也称为召回率。它是实际正确预测的正(第一)类的数字实例。
  • 特异性也称为真正的负面率。是负类(第二)类中实际预测的实例数是否正确。

您可以在维基百科页面上了解有关 ROC 的更多信息。

以下示例提供了计算 AUC 的演示。

# Cross Validation Classification ROC AUC
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
seed = 7
kfold = model_selection.KFold(n_splits=10, random_state=seed)
model = LogisticRegression()
scoring = 'roc_auc'
results = model_selection.cross_val_score(model, X, Y, cv=kfold, scoring=scoring)
print("AUC: %.3f (%.3f)") % (results.mean(), results.std())

您可以看到 AUC 相对接近 1 且大于 0.5,这表明预测中有一些技巧。

AUC: 0.824 (0.041)

4.混淆矩阵

混淆矩阵是具有两个或更多类的模型的准确率的便利表示。

该表提供了关于 x 轴的预测和 y 轴上的准确度结果。表格的单元格是机器学习算法所做的预测次数。

例如,机器学习算法可以预测 0 或 1,并且每个预测实际上可以是 0 或 1.对于 0 实际为 0 的预测出现在用于预测= 0 和实际= 0 的单元格中,而对于 0 的预测是 0 实际上 1 出现在单元格中,用于预测= 0 和实际= 1。等等。

您可以在维基百科文章上了解有关混淆矩阵的更多信息。

下面是通过测试集上的模型计算一组预测的混淆矩阵的示例。

# Cross Validation Classification Confusion Matrix
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
test_size = 0.33
seed = 7
X_train, X_test, Y_train, Y_test = model_selection.train_test_split(X, Y, test_size=test_size, random_state=seed)
model = LogisticRegression()
model.fit(X_train, Y_train)
predicted = model.predict(X_test)
matrix = confusion_matrix(Y_test, predicted)
print(matrix)

虽然数组的打印没有标题,但您可以看到大多数预测都落在矩阵的对角线上(这是正确的预测)。

[[141  21]
 [ 41  51]]

5.分类报告

在处理分类问题时,Scikit-learn 确实提供了便利报告,使您可以使用多种方法快速了解模型的准确率。

classification_report()函数显示每个类的精度,召回率,f1 分数和支持。

下面的示例演示了有关二分类问题的报告。

# Cross Validation Classification Report
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
test_size = 0.33
seed = 7
X_train, X_test, Y_train, Y_test = model_selection.train_test_split(X, Y, test_size=test_size, random_state=seed)
model = LogisticRegression()
model.fit(X_train, Y_train)
predicted = model.predict(X_test)
report = classification_report(Y_test, predicted)
print(report)

您可以看到该算法的良好预测和召回。

             precision    recall  f1-score   support

        0.0       0.77      0.87      0.82       162
        1.0       0.71      0.55      0.62        92

avg / total       0.75      0.76      0.75       254

回归指标

在本节中,将回顾 3 个用于评估回归机器学习问题预测的最常用指标:

  1. 平均绝对误差。
  2. 均方误差。
  3. R ^ 2。

1.平均绝对误差

平均绝对误差(或 MAE)是预测值与实际值之间的绝对差值之和。它给出了预测错误的概念。

该度量给出了误差幅度的概念,但不知道方向(例如,过度或低于预测)。

您可以在 Wikipedia 上了解有关平均绝对误差的更多信息。

以下示例演示了计算波士顿房价数据集的平均绝对误差。

# Cross Validation Regression MAE
import pandas
from sklearn import model_selection
from sklearn.linear_model import LinearRegression
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.data"
names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
dataframe = pandas.read_csv(url, delim_whitespace=True, names=names)
array = dataframe.values
X = array[:,0:13]
Y = array[:,13]
seed = 7
kfold = model_selection.KFold(n_splits=10, random_state=seed)
model = LinearRegression()
scoring = 'neg_mean_absolute_error'
results = model_selection.cross_val_score(model, X, Y, cv=kfold, scoring=scoring)
print("MAE: %.3f (%.3f)") % (results.mean(), results.std())

值 0 表示没有错误或完美预测。与 logloss 一样,该指标由cross_val_score()函数反转。

MAE: -4.005 (2.084)

2.均方误差

均方误差(或 MSE)非常类似于平均绝对误差,因为它提供了误差幅度的总体思路。

取均方误差的平方根将单位转换回输出变量的原始单位,对描述和表示有意义。这称为均方根误差(或均方根)。

您可以在维基百科上了解有关均方误差的更多信息。

以下示例提供了计算均方误差的演示。

# Cross Validation Regression MSE
import pandas
from sklearn import model_selection
from sklearn.linear_model import LinearRegression
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.data"
names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
dataframe = pandas.read_csv(url, delim_whitespace=True, names=names)
array = dataframe.values
X = array[:,0:13]
Y = array[:,13]
seed = 7
kfold = model_selection.KFold(n_splits=10, random_state=seed)
model = LinearRegression()
scoring = 'neg_mean_squared_error'
results = model_selection.cross_val_score(model, X, Y, cv=kfold, scoring=scoring)
print("MSE: %.3f (%.3f)") % (results.mean(), results.std())

此度量标准也被反转,因此结果会增加。如果您有兴趣计算 RMSE,请记住在取平方根之前取绝对值。

MSE: -34.705 (45.574)

3. R ^ 2 公制

R ^ 2(或 R Squared)度量提供了一组预测与实际值的拟合优度的指示。在统计文献中,该度量被称为确定系数。

对于不适合和完美贴合,这是 0 到 1 之间的值。

您可以在维基百科上了解更多关于决定系数的文章。

下面的示例提供了计算一组预测的平均 R ^ 2 的演示。

# Cross Validation Regression R²
import pandas
from sklearn import model_selection
from sklearn.linear_model import LinearRegression
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.data"
names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
dataframe = pandas.read_csv(url, delim_whitespace=True, names=names)
array = dataframe.values
X = array[:,0:13]
Y = array[:,13]
seed = 7
kfold = model_selection.KFold(n_splits=10, random_state=seed)
model = LinearRegression()
scoring = 'r2'
results = model_selection.cross_val_score(model, X, Y, cv=kfold, scoring=scoring)
print("R²: %.3f (%.3f)") % (results.mean(), results.std())

您可以看到预测与实际值的拟合度较差,其值接近零且小于 0.5。

R²: 0.203 (0.595)

摘要

在这篇文章中,您发现了可用于评估机器学习算法的指标。

您了解了 3 个分类指标:

  • 准确率。
  • 对数损失。
  • ROC 曲线下面积。

另外 2 种分类预测结果的便捷方法:

  • 混乱矩阵。
  • 分类报告。

和 3 个回归指标:

  • 平均绝对误差。
  • 均方误差。
  • R ^ 2。

您对评估机器学习算法或此帖子的指标有任何疑问吗?在评论中提出您的问题,我会尽力回答。

使用 Python 和 Sklearn 的多核机器学习

原文:machinelearningmastery.com/multi-core-…

机器学习的许多计算成本很高的任务可以通过将工作划分到多个中央处理器内核(称为多核处理)来并行完成。

可以并行执行的常见机器学习任务包括训练模型(如决策树的集合)、使用重采样过程(如 k 折交叉验证)评估模型,以及调整模型超参数(如网格和随机搜索)。

将多核用于常见的机器学习任务可以显著缩短执行时间,这是系统可用内核数量的一个因素。一台普通的笔记本电脑和台式电脑可能有 2、4 或 8 个内核。较大的服务器系统可能有 32 个、64 个或更多的可用内核,从而可以在几分钟内完成耗时数小时的机器学习任务。

在本教程中,您将发现如何为多核机器学习配置 Sklearn。

完成本教程后,您将知道:

  • 如何使用多核训练机器学习模型?
  • 如何使机器学习模型的评估并行化?
  • 如何使用多核调整机器学习模型超参数?

我们开始吧。

Multi-Core Machine Learning in Python With Sklearn

带 Scikit 的 Python 多核机器学习-学习 图片由 ER Bauer 提供,保留部分权利。

教程概述

本教程分为五个部分;它们是:

  1. 多核套件-学习
  2. 多核模型训练
  3. 多核模型评估
  4. 多核超参数调整
  5. 推荐

多核套件-学习

机器学习在计算上可能很昂贵。

这种计算成本有三个主要中心;它们是:

  • 训练机器学习模型。
  • 评估机器学习模型。
  • 超参数调整机器学习模型。

更糟糕的是,这些担忧加剧了。

例如,使用像 k 倍交叉验证这样的重采样技术来评估机器学习模型需要多次重复训练过程。

  • 评估需要反复训练

优化模型超参数进一步加剧了这一点,因为它需要对测试的每个超参数组合重复评估程序。

  • 调整需要重复评估

如果不是全部的话,大多数现代计算机都有多核处理器。这包括您的工作站、笔记本电脑以及更大的服务器。

您可以配置您的机器学习模型来利用您的计算机的多个内核,从而大大加快计算开销。

Sklearn Python 机器学习库通过关于关键机器学习任务的 n_jobs 参数提供了这种能力,例如模型训练、模型评估和超参数调整。

此配置参数允许您指定任务要使用的内核数量。默认值为无,将使用单核。您也可以将内核数量指定为整数,例如 1 或 2。最后,您可以指定-1,在这种情况下,任务将使用系统上所有可用的内核。

  • n_jobs :指定用于关键机器学习任务的核心数量。

常见的值有:

  • n_jobs=None :使用单核或您的后端库配置的默认值。
  • n_jobs=4 :使用指定数量的内核,本例中为 4。
  • n_jobs=-1 :使用所有可用的内核。

什么是核心?

一个 CPU 可能有多个物理 CPU 核,本质上就像有多个 CPU 一样。每个内核还可能有超线程,这是一种在许多情况下可以让内核数量翻倍的技术。

例如,我的工作站有四个物理内核,由于超线程,这些物理内核增加了一倍,达到八个。因此,我可以尝试使用 1-8 个内核,或者指定-1 个内核来使用工作站上的所有内核。

现在我们已经熟悉了 Sklearn 库支持机器学习多核并行处理的能力,让我们来看一些例子。

对于本教程中的所有示例,您将获得不同的计时;在评论中分享你的结果。您可能还需要更改内核数量,以匹配系统上的内核数量。

注意:是的,我知道 timeit API,但是在本教程中选择了反对。我们没有剖析代码示例本身;相反,我希望您关注如何以及何时使用 Sklearn 的多核功能,以及它们提供的真正好处。我希望代码示例简洁易读,即使对于初学者也是如此。我将其设置为一个扩展来更新所有示例,以使用 timeit API 并获得更精确的计时。在评论中分享你的结果。

多核模型训练

定义模型时,许多机器学习算法通过 n_jobs 参数支持多核训练。

这不仅会影响模型的训练,还会影响模型在进行预测时的使用。

一个流行的例子是决策树的集合,例如袋装决策树、随机森林和梯度增强。

在本节中,我们将探索使用多核加速训练随机森林分类器模型。我们将在实验中使用综合分类任务。

在这种情况下,我们将定义一个具有 500 棵树的随机森林模型,并使用单个核心来训练该模型。

...
# define the model
model = RandomForestClassifier(n_estimators=500, n_jobs=1)

我们可以使用*时间()功能记录调用列车()*功能前后的时间。然后,我们可以从结束时间中减去开始时间,并以秒为单位报告执行时间。

下面列出了评估使用单核训练随机森林模型的执行时间的完整示例。

# example of timing the training of a random forest model on one core
from time import time
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=500, n_jobs=1)
# record current time
start = time()
# fit the model
model.fit(X, y)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例会报告用单核训练模型所花费的时间。

在这种情况下,我们可以看到大约需要 10 秒钟。

你的系统需要多长时间?在下面的评论中分享你的结果。

10.702 seconds

我们现在可以将示例更改为使用系统上的所有物理内核,在本例中为四个。

...
# define the model
model = RandomForestClassifier(n_estimators=500, n_jobs=4)

下面列出了四核模型多核训练的完整示例。

# example of timing the training of a random forest model on 4 cores
from time import time
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=500, n_jobs=4)
# record current time
start = time()
# fit the model
model.fit(X, y)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例会报告用单核训练模型所花费的时间。

在这种情况下,我们可以看到执行速度减半以上,约为 3.151 秒。

**你的系统需要多长时间?**在下面的评论中分享你的结果。

3.151 seconds

我们现在可以将内核数量更改为八个,以考虑四个物理内核支持的超线程。

...
# define the model
model = RandomForestClassifier(n_estimators=500, n_jobs=8)

我们可以通过将 n_jobs 设置为-1 自动使用所有内核来达到同样的效果;例如:

...
# define the model
model = RandomForestClassifier(n_estimators=500, n_jobs=-1)

目前我们将坚持手动指定内核数量。

下面列出了八核模型多核训练的完整示例。

# example of timing the training of a random forest model on 8 cores
from time import time
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=500, n_jobs=8)
# record current time
start = time()
# fit the model
model.fit(X, y)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例会报告用单核训练模型所花费的时间。

在这种情况下,我们可以看到,通过使用所有内核,我们的执行速度再次从大约 3.151 下降到大约 2.521。

你的系统需要多长时间?在下面的评论中分享你的结果。

2.521 seconds

通过比较 1 和 8 之间的所有值并绘制结果,我们可以使训练期间使用的内核数量和执行速度之间的关系更加具体。

下面列出了完整的示例。

# example of comparing number of cores used during training to execution speed
from time import time
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from matplotlib import pyplot
# define dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
results = list()
# compare timing for number of cores
n_cores = [1, 2, 3, 4, 5, 6, 7, 8]
for n in n_cores:
	# capture current time
	start = time()
	# define the model
	model = RandomForestClassifier(n_estimators=500, n_jobs=n)
	# fit the model
	model.fit(X, y)
	# capture current time
	end = time()
	# store execution time
	result = end - start
	print('>cores=%d: %.3f seconds' % (n, result))
	results.append(result)
pyplot.plot(n_cores, results)
pyplot.show()

运行示例首先报告训练期间使用的每个内核数量的执行速度。

我们可以看到执行速度从一个内核稳步下降到八个内核,尽管在四个物理内核之后,这种显著的优势就停止了。

你的系统需要多长时间?在下面的评论中分享你的结果。

>cores=1: 10.798 seconds
>cores=2: 5.743 seconds
>cores=3: 3.964 seconds
>cores=4: 3.158 seconds
>cores=5: 2.868 seconds
>cores=6: 2.631 seconds
>cores=7: 2.528 seconds
>cores=8: 2.440 seconds

还创建了一个图来显示训练期间使用的内核数量和执行速度之间的关系,表明我们继续看到八个内核的优势。

Line Plot of Number of Cores Used During Training vs. Execution Speed

训练期间使用的内核数量与执行速度的线图

现在我们已经熟悉了机器学习模型多核训练的好处,下面我们来看看多核模型评估。

多核模型评估

模型评估的金标准是 k 倍交叉验证

这是一个重采样过程,需要在数据集的不同分区子集上训练和评估模型 k 次。结果是在对训练期间未使用的数据进行预测时对模型表现的估计,这些数据可用于比较和选择数据集的良好或最佳模型。

此外,多次重复此评估过程也是一种良好的做法,称为重复 k 倍交叉验证。

评估过程可以配置为使用多个核心,其中每个模型训练和评估都在单独的核心上进行。这可以通过在调用 cross_val_score()函数时设置 n_jobs 参数来实现;例如:

我们可以探索多核对模型评估的影响。

首先,让我们使用单个核心来评估模型。

...
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=1)

我们将评估随机森林模型,并在模型的训练中使用单个核心(目前)。

...
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=1)

下面列出了完整的示例。

# example of evaluating a model using a single core
from time import time
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=1)
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# record current time
start = time()
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=1)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例使用三次重复的 10 倍交叉验证来评估模型。

在这种情况下,我们看到模型的评估花费了大约 6.412 秒。

你的系统需要多长时间?在下面的评论中分享你的结果。

6.412 seconds

我们可以更新示例以使用系统的所有八个内核,并期待大幅加速。

...
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=8)

下面列出了完整的示例。

# example of evaluating a model using 8 cores
from time import time
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=1)
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# record current time
start = time()
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=8)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例使用多个内核评估模型。

在这种情况下,我们可以看到执行时间从 6.412 秒下降到大约 2.371 秒,这是一个可喜的加速。

你的系统需要多长时间?在下面的评论中分享你的结果。

2.371 seconds

正如我们在上一节中所做的,我们可以将每个内核数量的执行速度从 1 计时到 8,从而了解这种关系。

下面列出了完整的示例。

# compare execution speed for model evaluation vs number of cpu cores
from time import time
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from matplotlib import pyplot
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
results = list()
# compare timing for number of cores
n_cores = [1, 2, 3, 4, 5, 6, 7, 8]
for n in n_cores:
	# define the model
	model = RandomForestClassifier(n_estimators=100, n_jobs=1)
	# define the evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
	# record the current time
	start = time()
	# evaluate the model
	n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=n)
	# record the current time
	end = time()
	# store execution time
	result = end - start
	print('>cores=%d: %.3f seconds' % (n, result))
	results.append(result)
pyplot.plot(n_cores, results)
pyplot.show()

运行该示例首先报告用于评估模型的每个内核数量的执行时间(以秒为单位)。

我们可以看到,在四个物理内核之上没有显著的改进。

我们在这里也可以看到与之前实验中使用八个内核进行训练时的区别。在这种情况下,评估表现需要 1.492 秒,而独立的情况大约需要 2.371 秒。

这突出了我们使用的评估方法的局限性,我们报告的是单次运行而不是重复运行的表现。将类加载到内存中并执行任何 JIT 优化都需要一些加速时间。

不管我们脆弱的分析的准确性如何,我们确实看到了模型评估熟悉的加速,随着过程中使用的核心的增加。

你的系统需要多长时间?在下面的评论中分享你的结果。

>cores=1: 6.339 seconds
>cores=2: 3.765 seconds
>cores=3: 2.404 seconds
>cores=4: 1.826 seconds
>cores=5: 1.806 seconds
>cores=6: 1.686 seconds
>cores=7: 1.587 seconds
>cores=8: 1.492 seconds

还创建了内核数量和执行速度之间的关系图。

Line Plot of Number of Cores Used During Evaluation vs. Execution Speed

评估期间使用的内核数量与执行速度的线图

我们还可以在模型评估过程中使模型训练过程并行。

虽然这是可能的,但我们应该这样做吗?

为了探索这个问题,让我们首先考虑模型训练使用所有核心,模型评估使用单个核心的情况。

...
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=8)
...
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=1)

下面列出了完整的示例。

# example of using multiple cores for model training but not model evaluation
from time import time
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=8)
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# record current time
start = time()
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=1)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例使用单核评估模型,但是每个训练好的模型使用单核。

在这种情况下,我们可以看到模型评估需要 10 秒以上,比我们使用单个核心进行训练,所有核心进行并行模型评估时的 1 秒或 2 秒要长得多。

你的系统需要多长时间?在下面的评论中分享你的结果。

10.461 seconds

如果我们在培训和评估程序之间划分核心数量,会怎么样?

...
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=4)
...
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=4)

下面列出了完整的示例。

# example of using multiple cores for model training and evaluation
from time import time
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=8)
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=4)
# record current time
start = time()
# evaluate the model
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=4)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例使用四个核心评估模型,每个模型使用四个不同的核心进行训练。

我们可以看到使用所有核心进行训练和使用一个核心进行评估相比有所改进,但至少对于这个数据集上的这个模型,使用所有核心进行模型评估和使用单个核心进行模型训练效率更高。

你的系统需要多长时间?在下面的评论中分享你的结果。

3.434 seconds

多核超参数调整

通常使用网格搜索或随机搜索来调整机器学习模型的超参数。

Sklearn 库分别通过 GridSearchCVRandomizedSearchCV 类提供这些功能。

通过设置 n_jobs 参数,将每个超参数配置分配给一个核心进行评估,这两个搜索过程可以并行进行。

模型评估本身也可以是多核的,正如我们在上一节中看到的,给定评估的模型训练也可以是我们在之前的第二节中看到的训练。因此,潜在多核进程的堆栈开始变得难以配置。

在这个具体的实现中,我们可以使模型训练并行,但是我们无法控制每个模型超参数以及每个模型评估如何多核化。在撰写本文时,文档还不清楚,但我猜想使用单核超参数配置的每个模型评估都会被分成几个作业。

让我们探索使用多核执行模型超参数调整的好处。

首先,让我们使用一个内核来评估随机森林算法的不同配置的网格。

...
# define grid search
search = GridSearchCV(model, grid, n_jobs=1, cv=cv)

下面列出了完整的示例。

# example of tuning model hyperparameters with a single core
from time import time
from sklearn.datasets import make_classification
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=1)
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# define grid
grid = dict()
grid['max_features'] = [1, 2, 3, 4, 5]
# define grid search
search = GridSearchCV(model, grid, n_jobs=1, cv=cv)
# record current time
start = time()
# perform search
search.fit(X, y)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例测试随机森林的 max_features 配置的不同值,其中使用重复的 k 倍交叉验证来评估每个配置。

在这种情况下,单核上的网格搜索大约需要 28.838 秒。

你的系统需要多长时间?在下面的评论中分享你的结果。

28.838 seconds

我们现在可以将网格搜索配置为使用系统上所有可用的内核,在本例中是八个内核。

...
# define grid search
search = GridSearchCV(model, grid, n_jobs=8, cv=cv)

然后,我们可以评估多核网格搜索需要执行多长时间。下面列出了完整的示例。

# example of tuning model hyperparameters with 8 cores
from time import time
from sklearn.datasets import make_classification
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=1)
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# define grid
grid = dict()
grid['max_features'] = [1, 2, 3, 4, 5]
# define grid search
search = GridSearchCV(model, grid, n_jobs=8, cv=cv)
# record current time
start = time()
# perform search
search.fit(X, y)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

运行该示例会报告网格搜索的执行时间。

在这种情况下,我们看到大约四倍的速度从大约 28.838 秒增加到大约 7.418 秒。

你的系统需要多长时间?在下面的评论中分享你的结果。

7.418 seconds

直觉上,我们会认为让网格搜索多核应该是重点,而不是模型训练。

然而,我们可以在模型训练和网格搜索之间划分核心数量,看看它是否为这个数据集上的这个模型提供了好处。

...
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=4)
...
# define grid search
search = GridSearchCV(model, grid, n_jobs=4, cv=cv)

多核模型训练和多核超参数调整的完整示例如下所示。

# example of multi-core model training and hyperparameter tuning
from time import time
from sklearn.datasets import make_classification
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=3)
# define the model
model = RandomForestClassifier(n_estimators=100, n_jobs=4)
# define the evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# define grid
grid = dict()
grid['max_features'] = [1, 2, 3, 4, 5]
# define grid search
search = GridSearchCV(model, grid, n_jobs=4, cv=cv)
# record current time
start = time()
# perform search
search.fit(X, y)
# record current time
end = time()
# report execution time
result = end - start
print('%.3f seconds' % result)

在这种情况下,与单核情况相比,我们确实看到了执行速度的下降,但没有将所有内核分配给网格搜索过程那么多好处。

你的系统需要多长时间?在下面的评论中分享你的结果。

14.148 seconds

推荐

本节列出了使用多核进行机器学习时的一些一般建议。

  • 确认系统上可用的内核数量。
  • 考虑使用具有多个内核的 AWS EC2 实例来获得即时加速。
  • 查看应用编程接口文档,查看您使用的模型是否支持多核培训。
  • 确认多核培训为您的系统带来了可衡量的好处。
  • 当使用 k 倍交叉验证时,最好将核分配给重采样过程,并保留模型训练单核。
  • 在使用超参数调优时,可能更好的做法是使搜索成为多核,而让模型训练和评估成为单核。

你有自己的推荐吗?

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

相关教程

蜜蜂

文章

摘要

在本教程中,您发现了如何为多核机器学习配置 Sklearn。

具体来说,您了解到:

  • 如何使用多核训练机器学习模型?
  • 如何使机器学习模型的评估并行化?
  • 如何使用多核调整机器学习模型超参数?

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

Python 多项式逻辑回归

原文:machinelearningmastery.com/multinomial…

多项式逻辑回归是逻辑回归的扩展,增加了对多类分类问题的原生支持。

默认情况下,逻辑回归仅限于两类分类问题。像 one-vs-rest 这样的一些扩展可以允许逻辑回归用于多类分类问题,尽管它们要求首先将分类问题转化为多个二元分类问题。

相反,多项式逻辑回归算法是逻辑回归模型的扩展,其包括将损失函数改变为交叉熵损失,并将概率分布预测为多项式概率分布,以固有地支持多类分类问题。

在本教程中,您将发现如何在 Python 中开发多项式逻辑回归模型。

完成本教程后,您将知道:

  • 多项式逻辑回归是多分类逻辑回归的扩展。
  • 如何开发和评估多项逻辑回归,并开发一个最终模型,对新数据进行预测。
  • 多项式逻辑回归模型中惩罚超参数的调整。

我们开始吧。

Multinomial Logistic Regression With Python

尼古拉斯·雷纳克拍摄的 Python 多项式逻辑回归 图片,保留部分权利。

教程概述

本教程分为三个部分;它们是:

  1. 多项式逻辑回归
  2. 评估多项式逻辑回归模型
  3. 多项式逻辑回归的调谐惩罚

多项式逻辑回归

逻辑回归是一种分类算法。

它适用于具有数字输入变量和具有两个值或类的分类目标变量的数据集。这类问题被称为二元分类问题。

逻辑回归是为两类问题设计的,使用二项概率分布函数对目标建模。对于积极的类别或结果,类别标签被映射为 1,对于消极的类别或结果,类别标签被映射为 0。拟合模型预测一个例子属于类别 1 的概率。

默认情况下,逻辑回归不能用于具有两个以上类别标签的分类任务,即所谓的多类别分类。

相反,它需要修改以支持多类分类问题。

一种使逻辑回归适应多类分类问题的流行方法是将多类分类问题分成多个二元分类问题,并在每个子问题上拟合标准逻辑回归模型。这种类型的技术包括一对一和一对一包装模型

另一种方法是改变逻辑回归模型,直接支持多类标签的预测。具体来说,就是预测一个输入示例属于每个已知类标签的概率。

定义多类概率的概率分布称为多项式概率分布。适于学习和预测多项式概率分布的逻辑回归模型被称为多项式逻辑回归。同样,我们可以将默认或标准逻辑回归称为二项式逻辑回归。

  • 二项逻辑回归:预测每个输入示例的二项概率(即两类)的标准逻辑回归。
  • 多项式逻辑回归:逻辑回归的修改版本,预测每个输入示例的多项式概率(即两个以上的类)。

如果您不熟悉二项式和多项式概率分布,您可能需要阅读教程:

将逻辑回归从二项式概率更改为多项式概率需要更改用于训练模型的损失函数(例如,将对数损失更改为交叉熵损失),并将输出从单个概率值更改为每个类别标签的一个概率。

现在我们已经熟悉了多项式逻辑回归,让我们看看如何在 Python 中开发和评估多项式逻辑回归模型。

评价多项式逻辑回归模型

在本节中,我们将使用 Sklearn Python 机器学习库开发和评估一个多项式逻辑回归模型。

首先,我们将定义一个合成的多类分类数据集,作为调查的基础。这是一个通用数据集,您可以在以后用自己加载的数据集轻松替换它。

make_classification()函数可用于生成具有给定行数、列数和类数的数据集。在这种情况下,我们将生成一个包含 1,000 行、10 个输入变量或列以及 3 个类的数据集。

下面的示例生成数据集,并总结了数组的形状以及示例在三个类中的分布。

# test classification dataset
from collections import Counter
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, n_classes=3, random_state=1)
# summarize the dataset
print(X.shape, y.shape)
print(Counter(y))

运行该示例确认数据集有 1,000 行和 10 列,正如我们预期的那样,并且这些行在三个类中大致均匀分布,每个类中大约有 334 个示例。

(1000, 10) (1000,)
Counter({1: 334, 2: 334, 0: 332})

Sklearn 库中通过后勤回归类支持逻辑回归。

通过将“ multi_class ”参数设置为“多项式”并将“求解器”参数设置为支持多项式逻辑回归的求解器,如“ lbfgs ”,可以为多项式逻辑回归配置逻辑回归类。

...
# define the multinomial logistic regression model
model = LogisticRegression(multi_class='multinomial', solver='lbfgs')

多项式逻辑回归模型将使用交叉熵损失进行拟合,并将预测每个整数编码类别标签的整数值。

现在我们已经熟悉了多项式逻辑回归应用编程接口,我们可以看看如何在我们的合成多类分类数据集上评估多项式逻辑回归模型。

使用重复分层 k 折交叉验证来评估分类模型是一个很好的做法。分层确保每个交叉验证文件夹在每个类中的示例分布与整个训练数据集大致相同。

我们将使用 10 倍的三个重复,这是一个很好的默认值,并使用分类精确率来评估模型表现,假设类是平衡的。

下面列出了评估多类分类的多项逻辑回归的完整示例。

# evaluate multinomial logistic regression model
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 LogisticRegression
# define dataset
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, n_classes=3, random_state=1)
# define the multinomial logistic regression model
model = LogisticRegression(multi_class='multinomial', solver='lbfgs')
# define the model evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate the model and collect the scores
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
# report the model performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))

运行该示例会报告评估过程中所有折叠和重复的平均分类精确率。

:考虑到算法或评估程序的随机性,或数值精确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,在我们的综合分类数据集上,具有默认惩罚的多项式逻辑回归模型实现了大约 68.1%的平均分类精确率。

Mean Accuracy: 0.681 (0.042)

我们可能会决定使用多项式逻辑回归模型作为我们的最终模型,并对新数据进行预测。

这可以通过首先在所有可用数据上拟合模型,然后调用 predict() 函数对新数据进行预测来实现。

下面的例子演示了如何使用多项式逻辑回归模型对新数据进行预测。

# make a prediction with a multinomial logistic regression model
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
# define dataset
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, n_classes=3, random_state=1)
# define the multinomial logistic regression model
model = LogisticRegression(multi_class='multinomial', solver='lbfgs')
# fit the model on the whole dataset
model.fit(X, y)
# define a single row of input data
row = [1.89149379, -0.39847585, 1.63856893, 0.01647165, 1.51892395, -3.52651223, 1.80998823, 0.58810926, -0.02542177, -0.52835426]
# predict the class label
yhat = model.predict([row])
# summarize the predicted class
print('Predicted Class: %d' % yhat[0])

运行该示例首先在所有可用数据上拟合模型,然后定义一行数据,提供给模型以进行预测。

在这种情况下,我们可以看到模型为单行数据预测了类“1”。

Predicted Class: 1

多项式逻辑回归的一个好处是,它可以预测数据集中所有已知类别标签的校准概率。

这可以通过在模型上调用 predict_proba() 函数来实现。

下面的例子演示了如何使用多项式逻辑回归模型来预测一个新例子的多项式概率分布。

# predict probabilities with a multinomial logistic regression model
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
# define dataset
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=5, n_classes=3, random_state=1)
# define the multinomial logistic regression model
model = LogisticRegression(multi_class='multinomial', solver='lbfgs')
# fit the model on the whole dataset
model.fit(X, y)
# define a single row of input data
row = [1.89149379, -0.39847585, 1.63856893, 0.01647165, 1.51892395, -3.52651223, 1.80998823, 0.58810926, -0.02542177, -0.52835426]
# predict a multinomial probability distribution
yhat = model.predict_proba([row])
# summarize the predicted probabilities
print('Predicted Probabilities: %s' % yhat[0])

运行该示例首先在所有可用数据上拟合模型,然后定义一行数据,提供给模型以预测类概率。

:考虑到算法或评估程序的随机性,或数值精确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到类 1(例如,数组索引被映射到类整数值)具有大约 0.50 的最大预测概率。

Predicted Probabilities: [0.16470456 0.50297138 0.33232406]

现在我们已经熟悉了评估和使用多项式逻辑回归模型,让我们探索如何调整模型超参数。

多项式逻辑回归的调谐惩罚

用于多项式逻辑回归的一个重要超参数是惩罚项。

该术语对模型施加压力,要求其寻求更小的模型权重。这是通过将模型系数的加权和添加到损失函数中来实现的,鼓励模型在拟合模型时减小权重的大小以及误差。

一种流行的惩罚是 L2 惩罚,它将平方系数的(加权)和加到损失函数上。可以使用系数加权,将惩罚的强度从完全惩罚降低到非常轻微的惩罚。

默认情况下,物流配送类使用 L2 惩罚,权重系数设置为 1.0。处罚类型可以通过“处罚”参数设置,值为“ l1 ”、“ l2 ”、“ elasticnet ”(例如两者都有),尽管并非所有解算器都支持所有处罚类型。惩罚中系数的权重可以通过“ C 参数设置。

...
# define the multinomial logistic regression model with a default penalty
LogisticRegression(multi_class='multinomial', solver='lbfgs', penalty='l2', C=1.0)

惩罚的权重实际上是反向权重,也许惩罚= 1–c

从文档中:

C : float,默认值=1.0 正则化强度的倒数;必须是正浮动。像在支持向量机中一样,较小的值指定更强的正则化。

这意味着接近 1.0 的值表示很小的损失,接近 0 的值表示很大的损失。C 值为 1.0 可能表示没有任何惩罚。

  • C 接近 1.0 :轻罚。
  • C 接近 0.0 :强罚。

通过将“惩罚”参数设置为字符串“,可以禁用惩罚。

...
# define the multinomial logistic regression model without a penalty
LogisticRegression(multi_class='multinomial', solver='lbfgs', penalty='none')

现在我们已经熟悉了惩罚,让我们看看我们如何探索不同的惩罚值对多项式逻辑回归模型表现的影响。

通常在对数尺度上测试惩罚值,以便快速发现适合模型的惩罚尺度。一旦找到,在这个尺度上进一步调整可能是有益的。

除了无惩罚或 0.0 之外,我们还将探讨对数标度上加权值在 0.0001 到 1.0 之间的 L2 惩罚。

下面列出了评估多项逻辑回归的 L2 罚值的完整示例。

# tune regularization for multinomial logistic regression
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 LogisticRegression
from matplotlib import pyplot

# get the dataset
def get_dataset():
	X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1, n_classes=3)
	return X, y

# get a list of models to evaluate
def get_models():
	models = dict()
	for p in [0.0, 0.0001, 0.001, 0.01, 0.1, 1.0]:
		# create name for model
		key = '%.4f' % p
		# turn off penalty in some cases
		if p == 0.0:
			# no penalty in this case
			models[key] = LogisticRegression(multi_class='multinomial', solver='lbfgs', penalty='none')
		else:
			models[key] = LogisticRegression(multi_class='multinomial', solver='lbfgs', penalty='l2', C=p)
	return models

# evaluate a give model using cross-validation
def evaluate_model(model, X, y):
	# define the evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
	# evaluate the model
	scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
	return scores

# define dataset
X, y = get_dataset()
# get the models to evaluate
models = get_models()
# evaluate the models and store results
results, names = list(), list()
for name, model in models.items():
	# evaluate the model and collect the scores
	scores = evaluate_model(model, X, y)
	# store the results
	results.append(scores)
	names.append(name)
	# summarize progress along the way
	print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores)))
# plot model performance for comparison
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例会报告沿途每个配置的平均分类精确率。

:考虑到算法或评估程序的随机性,或数值精确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,C 值为 1.0 的最佳分数约为 77.7%,这与不使用达到相同分数的惩罚相同。

>0.0000 0.777 (0.037)
>0.0001 0.683 (0.049)
>0.0010 0.762 (0.044)
>0.0100 0.775 (0.040)
>0.1000 0.774 (0.038)
>1.0000 0.777 (0.037)

为每种配置的准确度分数创建了一个方框图和触须图,所有图都以相同的比例并排显示在图形上,以便直接比较。

在这种情况下,我们可以看到,我们对这个数据集使用的惩罚越大(即 C 值越小),模型的表现就越差。

Box and Whisker Plots of L2 Penalty Configuration vs. Accuracy for Multinomial Logistic Regression

多项逻辑回归的 L2 罚结构与精确度的盒须图

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

相关教程

蜜蜂

文章

摘要

在本教程中,您发现了如何在 Python 中开发多项式逻辑回归模型。

具体来说,您了解到:

  • 多项式逻辑回归是多分类逻辑回归的扩展。
  • 如何开发和评估多项逻辑回归,并开发一个最终模型,对新数据进行预测。
  • 多项式逻辑回归模型中惩罚超参数的调整。

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

Python 中的最近收缩质心

原文:machinelearningmastery.com/nearest-shr…

最近质心是一种线性分类机器学习算法。

它包括根据训练数据集中的基于类的质心预测新示例的类标签。

最近收缩质心算法是一种扩展,它涉及将基于类的质心向整个训练数据集的质心移动,并移除那些在区分类时不太有用的输入变量。

因此,最近收缩质心算法执行自动形式的特征选择,使其适用于具有大量输入变量的数据集。

在本教程中,您将发现最近收缩质心分类机器学习算法。

完成本教程后,您将知道:

  • 最近收缩质心是一种简单的线性机器学习分类算法。
  • 如何使用 Sklearn 的最近收缩质心模型进行拟合、评估和预测。
  • 如何在给定数据集上调整最近收缩质心算法的超参数。

我们开始吧。

Nearest Shrunken Centroids With Python

Giuseppe Milo 拍摄的最近的 Python 缩小质心 照片,保留部分权利。

教程概述

本教程分为三个部分;它们是:

  1. 最近质心算法
  2. 用 Sklearn 最近的质心
  3. 调谐最近质心超参数

最近质心算法

最近质心是一种分类机器学习算法。

该算法首先将训练数据集总结成一组质心(中心),然后使用质心对新的例子进行预测。

对于每个类别,通过取训练集中每个预测器(每个类别)的平均值来找到数据的质心。使用来自所有类别的数据计算总质心。

—第 307 页,应用预测建模,2013 年。

A 质心是数据分布的几何中心,如平均值。在多个维度中,这将是每个维度的平均值,形成每个变量的分布中心点。

最近质心算法假设输入特征空间中的质心对于每个目标标签是不同的。训练数据通过类标签分成组,然后计算每组数据的质心。每个质心只是每个输入变量的平均值。如果有两类,则计算两个质心或点;三个类给出三个质心,以此类推。

质心代表“模型”给定新的示例,例如测试集中的示例或新数据,计算给定数据行与每个质心之间的距离,并使用最近的质心为示例分配类别标签。

距离度量,如欧几里德距离,用于数值数据或汉明距离用于分类数据,在这种情况下,最佳实践是在训练模型之前通过标准化或规范化来缩放输入变量。这是为了确保具有大值的输入变量不会主导距离计算。

分类的最近质心方法的扩展是将每个输入变量的质心向整个训练数据集的质心收缩。那些缩小到数据质心值的变量可以被移除,因为它们无助于区分类别标签。

因此,应用于质心的收缩量是一个超参数,可以针对数据集进行调整,并用于执行自动形式的特征选择。因此,它适用于具有大量输入变量的数据集,其中一些变量可能是不相关的或有噪声的。

因此,最近的收缩质心模型也在模型训练过程中进行特征选择。

—第 307 页,应用预测建模,2013 年。

这种方法被称为“最近的收缩着丝粒”,最早由罗伯特·蒂比什拉尼等人在他们 2002 年发表的题为“通过基因表达的收缩着丝粒诊断多种癌症类型”的论文中描述

用 Sklearn 最近的质心

最近收缩质心可通过最近质心类在 Sklearn Python 机器学习库中获得。

该类允许通过“度量”参数配置算法中使用的距离度量,对于欧几里德距离度量,该参数默认为“欧几里德”。

这可以更改为其他内置指标,如“曼哈顿

...
# create the nearest centroid model
model = NearestCentroid(metric='euclidean')

默认情况下,不使用收缩,但是可以通过“收缩 _ 阈值参数指定收缩,该参数采用 0 到 1 之间的浮点值。

...
# create the nearest centroid model
model = NearestCentroid(metric='euclidean', shrink_threshold=0.5)

我们可以用一个工作示例来演示最近的收缩形心。

首先,让我们定义一个综合分类数据集。

我们将使用 make_classification()函数创建一个包含 1000 个示例的数据集,每个示例有 20 个输入变量。

该示例创建并汇总数据集。

# test classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# summarize the dataset
print(X.shape, y.shape)

运行该示例将创建数据集,并确认数据集的行数和列数。

(1000, 20) (1000,)

我们可以通过重复分层 k 折交叉验证类来拟合和评估最近收缩质心模型。我们将在测试装具中使用 10 次折叠和三次重复。

我们将使用欧几里德距离和无收缩的默认配置。

...
# create the nearest centroid model
model = NearestCentroid()

下面列出了评估合成二进制分类任务的最近收缩质心模型的完整示例。

# evaluate an nearest centroid model on the dataset
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.neighbors import NearestCentroid
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# define model
model = NearestCentroid()
# define model evaluation method
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# evaluate model
scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
# summarize result
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

运行该示例评估合成数据集上的最近收缩质心算法,并报告 10 倍交叉验证的三次重复的平均精确率。

鉴于学习算法的随机性,您的具体结果可能会有所不同。考虑运行这个例子几次。

在这种情况下,我们可以看到模型达到了大约 71%的平均精确率。

Mean Accuracy: 0.711 (0.055)

我们可能会决定使用最近的收缩质心作为最终模型,并根据新数据进行预测。

这可以通过在所有可用数据上拟合模型并调用传递新数据行的 predict() 函数来实现。

我们可以用下面列出的完整示例来演示这一点。

# make a prediction with a nearest centroid model on the dataset
from sklearn.datasets import make_classification
from sklearn.neighbors import NearestCentroid
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# define model
model = NearestCentroid()
# fit model
model.fit(X, y)
# define new data
row = [2.47475454,0.40165523,1.68081787,2.88940715,0.91704519,-3.07950644,4.39961206,0.72464273,-4.86563631,-6.06338084,-1.22209949,-0.4699618,1.01222748,-0.6899355,-0.53000581,6.86966784,-3.27211075,-6.59044146,-2.21290585,-3.139579]
# make a prediction
yhat = model.predict([row])
# summarize prediction
print('Predicted Class: %d' % yhat)

运行该示例符合模型,并对新的数据行进行类别标签预测。

Predicted Class: 0

接下来,我们可以看看配置模型超参数。

调谐最近质心超参数

必须为特定数据集配置最近收缩形心方法的超参数。

也许最重要的超参数是通过“收缩阈值参数控制的收缩。在值网格(如 0.1 或 0.01)上测试 0 到 1 之间的值是一个好主意。

下面的例子使用 GridSearchCV 类和我们定义的值网格来演示这一点。

# grid search shrinkage for nearest centroid
from numpy import arange
from sklearn.datasets import make_classification
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import NearestCentroid
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# define model
model = NearestCentroid()
# define model evaluation method
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# define grid
grid = dict()
grid['shrink_threshold'] = arange(0, 1.01, 0.01)
# define search
search = GridSearchCV(model, grid, scoring='accuracy', cv=cv, n_jobs=-1)
# perform the search
results = search.fit(X, y)
# summarize
print('Mean Accuracy: %.3f' % results.best_score_)
print('Config: %s' % results.best_params_)

运行该示例将使用重复的交叉验证来评估配置的每个组合。

鉴于学习算法的随机性,您的具体结果可能会有所不同。试着运行这个例子几次。

在这种情况下,我们可以看到我们获得了比默认情况下稍好的结果,71.4%对 71.1%。我们可以看到模型分配了一个 0.53 的收缩阈值值。

Mean Accuracy: 0.714
Config: {'shrink_threshold': 0.53}

另一个关键配置是使用的距离度量,可以根据输入变量的分布来选择。

可以使用任何内置的距离测量,如下所列:

常见的距离测量包括:

  • cityblock ','余弦','欧几里德',' l1 ',' l2 ','曼哈顿'

有关如何计算这些距离度量的更多信息,请参见教程:

假设我们的输入变量是数字,我们的数据集只支持“欧几里德”和“曼哈顿

我们可以在网格搜索中包含这些指标;下面列出了完整的示例。

# grid search shrinkage and distance metric for nearest centroid
from numpy import arange
from sklearn.datasets import make_classification
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.neighbors import NearestCentroid
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# define model
model = NearestCentroid()
# define model evaluation method
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# define grid
grid = dict()
grid['shrink_threshold'] = arange(0, 1.01, 0.01)
grid['metric'] = ['euclidean', 'manhattan']
# define search
search = GridSearchCV(model, grid, scoring='accuracy', cv=cv, n_jobs=-1)
# perform the search
results = search.fit(X, y)
# summarize
print('Mean Accuracy: %.3f' % results.best_score_)
print('Config: %s' % results.best_params_)

运行该示例符合模型,并使用交叉验证发现给出最佳结果的超参数。

鉴于学习算法的随机性,您的具体结果可能会有所不同。试着运行这个例子几次。

在这种情况下,我们可以看到,使用无收缩和曼哈顿代替欧几里德距离测量,我们获得了略好的 75%的精确率。

Mean Accuracy: 0.750
Config: {'metric': 'manhattan', 'shrink_threshold': 0.0}

这些实验的一个很好的扩展是将数据规范化或标准化作为建模管道的一部分添加到数据中。

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

教程

报纸

蜜蜂

文章

摘要

在本教程中,您发现了最近收缩质心分类机器学习算法。

具体来说,您了解到:

  • 最近收缩质心是一种简单的线性机器学习分类算法。
  • 如何使用 Sklearn 的最近收缩质心模型进行拟合、评估和预测。
  • 如何在给定数据集上调整最近收缩质心算法的超参数。

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

Python 机器学习的嵌套交叉验证

原文:machinelearningmastery.com/nested-cros…

最后更新于 2021 年 11 月 20 日

k-fold 交叉验证程序用于在对训练期间未使用的数据进行预测时估计机器学习模型的表现。

此过程既可用于优化数据集模型的超参数,也可用于比较和选择数据集模型。当使用相同的交叉验证过程和数据集来调整和选择模型时,很可能导致对模型表现的乐观偏见评估。

克服这种偏差的一种方法是将超参数优化过程嵌套在模型选择过程之下。这被称为双重交叉验证嵌套交叉验证,是评估和比较调整后的机器学习模型的首选方式。

在本教程中,您将发现用于评估调整后的机器学习模型的嵌套交叉验证。

完成本教程后,您将知道:

  • 超参数优化可以对数据集进行过度优化,并提供不应用于模型选择的模型的乐观评估。
  • 嵌套交叉验证提供了一种减少组合超参数调整和模型选择偏差的方法。
  • 如何在 Sklearn 中实现嵌套交叉验证来评估调整后的机器学习算法?

用我的新书Python 机器学习精通启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2021 年 1 月更新:增加了管道思维部分和相关教程的链接。

Nested Cross-Validation for Machine Learning with Python

Python 机器学习的嵌套交叉验证 图片由安德鲁·伯恩提供,保留部分权利。

教程概述

本教程分为三个部分;它们是:

  1. 组合超参数调整和模型选择
  2. 什么是嵌套交叉验证
    1. 嵌套交叉验证的成本是多少?
    2. 你如何设置 k?
    3. 如何配置最终模型?
    4. 内环选择了什么配置?
  3. 使用 Sklearn 进行嵌套交叉验证

组合超参数调整和模型选择

使用 k 折交叉验证在数据集上评估机器学习模型是很常见的。

k 折叠交叉验证过程将有限的数据集分成 k 个不重叠的折叠。k 个折叠中的每一个都有机会用作保留测试集,而所有其他折叠一起用作训练数据集。在 k 个保持测试集上对总共 k 个模型进行拟合和评估,并报告平均表现。

有关 k-fold 交叉验证过程的更多信息,请参见教程:

当对训练期间未使用的数据进行预测时,该过程提供对数据集的模型表现的估计。它比其他一些技术更少偏向,比如针对小到中等大小数据集的单一训练测试分割。k 的常见值有 k=3、k=5 和 k=10。

每个机器学习算法包括一个或多个超参数,这些超参数允许算法行为适合特定的数据集。问题是,关于如何为数据集配置模型超参数,很少有好的启发式方法。相反,优化过程用于发现数据集上表现良好或最好的一组超参数。优化算法的常见示例包括网格搜索和随机搜索,每组不同的模型超参数通常使用 k 倍交叉验证进行评估。

这突出表明,k-fold 交叉验证过程既用于选择模型超参数以配置每个模型,也用于选择已配置的模型。

k-fold 交叉验证程序是评估模型表现的有效方法。然而,该过程的一个限制是,如果它与同一算法一起使用多次,它会导致过拟合。

每次在数据集上评估具有不同模型超参数的模型时,它都会提供关于数据集的信息。具体来说,有噪声的数据集通常得分更低。可以在模型配置过程中利用数据集模型的这些知识来为数据集找到表现最佳的配置。k-fold 交叉验证过程试图减少这种影响,但它不能完全消除,将执行某种形式的爬山或模型超参数到数据集的过度拟合。这是超参数优化的正常情况。

问题是,如果仅使用这个分数来选择模型,或者使用相同的数据集来评估调整后的模型,那么选择过程将会由于这种无意的过度拟合而有所偏差。结果是对模型表现过于乐观的估计,不能推广到新数据。

需要一个过程,允许两个模型为数据集选择表现良好的超参数,并在数据集上配置良好的模型集合中进行选择。

解决这个问题的一种方法叫做嵌套交叉验证

什么是嵌套交叉验证

嵌套交叉验证是一种模型超参数优化和模型选择的方法,试图克服训练数据集过拟合的问题。

为了克服表现评估中的偏差,模型选择应被视为模型拟合程序的一个组成部分,并应在每个试验中独立进行,以防止选择偏差,因为它反映了操作使用中的最佳实践。

——关于模型选择中的过度拟合和绩效评估中的后续选择偏差,2010。

该过程包括将模型超参数优化视为模型本身的一部分,并在更广泛的 k 倍交叉验证过程中对其进行评估,以评估模型进行比较和选择。

因此,模型超参数优化的 k 倍交叉验证程序嵌套在模型选择的 k 倍交叉验证程序中。两个交叉验证循环的使用也导致该程序被称为“T2”双交叉验证

通常,k 折叠交叉验证过程包括在除一个折叠之外的所有折叠上拟合模型,并在保持折叠上评估拟合模型。让我们将用于训练模型的折叠集合称为“训练数据集”,将伸出的折叠称为“测试数据集

然后,每个训练数据集被提供给超参数优化过程,例如网格搜索或随机搜索,其为模型找到最优的超参数集。每组超参数的评估使用 k-fold 交叉验证来执行,该交叉验证将所提供的训练数据集分成 k 个折叠,而不是原始数据集。

这被称为“内部”协议,因为模型选择过程是在重采样过程的每个折叠中独立执行的。

——关于模型选择中的过度拟合和绩效评估中的后续选择偏差,2010。

在此过程中,超参数搜索没有机会对数据集进行过度填充,因为它只暴露给外部交叉验证过程提供的数据集子集。这降低了(如果不是消除的话)搜索过程过度拟合原始数据集的风险,并且应该提供对数据集上的优化模型表现的偏差较小的估计。

以这种方式,表现估计包括适当考虑由模型选择标准的过度拟合引入的误差的组件。

——关于模型选择中的过度拟合和绩效评估中的后续选择偏差,2010。

嵌套交叉验证的成本是多少?

嵌套交叉验证的缺点是执行的模型评估数量急剧增加。

如果 n * k 模型作为给定模型的传统交叉验证超参数搜索的一部分被拟合和评估,那么这将增加到 k * n * k ,因为在嵌套交叉验证的外部循环中,该过程随后对每个折叠执行 k 更多次。

为了使其具体化,您可以使用 k=5 进行超参数搜索,并测试 100 个模型超参数组合。因此,传统的超参数搜索将适合并评估 5 * 100 或 500 型号。外环中带有 k=10 折叠的嵌套交叉验证将适合并评估 5000 个模型。在这种情况下增加了 10 倍。

你如何设置 k?

内环和外环的 k 值应该像您为单个 k 折叠交叉验证程序设置 k 值一样进行设置。

您必须为数据集选择一个 k 值,该值平衡评估过程的计算成本(不要有太多的模型评估)和模型表现的无偏估计。

外环通常使用 k=10 ,内环使用较小的 k 值,如 k=3k=5

有关设置 k 的更多常规帮助,请参见本教程:

如何配置最终模型?

最终的模型使用在外环的一个过程中应用的过程进行配置和拟合,例如外环应用于整个数据集。

如下所示:

  1. 基于算法在嵌套交叉验证外环上的表现来选择算法。
  2. 然后将内部过程应用于整个数据集。
  3. 在最终搜索过程中找到的超参数随后被用于配置最终模型。
  4. 最终模型适合整个数据集。

这个模型可以用来对新数据进行预测。根据最终模型调优过程中提供的分数,我们知道它的平均表现。

内环选择了什么配置?

没关系,这就是全部想法。

使用了自动配置过程,而不是特定配置。只有一个最终模型,但是在最终运行时,通过选择的搜索过程可以找到该最终模型的最佳配置。

您不再需要深入所选的特定模型配置,就像在下一个级别,您不再需要每个交叉验证文件夹中的特定模型系数一样。

这需要思维的转变,并且可能具有挑战性,例如从“我这样配置我的模型… ”转变为“我使用了带有这些约束的自动模型配置过程… ”。

本教程有更多关于管道思维的话题,可能会有所帮助:

现在我们已经熟悉了嵌套交叉验证,让我们回顾一下如何在实践中实现它。

使用 Sklearn 进行嵌套交叉验证

k-fold 交叉验证程序可通过 KFold 类在 Sklearn Python 机器学习库中获得。

该类配置了折叠(拆分)的数量,然后调用 split() 函数,在数据集中传递。枚举 split() 函数的结果,以给出列车的行索引和每个折叠的测试集。

例如:

...
# configure the cross-validation procedure
cv = KFold(n_splits=10, random_state=1)
# perform cross-validation procedure
for train_ix, test_ix in cv_outer.split(X):
	# split data
	X_train, X_test = X[train_ix, :], X[test_ix, :]
	y_train, y_test = y[train_ix], y[test_ix]
	# fit and evaluate a model
	...

此类可用于执行嵌套交叉验证过程的外部循环。

Sklearn 库分别通过随机化搜索 CVGridSearchCV 类提供交叉验证随机搜索和网格搜索超参数优化。通过创建类并指定模型、数据集、要搜索的超参数和交叉验证过程来配置过程。

例如:

...
# configure the cross-validation procedure
cv = KFold(n_splits=3, shuffle=True, random_state=1)
# define search space
space = dict()
...
# define search
search = GridSearchCV(model, space, scoring='accuracy', n_jobs=-1, cv=cv)
# execute search
result = search.fit(X, y)

这些类可用于嵌套交叉验证的内部循环,其中由外部循环定义的训练数据集用作内部循环的数据集。

我们可以将这些元素联系在一起,并实现嵌套的交叉验证过程。

重要的是,我们可以配置超参数搜索,使用搜索过程中找到的最佳超参数,用整个训练数据集重新调整最终模型。这可以通过将“ refit ”参数设置为 True,然后通过搜索结果上的“ best_estimator_ ”属性检索模型来实现。

...
# define search
search = GridSearchCV(model, space, scoring='accuracy', n_jobs=-1, cv=cv_inner, refit=True)
# execute search
result = search.fit(X_train, y_train)
# get the best performing model fit on the whole training set
best_model = result.best_estimator_

然后,该模型可用于对来自外环的保持数据进行预测,并估计模型的表现。

...
# evaluate model on the hold out dataset
yhat = best_model.predict(X_test)

将所有这些联系在一起,我们可以在一个综合分类数据集上演示随机森林分类器的嵌套交叉验证。

我们将保持简单,只调整两个各有三个值的超参数,例如( 3 * 3 ) 9 的组合。我们将在外部交叉验证中使用 10 个折叠,在内部交叉验证中使用 3 个折叠,从而得到( 10 * 9 * 3 )或 270 个模型评估。

下面列出了完整的示例。

# manual nested cross-validation for random forest on a classification dataset
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import KFold
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# create dataset
X, y = make_classification(n_samples=1000, n_features=20, random_state=1, n_informative=10, n_redundant=10)
# configure the cross-validation procedure
cv_outer = KFold(n_splits=10, shuffle=True, random_state=1)
# enumerate splits
outer_results = list()
for train_ix, test_ix in cv_outer.split(X):
	# split data
	X_train, X_test = X[train_ix, :], X[test_ix, :]
	y_train, y_test = y[train_ix], y[test_ix]
	# configure the cross-validation procedure
	cv_inner = KFold(n_splits=3, shuffle=True, random_state=1)
	# define the model
	model = RandomForestClassifier(random_state=1)
	# define search space
	space = dict()
	space['n_estimators'] = [10, 100, 500]
	space['max_features'] = [2, 4, 6]
	# define search
	search = GridSearchCV(model, space, scoring='accuracy', cv=cv_inner, refit=True)
	# execute search
	result = search.fit(X_train, y_train)
	# get the best performing model fit on the whole training set
	best_model = result.best_estimator_
	# evaluate model on the hold out dataset
	yhat = best_model.predict(X_test)
	# evaluate the model
	acc = accuracy_score(y_test, yhat)
	# store the result
	outer_results.append(acc)
	# report progress
	print('>acc=%.3f, est=%.3f, cfg=%s' % (acc, result.best_score_, result.best_params_))
# summarize the estimated performance of the model
print('Accuracy: %.3f (%.3f)' % (mean(outer_results), std(outer_results)))

运行该示例使用合成分类数据集上的嵌套交叉验证来评估随机森林

:考虑到算法或评估程序的随机性,或数值精确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

您可以使用该示例作为起点,并对其进行调整以评估不同的算法超参数、不同的算法或不同的数据集。

外部交叉验证过程的每一次迭代都报告最佳表现模型的估计表现(使用 3 倍交叉验证)和被发现表现最佳的超参数,以及保持数据集的精确率。

这是有见地的,因为我们可以看到,实际和估计的准确性是不同的,但在这种情况下,类似的。我们还可以看到,每次迭代都会发现不同的超参数,这表明这个数据集上的好的超参数取决于数据集的细节。

然后报告最终的平均分类精确率。

>acc=0.900, est=0.932, cfg={'max_features': 4, 'n_estimators': 100}
>acc=0.940, est=0.924, cfg={'max_features': 4, 'n_estimators': 500}
>acc=0.930, est=0.929, cfg={'max_features': 4, 'n_estimators': 500}
>acc=0.930, est=0.927, cfg={'max_features': 6, 'n_estimators': 100}
>acc=0.920, est=0.927, cfg={'max_features': 4, 'n_estimators': 100}
>acc=0.950, est=0.927, cfg={'max_features': 4, 'n_estimators': 500}
>acc=0.910, est=0.918, cfg={'max_features': 2, 'n_estimators': 100}
>acc=0.930, est=0.924, cfg={'max_features': 6, 'n_estimators': 500}
>acc=0.960, est=0.926, cfg={'max_features': 2, 'n_estimators': 500}
>acc=0.900, est=0.937, cfg={'max_features': 4, 'n_estimators': 500}
Accuracy: 0.927 (0.019)

我们可以执行相同程序的一个更简单的方法是使用 cross_val_score()函数,该函数将执行外部交叉验证程序。这可以在已配置的 GridSearchCV 上直接执行,它将从外环自动使用测试集上的改装最佳表现模型。

这大大减少了执行嵌套交叉验证所需的代码量。

下面列出了完整的示例。

# automatic nested cross-validation for random forest on a classification dataset
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 KFold
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
# create dataset
X, y = make_classification(n_samples=1000, n_features=20, random_state=1, n_informative=10, n_redundant=10)
# configure the cross-validation procedure
cv_inner = KFold(n_splits=3, shuffle=True, random_state=1)
# define the model
model = RandomForestClassifier(random_state=1)
# define search space
space = dict()
space['n_estimators'] = [10, 100, 500]
space['max_features'] = [2, 4, 6]
# define search
search = GridSearchCV(model, space, scoring='accuracy', n_jobs=1, cv=cv_inner, refit=True)
# configure the cross-validation procedure
cv_outer = KFold(n_splits=10, shuffle=True, random_state=1)
# execute the nested cross-validation
scores = cross_val_score(search, X, y, scoring='accuracy', cv=cv_outer, n_jobs=-1)
# report performance
print('Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

:考虑到算法或评估程序的随机性,或数值精确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

运行示例在随机森林算法上执行嵌套交叉验证,达到了与我们的手动过程相匹配的平均精确率。

Accuracy: 0.927 (0.019)

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

教程

报纸

蜜蜂

摘要

在本教程中,您发现了用于评估调整后的机器学习模型的嵌套交叉验证。

具体来说,您了解到:

  • 超参数优化可以对数据集进行过度优化,并提供不应用于模型选择的模型的乐观评估。
  • 嵌套交叉验证提供了一种减少组合超参数调整和模型选择偏差的方法。
  • 如何在 Sklearn 中实现嵌套交叉验证来评估调整后的机器学习算法?

你有什么问题吗? 在下面的评论中提问,我会尽力回答。

如何在 Sklearn 中识别过拟合机器学习模型

原文:machinelearningmastery.com/overfitting…

最后更新于 2020 年 11 月 27 日

过拟合是预测模型表现不佳的常见解释。

对学习动态的分析可以帮助识别模型是否过度训练了训练数据集,并且可以建议使用替代配置来获得更好的预测表现。

对于像神经网络这样的增量学习算法来说,对学习动态进行分析是很简单的,但是不太清楚我们如何对其他不增量学习的算法进行同样的分析,例如决策树、k 近邻以及 Sklearn 机器学习库中的其他通用算法。

在本教程中,您将发现如何在 Python 中识别机器学习模型的过拟合。

完成本教程后,您将知道:

  • 过拟合是预测模型泛化表现差的一个可能原因。
  • 可以通过改变关键模型超参数来分析机器学习模型的过拟合。
  • 虽然过拟合是一个有用的分析工具,但它不能与模型选择混淆。

我们开始吧。

Identify Overfitting Machine Learning Models With Sklearn

用 Scikit 识别过度拟合的机器学习模型-学习 图片由邦妮·莫兰提供,保留部分权利。

教程概述

本教程分为五个部分;它们是:

  1. 什么是过度拟合
  2. 如何执行过度拟合分析
  3. Sklearn 中的过度拟合示例
  4. 科学知识学习中过度拟合的反例
  5. 将过拟合分析与模型选择分开

什么是过度拟合

过拟合指的是用于预测建模的机器学习算法的有害行为。

在这种情况下,模型在训练数据集上的表现得到了提高,但代价是在训练期间看不到的数据(如保持测试数据集或新数据)上的表现更差。

我们可以通过首先在训练数据集上评估模型,然后在保持测试数据集上评估相同的模型,来识别机器学习模型是否过度。

如果模型在训练数据集上的表现明显优于在测试数据集上的表现,则模型可能过度填充了训练数据集。

我们关心过拟合,因为这是模型“T0”泛化能力差的常见原因,用高“泛化误差来衡量。”这是模型在对新数据进行预测时产生的误差。

这意味着,如果我们的模型表现不佳,可能是因为它过度了。

但是,如果一个模型在训练集上的表现比测试集上的表现“T0”明显更好,这意味着什么呢?

例如,模型在训练集上比在测试集上有更好的表现是常见的,也可能是正常的。

因此,我们可以对数据集执行算法分析,以更好地揭示过拟合行为。

如何执行过度拟合分析

过拟合分析是一种探索特定模型如何以及何时对特定数据集进行过拟合的方法。

它是一个工具,可以帮助您了解更多关于机器学习模型的学习动态。

这可以通过在单次运行过程中检查模型行为来实现,例如逐步适应训练数据集的神经网络算法。

在训练过程中,可以在每个点计算模型在列车和测试集上的表现图,并创建图。该图通常称为学习曲线图,显示了训练集上模型表现的一条曲线和每次学习增量的测试集的一条曲线。

如果您想了解有关增量学习算法的学习曲线的更多信息,请参阅教程:

在学习曲线图上可以看到过度拟合的常见模式,其中训练数据集上的模型表现持续改善(例如,损失或误差持续下降或精确率持续上升),测试或验证集上的表现改善到一定程度,然后开始变差。

如果观察到这种模式,那么训练应该停止在增量学习算法的测试或验证集表现变差的地方

这对于像神经网络那样增量学习的算法是有意义的,但是其他算法呢?

  • 如何在 Sklearn 中对机器学习算法进行过拟合分析?

一种对不增量学习的算法执行过拟合分析的方法是通过改变关键模型超参数并评估每个配置的训练和测试集上的模型表现。

为了说明这一点,让我们在下一节探讨一个分析过拟合模型的案例。

Sklearn 中的过度拟合示例

在本节中,我们将看一个将机器学习模型过度拟合到训练数据集的例子。

首先,让我们定义一个综合分类数据集。

我们将使用 make_classification()函数定义一个包含 10,000 个示例(行)和 20 个输入特征(列)的二进制(两类)分类预测问题。

下面的示例创建数据集并总结输入和输出组件的形状。

# synthetic classification dataset
from sklearn.datasets import make_classification
# define dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=5, n_redundant=15, random_state=1)
# summarize the dataset
print(X.shape, y.shape)

运行该示例会创建数据集并报告形状,这证实了我们的预期。

(10000, 20) (10000,)

接下来,我们需要将数据集分割成训练和测试子集。

我们将使用 train_test_split()函数,将数据分成 70%用于训练模型,30%用于评估模型。

# split a dataset into train and test sets
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# create dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=5, n_redundant=15, random_state=1)
# split into train test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# summarize the shape of the train and test sets
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

运行该示例会分割数据集,我们可以确认我们有 7000 个示例用于训练,3000 个示例用于评估模型。

(7000, 20) (3000, 20) (7000,) (3000,)

接下来,我们可以探索一种超拟合训练数据集的机器学习模型。

我们将通过决策树分类器使用决策树,并用“最大深度参数测试不同的树深度。

浅层决策树(例如,几个级别)通常不会过度拟合,但表现较差(高偏差、低方差)。而深树(例如,许多级别)通常会过度填充并具有良好的表现(低偏差、高方差)。理想的树不是浅到技能低,也不是深到覆盖训练数据集。

我们评估决策树深度从 1 到 20。

...
# define the tree depths to evaluate
values = [i for i in range(1, 21)]

我们将枚举每个树的深度,在训练数据集上用给定的深度拟合一棵树,然后在训练集和测试集上评估该树。

预期随着树的深度增加,训练和测试的表现将提高到一定程度,随着树变得太深,它将开始过度填充训练数据集,代价是保持测试集的表现变差。

...
# evaluate a decision tree for each depth
for i in values:
	# configure the model
	model = DecisionTreeClassifier(max_depth=i)
	# fit model on the training dataset
	model.fit(X_train, y_train)
	# evaluate on the train dataset
	train_yhat = model.predict(X_train)
	train_acc = accuracy_score(y_train, train_yhat)
	train_scores.append(train_acc)
	# evaluate on the test dataset
	test_yhat = model.predict(X_test)
	test_acc = accuracy_score(y_test, test_yhat)
	test_scores.append(test_acc)
	# summarize progress
	print('>%d, train: %.3f, test: %.3f' % (i, train_acc, test_acc))

在运行结束时,我们将在列车和测试集上绘制所有模型准确度分数,以便进行视觉比较。

...
# plot of train and test scores vs tree depth
pyplot.plot(values, train_scores, '-o', label='Train')
pyplot.plot(values, test_scores, '-o', label='Test')
pyplot.legend()
pyplot.show()

综上所述,下面列出了在合成二进制分类数据集上探索不同树深度的完整示例。

# evaluate decision tree performance on train and test sets with different tree depths
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier
from matplotlib import pyplot
# create dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=5, n_redundant=15, random_state=1)
# split into train test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# define lists to collect scores
train_scores, test_scores = list(), list()
# define the tree depths to evaluate
values = [i for i in range(1, 21)]
# evaluate a decision tree for each depth
for i in values:
	# configure the model
	model = DecisionTreeClassifier(max_depth=i)
	# fit model on the training dataset
	model.fit(X_train, y_train)
	# evaluate on the train dataset
	train_yhat = model.predict(X_train)
	train_acc = accuracy_score(y_train, train_yhat)
	train_scores.append(train_acc)
	# evaluate on the test dataset
	test_yhat = model.predict(X_test)
	test_acc = accuracy_score(y_test, test_yhat)
	test_scores.append(test_acc)
	# summarize progress
	print('>%d, train: %.3f, test: %.3f' % (i, train_acc, test_acc))
# plot of train and test scores vs tree depth
pyplot.plot(values, train_scores, '-o', label='Train')
pyplot.plot(values, test_scores, '-o', label='Test')
pyplot.legend()
pyplot.show()

运行该示例适合并评估列车上的决策树和每个树深度的测试集,并报告准确性分数。

:考虑到算法或评估程序的随机性,或数值精确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到一种趋势,即随着树的深度达到 19-20 层深度附近的一个点,训练数据集的精确率会提高,在这个点上树与训练数据集完全匹配。

我们还可以看到,测试集上的准确性随着树的深度而提高,直到大约八到九个级别的深度,之后准确性随着树深度的每次增加而开始变差。

这正是我们期望在过度拟合模式中看到的。

在模型开始过度填充训练数据集之前,我们会选择 8 或 9 的树深度。

>1, train: 0.769, test: 0.761
>2, train: 0.808, test: 0.804
>3, train: 0.879, test: 0.878
>4, train: 0.902, test: 0.896
>5, train: 0.915, test: 0.903
>6, train: 0.929, test: 0.918
>7, train: 0.942, test: 0.921
>8, train: 0.951, test: 0.924
>9, train: 0.959, test: 0.926
>10, train: 0.968, test: 0.923
>11, train: 0.977, test: 0.925
>12, train: 0.983, test: 0.925
>13, train: 0.987, test: 0.926
>14, train: 0.992, test: 0.921
>15, train: 0.995, test: 0.920
>16, train: 0.997, test: 0.913
>17, train: 0.999, test: 0.918
>18, train: 0.999, test: 0.918
>19, train: 1.000, test: 0.914
>20, train: 1.000, test: 0.913

还创建了一个图形,显示了列车上模型精确率的线图和具有不同树深的测试集。

该图清楚地表明,在早期阶段增加树的深度会导致训练集和测试集的相应改进。

这种情况一直持续到大约 10 个级别的深度,之后该模型被显示为过度填充训练数据集,代价是保持数据集的表现更差。

Line Plot of Decision Tree Accuracy on Train and Test Datasets for Different Tree Depths

不同树深的训练和测试数据集上决策树精确率的线图

这个分析很有意思。它显示了为什么当“ max_depth ”设置为大值时,模型的保持测试集表现更差。

但这不是必需的。

我们可以使用网格搜索轻松选择“ max_depth ”,而无需分析为什么有些值会导致更好的表现,而有些值会导致更差的表现。

事实上,在下一节中,我们将展示这种分析在哪些地方会产生误导。

科学知识学习中过度拟合的反例

有时,我们可能会对机器学习模型行为进行分析,并被结果所欺骗。

一个很好的例子是改变 k 近邻算法的邻居数量,我们可以使用 KNeighborsClassifier 类实现,并通过“n _ neights参数进行配置。

让我们暂时忘记 KNN 是如何工作的。

我们可以对 KNN 算法执行与上一节中对决策树所做的分析相同的分析,并查看我们的模型对于不同的配置值是否过度。在这种情况下,我们将改变邻居的数量,从 1 到 50,以获得更多的效果。

下面列出了完整的示例。

# evaluate knn performance on train and test sets with different numbers of neighbors
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.neighbors import KNeighborsClassifier
from matplotlib import pyplot
# create dataset
X, y = make_classification(n_samples=10000, n_features=20, n_informative=5, n_redundant=15, random_state=1)
# split into train test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# define lists to collect scores
train_scores, test_scores = list(), list()
# define the tree depths to evaluate
values = [i for i in range(1, 51)]
# evaluate a decision tree for each depth
for i in values:
	# configure the model
	model = KNeighborsClassifier(n_neighbors=i)
	# fit model on the training dataset
	model.fit(X_train, y_train)
	# evaluate on the train dataset
	train_yhat = model.predict(X_train)
	train_acc = accuracy_score(y_train, train_yhat)
	train_scores.append(train_acc)
	# evaluate on the test dataset
	test_yhat = model.predict(X_test)
	test_acc = accuracy_score(y_test, test_yhat)
	test_scores.append(test_acc)
	# summarize progress
	print('>%d, train: %.3f, test: %.3f' % (i, train_acc, test_acc))
# plot of train and test scores vs number of neighbors
pyplot.plot(values, train_scores, '-o', label='Train')
pyplot.plot(values, test_scores, '-o', label='Test')
pyplot.legend()
pyplot.show()

运行该示例适合并评估列车上的 KNN 模型和每个邻居的测试集,并报告准确性分数。

:考虑到算法或评估程序的随机性,或数值精确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

回想一下,我们正在寻找一种模式,在这种模式下,测试集的表现会提高,然后开始变得更差,而训练集的表现会继续提高。

我们看不到这种模式。

相反,我们看到训练数据集的精确率从完美的精确率开始,几乎随着邻居数量的每一次增加而下降。

我们还看到,模型在保持测试中的表现提高到大约五个邻居的值,保持水平,并在此之后开始下降趋势。

>1, train: 1.000, test: 0.919
>2, train: 0.965, test: 0.916
>3, train: 0.962, test: 0.932
>4, train: 0.957, test: 0.932
>5, train: 0.954, test: 0.935
>6, train: 0.953, test: 0.934
>7, train: 0.952, test: 0.932
>8, train: 0.951, test: 0.933
>9, train: 0.949, test: 0.933
>10, train: 0.950, test: 0.935
>11, train: 0.947, test: 0.934
>12, train: 0.947, test: 0.933
>13, train: 0.945, test: 0.932
>14, train: 0.945, test: 0.932
>15, train: 0.944, test: 0.932
>16, train: 0.944, test: 0.934
>17, train: 0.943, test: 0.932
>18, train: 0.943, test: 0.935
>19, train: 0.942, test: 0.933
>20, train: 0.943, test: 0.935
>21, train: 0.942, test: 0.933
>22, train: 0.943, test: 0.933
>23, train: 0.941, test: 0.932
>24, train: 0.942, test: 0.932
>25, train: 0.942, test: 0.931
>26, train: 0.941, test: 0.930
>27, train: 0.941, test: 0.932
>28, train: 0.939, test: 0.932
>29, train: 0.938, test: 0.931
>30, train: 0.938, test: 0.931
>31, train: 0.937, test: 0.931
>32, train: 0.938, test: 0.931
>33, train: 0.937, test: 0.930
>34, train: 0.938, test: 0.931
>35, train: 0.937, test: 0.930
>36, train: 0.937, test: 0.928
>37, train: 0.936, test: 0.930
>38, train: 0.937, test: 0.930
>39, train: 0.935, test: 0.929
>40, train: 0.936, test: 0.929
>41, train: 0.936, test: 0.928
>42, train: 0.936, test: 0.929
>43, train: 0.936, test: 0.930
>44, train: 0.935, test: 0.929
>45, train: 0.935, test: 0.929
>46, train: 0.934, test: 0.929
>47, train: 0.935, test: 0.929
>48, train: 0.934, test: 0.929
>49, train: 0.934, test: 0.929
>50, train: 0.934, test: 0.929

还创建了一个图形,显示了列车上模型精确率的线图和具有不同邻居数量的测试集。

情节使情况变得更清楚了。看起来训练集的线图正在下降以与测试集的线收敛。事实上,这正是正在发生的事情。

Line Plot of KNN Accuracy on Train and Test Datasets for Different Numbers of Neighbors

不同邻居数的训练和测试数据集上 KNN 精确率的线图

现在,回想一下 KNN 是如何工作的。

模型”实际上只是存储在高效数据结构中的整个训练数据集。训练数据集中“模型”的技能应该是 100%,任何低于这个的都是不可原谅的。

事实上,这一论点适用于任何机器学习算法,并切中了初学者过度拟合的核心困惑。

将过拟合分析与模型选择分开

过度拟合可能是预测模型表现不佳的一个原因。

创建显示模型在训练和测试数据集上的学习动态的学习曲线是一种有助于学习更多关于数据集上的模型的分析。

但过拟合不应与模型选择混淆。

我们根据其样本外表现选择预测模型或模型配置。也就是说,它在训练中没有看到的新数据上的表现。

我们这样做的原因是,在预测建模中,我们主要对能够做出巧妙预测的模型感兴趣。我们希望这个模型能够在给定时间和计算资源的情况下做出最好的预测。

这可能意味着我们选择一个看起来已经覆盖了训练数据集的模型。在这种情况下,过度分析可能会产生误导。

这也可能意味着模型在训练数据集上的表现很差或很糟糕。

一般来说,如果我们在模型选择中关心模型在训练数据集上的表现,那么我们将期望模型在训练数据集上具有完美的表现。这是我们现有的数据;我们不应该容忍任何不足。

正如我们在上面的 KNN 示例中看到的那样,我们可以通过直接存储训练集并使用一个邻居返回预测来实现训练集的完美表现,但代价是任何新数据的表现都很差。

  • 在训练数据集和测试数据集上都表现良好的模型不是更好的模型吗?

也许吧。但是,也许不是。

这个论点是基于这样的想法,即在训练集和测试集上都表现良好的模型对潜在问题有更好的理解。

一个推论是,在测试集上表现良好但在训练集上表现不佳的模型是幸运的(例如统计侥幸),而在训练集上表现良好但在测试集上表现不佳的模型是过度匹配的。

我相信这是初学者的症结所在,他们经常问如何为他们的 Sklearn 机器学习模型修复过度拟合。

令人担心的是,模型必须在列车和测试集上都表现良好,否则,它们就有麻烦了。

情况并非如此

训练集的表现与模型选择无关。只有在选择预测模型时,您才必须关注样本外表现。

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

教程

蜜蜂

文章

摘要

在本教程中,您发现了如何在 Python 中识别机器学习模型的过拟合。

具体来说,您了解到:

  • 过拟合是预测模型泛化表现差的一个可能原因。
  • 可以通过改变关键模型超参数来分析机器学习模型的过拟合。
  • 虽然过拟合是一个有用的分析工具,但它不能与模型选择混淆。

你有什么问题吗? 在下面的评论中提问,我会尽力回答。