交叉驗(yàn)證是建立模型后進(jìn)行參數(shù)調(diào)整和模型檢驗(yàn)的一個(gè)步驟涮坐。本文就sklearn自帶的鳶尾花數(shù)據(jù)集,進(jìn)行基本的建模思路整理和交叉驗(yàn)證梳理关摇。
注:
鳶尾花案例的背景是屑埋,通過已知(歷史)花的數(shù)據(jù)和對(duì)應(yīng)的分類,訓(xùn)練出模型結(jié)果惋嚎,從而得到分類模型杠氢。
實(shí)現(xiàn)效果是可以預(yù)測鳶尾花的分類。
建立model的基本思路與步驟
- 首先另伍,導(dǎo)入相應(yīng)模塊
- 下載數(shù)據(jù)集鼻百,定義好x/y
- 分割數(shù)據(jù)集
- 選擇算法對(duì)訓(xùn)練集訓(xùn)練
- 預(yù)測分類結(jié)果
- 檢驗(yàn)得分:交叉驗(yàn)證
- 首先,導(dǎo)入相應(yīng)模塊摆尝;
- 下載數(shù)據(jù)集温艇,定義好x/y
import numpy as np
from sklearn import datasets
from sklearn.cross_validation import train_test_split #用于分割數(shù)據(jù)集
from sklearn.neighbors import KNeighborsClassifier #引入算法
iris=datasets.load_iris() #下載數(shù)據(jù)集
iris_X=iris.data #定義屬性(x)
iris_y=iris.target #定義分類(y)
print(iris_X[:2,:]) #查看一下屬性的前兩行
print(iris_y) #查看分類
[[5.1 3.5 1.4 0.2]
[4.9 3. 1.4 0.2]]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
分割數(shù)據(jù)集——將數(shù)據(jù)分為為訓(xùn)練集(70% train)和測試集(30% test):trian_test_split()
選擇算法對(duì)訓(xùn)練集訓(xùn)練——用knn算法對(duì)數(shù)據(jù)進(jìn)行訓(xùn)練:knn.fit(X_train,y_train)
#分割數(shù)據(jù)集,同時(shí)對(duì)數(shù)據(jù)做亂序
X_train,X_test,y_train,y_test=train_test_split(iris_X,iris_y,test_size=0.3)
# print(y_train) #從這里可以看到堕汞,數(shù)字已經(jīng)被打亂
knn=KNeighborsClassifier()
knn.fit(X_train,y_train)
[0 0 2 1 2 1 0 0 1 2 0 1 0 2 2 0 1 1 1 1 1 2 2 1 0 2 1 1 1 0 0 0 0 0 1 1 0
2 0 2 0 2 2 2 2 2 1 0 1 1 0 2 2 0 0 1 2 1 0 2 1 2 1 1 1 0 1 2 2 2 0 0 1 0
1 1 0 1 2 2 0 2 0 1 0 2 2 2 0 2 1 0 0 2 0 2 2 1 1 0 2 1 1 2 2]
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=1, n_neighbors=5, p=2,
weights='uniform')
- 預(yù)測分類結(jié)果——把測試集(test)代入訓(xùn)練得到的結(jié)果:knn.predict()
- 檢驗(yàn)——對(duì)預(yù)測結(jié)果與實(shí)際數(shù)值進(jìn)行效果對(duì)比(驗(yàn)證是否選用該模型勺爱。接下來引入交叉驗(yàn)證)
print(knn.predict(X_test))
print(y_test)
[1 1 1 1 2 2 2 1 2 2 2 0 0 0 2 1 1 1 2 2 1 2 2 0 0 0 1 0 0 0 0 1 1 1 2 1 2
0 1 1 0 2 0 2 0]
[1 1 1 1 2 2 2 1 2 1 2 0 0 0 2 1 1 1 2 2 1 2 2 0 0 0 1 0 0 0 0 1 1 1 2 1 2
0 1 2 0 2 0 2 0]
交叉驗(yàn)證
交叉驗(yàn)證的基本思想是在某種意義下將原始數(shù)據(jù)(dataset)進(jìn)行分組,一部分做為訓(xùn)練集(train set),另一部分做為驗(yàn)證集(validation set or test set),首先用訓(xùn)練集對(duì)分類器進(jìn)行訓(xùn)練,再利用驗(yàn)證集來測試訓(xùn)練得到的模型(model),以此來做為評(píng)價(jià)分類器的性能指標(biāo)。
而對(duì)一個(gè)數(shù)據(jù)集進(jìn)行多次(cv)交叉驗(yàn)證臼朗,并對(duì)每一次的得分求平均得到最客觀的評(píng)價(jià)分?jǐn)?shù)可以作為最終評(píng)分邻寿。
因此,它的作用就是:用于參數(shù)調(diào)整和模型選擇/評(píng)價(jià)视哑。
用于模型選擇——模型評(píng)價(jià)分的高低
from sklearn.datasets import load_iris
from sklearn.cross_validation import train_test_split
from sklearn.neighbors import KNeighborsClassifier
iris=load_iris()
X=iris.data
y=iris.target
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=4)
knn=KNeighborsClassifier(n_neighbors=5)
# 表示考慮數(shù)據(jù)點(diǎn)附近5個(gè)點(diǎn)的值并綜合绣否,得到預(yù)測值
knn.fit(X_train,y_train)
print(knn.score(X_test,y_test)) #只做一次分組測試,打印準(zhǔn)確率
0.9736842105263158
訓(xùn)練五次獲得綜合評(píng)價(jià)
from sklearn.datasets import load_iris
from sklearn.cross_validation import train_test_split
from sklearn.neighbors import KNeighborsClassifier
iris=load_iris()
X=iris.data
y=iris.target
from sklearn.cross_validation import cross_val_score
knn=KNeighborsClassifier(n_neighbors=5)
scores=cross_val_score(knn,X,y,cv=5,scoring='accuracy')
# 分成5組不同的訓(xùn)練&測試集挡毅;得分標(biāo)準(zhǔn)定位 準(zhǔn)確度(分類模型通常以準(zhǔn)確度為準(zhǔn))
print(scores.mean()) #綜合五次訓(xùn)練得分的平均分
0.9733333333333334
該結(jié)果接近滿分蒜撮,說明模型分類效果較好」虺剩可以采用該模型段磨。
用于調(diào)整參數(shù)
循環(huán)找到合適的k值
KNN算法中k值的大小,代表分類時(shí)考慮訓(xùn)練數(shù)據(jù)點(diǎn)周圍的數(shù)據(jù)點(diǎn)的個(gè)數(shù)耗绿。不同的k的取值苹支,分類結(jié)果不同。我們可以用循環(huán)的方法對(duì)k進(jìn)行循環(huán)误阻,根據(jù)不同k值對(duì)應(yīng)的得分(上述交叉驗(yàn)證的評(píng)價(jià)得分)決定k的取值债蜜,從而確定最終的模型和模型評(píng)價(jià)晴埂。
- 用準(zhǔn)確度評(píng)價(jià)
from sklearn.datasets import load_iris
from sklearn.cross_validation import train_test_split
from sklearn.neighbors import KNeighborsClassifier
iris=load_iris()
X=iris.data
y=iris.target
# X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=4)
# knn=KNeighborsClassifier(n_neighbors=5)
# knn.fit(X_train,y_train)
# print(knn.score(X_test,y_test))
# knn=KNeighborsClassifier(n_neighbors=5)
# scores=cross_val_score(knn,X,y,cv=5,scoring='accuracy') #分成5組
print(scores.mean()) #綜合五次訓(xùn)練得分的平均分
from sklearn.cross_validation import cross_val_score
import matplotlib.pyplot as plt
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') #for classification 分類的評(píng)價(jià)用準(zhǔn)確度
k_scores.append(scores.mean())
plt.plot(k_range,k_scores)
plt.xlabel('Value of K for KNN')
plt.ylabel('Cross_Validated Accuracy')
plt.show()
上圖是以準(zhǔn)確度為評(píng)價(jià)標(biāo)準(zhǔn),k從1~31對(duì)應(yīng)的score的值
這組數(shù)據(jù)選擇12~18至間的數(shù)字會(huì)比較好寻定。
from sklearn.datasets import load_iris
from sklearn.cross_validation import train_test_split
from sklearn.neighbors import KNeighborsClassifier
iris=load_iris()
X=iris.data
y=iris.target
from sklearn.cross_validation import cross_val_score
import matplotlib.pyplot as plt
k_range=range(1,31)
k_scores=[]
for k in k_range:
knn=KNeighborsClassifier(n_neighbors=k)
loss=-cross_val_score(knn,X,y,cv=10,scoring='neg_mean_squared_error') # for regression 儒洛,回歸的評(píng)價(jià)用 平均方差
#scores=cross_val_score(knn,X,y,cv=10,scoring='accuracy') #for classification 對(duì)比regression發(fā)現(xiàn),只有前面的負(fù)號(hào)和評(píng)分方式不同狼速。
k_scores.append(loss.mean())
plt.plot(k_range,k_scores)
plt.xlabel('Value of K for KNN')
plt.ylabel('Cross_Validated Accuracy')
plt.show()
上圖是用平均方差值來作為評(píng)價(jià)標(biāo)準(zhǔn)(越接近0說明擬合效果越好)琅锻,k選擇13~18是比較合適的。
(回歸模型的評(píng)價(jià)一般用R^2 值來判斷向胡,R^2越接近1恼蓬,也就是誤差平方和越接近0,擬合效果越好)
上述兩個(gè)不同評(píng)價(jià)標(biāo)準(zhǔn)下的數(shù)值是調(diào)參的過程捷枯,可以由此定下k的值滚秩,從而確定模型。