1. 程式人生 > >【機器學習演算法實現】kNN演算法__手寫識別——基於Python和NumPy函式庫

【機器學習演算法實現】kNN演算法__手寫識別——基於Python和NumPy函式庫

【機器學習演算法實現】系列文章將記錄個人閱讀機器學習論文、書籍過程中所碰到的演算法,每篇文章描述一個具體的演算法、演算法的程式設計實現、演算法的具體應用例項。爭取每個演算法都用多種語言程式設計實現。所有程式碼共享至github:https://github.com/wepe/MachineLearning-Demo     歡迎交流指正!

(1)kNN演算法_手寫識別例項——基於Python和NumPy函式庫

1、kNN演算法簡介

kNN演算法,即K最近鄰(k-NearestNeighbor)分類演算法,是最簡單的機器學習演算法之一,演算法思想很簡單:從訓練樣本集中選擇k個與測試樣本“距離”最近的樣本,這k個樣本中出現頻率最高的類別即作為測試樣本的類別。下面的簡介選自wiki百科:

http://zh.wikipedia.org/wiki/%E6%9C%80%E8%BF%91%E9%84%B0%E5%B1%85%E6%B3%95

方法

  • 目標:分類未知類別案例。
  • 輸入:待分類未知類別案例專案。已知類別案例集合D ,其中包含 j個已知類別的案例。
  • 輸出:專案可能的類別。

步驟

如下圖
我們考慮樣本為二維的情況下,利用knn方法進行二分類的問題。圖中三角形和方形是已知類別的樣本點,這裡我們假設三角形為正類,方形為負類。圖中圓形點是未知類別的資料,我們要利用這些已知類別的樣本對它進行分類。

分類過程如下:
1 首先我們事先定下k值(就是指k近鄰方法的k的大小,代表對於一個待分類的資料點,我們要尋找幾個它的鄰居)。這邊為了說明問題,我們取兩個k值,分別為3和5;
2 根據事先確定的距離度量公式(如:歐氏距離),得出待分類資料點和所有已知類別的樣本點中,距離最近的k個樣本。
3 統計這k個樣本點中,各個類別的數量。如上圖,如果我們選定k值為3,則正類樣本(三角形)有2個,負類樣本(方形)有1個,那麼我們就把這個圓形資料點定為正類;而如果我們選擇k值為5,則正類樣本(三角形)有2個,負類樣本(方形)有3個,那麼我們這個資料點定為負類。即,根據k個樣本中,數量最多的樣本是什麼類別,我們就把這個資料點定為什麼類別。

補充:

優缺點:

(1)優點:

演算法簡單,易於實現,不需要引數估計,不需要事先訓練。

(2)缺點:

屬於懶惰演算法,“平時不好好學習,考試時才臨陣磨槍”,意思是kNN不用事先訓練,而是在輸入待分類樣本時才開始執行,這一特點導致kNN計算量特別大,而且訓練樣本必須儲存在本地,記憶體開銷也特別大。

K的取值:

引數k的取值一般通常不大於20。——《機器學習實戰》

2、手寫識別例項

kNN演算法主要被應用於文字分類、相似推薦。本文將描述一個分類的例子,是《機器學習實戰》一書中的例項,使用python語言以及數值計算庫NumPy。下面首先簡單介紹本例項程式設計開發過程中所用到的python、numpy中的函式。

2.1 python、numpy函式

NumPy庫總包含兩種基本的資料型別:矩陣和陣列,矩陣的使用類似Matlab,本例項用得多的是陣列array。

shape()

shape是numpy函式庫中的方法,用於檢視矩陣或者陣列的維素

>>>shape(array) 若矩陣有m行n列,則返回(m,n)

>>>array.shape[0] 返回矩陣的行數m,引數為1的話返回列數n

tile()

tile是numpy函式庫中的方法,用法如下:

>>>tile(A,(m,n))  將陣列A作為元素構造出m行n列的陣列

sum()

sum()是numpy函式庫中的方法

>>>array.sum(axis=1)按行累加,axis=0為按列累加

argsort()

argsort()是numpy中的方法,得到矩陣中每個元素的排序序號

