5折交叉验证_Python中训练集/测试集的分割和交叉验证

138871c5244d93818808731dfe01e91c.png

嗨,大家好!在上一篇关于Python线性回归的文章之后,我认为撰写关于切分训练集/测试集和交叉验证的文章是很自然的,和往常一样,我将对该主题进行简短概述,然后给出在Python中实现该示例的示例。这是数据科学和数据分析中两个相当重要的概念,并用作防止(或最小化)过度拟合的工具。我将解释这是什么—当我们使用统计模型(例如,线性回归)时,我们通常将模型拟合到训练集上,以便对未经训练的数据(常规数据)进行预测 )。过度拟合意味着我们对模型的拟合程度过高。我保证,这一切很快就会变得有意义。

1.什么是模型的过拟合/欠拟合?

如前所述,在统计和机器学习中,我们通常将数据分为两个子集:训练数据和测试数据(有时分为三个子集:训练,验证和测试),并在训练数据上拟合我们的模型,以便对测试数据做预测。当我们这样做时,可能会发生两件事之一:我们过度拟合我们的模型或我们欠拟合我们的模型。我们不希望发生这些事情,因为它们会影响我们模型的可预测性-我们可能使用的是准确性较低和/或未概括的模型(这意味着您无法对其他数据进行概括)。让我们看看欠拟合和过度拟合的实际含义:

1.1 过拟合

过度拟合意味着我们训练的模型训练得“太好了”,也就是说太适合训练数据集了。这通常在模型过于复杂时发生(即与观察数量相比,特征/变量太多)。该模型在训练数据上将非常准确,但是在未训练或新数据上可能会非常不准确。这是因为此模型未通用化,当发生这种情况时,模型将学习或描述训练数据中的“噪声”,而不是数据中变量之间的实际关系。显然,这种噪声不是任何新数据集的一部分,也无法对其应用。

1.2 欠拟合

与过度拟合相反,当模型拟合不足时,这意味着该模型不适合训练数据,因此会错过数据中的趋势。这也意味着该模型无法推广到新数据。您可能已经猜到,这通常是一个非常简单的模型(没有足够的预测变量/独立变量)导致的。例如,当我们将线性模型(如线性回归)拟合到非线性数据时,也会发生这种情况。不用说,该模型的预测能力很差(在训练数据上,不能推广到其他数据)。

b1a2e0433b485329a819393591adafca.png

   欠拟合,“恰到好处”,过拟合的实例

值得注意的是,拟合不足不如拟合过度普遍。 但是,我们希望避免在数据分析中同时遇到这两个问题。 您可能会说我们正在尝试寻找模型不足和过度拟合之间的中间点。 正如您将看到的,训练/测试拆分和交叉验证有助于避免过度拟合而不是过度拟合。 让我们一起来研究它们!

2.训练/测试拆分

正如我之前所说,我们使用的数据通常分为训练数据和测试数据。 训练集包含一个已知的输出,并且模型在此数据上学习,以便稍后将其推广到其他数据。 我们具有测试数据集(或子集),以测试我们对该子集的模型预测。

d68df43d3723d30c8bcdf2f675fbb0e9.png

让我们看看如何在Python中执行此操作。 

我们将使用Scikit-Learn库(尤其是train_test_split方法)进行此操作。 我们将从导入必要的库开始:

让我们快速浏览一下我导入的库:

Pandas- 将数据文件加载为pandas数据框并分析数据。 

From Sklearn- 导入了数据集模块,因此可以加载示例数据集和linear_model,从而可以运行线性回归

From Sklearn- 从子库model_selection中导入了train_test_split,因此可以将其拆分为训练集和测试集

Matplotlib-导入了pyplot,以便绘制数据图

好,准备好了! 让我们加载糖尿病数据集(diabetes dataset),将其转换为数据框并定义列的名称:

# Load the Diabetes dataset
columns = “age sex bmi map tc ldl hdl tch ltg glu”.split() # Declare the columns names
diabetes = datasets.load_diabetes() # Call the diabetes dataset from sklearn
df = pd.DataFrame(diabetes.data, columns=columns) # load the dataset as a pandas data frame
y = diabetes.target # define the target variable (dependent variable) as y

