[置顶] Scikit-Learn实战之——交叉验证
2017-10-04 21:16
288 查看
本文将从以下几个方面进行介绍:
简单地讲训练集/测试集分割进行模型验证的缺点;
K折交叉验证的做法和优点;
交叉验证如何用于选择调节参数、选择模型、选择特征;
对交叉验证进行升级。
最先我们用训练准确度(用全部数据进行训练和测试)来衡量模型的效果,这种方法容易导致模型过拟合。最初,为了解决这个问题,我们将所有数据分成两部分:训练集 和 测试集。我们用训练集进行模型训练,得到的模型再用测试集来衡量模型的预测表现能力,这种度量方式叫测试准确度,这种方式可以有效避免过拟合。
测试准确度的一个缺点是其样本准确度是一个高方差估计(high variance estimate),所以该样本准确度会依赖不同的测试集,其表现效果不尽相同。
数据输出结果:
上面的测试准确率可以看出,不同的训练集、测试集分割的方法导致其准确率不同,而交叉验证的基本思想是:将数据集进行一系列分割,生成一组不同的训练测试集,然后分别训练模型并计算测试准确率,最后对结果进行平均处理。这样来有效降低测试准确率的差异。
使用1份数据作为测试数据,其余作为训练数据;
计算测试准确率;
使用不同的测试集,重复2、3步骤;
计算以上测试准确率的平均值,作为模型对未知数据预测准确率的估计。
![](http://nbviewer.jupyter.org/github/jasonding1354/pyDataScienceToolkits_Base/blob/master/Scikit-learn/Image/cross_validation_diagram.png)
下面代码演示了K-fold交叉验证是如何进行数据分割的:
如果对于分类问题,应该使用分层抽样(stratified sampling)来生成数据,保证正负例的比例在训练集和测试集中的比例相同。
输出结果:
输出结果:
绘图显示:
显示结果:
![](https://img-blog.csdn.net/20171004210156185?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzcwOTI3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
上面的例子显示了偏置-方差的折中,K较小的情况时偏置较低,方差较高;K较高的情况时,偏置较高,方差较低;最佳的模型参数取在中间位置,该情况下,使得偏置和方差得以平衡,模型针对于非样本数据的泛化能力是最佳的。
输出结果:
下面我们使用advertising数据,通过交叉验证来进行特征的选择,对比不同的特征组合对于模型的预测效果。
输出结果:
这里要注意的是,上面的scores都是负数,为什么均方误差会出现负数的情况呢?因为这里的mean_squared_error是一种损失函数,优化的目标的使其最小化,而分类准确率是一种奖励函数,优化的目标是使其最大化。
输出结果:
由于不加入Newspaper这一个特征得到的分数较小(1.68 < 1.69),所以,使用所有特征得到的模型是一个更好的模型。
简单地讲训练集/测试集分割进行模型验证的缺点;
K折交叉验证的做法和优点;
交叉验证如何用于选择调节参数、选择模型、选择特征;
对交叉验证进行升级。
1. 为什么要进行模型验证
众所周知,在机器学习与数据挖掘中进行模型验证的一个重要目的是要选出一个最合适的模型。对于有监督学习而言,我们希望模型对于未知数据具有很强的泛化能力,所以就需要模型验证这一过程来评估不同的模型对于未知数据的表现效果。最先我们用训练准确度(用全部数据进行训练和测试)来衡量模型的效果,这种方法容易导致模型过拟合。最初,为了解决这个问题,我们将所有数据分成两部分:训练集 和 测试集。我们用训练集进行模型训练,得到的模型再用测试集来衡量模型的预测表现能力,这种度量方式叫测试准确度,这种方式可以有效避免过拟合。
测试准确度的一个缺点是其样本准确度是一个高方差估计(high variance estimate),所以该样本准确度会依赖不同的测试集,其表现效果不尽相同。
1.1 高方差估计的例子。
下面我们使用iris数据来说明利用测试准确度来衡量模型表现的方差很高。from sklearn.datasets import load_iris from sklearn.cross_validation import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn import metrics # read in the iris data iris = load_iris() X = iris.data y = iris.target for i in range(1, 5): print("Random times", i, ", accuracy score is:",end=' ') X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=i) knn = KNeigh 4000 borsClassifier(n_neighbors=5) knn.fit(X_train, y_train) y_pred = knn.predict(X_test) print(metrics.accuracy_score(y_test, y_pred),'\n')
数据输出结果:
Random times 1 , accuracy score is: 1.0 Random times 2 , accuracy score is: 1.0 Random times 3 , accuracy score is: 0.947368421053 Random times 4 , accuracy score is: 0.973684210526
上面的测试准确率可以看出,不同的训练集、测试集分割的方法导致其准确率不同,而交叉验证的基本思想是:将数据集进行一系列分割,生成一组不同的训练测试集,然后分别训练模型并计算测试准确率,最后对结果进行平均处理。这样来有效降低测试准确率的差异。
2. K折交叉验证
2.1 K折交叉验证步骤
将数据集平均分割成K个等份;使用1份数据作为测试数据,其余作为训练数据;
计算测试准确率;
使用不同的测试集,重复2、3步骤;
计算以上测试准确率的平均值,作为模型对未知数据预测准确率的估计。
![](http://nbviewer.jupyter.org/github/jasonding1354/pyDataScienceToolkits_Base/blob/master/Scikit-learn/Image/cross_validation_diagram.png)
下面代码演示了K-fold交叉验证是如何进行数据分割的:
# simulate splitting a dataset of 25 observations into 5 folds from sklearn.cross_validation import KFold kf = KFold(25, n_folds=5, shuffle=False) # print the contents of each training and testing set print(str('{} {:^61} {}'.format('Iteration', 'Training set observations', 'Testing set observations'))) for iteration, data in enumerate(kf, start=1): print(str('{:^9} {} {:^25}'.format(str(iteration), str(data[0]), str(data[1]))))
2.2 使用交叉验证的建议
K=10是一个一般的建议;如果对于分类问题,应该使用分层抽样(stratified sampling)来生成数据,保证正负例的比例在训练集和测试集中的比例相同。
3. 交叉验证的作用
3.1 用于调节参数
交叉验证的方法可以帮助我们进行调参,最终得到一组最佳的模型参数。下面的例子我们依然使用iris数据和KNN模型,通过调节参数,得到一组最佳的参数使得测试数据的准确率和泛化能力最佳。from sklearn.cross_validation import cross_val_score knn = KNeighborsClassifier(n_neighbors=5) # 这里的cross_val_score将交叉验证的整个过程连接起来,不用再进行手动的分割数据 # cv参数用于规定将原始数据分成多少份 scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy') print(scores) #计算平均准确率 print("Mean accuracy: ", scores.mean())
输出结果:
[ 1. 0.93333333 1. 1. 0.86666667 0.93333333 0.93333333 1. 1. 1. ] Mean accuracy: 0.966666666667
3.1.1 寻找最优的K值:
# search for an optimal value of K for KNN model k_range = range(1,31) k_scores = [] for k in k_range: knn = KNeighborsClassifier(n_neighbors=k) scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy') k_scores.append(scores.mean()) print (k_scores)
输出结果:
[0.95999999999999996, 0.95333333333333337, 0.96666666666666656, 0.96666666666666656, 0.96666666666666679, 0.96666666666666679, 0.96666666666666679, 0.96666666666666679, 0.98000000000000009, 0.97333333333333338, 0.97333333333333338, 0.97333333333333338, 0.97333333333333338, 0.98000000000000009, 0.97333333333333338, 0.98000000000000009, 0.96666666666666656, 0.95999999999999996, 0.96666666666666656, 0.95333333333333337, 0.95333333333333337, 0.95333333333333337]
绘图显示:
import matplotlib.pyplot as plt plt.plot(k_range, k_scores) plt.xlabel("Value of K for KNN") plt.ylabel("Cross validated accuracy") plt.show()
显示结果:
上面的例子显示了偏置-方差的折中,K较小的情况时偏置较低,方差较高;K较高的情况时,偏置较高,方差较低;最佳的模型参数取在中间位置,该情况下,使得偏置和方差得以平衡,模型针对于非样本数据的泛化能力是最佳的。
3.2 用于模型选择
交叉验证也可以帮助我们进行模型选择,以下是一组例子,分别使用iris数据,KNN和logistic回归模型进行模型的比较和选择。# 10-fold cross-validation with the best KNN model knn = KNeighborsClassifier(n_neighbors=20) print(cross_val_score(knn, X, y, cv=10, scoring='accuracy').mean()) # 10-fold cross-validation with logistic regression from sklearn.linear_model import LogisticRegression logreg = LogisticRegression() print(cross_val_score(logreg, X, y, cv=10, scoring='accuracy').mean())
输出结果:
0.98 0.953333333333
3.3 用于特征选择
下面我们使用advertising数据,通过交叉验证来进行特征的选择,对比不同的特征组合对于模型的预测效果。
import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression # read in the advertising dataset data = pd.read_csv('http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv', index_col=0) # create a Python list of three feature names feature_cols = ['TV', 'Radio', 'Newspaper'] # use the list to select a subset of the DataFrame (X) X = data[feature_cols] # select the Sales column as the response (y) y = data.Sales # 10-fold cv with all features lm = LinearRegression() scores = cross_val_score(lm, X, y, cv=10, scoring='mean_squared_error') print scores
输出结果:
[-3.56038438 -3.29767522 -2.08943356 -2.82474283 -1.3027754 -1.74163618 -8.17338214 -2.11409746 -3.04273109 -2.45281793]
这里要注意的是,上面的scores都是负数,为什么均方误差会出现负数的情况呢?因为这里的mean_squared_error是一种损失函数,优化的目标的使其最小化,而分类准确率是一种奖励函数,优化的目标是使其最大化。
# fix the sign of MSE scores mse_scores = -scores print(mse_scores) # convert from MSE to RMSE rmse_scores = np.sqrt(mse_scores) print(rmse_scores) # calculate the average RMSE print(rmse_scores.mean()) # 10-fold cross-validation with two features (excluding Newspaper) feature_cols = ['TV', 'Radio'] X = data[feature_cols] print np.sqrt(-cross_val_score(lm, X, y, cv=10, scoring='mean_squared_error')).mean()
输出结果:
[ 3.56038438 3.29767522 2.08943356 2.82474283 1.3027754 1.74163618 8.17338214 2.11409746 3.04273109 2.45281793] [ 1.88689808 1.81595022 1.44548731 1.68069713 1.14139187 1.31971064 2.85891276 1.45399362 1.7443426 1.56614748] 1.69135317081 1.67967484191
由于不加入Newspaper这一个特征得到的分数较小(1.68 < 1.69),所以,使用所有特征得到的模型是一个更好的模型。
相关文章推荐
- [置顶] Scikit-learn实战之SVM回归分析、密度估计、异常点检测
- [置顶] Scikit-learn实战之SVM分类
- scikit-learn 实战之监督学习 4
- 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(四)
- Scikit-learn实战之线性模型
- scikit-learn 实战之非监督学习 4
- scikit-learn 实战之非监督学习
- python3.5《机器学习实战》学习笔记(三):k近邻算法scikit-learn实战手写体识别
- 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(五)
- 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(八)
- 机器学习系统模型调优实战--所有调优技术都附相应的scikit-learn实现
- 机器学习实战之使用 scikit-learn 库实现 knn
- scikit-learn常用的一些函数及在实战中的用法
- Scikit-learn实战之聚类-Kmeans
- 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(二)
- 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(三)
- 机器学习实战之使用 scikit-learn 库实现 svm
- Scikit-learn机器学习实战之Kmeans
- 分享《机器学习实战:基于Scikit-Learn和TensorFlow》高清中英文PDF+源代码
- 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(九)