交叉驗證概述
進行模型驗證的一個重要目的是要選出一個最合適的模型嚷堡,對于監(jiān)督學(xué)習而言,我們希望模型對于未知數(shù)據(jù)的泛化能力強艇棕,所以就需要模型驗證這一過程來體現(xiàn)不同的模型對于未知數(shù)據(jù)的表現(xiàn)效果蝌戒。
最先我們用訓(xùn)練準確度(用全部數(shù)據(jù)進行訓(xùn)練和測試)來衡量模型的表現(xiàn)串塑,這種方法會導(dǎo)致模型過擬合;為了解決這一問題北苟,我們將所有數(shù)據(jù)分成訓(xùn)練集和測試集兩部分疾牲,我們用訓(xùn)練集進行模型訓(xùn)練诲锹,得到的模型再用測試集來衡量模型的預(yù)測表現(xiàn)能力楞卡,這種度量方式叫測試準確度篓叶,這種方式可以有效避免過擬合溉旋。
測試準確度的一個缺點是其樣本準確度是一個高方差估計(high varianceestimate)社痛,所以該樣本準確度會依賴不同的測試集胀蛮,其表現(xiàn)效果不盡相同蹂析。
K折交叉驗證
- 將數(shù)據(jù)集平均分割成K個等份
- 使用1份數(shù)據(jù)作為測試數(shù)據(jù)葛碧,其余作為訓(xùn)練數(shù)據(jù)
- 計算測試準確率
- 使用不同的測試集借杰,重復(fù)2、3步驟
- 對測試準確率做平均进泼,作為對未知數(shù)據(jù)預(yù)測準確率的估計
n_splits : 默認3蔗衡,最小為2;K折驗證的K值
shuffle : 默認False;shuffle會對數(shù)據(jù)產(chǎn)生隨機攪動(洗牌)
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) 返回訓(xùn)練集和測試集的索引
# 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類似绞惦,將數(shù)據(jù)集劃分成k份,不同點在于洋措,劃分的k份中济蝉,每一份內(nèi)各個類別數(shù)據(jù)的比例和原始數(shù)據(jù)集中各個類別的比例相同。
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折的折數(shù)菠发,輸出為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(現(xiàn)在更換為Model selection)大概的意思是:對于原始數(shù)據(jù)我們要將其一部分分為traindata王滤,一部分分為test data。train data用于訓(xùn)練滓鸠,test data用于測試準確率雁乡。在test data上測試的結(jié)果叫做validation error。將一個算法作用于一個原始數(shù)據(jù)糜俗,我們不可能只做出隨機的劃分一次train和testdata踱稍,然后得到一個validation error,就作為衡量這個算法好壞的標準悠抹。因為這樣存在偶然性珠月。我們必須多次的隨機的劃分train data和test data,分別在其上面算出各自的validation error锌钮。這樣就有一組validationerror桥温,根據(jù)這一組validationerror,就可以較好的準確的衡量算法的好壞梁丘。crossvalidation是在數(shù)據(jù)量有限的情況下的非常好的一個evaluate performance的方法侵浸。而對原始數(shù)據(jù)劃分出train data和testdata的方法有很多種旺韭,這也就造成了cross validation的方法有很多種。
返回值就是對于每次不同的的劃分raw data時掏觉,在test data上得到的分類的準確率区端。
參數(shù)解釋:
estimator:是不同的分類器,可以是任何的分類器澳腹。比如支持向量機分類器:estimator = svm.SVC(kernel='linear', C=1)
cv:代表不同的cross validation的方法织盼。如果cv是一個int值,并且如果提供了rawtarget參數(shù)酱塔,那么就代表使用StratifiedKFold分類方式沥邻;如果cv是一個int值,并且沒有提供rawtarget參數(shù)羊娃,那么就代表使用KFold分類方式唐全;也可以給定它一個CV迭代策略生成器,指定不同的CV方法蕊玷。
scoring:默認Nnoe邮利,準確率的算法,可以通過score_func參數(shù)指定垃帅;如果不指定的話延届,是用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)
輸出結(jié)果
[0.97852941 0.98212121 0.97757576]
0.9794087938205586
0.9996078431372549
True
實戰(zhàn)
使用knn和iris數(shù)據(jù)集測試
一個是通過 train_test_split方法分割贸诚,訓(xùn)練方庭,預(yù)測,然后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數(shù)據(jù),通過交叉驗證來進行特征的選擇媒怯,對比不同的特征組合對于模型的預(yù)測效果
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都是負數(shù),為什么均方誤差會出現(xiàn)負數(shù)的情況呢扇苞?因為這里的mean_squared_error是一種損失函數(shù)欺殿,優(yōu)化的目標的使其最小化,而分類準確率是一種獎勵函數(shù)鳖敷,優(yōu)化的目標是使其最大化脖苏。
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())
結(jié)果分別是1.6913531708051797和1.6796748419090766
由于不加入Newspaper這一個特征得到的分數(shù)較小(1.68 < 1.69)定踱,所以棍潘,使用所有特征得到的模型是一個更好的模型。
參考
https://blog.csdn.net/jasonding1354/article/details/50562513
https://blog.csdn.net/cherdw/article/details/54986863
http://www.reibang.com/p/a4e94e72a46d