機(jī)器學(xué)習(xí)實(shí)戰(zhàn)筆記-KNN(k近鄰法)篇

本文是作者學(xué)習(xí)機(jī)器學(xué)習(xí)KNN的學(xué)習(xí)記錄與筆記,文章會(huì)從簡(jiǎn)介、kd樹算法、代碼實(shí)現(xiàn)等幾個(gè)方面展開。本文的目的是為了記錄作者的學(xué)習(xí)歷程以及進(jìn)行總結(jié),為之后的復(fù)習(xí)做準(zhǔn)備。當(dāng)然,如果同時(shí)能夠幫組到同樣在入門機(jī)器學(xué)習(xí)的小伙伴當(dāng)然就更好了。

一、簡(jiǎn)介

k近鄰法是一種基本分類與回歸方法,這篇文章只討論分類問題中的k近鄰法。k近鄰法的輸?為實(shí)例的特征向量,對(duì)應(yīng)于特征空間的點(diǎn);輸出為實(shí)例的類別,可以取多類。k近鄰法假設(shè)給定?個(gè)訓(xùn)練數(shù)據(jù)集,其中的實(shí)例類別已定。分類時(shí),對(duì)新的實(shí)例,根據(jù)其k個(gè)最近鄰的訓(xùn)練實(shí) 例的類別,通過多數(shù)表決等?式進(jìn)?預(yù)測(cè)。因此,k近鄰法不具有顯式的學(xué)習(xí)過程。k近鄰法實(shí)際上利? 訓(xùn)練數(shù)據(jù)集對(duì)特征向量空間進(jìn)?劃分,并作為其分類的“模型”。k值的選擇、距離度量及分類決策規(guī)則是k近鄰法的三個(gè)基本要素。k近鄰法1968年由Cover和Hart提出。

1、例子

有一種兔子叫作悲傷(Grief),它們的平均身高是5050厘米,平均體重55公斤。我們拿來一百個(gè)悲傷,分別測(cè)量它們的身高和體重,畫在坐標(biāo)圖上,用綠色方塊表示。還有一種兔子呢,叫作痛苦(Agony)。它們體型比較小,平均身高是3030厘米,平均體重是44公斤。我們將一百個(gè)痛苦的身高和體重畫在同一個(gè)坐標(biāo)圖上,用藍(lán)色三角表示。最后一種兔子叫絕望(Despair)。它們的平均身高45厘米,但體重較輕,平均只有2.5公斤。一百只絕望的數(shù)據(jù)用黃色圓圈表示。

image

在這些數(shù)據(jù)中,(身高,體重) 的二元組叫做特征(features),兔子的品種則是分類標(biāo)簽(class label)。我們想解決的問題是,給定一個(gè)未知分類的新樣本的所有特征,通過已知數(shù)據(jù)來判斷它的類別。

所以現(xiàn)在我們想解決的問題是,如果有一只新的兔子,我們知道它的身高和體重,然后我們想要知道它屬于這三類的那一類。這個(gè)時(shí)候k鄰近法就派上用場(chǎng)了。

我們對(duì)兔子進(jìn)行建模,使其形成關(guān)于身高體重的特征向量,然后找到離新兔子在向量空間上舉例最近的k個(gè)兔子(k由自己設(shè)定),然后根據(jù)這k個(gè)兔子的類型去預(yù)測(cè)判斷新兔子的類型。

2、算法

image

2.1、距離度量

image

一般情況下,我們都是用p=2,也就是歐式距離。

2.2、k值選擇

