版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)指明轉(zhuǎn)載地址

www.cnblogs.com/fydeblog/p/7140974.html 

前言

這篇notebook是關(guān)于機(jī)器學(xué)習(xí)中監(jiān)督學(xué)習(xí)的k近鄰算法,將介紹2個(gè)實(shí)例,分別是使用k-近鄰算法改進(jìn)約會(huì)網(wǎng)站的效果和手寫識(shí)別系統(tǒng).
操作系統(tǒng):ubuntu14.04    運(yùn)行環(huán)境:anaconda-python2.7-notebook    參考書籍:機(jī)器學(xué)習(xí)實(shí)戰(zhàn)      notebook  writer ----方陽(yáng) 

k-近鄰算法(kNN)的工作原理:存在一個(gè)樣本數(shù)據(jù)集合,也稱作訓(xùn)練樣本集,并且樣本集中的每個(gè)數(shù)據(jù)都存在標(biāo)簽,即我們知道樣本集中每一組數(shù)據(jù)與所屬分類的對(duì)應(yīng)關(guān)系,輸入沒有標(biāo)簽的新數(shù)據(jù)后,將新數(shù)據(jù)的每個(gè)特征與樣本集中數(shù)據(jù)對(duì)應(yīng)的特征進(jìn)行比較,然后算法提取樣本集中特征最相似的分類標(biāo)簽。

注意事項(xiàng):在這里說一句,默認(rèn)環(huán)境python2.7的notebook,用python3.6的會(huì)出問題,還有我的目錄可能跟你們的不一樣,你們自己跑的時(shí)候記得改目錄,我會(huì)把notebook和代碼以及數(shù)據(jù)集放到結(jié)尾的百度云盤,方便你們下載!

1.改進(jìn)約會(huì)網(wǎng)站的匹配效果

1-1.準(zhǔn)備導(dǎo)入數(shù)據(jù)

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

1 from numpy import *2 import operator3 4 def createDataSet():5     group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])6     labels = ['A','A','B','B']7     return group, labels

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

先來點(diǎn)開胃菜,在上面的代碼中,我們導(dǎo)入了兩個(gè)模塊,一個(gè)是科學(xué)計(jì)算包numpy,一個(gè)是運(yùn)算符模塊,在后面都會(huì)用到,在createDataSet函數(shù)中,我們初始化了group,labels,我們將做這樣一件事,[1.0,1.1]和[1.0,1.0] 對(duì)應(yīng)屬于labels中 A 分類,[0,0]和[0,0.1]對(duì)應(yīng)屬于labels中的B分類,我們想輸入一個(gè)新的二維坐標(biāo),根據(jù)上面的坐標(biāo)來判斷新的坐標(biāo)屬于那一類,在這之前,我們要實(shí)現(xiàn)k-近鄰算法,下面就開始實(shí)現(xiàn)

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

 1 def classify0(inX, dataSet, labels, k): 2     dataSetSize = dataSet.shape[0]                  
 3     diffMat = tile(inX, (dataSetSize,1)) - dataSet 
 4     sqDiffMat = diffMat**2 5     sqDistances = sqDiffMat.sum(axis=1) 6     distances = sqDistances**0.5                    
 7     sortedDistIndicies = distances.argsort()     
 8     classCount={}          
 9     for i in range(k):10         voteIlabel = labels[sortedDistIndicies[i]]11         classCount[voteIlabel] = classCount.get(voteIlabel,0) + 112     sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)13     return sortedClassCount[0][0]

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

代碼解析:

函數(shù)的第一行是要得到數(shù)據(jù)集的數(shù)目,例如group.shape就是(4,2),shape[0]反應(yīng)數(shù)據(jù)集的行,shape[1]反應(yīng)列數(shù)

函數(shù)的第二行是array對(duì)應(yīng)相減,tile會(huì)生成關(guān)于Inx的dataSetSize大小的array,例如,InX是[0,0],則tile(InX,(4,1))是array([[0, 0], [0, 0], [0, 0],[0, 0]]),然后與dataSet對(duì)應(yīng)相減,得到新的array

