sklearn調包俠之KNN演算法

weixin_34353714發表於2018-06-26
3629157-5202565eeac207ff.png

天下武功,唯快不破。今天就正式講解如何通過《sklearn小抄》武林祕籍,成為一代宗師調包俠。欲練此功,必先自宮;就算自宮,未必成功;若不自宮,也能成功。傳說江湖(機器學習領域)有兩大派別:一是學術派,該派資歷高,家境好,多為名門世家(學歷高,數學好),重基礎(數學推導和理論知識);一是實踐派,以找人切磋為主(實踐為主),多在切磋中提升能力。《機器學習實戰》系列為學術派,《sklearn調包俠》系列為實踐派,該系列會簡單講解原理,多引用於《機器學習實戰》系列的演算法講解(必要的內力),然後在實操中完成各機器學習演算法。
tips:在本篇中會按小抄詳細過一遍,之後就可能會隨意一些。

KNN演算法原理

計算測試樣本與每個訓練樣本的距離,取前k個距離最小的訓練樣本,最後選擇這k個樣本中出現最多的分類,作為測試樣本的分類。
如圖所示,綠色的為測試樣本,當k取3時,該樣本就屬於紅色類;當k取5時,就屬於藍色類了。所以k值的選擇很大程度影響著該演算法的結果,通常k的取值不大於20。

3629157-d180f5f5f990ace7.png
KNN演算法原理

實戰——糖尿病預測

資料匯入

本資料可在kaggle中進行下載,讀者可以去我的百度雲連結進行下載。
(連結:https://pan.baidu.com/s/1gqaGuQ9kWZFfc-SXbYFDkA 密碼:lxfx)
該資料為csv格式檔案,我們通過pandas讀入:

import numpy as np
import pandas as pd

data = pd.read_csv('data/pima-indians-diabetes/diabetes.csv')
data.head()
3629157-dcb07b473621e699.png

我們簡單看下各欄位的意思:

  • Pregnancies:懷孕的次數
  • Glucose:血漿葡萄糖濃度
  • BloodPressure:舒張壓
  • SkinThickness:肱三頭肌皮膚皺皺厚度
  • Insulin: 胰島素
  • BMI:身體質量指數
  • Dia....:糖尿病血統指數
  • Age:年齡
  • Outcone:是否糖尿病,1為是

我們把資料劃分為特徵和label,前8列為特徵,最後一列為label。

X = data.iloc[:, 0:8]
Y = data.iloc[:, 8]
切分資料集

在模型訓練前,需要將資料集切分為訓練集和測試集(73開或者其它),這裡選擇82開,使用sklearn中model_selection模組中的train_test_split方法。

from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=22)

這裡的test_size為測試集的比例,random_state為隨機種子,這裡可設定任意數字,保證下次執行同樣可以選擇出對應的訓練集和測試集。

資料預處理

這裡沒有對資料進行預處理。

模型訓練與評估

KNN演算法使用sklearn.neighbors模組中的KNeighborsClassifier方法。常用的引數如下:

  • n_neighbors,整數,也就是k值。
  • weights,預設為‘uniform’;這個引數可以針對不同的鄰居指定不同的權重,也就是說,越近可以權重越高,預設是一樣的權重。‘distance’可以設定不同權重。

在sklearn.neighbors還有一個變種KNN演算法,為RadiusNeighborsClassifier演算法,可以使用一定半徑的點來取代距離最近的k個點。
接下來,我們通過設定weight和RadiusNeighborsClassifier,對演算法進行比較。

from sklearn.neighbors import KNeighborsClassifier,RadiusNeighborsClassifier

model1 = KNeighborsClassifier(n_neighbors=2)
model1.fit(X_train, Y_train)
score1 = model1.score(X_test, Y_test)

model2 = KNeighborsClassifier(n_neighbors=2, weights='distance')
model2.fit(X_train, Y_train)
score2 = model2.score(X_test, Y_test)

model3 = RadiusNeighborsClassifier(n_neighbors=2, radius=500.0)
model3.fit(X_train, Y_train)
score3 = model3.score(X_test, Y_test)

print(score1, score2, score3)


#result
#0.714285714286 0.701298701299 0.649350649351

可以看出預設情況的KNN演算法結果最好。

交叉驗證

通過上述結果可以看出:預設情況的KNN演算法結果最好。這個判斷準確麼?答案是不準確,因為我們只是隨機分配了一次訓練和測試樣本,可能下次隨機選擇訓練和測試樣本,結果就不一樣了。這裡的方法為:交叉驗證。我們把資料集劃分為10折,每次用9折訓練,1折測試,就會有10次結果,求十次的平均即可。當然,可以設定cv的值,選擇不同的折數。

from sklearn.model_selection import cross_val_score

result1 = cross_val_score(model1, X, Y, cv=10)
result2 = cross_val_score(model2, X, Y, cv=10)
result3 = cross_val_score(model3, X, Y, cv=10)

print(result1.mean(), result2.mean(), result3.mean())

# result
# 0.712235133288 0.67966507177 0.64976076555

可以看出,還是預設情況的KNN演算法結果最好。

模型調優

無模型調優。

相關文章