机器学习中级教程 5.交叉验证

机器学习中级教程

在本教程中,您将学习如何使用交叉验证来更好地衡量模型性能。

正文

介绍

机器学习是一个迭代过程。

您将面临关于使用什么预测变量、使用什么类型的模型、为这些模型提供什么参数等方面的选择。到目前为止,您已经以数据驱动的方式通过使用验证集(或保持集)测量模型质量来做出这些选择。

但这种方法也有一些缺点。要看到这一点,假设您有一个包含5000行的数据集。通常,您将保留大约20%的数据作为验证数据集,或1000行。但这给确定模型分数留下了一些随机机会。也就是说,一个模型可能在一组1000行上表现良好,即使它在另一组1000行上不准确。

在极端情况下,您可以想象验证集中只有一行数据。如果你比较不同的模型,哪一个能在单个数据点上做出最好的预测将主要取决于运气!

一般来说,验证集越大,模型质量度量中的随机性(也称为“噪声”)就越小,也就越可靠。不幸的是,我们只能通过从训练数据中删除行来获得大的验证集,而较小的训练数据集意味着更糟糕的模型!

什么是交叉验证?

在交叉验证中,我们在不同的数据子集上运行建模过程,以获得模型质量的多个度量。
例如,我们可以首先将数据分成5个部分,每个部分占整个数据集的20%。在这种情况下,我们说我们已经将数据分成5个“折叠”。
cv
然后,我们对每个折叠进行一个实验:

  • 实验1中,我们使用第一个折叠作为验证集(或保持集),其他所有内容作为训练数据。这为我们提供了一个基于20%保持集的模型质量度量。
  • 实验2中,我们从第二个折叠中拿出数据(并使用除第二个折叠外的所有东西来训练模型)。然后使用保持集对模型质量进行第二次估计。
  • 我们重复这个过程,每折叠一次作为保持集。综上所述,在某一点上,100%的数据被用作保持数据,我们最终得到了基于数据集中所有行的模型质量度量(即使我们不同时使用所有行)。

什么时候应该使用交叉验证?

交叉验证为模型质量提供了更准确的度量,如果您正在做出大量建模决策,这一点尤其重要。然而,它可能需要更长的运行时间,因为它估计了多个模型(每个折叠一个)。

那么,考虑到这些权衡,您应该在什么时候使用每种方法?

  • 对于小型数据集,如果额外的计算负担不是什么大问题,则应该运行交叉验证。
  • 对于较大的数据集,单个验证集就足够了。您的代码将运行得更快,并且您可能有足够的数据,因此几乎不需要将其中的一些数据重新用于保持。

对于大数据集和小数据集的构成,没有简单的界限。但是,如果你的模型只需要几分钟或更少的时间就可以运行,那么切换到交叉验证可能是值得的。
或者,你可以进行交叉验证,看看每个实验的分数是否接近。如果每个实验产生相同的结果,一个单一的验证集可能就足够了。

举例

我们将使用与上一个教程中相同的数据。我们在X中加载输入数据,在y中加载输出数据。

import pandas as pd

# Read the data
data = pd.read_csv('../input/melbourne-housing-snapshot/melb_data.csv')

# Select subset of predictors
cols_to_use = ['Rooms', 'Distance', 'Landsize', 'BuildingArea', 'YearBuilt']
X = data[cols_to_use]

# Select target
y = data.Price

然后,我们定义了一个管道,它使用一个插补器来填充缺失值,并使用一个随机森林模型来进行预测。
虽然可以在没有管道的情况下进行交叉验证,但这相当困难!使用管道将使代码非常简单。

from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer

my_pipeline = Pipeline(steps=[('preprocessor', SimpleImputer()),
                              ('model', RandomForestRegressor(n_estimators=50,
                                                              random_state=0))
                             ])

我们使用scikit-learn中的cross_val_score()函数获得交叉验证分数。我们使用cv参数设置折叠的数量。

from sklearn.model_selection import cross_val_score

# Multiply by -1 since sklearn calculates *negative* MAE
scores = -1 * cross_val_score(my_pipeline, X, y,
                              cv=5,
                              scoring='neg_mean_absolute_error')

print("MAE scores:\n", scores)

MAE scores:
[301628.7893587 303164.4782723 287298.331666 236061.84754543
260383.45111427]

评分参数选择要报告的模型质量度量:在这种情况下,我们选择负平均绝对误差(MAE)。scikit-learn的文档显示了一个选项列表
我们指定MAE有点奇怪。Scikit-learn 有一个约定,其中定义了所有指标,因此高数字更好。在这里使用否定词可以让它们与传统保持一致,尽管否定词在其他地方几乎闻所未闻。
我们通常需要一个模型质量的单一度量来比较替代模型。所以我们取实验的平均值。

print("Average MAE score (across experiments):")
print(scores.mean())

Average MAE score (across experiments):
277707.3795913405

结论

使用交叉验证可以更好地衡量模型质量,还可以清理代码:请注意,我们不再需要跟踪单独的训练集和验证集。因此,特别是对于小型数据集,这是一个很好的改进!

轮到你了

在下一个练习中运用你的新技能!


练习部分

