【scikit-learn】交叉验证及其用于參数选择、模型选择、特征选择的样例

??

内容概要?

  • 训练集/測试集切割用于模型验证的缺点
  • K折交叉验证是怎样克服之前的不足
  • 交叉验证怎样用于选择调节參数、选择模型、选择特征
  • 改善交叉验证

1. 模型验证回想?

进行模型验证的一个重要目的是要选出一个最合适的模型,对于监督学习而言,我们希望模型对于未知数据的泛化能力强,所以就须要模型验证这一过程来体现不同的模型对于未知数据的表现效果。

最先我们用训练精确度(用所有数据进行训练和測试)来衡量模型的表现,这样的方法会导致模型过拟合;为了解决这一问题,我们将所有数据分成训练集和測试集两部分,我们用训练集进行模型训练。得到的模型再用測试集来衡量模型的预測表现能力,这样的度量方式叫測试精确度,这样的方式能够有效避免过拟合。

測试精确度的一个缺点是其样本精确度是一个高方差预计(high variance estimate),所以该样本精确度会依赖不同的測试集。其表现效果不尽同样。

高方差预计的样例?

以下我们使用iris数据来说明利用測试精确度来衡量模型表现的方差非常高。

In [1]:

from sklearn.datasets import load_iris
from sklearn.cross_validation import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics

In [2]:

# read in the iris data
iris = load_iris()

X = iris.data
y = iris.target

In [3]:

for i in xrange(1,5):
    print "random_state is ", i,", and accuracy score is:"
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=i)

    knn = KNeighborsClassifier(n_neighbors=5)
    knn.fit(X_train, y_train)
    y_pred = knn.predict(X_test)
    print metrics.accuracy_score(y_test, y_pred)
random_state is  1 , and accuracy score is:
1.0
random_state is  2 , and accuracy score is:
1.0
random_state is  3 , and accuracy score is:
0.947368421053
random_state is  4 , and accuracy score is:
0.973684210526

以上測试准确率能够看出,不同的训练集、測试集切割的方法导致其准确率不同。而交叉验证的基本思想是:将数据集进行一系列切割。生成一组不同的训练測试集,然后分别训练模型并计算測试准确率,最后对结果进行平均处理。这样来有效减少測试准确率的差异。

2. K折交叉验证?

  1. 将数据集平均切割成K个等份
  2. 使用1份数据作为測试数据,其余作为训练数据
  3. 计算測试准确率
  4. 使用不同的測试集。反复2、3步骤
  5. 对測试准确率做平均。作为对未知数据预測准确率的预计

In [4]:

# 以下代码演示了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 ‘{} {:^61} {}‘.format(‘Iteration‘, ‘Training set observations‘, ‘Testing set observations‘)
for iteration, data in enumerate(kf, start=1):
    print ‘{:^9} {} {:^25}‘.format(iteration, data[0], data[1])
Iteration                   Training set observations                   Testing set observations
    1     [ 5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]        [0 1 2 3 4]
    2     [ 0  1  2  3  4 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]        [5 6 7 8 9]
    3     [ 0  1  2  3  4  5  6  7  8  9 15 16 17 18 19 20 21 22 23 24]     [10 11 12 13 14]
    4     [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 20 21 22 23 24]     [15 16 17 18 19]
    5     [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]     [20 21 22 23 24]

3. 使用交叉验证的建议?

  1. K=10是一个一般的建议
  2. 假设对于分类问题。应该使用分层抽样(stratified sampling)来生成数据。保证正负例的比例在训练集和測试集中的比例同样

4. 交叉验证的样例?

4.1 用于调节參数?

交叉验证的方法能够帮助我们进行调參。终于得到一组最佳的模型參数。以下的样例我们依旧使用iris数据和KNN模型,通过调节參数,得到一组最佳的參数使得測试数据的准确率和泛化能力最佳。

In [6]:

from sklearn.cross_validation import cross_val_score

In [7]:

knn = KNeighborsClassifier(n_neighbors=5)
# 这里的cross_val_score将交叉验证的整个过程连接起来,不用再进行手动的切割数据
# cv參数用于规定将原始数据分成多少份
scores = cross_val_score(knn, X, y, cv=10, scoring=‘accuracy‘)
print scores
[ 1.          0.93333333  1.          1.          0.86666667  0.93333333
  0.93333333  1.          1.          1.        ]

