目錄
簡單理論介紹
K最近鄰(k-Nearest Neighbor,KNN)分類算法應該是最簡單的機器學習算法了。它採用測量不同特徵值之間的距離方法進行分類。它的思想很簡單:與它附近的k個樣本比較,與它最相似(即特徵空間中最鄰近)的這K個樣本中,大多數屬於某一個類別,則該樣本就屬於這個類別。
對於兩個n維向量x和y,距離度量一般用
歐式距離:
或者曼哈頓距離:
KNN的實現有兩個方式:一種是暴力實現,將帶分類樣本與所有的數據樣本計算距離度量,然後排序,選擇排序結果的前K個,這K個距離最近的樣本中,類別最多的就是待分類樣本的類別。KNN的升級版本爲KD樹劃分。
kNN算法之約會網站配對(Python)
第一步:讀取數據
這裏先看一下這裏的數據,它是一個文本文件,數據長這個樣子,最後一列是標籤,前面是特徵數據。
飛機里程數;一週喫的冰淇淋;打遊戲佔的時間
# 導入程序所需要的模塊
import numpy as np
import operator
#定義數據集導入函數
def file2matrix(filename):
love_dictionary = {'largeDoses':3, 'smallDoses':2, 'didntLike':1} # 三個類別
fr = open(filename) # 打開文件
arrayOLines = fr.readlines() # 逐行打開
numberOfLines = len(arrayOLines) #得到文件的行數
returnMat = np.zeros((numberOfLines, 3)) #初始化特徵矩陣
classLabelVector = [] #初始化輸出標籤向量
index = 0
for line in arrayOLines:
line = line.strip() # 刪去字符串首部尾部空字符
listFromLine = line.split('\t') # 按'\t'對字符串進行分割,listFromLine 是列表
returnMat[index, :] = listFromLine[0:3] # listFromLine的0,1,2元素是特徵,賦值給returnMat的當前行
if(listFromLine[-1].isdigit()): # 如果listFromLine最後一個元素是數字
classLabelVector.append(int(listFromLine[-1])) # 直接賦值給classLabelVector
else: # 如果listFromLine最後一個元素不是數字,而是字符串
classLabelVector.append(love_dictionary.get(listFromLine[-1])) # 根據字典love_dictionary轉化爲數字
index += 1
return returnMat, classLabelVector # 返回的類別標籤classLabelVector是1,2,3
第二步:數據預處理
我們看數據,前面三列是特徵數據,後面一列是標籤,可以看到每一列特徵數據的量綱不同(數值大小),把每一列特徵數據劃分到統一的範圍([0,1]之間}):(雖然KNN對於異常點不敏感,但是我們一般處理數值型數據做一個歸一化或者標準化是常用手段)
def autoNorm(dataSet):
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = np.zeros(np.shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - np.tile(minVals, (m, 1))
normDataSet = normDataSet/np.tile(ranges, (m, 1)) # normDataSet值被限定在[0,1]之間
return normDataSet, ranges, minVals
第三步:定義模型
def classify0(inX, dataSet, labels, k): # inX是測試集,dataSet是訓練集,lebels是訓練樣本標籤,k是取的最近鄰個數
dataSetSize = dataSet.shape[0] # 訓練樣本個數
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet # np.tile: 重複n次
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5 # distance是inX與dataSet的歐氏距離
sortedDistIndicies = distances.argsort() # 返回排序從小到達的索引位置
classCount = {} # 字典存儲k近鄰不同label出現的次數
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 對應label加1,classCount中若無此key,則默認爲0
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) # operator.itemgetter 獲取對象的哪個維度的數據
return sortedClassCount[0][0] # 返回k近鄰中所屬類別最多的哪一類
第四步: 測試算法
def datingClassTest():
hoRatio = 0.10 #整個數據集的10%用來測試
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') #導入數據集
normMat, ranges, minVals = autoNorm(datingDataMat) # 所有特徵歸一化
m = normMat.shape[0] # 樣本個數
numTestVecs = int(m*hoRatio) # 測試樣本個數
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]): errorCount += 1.0
print("the total error rate is: %f" % (errorCount / float(numTestVecs))) # 打印錯誤率
print(errorCount) # 打印錯誤個數
第五步:可用系統(選做)
根據用戶的輸入,在線判斷匹配的類別
def classifyPerson():
resultList = ['not at all', 'in small doses', 'in large doses']
percentTats = float(input(\
"percentage of time spent playing video games?"))
ffMiles = float(input("frequent flier miles earned per year?"))
iceCream = float(input("liters of ice cream consumed per year?"))
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
inArr = np.array([ffMiles, percentTats, iceCream, ])
classifierResult = classify0((inArr - \
minVals)/ranges, normMat, datingLabels, 3)
print("You will probably like this person: %s" % resultList[classifierResult - 1])
scikit-learn實現
簡單實例:
還是用約會網站數據做練習,讀取數據和數據處理沿用上面的函數,模型實現用sklearn。
from sklearn import neighbors #導包
import numpy as np
import operator
filename = 'datingTestSet2.txt'
X,Y = file2matrix(filename) #導入數據
clf = neighbors.KNeighborsClassifier(n_neighbors = 3 , weights='distance') #實例化對象
clf.fit(X, Y) #擬合數據
clf.predict(X[:10]) #預測
參數列表:
==============================參考資料
參考資料:《機器學習實戰》--KNN 代碼和數據:http://www.manning.com/MachineLearninginAction
sklearn文檔:
極力推薦資源:深度之眼機器學習訓練營 和 西瓜書訓練營