
KNN算法思想與應(yīng)用例子
這篇文章是在學(xué)習(xí)KNN時(shí)寫的筆記,所參考的書為《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》,希望深入淺出地解釋K近鄰算法的思想,最后放一個(gè)用k近鄰算法識(shí)別圖像數(shù)字的例子。
KNN算法也稱K近鄰,是一種監(jiān)督學(xué)習(xí)算法,即它需要訓(xùn)練集參與模型的構(gòu)建。它適用于帶標(biāo)簽集的行列式(可理解為二維數(shù)組)的數(shù)據(jù)集。
需要準(zhǔn)備的數(shù)據(jù)有:訓(xùn)練數(shù)據(jù)集,訓(xùn)練標(biāo)簽集(每個(gè)數(shù)據(jù)與每個(gè)標(biāo)簽都一一對(duì)應(yīng))用于參與模型構(gòu)建;
需要測(cè)試的數(shù)據(jù)集——通過這個(gè)模型得出——標(biāo)簽集(每個(gè)數(shù)據(jù)對(duì)應(yīng)的標(biāo)簽)
舉個(gè)例子:我們把人體的指標(biāo)量化,比如體重多少,三圍多少,脂肪比例多少,然后這個(gè)標(biāo)簽就是性別(男或女)。我們的訓(xùn)練數(shù)據(jù)集就是500個(gè)男性和500個(gè)女性的身體指標(biāo),每個(gè)數(shù)據(jù)對(duì)應(yīng)性別標(biāo)簽(男或女),這個(gè)就是訓(xùn)練標(biāo)簽集。然后我們輸入一個(gè)人的指標(biāo),模型給出一個(gè)性別的判斷,這個(gè)就是輸出的標(biāo)簽集,也就是最后的預(yù)測(cè)結(jié)果。
算法的流程為:
1、計(jì)算輸入測(cè)試數(shù)據(jù)與訓(xùn)練數(shù)據(jù)集的距離,這里用歐式距離來(lái)計(jì)算。
2、根據(jù)得到的距離大小,按升序排序
3、取前K個(gè)距離最小的數(shù)據(jù)集對(duì)應(yīng)的標(biāo)簽
4、計(jì)算這些標(biāo)簽的出現(xiàn)頻率
5、取出現(xiàn)頻率最高的標(biāo)簽作為輸入的測(cè)試數(shù)據(jù)的最后的標(biāo)簽,即預(yù)測(cè)結(jié)果
其中,歐式距離的計(jì)算公式如下:
這個(gè)公式怎么理解呢?假設(shè)輸入的被測(cè)數(shù)據(jù)為A,它有兩個(gè)維度(或者說字段),分別是AX-1和AX2。B為訓(xùn)練數(shù)據(jù)集,同理也有兩個(gè)維度,BX-1和BX2和,所以以上的計(jì)算公式即不同維度的差的平方的和的開方。
下面直接貼上代碼,每一段都附有注釋,希望童鞋們可以通過理解代碼的執(zhí)行來(lái)掌握整個(gè)KNN算法的流程。
# KNN算法主程序
def knnmain(inX,dataset,labels,k): #輸入量有(被測(cè)數(shù)據(jù),訓(xùn)練數(shù)據(jù)集,訓(xùn)練標(biāo)簽集,K值),輸入量皆為數(shù)組形式
datasetsite=dataset.shape[0] #取訓(xùn)練數(shù)據(jù)集的總數(shù)量n
inXdata=tile(inX,(datasetsite,1)) #將被測(cè)數(shù)據(jù)的數(shù)組復(fù)制為n行相同數(shù)組組成的二維數(shù)組,方便下面的歐式距離計(jì)算
sqdistance=inXdata-dataset #開始計(jì)算歐式距離,這里計(jì)算被測(cè)數(shù)據(jù)和訓(xùn)練數(shù)據(jù)集之間相同維度的差
distance=sqdistance**2 #計(jì)算差的平方
dist=distance.sum(axis=1) #計(jì)算不同維度的差的平方的總和
lastdistance=dist**0.5 #將總和開方
sortnum=lastdistance.argsort() #返回從小到大(增序)的索引值
countdata={} #創(chuàng)建一個(gè)空字典用于儲(chǔ)存標(biāo)簽和對(duì)應(yīng)的數(shù)量值
for i in range(k):
vlabels=labels[sortnum[i]] #將前k個(gè)距離最近的數(shù)據(jù)的標(biāo)簽傳給vlabels
countdata[vlabels]=countdata.get(vlabels,0)+1 #vlabels作為字典的鍵,而其出現(xiàn)的次數(shù)作為字典的值
sortnumzi=sorted(countdata.iteritems(),key=operator.itemgetter(1),reverse=True) #將字典按值降序排序,即第一位是出現(xiàn)次數(shù)最多的標(biāo)簽
return sortnumzi[0][0] #返回出現(xiàn)次數(shù)最多的標(biāo)簽值
整個(gè)KNN算法的核心思想是比較簡(jiǎn)潔的,下面貼一個(gè)手寫數(shù)字識(shí)別的應(yīng)用。
一個(gè)文本文檔里儲(chǔ)存一個(gè)32*32的由1和0組成的圖像,差不多是下圖所示:
我們大概能識(shí)別出第一個(gè)圖片里是0,第二個(gè)圖片里是1,實(shí)際上每個(gè)文本文檔都有一個(gè)文檔名,如第一個(gè)圖片的文檔名就是"0_0.txt",那么我們就可以從文檔名里取得該圖片的標(biāo)簽。我們有一個(gè)訓(xùn)練文件夾,里面的文檔文件可以獲取并構(gòu)成訓(xùn)練數(shù)據(jù)集和訓(xùn)練標(biāo)簽集。
我們也有一個(gè)測(cè)試文件夾,同理里面的文檔文件也可以獲取并構(gòu)成測(cè)試數(shù)據(jù)集和測(cè)試標(biāo)簽集(拿來(lái)與預(yù)測(cè)結(jié)果做對(duì)比)。文件夾截圖如下:
下面直接貼上代碼幫助理解
先是一個(gè)將32*32的文本文檔轉(zhuǎn)化為1*1024的程序,因?yàn)槲覀儗懙?a href='/map/knn/' style='color:#000;font-size:inherit;'>KNN算法主程序是以一行為單位的。
def to_32(filename):
returnoss=zeros((1,1024))
ma=open(filename)
i=int(0)
for line in ma.readlines():
for j in range(32):
returnoss[0,i*32+j]=line[j]
i += 1
return returnoss
下面是手寫數(shù)字識(shí)別程序:
def distinguish():
filestrain=listdir('trainingDigits') #打開訓(xùn)練集文件夾
filestest=listdir('testDigits') #打開測(cè)試集文件夾
mtrain=len(filestrain) #訓(xùn)練集文件數(shù)量
mtest=len(filestest) #測(cè)試集文件數(shù)量
allfilestrain=zeros((mtrain,1024)) #m行1024列的矩陣
allfilestest=zeros((mtest,1024))
labelstrain=[] #創(chuàng)造一個(gè)空列表用于儲(chǔ)存試驗(yàn)向量的標(biāo)簽
labelstest=[]
for i in range(mtrain):
nametrain=filestrain[i] #選取文件名
inX=open('trainingDigits/%s' % nametrain)
allfilestrain[i,:]=to_32(inX) ##把每個(gè)文件中的32*32矩陣轉(zhuǎn)換成1*1024的矩陣
label1=nametrain.split('.')[0]
label1=int(label1.split('_')[0]) #獲取每個(gè)數(shù)據(jù)的標(biāo)簽
labelstrain.append(label1) #將所有標(biāo)簽合成一個(gè)列表
for j in range(mtest):
nametest=filestest[j]
inY=open('trainingDigits/%s' % nametest)
allfilestest[j,:]=to_32(inY)
label2=nametest.split('.')[0]
label2=int(label2.split('_')[0])
labelstest.append(label2)
labelstrain=np.array(labelstrain)
labelstest=np.array(labelstest)
grouptrain=allfilestrain
grouptest=allfilestest
error=0.0 #初始化判斷錯(cuò)誤率
results=[]
for line in grouptest:
result=knnmain(line,grouptrain,labelstrain,3)
results.append(result)
errornum=0 ##初始化判斷錯(cuò)誤數(shù)量
print 'the wrong prodiction as:'
for i in range(mtest):
if results[i] != labelstest[i]:
print 'result=',results[i],'labelstest=',labelstest[i] #輸出所有判斷錯(cuò)誤的例子
errornum +=1
print 'the errornum is:',errornum #輸出判斷錯(cuò)誤量
print 'the allnum is:',mtest #輸出總測(cè)試量
error=float(errornum/float(mtest))
print 'the error persent is:',error #輸出總測(cè)試錯(cuò)誤率
該程序運(yùn)行截圖如下:
我們看到錯(cuò)誤率是比較低,說明該算法的精度是很高的。
結(jié)語(yǔ):從上面例子的應(yīng)用來(lái)看,KNN算法的精度是很高,但是對(duì)噪聲有些敏感,我們觀察上面的運(yùn)行結(jié)果,凡是判斷失誤的一般是兩個(gè)數(shù)字長(zhǎng)得比較像,比如9和5,下面的勾很像,9和7,也是比較像的,也就是說,假如測(cè)試的數(shù)據(jù)有些偏于常態(tài),可能一個(gè)7長(zhǎng)得比較歪,那就判斷為9了,這些都是噪聲,它對(duì)這些噪聲的數(shù)據(jù)是無(wú)法精準(zhǔn)識(shí)別的,因?yàn)閗值較小,下面會(huì)說到k值得取值問題。另有,它的計(jì)算相對(duì)復(fù)雜,若對(duì)象數(shù)據(jù)集巨大,則計(jì)算量也很大。當(dāng)然,最重要的一點(diǎn),對(duì)k值的把握很重要,這一般是根據(jù)具體情況來(lái)判斷,較大的k值能減少噪聲干擾,但會(huì)使分類界限模糊,較小的k值又容易被噪聲影響。一般取一個(gè)較小的k值,再通過交叉驗(yàn)證來(lái)選取最優(yōu)k值。
數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼
若不方便掃碼,搜微信號(hào):CDAshujufenxi
LSTM 模型輸入長(zhǎng)度選擇技巧:提升序列建模效能的關(guān)鍵? 在循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)家族中,長(zhǎng)短期記憶網(wǎng)絡(luò)(LSTM)憑借其解決長(zhǎng)序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報(bào)考條件詳解與準(zhǔn)備指南? ? 在數(shù)據(jù)驅(qū)動(dòng)決策的時(shí)代浪潮下,CDA 數(shù)據(jù)分析師認(rèn)證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計(jì)的實(shí)用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強(qiáng)大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠(chéng)摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實(shí)施重大更新。 此次更新旨在確保認(rèn) ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務(wù)的價(jià)值轉(zhuǎn)化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡(jiǎn)稱 BI)深度融合的時(shí)代,BI ...
2025-07-10SQL 在預(yù)測(cè)分析中的應(yīng)用:從數(shù)據(jù)查詢到趨勢(shì)預(yù)判? ? 在數(shù)據(jù)驅(qū)動(dòng)決策的時(shí)代,預(yù)測(cè)分析作為挖掘數(shù)據(jù)潛在價(jià)值的核心手段,正被廣泛 ...
2025-07-10數(shù)據(jù)查詢結(jié)束后:分析師的收尾工作與價(jià)值深化? ? 在數(shù)據(jù)分析的全流程中,“query end”(查詢結(jié)束)并非工作的終點(diǎn),而是將數(shù) ...
2025-07-10CDA 數(shù)據(jù)分析師考試:從報(bào)考到取證的全攻略? 在數(shù)字經(jīng)濟(jì)蓬勃發(fā)展的今天,數(shù)據(jù)分析師已成為各行業(yè)爭(zhēng)搶的核心人才,而 CDA(Certi ...
2025-07-09【CDA干貨】單樣本趨勢(shì)性檢驗(yàn):捕捉數(shù)據(jù)背后的時(shí)間軌跡? 在數(shù)據(jù)分析的版圖中,單樣本趨勢(shì)性檢驗(yàn)如同一位耐心的偵探,專注于從單 ...
2025-07-09year_month數(shù)據(jù)類型:時(shí)間維度的精準(zhǔn)切片? ? 在數(shù)據(jù)的世界里,時(shí)間是最不可或缺的維度之一,而year_month數(shù)據(jù)類型就像一把精準(zhǔn) ...
2025-07-09CDA 備考干貨:Python 在數(shù)據(jù)分析中的核心應(yīng)用與實(shí)戰(zhàn)技巧? ? 在 CDA 數(shù)據(jù)分析師認(rèn)證考試中,Python 作為數(shù)據(jù)處理與分析的核心 ...
2025-07-08SPSS 中的 Mann-Kendall 檢驗(yàn):數(shù)據(jù)趨勢(shì)與突變分析的有力工具? ? ? 在數(shù)據(jù)分析的廣袤領(lǐng)域中,準(zhǔn)確捕捉數(shù)據(jù)的趨勢(shì)變化以及識(shí)別 ...
2025-07-08備戰(zhàn) CDA 數(shù)據(jù)分析師考試:需要多久?如何規(guī)劃? CDA(Certified Data Analyst)數(shù)據(jù)分析師認(rèn)證作為國(guó)內(nèi)權(quán)威的數(shù)據(jù)分析能力認(rèn)證 ...
2025-07-08LSTM 輸出不確定的成因、影響與應(yīng)對(duì)策略? 長(zhǎng)短期記憶網(wǎng)絡(luò)(LSTM)作為循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)的一種變體,憑借獨(dú)特的門控機(jī)制,在 ...
2025-07-07統(tǒng)計(jì)學(xué)方法在市場(chǎng)調(diào)研數(shù)據(jù)中的深度應(yīng)用? 市場(chǎng)調(diào)研是企業(yè)洞察市場(chǎng)動(dòng)態(tài)、了解消費(fèi)者需求的重要途徑,而統(tǒng)計(jì)學(xué)方法則是市場(chǎng)調(diào)研數(shù) ...
2025-07-07CDA數(shù)據(jù)分析師證書考試全攻略? 在數(shù)字化浪潮席卷全球的當(dāng)下,數(shù)據(jù)已成為企業(yè)決策、行業(yè)發(fā)展的核心驅(qū)動(dòng)力,數(shù)據(jù)分析師也因此成為 ...
2025-07-07剖析 CDA 數(shù)據(jù)分析師考試題型:解鎖高效備考與答題策略? CDA(Certified Data Analyst)數(shù)據(jù)分析師考試作為衡量數(shù)據(jù)專業(yè)能力的 ...
2025-07-04SQL Server 字符串截取轉(zhuǎn)日期:解鎖數(shù)據(jù)處理的關(guān)鍵技能? 在數(shù)據(jù)處理與分析工作中,數(shù)據(jù)格式的規(guī)范性是保證后續(xù)分析準(zhǔn)確性的基礎(chǔ) ...
2025-07-04CDA 數(shù)據(jù)分析師視角:從數(shù)據(jù)迷霧中探尋商業(yè)真相? 在數(shù)字化浪潮席卷全球的今天,數(shù)據(jù)已成為企業(yè)決策的核心驅(qū)動(dòng)力,CDA(Certifie ...
2025-07-04CDA 數(shù)據(jù)分析師:開啟數(shù)據(jù)職業(yè)發(fā)展新征程? ? 在數(shù)據(jù)成為核心生產(chǎn)要素的今天,數(shù)據(jù)分析師的職業(yè)價(jià)值愈發(fā)凸顯。CDA(Certified D ...
2025-07-03