函數(shù)的第三行是對(duì)第二步的結(jié)果進(jìn)行平方算法,方便下一步算距離

函數(shù)的第四行是進(jìn)行求和,注意是axis=1,也就是array每個(gè)二維數(shù)組成員進(jìn)行求和(行求和),如果是axis=0就是列求和

第五行是進(jìn)行平方距離的開根號(hào)

以上5行實(shí)現(xiàn)的是距離的計(jì)算 ,下面的是選出距離最小的k個(gè)點(diǎn),對(duì)類別進(jìn)行統(tǒng)計(jì),返回所占數(shù)目多的類別

classCount定義為存儲(chǔ)字典,里面有‘A’和‘B’,它們的值是在前k個(gè)距離最小的數(shù)據(jù)集中的個(gè)數(shù),本例最后classCount={'A':1,'B':2},函數(shù)argsort是返回array數(shù)組從小到大的排列的序號(hào),get函數(shù)返回字典的鍵值,由于后面加了1,所以每次出現(xiàn)鍵值就加1,就可以就算出鍵值出現(xiàn)的次數(shù)里。最后通過sorted函數(shù)將classCount字典分解為列表,sorted函數(shù)的第二個(gè)參數(shù)導(dǎo)入了運(yùn)算符模塊的itemgetter方法,按照第二個(gè)元素的次序(即數(shù)字)進(jìn)行排序,由于此處reverse=True,是逆序,所以按照從大到小的次序排列。

1-2.準(zhǔn)備數(shù)據(jù):從文本中解析數(shù)據(jù)

這上面是k-近鄰的一個(gè)小例子,我的標(biāo)題還沒介紹,現(xiàn)在來介紹標(biāo)題,準(zhǔn)備數(shù)據(jù),一般都是從文本文件中解析數(shù)據(jù),還是從一個(gè)例子開始吧!

本次例子是改進(jìn)約會(huì)網(wǎng)站的效果,我們定義三個(gè)特征來判別三種類型的人
特征一:每年獲得的飛行??屠锍虜?shù)
特征二:玩視頻游戲所耗時(shí)間百分比
特征三:每周消費(fèi)的冰淇淋公升數(shù)
根據(jù)以上三個(gè)特征:來判斷一個(gè)人是否是自己不喜歡的人,還是魅力一般的人,還是極具魅力的人

于是,收集了1000個(gè)樣本,放在datingTestSet2.txt中,共有1000行,每一行有四列,前三列是特征,后三列是從屬那一類人,于是問題來了,我們這個(gè)文本文件的輸入導(dǎo)入到python中來處理,于是需要一個(gè)轉(zhuǎn)換函數(shù)file2matrix,函數(shù)輸入是文件名字字符串,輸出是訓(xùn)練樣本矩陣(特征矩陣)和類標(biāo)簽向量

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

 1 def file2matrix(filename): 2     fr = open(filename) 3     numberOfLines = len(fr.readlines())         #get the number of lines in the file 4     returnMat = zeros((numberOfLines,3))        #prepare matrix to return 5     classLabelVector = []                       #prepare labels return    6     fr = open(filename) 7     index = 0 8     for line in fr.readlines(): 9         line = line.strip()10         listFromLine = line.split('\t')11         returnMat[index,:] = listFromLine[0:3]12         classLabelVector.append(int(listFromLine[-1]))13         index += 114     return returnMat,classLabelVector

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