>>>A=array.argsort()  A[0]表示排序後 排在第一個的那個數在原來陣列中的下標

dict.get(key,x)

python中字典的方法,get(key,x)從字典中獲取key對應的value,字典中沒有key的話返回0

sorted()

python中的方法

min()、max()

numpy中有min()、max()方法,用法如下

>>>array.min(0)  返回一個數組,陣列中每個數都是它所在列的所有數的最小值

>>>array.min(1)  返回一個數組,陣列中每個數都是它所在行的所有數的最小值

listdir('str')

python的operator中的方法

>>>strlist=listdir('str')  讀取目錄str下的所有檔名,返回一個字串列表

split()

python中的方法,切片函式

>>>string.split('str')以字元str為分隔符切片,返回list

2.2  程式設計實現“手寫識別”

手寫識別的概念:是指將在手寫裝置上書寫時產生的軌跡資訊轉化為具體字碼。 手寫識別系統是個很大的專案,識別漢字、英語、數字、其他字元。本文只是個小demo,重點不在手寫識別而在於理解kNN,因此只識別0~9單個數字。 輸入格式:每個手寫數字已經事先處理成32*32的二進位制文字,儲存為txt檔案。0~9每個數字都有10個訓練樣本,5個測試樣本。訓練樣本集如下圖: 開啟3_3.txt這個檔案看看:
上面的背景介紹完了,現在程式設計實現,大概分為三個步驟 (1)將每個圖片(即txt文字,以下提到圖片都指txt文字)轉化為一個向量,即32*32的陣列轉化為1*1024的陣列,這個1*1024的陣列用機器學習的術語來說就是特徵向量。 (2)訓練樣本中有10*10個圖片,可以合併成一個100*1024的矩陣,每一行對應一個圖片。(這是為了方便計算,很多機器學習演算法在計算的時候採用矩陣運算,可以簡化程式碼,有時還可以減少計算複雜度)。 (3)測試樣本中有10*5個圖片,我們要讓程式自動判斷每個圖片所表示的數字。同樣的,對於測試圖片,將其轉化為1*1024的向量,然後計算它與訓練樣本中各個圖片的“距離”(這裡兩個向量的距離採用歐式距離),然後對距離排序,選出較小的前k個,因為這k個樣本來自訓練集,是已知其代表的數字的,所以被測試圖片所代表的數字就可以確定為這k箇中出現次數最多的那個數字。 第一步:轉化為1*1024的特徵向量。程式中的filename是檔名,比如3_3.txt
<span style="font-family:SimSun;font-size:18px;">#樣本是32*32的二值圖片,將其處理成1*1024的特徵向量
def img2vector(filename):
    returnVect = zeros((1,1024))
    fr = open(filename)
    for i in range(32):
        lineStr = fr.readline()
        for j in range(32):
            returnVect[0,32*i+j] = int(lineStr[j])
    return returnVect</span>
第二步、第三步:將訓練集圖片合併成100*1024的大矩陣,同時逐一對測試集中的樣本分類
<span style="font-family:SimSun;font-size:18px;">def handwritingClassTest():
    #載入訓練集到大矩陣trainingMat
    hwLabels = []
    trainingFileList = listdir('trainingDigits')           #os模組中的listdir('str')可以讀取目錄str下的所有檔名,返回一個字串列表
    m = len(trainingFileList)
    trainingMat = zeros((m,1024))
    for i in range(m):
        fileNameStr = trainingFileList[i]                  #訓練樣本的命名格式:1_120.txt
        fileStr = fileNameStr.split('.')[0]                #string.split('str')以字元str為分隔符切片,返回list,這裡去list[0],得到類似1_120這樣的
        classNumStr = int(fileStr.split('_')[0])           #以_切片,得到1,即類別
        hwLabels.append(classNumStr)
        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)
        
    #逐一讀取測試圖片,同時將其分類   
    testFileList = listdir('testDigits')       
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]     
        classNumStr = 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.0
    print "\nthe total number of errors is: %d" % errorCount
    print "\nthe total error rate is: %f" % (errorCount/float(mTest))</span>