在本练习中,您将利用所学知识调整具有交叉验证的机器学习模型。

设置

下面的问题将为你的工作提供反馈。运行以下单元格设置反馈系统。

# Set up code checking
import os
if not os.path.exists("../input/train.csv"):
    os.symlink("../input/home-data-for-ml-course/train.csv", "../input/train.csv")  
    os.symlink("../input/home-data-for-ml-course/test.csv", "../input/test.csv") 
from learntools.core import binder
binder.bind(globals())
from learntools.ml_intermediate.ex5 import *
print("Setup Complete")

Setup Complete

您将使用来自 Housing Prices Competition for Kaggle Learn Users 案例.

banner

在不做任何更改的情况下运行以下代码单元,以加载X_train、X_valid、y_train和y_valid中的训练集和验证集。测试集在X_test中加载。

import pandas as pd
from sklearn.model_selection import train_test_split

# Read the data
train_data = pd.read_csv('../input/train.csv', index_col='Id')
test_data = pd.read_csv('../input/test.csv', index_col='Id')

# Remove rows with missing target, separate target from predictors
train_data.dropna(axis=0, subset=['SalePrice'], inplace=True)
y = train_data.SalePrice              
train_data.drop(['SalePrice'], axis=1, inplace=True)

# Select numeric columns only
numeric_cols = [cname for cname in train_data.columns if train_data[cname].dtype in ['int64', 'float64']]
X = train_data[numeric_cols].copy()
X_test = test_data[numeric_cols].copy()

使用下一个代码单元打印数据的前几行。

X_train.head()

到目前为止,您已经学会了如何使用scikit-learn构建管道。例如,下面的管道将使用SimpleImputer()替换数据中缺失的值,然后使用RandomForestRegressionor()训练随机森林模型进行预测。我们使用n_estimators参数设置随机森林模型中的树数,设置random_state确保可重复性。

from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer

my_pipeline = Pipeline(steps=[
    ('preprocessor', SimpleImputer()),
    ('model', RandomForestRegressor(n_estimators=50, random_state=0))
])

您还学习了如何在交叉验证中使用管道。下面的代码使用cross_val_score()函数来获得平均绝对误差(MAE),它在五个不同的折叠中取平均值。回想一下,我们用cv参数设置了折叠次数。

from sklearn.model_selection import cross_val_score

# Multiply by -1 since sklearn calculates *negative* MAE
scores = -1 * cross_val_score(my_pipeline, X, y,
                              cv=5,
                              scoring='neg_mean_absolute_error')

print("Average MAE score:", scores.mean())

Average MAE score: 18276.410356164386

第1步:编写一个有用的函数

在本练习中,您将使用交叉验证为机器学习模型选择参数。
首先编写一个函数get_score(),该函数报告机器学习管道的平均(超过三次交叉验证)MAE,该管道使用:

  • Xy中的数据用于创建褶皱,
  • SimpleImputer()所有参数保留为默认值)以替换缺少的值,以及
  • RandomForestRegressor()(使用random_state=0)来拟合随机森林模型。

在设置随机森林模型中的树数时,使用n_estimators参数提供给get_score()。

def get_score(n_estimators):
    """Return the average MAE over 3 CV folds of random forest model.
    
    Keyword argument:
    n_estimators -- the number of trees in the forest
    """
    # Replace this body with your own code
    pass    

# Check your answer
step_1.check()

第2步:测试不同的参数值

现在,您将使用在步骤1中定义的函数来评估与随机林中树数的八个不同值相对应的模型性能:50、100、150、。。。,300, 350, 400.
将结果存储在Python 字典 results 中,其中results[i]get_score(i)返回的平均MAE。

results = ____ # Your code here

# Check your answer
step_2.check()

注意,运行 以上代码 需要一些时间

使用下一个单元格可视化第2步的结果。运行代码,不做任何更改。

import matplotlib.pyplot as plt
%matplotlib inline

plt.plot(list(results.keys()), list(results.values()))
plt.show()

plot

第3步:找到最佳参数值

考虑到结果,对于随机森林模型,哪个n_estimators似乎最适合?使用你的答案来设置n_estimators的最佳值。

n_estimators_best = ____

# Check your answer
step_3.check()

在本练习中,您探讨了在机器学习模型中选择适当参数的一种方法。
如果您想了解更多关于超参数优化的信息,建议您从网格搜索开始,这是一种确定机器学习模型参数最佳组合的简单方法。谢天谢地,scikit-learn还包含一个内置函数GridSearchCV(),它可以使网格搜索代码非常高效!

继续前进

继续学习梯度增强,这是一种强大的技术,可以在各种数据集上获得最优秀的结果。

答案

### step 1 
def get_score(n_estimators):
    my_pipeline = Pipeline(steps=[
        ('preprocessor', SimpleImputer()),
        ('model', RandomForestRegressor(n_estimators, random_state=0))
    ])
    scores = -1 * cross_val_score(my_pipeline, X, y,
                                  cv=3,
                                  scoring='neg_mean_absolute_error')
    return scores.mean()

# step 2
results = {}
for i in range(1,9):
    results[50*i] = get_score(50*i)

# step 3
n_estimators_best = min(results, key=results.get)
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值