前言
這是一個KNN算法的應用實例,參考《機器學習實戰》中的datingTestSet2.txt的數據集。
能夠經過對不一樣約會對象的特徵進行分析而後自動得出如下三種結論:
準備數據
這個數據集中針對每個約會對象收集了三種具備表明性的特徵,分別是:
- 每一年得到的飛行常客里程數
- 玩網遊所消耗的時間比
- 每一年消耗的冰淇淋公升數
而後對每一個約會對象的三種結論進行打分,對應的分數分別爲一、二、3。
數據展現:
這樣的數據須要處理成分類器能夠接受的格式,因此咱們建立了file2matrix函數用與完成這個功能。
代碼以下 :
# ==========================# 讀入文本記錄,轉換爲NumPy,便於其餘函數使用# 輸入:文本記錄的路徑# ==========================def file2matrix(filename): fr = open(filename) arrayOLines = fr.readlines() numberOfLines = len(arrayOLines) returnMat = zeros((numberOfLines, 3)) classLabelVector = [] index = 0 for line in arrayOLines: line = line.strip() # 刪除字符串首尾的空白符(包括'\n', '\r', '\t', ' ') listFromLines = line.split("\t") returnMat[index, :] = listFromLines[0:3] classLabelVector.append(int(listFromLines[-1])) index += 1 return returnMat, classLabelVector
可視化分析數據:
咱們用matplotlib製做原始數據的散點圖,用於分析並找出三個特徵中的哪兩個特徵能夠獲得更好的分類效果。
繪圖代碼:
def plotSca(datingDataMat, datingLabels): import matplotlib.pyplot as plt fig = plt.figure() ax1 = fig.add_subplot(121) # 玩網遊所消耗的時間比(橫軸)與每一年消耗的冰淇淋公升數(縱軸)的散點圖 ax1.scatter(datingDataMat[:,1], datingDataMat[:, 2], 15.0*array(datingLabels), 5.0*array(datingLabels)) ax2 = fig.add_subplot(122) # 每一年得到的飛行常客里程數(橫軸)與 玩網遊所消耗的時間比(縱軸)的散點圖 ax2.scatter(datingDataMat[:,0], datingDataMat[:, 1], 15.0*array(datingLabels), 5.0*array(datingLabels)) plt.show()
繪圖效果:
從圖中能夠看出,顯然圖二中展現的兩個特徵更容易區分數據點從屬的類別。
歸一化數值:
從展現數據中咱們能夠很明顯的看出,不一樣特徵值量級相差太大。
而他們在模型中佔的權重又並不比其餘特徵大,這個時候就須要對特徵值進行歸一化,
也就是將取值範圍處理爲0到1或者-1到1之間
這裏用autoNorm()函數實現這個功能
# =====================================# 若是不一樣特徵值量級相差太大,# 而他們在模型中佔的權重又並不比其餘特徵大,# 這個時候就須要對特徵值進行歸一化,# 也就是將取值範圍處理爲0到1或者-1到1之間# 本函數就是對數據集歸一化特徵值# dataset: 輸入數據集# =====================================def autoNorm(dataset): minVals = dataset.min(0) maxVals = dataset.max(0) ranges = maxVals - minVals normDataset = zeros(shape(dataset)) m = dataset.shape[0] normDataset = dataset - tile(minVals, (m, 1)) normDataset = normDataset/tile(ranges, (m, 1)) # 矩陣中對應數值相除 return normDataset, ranges, minVals
測試算法:
經過上面的準備工做,再加上上一節的classify0分類函數就能夠構成一個完整的分類器,用於對約會對象快速分類打分。
測試的時候一個很重要的工做就是評估算法的正確率。
一般咱們會把整個數據集按9:1的比例分紅訓練集和測試集。
測試集就是用來檢測分類器的正確率。
須要注意的是,在選擇測試集的時候須要保持數據的隨機性。
測試分類代碼以下:
'''分類器針對約會網站的測試代碼'''def datingClassTest(): hoRatio = 0.10 # 數據集中用於測試的比例 filePath = "E:\ml\machinelearninginaction\Ch02\datingTestSet2.txt" datingDataMat, datingLabels = file2matrix(filePath) # plotSca(datingDataMat, datingLabels) normMat, ranges, minVals = autoNorm(datingDataMat) m = normMat.shape[0] numTestVecs = int(hoRatio*m) errcounter = 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]): errcounter +=1.0 print "the total error rate is: %f" % (errcounter/float(numTestVecs)) print errcounter
輸出效果如圖所示:
輸出表示錯誤率爲5%,且顯示了算法的運行時間(經過import time,而後用time.clock - time.start實現)
小結
從運行效果看,算法的優勢是精度高。並且算法對異常值不敏感,不須要事先訓練。
可是從算法步驟上看,在對每個新數據進行分類的時候都要和訓練集中的每個已知數據進行比較和類似度計算
能夠預見的是,一旦數據集很大的時候,算法所要求的時間複雜度和空間複雜度就會迅速提升