這個(gè)函數(shù)比較簡(jiǎn)單,就不詳細(xì)說明里,這里只介紹以下一些函數(shù)的功能吧!
open函數(shù)是打開文件,里面必須是字符串,由于后面沒加‘w’,所以是讀文件
readlines函數(shù)是一次讀完文件,通過len函數(shù)就得到文件的行數(shù)
zeros函數(shù)是生成numberOfLines X 3的矩陣,是array型的
strip函數(shù)是截掉所有的回車符
split函數(shù)是以輸入?yún)?shù)為分隔符,輸出分割后的數(shù)據(jù),本例是制表鍵,最后輸出元素列表
append函數(shù)是向列表中加入數(shù)據(jù)

1-3.分析數(shù)據(jù):使用Matplotlib創(chuàng)建散點(diǎn)圖

首先,從上一步得到訓(xùn)練樣本矩陣和類標(biāo)簽向量,先更換一下路徑

cd /home/fangyang/桌面/machinelearninginaction/Ch02/
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

1 import matplotlib2 import matplotlib.pyplot as plt3 fig = plt.figure()4 ax =  fig.add_subplot(111)5 ax.scatter(datingDataMat[:,0], datingDataMat[:,1], 15.0*array(datingLabels), 15.0*array(datingLabels))  #scatter函數(shù)是用來畫散點(diǎn)圖的6 plt.show()

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

結(jié)果顯示

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

1-4. 準(zhǔn)備數(shù)據(jù): 歸一化處理

我們從上圖可以上出,橫坐標(biāo)的特征值是遠(yuǎn)大于縱坐標(biāo)的特征值的,這樣再算新數(shù)據(jù)和數(shù)據(jù)集的數(shù)據(jù)的距離時(shí),數(shù)字差值最大的屬性對(duì)計(jì)算結(jié)果的影響最大,我們就可能會(huì)丟失掉其他屬性,例如這個(gè)例子,每年獲取的飛行??屠锍虜?shù)對(duì)計(jì)算結(jié)果的影響遠(yuǎn)大于其余兩個(gè)特征,這是我們不想看到的,所以這里采用歸一化數(shù)值處理,也叫特征縮放,用于將特征縮放到同一個(gè)范圍內(nèi)。
本例的縮放公式    newValue = (oldValue - min) / (max - min)
其中min和max是數(shù)據(jù)集中的最小特征值和最大特征值。通過該公式可將特征縮放到區(qū)間(0,1)
下面是特征縮放的代碼

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

1 def autoNorm(dataSet):2     minVals = dataSet.min(0)3     maxVals = dataSet.max(0)4     ranges = maxVals - minVals5     normDataSet = zeros(shape(dataSet))6     m = dataSet.shape[0]7     normDataSet = dataSet - tile(minVals, (m,1))8     normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide9     return normDataSet, ranges, minVals

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

normDataSet(1000 X 3)是歸一化后的數(shù)據(jù),range(1X3)是特征的范圍差(即最大值減去最小值),minVals(1X3)是最小值。
原理上面已介紹,這里不在復(fù)述。

1-5.測(cè)試算法:作為完整程序驗(yàn)證分類器

好了,我們已經(jīng)有了k-近鄰算法、從文本解析出數(shù)據(jù)、還有歸一化處理,現(xiàn)在可以使用之前的數(shù)據(jù)進(jìn)行測(cè)試了,測(cè)試代碼如下

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

 1 def datingClassTest(): 2     hoRatio = 0.50      
 3     datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file 4     normMat, ranges, minVals = autoNorm(datingDataMat) 5     m = normMat.shape[0] 6     numTestVecs = int(m*hoRatio) 7     errorCount = 0.0 8     for i in range(numTestVecs): 9         classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)10         print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])11         if (classifierResult != datingLabels[i]): errorCount += 1.012     print "the total error rate is: %f" % (errorCount/float(numTestVecs))13     print errorCount

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