现在,我们可以使用train_test_split函数进行拆分。 函数内部的test_size = 0.2表示应保留进行测试的数据百分比。 通常是80/20或70/30。

# create training and testing vars
X_train, X_test, y_train, y_test = train_test_split(df, y, test_size=0.2)
print X_train.shape, y_train.shape
print X_test.shape, y_test.shape

(353, 10) (353,)
(89, 10) (89,)

现在,我们将模型拟合到训练数据上:

# fit a model
lm = linear_model.LinearRegression()model = lm.fit(X_train,y_train)
predictions = lm.predict(X_test)

如您所见,我们正在训练模型上拟合模型,并试图预测测试数据。 让我们看看预测是什么(部分):

predictions[0:5]
array([ 205.68012533, 64.58785513, 175.12880278, 169.95993301,128.92035866])

注意:由于我在预测后使用了[0:5],因此只显示了前五个预测值。 删除[0:5]将使其打印我们的模型创建的所有预测值。

让我们绘制模型:

## The line / model
plt.scatter(y_test, predictions)
plt.xlabel(“True Values”)
plt.ylabel(“Predictions”)

537b0a5687a0abd2a9d7b0af7f574626.png

并输出准确性分数:

print “Score:”, model.score(X_test, y_test)

Score: 0.485829586737

做得好! 以下是我所做工作的摘要:我已经加载了数据,将其分为训练和测试集,对训练数据拟合了回归模型,基于该数据对测试数据进行了预测。 看起来不错吧? 但是训练/测试拆分确实有其危险-如果我们进行的拆分不是随机的,该怎么办? 如果我们数据的一个子集仅包含来自某个州的人员,具有一定收入水平的员工,而没有其他收入水平,只有女性或只有特定年龄的人员,该怎么办? (想象一个由这些命令之一排序的文件)。 即使我们试图避免过度拟合,也会导致过度拟合! 这是交叉验证的来源。

3.交叉验证

在上一段中,我提到了训练/测试拆分方法中的注意事项。 为了避免这种情况,我们可以执行称为交叉验证的操作。 它与训练/测试拆分非常相似,但适用于更多子集。 意思是,我们将数据分为k个子集,并在k-1个子集中训练。 我们要做的是保留最后一个子集进行测试, 并且需要为每个子集重复这个步骤。

4ff97bfb9a390a87c9a7981477e97ad6.png

 训练/测试拆分和交叉验证的可视化表示

有很多交叉验证方法,我将介绍其中的两种:第一种是K-folds交叉验证,第二种是“ Leave One Out”交叉验证(LOOCV)

3.1 K折交叉验证

在K折交叉验证中,我们将数据分为k个不同的子集(或折)。 我们使用k-1个子集来训练我们的数据,并保留最后一个子集(或最后一个折叠)作为测试数据。 然后,我们针对每个子集对模型进行平均,然后最终确定模型。 之后,我们针对测试集对其进行测试。

4abcdf9b2aeb2f70772c086a6b96279b.png

 可视化的K折

这是Sklearn文档中有关K折的一个非常简单的示例:

from sklearn.model_selection import KFold # import KFold
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]]) # create an array
y = np.array([1, 2, 3, 4]) # Create another array
kf = KFold(n_splits=2) # Define the split - into 2 folds
kf.get_n_splits(X) # returns the number of splitting iterations in the cross-validatorprint(kf) KFold(n_splits=2, random_state=None, shuffle=False)

让我们看看结果-折叠:

for train_index, test_index in kf.split(X):

 print(“TRAIN:”, train_index, “TEST:”, test_index)

 X_train, X_test = X[train_index], X[test_index]

 y_train, y_test = y[train_index], y[test_index]

('TRAIN:', array([2, 3]), 'TEST:', array([0, 1]))

('TRAIN:', array([0, 1]), 'TEST:', array([2, 3]))

如您所见,该函数将原始数据拆分为数据的不同子集。 同样,这是一个非常简单的示例,但我认为它很好地解释了这个概念。

3.2 留一交叉验证(LOOCV)

