機器學(xué)習(xí)算法之KNN(k-近鄰算法)

工作原理:(近朱者赤,近墨者黑)
存在一個樣本數(shù)據(jù)集合,也稱作訓(xùn)練樣本集,并且樣本集中每個數(shù)據(jù)都存在標(biāo)簽,即我們知道樣本集中每一數(shù)據(jù)與所屬分類的對應(yīng)關(guān)系。輸入沒有標(biāo)簽的新數(shù)據(jù)后,將新數(shù)據(jù)的每個特征與樣本集中數(shù)據(jù)對應(yīng)的特征進行比較然后算法提取樣本集中特征最相近數(shù)據(jù)(最近鄰)的分類標(biāo)簽。我們只選擇樣本數(shù)據(jù)集中前k個最相似的數(shù)據(jù),這也是為什么叫k-近鄰算法的出處。最后,選擇k個最相似的數(shù)據(jù)中出現(xiàn)次數(shù)最多的分類,作為新數(shù)據(jù)的分類。簡化說就是在樣本空間當(dāng)中找到與樣本A最接近的k個樣本,假設(shè)在這個k個樣本絕大多數(shù)屬于C分類,則樣本A也屬于分類C

算法偽代碼描述:

  1. 計算已知類別數(shù)據(jù)集中的點與當(dāng)前點的距離;
  2. 按照距離遞增的次序排序;
  3. 選取與當(dāng)前點距離最小的k個點;
  4. 確定前k個點所在類別出現(xiàn)的頻率;
  5. 返回前k個點出現(xiàn)頻率最高的類別作為當(dāng)前點的預(yù)測分類。

計算兩個向量點之間的距離采用歐氏距離公式:
sqrt((xa - xb)2 + (ya - yb)2)

python代碼實現(xiàn):

def classify0(inX, dataSet, labels, k):
    # shape 返回一個整型數(shù)字的元組,元組中的每個元素表示相應(yīng)的數(shù)組每一維的長度
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet
    sqDiffMat = diffMat ** 2

    # axis=1是將一個矩陣的每一行向量相加
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.5
    # 返回從小到大排序的索引
    sortedDistIndicies = distances.argsort() 

    # 創(chuàng)建一個字典,用于存儲前K個點所出現(xiàn)的頻率
    classCount = {}
    for i in range(k):
        voteLabel = labels[sortedDistIndicies[i]]
        classCount[voteLabel] = classCount.get(voteLabel, 0) + 1

    # 排序后返回的是一個List,而原字典中的鍵值對被轉(zhuǎn)換為了list中的元組。
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

但由于計算距離的時,數(shù)字差值最大的屬性對計算的結(jié)果影響最大,但每個特征是同等重要的,在處理這種不同取值范圍的特征值時,我們通常采用的方法是將數(shù)值歸一化,如將取值范圍處理為0到1或者-1到1之間。下面的公式可以將任意取值范圍的特征值轉(zhuǎn)化為0到1區(qū)間內(nèi)的值:

newValue = (oldValue - minValue) / (maxValue - minValue)

python代碼實現(xiàn):

# 數(shù)據(jù)歸一化:newValue = (oldValue - minValue) / (maxValue - minValue)
def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals  # (maxValue - minValue)
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]  # return number of line
    normDataSet = dataSet - tile(minVals, (m, 1))  # (oldValue - minValue)
    normDataSet = normDataSet / tile(ranges, (m, 1))  # (oldValue - minValue) / (maxValue - minValue)
    return normDataSet, ranges, minVals

k-近鄰算法是分類數(shù)據(jù)最簡單最有效的算法,k-近鄰算法是基于實例的學(xué)習(xí),使用算法時我們必須有接近實際數(shù)據(jù)的訓(xùn)練樣本數(shù)據(jù)。k-近鄰算法必須保存全部數(shù)據(jù)集,如果訓(xùn)練數(shù)據(jù)集很大,必須使用大量的存儲空間。此外,由于必須對數(shù)據(jù)集中每個數(shù)據(jù)計算距離值,實際使用時可能非常耗時。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容