這里函數(shù)用到里之前講的三個(gè)函數(shù):file2matrix、autoNorm和classify0.這個(gè)函數(shù)將數(shù)據(jù)集分成兩個(gè)部分,一部分當(dāng)作分類器的訓(xùn)練樣本,一部分當(dāng)作測(cè)試樣本,通過hoRatio進(jìn)行控制,函數(shù)hoRatio是0.5,它與樣本總數(shù)相乘,將數(shù)據(jù)集平分,如果想把訓(xùn)練樣本調(diào)大一些,可增大hoRatio,但最好不要超過0.8,以免測(cè)試樣本過少,在函數(shù)的最后,加了錯(cuò)誤累加部分,預(yù)測(cè)出來的結(jié)果不等于實(shí)際結(jié)果,errorCount就加1,然后最后除以總數(shù)就得到錯(cuò)誤的概率。

說了這么多,都還沒有測(cè)試以下,下面來測(cè)試一下!先從簡(jiǎn)單的開始(已將上面的函數(shù)放在kNN.py中了)

1 import  kNN2 group , labels = kNN.createDataSet()
group   #結(jié)果在下
array([[ 1. ,  1.1],
       [ 1. ,  1. ],
       [ 0. ,  0. ],
       [ 0. ,  0.1]])
labels  #結(jié)果在下
['A', 'A', 'B', 'B']

這個(gè)小例子最開始提過,有兩個(gè)分類A和B,通過上面的group為訓(xùn)練樣本,測(cè)試新的數(shù)據(jù)屬于那一類

1 kNN.classify0([0,0], group, labels, 3)   #使用k-近鄰算法進(jìn)行測(cè)試
'B'    #結(jié)果是B分類

直觀地可以看出[0,0]是與B所在的樣本更近,下面來測(cè)試一下約會(huì)網(wǎng)站的匹配效果

先將文本中的數(shù)據(jù)導(dǎo)出來,由于前面在分析數(shù)據(jù)畫圖的時(shí)候已經(jīng)用到里file2matrix,這里就不重復(fù)用了。

datingDataMat   #結(jié)果在下

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

array([[  4.09200000e+04,   8.32697600e+00,   9.53952000e-01],
       [  1.44880000e+04,   7.15346900e+00,   1.67390400e+00],
       [  2.60520000e+04,   1.44187100e+00,   8.05124000e-01],
       ..., 
       [  2.65750000e+04,   1.06501020e+01,   8.66627000e-01],
       [  4.81110000e+04,   9.13452800e+00,   7.28045000e-01],
       [  4.37570000e+04,   7.88260100e+00,   1.33244600e+00]])

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

datingLabels  #由于過長(zhǎng),只截取一部分,詳細(xì)去看jupyter notebook

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

然后對(duì)數(shù)據(jù)進(jìn)行歸一化處理

1 normMat , ranges , minVals = kNN.autoNorm(datingDataMat)    #使用歸一化函數(shù)
normMat

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

array([[ 0.44832535,  0.39805139,  0.56233353],
       [ 0.15873259,  0.34195467,  0.98724416],
       [ 0.28542943,  0.06892523,  0.47449629],
       ..., 
       [ 0.29115949,  0.50910294,  0.51079493],
       [ 0.52711097,  0.43665451,  0.4290048 ],
       [ 0.47940793,  0.3768091 ,  0.78571804]])

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

ranges
array([  9.12730000e+04,   2.09193490e+01,   1.69436100e+00])
minVals
array([ 0.      ,  0.      ,  0.001156])

最后進(jìn)行測(cè)試,運(yùn)行之前的測(cè)試函數(shù)datingClassTest

1 kNN.datingClassTest()

由于過長(zhǎng),只截取一部分,詳細(xì)去看jupyter notebook

 電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

可以看到上面結(jié)果出現(xiàn)錯(cuò)誤32個(gè),錯(cuò)誤率6.4%,所以這個(gè)系統(tǒng)還算不錯(cuò)!

 1-6.系統(tǒng)實(shí)現(xiàn)

