歡迎關注哈希大數據微信公眾號【哈希大數據】
1 KNN算法基本介紹
K-Nearest Neighbor(k最鄰近分類算法),簡稱KNN,是最簡單的一種有監督的機器學習算法。也是一種懶惰學習算法,即開始訓練僅僅是保存所有樣本集的信息,直到測試樣本到達才開始進行分類決策。
KNN算法的核心思想:要想確定測試樣本屬于哪一類,就先尋找所有訓練樣本中與該測試樣本“距離”最近的前K個樣本,然后判斷這K個樣本中大部分所屬的類型,就認為是該測試樣本的類型。也就是所謂的“近朱者赤近墨者黑”,根據與其最近的k個樣本的類型決定其自身的類型。因此K的確定和測算距離的方式是影響樣本最終分類準確率的重要因素。
常用的測算距離的方法是多維空間的歐式距離法。
其優點為:易于理解,實現簡單,無需估計參數,無需訓練。
缺點為:需要保存所有的訓練數據,內存開銷大,而且訓練數據較多時會導致很高的算法復雜度,訓練數據類型不均勻可能會導致預測準確率下降。
2 標準數據集介紹
我們將采用scikit-learn庫中自帶的鳶尾花數據集進行測試。可以在D:\anaconda python\pkgs\scikit-learn-0.19.0-np113py36_0\Lib\site-packages\sklearn\datasets\data路徑下查看元數據,部分數據實例如下圖(共計150條數據)。
鳶尾花數據集包括鳶尾花的測量數據(特征屬性)以及其所屬的類別。
測量數據特征包括: 萼片長度、萼片寬度、花瓣長度、花瓣寬度
所屬類別有三類: Iris Setosa,Iris Versicolour,Iris Virginica ,用數字0,1,2表示。
#通過python加載鳶尾花數據集
from sklearn import datasetsiris = datasets.load_iris()
# 獲取鳶尾花屬性數據并查看數據特征
iris_X = iris.dataprint(iris.data.shape)
# 獲取鳶尾花類別數據
iris_y = iris.target
拆分****數據集****為訓練數據和測試數據:
# 方法一:使用python的train_test_split庫進行數據集拆分
iris_train_X , iris_test_X, iris_train_y ,iris_test_y = train_test_split(iris_X, iris_y, test_size=0.2,random_state=0)
# 方法二:隨機選擇部分數據(20%)作為測試集(適用于少量數據)
np.random.seed(0)
select = np.random.permutation(len(iris_y))
iris_X_train = iris_X[select[:-30]]
iris_y_train = iris_y[indices[:-30]]
iris_X_test = iris_X[indices[-30:]]
iris_y_test = iris_y[indices[-30:]]
3 KNN算法python實現
在此我們將直接使用python的scikit-learn 庫中的 neighbors.KNeighborsClassifier類,通過KNN算法對測試集中鳶尾花進行分類。
首先進行類的初始化
knn =KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=1, n_neighbors=5, p=2, weights='uniform')
參數介紹
l n_neighbors=5,就是KNN中的k,默認為5。
l weights='uniform',是距離計算中使用的權重,默認為'uniform' 是等權加權,也可以選'distance'是按照距離的倒數進行加權,也可以自己設置其他加權方式。(給距離增加權重,如果越近的距離權重越高,能在一定程度上避免樣本分布不平均的問題)
l metric='minkowski'、p=2,表示采用的是歐氏距離的計算。
計算距離的方式默認為閔可夫斯基距離,是一組距離的定義。
兩個n維變量a(x11,x12,…,x1n)與 b(x21,x22,…,x2n)間的閔可夫斯基距離:
。
其中p=1時,為曼哈頓距離;p=2時,為歐氏距離;p→∞時,為切比雪夫距離。根據變參數p的不同,閔氏距離可以表示一類的距離。
l algorithm='auto',是分類時采取的算法,有'brute'、'kd_tree'和'ball_tree',三種默認按照數據特征從這三種中選擇最合適的。其中kd-tree基于歐氏距離的特性可以快速處理20維以內的數據集,balltree基于更一般的距離特性,適合處理高維數據。(三種算法的具體實現之后會進行詳細介紹)
l leaf_size=30,是kd_tree或ball_tree生成的樹的樹葉(二叉樹中未分枝的節點)的大小。
l n_job=1,是并行計算的線程數量,默認是1,輸入-1則設為CPU的內核數。
# ****提供數據集進行訓練
knn.fit(iris_X_train, iris_y_train)
# ****預測測試集數據鳶尾花類型
predict_result = knn.predict(iris_X_test)print(predict_result)
# ****計算預測的準確率
print(knn.score(iris_X_test, iris_y_test))
4 完整源碼及輸出結果
!/usr/bin/python
-- coding: utf-8 --
KNN調用
import numpy as np
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn import datasets
導入鳶尾花數據并查看數據特征
iris = datasets.load_iris()
print('數據量',iris.data.shape)
拆分屬性數據
iris_X = iris.data
拆分類別數據
iris_y = iris.target
方法一:拆分測試集和訓練集,并進行預測
iris_train_X , iris_test_X, iris_train_y ,iris_test_y = train_test_split(iris_X, iris_y, test_size=0.2,random_state=0)
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(iris_train_X, iris_train_y)
knn.predict(iris_test_X)
方法二:拆分測試集和訓練集
np.random.seed(0)
permutation隨機生成0-150的系列
indices = np.random.permutation(len(iris_y))
iris_X_train = iris_X[indices[:-30]]
iris_y_train = iris_y[indices[:-30]]
iris_X_test = iris_X[indices[-30:]]
iris_y_test = iris_y[indices[-30:]]
knn = KNeighborsClassifier()
提供訓練集進行順利
knn.fit(iris_X_train, iris_y_train)
預測測試集鳶尾花類型
predict_result = knn.predict(iris_X_test)
print('預測結果',predict_result)
計算預測的準確率
print('預測準確率',knn.score(iris_X_test, iris_y_test))
輸出結果
"D:\anaconda python\python3.6.exe" D:/machine_learning/coding/knntest.py
數據量 (150, 4)
預測結果 [0 2 0 0 2 0 2 1 1 1 2 2 2 1 0 1 2 2 0 1 1 2 1 0 0 0 2 1 2 0]
預測準確率 0.933333333333
Process finished with exit code 0