k值的選擇會(huì)對(duì)k近鄰法的結(jié)果產(chǎn)?重?影響。 如果選擇較?的k值, 就相當(dāng)于?較?的鄰域中的訓(xùn)練實(shí)例進(jìn)?預(yù)測(cè), “學(xué)習(xí)”的近似誤差 (approximation error)會(huì)減?,只有與輸?實(shí)例較近的(相似的)訓(xùn)練實(shí)例才會(huì)對(duì)預(yù)測(cè)結(jié)果起作?。但缺點(diǎn)是“學(xué)習(xí)”的估計(jì)誤差(estimation error)會(huì)增?,預(yù)測(cè)結(jié)果會(huì)對(duì)近鄰的實(shí)例點(diǎn)?常敏感。如果鄰近的實(shí)例點(diǎn)恰巧是噪聲,預(yù)測(cè)就會(huì)出錯(cuò)。換句話說,k值的減?就意味著整體模型變得復(fù)雜,容易發(fā)?過 擬合。

如果選擇較?的k值,就相當(dāng)于?較?鄰域中的訓(xùn)練實(shí)例進(jìn)?預(yù)測(cè)。其優(yōu)點(diǎn)是可以減少學(xué)習(xí)的估計(jì) 誤差。但缺點(diǎn)是學(xué)習(xí)的近似誤差會(huì)增?。這時(shí)與輸?實(shí)例較遠(yuǎn)的(不相似的)訓(xùn)練實(shí)例也會(huì)對(duì)預(yù)測(cè)起作?,使預(yù)測(cè)發(fā)?錯(cuò)誤。k值的增?就意味著整體的模型變得簡(jiǎn)單。

如果k=N,那么?論輸?實(shí)例是什么,都將簡(jiǎn)單地預(yù)測(cè)它屬于在訓(xùn)練實(shí)例中最多的類。這時(shí),模 型過于簡(jiǎn)單,完全忽略訓(xùn)練實(shí)例中的?量有?信息,是不可取的。

在應(yīng)?中,k值?般取?個(gè)?較?的數(shù)值。通常采?交叉驗(yàn)證法來選取最優(yōu)的k值。

3、概率KNN

簡(jiǎn)單的來說,就是結(jié)果是屬于每一類的概率大小,而不是絕對(duì)的屬于某一個(gè)類別。

二、kd樹算法實(shí)現(xiàn)

本來打算貼上算法流程,但是看了一遍又一遍,感覺算法實(shí)在是晦澀難懂。干脆直接貼鏈接上例子。

https://www.joinquant.com/view/community/detail/c2c41c79657cebf8cd871b44ce4f5d97

三、代碼實(shí)現(xiàn)

現(xiàn)導(dǎo)入需要使用到的包


from numpy import random

from sklearn import neighbors

import numpy as np

import matplotlib.pyplot as plt

from matplotlib.colors import ListedColormap

生成期望、方差不同的三組隨機(jī)數(shù)據(jù)


x1 = random.normal(50, 6, 200)

y1 = random.normal(5, 0.5, 200)

x2 = random.normal(30,6,200)

y2 = random.normal(4,0.5,200)

x3 = random.normal(45,6,200)

y3 = random.normal(2.5, 0.5, 200)

對(duì)數(shù)據(jù)進(jìn)行可視化

plt.scatter(x1,y1,c='b',marker='s',s=50,alpha=0.8)

plt.scatter(x2,y2,c='r', marker='^', s=50, alpha=0.8)

plt.scatter(x3,y3, c='g', s=50, alpha=0.8)
image

從圖中我們可以看出來,三類數(shù)據(jù)分布還是比較明顯。

之后,我們進(jìn)行數(shù)據(jù)的預(yù)處理,并且給數(shù)據(jù)分類到具體標(biāo)簽里

x_val = np.concatenate((x1,x2,x3))

y_val = np.concatenate((y1,y2,y3))

x_diff = max(x_val)-min(x_val)

y_diff = max(y_val)-min(y_val)

x_normalized = [x/(x_diff) for x in x_val]

y_normalized = [y/(y_diff) for y in y_val]

xy_normalized = zip(x_normalized,y_normalized)

xy_train = list(xy_normalized)

labels = [1]*200+[2]*200+[3]*200 # 三類標(biāo)簽,1(藍(lán)色),2(紅色),3(綠色)