我們可以看到,測(cè)試固然不錯(cuò),但用戶交互式很差,所以結(jié)合上面,我們要寫一個(gè)完整的系統(tǒng),代碼如下:

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

 1 def classifyPerson(): 2     resultList = ['not at all', 'in small doses', 'in large doses'] 3     percentTats = float(raw_input("percentage of time spent playing video games?")) 4     ffMiles = float(raw_input("frequent flier miles earned per year?")) 5     iceCream = float(raw_input("liters of ice cream consumed per year?")) 6     datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') 7     normMat, ranges, minVals = autoNorm(datingDataMat) 8     inArr = array([ffMiles, percentTats, iceCream])     
 9     classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels,3)10     print "You will probably like this person" , resultList[classifierResult - 1]

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

運(yùn)行情況

1 kNN.classifyPerson()
percentage of time spent playing video games?10   #這里的數(shù)字都是用戶自己輸入的frequent flier miles earned per year?10000liters of ice cream consumed per year?0.5You will probably like this person in small doses

這個(gè)就是由用戶自己輸出參數(shù),并判斷出感興趣程度,非常友好

2. 手寫識(shí)別系統(tǒng)

下面再介紹一個(gè)例子,也是用k-近鄰算法,去實(shí)現(xiàn)對(duì)一個(gè)數(shù)字的判斷,首先我們是將寬高是32X32的像素的黑白圖像轉(zhuǎn)換成文本文件存儲(chǔ),但我們知道文本文件必須轉(zhuǎn)換成特征向量,才能進(jìn)入k-近鄰算法中進(jìn)行處理,所以我們需要一個(gè)img2vector函數(shù)去實(shí)現(xiàn)這個(gè)功能!

img2vector代碼如下:

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

1 def img2vector(filename):2     returnVect = zeros((1,1024))3     fr = open(filename)4     for i in range(32):5         lineStr = fr.readline()6         for j in range(32):7             returnVect[0,32*i+j] = int(lineStr[j])8     return returnVect

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

這個(gè)函數(shù)挺簡(jiǎn)單的,先用zeros生成1024的一維array,然后用兩重循環(huán),外循環(huán)以行遞進(jìn),內(nèi)循環(huán)以列遞進(jìn),將32X32的文本數(shù)據(jù)依次賦值給returnVect

好了,轉(zhuǎn)換函數(shù)寫好了,說一下訓(xùn)練集和測(cè)試集,所有的訓(xùn)練集都放在trainingDigits文件夾中,測(cè)試集放在testDigits文件夾中,訓(xùn)練集有兩千個(gè)樣本,0~9各有200個(gè),測(cè)試集大約有900個(gè)樣本,這里注意一點(diǎn),所有在文件夾里的命名方式是有要求的,我們是通過命名方式來解析出它的真實(shí)數(shù)字,然后與通過k-近鄰算法得出的結(jié)果相對(duì)比,例如945.txt,這里的數(shù)字是9,連接符前面的數(shù)字就是這個(gè)樣本的真實(shí)數(shù)據(jù)。該系統(tǒng)實(shí)現(xiàn)的方法與前面的約會(huì)網(wǎng)站的類似,就不多說了。

系統(tǒng)測(cè)試代碼如下

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

 1 def handwritingClassTest(): 2     hwLabels = [] 3     trainingFileList = listdir('trainingDigits')           #load the training set 4     m = len(trainingFileList) 5     trainingMat = zeros((m,1024)) 6     for i in range(m): 7         fileNameStr = trainingFileList[i] 8         fileStr = fileNameStr.split('.')[0]     #take off .txt 9         classNumStr = int(fileStr.split('_')[0])10         hwLabels.append(classNumStr)11         trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)12     testFileList = listdir('testDigits')        #iterate through the test set13     errorCount = 0.014     mTest = len(testFileList)15     for i in range(mTest):16         fileNameStr = testFileList[i]17         fileStr = fileNameStr.split('.')[0]     #take off .txt18         classNumStr = int(fileStr.split('_')[0])19         vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)20         classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)21         print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)22         if (classifierResult != classNumStr): errorCount += 1.023     print "\nthe total number of errors is: %d" % errorCount24     print "\nthe total error rate is: %f" % (errorCount/float(mTest))

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

