機器學習筆記(二)——k-近鄰算法

k-鄰近算法概述

 

k-鄰近算法採用測量不同特徵值之間的距離方法進行分類

 

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

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

使用數據範圍:數值型和標稱型

 

工作原理:存在一個樣本數據集合(也稱作訓練樣本集),並且樣本集中每個數據都存在標籤,即我們知道樣本集中每一數據與所屬的對應關係。輸入沒有標籤的新數據後,將新數據的每個特徵與樣本集中數據對應的特徵進行比較,然後算法提取樣本集中特徵最相似數據(最鄰近)的分類標籤。一般來說,選取樣本數據集中前k個最相似的數據,這就是k-近鄰算法中k的出處,通常k是不大於20的整數。最後,選擇k個最相似數據中出現次數最多的分類,作爲新數據的分類。

 

k-鄰近算法代碼分析:

對未知類別屬性的數據集中的每個點依次執行以下操作:

(1)計算已知類別數據集中的點與當前點之間的距離;

(2)按照距離遞增次序排序;

(3)選取與當前點距離最小的k個點;

(4)確定前k個點所在類別的出現頻率;

(5)返回前k個點出現頻率最高的類別作爲當前點的預測分類。

 

代碼如下:

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]


代碼註解:

1shape[0] 計算矩陣的行數,shape[1]計算矩陣的列數

2tile 數組inXdataSetSize1列重複,例如:intX [0, 0],則tile計算後

          [0, 0]

          [0, 0]

          [0, 0]

          [0, 0]  

           .....   dataSetSize

3** 是指次方, diffMat**2 diffMat的平方比如[1, 2]**2 = [1, 4]

4sqDiffMat.sum(axis=1) array中每行元素的和,這些和再組成一個array

  例如: >>>a = array([[1, 2], [2, 4]])

       >>>s = a.sum(axis=1)

       >>>s

       array([3, 6]) 

       >>>a = array([[1, 2, 3], [2, 3, 4]])

       >>>s = a.sum(axis=1)

       >>>s

       array([6, 9])

  但是如果array只有一行,例如array([1, 2]), 則不能用sum(axis=1),只能用sum()

5classCount = {}新建一個dict, dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value,這裏classCount.get(voteIlabel, 0)是指不存在相對應key值的value則返回0

  例如:   >>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

        >>> d['Michael']

       95

       >>> d['Thomas']

       Traceback (most recent call last):

         File "<stdin>", line 1, in <module>

       KeyError: 'Thomas'

  要避免key不存在的錯誤,有兩種辦法,一是通過in判斷key是否存在:

      >>> 'Thomas' in d

      False

  二是通過dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value

      >>> d.get('Thomas')

      >>> d.get('Thomas', -1)

      -1

6sorted() classCount字典的第2個元素(即類別出現的次數)從大到小排序

 

測試代碼運行效果:

    kNN.py文件:

from numpy import *
import operator
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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章