k最近鄰(knn,k-nearestneighbor)分類演算法
,所謂k最近鄰,就是k個最近的鄰居的意思,說的是每個樣本都可以用它最接近的k個鄰居來代表。
用的是近朱者赤近墨者黑的思想。
knn沒有顯式的學習過程,也就是說沒有訓練階段,資料集事先已有了分類和特徵值,待收到新樣本後直接進行處理。
思路是:如果乙個樣本在特徵空間中的k個最鄰近的樣本中的大多數屬於某乙個類別,則該樣本也劃分為這個類別。knn演算法中,所選擇的鄰居都是已經正確分類的物件。該方法在定類決策上只依據最鄰近的乙個或者幾個樣本的類別來決定待分樣本所屬的類別。
我們要確定綠點屬於哪個顏色(紅色或者藍色),要做的就是選出距離目標點距離最近的k個點,看這k個點的大多數顏色是什麼顏色。當k取3的時候,我們可以看出距離最近的三個,分別是紅色、紅色、藍色,因此得到目標點為紅色。
1)計算測試資料與各個訓練資料之間的距離;
2)按照距離的遞增關係進行排序;
3)選取距離最小的k個點;
4)確定前k個點所在類別的出現頻率;
5)返回前k個點**現頻率最高的類別作為測試資料的**分類
input: 訓練資料data、待**樣本x、k
ouput:待**樣本所屬類別y
# 1. 計算待**樣本和所有訓練資料的距離/相似度
d =
idx = 0
for train_x in data.x:
# a. 使用歐式距離公式計算兩個樣本之間的距離
distince = calc_distince(train_x, x)
# b. 距離儲存
idx += 1
# 2. 從所有訓練資料中,獲取距離最近/相似度最大的k個鄰近樣本
sorted(d) # 排序,預設為公升序
n = d[:k] # 獲取這個距離最近的k個
# 3. 將這k個鄰近樣本**現數目最多的類別作為當前待**樣本的**值。
# a. 統計各個類別出現的次數
label_2_count = {}
for distince,idx in n:
label = data.y[idx]
label_2_count[label] = label_2_count.get(label,0) + 1
# b. 從統計結果中獲取出現次數最多的那個類別
max_count = 0
y = none
for label, count in label_2_count.items():
if count > max_count:
y = label
count = max_count
return y
如上**的缺陷:消耗空間大,需要儲存所有的距離嗎,是不是可以直接儲存前k小的距離就可以,在儲存距離的時候用插入法,從小到大排序,如果有比最後乙個數小的距離,則插入到列表,刪除最後最後乙個資料。
計算開銷大,分類效率低; -->解決方案:kdtree
k值難以確認,不同近鄰樣本數,對分類準確程度影響較大;(k過大->欠擬合, k過小->過擬合) --> 一般情況20~50之間居多,具體的會通過gridsearchcv來選擇
樣本向量以及距離的度量公式之間的選擇
1.採用m個樣本中的n個屬性進行劃分a、kdtree是如何解決knn的缺陷的2.分別計算n個屬性特徵的方差,進行從大到小的排序
3.選取方差最大的屬性作為劃分,選取樣本的中位數點nkv,以此樣本點為根節點,將該屬性特徵小於nvk的樣本的放在左子樹上,大於的放在右子樹上。
4.根據方差第二大的屬性進行左,右子樹的劃分,同上述過程。
5.迴圈迭代,資料集劃分完畢
kdtree解決了knn中在大資料量的情況下,求解k個近鄰樣本計算量過大的問題。在構建kdtree的時候,選擇的是方差最大的特徵屬性的特徵屬性中值作為資料分割點,將資料分割為左右兩個資料子集,然後再左右兩個資料子集中繼續按照這種方式進行劃分;這樣構建出來的kdtree在查詢資料的時候可以保障盡可能少的搜尋分支(因為方差大表示資料比較離散)
b、除了kdtree之外,還有沒有其他方式來解決該問題?
balltree
c、kdtree除了可以用於knn解決knn的問題外,kdtree還可以應用到哪些場景?
kdtree的主要功能實際上是加速資料的檢索。
eg:人臉識別(人臉打卡、人臉支付....)
聊天機械人(檢索式)
from collections import counter
import numpy as np
class knnscratch(object):
def fit(self, x_train, y_train):
self.x_train = x_train
self.y_train = y_train
def predict_once(self, x_test, k): #**單個樣本
lst_distance =
lst_predict =
for i in xrange(len(self.x_train)):
# euclidean distance
distance = np.linalg.norm(x_test - self.x_train[i, :])
lst_distance = sorted(lst_distance)
for i in xrange(k):
idx = lst_distance[i][1]
return counter(lst_predict).most_common(1)[0][0]
def predict(self, x_test, k): # 批量**
lst_predict =
for i in xrange(len(x_test)):
return lst_predict
if __name__ == '__main__':
x_train = np.array([[1, 1, 1], [2, 2, 2], [10, 10, 10], [13, 13, 13]])
y_train = ['aa', 'aa', 'bb', 'bb']
x_test = np.array([[3, 2, 4], [9, 13, 11]])
knn = knnscratch()
knn.fit(x_train, y_train)
print knn.predict_once(x_test[0], 2)
# aa
print knn.predict(x_test, 2)
# ['aa', 'bb']
#-*- coding: utf-8 -*-
from sklearn import neighbors
from sklearn import datasets
from sklearn.model_selection import train_test_split
# 載入資料
iris = datasets.load_iris()
# 資料劃分
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.5, random_state=2)
# 模型載入
knn = neighbors.kneighborsclassifier()
knn.fit(x_train, y_train)
# 模型評估
print("訓練集準確率:",knn.score(x_train,y_train))
print("測試集準確率:",knn.score(x_test,y_test))
# **
predicted = knn.predict(x_test)
print(predicted)
Python實現KNN演算法
from numpy import import operator def creatdataset group array 1.0,1.1 1.0,1.0 0,0 0,0.1 lables a a b b return group,lables def classify0 inx,dataset,...
python實現knn演算法
importnumpyasnp importoperator defcreatedataset group np.array 1.0 1.1 1.0 1.0 0.0 0.0 0.0 0.1 labels a a b b returngroup,labels 分類演算法 inx待分類的點 defcla...
python實現KNN演算法
具體 如下 import numpy as np import matplotlib.pyplot as plt class myknn def init self,k self.k k def compute self,x train,y train,x test dist i 0 計算歐式距離 ...