這里的listdir是從os模塊導(dǎo)入的,它的功能是列出給定目錄下的所有文件名,以字符串形式存放,輸出是一個(gè)列表
這里的split函數(shù)是要分離符號(hào),得到該文本的真實(shí)數(shù)據(jù),第一個(gè)split函數(shù)是以小數(shù)點(diǎn)為分隔符,例如‘1_186.txt’ ,就變成了['1_186','txt'],然后取出第一個(gè),就截掉了.txt,第二個(gè)split函數(shù)是以連接符_為分隔符,就截掉后面的序號(hào),剩下前面的字符數(shù)據(jù)‘1’,然后轉(zhuǎn)成int型就得到了它的真實(shí)數(shù)據(jù),其他的沒什么,跟前面一樣

下面開始測(cè)試

1 kNN.handwritingClassTest()

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

我們可以看到最后結(jié)果,錯(cuò)誤率1.2%, 可見效果還不錯(cuò)!

這里把整個(gè)kNN.py文件貼出來,主要是上面已經(jīng)介紹的函數(shù)

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

'''Input:      inX: vector to compare to existing dataset (1xN)
            dataSet: size m data set of known vectors (NxM)
            labels: data set labels (1xM vector)
            k: number of neighbors to use for comparison (should be an odd number)
            
Output:     the most popular class label'''from numpy import *import operatorfrom os import listdirdef classify0(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()     
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)    return sortedClassCount[0][0]def createDataSet():
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']    return group, labelsdef file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #get the number of lines in the file
    returnMat = zeros((numberOfLines,3))        #prepare matrix to return
    classLabelVector = []                       #prepare labels return   
    fr = open(filename)
    index = 0    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1    return returnMat,classLabelVector    
def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m,1))
    normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals   
def datingClassTest():
    hoRatio = 0.50      #hold out 10%
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)        print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])        if (classifierResult != datingLabels[i]): errorCount += 1.0    print "the total error rate is: %f" % (errorCount/float(numTestVecs))    print errorCount    
def classifyPerson():
    resultList = ['not at all', 'in small doses', 'in large doses']
    percentTats = float(raw_input("percentage of time spent playing video games?"))
    ffMiles = float(raw_input("frequent flier miles earned per year?"))
    iceCream = float(raw_input("liters of ice cream consumed per year?"))
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = array([ffMiles, percentTats, iceCream])     
    classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels,3)    print "You will probably like this person" , resultList[classifierResult - 1]    
def img2vector(filename):
    returnVect = zeros((1,1024))
    fr = open(filename)    for i in range(32):
        lineStr = fr.readline()        for j in range(32):
            returnVect[0,32*i+j] = int(lineStr[j])    return returnVectdef handwritingClassTest():
    hwLabels = []
    trainingFileList = listdir('trainingDigits')           #load the training set
    m = len(trainingFileList)
    trainingMat = zeros((m,1024))    for i in range(m):
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]     #take off .txt
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)
        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)
    testFileList = listdir('testDigits')        #iterate through the test set
    errorCount = 0.0
    mTest = len(testFileList)    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]     #take off .txt
        classNumStr = int(fileStr.split('_')[0])
        vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)        print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)        if (classifierResult != classNumStr): errorCount += 1.0    print "\nthe total number of errors is: %d" % errorCount    print "\nthe total error rate is: %f" % (errorCount/float(mTest))

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

結(jié)尾

至此,這個(gè)k-近鄰算法的介紹到這里就結(jié)束了,希望這篇文章對(duì)你的學(xué)習(xí)有幫助!

百度云鏈接: https://http://www.cnblogs.com/fydeblog/p/7140974.htmlpan.baidu.com/s/1mhLcAy0 密碼: e8dp

http://www.cnblogs.com/fydeblog/p/7140974.html