
機器學(xué)習(xí)之k-近鄰(kNN)算法與Python實現(xiàn)
k-近鄰算法(kNN,k-NearestNeighbor),是最簡單的機器學(xué)習(xí)分類算法之一,其核心思想在于用距離目標(biāo)最近的k個樣本數(shù)據(jù)的分類來代表目標(biāo)的分類(這k個樣本數(shù)據(jù)和目標(biāo)數(shù)據(jù)最為相似)。
一 k-近鄰(kNN)算法概述
1.概念
kNN算法的核心思想是用距離最近的k個樣本數(shù)據(jù)的分類來代表目標(biāo)數(shù)據(jù)的分類。
其原理具體地講,存在一個訓(xùn)練樣本集,這個數(shù)據(jù)訓(xùn)練樣本的數(shù)據(jù)集合中的每個樣本都包含數(shù)據(jù)的特征和目標(biāo)變量(即分類值),輸入新的不含目標(biāo)變量的數(shù)據(jù),將該數(shù)據(jù)的特征與訓(xùn)練樣本集中每一個樣本進行比較,找到最相似的k個數(shù)據(jù),這k個數(shù)據(jù)出席那次數(shù)最多的分類,即輸入的具有特征值的數(shù)據(jù)的分類。
例如,訓(xùn)練樣本集中包含一系列數(shù)據(jù),這個數(shù)據(jù)包括樣本空間位置(特征)和分類信息(即目標(biāo)變量,屬于紅色三角形還是藍(lán)色正方形),要對中心的綠色數(shù)據(jù)的分類。運用kNN算法思想,距離最近的k個樣本的分類來代表測試數(shù)據(jù)的分類,那么:
當(dāng)k=3時,距離最近的3個樣本在實線內(nèi),具有2個紅色三角和1個藍(lán)色正方形**,因此將它歸為紅色三角。
當(dāng)k=5時,距離最近的5個樣本在虛線內(nèi),具有2個紅色三角和3個藍(lán)色正方形**,因此將它歸為藍(lán)色正方形。
2.特點
優(yōu)點
(1)監(jiān)督學(xué)習(xí):可以看到,kNN算法首先需要一個訓(xùn)練樣本集,這個集合中含有分類信息,因此它屬于監(jiān)督學(xué)習(xí)。
(2)通過計算距離來衡量樣本之間相似度,算法簡單,易于理解和實現(xiàn)。
(3)對異常值不敏感
缺點 (4)需要設(shè)定k值,結(jié)果會受到k值的影響,通過上面的例子可以看到,不同的k值,最后得到的分類結(jié)果不盡相同。k一般不超過20。(5)計算量大,需要計算樣本集中每個樣本的距離,才能得到k個最近的數(shù)據(jù)樣本。 (6)訓(xùn)練樣本集不平衡導(dǎo)致結(jié)果不準(zhǔn)確問題。當(dāng)樣本集中主要是某個分類,該分類數(shù)量太大,導(dǎo)致近鄰的k個樣本總是該類,而不接近目標(biāo)分類。
3.kNN算法流程
一般情況下,kNN有如下流程:
(1)收集數(shù)據(jù):確定訓(xùn)練樣本集合測試數(shù)據(jù);
(2)計算測試數(shù)據(jù)和訓(xùn)練樣本集中每個樣本數(shù)據(jù)的距離;
常用的距離計算公式:
(3)按照距離遞增的順序排序;
(4)選取距離最近的k個點;
(5)確定這k個點中分類信息的頻率;
(6)返回前k個點中出現(xiàn)頻率最高的分類,作為當(dāng)前測試數(shù)據(jù)的分類。二 、Python算法實現(xiàn)
1.KNN算法分類器
建立一個名為“KNN.py”的文件,構(gòu)造一個kNN算法分類器的函數(shù):
from numpy import *
import operator
#定義KNN算法分類器函數(shù)
#函數(shù)參數(shù)包括:(測試數(shù)據(jù),訓(xùn)練數(shù)據(jù),分類,k值)
def classify(inX,dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = tile(inX,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
sqDistances=sqDiffMat.sum(axis=1)
distances=sqDistances**0.5 #計算歐式距離
sortedDistIndicies=distances.argsort() #排序并返回index
#選擇距離最近的k個值
classCount={}
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]]
#D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
#排序
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
在KNN.py中定義一個生成“訓(xùn)練樣本集”的函數(shù):
#定義一個生成“訓(xùn)練樣本集”的函數(shù),包含特征和分類信息在Python控制臺先將當(dāng)前目錄設(shè)置為“KNN.py”所在的文件目錄,將測試數(shù)據(jù)[0,0]進行KNN算法分類測試,輸入:
import KNN
#生成訓(xùn)練樣本
group,labels=KNN.createDataSet()
#對測試數(shù)據(jù)[0,0]進行KNN算法分類測試
KNN.classify([0,0],group,labels,3)
Out[3]: 'B'
可以看到該分類器函數(shù)將[0,0]分類為B組,符合實際情況,分入了符合邏輯的正確的類別。但如何知道KNN分類的正確性呢?
2.kNN算法用于約會網(wǎng)站配對
2.1準(zhǔn)備數(shù)據(jù)
該數(shù)據(jù)在文本文件datingTestSet2.txt中,該數(shù)據(jù)具有1000行,4列,分別是特征數(shù)據(jù)(每年獲得的飛行??屠锍虜?shù),玩視頻游戲所耗時間百分比,每周消費的冰淇淋公升數(shù)),和目標(biāo)變量/分類數(shù)據(jù)(是否喜歡(1表示不喜歡,2表示魅力一般,3表示極具魅力)),部分?jǐn)?shù)據(jù)展示如下:
完整地數(shù)據(jù)下載地址如下:
約會網(wǎng)站測試數(shù)據(jù)
(1)將文本記錄轉(zhuǎn)為成numpy
在python控制臺輸入:
in [5]:datingDataMat,datingLabels=KNN.file2matrix('G:\Workspaces\MachineLearning\machinelearninginaction\Ch02\datingTestSet2.txt')#括號是文件路徑
(2)可視化分析數(shù)據(jù)
運用Matplotlib創(chuàng)建散點圖來分析數(shù)據(jù):
import matplotlib
import matplotlib.pyplot as plt
#對第二列和第三列數(shù)據(jù)進行分析:
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],c=datingLabels)
plt.xlabel('Percentage of Time Spent Playing Video Games')
plt.ylabel('Liters of Ice Cream Consumed Per Week')
#對第一列和第二列進行分析:
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(datingDataMat[:,0],datingDataMat[:,1],c=datingLabels)
plt.xlabel('Miles of plane Per year')
plt.ylabel('Percentage of Time Spent Playing Video Games')
ax.legend(loc='best')
(3)數(shù)據(jù)歸一化
由于不同的數(shù)據(jù)在大小上差別較大,在計算歐式距離,整體較大的數(shù)據(jù)明細(xì)所占的比重更高,因此需要對數(shù)據(jù)進行歸一化處理。
在Python控制臺輸入:
reload(KNN)數(shù)據(jù)的準(zhǔn)備工作完成,下一步對算法進行測試。
2.2 算法測試
kNN算法分類的結(jié)果的效果,可以使用正確率/錯誤率來衡量,錯誤率為0,則表示分類很完美,如果錯誤率為1,表示分類完全錯誤。我們使用1000條數(shù)據(jù)中的90%作為訓(xùn)練樣本集,其中的10%來測試錯誤率。
#定義測試算法的函數(shù)在控制臺輸入命令來測試錯誤率:
reload(KNN)
Out[150]: <module 'KNN' from 'G:\\Workspaces\\MachineLearning\\KNN.py'>
KNN.datingClassTest()
the classifier came back with: 3,the real answer is: 3
the classifier came back with: 2,the real answer is: 2
the classifier came back with: 1,the real answer is: 1
... ...
the classifier came back with: 2,the real answer is: 2
the classifier came back with: 1,the real answer is: 1
the classifier came back with: 3,the real answer is: 1
the total error rate is : 0.050000
可以看到KNN算法分類器處理約會數(shù)據(jù)的錯誤率是5%,具有較高額正確率。
可以在datingClassTest函數(shù)中傳入?yún)?shù)h來改變測試數(shù)據(jù)比例,來看修改后Ration后錯誤率有什么樣的變化。
KNN.datingClassTest(0.2)
the classifier came back with: 3,the real answer is: 3
the classifier came back with: 2,the real answer is: 2
the classifier came back with: 1,the real answer is: 1
... ...
the classifier came back with: 2,the real answer is: 2
the classifier came back with: 3,the real answer is: 3
the classifier came back with: 2,the real answer is: 2
the total error rate is : 0.080000
減小訓(xùn)練樣本集數(shù)據(jù),增加測試數(shù)據(jù),錯誤率增加到8%。
2.3 使用KNN算法進行預(yù)測
def classifypersion():測試一下:
reload(KNN)
Out[153]: <module 'KNN' from 'G:\\Workspaces\\MachineLearning\\KNN.py'>
KNN.classifypersion()
percentage of time spent playing video games?10
frequent flier miles earned per year?10000
liters of ice creamconsued per year?0.5
You will probably like this persion :not at all
3. KNN算法用于手寫識別系統(tǒng)
已經(jīng)將圖片轉(zhuǎn)化為32*32 的文本格式,文本格式如下:
00000000000111110000000000000000
00000000001111111000000000000000
00000000011111111100000000000000
00000000111111111110000000000000
00000001111111111111000000000000
00000011111110111111100000000000
00000011111100011111110000000000
00000011111100001111110000000000
00000111111100000111111000000000
00000111111100000011111000000000
00000011111100000001111110000000
00000111111100000000111111000000
00000111111000000000011111000000
00000111111000000000011111100000
00000111111000000000011111100000
00000111111000000000001111100000
00000111111000000000001111100000
00000111111000000000001111100000
00000111111000000000001111100000
00000111111000000000001111100000
00000011111000000000001111100000
00000011111100000000011111100000
00000011111100000000111111000000
00000001111110000000111111100000
00000000111110000001111111000000
00000000111110000011111110000000
00000000111111000111111100000000
00000000111111111111111000000000
00000000111111111111110000000000
00000000011111111111100000000000
00000000001111111111000000000000
00000000000111111110000000000000
3.1數(shù)據(jù)準(zhǔn)備
(1)將32*32的文本格式轉(zhuǎn)為成1*2014的向量
在控制臺中輸入命令測試下函數(shù):
reload(KNN)
3.2 算法測試
使用kNN算法測試手寫數(shù)字識別
#引入os模塊的listdir函數(shù),列出給定目錄的文件名
from os impor listdir
def handwritingClassTest():
hwLabels=[]
trainingFileList=listdir('G:/Workspaces/MachineLearning/machinelearninginaction/Ch02/trainingDigits')#列出文件名
m=len(trainingFileList) #文件數(shù)目
trainMat=zeros((m,1024))
#從文件名中解析分類信息,如0_13.txt
for i in range(m):
fileNameStr=trainingFileList[i]
fileStr=fileNameStr.split('.')[0]
classNumber=int(fileStr.split('_')[0])
hwLabels.append(classNumber)
trainMat[i]=img2vector('G:/Workspaces/MachineLearning/machinelearninginaction/Ch02/trainingDigits/%s'%fileNameStr)
testFileList=listdir('G:/Workspaces/MachineLearning/machinelearninginaction/Ch02/testDigits')
errorCount=0
#同上,解析測試數(shù)據(jù)的分類信息
mTest=len(testFileList)
for i in range(mTest):
fileNameStr=testFileList[i]
fileStr=fileNameStr.split('.')[0]
classNumber=int(fileStr.split('_')[0])
vectorUnderTest=img2vector('G:/Workspaces/MachineLearning/machinelearninginaction/Ch02/testDigits/%s'%fileNameStr)
classifierResult=classify(vectorUnderTest,trainMat,hwLabels,3)
print('the classifier came back with :%d,the real answer is:%d'%(classifierResult,classNumber))
if(classifierResult!=classNumber):errorCount+=1
print('\n the total number of errors is: %d'%errorCount)
print('\n total error rate is %f'%(errorCount/float(mTest)))
接下來在Python控制臺輸入命令來測試手寫數(shù)字識別:
reload(KNN)
KNN.handwritingClassTest()
the classifier came back with :0,the real answer is:0
the classifier came back with :0,the real answer is:0
the classifier came back with :0,the real answer is:0
... ...
the classifier came back with :9,the real answer is:9
the classifier came back with :9,the real answer is:9
the classifier came back with :9,the real answer is:9
the total number of errors is: 10
total error rate is 0.010571
錯誤利率1.057%,具有較高的準(zhǔn)確率。
數(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)查詢效率:打破 “拆分必慢” 的認(rè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 導(dǎo)入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實戰(zhàn)應(yīng)用 在用 Python(如 pandas 庫)處理 Excel 數(shù)據(jù)時,“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗與 t 檢驗:差異、適用場景與實踐應(yīng)用 在數(shù)據(jù)分析與統(tǒng)計學(xué)領(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ù)量的準(zhǔn)確性解析:原理、影響因素與優(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ù)的科學(xué)計數(shù)法問題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長浮點數(shù)據(jù)時的科學(xué)計數(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ū)動下的精準(zhǔn)零售革命與啟示 在零售行業(yè) “流量紅利見頂” 的當(dāng)下,精準(zhǔn)營銷成為企業(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策支撐的價值導(dǎo)向 統(tǒng)計模型作為數(shù)據(jù)分析的核心工具,并非簡單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10