KNN(K近鄰)算法
前言
因爲自己準備數據集耗時耗力還不一定真實,所以小編在此採用scikit-learn數據集
什麼是KNN?
如果一個樣本在特徵空間中的k個最相似(即特徵空間中最鄰近)的樣本中的大多數屬於某一個類別,則該樣本也屬於這個類別。
小編的理解是:根據你的“鄰居”判斷你的類別
k近鄰(KNN)算法是一種簡單,易於實現的有監督的機器學習算法,可用於解決分類和迴歸問題。
舉例
如上圖所示,我們將打鬥鏡頭、接吻鏡頭當作你的特徵值,那麼電影類型就是你的目標值。那麼對於電影名稱爲“?”,我們怎麼判斷電影類型?
如果在表中在添加如下一列“與目標電影的距離”,我們可以發現電影名稱“?”與“He‘s not Really into dues”的距離最近,那麼我們就能以此爲依據判斷“?”的電影類型了。
這個距離怎麼計算呢?
兩個樣本的距離可以通過如下公式計算,又叫歐式距離。
比如說,a(a1,a2,a3),b(b1,b2,b3)
那麼對於上述示例而言,以“California Man”舉例,其距離爲:
細心的讀者一定可以發現,如果根號下兩個平方數值差距特別大,(例:根號((100-3)^2 +(14-13)^2),我們會發現這個距離是被(100-3)這部分數值所主導
如何避免這個問題?
KNN算法需要進行標準化!!!
當然,KNN算法中K的取值也會影響最終分類的結果
假設k=1,則取距離最近的1個電影類型來判斷“?”的類型
假設k=2,則取距離最近的2個電影類型來判斷“?”的類型
假設k=3,則取距離最近的3個電影類型來判斷“?”的類型
…
但是這個k不是越大越好
知識儲備
sklearn k-近鄰算法API:
sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm=‘auto’)
- n_neighbors:int,可選(默認= 5),k_neighbors查詢默認使用的鄰居數
- algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可選用於計算最近鄰居的算法:‘ball_tree’將會使用BallTree,‘kd_tree’將使用 KDTree。‘auto’將嘗試根據傳遞給fit方法的值來決定最合適的算法。(不同實現方式影響效率)
代碼演示
這是一個簡單的KNN算法流程
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
def knn_alg():
'''
classfied iris
:return:None
'''
# 加載數據集
iris_data = load_iris()
#將數據劃分爲訓練集和測試集
#test_size是劃分的比例
x_train,x_test,y_train,y_test = train_test_split(iris_data["data"],iris_data["target"],test_size=0.25)
#對特徵工程進行標準化
std = StandardScaler()
#對測試集和訓練集的特徵值進行標準化
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)
#進行KNN算法流程
knn =KNeighborsClassifier()
#構造這個模型
knn.fit(x_train,y_train)
#得出預測結果
y_predict = knn.predict(x_test)
print("預測結果", y_predict)
#得出準確率
score = knn.score(x_test,y_test)
print("準確率",score)
return None
if __name__ == "__main__":
knn_alg();
優化
前面小編說過K的取值也會影響KNN算法,所以我們可以對以上流程再做一部分改進。
網格搜索
通常情況下,有很多參數是需要手動指定的(如k-近鄰算法中的K值),這種叫超參數。但是手動過程繁雜,所以需要對模型預設幾種超參數組合。每組超參數都採用交叉驗證來進行評估。最後選出最優參數組合建立模型。
GridSearchCV
sklearn.model_selection.GridSearchCV(estimator,param_grid=None,cv=None)對估計器的指定參數值進行詳盡搜索
- estimator:估計器對象
- param_grid:估計器參數(dict){“n_neighbors”:[1,3,5]}
- cv:指定幾折交叉驗證
- fit:輸入訓練數據
- score:準確率
結果分析: - best_score_:在交叉驗證中測試的最好結果
- best_estimator_:最好的參數模型
- cv_results_:每次交叉驗證後的測試集準確率結果和訓練集準確率結果
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
def knn_alg():
'''
classfied iris
:return:None
'''
# 加載數據集
iris_data = load_iris()
#將數據劃分爲訓練集和測試集
#test_size是劃分的比例
x_train,x_test,y_train,y_test = train_test_split(iris_data["data"],iris_data["target"],test_size=0.25)
#對特徵工程進行標準化
std = StandardScaler()
#對測試集和訓練集的特徵值進行標準化
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)
#進行KNN算法流程
knn =KNeighborsClassifier()
# #構造這個模型
# knn.fit(x_train,y_train)
#
# #得出預測結果
# y_predict = knn.predict(x_test)
# print("預測結果", y_predict)
#
# #得出準確率
# score = knn.score(x_test,y_test)
# print("準確率",score)
# 構造一些參數的值進行搜索
param = {"n_neighbors": [3, 5, 10]}
# 進行網格搜索
gc = GridSearchCV(knn, param_grid=param, cv=2)
gc.fit(x_train, y_train)
# 預測準確率
print("在測試集上準確率:", gc.score(x_test, y_test))
print("在交叉驗證當中最好的結果:", gc.best_score_)
print("選擇最好的模型是:", gc.best_estimator_)
print("每個超參數每次交叉驗證的結果:", gc.cv_results_)
return None
if __name__ == "__main__":
knn_alg();