
KNN算法思想與應(yīng)用例子
這篇文章是在學習KNN時寫的筆記,所參考的書為《機器學習實戰(zhàn)》,希望深入淺出地解釋K近鄰算法的思想,最后放一個用k近鄰算法識別圖像數(shù)字的例子。
KNN算法也稱K近鄰,是一種監(jiān)督學習算法,即它需要訓練集參與模型的構(gòu)建。它適用于帶標簽集的行列式(可理解為二維數(shù)組)的數(shù)據(jù)集。
需要準備的數(shù)據(jù)有:訓練數(shù)據(jù)集,訓練標簽集(每個數(shù)據(jù)與每個標簽都一一對應(yīng))用于參與模型構(gòu)建;
需要測試的數(shù)據(jù)集——通過這個模型得出——標簽集(每個數(shù)據(jù)對應(yīng)的標簽)
舉個例子:我們把人體的指標量化,比如體重多少,三圍多少,脂肪比例多少,然后這個標簽就是性別(男或女)。我們的訓練數(shù)據(jù)集就是500個男性和500個女性的身體指標,每個數(shù)據(jù)對應(yīng)性別標簽(男或女),這個就是訓練標簽集。然后我們輸入一個人的指標,模型給出一個性別的判斷,這個就是輸出的標簽集,也就是最后的預(yù)測結(jié)果。
算法的流程為:
1、計算輸入測試數(shù)據(jù)與訓練數(shù)據(jù)集的距離,這里用歐式距離來計算。
2、根據(jù)得到的距離大小,按升序排序
3、取前K個距離最小的數(shù)據(jù)集對應(yīng)的標簽
4、計算這些標簽的出現(xiàn)頻率
5、取出現(xiàn)頻率最高的標簽作為輸入的測試數(shù)據(jù)的最后的標簽,即預(yù)測結(jié)果
其中,歐式距離的計算公式如下:
這個公式怎么理解呢?假設(shè)輸入的被測數(shù)據(jù)為A,它有兩個維度(或者說字段),分別是AX-1和AX2。B為訓練數(shù)據(jù)集,同理也有兩個維度,BX-1和BX2和,所以以上的計算公式即不同維度的差的平方的和的開方。
下面直接貼上代碼,每一段都附有注釋,希望童鞋們可以通過理解代碼的執(zhí)行來掌握整個KNN算法的流程。
# KNN算法主程序
def knnmain(inX,dataset,labels,k): #輸入量有(被測數(shù)據(jù),訓練數(shù)據(jù)集,訓練標簽集,K值),輸入量皆為數(shù)組形式
datasetsite=dataset.shape[0] #取訓練數(shù)據(jù)集的總數(shù)量n
inXdata=tile(inX,(datasetsite,1)) #將被測數(shù)據(jù)的數(shù)組復制為n行相同數(shù)組組成的二維數(shù)組,方便下面的歐式距離計算
sqdistance=inXdata-dataset #開始計算歐式距離,這里計算被測數(shù)據(jù)和訓練數(shù)據(jù)集之間相同維度的差
distance=sqdistance**2 #計算差的平方
dist=distance.sum(axis=1) #計算不同維度的差的平方的總和
lastdistance=dist**0.5 #將總和開方
sortnum=lastdistance.argsort() #返回從小到大(增序)的索引值
countdata={} #創(chuàng)建一個空字典用于儲存標簽和對應(yīng)的數(shù)量值
for i in range(k):
vlabels=labels[sortnum[i]] #將前k個距離最近的數(shù)據(jù)的標簽傳給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ù)最多的標簽
return sortnumzi[0][0] #返回出現(xiàn)次數(shù)最多的標簽值
整個KNN算法的核心思想是比較簡潔的,下面貼一個手寫數(shù)字識別的應(yīng)用。
一個文本文檔里儲存一個32*32的由1和0組成的圖像,差不多是下圖所示:
我們大概能識別出第一個圖片里是0,第二個圖片里是1,實際上每個文本文檔都有一個文檔名,如第一個圖片的文檔名就是"0_0.txt",那么我們就可以從文檔名里取得該圖片的標簽。我們有一個訓練文件夾,里面的文檔文件可以獲取并構(gòu)成訓練數(shù)據(jù)集和訓練標簽集。
我們也有一個測試文件夾,同理里面的文檔文件也可以獲取并構(gòu)成測試數(shù)據(jù)集和測試標簽集(拿來與預(yù)測結(jié)果做對比)。文件夾截圖如下:
下面直接貼上代碼幫助理解
先是一個將32*32的文本文檔轉(zhuǎn)化為1*1024的程序,因為我們寫的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ù)字識別程序:
def distinguish():
filestrain=listdir('trainingDigits') #打開訓練集文件夾
filestest=listdir('testDigits') #打開測試集文件夾
mtrain=len(filestrain) #訓練集文件數(shù)量
mtest=len(filestest) #測試集文件數(shù)量
allfilestrain=zeros((mtrain,1024)) #m行1024列的矩陣
allfilestest=zeros((mtest,1024))
labelstrain=[] #創(chuàng)造一個空列表用于儲存試驗向量的標簽
labelstest=[]
for i in range(mtrain):
nametrain=filestrain[i] #選取文件名
inX=open('trainingDigits/%s' % nametrain)
allfilestrain[i,:]=to_32(inX) ##把每個文件中的32*32矩陣轉(zhuǎn)換成1*1024的矩陣
label1=nametrain.split('.')[0]
label1=int(label1.split('_')[0]) #獲取每個數(shù)據(jù)的標簽
labelstrain.append(label1) #將所有標簽合成一個列表
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 #初始化判斷錯誤率
results=[]
for line in grouptest:
result=knnmain(line,grouptrain,labelstrain,3)
results.append(result)
errornum=0 ##初始化判斷錯誤數(shù)量
print 'the wrong prodiction as:'
for i in range(mtest):
if results[i] != labelstest[i]:
print 'result=',results[i],'labelstest=',labelstest[i] #輸出所有判斷錯誤的例子
errornum +=1
print 'the errornum is:',errornum #輸出判斷錯誤量
print 'the allnum is:',mtest #輸出總測試量
error=float(errornum/float(mtest))
print 'the error persent is:',error #輸出總測試錯誤率
該程序運行截圖如下:
我們看到錯誤率是比較低,說明該算法的精度是很高的。
結(jié)語:從上面例子的應(yīng)用來看,KNN算法的精度是很高,但是對噪聲有些敏感,我們觀察上面的運行結(jié)果,凡是判斷失誤的一般是兩個數(shù)字長得比較像,比如9和5,下面的勾很像,9和7,也是比較像的,也就是說,假如測試的數(shù)據(jù)有些偏于常態(tài),可能一個7長得比較歪,那就判斷為9了,這些都是噪聲,它對這些噪聲的數(shù)據(jù)是無法精準識別的,因為k值較小,下面會說到k值得取值問題。另有,它的計算相對復雜,若對象數(shù)據(jù)集巨大,則計算量也很大。當然,最重要的一點,對k值的把握很重要,這一般是根據(jù)具體情況來判斷,較大的k值能減少噪聲干擾,但會使分類界限模糊,較小的k值又容易被噪聲影響。一般取一個較小的k值,再通過交叉驗證來選取最優(yōu)k值。
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
SQL Server 中 CONVERT 函數(shù)的日期轉(zhuǎn)換:從基礎(chǔ)用法到實戰(zhàn)優(yōu)化 在 SQL Server 的數(shù)據(jù)處理中,日期格式轉(zhuǎn)換是高頻需求 —— 無論 ...
2025-09-18MySQL 大表拆分與關(guān)聯(lián)查詢效率:打破 “拆分必慢” 的認知誤區(qū) 在 MySQL 數(shù)據(jù)庫管理中,“大表” 始終是性能優(yōu)化繞不開的話題。 ...
2025-09-18CDA 數(shù)據(jù)分析師:表結(jié)構(gòu)數(shù)據(jù) “獲取 - 加工 - 使用” 全流程的賦能者 表結(jié)構(gòu)數(shù)據(jù)(如數(shù)據(jù)庫表、Excel 表、CSV 文件)是企業(yè)數(shù)字 ...
2025-09-18DSGE 模型中的 Et:理性預(yù)期算子的內(nèi)涵、作用與應(yīng)用解析 動態(tài)隨機一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開始提取前,需先判斷 TIF 文件的類型 —— ...
2025-09-17CDA 數(shù)據(jù)分析師:解鎖表結(jié)構(gòu)數(shù)據(jù)特征價值的專業(yè)核心 表結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 規(guī)范存儲的結(jié)構(gòu)化數(shù)據(jù),如數(shù)據(jù)庫表、Excel 表、 ...
2025-09-17Excel 導入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實戰(zhàn)應(yīng)用 在用 Python(如 pandas 庫)處理 Excel 數(shù)據(jù)時,“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗與 t 檢驗:差異、適用場景與實踐應(yīng)用 在數(shù)據(jù)分析與統(tǒng)計學領(lǐng)域,假設(shè)檢驗是驗證研究假設(shè)、判斷數(shù)據(jù)差異是否 “ ...
2025-09-16CDA 數(shù)據(jù)分析師:掌控表格結(jié)構(gòu)數(shù)據(jù)全功能周期的專業(yè)操盤手 表格結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 存儲的結(jié)構(gòu)化數(shù)據(jù),如 Excel 表、數(shù)據(jù) ...
2025-09-16MySQL 執(zhí)行計劃中 rows 數(shù)量的準確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調(diào)優(yōu)中,EXPLAIN執(zhí)行計劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對象的 text 與 content:區(qū)別、場景與實踐指南 在 Python 進行 HTTP 網(wǎng)絡(luò)請求開發(fā)時(如使用requests ...
2025-09-15CDA 數(shù)據(jù)分析師:激活表格結(jié)構(gòu)數(shù)據(jù)價值的核心操盤手 表格結(jié)構(gòu)數(shù)據(jù)(如 Excel 表格、數(shù)據(jù)庫表)是企業(yè)最基礎(chǔ)、最核心的數(shù)據(jù)形態(tài) ...
2025-09-15Python HTTP 請求工具對比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請求(如接口調(diào)用、數(shù)據(jù)爬取 ...
2025-09-12解決 pd.read_csv 讀取長浮點數(shù)據(jù)的科學計數(shù)法問題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長浮點數(shù)據(jù)時的科學計數(shù)法問題 ...
2025-09-12CDA 數(shù)據(jù)分析師:業(yè)務(wù)數(shù)據(jù)分析步驟的落地者與價值優(yōu)化者 業(yè)務(wù)數(shù)據(jù)分析是企業(yè)解決日常運營問題、提升執(zhí)行效率的核心手段,其價值 ...
2025-09-12用 SQL 驗證業(yè)務(wù)邏輯:從規(guī)則拆解到數(shù)據(jù)把關(guān)的實戰(zhàn)指南 在業(yè)務(wù)系統(tǒng)落地過程中,“業(yè)務(wù)邏輯” 是連接 “需求設(shè)計” 與 “用戶體驗 ...
2025-09-11塔吉特百貨孕婦營銷案例:數(shù)據(jù)驅(qū)動下的精準零售革命與啟示 在零售行業(yè) “流量紅利見頂” 的當下,精準營銷成為企業(yè)突圍的核心方 ...
2025-09-11CDA 數(shù)據(jù)分析師與戰(zhàn)略 / 業(yè)務(wù)數(shù)據(jù)分析:概念辨析與協(xié)同價值 在數(shù)據(jù)驅(qū)動決策的體系中,“戰(zhàn)略數(shù)據(jù)分析”“業(yè)務(wù)數(shù)據(jù)分析” 是企業(yè) ...
2025-09-11Excel 數(shù)據(jù)聚類分析:從操作實踐到業(yè)務(wù)價值挖掘 在數(shù)據(jù)分析場景中,聚類分析作為 “無監(jiān)督分組” 的核心工具,能從雜亂數(shù)據(jù)中挖 ...
2025-09-10統(tǒng)計模型的核心目的:從數(shù)據(jù)解讀到?jīng)Q策支撐的價值導向 統(tǒng)計模型作為數(shù)據(jù)分析的核心工具,并非簡單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10