這裡面的函式classify()為分類主體函式,計算歐式距離,並最終返回測試圖片類別:
<span style="font-family:SimSun;font-size:18px;">#分類主體程式,計算歐式距離,選擇距離最小的k個,返回k箇中出現頻率最高的類別
#inX是所要測試的向量
#dataSet是訓練樣本集,一行對應一個樣本。dataSet對應的標籤向量為labels
#k是所選的最近鄰數目
def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]                       #shape[0]得出dataSet的行數,即樣本個數
    diffMat = tile(inX, (dataSetSize,1)) - dataSet       #tile(A,(m,n))將陣列A作為元素構造m行n列的陣列
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)                  #array.sum(axis=1)按行累加,axis=0為按列累加
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()             #array.argsort(),得到每個元素的排序序號
    classCount={}                                        #sortedDistIndicies[0]表示排序後排在第一個的那個數在原來陣列中的下標
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #get(key,x)從字典中獲取key對應的value,沒有key的話返回0
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) #sorted()函式,按照第二個元素即value的次序逆向(reverse=True)排序
    return sortedClassCount[0][0]</span>


3、工程檔案

整個工程檔案包括原始碼、訓練集、測試集,可到github獲取:github地址
進入use Python and NumPy目錄,開啟python開發環境,import kNN模組,呼叫手寫識別函式:
因為我用的訓練集和測試集都比較小,所以湊巧沒有識別錯誤的情況:

相關推薦

機器學習演算法實現kNN演算法__識別——基於PythonNumPy函式

【機器學習演算法實現】系列文章將記錄個人閱讀機器學習論文、書籍過程中所碰到的演算法,每篇文章描述一個具體的演算法、演算法的程式設計實現、演算法的具體應用例項。爭取每個演算法都用多種語言程式設計實現。所

kNN演算法__識別——基於PythonNumPy函式

(3)測試樣本中有10*5個圖片,我們要讓程式自動判斷每個圖片所表示的數字。同樣的,對於測試圖片,將其轉化為1*1024的向量,然後計算它與訓練樣本中各個圖片的“距離”(這裡兩個向量的距離採用歐式距離),然後對距離排序,選出較小的前k個,因為這k個樣本來自訓練集,是已知其代表的數字的,所以被測試圖片所代表的數

機器學習演算法實現kNN演算法 識別——基於PythonNumPy函式

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

機器學習演算法實現logistic迴歸 基於PythonNumpy函式

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

機器學習演算法實現logistic迴歸__基於PythonNumpy函式

1、演算法簡介 本文的重點放在演算法的工程實現上,關於演算法的原理不具體展開,logistic迴歸演算法很簡單,可以看看Andrew Ng的視訊:https://class.coursera.org/ml-007,也可以看看一些寫得比較好的博文:洞庭之子的博文。下面我只列出一些個人認為重要的點。 迴歸的概

機器學習筆記27CART演算法-迴歸樹分類樹

基本概念 分類和迴歸樹(classification and regression tree, CART) 是應用廣泛的決策樹學習方法,由特徵選擇、樹的生成和剪枝組成,既可以用做分類也可以用作迴歸。 迴歸樹 迴歸樹的定義 假設X和Y分別作為輸入和輸出變數,那麼

機器學習詳解SMO演算法剖析

CSDN−勿在浮沙築高臺 本文力求簡化SMO的演算法思想,畢竟自己理解有限,無奈還是要拿一堆公式推來推去,但是靜下心看完本篇並隨手推導,你會迎刃而解的。推薦參看SMO原文中的虛擬碼。 1.SMO概念 上一篇部落格已經詳細介紹了SVM原理,為了方便求解,把原

機器學習詳解KNN分類的概念、誤差率及其問題

勿在浮沙築高臺 KNN概念         KNN(K-Nearest Neighbors algorithm)是一種非引數模型演算法。在訓練資料量為N的樣本點中,尋找最近鄰測試資料x的K個樣本,然

機器學習實戰之一:C++實現K-近鄰演算法KNN

本文不對KNN演算法做過多的理論上的解釋,主要是針對問題,進行演算法的設計和程式碼的註解。 KNN演算法: 優點:精度高、對異常值不敏感、無資料輸入假定。 缺點:計算複雜度高、空間複雜度高。 適用資料範圍:數值型和標稱性。 工作原理:存在一個樣本資料集合,也稱作訓練樣本集,