開始訓(xùn)練模型

clf = neighbors.KNeighborsClassifier(30) # 設(shè)置k值為30, 其他默認(rèn)

clf.fit(xy_train, labels)

進(jìn)行預(yù)測(cè)

prediction = clf.predict([(50/x_diff, 5/y_diff),(30/x_diff, 3/y_diff)])

print(prediction)
image

可視化結(jié)果

plt.scatter(x1,y1,c='b',marker='s',s=50,alpha=0.8)

plt.scatter(x2,y2,c='r', marker='^', s=50, alpha=0.8)

plt.scatter(x3,y3, c='g', s=50, alpha=0.8)

plt.scatter(50,5, c='y',s = 50, alpha = 0.8)

plt.scatter(30,3, c='y',s = 50, alpha = 0.8)
image

我們可以看到,這兩個(gè)黃色的新實(shí)例,第一個(gè)確實(shí)在1(藍(lán)色)中,第二個(gè)感覺比較模糊,在2(紅色)和3(綠色)之間,并沒有很明顯的差別。讓我們看下概率KNN.

prediction_proba = clf.predict_proba([(50/x_diff, 5/y_diff),(30/x_diff, 3/y_diff)])

print(prediction_proba)
image

我們可以看到第一個(gè)是100%的概率在分類1中,而第二個(gè)實(shí)例分別是77%和23%的概率屬于分類2或者分類3.

接下來,我們?cè)偕梢恍┬碌膶?shí)例來作為測(cè)試集,對(duì)我們的模型進(jìn)行測(cè)試。

x1_test = random.normal(50, 6, 100)

y1_test = random.normal(5, 0.5, 100)

x2_test = random.normal(30,6,100)

y2_test = random.normal(4,0.5,100)

x3_test = random.normal(45,6,100)

y3_test = random.normal(2.5, 0.5, 100)

xy_test_normalized = zip(np.concatenate((x1_test,x2_test,x3_test))/x_diff,\

                        np.concatenate((y1_test,y2_test,y3_test))/y_diff)

xy_test = list(xy_test_normalized)

labels_test = [1]*100+[2]*100+[3]*100

來看下我們的模型分?jǐn)?shù)

score = clf.score(xy_test, labels_test)

print(score)
image

可以看到我們的分?jǐn)?shù)還不錯(cuò),主要因?yàn)閿?shù)據(jù)都是我們生成的,規(guī)律比較明顯。以后還是要多用實(shí)際數(shù)據(jù)去試一試。

之前我們提到過,不同的k值會(huì)導(dǎo)致結(jié)果的不同。接下來我們就想看一下不同的k值,結(jié)果有什么不同,哪一個(gè)k值得結(jié)果最好。

record = []

for i in range(1,31):

    clf = neighbors.KNeighborsClassifier(i)

    clf.fit(xy_train, labels)

    score = clf.score(xy_test, labels_test)

    record.append(score)

    print("when k = %i, score = %f"%(i,score))
image
k = []

for i, value in enumerate(record):

    if  value == np.max(record):

          k.append(i+1)

print("when k = ", k)

print("the score is the highest = ", np.max(record))
image

從結(jié)果我們可以看到,最高的分?jǐn)?shù)就是98.67%,很多種不同的k的選擇都會(huì)有這一個(gè)結(jié)果。這個(gè)時(shí)候我們是不是應(yīng)該用較為小的k值呢,去降低算法復(fù)雜度,加快預(yù)算時(shí)間。

參考:

李航博士《統(tǒng)計(jì)學(xué)習(xí)方法》

https://www.joinquant.com/view/community/detail/a98b7021e7391c62f6369207242700b2

https://www.joinquant.com/view/community/detail/c2c41c79657cebf8cd871b44ce4f5d97

https://www.joinquant.com/view/community/detail/bb850ee76d1cae16cc587f29c4439ebd

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容