資料科學和人工智慧技術筆記 十四、K 最近鄰
十四、K 最近鄰
作者:Chris Albon
譯者:飛龍
確定 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 有三個基本部分
- : 觀測的類別(我們試圖在測試資料中預測的東西)。
- : 觀察的預測因子/ IV /屬性。
-
: 研究者指定的正數。 K 表示最接近特定觀測的觀測數,它定義了“鄰域”。 例如,
K = 2
意味著每個觀測都有一個鄰域,包含最接近它的另外兩個觀測。
想象一下,我們有一個觀測,我們知道它的自變數 ,但不知道它的類別 。 KNN 學習器找到最接近 的K個其他觀測,並使用他們已知的類別,將類別分配給 。
import pandas as pd
from sklearn import neighbors
import numpy as np
%matplotlib inline
import seaborn
這裡我們建立三個變數,test_1
和test_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>
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%!
注:在任何現實世界的例子中,我們都希望將訓練的模型與一些保留的測試資料進行比較。 但由於這是一個玩具示例,我使用了訓練資料。
現在我們已經訓練了我們的模型,我們可以預測班級的任何新觀測, 。 我們現在就這樣做吧!
# 使用 '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 中,RadiusNeighborsClassifier
與KNeighborsClassifier
非常相似,但有兩個引數除外。 首先,在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])