In [8]:

# use average accuracy as an estimate of out-of-sample accuracy
# 对十次迭代计算平均的測试准确率
print scores.mean()
0.966666666667

In [11]:

# 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.97333333333333338, 0.96666666666666679, 0.96666666666666679, 0.97333333333333338, 0.98000000000000009, 0.97333333333333338, 0.97333333333333338, 0.97333333333333338, 0.97333333333333338, 0.98000000000000009, 0.97333333333333338, 0.98000000000000009, 0.96666666666666656, 0.96666666666666656, 0.97333333333333338, 0.95999999999999996, 0.96666666666666656, 0.95999999999999996, 0.96666666666666656, 0.95333333333333337, 0.95333333333333337, 0.95333333333333337]

In [10]:

import matplotlib.pyplot as plt
%matplotlib inline

In [12]:

plt.plot(k_range, k_scores)
plt.xlabel("Value of K for KNN")
plt.ylabel("Cross validated accuracy")

Out[12]:

<matplotlib.text.Text at 0x6dd0fb0>

上面的样例显示了偏置-方差的折中,K较小的情况时偏置较低。方差较高。K较高的情况时。偏置较高,方差较低;最佳的模型參数取在中间位置,该情况下,使得偏置和方差得以平衡,模型针对于非样本数据的泛化能力是最佳的。

4.2 用于模型选择?

交叉验证也能够帮助我们进行模型选择,下面是一组样例,分别使用iris数据,KNN和logistic回归模型进行模型的比較和选择。

In [13]:

# 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()
0.98

In [14]:

# 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.953333333333

4.3 用于特征选择?

以下我们使用advertising数据,通过交叉验证来进行特征的选择,对照不同的特征组合对于模型的预測效果。

In [15]:

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression

In [16]:

# read in the advertising dataset
data = pd.read_csv(‘http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv‘, index_col=0)

In [17]:

# 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

In [18]:

# 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是一种损失函数,优化的目标的使其最小化。而分类准确率是一种奖励函数,优化的目标是使其最大化。

In [19]:

# fix the sign of MSE scores
mse_scores = -scores
print mse_scores
[ 3.56038438  3.29767522  2.08943356  2.82474283  1.3027754   1.74163618
  8.17338214  2.11409746  3.04273109  2.45281793]

In [20]:

# convert from MSE to RMSE
rmse_scores = np.sqrt(mse_scores)
print rmse_scores
[ 1.88689808  1.81595022  1.44548731  1.68069713  1.14139187  1.31971064
  2.85891276  1.45399362  1.7443426   1.56614748]

In [21]:

# calculate the average RMSE
print rmse_scores.mean()
1.69135317081

In [22]:

# 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()
1.67967484191

因为不增加Newspaper这一个特征得到的分数较小(1.68 < 1.69)。所以,使用全部特征得到的模型是一个更好的模型。

參考资料?

时间: 2024-11-08 18:58:30

【scikit-learn】交叉验证及其用于參数选择、模型选择、特征选择的样例的相关文章

可变參数学习笔记

