KNN(K-Nearest Neighbor)K-近鄰演算法

K-近鄰演算法(k-nearest neighbors,縮寫為KNN)屬於監督式學習,用於分類問題。透過樣本與樣本之間的距離進行分類,找尋未知分類元素的最接近的K個樣本,這K個樣本中的最多分類,就是這個元素的分類。

K-近鄰演算法使用距離進行分類,計算資料的距離類似計算座標點的距離,資料的每個欄位內容需要是數值,無法使用字串。若輸入資料欄位內容出現字串,可以選擇刪除該欄位或使用前一章決策樹介紹的LabelEncoder功能,將字串轉換成數值。

6-1 K-近鄰演算法的運作過程

K-近鄰演算法的運作過程如下。

Step1)計算所有訓練資料(已知分類)的距離。

Step2)找出測試資料(未知分類)最接近的K個訓練資料(已知分類)。

Step3)找出這K個訓練資料(已知分類)最多出現的分類,就是測試資料(未知分類)的分類。

假設有六個訓練資料(已知分類)分別為點(3,5),(4,4),(5,3),(3,2)是同一組(代號為X),左下方的點(2,3),(2,2)為同一組(代號為○),未知分類點(2.5, 2.5)不知道所屬分類,假設K=3,最接近未知分類點(2.5, 2.5)的三個點,有兩個是○組,一個是X組,所以未知分類點(2.5, 2.5)會被分類到○組。

6-2 使用sklearn實作K-近鄰演算法

使用sklearn實作K-近鄰演算法,將每筆訓練資料輸入K-近鄰演算法模型就可計算出每筆訓練資料的距離,接著使用測試資料評估此模型。使用sklearn實作K-近鄰演算法的步驟如下。

(1)輸入資料

train_X , test_X , train_y , test_y = train_test_split(X, y,test_size=0.2,random_state=42)

(2)建立與訓練模型

model = KNeighborsClassifier(n_neighbors=3)

model.fit(train_X, train_y)

(3)使用模型進行預測

pred_y = model.predict(test_X)

(4)使用正確率與混淆矩陣比較目標值與預測值的差異

print(model.score(test_X, test_y))

print(confusion_matrix(test_y, pred_y))

6-3 K-近鄰演算法模型實作範例

6-3-1 使用K-近鄰演算法預估鳶尾花種類

(6-3-1使用K-近鄰演算法預估鳶尾花種類.ipynb)

使用花瓣長度、花瓣寬度、萼片長度、萼片寬度經由K-近鄰演算法模型預估鳶尾花種類,本範例測資來自於sklearn.datasets的函式load_iris下載鳶尾花資料,匯入程式如下。

from sklearn.datasets import load_iris

iris = load_iris()

Step1)匯入資料

從sklearn.datasets的函式load_iris下載鳶尾花資料,並且轉換成DataFrame,當成K-近鄰演算法模型的訓練資料與測試資料。

程式說明

第1到9行:匯入函式庫。

第10行:設定繪圖的中文字型。

第11行:使用函式load_iris匯入鳶尾花資料集到變數iris。

第12行:讀取鳶尾花資料集的data,以鳶尾花資料集的陣列feature_names為行名稱轉換成DataFrame,當成模型的獨立變數到變數X。

第13行:讀取鳶尾花資料集的target,以Species為行名稱轉換成DataFrame,當成模型的相依變數到變數y。

第14行:以行為主方式串接X與y,使用變數df參考到此結果。

第15行:使用函式head顯示變數df前五筆資料。

Step2)檢查資料

要將資料輸入機器學習模型前,先要檢查資料是否有空值、資料筆數、欄位名稱、第一筆資料內容、第一筆預測目標值等。

程式說明

第1行:使用函式isnull檢查資料是否有空值,如果欄位有空值就會回傳True,轉換成數值1,加總結果就會是空值個數。

第2行:使用shape顯示資料的筆數。

第3行:函式keys顯示欄位名稱。

第4行:iloc顯示指定範圍的資料內容。

第5行:使用[]顯示指定欄位的資料內容。

Step3)分析資料、建立訓練資料與測試資料

(1)在進行機器學習之前,先將英文欄位名稱翻譯成中文

程式說明

第1到5行:使用函式rename,重新命名資料集的行名稱,「sepal length (cm)」對應「萼片長(公分)」,「sepal width (cm)」對應「萼片寬(公分)」,「petal length (cm)」對應「花瓣長(公分)」,「petal length (cm)」對應「花瓣寬(公分)」,「Species」對應「種類」,設定inplace為True,表示不建立新的資料集,直接修改原來的資料集。

第6到11行:設定字典irdict,「0」對應到「山鳶尾」,「1」對應到「染色鳶尾」,「2」對應到「維吉尼亞鳶尾」,使用函式map將字典irdict套用到「種類」欄位,將數值0到2轉換成鳶尾花中文名稱。

第12行:使用函式head顯示變數df前五筆資料。

第13行:使用函式groupby計算各種類鳶尾花個數。

(2)使用seaborn函式庫分析任兩欄位的資料分布情形

程式說明

第1行:使用函式figure建立新圖片。

第2行:使用函式pairplot繪製資料表df的所有欄位兩兩之間的關係,設定hue為「種類」,表示不同「種類」設定不同顏色,設定markers為「"o", "X", "D"」,表示第一個種類以「○」標示,第二個種類以「X」標示,第三個種類以「◇」標示,因為資料表df有4個欄位(去除「種類」欄位),總共會有16張小圖表示兩兩之間關係。

第3行:使用函式show顯示圖片。

第4行:使用函式figure建立新圖片。

