統計學習方法 3K近鄰法

2021-09-12 14:16:33 字數 3062 閱讀 8816

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近鄰法是這樣乙個過...