【機(jī)器學(xué)習(xí)實(shí)戰(zhàn)】01-kNN近鄰算法

【博客的主要內(nèi)容主要是自己的學(xué)習(xí)筆記,并結(jié)合個(gè)人的理解,供各位在學(xué)習(xí)過(guò)程中參考,若有疑問(wèn),歡迎提出;若有侵權(quán),請(qǐng)告知博主刪除,原創(chuàng)文章轉(zhuǎn)載還請(qǐng)注明出處?!?/p>

1.什么是kNN#

k-近鄰算法(kNN k-NearestNeighbor)采用測(cè)量不同特征值之間的距離方法進(jìn)行分類(lèi)。在確定分類(lèi)決策上僅依據(jù)最鄰近的一個(gè)或多個(gè)樣本的類(lèi)別來(lái)決定待分樣本所屬類(lèi)別。

2.用途#

kNN算法主要被用于文本分類(lèi)、相似推薦.

3. kNN工作原理#

存在一個(gè)樣本數(shù)據(jù)集合(即訓(xùn)練樣本集),并且樣本集中每個(gè)數(shù)據(jù)都存在標(biāo)簽(即每個(gè)數(shù)據(jù)與所屬分類(lèi)的對(duì)應(yīng)關(guān)系)。輸入沒(méi)有標(biāo)簽的新數(shù)據(jù)之后,將新數(shù)據(jù)的每個(gè)特征與樣本集中數(shù)據(jù)對(duì)應(yīng)的特征進(jìn)行比較,算法將提取出樣本集中特征最相似數(shù)據(jù)(最近鄰)的分類(lèi)標(biāo)簽。

一般選擇樣本數(shù)據(jù)集中前K個(gè)最相似的數(shù)據(jù),k一般不大于20的整數(shù)。

說(shuō)明:圖中綠色圓點(diǎn)表示新數(shù)據(jù),藍(lán)色正方形和紅色三角形表示已分類(lèi)的樣本集。
如果K=3,由于紅色三角形所占比例為2/3,綠色圓點(diǎn)則屬于“紅色三角形”分類(lèi);
如果K=5,由于藍(lán)色正方形所占比例為3/5,綠色圓點(diǎn)則屬于“藍(lán)色正方形”分類(lèi)。

4. kNN算法流程#

使用K-近鄰算法將每組數(shù)據(jù)劃分到某個(gè)類(lèi)中:
1)計(jì)算已知類(lèi)別數(shù)據(jù)集中的點(diǎn)與當(dāng)前點(diǎn)之間的距離;



2)按照距離遞增次序排序;
3)選取與當(dāng)前點(diǎn)距離最小的K個(gè)點(diǎn);
4)確定前K個(gè)點(diǎn)所在類(lèi)別的出現(xiàn)頻率;
5)返回前K個(gè)點(diǎn)出現(xiàn)頻率最高的類(lèi)別作為當(dāng)前點(diǎn)的預(yù)測(cè)分類(lèi)。

5. kNN算法Code#

1.Python算法實(shí)現(xiàn)

from numpy import *
import  operator
from os import listdir

def classify0(inX, dataSet, labels,k):        
    #0、獲取數(shù)據(jù)Count
    dataSetSize = dataSet.shape[0]
    
    #1、計(jì)算距離
    diffMat = tile(inX,(dataSetSize,1)) - dataSet
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.5
    
    #2、選擇最小距離的k個(gè)點(diǎn)
    sortedDistIndicies = distances.argsort()
    
    #3、確定前K個(gè)點(diǎn)所在類(lèi)別的出現(xiàn)頻率
    classCount={}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    
    #4、返回前K個(gè)點(diǎn)出現(xiàn)頻率最高的類(lèi)別作為當(dāng)前點(diǎn)的預(yù)測(cè)分類(lèi)
    sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
    
    return sortedClassCount[0][0]  

2、kNN算法測(cè)試

def createDataSet():
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    return group,labels

6. kNN算法特點(diǎn)#

優(yōu)點(diǎn)
1、簡(jiǎn)單,易于理解,易于實(shí)現(xiàn),無(wú)需估計(jì)參數(shù),無(wú)需訓(xùn)練;
2、適合對(duì)稀有事件進(jìn)行分類(lèi);
3、適用于多分類(lèi)問(wèn)題。
缺點(diǎn)
1、計(jì)算復(fù)雜度高、空間復(fù)雜度高;
2、可理解性差,無(wú)法給出像決策樹(shù)類(lèi)的規(guī)則。

7. kNN示例分析#

7.1 示例1:使用k-近鄰算法改進(jìn)約會(huì)網(wǎng)站的配對(duì)效果##

1.背景
海倫通過(guò)在線(xiàn)約會(huì)網(wǎng)尋找自己合適的約會(huì)對(duì)象。根據(jù)自己一番總結(jié)將約會(huì)對(duì)象分為三類(lèi):
1、不喜歡的人;
2、魅力一般的人;
3、極具魅力的人.

海倫收集網(wǎng)站中每位約會(huì)對(duì)象的以下數(shù)據(jù)來(lái)劃分其約會(huì)類(lèi)型:
1、每年獲得的飛行公里數(shù);
2、玩視頻游戲所耗時(shí)間百分比;
3、每周消費(fèi)的冰淇淋公升數(shù).

編寫(xiě)個(gè)小程序,海倫輸入會(huì)員特征值程序顯示該會(huì)員所屬分類(lèi)。