这是另一种进行交叉验证的方法: 留一交叉验证(顺便说一句,这些方法不是仅有的两种,还有很多其他交叉验证方法。请在Sklearn网站上进行检查)。 在这种类型的交叉验证中,折叠(子集)的数量等于我们在数据集中观察到的数量。 然后,我们对所有这些折叠进行平均,并用平均数建立模型。 然后,我们针对最后的折叠测试模型。 由于我们将获得大量训练集(等于样本数量),因此该方法的计算量非常大,应在小型数据集上使用。 如果数据集很大,则最好使用其他方法,例如k-fold。

让我们看看Sklearn的另一个示例:

from sklearn.model_selection import LeaveOneOut
X = np.array([[1, 2], [3, 4]])
y = np.array([1, 2])
loo = LeaveOneOut()
loo.get_n_splits(X)
for train_index, test_index in loo.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
print(X_train, X_test, y_train, y_test)

这是输出:

('TRAIN:', array([1]), 'TEST:', array([0]))
(array([[3, 4]]), array([[1, 2]]), array([2]), array([1]))
('TRAIN:', array([0]), 'TEST:', array([1]))
(array([[1, 2]]), array([[3, 4]]), array([1]), array([2]))

同样,简单的示例,但我确实确实认为这有助于理解此方法的基本概念。

那么,我们应该使用什么方法呢? 应该使用多少折? 当我们使用更多折,我们将减少由于偏差引起的误差,但由于方差导致的误差增加; 很明显,计算成本也会上涨-折叠的次数越多,计算时间就越长,并且您将需要更多的内存。K折数量较少时,我们会减少由于方差引起的误差,但由于偏斜引起的误差会更大。 在计算上也更便宜。 因此,在大数据集中,通常建议k = 3。 如前所述,在较小的数据集中,最好使用LOOCV。

让我们看看我以前使用的示例,这次使用交叉验证。 我将使用cross_val_predict函数返回每个数据点在测试切片中的预测值。

# Necessary imports:
from sklearn.cross_validation import cross_val_score, cross_val_predict
from sklearn import metrics

您还记得,我之前为糖尿病数据集创建了训练/测试拆分并拟合了模型。 让我们看看交叉验证后的得分是多少:

# Perform 6-fold cross validation
scores = cross_val_score(model, df, y, cv=6)
print “Cross-validated scores:”, scoresCross-validated scores: [ 0.4554861   0.46138572  0.40094084  0.55220736  0.43942775  0.56923406]

如您所见,最后的折叠将原始模型的得分从0.485提高到0.569。 这不是一个惊人的结果,但是,我们将尽我们所能:)

现在,在执行交叉验证后,让我们绘制新的预测:

# Make cross validated predictions
predictions = cross_val_predict(model, df, y, cv=6)
plt.scatter(y, predictions)

15f038ba81bfbe4689b04fb63a4e3cfc.png

您会发现它与之前的原始图有很大不同。 因为我使用cv = 6,所以它的点数是原始图的六倍。

最后,让我们检查一下模型的R²得分(R²是一个“数字,该数字表明可以从自变量中预测出的因变量中的方差比例。”基本上,我们的模型有多准确):

accuracy = metrics.r2_score(y, predictions)
print “Cross-Predicted Accuracy:”, accuracyCross-Predicted Accuracy: 0.490806583864

这次就是这样! 希望您喜欢这篇文章。 与往常一样,我欢迎您提出关于您要阅读的主题的问题,注释,评论和帖子请求。 下次见!

作者:Adi Bronshtein

翻译:Fan Wang

138871c5244d93818808731dfe01e91c.png

往期精彩回顾

天花板?PIP?一文看懂美国公司技术岗位职场晋升(潜)规则

全!免!费!100+ 节 Python, SQL, R, Tableau等入门课线上课程通通免费!

Google 官方 Channel 盖戳:谷歌面试官眼中的优秀简历长什么样?

使用Python的scikit-learn进行特征缩放

2020年CIO的首要任务:利用它们来提升你的职业生涯

6cf1353b0588a42126c74879344943a4.png

dd8f50fdf064dcb20be034ec23a96f46.png

fb9de96ee357c546b3a75a6e70f5d17c.png

点「在看」的人都变好看了哦
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值