第5行:使用函式pairplot繪製資料表df的所有欄位兩兩之間的關係,設定hue為「種類」,表示不同「種類」設定不同顏色,設定markers為「"o", "X", "D"」,表示第一個種類以「○」標示,第二個種類以「X」標示,第三個種類以「◇」標示,設定vars為「"萼片長(公分)","花瓣長(公分)"」,只看這兩個欄位,總共會有4張小圖表示兩兩之間關係。

第6行:使用函式show顯示圖片。

(3)建立訓練資料與測試資料

程式說明

第1行:設定X為資料集df欄位「萼片長(公分)」、「萼片寬(公分)」、「花瓣長(公分)」、「花瓣寬(公分)」。

第2行:設定y為資料集df欄位「種類」。

第3行:使用函式train_test_split,以X為獨立變數,y為相依變數,隨機挑選出訓練集與測試集,原始資料的百分之70為訓練集,剩餘百分之30為測試集。

第4到5行:使用shape顯示訓練資料與測試資料的筆數。

Step4)建立與訓練模型

使用KNeighborsClassifier建立K-近鄰演算法模型,並輸入訓練資料進行訓練。

程式說明

第1行:建立K-近鄰演算法模型,設定n_neighbors為3,表示K值等於3。

第2行:輸入訓練資料train_X與train_y到模型進行訓練。

Step5)模型預測

使用測試資料進行模型預測,並計算模型的正確率與測試資料的混淆矩陣。

程式說明

第1行:以test_X為輸入,使用函式predict進行預測,變數pred_y參考到此結果。

第2行:使用函式accuracy_score計算正確率。

第3行:計算測試資料的混淆矩陣。

發現本範例正確率達100%,表示使用K-近鄰演算法模型可以完美分類三種鳶尾花。

Step6) 找出最適合的K值

本範例已知只有三種鳶尾花,所以K值一定選用3。當不確定K值時,可以使用迴圈測試每一個K值,每次輸入訓練資料到K-近鄰演算法模型,再使用測試資料進行估算正確率,就可以找到正確率最高的K值。

程式說明

第1行:宣告accuracy為空陣列。

第2到6行:使用for迴圈計算不同n_neighbors對KNeighborsClassifier的影響,迴圈變數i由3到49每次遞增1。

第3行:將此迴圈變數i設定給n_neighbors,讓KNeighborsClassifier的n_neighbors由3到49每次遞增1,變數model參考到此結果。

第4行:輸入訓練資料train_X與train_y到模型進行訓練。

第5行:以test_X為輸入,使用函式predict進行預測,變數pred_y參考到此結果。

第6行:使用函式accuracy_score計算正確率,將每種n_neighbors的正確率儲存到陣列accuracy。

第7行:設定變數i為3到到49,每次遞增1。

第8行:畫出X軸為變數i與Y軸為正確率(陣列accuracy)的折線圖。

第9行:使用函式show顯示折線圖到螢幕上。

6-3-2使用K-近鄰演算法預估蘑菇是否有毒

(6-3-2使用K-近鄰演算法預估蘑菇是否有毒.ipynb)

使用蘑菇的各種外觀屬性、顏色、氣味等資訊,經由K-近鄰演算法模型預估蘑菇是否有毒。本範例測資來自於Kaggle網站,可以從以下網址下載mushrooms.csv。 https://www.kaggle.com/uciml/mushroom-classification

Step1)匯入資料

匯入mushrooms.csv並且轉換成DataFrame,當成K-近鄰演算法模型的訓練資料與測試資料。

程式說明

第1到9行:匯入函式庫。

第10行:匯入mushrooms.csv並轉換成DataFrame,變數df參考到此結果。

第11行:使用函式head顯示變數df前五筆資料。

Step2)檢查資料

將資料輸入機器學習模型前,先要檢查資料是否有空值、資料筆數、欄位名稱、第一筆資料內容、第一筆目標值等。

程式說明

第1行:使用函式isnull檢查資料是否有空值,如果欄位有空值就會回傳True,轉換成數值1,加總結果就會是空值個數。

第2行:使用shape顯示資料的筆數。

第3行:函式keys顯示欄位名稱。

第4行:iloc顯示指定範圍的資料內容。

第5行:使用[]顯示指定欄位的資料內容。

Step3)建立訓練資料與測試資料

(1)字串轉數值

程式說明

第1到3行:使用LabelEncoder與迴圈,將所有字串資料轉換成數值。

第4行:使用函式head顯示變數df前五筆資料。

(2)建立訓練資料與測試資料

程式說明

第1行:設定X為資料集df刪除欄位「class」。

第2行:設定y為資料集df欄位「class」。

第3行:使用函式train_test_split,以X為獨立變數,y為相依變數,隨機挑選出訓練集與測試集,原始資料的百分之80為訓練集,剩餘百分之20為測試集,設定random_state為42。

第4到6行:使用StandardScaler標準化輸入資料train_X與test_X,讓平均值為0,標準差平方為1。

第7到8行:使用shape顯示訓練資料與測試資料的筆數。

Step4)建立與訓練模型

使用KNeighborsClassifier建立K-近鄰演算法模型,並輸入訓練資料進行訓練。

程式說明

第1行:建立K-近鄰演算法模型,設定n_neighbors為2,表示K值等於2。

第2行:輸入訓練資料train_X_std與train_y到模型進行訓練。

Step5)模型預測

使用測試資料進行模型預測,並計算模型的正確率與測試資料的混淆矩陣。

程式說明

第1行:以test_X_std為輸入,使用函式predict進行預測,變數pred_y參考到此結果。

第2行:使用函式accuracy_score計算正確率。

第3行:計算測試資料的混淆矩陣。