2. 分析
1)收集數(shù)據(jù):提供文本文件
2)準(zhǔn)備數(shù)據(jù):使用Python解析文本文件
3)分析數(shù)據(jù):使用Matplotlib畫(huà)二維擴(kuò)散圖
4)訓(xùn)練數(shù)據(jù):不適合kNN
5)測(cè)試數(shù)據(jù):使用海倫提供的部分?jǐn)?shù)據(jù)作為測(cè)試樣本
6)使用算法:產(chǎn)生簡(jiǎn)單的命令行程序,然后海倫可以輸入一些特征數(shù)據(jù)以判斷是否為自己喜歡的類(lèi)型。

3. Code
使用Python解析文本文件

def file2matrix(filename):
     fr = open(filename)
     numberOfLines = len(fr.readlines())
     
     #初始化矩陣
    returnMat = zeros((numberOfLines,3))
         
     #初始化標(biāo)簽矩陣
     classLabelVector = []
         
     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

4. 使用Matplotlib畫(huà)二維擴(kuò)散圖

#讀取樣本數(shù)據(jù)   
datingDataMat,datingLabels = file2matrix('H:\workspacePy\machinelearninginaction\Ch02\datingTestSet2.txt')
             
#散點(diǎn)圖顯示樣本數(shù)據(jù)
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.font_manager 
             
fig = plt.figure()
ax = fig.add_subplot(111)
             
##1、散點(diǎn)圖顯示“玩視頻游戲所耗時(shí)間百分比”、“每周消費(fèi)的冰淇淋公升數(shù)”
ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels),15.0*array(datingLabels))
plt.show()
             
##2、散點(diǎn)圖顯示“每年獲得的飛行??屠锍虜?shù)”、“玩視頻游戲所耗時(shí)間百分比”
ax.scatter(datingDataMat[:,0],datingDataMat[:,1],15.0*array(datingLabels),15.0*array(datingLabels))
plt.show()

5.歸一化特征值

特征值數(shù)值間相差較大,在計(jì)算距離時(shí)易產(chǎn)生較大偏差。例如:


”每年獲得飛行??屠锍虜?shù)”遠(yuǎn)大于“玩視頻游戲所耗時(shí)間百分比”和“每周消費(fèi)冰淇淋公升數(shù)”,僅僅因?yàn)椤懊磕戢@得飛行??屠锍虜?shù)”遠(yuǎn)大于其它2個(gè)特征值,計(jì)算距離結(jié)果將放大。我們將“每年獲得飛行??屠锍虜?shù)”特征換算為“0到1”或“-1到1”之間,稱(chēng)為“歸一化特征值”

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))
    return normDataSet,ranges,minVals

6.測(cè)試算法

機(jī)器學(xué)習(xí)算法很大重要工作就是評(píng)估算法的正確率,通常將提供已有數(shù)據(jù)的90%作為訓(xùn)練樣本來(lái)訓(xùn)練分類(lèi)器,而使用其余的10%數(shù)據(jù)去測(cè)試分類(lèi)器,檢查分類(lèi)器的正確率。

def datingClassTest():
     hoRatio = 0.10
    datingDataMat,datingLabels = file2matrix('datingTestSet.txt')
     normDataSet,ranges,minVals = autoNorm(datingDataMat)
    m = normDataSet.shape[0]
    numTestVecs = int(m * hoRatio)
    errorCount = 0.0    
    for i in range(numTestVecs):
        classifierResult = classify0(normDataSet[i,:],normDataSet[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))

7.2 示例2:手寫(xiě)識(shí)別系統(tǒng)##

1. 背景
數(shù)字09,通過(guò)32*32位圖來(lái)展現(xiàn)?,F(xiàn)有1900個(gè)位圖數(shù)據(jù),分別表示了09數(shù)字內(nèi)容。需通過(guò)kNN方法能快速分辨出位圖的數(shù)字。

2. 分析
1)收集數(shù)據(jù):提供文本文件;
2)準(zhǔn)備數(shù)據(jù):將圖像格式轉(zhuǎn)換為分類(lèi)器使用的list格式;
3)分析數(shù)據(jù):在Python命令提示符中檢查數(shù)據(jù),確保它符合要求;
4)訓(xùn)練算法:不適合kNN算法;
5)測(cè)試數(shù)據(jù):編寫(xiě)函數(shù)使用提供的部分?jǐn)?shù)據(jù)集作為測(cè)試樣本,測(cè)試樣本與非測(cè)試樣本的區(qū)別在于測(cè)試樣本是已經(jīng)完成分類(lèi)的數(shù)據(jù),如果預(yù)測(cè)分類(lèi)與實(shí)際類(lèi)別不同,則標(biāo)記為一個(gè)錯(cuò)誤。
6)使用算法:省略

3.Code

#將32**32位圖片數(shù)據(jù)轉(zhuǎn)換為1*1024的list
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 returnVect

4.測(cè)試算法

#測(cè)試算法
def handwritingClassTest():
    #1、獲取樣本數(shù)據(jù)集合,
    hwLabels = []
    path = 'H:\\workspacePy\\machinelearninginaction\\Ch02\\digits\\trainingDigits'
    trainingFileList = listdir(path)
    m = len(trainingFileList)
    trainingMat = zeros((m,1024))
    
    #2、將樣本數(shù)據(jù)并轉(zhuǎn)換為list
    for i in range(m):
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)
        
        trainingMat[i,:] = img2vector(path + '/%s' % fileNameStr)
                
    #3、使用測(cè)試樣本進(jìn)行測(cè)試對(duì)比。
    path1 = 'H:\\workspacePy\\machinelearninginaction\\Ch02\\digits\\testDigits'
    testFileList = listdir(path1)
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        
        vectorUnderTest = img2vector(path1 + '/%s' % fileNameStr)
        
        ##knn
        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))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容