交叉验证概述
进行模型验证的一个重要目的是要选出一个最合适的模型,对于监督学习而言,我们希望模型对于未知数据的泛化能力强,所以就需要模型验证这一过程来体现不同的模型对于未知数据的表现效果。
最先我们用训练准确度(用全部数据进行训练和测试)来衡量模型的表现,这种方法会导致模型过拟合;为了解决这一问题,我们将所有数据分成训练集和测试集两部分,我们用训练集进行模型训练,得到的模型再用测试集来衡量模型的预测表现能力,这种度量方式叫测试准确度,这种方式可以有效避免过拟合。
测试准确度的一个缺点是其样本准确度是一个高方差估计(high varianceestimate),所以该样本准确度会依赖不同的测试集,其表现效果不尽相同。
K折交叉验证
- 将数据集平均分割成K个等份
- 使用1份数据作为测试数据,其余作为训练数据
- 计算测试准确率
- 使用不同的测试集,重复2、3步骤
- 对测试准确率做平均,作为对未知数据预测准确率的估计
n_splits : 默认3,最小为2;K折验证的K值
shuffle : 默认False;shuffle会对数据产生随机搅动(洗牌)
random_state :默认None,随机种子
from sklearn.model_selection import KFold
from numpy import *
X = array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = array([1, 2, 3, 4])
kf = KFold(n_splits=2)
kf.get_n_splits(X)
print(kf)
#kf.split(x) 返回训练集和测试集的索引
# http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html
for train_index, test_index in kf.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
#输出:TRAIN: [2 3] TEST: [0 1]
# TRAIN: [0 1] TEST: [2 3]
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
Stratified k-fold
与k-fold类似,将数据集划分成k份,不同点在于,划分的k份中,每一份内各个类别数据的比例和原始数据集中各个类别的比例相同。
from sklearn.model_selection importStratifiedKFold
X= np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y= np.array([0, 0, 1, 1])
skf= StratifiedKFold(n_splits=2)
skf.get_n_splits(X, y)#给出K折的折数,输出为2
print(skf)
#输出为:StratifiedKFold(n_splits=2,random_state=None, shuffle=False)
for train_index, test_index in skf.split(X, y):
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: [1 3] TEST: [0 2]
TRAIN: [0 2] TEST: [1 3]
模型验证方法
cross validation(现在更换为Model selection)大概的意思是:对于原始数据我们要将其一部分分为traindata,一部分分为test data。train data用于训练,test data用于测试准确率。在test data上测试的结果叫做validation error。将一个算法作用于一个原始数据,我们不可能只做出随机的划分一次train和testdata,然后得到一个validation error,就作为衡量这个算法好坏的标准。因为这样存在偶然性。我们必须多次的随机的划分train data和test data,分别在其上面算出各自的validation error。这样就有一组validationerror,根据这一组validationerror,就可以较好的准确的衡量算法的好坏。crossvalidation是在数据量有限的情况下的非常好的一个evaluate performance的方法。而对原始数据划分出train data和testdata的方法有很多种,这也就造成了cross validation的方法有很多种。
返回值就是对于每次不同的的划分raw data时,在test data上得到的分类的准确率。
参数解释:
estimator:是不同的分类器,可以是任何的分类器。比如支持向量机分类器:estimator = svm.SVC(kernel='linear', C=1)
cv:代表不同的cross validation的方法。如果cv是一个int值,并且如果提供了rawtarget参数,那么就代表使用StratifiedKFold分类方式;如果cv是一个int值,并且没有提供rawtarget参数,那么就代表使用KFold分类方式;也可以给定它一个CV迭代策略生成器,指定不同的CV方法。
scoring:默认Nnoe,准确率的算法,可以通过score_func参数指定;如果不指定的话,是用estimator默认自带的准确率算法。
from sklearn.model_selection import cross_val_score
from sklearn.datasets import make_blobs
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.tree import DecisionTreeClassifier
X, y = make_blobs(n_samples=10000, n_features=10, centers=100,
random_state=0)
clf = DecisionTreeClassifier(max_depth=None, min_samples_split=2,
random_state=0)
scores = cross_val_score(clf, X, y)
print(scores)
print(scores.mean())
clf = RandomForestClassifier(n_estimators=10, max_depth=None,
min_samples_split=2, random_state=0)
scores = cross_val_score(clf, X, y)
print(scores.mean())
clf = ExtraTreesClassifier(n_estimators=10, max_depth=None,
min_samples_split=2, random_state=0)
scores = cross_val_score(clf, X, y)
print(scores.mean() > 0.999)
输出结果
[0.97852941 0.98212121 0.97757576]
0.9794087938205586
0.9996078431372549
True
实战
使用knn和iris数据集测试
一个是通过 train_test_split方法分割,训练,预测,然后metrics.accuracy_score计算准确率。
或者直接通过上面讲的cross_val_score进行验证。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
from numpy import *
iris = load_iris()
X = iris.data
y = iris.target
knn = KNeighborsClassifier(n_neighbors=5)
for i in range(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.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print(metrics.accuracy_score(y_test, y_pred))
print(cross_val_score(knn,X,y))
输出
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.9473684210526315
random_state is 4 , and accuracy score is:
0.9736842105263158
[0.98039216 0.98039216 1. ]
可以同时对比logtic回归和knn的准确率
from sklearn.linear_model import LogisticRegression
iris = load_iris()
X = iris.data
y = iris.target
knn = KNeighborsClassifier(n_neighbors=5)
print(cross_val_score(knn,X,y,cv=10,scoring='accuracy').mean())
logreg = LogisticRegression()
print(cross_val_score(logreg, X, y, cv=10, scoring='accuracy').mean())
用于特征选择
使用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='neg_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是一种损失函数,优化的目标的使其最小化,而分类准确率是一种奖励函数,优化的目标是使其最大化。
mse_scores = -scores
rmse_scores = np.sqrt(mse_scores)
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='neg_mean_squared_error')).mean())
结果分别是1.6913531708051797和1.6796748419090766
由于不加入Newspaper这一个特征得到的分数较小(1.68 < 1.69),所以,使用所有特征得到的模型是一个更好的模型。
参考
https://blog.csdn.net/jasonding1354/article/details/50562513
https://blog.csdn.net/cherdw/article/details/54986863
https://www.jianshu.com/p/a4e94e72a46d
网友评论