一.什么是可变參数 我们在C语言编程中有时会遇到一些參数个数可变的函数,比如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一个參数format固定以外,后面跟的參数的个数和类型是可变的(用三个点"-"做參数占位符),实际调用时能够有下面的形式: printf("%d",i); printf("%s",s); printf("the number is %d ,s

总结:Bias(偏差),Error(误差),Variance(方差)及CV(交叉验证)

犀利的开头 在机器学习中,我们用训练数据集去训练(学习)一个model(模型),通常的做法是定义一个Loss function(误差函数),通过将这个Loss(或者叫error)的最小化过程,来提高模型的性能(performance).然而我们学习一个模型的目的是为了解决实际的问题(或者说是训练数据集这个领域(field)中的一般化问题),单纯地将训练数据集的loss最小化,并不能保证在解决更一般的问题时模型仍然是最优,甚至不能保证模型是可用的.这个训练数据集的loss与一般化的数据集的loss

Query意图分析:记一次完整的机器学习过程(scikit learn library学习笔记)

所谓学习问题,是指观察由n个样本组成的集合,并根据这些数据来预测未知数据的性质. 学习任务(一个二分类问题): 区分一个普通的互联网检索Query是否具有某个垂直领域的意图.假设现在有一个O2O领域的垂直搜索引擎,专门为用户提供团购.优惠券的检索:同时存在一个通用的搜索引擎,比如百度,通用搜索引擎希望能够识别出一个Query是否具有O2O检索意图,如果有则调用O2O垂直搜索引擎,获取结果作为通用搜索引擎的结果补充. 我们的目的是学习出一个分类器(classifier),分类器可以理解为一个函数,

scikit learn 模块 调参 pipeline+girdsearch 数据举例:文档分类

scikit learn 模块 调参 pipeline+girdsearch 数据举例:文档分类数据集 fetch_20newsgroups #-*- coding: UTF-8 -*- import numpy as np from sklearn.pipeline import Pipeline from sklearn.linear_model import SGDClassifier from sklearn.grid_search import GridSearchCV from sk

OpenCV中的SVM參数优化

SVM(支持向量机)是机器学习算法里用得最多的一种算法.SVM最经常使用的是用于分类,只是SVM也能够用于回归,我的实验中就是用SVM来实现SVR(支持向量回归). 对于功能这么强的算法,opencv中自然也是有集成好了,我们能够直接调用.OpenCV中的SVM算法是基于LibSVM软件包开发的,LibSVM是台湾大学林智仁(Lin Chih-Jen)等开发设计的一个简单.易于使用和高速有效的SVM模式识别与回归的软件包. 网上讲opencv中SVM使用的文章有非常多,但讲SVM參数优化的文章却

机器学习 libsvm交叉验证与网格搜索(参数选择)

首先说交叉验证. 交叉验证(Cross validation)是一种评估统计分析.机器学习算法对独立于训练数据的数据集的泛化能力(generalize), 能够避免过拟合问题. 交叉验证一般要尽量满足: 1)训练集的比例要足够多,一般大于一半 2)训练集和测试集要均匀抽样 交叉验证主要分成以下几类: 1)Double cross-validation Double cross-validation也称2-fold cross-validation(2-CV),作法是将数据集分成两个相等大小的子集

交叉验证 Cross-validation

对交叉验证这个问题,一直以来,不明白是怎么回事.近期看材料,涉及到了这个问题,写的通俗易懂,有种恍然大悟的感觉.下面,我写下对这个问题的理解. 现在假设这里有一堆数据,作为统计er的任务就是从这些数据中提取有用的信息.如何提取信息呢,我们的法宝就是–模型.模型在统计当中是极其重要的,学统计就是跟各种各样的模型混个脸熟.在模型的基础上,我们利用数据对模型的参数进行估计,从而通过参数化后的模型来描述数据的内在关系,了解数据内在的关系(pattern)非常必要,有助于对未来进行预测. 那么对于手里的数

机器学习-CrossValidation交叉验证详解

版权声明:本文为原创文章,转载请注明来源. 1.原理 1.1 概念 交叉验证(Cross-validation)主要用于模型训练或建模应用中,如分类预测.PCR.PLS回归建模等.在给定的样本空间中,拿出大部分样本作为训练集来训练模型,剩余的小部分样本使用刚建立的模型进行预测,并求这小部分样本的预测误差或者预测精度,同时记录它们的加和平均值.这个过程迭代K次,即K折交叉.其中,把每个样本的预测误差平方加和,称为PRESS(predicted Error Sum of Squares). 1.2

微信公众号开发系列-微信企业号开发相关參数

微信企业号出来之后,本人也抱着前面开发订阅号和服务号的经验来探究了一番,这里整理了下再开发企业号时候碰到的一些接口參数.企业号开发文档详见http://qydev.weixin.qq.com/wiki/index.php?title=首页 1.创建自己定义菜单參数解释: 菜单管理的创建操作.官方定义例如以下所看到的. 请求说明 Https请求方式: POST https://qyapi.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_T