寫在前面
額、、、最近開始學習機器學習嘛,網上找到一本關於機器學習的書籍,名字叫做《機器學習實戰》。很巧的是,這本書裡的演算法是用Python語言實現的,剛好之前我學過一些Python基礎知識,所以這本書對於我來說,無疑是雪中送炭啊。接下來,我還是給大家講講實際的東西吧。
什麼是K-近鄰演算法?
簡單的說,K-近鄰演算法就是採用測量不同特徵值之間的距離方法來進行分類。它的工作原理是:存在一個樣本資料集合,也稱作訓練樣本集,並且樣本集中每個資料都存在標籤,即我們知道樣本集中每一資料與所屬分類的對應關係,輸入沒有標籤的新資料之後,將新資料的每個特徵與樣本集中資料對應的特徵進行比較,然後演算法提取出樣本集中特徵最相似資料的分類標籤。一般來說,我們只選擇樣本資料集中前k個最相似的資料,這就是K-近鄰演算法名稱的由來。
提問:親,你造K-近鄰演算法是屬於監督學習還是無監督學習呢?
使用Python匯入資料
從K-近鄰演算法的工作原理中我們可以看出,要想實施這個演算法來進行資料分類,我們手頭上得需要樣本資料,沒有樣本資料怎麼建立分類函式呢。所以,我們第一步就是匯入樣本資料集合。
建立名為kNN.py的模組,寫入程式碼:
1 2 3 4 5 6 7 |
1 from numpy import * 2 import operator 3 4 def createDataSet(): 5 group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) 6 labels = ['A','A','B','B'] 7 return group, labels |
程式碼中,我們需要匯入Python的兩個模組:科學計算包NumPy和運算子模組。NumPy函式庫是Python開發環境的一個獨立模組,大多數Python版本里沒有預設安裝NumPy函式庫,因此這裡我們需要單獨安裝這個模組。
下載戳這裡:NumPy
有很多的版本,這裡我選擇的是numpy-1.7.0-win32-superpack-python2.7.exe。
實現K-近鄰演算法
K-近鄰演算法的具體思想如下:
(1)計算已知類別資料集中的點與當前點之間的距離
(2)按照距離遞增次序排序
(3)選取與當前點距離最小的k個點
(4)確定前k個點所在類別的出現頻率
(5)返回前k個點中出現頻率最高的類別作為當前點的預測分類
Python語言實現K-近鄰演算法的程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# coding : utf-8 from numpy import * import operator import kNN group, labels = kNN.createDataSet() def classify(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 sortedDistances = distances.argsort() classCount = {} for i in range(k): numOflabel = labels[sortedDistances[i]] classCount[numOflabel] = classCount.get(numOflabel,0) + 1 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1),reverse=True) return sortedClassCount[0][0] my = classify([0,0], group, labels, 3) print my |
運算結果如下:
輸出結果是B:說明我們新的資料([0,0])是屬於B類。
程式碼詳解
相信有很多朋友們對上面這個程式碼有很多不理解的地方,接下來,我重點講解幾個此函式的關鍵點,以方便讀者們和我自己回顧一下這個演算法程式碼。
classify函式的引數:
- inX:用於分類的輸入向量
- dataSet:訓練樣本集合
- labels:標籤向量
- k:K-近鄰演算法中的k
shape:是array的屬性,描述一個多維陣列的維度
tile(inX, (dataSetSize,1)):把inX二維陣列化,dataSetSize表示生成陣列後的行數,1表示列的倍數。整個這一行程式碼表示前一個二維陣列矩陣的每一個元素減去後一個陣列對應的元素值,這樣就實現了矩陣之間的減法,簡單方便得不讓你佩服不行!
axis=1:引數等於1的時候,表示矩陣中行之間的數的求和,等於0的時候表示列之間數的求和。
argsort():對一個陣列進行非降序排序
classCount.get(numOflabel,0) + 1:這一行程式碼不得不說的確很精美啊。get():該方法是訪問字典項的方法,即訪問下標鍵為numOflabel的項,如果沒有這一項,那麼初始值為0。然後把這一項的值加1。所以Python中實現這樣的操作就只需要一行程式碼,實在是很簡潔高效。
後話
K-近鄰演算法(KNN)原理以及程式碼實現差不多就這樣了,接下來的任務就是更加熟悉它,爭取達到裸敲的地步。
加油!!!