2023年由cover和hart提出。k近鄰法假設給定乙個訓練資料集,其中的例項類別已定。分類時,對新的例項,根據其k個最近鄰的訓練例項的類別,通過多數表決等方式進行**。
k近鄰法實際上利用訓練資料集對特徵向量空間進行劃分,並作為其分類的「模型」。
k近鄰法三要素:k值得選擇、距離度量和分類決策規則。
lp距離、歐式距離、曼哈頓距離:
由不同的距離度量所確定的最近鄰點是不同的。
多數表決:由輸入例項的k個鄰近的訓練例項中的多數類決定輸入例項的類。等價於經驗風險最小化
最簡單的實現:線性掃瞄(linear scan)。但計算非常耗時。→引出kd樹(kd tree)方法。
kd樹是一種對k維空間中的例項點進行儲存以便對其進行快速檢索得樹形資料結構。(kd樹是二叉樹,表示對k維空間的乙個劃分)
構造kd樹相當於不斷地用垂直於座標軸的超平面將k維空間切分,構成一系列的k維超矩形區域。kd樹的每個節點對應於乙個k維超矩形區域。
給定乙個目標點,搜尋其最近鄰。
首先,找到包含目標點的葉結點;然後,從該葉結點出發,依次回退到父結點;不斷查詢與目標點最近鄰的結點,當確定不可能存在更近的結點時終止。
這樣搜尋就被限制在空間的區域性區域上,效率大為提高。
《統計學習方法》李航def calcdist(x1, x2):
'''計算兩個樣本點向量之間的距離
使用的是歐氏距離,即 樣本點每個元素相減的平方 再求和 再開方
:param x1:向量1
:param x2:向量2
:return:向量之間的歐式距離
'''return np.sqrt(np.sum(np.square(x1 - x2)))
#馬哈頓距離計算公式
# return np.sum(x1 - x2)
def getclosest(traindatamat, trainlabelmat, x, topk):
'''**樣本x的標記。
獲取方式通過找到與樣本x最近的topk個點,並檢視它們的標籤。
查詢裡面佔某類標籤最多的那類標籤
(書中3.1 3.2節)
:param traindatamat:訓練集資料集
:param trainlabelmat:訓練集標籤集
:param x:要**的樣本x
:param topk:選擇參考最鄰近樣本的數目(樣本數目的選擇關係到正確率,詳看3.2.3 k值的選擇)
:return:**的標記
'''#建立乙個存放向量x與每個訓練集中樣本距離的列表
#列表的長度為訓練集的長度,distlist[i]表示x與訓練集中第
## i個樣本的距離
distlist = [0] * len(trainlabelmat)
#遍歷訓練集中所有的樣本點,計算與x的距離
for i in range(len(traindatamat)):
#獲取訓練集中當前樣本的向量
x1 = traindatamat[i]
#計算向量x與訓練集樣本x的距離
curdist = calcdist(x1, x)
#將距離放入對應的列表位置中
distlist[i] = curdist
#對距離列表進行排序
#argsort:函式將陣列的值從小到大排序後,並按照其相對應的索引值輸出
#例如:
# >>> x = np.array([3, 1, 2])
# >>> np.argsort(x)
# array([1, 2, 0])
#返回的是列表中從小到大的元素索引值,對於我們這種需要查詢最小距離的情況來說很合適
#array返回的是整個索引值列表,我們通過[:topk]取列表中前topl個放入list中。
#----------------優化點-------------------
#由於我們只取topk小的元素索引值,所以其實不需要對整個列表進行排序,而argsort是對整個
#列表進行排序的,存在時間上的浪費。字典有現成的方法可以只排序top大或top小,可以自行查閱
#對**進行稍稍修改即可
#這裡沒有對其進行優化主要原因是knn的時間耗費大頭在計算向量與向量之間的距離上,由於向量高維
#所以計算時間需要很長,所以如果要提公升時間,在這裡優化的意義不大。(當然不是說就可以不優化了,
#主要是我太懶了)
topklist = np.argsort(np.array(distlist))[:topk] #公升序排序
#建立乙個長度時的列表,用於選擇數量最多的標記
#3.2.4提到了分類決策使用的是投票表決,topk個標記每人有一票,在陣列中每個標記代表的位置中投入
#自己對應的地方,隨後進行唱票選擇最高票的標記
labellist = [0] * 10
#對topk個索引進行遍歷
for index in topklist:
#trainlabelmat[index]:在訓練集標籤中尋找topk元素索引對應的標記
#int(trainlabelmat[index]):將標記轉換為int(實際上已經是int了,但是不int的話,報錯)
#labellist[int(trainlabelmat[index])]:找到標記在labellist中對應的位置
#最後加1,表示投了一票
labellist[int(trainlabelmat[index])] += 1
#max(labellist):找到選票箱中票數最多的票數值
#labellist.index(max(labellist)):再根據最大值在列表中找到該值對應的索引,等同於**的標記
return labellist.index(max(labellist))
knn.py
《統計學習方法》筆記(3) k近鄰
k近鄰 knn 是相對基本的機器學習方法,特點是不需要建立模型,而是直接根據訓練樣本的資料對測試樣本進行分類。1 k近鄰的演算法?演算法對測試樣本進行分類的一般過程如下 1 根據給定的k值,搜尋與測試樣本距離最近的k個訓練樣本 2 統計k個樣本對應的每種分類數量 3 根據每種分類的數量投票決定樣本點...
機器學習 統計學習方法 3 k近鄰法 筆記
注 本章只介紹分類問題的k近鄰演算法。t t t 其中,xi x rn x i in mathcal subset r n xi x rn為例項的特徵變數,yi y y i in mathcal yi y 為例項的類別,i 1 2,3 n i 1,2,3,n i 1,2,3,n 例項特徵變數 xxx...
統計學習方法 k近鄰法
k近鄰法 knn 是一種基本的分類與回歸方法 分類這種需求,滲透到我們生活的方方面面 分類演算法可以幫助我們完成這些繁瑣的操作,並根據我們的要求不斷修正分類結果。分類演算法其實蠻多的,這裡順著書本順序,詳細講解knn演算法,再與k means k means 演算法進行簡單對比。k近鄰法是這樣乙個過...