python機器學習入門1KNN(k近鄰)演算法2 識別系統

參考部落格:超詳細的機器學習python入門knn乾貨 (po主Jack-Cui 參考書籍:《機器學習實戰》——第二章 KNN入門第二彈——手寫識別系統demo ——《機器學習實戰》第二章2.3 手寫識別系統       &

機器學習入門二整合學習及AdaBoost演算法python實現

本文主要基於周志華老師的《機器學習》第八章內容 個體與整合 整合學習通過構建並結合多個學習器來完成學習任務。整合學習的一般結構如圖所示: 先產生一組個體學習器,在用某種策略把它們結合在一起。個體學習器通常有一個現有的學習演算法從訓練資料產生,如決策

機器學習實戰系列讀書筆記之KNN演算法(三)

本次讀書筆記在於延續上一篇部落格的工程,做出微小的改動,即使用Matplotlib建立散點圖(散點圖使用DataMat矩陣的第一、第二列資料)。首先還是介紹一個相關知識點,方便程式碼瀏覽。知識點一:1、在使用Matplotlib生成圖表時,預設不支援漢字,所有漢字都會顯示成框

機器學習筆記35蟻群演算法

【參考資料】 【1】《蟻群演算法原理及其應用》 【2】測試資料: https://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/att48.tsp.gz 演算法原理(以TSP問題為例) (1)引數初始化。令時間t=0和迴圈次數

機器學習實戰系列讀書筆記之AdaBoost演算法公式推導例子講解(一)

最近在看整合演算法AdaBoost,推薦先看李航的統計學習方法第8章,然後再看機器學習實戰第7章,李航的書上的公式推導講的很詳細了,但是很多地方對於初學者來說,還是需要時間去理解和消化的。本文將從以下幾個方面來介紹AdaBoost演算法。一、AdaBoost演算法公式推導二、

機器學習---scikit-learn中KNN演算法的封裝

1,工具準備,python環境,pycharm 2,在機器學習中,KNN是不需要訓練過程的演算法,也就是說,輸入樣例可以直接呼叫predict預測結果,訓練資料集就是模型。當然這裡必須將訓練資料和訓練標籤進行擬合才能形成模型。 3 3,在pycharm中建立新的專案工程

機器學習實戰筆記——利用KNN演算法改進約會網站的配對效果

一、案例背景 我的朋友海倫一直使用線上約會網站尋找合適自己的約會物件。儘管約會網站會推薦不同的人選,但她並不是喜歡每一個人。經過一番總結,她發現曾交往過三種類型的人: (1)不喜歡的人; (2)

機器學習之K近鄰(KNN)演算法

1.KNN簡介 K近鄰(K-Nearest Neighbors, KNN)演算法既可處理分類問題,也可處理迴歸問題,其中分類和迴歸的主要區別在於最後做預測時的決策方式不同。KNN做分類預測時一般採用多數表決法,即訓練集裡和預測樣本特徵最近的K個樣本,預測結果為裡

好玩的計算機視覺KNN演算法數字識別

OCR應用非常廣泛,而且有許多方法,今天用KNN演算法實現簡單的0-9手寫數字識別。本程式使用OpenCV 3.0和Python 3。 KNN演算法是K近鄰分類演算法,屬於機器學習中的監督學習,需要一定量的帶標籤的輸入樣本資料進行“訓練”,然後就可以識別。我給“訓練”打引

機器學習基石筆記一、綜述

model 但是 目標 學習 imp 選擇 處理 定義 條件 課程定位: 註重基礎、故事性 機器學習定義: data - Algo - improve 機器學習使用條件 1、有優化的目標,可量化的。 2、規則不容易寫下來,需要學習。 3、要有數據 一個可能的推薦

機器學習基石筆記二、感知機

證明 機器學習 sign 線性可分 缺點 學習 犯錯 nbsp 錯誤 感知機算法: 1、首先找到點,使得sign(wt * xt) != yt,   那麽如果yt = 1,說明wt和xt呈負角度,wt+1 = wt + xt能令wt偏向正角度。   如果yt = -1, 說