1. 程式人生 > >機器學習實戰(一)k-近鄰算法

機器學習實戰(一)k-近鄰算法

復雜 ssi bsp 體重 工具 等級 lap 問題 種類

  轉載請註明源出處:http://www.cnblogs.com/lighten/p/7593656.html

1.原理

  本章介紹機器學習實戰的第一個算法——k近鄰算法(k Nearest Neighbor),也稱為kNN。說到機器學習,一般都認為是很復雜,很高深的內容,但實際上其學習門欄並不算高,具備基本的高等數學知識(包括線性代數,概率論)就可以了,甚至一些算法高中生就能夠理解了。kNN算法就是一個原理很好理解的算法,不需要多好的數學功底,這是一個分類算法(另一個大類是回歸),屬於監督學習的範疇(還有非監督學習,監督學習需要註有標記的訓練集)。

  首先,分類顧名思義就是給同一種事物分成不同的種類,比如人分成男人、女人,書分為工具書,教科書,漫畫書等。要對一個事物分類,要有分類的依據,即你為什麽這樣劃分,有時候劃分的依據十分準確比如男女按性別,但很多時候是由多個因素來決定劃分到哪一個類別,而不同的分類某一單一的因素又可能存在交集,這些因素在機器學習中被稱之為特征,特征的選擇對算法的準確率也是有影響的。個體用一組特征數據來進行描述,這樣計算機處理就成了可能,分類算法所要做的就是判斷這個個體所給出的特征屬於哪一個類別。方法有很多,kNN采取了一個最簡單的方法來判斷:判斷其與已知分類的訓練集數據的差異,差異最小的前k個訓練集個體大部分處於哪個分類該輸入個體就被認作是哪個分類

  這個原理很好理解,比如判斷男女,特征只有身高,體重。通常來說男人都比女人要高和重,即便女人要高,體重也比同等級的男人大部分會輕。所以對於一個輸入個體來說,在已知身高、體重的情況下,求其與訓練集樣本的身高、體重差異,找到訓練集中差異最小的k個個體,這k個個體如果大部分是男人,則輸入樣本就是男人,否則則是女人。選擇差異最小的k個個體也就是為了避免小部分不同尋常的樣本,因為男人都比女人要高和重也只是大部分情況,這樣選擇k個的權重,可信度就較高了。差異計算一般采用歐式距離,即各個特征相減,求平方和,開根號:

  技術分享

  上圖就是差異的定義了,這樣挑選出K個最小的訓練集,已知這些訓練集的分類,選擇K個訓練集大部分所屬的分類就是新輸入個體的分類了。

2.問題及優缺點

  kNN算法的原理簡單易懂,但是在實現過程中也是有些問題需要解決的。首先我們需要關註d的計算,kNN選擇的是d最小的k個訓練集個體,所以d的結果合理性是很重要的。但是由該公式可以很明顯的看出,d的大小很可能受到某一單一的特征影響。試想一下如果X的取值範圍在1~10,Y的取值範圍在1000~10000,那麽d的大小嚴重受到Y特征的影響,那麽X的作用就幾乎沒有了。解決該問題的方法就是將數值歸一化,意思就是不管X還是Y,按照合理的放縮方法,使他們落在同一個範圍區間,一般就選擇0~1之間了。這個放縮方法也並不難得出,公式如下:

技術分享

  優點:精度高,對異常值不敏感,無數據輸入假定

  缺點:計算復雜度高、空間復雜度高

  從kNN的實現上也能看出來,其計算代價較高,每個個體都需要和所有的訓練集個體進行比較,而且kNN算法無法獲得指定分類的一般性特征,因此其不適合大量的訓練集。

3.代碼

  下面代碼出自《機器學習實戰》一書,原書中所有代碼例子可以在網站:這裏。進行下載。

def 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, labels 

機器學習實戰(一)k-近鄰算法