机器学习实战之K近邻算法
k近鄰算法概述
簡單地說,K近鄰算法采用測量不同特征值之間的距離方法進行分類。
優 點 :精度高、對異常值不敏感、無數據輸入假定。
缺點:計算復雜度高、空間復雜度高。
適用數據范圍:數值型和標稱型。
它的工作原理是:存在一個樣本數 據集合,也稱作訓練樣本集,并且樣本集中每個數據都存在標簽,即我們知道樣本集中每一數據 與所屬分類的對應關系。輸人沒有標簽的新數據后,將新數據的每個特征與樣本集中數據對應的 特征進行比較,然后算法提取樣本集中特征最相似數據(最近鄰)的分類標簽。一般來說,我們 只選擇樣本數據集中前K個最相似的數據,這就是K近鄰算法中K的出處,通常K是不大于20的整數。 最后,選擇K個最相似數據中出現次數最多的分類,作為新數據的分類。
K近鄰算法的一般流程
(1)收集數據:可以使用任何方法。
(2)準備數據:距離計算所需要的數值,最好是結構化的數據格式。
(3)分析數據:可以使用任何方法。
(4)訓練算法:此步驟不適用于1 近鄰算法。
(5)測試算法:計算錯誤率。
(6)使用算法:首先需要輸入樣本數據和結構化的輸出結果,然后運行k-近鄰算法判定輸入數據分別屬于哪個分類,最后應用對計算出的分類執行后續的處理。
K近鄰算法偽代碼實現
對未知類別屬性的數據集中的每個點依次執行以下操作:
(1)計算已知類別數據集中的點與當前點之間的距離,常常使用歐氏距離公式;
(2)按照距離遞增次序排序;
(3)選取與當前點距離最小的K個點;
(4)確定前K個點所在類別的出現頻率;
(5)返回前K個點出現頻率最高的類別作為當前點的預測分類。
使用k近鄰算法改進約會網站的配對效果
(1)收集數據:提供文本文件。
(2)準備數據: 使用python解析文本文件。
(3)使用Matplotlib畫二維擴散圖
(4)訓練算法:此步驟不適用于k近鄰算法。
(5)測試算法:使用海倫提供的部分數據作為測試樣本。
測試樣本和非測試樣本的區別在于:測試樣本是已經完成分類的數據,如果預測分類與實際類別不同,則標記為一個錯誤。
(6)使用算法:產生簡單的命令行程序,然后海倫可以輸入一些特征數據以判斷對方是否為自己喜歡的類型。
從文本文件中解析數據
海倫收集約會數據巳經有了一段時間,她把這些數據存放在文本文件中 ,每 個樣本數據占據一行,總共有1000行。海倫的樣本主要包含以下3種特征:
□ 每年獲得的飛行常客里程數
□ 玩視頻游戲所耗時間百分比
□ 每周消費的冰淇淋公升數
我們通過file2matrix函數讀入數據,該函數的輸人為文 件名字符串 輸出為訓練樣本矩陣和類標簽向量。
def file2matrix(filename):fr = open(filename)numberOfLines = len(fr.readlines()) # get the number of lines in the filereturnMat = zeros((numberOfLines, 3)) # prepare matrix to returnclassLabelVector = [] # prepare labels returnfr = open(filename)index = 0for line in fr.readlines():line = line.strip()listFromLine = line.split('\t')returnMat[index, :] = listFromLine[0:3]classLabelVector.append(int(listFromLine[-1]))index += 1return returnMat, classLabelVector分析數據:使用matplotlib創建散點圖
在python命令環境下,輸入下列命令
import matplotlib import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(datingDataMat[:,1],datingDataMat[:2]) plt.show()
由于沒有使用樣本分類特征值,我們很難從圖中看到有用的數據模式信息。
重新輸入上面的代碼,調用scatter函數時使用如下代碼:
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
數據歸一化
我們很容易發現,上面方程中數字差值最大的屬性對計算結果的影響最大,也就是說,每年獲取的飛行常客里程數對于計算結果的影響將遠遠大于表2-3中其他兩個特征— 玩視頻游戲的 和每周消費冰洪淋公升數— 的影響。而產生這種現象的唯一原因,僅僅是因為飛行常客里程數 遠大于其他特征值。但海倫認為這三種特征是同等重要的,因此作為三個等權重的特征之一,飛 行常客里程數并不應該如此嚴重地影響到計算結果。
在處理這種不同取值范圍的特征值時,我們通常采用的方法是將數值歸一化,如將取值范圍處理為0到1或者-1到1之間。下面的公式可以將任意取值范圍的特征值轉化為0到1區間內的值:
newValue=(oldValue-min)/(max-min)
其中min和max分別是數據集中的最小特征值和最大特征值。雖然改變數值取值范圍增加了 分類器的復雜度,但為了得到準確結果,我們必須這樣做
測試算法
前面我們巳經提到可以使用錯誤率來檢測分類器的性能。對于分類器來說,錯誤率就是分類器給出錯誤結果的次數除以測試數據的總數,完美分類器的錯誤率為0,而錯誤率為1.0的分類器 不會給出任何正確的分類結果。代碼里我們定義一個計數器變量,每次分類器錯誤地分類數據,計數器就加1,程序執行完成之后計數器的結果除以數據點總數即是錯誤率。
分類器處理約會數據集的錯誤率是2.4%,這是一個相當不錯的結果。依賴于分類算法、數據集和程序設置,分類器的輸出結果可能有很大的不同。
這個例子表明我們可以正確地預測分類,錯誤率僅僅是2.4%。海倫完全可以輸人未知對象的屬性信息’由分類軟件來幫助她判定某一對象的可交往程度:討厭、一般喜歡、非常喜歡。
手寫識別系統
本節我們一步步地構造使用K-近鄰分類器的手寫識別系統。為了簡單起見,這里構造的系統只能識別數字0到9,參見圖2.6。需要識別的數字已經使用圖形處理軟件,處理成具有相同的色彩和大小?:寬髙是32像素*32像素的黑白圖像。盡管采用文本格式存儲圖像不能有效地利用內存空間,但是為了方便理解,我們還是將圖像轉換為文本格式。
(1)收集數據:提供文本文件。
(2)準備數據:編寫函數classify0(),將圖像格式轉換為分類器使用的list格式。
(3)分析數據:在python命令提示符中檢查數據,確保它符合要求。
(4)訓 練 算 法 :此步驟不適用于各近鄰算法。
(5)測試算法:編寫函數使用提供的部分數據集作為測試樣本,測試樣本與非測試樣本的區別在于測試樣本是已經完成分類的數據,如果預測分類與實際類別不同,則標記
為一個錯誤。
(6)使用算法:本例沒有完成此步驟,若你感興趣可以構建完整的應用程序,從圖像中提取數字,并完成數字識別,美國的郵件分揀系統就是一個實際運行的類似系統
為了使用前面兩個例子的分類器,我們必須將圖像格式化處理為一個向量。我們將把一個32*32的二進制圖像矩陣轉換為1*1024的向量,這樣前兩節使用的分類器就可以處理數字圖像信息了。
我們首先編寫一段函數img2vector將圖像轉換為向量:該函數創建1*1024的numpy數組,然后打開給定的文件,循環讀出文件的前32行,并將每行的頭32個字符值存儲在numpy數 組 中,最后返回數組。
測試算法
def handwritingClassTest():hwLabels = []trainingFileList = listdir('trainingDigits') # load the training setm = len(trainingFileList)trainingMat = zeros((m, 1024))for i in range(m):fileNameStr = trainingFileList[i]fileStr = fileNameStr.split('.')[0] # take off .txtclassNumStr = int(fileStr.split('_')[0])hwLabels.append(classNumStr)trainingMat[i, :] = img2vector('trainingDigits/%s' % fileNameStr)testFileList = listdir('testDigits') # iterate through the test seterrorCount = 0.0mTest = len(testFileList)for i in range(mTest):fileNameStr = testFileList[i]fileStr = fileNameStr.split('.')[0] # take off .txtclassNumStr = int(fileStr.split('_')[0])vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)if (classifierResult != classNumStr): errorCount += 1.0print "\nthe total number of errors is: %d" % errorCountprint "\nthe total error rate is: %f" % (errorCount / float(mTest))K-近鄰算法識別手寫數字數據集,錯誤率為1.2%
實際使用這個算法時,算法的執行效率并不高。因為算法需要為每個測試向量做2000次距離計算,每個距離計算包括了1024個維度浮點運算,總計要執行900次,此外,我們還需要為測試向量準備2MB的存儲空間。是否存在一種算法減少存儲空間和計算時間的開銷呢?k決策樹就是K-近鄰算法的優化版,可以節省大量的計算開銷。
總結
K-近鄰算法是分類數據最簡單最有效的算法,本章通過兩個例子講述了如何使用K-近鄰算法構造分類器。K-近鄰算法是基于實例的學習,使用算法時我們必須有接近實際數據的訓練樣本數 據。K-近鄰算法必須保存全部數據集,如果訓練數據集的很大,必須使用大量的存儲空間。此外,由于必須對數據集中的每個數據計算距離值,實際使用時可能非常耗時。
總結
以上是生活随笔為你收集整理的机器学习实战之K近邻算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kudu参数优化设置,让集群飞起来~
- 下一篇: TFRecords文件的存储与读取