Python實(shí)現(xiàn)KNN(K-近鄰)算法的示例代碼
一、概述
KNN(K-最近鄰)算法是相對比較簡單的機(jī)器學(xué)習(xí)算法之一,它主要用于對事物進(jìn)行分類。用比較官方的話來說就是:給定一個(gè)訓(xùn)練數(shù)據(jù)集,對新的輸入實(shí)例,在訓(xùn)練數(shù)據(jù)集中找到與該實(shí)例最鄰近的K個(gè)實(shí)例, 這K個(gè)實(shí)例的多數(shù)屬于某個(gè)類,就把該輸入實(shí)例分類到這個(gè)類中。為了更好地理解,通過一個(gè)簡單的例子說明。
我們有一組自擬的關(guān)于電影中鏡頭的數(shù)據(jù):

那么問題來了,如果有一部電影 X,它的打戲?yàn)?3,吻戲?yàn)?2。那么這部電影應(yīng)該屬于哪一類?
我們把所有數(shù)據(jù)通過圖表顯示出來(圓點(diǎn)代表的是自擬的數(shù)據(jù),也稱訓(xùn)練集;三角形代表的是 X 電影的數(shù)據(jù),稱為測試數(shù)據(jù)):

計(jì)算測試數(shù)據(jù)到訓(xùn)練數(shù)據(jù)之間的距離,假設(shè) k 為 3,那么我們就找到距離中最小的三個(gè)點(diǎn),假如 3 個(gè)點(diǎn)中有 2 個(gè)屬于動(dòng)作片,1 個(gè)屬于愛情片,那么把該電影 X 分類為動(dòng)作片。這種通過計(jì)算距離總結(jié) k 個(gè)最鄰近的類,按照”少數(shù)服從多數(shù)“原則分類的算法就為 KNN(K-近鄰)算法。
二、算法介紹
還是以上面的數(shù)據(jù)為例,打戲數(shù)為 x,吻戲數(shù)為 y,通過歐式距離公式計(jì)算測試數(shù)據(jù)到訓(xùn)練數(shù)據(jù)的距離,我上中學(xué)那會(huì)兒不知道這個(gè)叫做歐式距離公式,一直用”兩點(diǎn)間的距離公式“來稱呼這個(gè)公式:
。但是現(xiàn)實(shí)中的很多數(shù)據(jù)都是多維的,即使如此,也還是按照這個(gè)思路進(jìn)行計(jì)算,比如如果是三維的話,就在根號里面再加上 z 軸差的平方,即
,以此類推。
知道了這個(gè)計(jì)算公式,就可以計(jì)算各個(gè)距離了。我們以到最上面的點(diǎn)的距離為例:
,那么從上到下的距離分別是:
,
,
,
?,F(xiàn)在我們把 k 定為 3,那么距離最近的就是后面三個(gè)數(shù)了,在這三個(gè)數(shù)中,有兩個(gè)屬于動(dòng)作片,因此,電影 X 就分類為動(dòng)作片。
三、算法實(shí)現(xiàn)
知道了原理,那就可以用代碼實(shí)現(xiàn)了,這里就不再贅述了,直接上帶注釋的 Python 代碼:
'''
trainData - 訓(xùn)練集
testData - 測試集
labels - 分類
'''
def knn(trainData, testData, labels, k):
# 計(jì)算訓(xùn)練樣本的行數(shù)
rowSize = trainData.shape[0]
# 計(jì)算訓(xùn)練樣本和測試樣本的差值
diff = np.tile(testData, (rowSize, 1)) - trainData
# 計(jì)算差值的平方和
sqrDiff = diff ** 2
sqrDiffSum = sqrDiff.sum(axis=1)
# 計(jì)算距離
distances = sqrDiffSum ** 0.5
# 對所得的距離從低到高進(jìn)行排序
sortDistance = distances.argsort()
count = {}
for i in range(k):
vote = labels[sortDistance[i]]
count[vote] = count.get(vote, 0) + 1
# 對類別出現(xiàn)的頻數(shù)從高到低進(jìn)行排序
sortCount = sorted(count.items(), key=operator.itemgetter(1), reverse=True)
# 返回出現(xiàn)頻數(shù)最高的類別
return sortCount[0][0]
ps:np.tile(testData, (rowSize, 1)) 是將 testData 這個(gè)數(shù)據(jù)擴(kuò)展為 rowSize 列,這樣能避免運(yùn)算錯(cuò)誤;
sorted(count.items(), key=operator.itemgetter(1), reverse=True) 排序函數(shù),里面的參數(shù) key=operator.itemgetter(1), reverse=True 表示按照 count 這個(gè)字典的值(value)從高到低排序,如果把 1 換成 0,則是按字典的鍵(key)從高到低排序。把 True 換成 False 則是從低到高排序。
四、測試與總結(jié)
用 Python 實(shí)現(xiàn)了算法之后,我們用上面的數(shù)據(jù)進(jìn)行測試,看一下結(jié)果是否和我們預(yù)測的一樣為動(dòng)作片:
trainData = np.array([[5, 1], [4, 0], [1, 3], [0, 4]]) labels = ['動(dòng)作片', '動(dòng)作片', '愛情片', '愛情片'] testData = [3, 2] X = knn(trainData, testData, labels, 3) print(X)
執(zhí)行這段代碼后輸出的結(jié)果為:動(dòng)作片 。和預(yù)測的一樣。當(dāng)然通過這個(gè)算法分類的正確率不可能為 100%,可以通過增加修改數(shù)據(jù)測試,如果有大量多維的數(shù)據(jù)就更好了。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
django 按時(shí)間范圍查詢數(shù)據(jù)庫實(shí)例代碼
這篇文章主要介紹了django 按時(shí)間范圍查詢數(shù)據(jù)庫實(shí)例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02
用pycharm開發(fā)django項(xiàng)目示例代碼
這篇文章主要介紹了用pycharm開發(fā)django項(xiàng)目示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
python使用UDP實(shí)現(xiàn)客戶端和服務(wù)器對話
這篇文章主要為大家介紹了python使用UDP實(shí)現(xiàn)客戶端和服務(wù)器對話示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Python爬取智聯(lián)招聘數(shù)據(jù)分析師崗位相關(guān)信息的方法
這篇文章主要介紹了Python爬取智聯(lián)招聘數(shù)據(jù)分析師崗位相關(guān)信息的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
Python+Selenium實(shí)現(xiàn)一鍵摸魚&采集數(shù)據(jù)
將Selenium程序編寫為 .bat 可執(zhí)行文件,從此一鍵啟動(dòng)封裝好的Selenium程序,省時(shí)省力還可以復(fù)用,豈不美哉。所以本文將利用Selenium實(shí)現(xiàn)一鍵摸魚&一鍵采集數(shù)據(jù),需要的可以參考一下2022-08-08

