1. 程式人生 > >資料科學和人工智慧技術筆記 十四、K 最近鄰

資料科學和人工智慧技術筆記 十四、K 最近鄰

十四、K 最近鄰

作者:Chris Albon

譯者:飛龍

協議:CC BY-NC-SA 4.0

確定 K 的最佳值

# 載入庫
from sklearn.neighbors import KNeighborsClassifier
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import
GridSearchCV # 載入資料 iris = datasets.load_iris() X = iris.data y = iris.target # 建立標準化器 standardizer = StandardScaler() # 標準化特徵 X_std = standardizer.fit_transform(X) # 擬合 5 個鄰居的 KNN 分類器 knn = KNeighborsClassifier(n_neighbors=5, metric='euclidean', n_jobs=-1).fit(X_std, y) # 建立流水線 pipe = Pipeline(
[('standardizer', standardizer), ('knn', knn)]) # 建立候選值空間 search_space = [{'knn__n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}] # 建立網格搜尋 clf = GridSearchCV(pipe, search_space, cv=5, verbose=0).fit(X_std, y) # 最佳鄰居大小(K) clf.best_estimator_.get_params()['knn__n_neighbors'] # 6

KNN 分類

K 最近鄰分類器(KNN)是一種簡單而強大的分類學習器。

KNN 有三個基本部分

  • y i y_i : 觀測的類別(我們試圖在測試資料中預測的東西)。
  • X i X_i : 觀察的預測因子/ IV /屬性。
  • K K : 研究者指定的正數。 K 表示最接近特定觀測的觀測數,它定義了“鄰域”。 例如,K = 2意味著每個觀測都有一個鄰域,包含最接近它的另外兩個觀測。

想象一下,我們有一個觀測,我們知道它的自變數 x t e s t x_{test} ,但不知道它的類別 y t e s t y_{test} 。 KNN 學習器找到最接近 x t e s t x_{test} 的K個其他觀測,並使用他們已知的類別,將類別分配給 x t e s t x_{test}

import pandas as pd
from sklearn import neighbors
import numpy as np
%matplotlib inline  
import seaborn

這裡我們建立三個變數,test_1test_2是我們的自變數,outcome是我們的因變數。 我們將使用這些資料來訓練我們的學習器。

training_data = pd.DataFrame()

training_data['test_1'] = [0.3051,0.4949,0.6974,0.3769,0.2231,0.341,0.4436,0.5897,0.6308,0.5]
training_data['test_2'] = [0.5846,0.2654,0.2615,0.4538,0.4615,0.8308,0.4962,0.3269,0.5346,0.6731]
training_data['outcome'] = ['win','win','win','win','win','loss','loss','loss','loss','loss']

training_data.head()
test_1 test_2 outcome
0 0.3051 0.5846 win
1 0.4949 0.2654 win
2 0.6974 0.2615 win
3 0.3769 0.4538 win
4 0.2231 0.4615 win

這不是必需的,但因為我們只有三個變數,所以我們可以繪製訓練資料集。 X 軸和 Y 軸是自變數,而點的顏色是它們的類別。

seaborn.lmplot('test_1', 'test_2', data=training_data, fit_reg=False,hue="outcome", scatter_kws={"marker": "D","s": 100})

# <seaborn.axisgrid.FacetGrid at 0x11008aeb8> 

png

scikit-learn庫需要將資料格式化為numpy陣列。 這是重新格式化的程式碼。

X = training_data.as_matrix(columns=['test_1', 'test_2'])
y = np.array(training_data['outcome'])

這是我們的重點。 我們使用“觀測的鄰域是其三個最近的鄰居”的引數來訓練 KNN 學習器。 weights ='uniform'可以當做所用的投票系統。 例如,uniform意味著所有鄰居對觀測的類別進行同等權重的“投票”,而weight ='distance'則告訴學習器根據到我們正在分類的觀測的距離,來調整每個觀測的“投票”。

clf = neighbors.KNeighborsClassifier(3, weights = 'uniform')
trained_model = clf.fit(X, y)

與訓練資料相比,我們訓練的模型有多好?

trained_model.score(X, y)

# 0.80000000000000004 

我們的模型準確率達 80%!

注:在任何現實世界的例子中,我們都希望將訓練的模型與一些保留的測試資料進行比較。 但由於這是一個玩具示例,我使用了訓練資料。

現在我們已經訓練了我們的模型,我們可以預測班級的任何新觀測, y t e s t y_{test} 。 我們現在就這樣做吧!

# 使用 'test_1' 第一個和第二個自變數的值
# 建立一個新觀測,為 .4 和 .6
x_test = np.array([[.4,.6]])

# 將學習者應用於新的未分類的觀測。
trained_model.predict(x_test)

# array(['loss'], dtype=object) 

好哇! 我們可以看到學習器預測的新觀測的類是“輸”。

我們甚至可以檢視學習器分配給每個分類的概率:

trained_model.predict_proba(x_test)

# array([[ 0.66666667,  0.33333333]]) 

根據這個結果,模型預測觀測結果是“輸”的概率約為 67%,“贏”的概率為 33%。 因為觀測有更大的“輸”的概率,所以它預測為這個分類。

  • K 的選擇對建立的分類器有重大影響。
  • K 越大,決策邊界越線性(高偏差和低方差)。
  • 有多種方法可以測量距離,兩種流行的方法是簡單的歐幾里德距離和餘弦相似度。

基於半徑的 KNN 分類器

# 載入庫
from sklearn.neighbors import RadiusNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn import datasets

# 載入資料
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 建立標準化器
standardizer = StandardScaler()

# 標準化特徵
X_std = standardizer.fit_transform(X)

在 scikit-learn 中,RadiusNeighborsClassifierKNeighborsClassifier非常相似,但有兩個引數除外。 首先,在RadiusNeighborsClassifier中,我們需要指定固定區域的半徑,用於確定觀測是否是半徑內的鄰居。 將半徑設定為某個值,最好將其視為任何其他超引數,並在模型選擇期間對其進行調整。 第二個有用的引數是outlier_label,它表示半徑內沒有觀測的觀測的標籤 - 這本身通常可以是識別異常值的有用工具。

# 訓練半徑鄰居分類器
rnn = RadiusNeighborsClassifier(radius=.5, n_jobs=-1).fit(X_std, y)

# 建立兩個觀測
new_observations = [[ 1,  1,  1,  1]]

# 預測兩個觀測的類別
rnn.predict(new_observations)

# array([2])