機器學習:K近鄰(KNN)

K近鄰(K-Nearest Neighor,KNN)學習是一種常用的監督學習方法,它的思想非常簡單:給定測試樣本,基於某種距離度量找出訓練集中與其最靠近的K個訓練樣本,然後基於這K個鄰居的信息進行預測。KNN是一種基本的機器學習算法。KNN既可以用作分類,也可以用作迴歸。KNN做分類預測時,一般是選擇多數表決法,即訓練集裏和預測的樣本特徵最近的K個樣本,預測爲裏面有最多類別數的類別。而KNN做迴歸時,一般是選擇平均法,即最近的K個樣本的樣本輸出的平均值作爲迴歸預測值。

一般通過交叉驗證選擇最優的K值。對於距離的度量方式,最常見的是歐氏距離:
在這裏插入圖片描述
KNN的主要優點有:
1) 理論成熟,思想簡單,既可以用來做分類也可以用來做迴歸
2) 可用於非線性分類
3) 訓練時間複雜度比支持向量機之類的算法低,僅爲O(n)
4) 和樸素貝葉斯之類的算法比,對數據沒有假設,準確度高,對異常點不敏感
5) 由於KNN方法主要靠周圍有限的鄰近的樣本,而不是靠判別類域的方法來確定所屬類別的,因此對於類域的交叉或重疊較多的待分樣本集來說,KNN方法較其他方法更爲適合
6)該算法比較適用於樣本容量比較大的類域的自動分類,而那些樣本容量較小的類域採用這種算法比較容易產生誤分
    
KNN的主要缺點有:
1)計算量大,尤其是特徵數非常多的時候
2)樣本不平衡的時候,對稀有類別的預測準確率低
3)使用懶散學習方法,基本上不學習,導致預測時速度比起邏輯迴歸之類的算法慢
4)相比決策樹模型,KNN模型可解釋性不強

# K近鄰
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt

# 隨機生成數據
x, y = make_classification(n_clusters_per_class=1, n_samples=500, n_redundant=0, n_features=2, random_state=14)
# 數據劃分
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=2)

# 畫出原始數據
plt.scatter(x[:, 0], x[:, 1], c=y)
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('Orical Data')
plt.show()

# 參數n_neighbor的選擇
n_neighbors = [3, 5, 7, 9, 11]

# 平均值
accuracy_list = []
# 方差
accuracy_std = []

# 找到最優參數
for n in n_neighbors:
    knn = KNeighborsClassifier(n_neighbors=n)
    scores = cross_val_score(knn, x_train, y_train, cv=5)
    accuracy_list.append(scores.mean())
    accuracy_std.append(scores.std())
    
# 可視化
plt.grid()
plt.plot(n_neighbors, accuracy_list)
plt.scatter(n_neighbors, accuracy_list, c='r')
plt.errorbar(n_neighbors, accuracy_list, accuracy_std, c='g')
plt.xlabel('n')
plt.ylabel('accuracy')
plt.show()

# 由上圖可以看出n_neighbor最優值爲3
knn = KNeighborsClassifier(n_neighbors=3).fit(x_train, y_train)
y_pred = knn.predict(x_test)

print('tesing accuracy:', accuracy_score(y_pred, y_test))

# 畫出訓練集樣本點
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)

# 畫出測試集樣本點
for i in range(len(x_test)):
    if y_pred[i] == 0:
        plt.scatter(x_test[i, 0], x_test[i, 1], c='r')  # 標籤爲0的樣本點
    else:
        plt.scatter(x_test[i, 0], x_test[i, 1], c='g')  # 標籤爲1的樣本點

plt.show()

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章