用Python實(shí)現(xiàn)KNN分類(lèi)算法
本文實(shí)例為大家分享了Python KNN分類(lèi)算法的具體代碼,供大家參考,具體內(nèi)容如下
KNN分類(lèi)算法應(yīng)該算得上是機(jī)器學(xué)習(xí)中最簡(jiǎn)單的分類(lèi)算法了,所謂KNN即為K-NearestNeighbor(K個(gè)最鄰近樣本節(jié)點(diǎn))。在進(jìn)行分類(lèi)之前KNN分類(lèi)器會(huì)讀取較多數(shù)量帶有分類(lèi)標(biāo)簽的樣本數(shù)據(jù)作為分類(lèi)的參照數(shù)據(jù),當(dāng)它對(duì)類(lèi)別未知的樣本進(jìn)行分類(lèi)時(shí),會(huì)計(jì)算當(dāng)前樣本與所有參照樣本的差異大??;該差異大小是通過(guò)數(shù)據(jù)點(diǎn)在樣本特征的多維度空間中的距離來(lái)進(jìn)行衡量的,也就是說(shuō),如果兩個(gè)樣本點(diǎn)在在其特征數(shù)據(jù)多維度空間中的距離越近,則這兩個(gè)樣本點(diǎn)之間的差異就越小,這兩個(gè)樣本點(diǎn)屬于同一類(lèi)別的可能性就越大。KNN分類(lèi)算法利用這一基本的認(rèn)知,通過(guò)計(jì)算待預(yù)測(cè)樣本點(diǎn)與參照樣本空間中所有的樣本的距離,并找到K個(gè)距離該樣本點(diǎn)最近的參照樣本點(diǎn),統(tǒng)計(jì)出這最鄰近的K個(gè)樣本點(diǎn)中占比數(shù)量最多的類(lèi)別,并將該類(lèi)別作為預(yù)測(cè)結(jié)果。
KNN的模型十分簡(jiǎn)單,沒(méi)有涉及到模型的訓(xùn)練,每一次預(yù)測(cè)都需要計(jì)算該點(diǎn)與所有已知點(diǎn)的距離,因此隨著參照樣本集的數(shù)量增加,KNN分類(lèi)器的計(jì)算開(kāi)銷(xiāo)也會(huì)呈比例增加,并且KNN并不適合數(shù)量很少的樣本集。并且KNN提出之后,后續(xù)很多人提出了很多改進(jìn)的算法,分別從提高算法速率和提高算法準(zhǔn)確率兩個(gè)方向,但是都是基于“距離越近,相似的可能性越大”的原則。這里利用Python實(shí)現(xiàn)了KNN最原始版本的算法,數(shù)據(jù)集使用的是機(jī)器學(xué)習(xí)課程中使用得非常多的鶯尾花數(shù)據(jù)集,同時(shí)我在原數(shù)據(jù)集的基礎(chǔ)上向數(shù)據(jù)集中添加了少量的噪聲數(shù)據(jù),測(cè)試KNN算法的魯棒性。
數(shù)據(jù)集用得是鶯尾花數(shù)據(jù)集,下載地址。
數(shù)據(jù)集包含90個(gè)數(shù)據(jù)(訓(xùn)練集),分為2類(lèi),每類(lèi)45個(gè)數(shù)據(jù),每個(gè)數(shù)據(jù)4個(gè)屬性
Sepal.Length(花萼長(zhǎng)度),單位是cm;
Sepal.Width(花萼寬度),單位是cm;
Petal.Length(花瓣長(zhǎng)度),單位是cm;
Petal.Width(花瓣寬度),單位是cm;
分類(lèi)種類(lèi): Iris Setosa(山鳶尾)、Iris Versicolour(雜色鳶尾)
之前主打C++,近來(lái)才學(xué)的Python,今天想拿實(shí)現(xiàn)KNN來(lái)練練手,下面上代碼:
#coding=utf-8 import math #定義鳶尾花的數(shù)據(jù)類(lèi) class Iris: data=[] label=[] pass #定義一個(gè)讀取鶯尾花數(shù)據(jù)集的函數(shù) def load_dataset(filename="Iris_train.txt"): f=open(filename) line=f.readline().strip() propty=line.split(',')#屬性名 dataset=[]#保存每一個(gè)樣本的數(shù)據(jù)信息 label=[]#保存樣本的標(biāo)簽 while line: line=f.readline().strip() if(not line): break temp=line.split(',') content=[] for i in temp[0:-1]: content.append(float(i)) dataset.append(content) label.append(temp[-1]) total=Iris() total.data=dataset total.label=label return total#返回?cái)?shù)據(jù)集 #定義一個(gè)Knn分類(lèi)器類(lèi) class KnnClassifier: def __init__(self,k,type="Euler"):#初始化的時(shí)候定義正整數(shù)K和距離計(jì)算方式 self.k=k self.type=type self.dataloaded=False def load_traindata(self,traindata):#加載數(shù)據(jù)集 self.data=traindata.data self.label=traindata.label self.label_set=set(traindata.label) self.dataloaded=True#是否加載數(shù)據(jù)集的標(biāo)記 def Euler_dist(self,x,y):# 歐拉距離計(jì)算方法,x、y都是向量 sum=0 for i,j in zip(x,y): sum+=math.sqrt((i-j)**2) return sum def Manhattan_dist(self,x,y):#曼哈頓距離計(jì)算方法,x、y都是向量 sum=0 for i,j in zip(x,y): sum+=abs(i-j) return sum def predict(self,temp):#預(yù)測(cè)函數(shù),讀入一個(gè)預(yù)測(cè)樣本的數(shù)據(jù),temp是一個(gè)向量 if(not self.dataloaded):#判斷是否有訓(xùn)練數(shù)據(jù) print "No train_data load in" return distance_and_label=[] if(self.type=="Euler"):#判斷距離計(jì)算方式,歐拉距離或者曼哈頓距離 for i,j in zip(self.data,self.label): dist=self.Euler_dist(temp,i) distance_and_label.append([dist,j]) else: if(self.type=="Manhattan"): for i,j in zip(self.data,self.label): dist=self.Manhattan_dist(temp,i) distance_and_label.append([dist,j]) else: print "type choice error" #獲取K個(gè)最鄰近的樣本的距離和類(lèi)別標(biāo)簽 neighborhood=sorted(distance_and_label,cmp=lambda x,y : cmp(x[0],y[0]))[0:self.k] neighborhood_class=[] for i in neighborhood: neighborhood_class.append(i[1]) class_set=set(neighborhood_class) neighborhood_class_count=[] print "In k nearest neighborhoods:" #統(tǒng)計(jì)該K個(gè)最鄰近點(diǎn)中各個(gè)類(lèi)別的個(gè)數(shù) for i in class_set: a=neighborhood_class.count(i) neighborhood_class_count.append([i,a]) print "class: ",i," count: ",a result=sorted(neighborhood_class_count,cmp=lambda x,y : cmp(x[1],y[1]))[-1][0] print "result: ",result return result#返回預(yù)測(cè)的類(lèi)別 if __name__ == '__main__': traindata=load_dataset()#training data testdata=load_dataset("Iris_test.txt")#testing data #新建一個(gè)Knn分類(lèi)器的K為20,默認(rèn)為歐拉距離計(jì)算方式 kc=KnnClassifier(20) kc.load_traindata(traindata) predict_result=[] #預(yù)測(cè)測(cè)試集testdata中所有待預(yù)測(cè)樣本的結(jié)果 for i,j in zip(testdata.data,testdata.label): predict_result.append([i,kc.predict(i),j]) correct_count=0 #將預(yù)測(cè)結(jié)果和正確結(jié)果進(jìn)行比對(duì),計(jì)算該次預(yù)測(cè)的準(zhǔn)確率 for i in predict_result: if(i[1]==i[2]): correct_count+=1 ratio=float(correct_count)/len(predict_result) print "correct predicting ratio",ratio
測(cè)試集中11個(gè)待測(cè)樣本點(diǎn)的分類(lèi)結(jié)果:
In k nearest neighborhoods: class: Iris-setosa count: 20 result: Iris-setosa In k nearest neighborhoods: class: Iris-setosa count: 20 result: Iris-setosa In k nearest neighborhoods: class: Iris-setosa count: 20 result: Iris-setosa In k nearest neighborhoods: class: Iris-setosa count: 20 result: Iris-setosa In k nearest neighborhoods: class: Iris-setosa count: 20 result: Iris-setosa In k nearest neighborhoods: class: Iris-versicolor count: 20 result: Iris-versicolor In k nearest neighborhoods: class: Iris-versicolor count: 20 result: Iris-versicolor In k nearest neighborhoods: class: Iris-versicolor count: 20 result: Iris-versicolor In k nearest neighborhoods: class: Iris-versicolor count: 20 result: Iris-versicolor In k nearest neighborhoods: class: Iris-versicolor count: 20 result: Iris-versicolor In k nearest neighborhoods: class: Iris-setosa count: 18 class: Iris-versicolor count: 2 result: Iris-setosa correct predicting ratio 0.909090909091
KNN中對(duì)距離的計(jì)算有很多種方法,不同的方法適用于不同的數(shù)據(jù)集,該代碼中只實(shí)現(xiàn)了歐拉距離和曼哈頓距離兩種計(jì)算方式;測(cè)試集中的數(shù)據(jù)是從原數(shù)據(jù)集中抽離出來(lái)的,數(shù)據(jù)量不是很大,結(jié)果并不能很好地體現(xiàn)KNN的性能,所以程序運(yùn)行結(jié)果僅供參考。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python實(shí)現(xiàn)身份證實(shí)名認(rèn)證的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于python實(shí)現(xiàn)身份證實(shí)名認(rèn)證的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Pycharm正版2022.2.2?官方翻譯插件更新tkk失敗不能用問(wèn)題及解決方案
這篇文章主要介紹了Pycharm正版2022.2.2?|?官方翻譯插件更新tkk失敗解決,?出現(xiàn)tkk問(wèn)題的是這個(gè)翻譯插件,本教程只解決該翻譯插件不能用的問(wèn)題,需要的朋友可以參考下2022-11-11Python中的True,False條件判斷實(shí)例分析
這篇文章主要介紹了Python中的True,False條件判斷的用法,實(shí)例分析了針對(duì)不同數(shù)據(jù)類(lèi)型的條件判斷用法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01Pycharm中如何關(guān)掉python console
這篇文章主要介紹了Pycharm中如何關(guān)掉python console,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10從CentOS安裝完成到生成詞云python的實(shí)例
下面小編就為大家分享一篇從CentOS安裝完成到生成詞云python的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助2017-12-12解決python中set與dict的無(wú)序問(wèn)題
這篇文章主要介紹了解決python中set與dict的無(wú)序問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03Pytorch實(shí)現(xiàn)邏輯回歸分類(lèi)
這篇文章主要為大家詳細(xì)介紹了Pytorch實(shí)現(xiàn)邏輯回歸分類(lèi),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07