1. 程式人生 > >機器學習-KNN分類器

機器學習-KNN分類器

pos show sha key borde 不同 簡單的 測試 solid

1. K-近鄰(k-Nearest NeighborsKNN)的原理

通過測量不同特征值之間的距離來衡量相似度的方法進行分類。

2. KNN算法過程

訓練樣本集:樣本集中每個特征值都已經做好類別標簽;

測試樣本: 測試樣本中每個特征值都沒有類別標簽;

算法過程: 計算測試樣本中特征值與訓練樣本集中的每個特征值之間的距離,提取與訓練樣本集中的特征值距離最近的前K個樣本,然後選取出現次數最多的類別標簽,作為測試樣本的類別標簽。

3. 度量特征值之間距離的方法

(1) 歐氏距離

可稱為L2範數:

技術分享

其中p=2,則特征向量a=(a1,a2,…,am)和特征向量b=( b

1,b2,…,bm)之間的距離為

技術分享


又稱歐式距離。

例如二維平面上的兩點a(x1, y1)b(x2, y2)之間的歐式距離:

技術分享

d值越小,表明特征值之間距離越小,兩個特征越相似。

(2) 夾角余弦

特征向量a=(a1,a2,…,am)和特征向量b=( b1,b2,…,bm)之間的夾角余弦為:

技術分享


cos值越大,表明特征值之間距離越小,兩個特征越相似。

4. 一個簡單的例子

Python代碼示例:

# coding: utf-8

from numpy import *
import operator
import matplotlib.pyplot as plt

def createDataSet(): # 生成訓練集 group = array([[1.0, 1.1], [0.9, 1.3], [ 0, 0.1], [0.1, 0.2]]) labels = [A, A, B, B] return group, labels def showDataSet(dataSet, labels): # 顯示訓練集 fig = plt.figure() ax = fig.add_subplot(111) index = 0 for point in dataSet: if labels[index] ==
A: ax.scatter(point[0], point[1], c=blue) ax.annotate("A", xy = (point[0], point[1])) else: ax.scatter(point[0], point[1], c=red) ax.annotate("B", xy = (point[0], point[1])) index += 1 plt.show() def eulerDist(inXmat, dataSet): # 使用歐式距離 diffMat = inXmat - dataSet # 輸入向量分別與樣本中其他的向量之差 sqDiffMat = diffMat**2 # 差值求平方 sqDistances = sqDiffMat.sum(axis=1) # axis=1將一個矩陣的每一行向量相加, 將差值相加 dist = sqDistances**0.5 # 開方 return dist def cosDist(inXmat, dataSet): # 使用夾角余弦 m = shape(inXmat)[0] dist = zeros((m)) # 與訓練集中每一個特征求距離 for i in range(m): cos = dot(inXmat[i,:], dataSet[i,:])/(linalg.norm(inXmat[i,:])*linalg.norm(dataSet[i,:])) # 求余弦值 dist[i] = cos return dist def KNNclassify(inX, dataSet, labels, k): dataSetSize = dataSet.shape[0] # 行數 inXmat = tile(inX, (dataSetSize, 1)) # tile(A,reps)若reps為一個元組(m,n),則構造一個m行n列的數組,其中每個元素均為A, # 目的是求inX分別與其他dataSet的數據間的距離 distance = eulerDist(inXmat, dataSet) # 使用歐式距離度量向量間距離 sortedDistIndicies = distance.argsort() # 對一個數組進行升序排列,結果返回的就是a中所有元素排序後各個元素在a中之前的下標 #distance = cosDist(inXmat, dataSet) # 使用夾角余弦度量向量間距離 #sortedDistIndicies = argsort(-distance) # 降序排列 classcount = {} # 字典 for i in range(k): voteIlabel = labels[sortedDistIndicies[i]] classcount[voteIlabel] = classcount.get(voteIlabel,0) + 1 # dict.get(key, default=None) key:字典中要查找的鍵。 # default -- 如果指定鍵的值不存在時,返回該默認值。 # classcount.iteritems()返回一個叠代器。返回一個可以調用的對象(可以從操作對象中提取item) # operator.itemgetter函數獲取的不是值,而是定義了一個函數。獲取對象的第1個域的值在這裏使用字典中的值進行從小到大進行排序 # sorted(iterable, cmp, key, reverse),iterable指定要排序的list或者iterable, # cmp為函數,指定排序時進行比較的函數,可以指定一個函數或者lambda函數 # key為函數,指定取待排序元素的哪一項進行排序 # reverse默認為false(升序排列),定義為True時將按降序排列。 sortedClassCount = sorted(classcount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] dataSet, labels = createDataSet(); # 生成訓練集 showDataSet(dataSet,labels) # 顯示訓練集 inX = array([1, 1]) # 輸入一個測試樣本 classLabel = KNNclassify(inX, dataSet, labels, 3) # 使用KNN進行分類 print classLabel # 輸入分類之後所屬的標簽

執行結果:

技術分享

-tany 2017年10月4日 中秋 於杭州

機器學習-KNN分類器