1. 程式人生 > >使用K近鄰演算法實現手寫體識別系統

使用K近鄰演算法實現手寫體識別系統

目錄
1.應用介紹
1.1實驗環境介紹
1.2應用背景介紹
2.資料來源及預處理
2.1資料來源及格式
2.2資料預處理
3.演算法設計與實現
3.1手寫體識別系統演算法實現過程
3.2 K近鄰演算法實現
3.3手寫體識別系統實現
3.4演算法改進與優化

4.系統執行過程與結果展示

1.應用介紹
1.1實驗環境介紹
本次實驗主要使用Python語言開發完成,Python的版本為2.7,並且使用numpy函式庫做一些數值計算和處理。
1.2應用背景介紹
本次實驗實現的是簡易的手寫體識別系統,即根據使用者輸入的手寫體照片可以識別出手寫體數字是多少。本次輸入的手寫體是用0,1數字拼成的手寫體數字。本次完成手寫體的識別使用K近鄰演算法,k近鄰演算法設計簡單,容易實現,且對特定的問題分類的效果也比較好。因此本次實驗選擇k近鄰來對手寫體進行分類和識別,也是對手寫體圖片特徵資料的挖掘過程。


2.資料來源及預處理
2.1資料來源及格式
該資料集合修改自“手寫數字資料集的光學識別” 一文中的資料集合,該文登載於2010年10月3日的UCI資料庫中http://archive.ics.uci.edu/ml。
為了簡單起見,這裡構造的系統只能識別數字0到9。需要識別的數字已經使用圖形處理軟體,處理成具有相同的色彩和大小: 寬髙是32畫素*32畫素的黑白影象。儘管採用文字格式儲存影象不能有效地利用記憶體空間,但是為了方便理解,我們還是將影象轉換為文字格式。



圖:資料來源:手寫體資料格式


2.2資料預處理
首先將影象轉換為測試向量,本次實驗大約使用了2000個例子,每個例子的內容如上圖所示,每個數字大約有200個樣本;目錄testDigits中包含了大約900個測試資料。我們使用目錄trainingDigits中的資料訓練分類器,使用目錄testDigits中的資料測試分類器的效果。兩組資料沒有覆蓋。部分資料如下:



圖:資料目錄

這裡將影象格式化處理為一個向量。把一個32*32的二進位制影象矩陣轉換為1 x 1024的向量,這樣前兩節使用的分類器就可以處理數字影象資訊了。

首先編寫一段函式img2vector將影象轉換為向量:該函式建立1*1024的Numpy組,然後開啟給定的檔案,迴圈讀出檔案的前32行,並將每行的頭32個字元值儲存在Numpy陣列中,最後返回陣列。


3. 演算法設計與實現

3.1手寫體識別系統演算法實現過程

(1)收集資料:提供文字檔案。

(2)準備資料:編寫函式clasify0()將影象格式轉換為分類器使用的list格式。

(3)分析資料:在python命令提示符中檢查資料,確保它符合要求。

(4測試演算法:編寫函式使用提供的部分資料集作為測試樣本,測試樣本與非測試樣本的區別在於測試樣本是已經完成分類的資料,如果預測分類與實際類別不同,則標記為一個錯誤。

3.2 K近鄰演算法實現

K近鄰演算法的實現過程是:

(1)計算已知類別資料集中的點與當前點之間的距離;

(2)按照距離遞增次序排序;

(3)選取與當前點距離最小的k個點;

(4)確定前k個點所在類別的出現頻率;

(5)返回前k個點出現頻率最高的類別作為當前點的預測分類。

本系統在classify0函式中實現了k近鄰演算法。


classifyO ()函式有4個輸人蔘數:用於分類的輸人向量是inX輸人的訓練樣本集為dataSet

標籤向量為labels,最後的引數義表示用於選擇最近鄰居的數目,其中標籤向量的元素數目和矩陣dataSet的行數相同。程式使用歐氏距離公式,計算兩個向量點xAxB之間的距離。

計算完所有點之間的距離後,可以對資料按照從小到大的次序排序。然後,確定前k個距離

最小元素所在的主要分類,輸人k總是正整數;最後,將classCount字典分解為元組列表,然後使用程式第二行匯入運算子模組的itemgetter方法,按照第二個元素的次序對元組進行排序。此處的排序為逆序,即按照從最大到最小次序排序,最後返回發生頻率最高的元素標籤。

3.3手寫體識別系統實現

系統需要呼叫img2vector做資料預處理,然後呼叫classify0做分類,最後將對測試集分類的結果輸出,並計算錯誤率。在實現中需要從os中匯入listdir,可以列出給定目錄的檔名。

將trainingDigits目錄中的檔案內容儲存在列表中。然後可以得到目錄中有多少檔案,並將其儲存在變數m中。接著,程式碼建立一個m1024列的訓練矩陣,該矩陣的每行資料儲存一個影象。我們可以從檔名中解析出分類數字。該目錄下的檔案按照規則命名,如檔案

9_45.txt的分類是9,它是數字9的第45個例項。


3.4演算法改進與優化

改變變數k的值、修改函式handwritingClassTest隨機選取訓練樣本、改變訓練樣本的數目,都會對k近鄰演算法的錯誤率產生影響

實際使用這個演算法時,演算法的執行效率並不高。因為演算法需要為每個測試向量做2000次距離計算,每個距離計算包括了1024個維度浮點運算,總計要執行900次,此外,我們還需要為測試向量準備2 M B的儲存空間。因此可以使用其他的演算法做一些改進和優化。

4. 系統執行過程與結果展示

本次實驗使用Python自帶的ide編輯程式碼,之後直接呼叫相應的函式執行即可,程式輸入是trainingDigitstestDigits中的手寫體資料集。輸出是對測試集識別的結果及正確的結果和最終識別的錯誤率。

(1)設定k值為3,執行過程及結果如下:





最終識別的錯誤率為1.2%

(2)改變K值大小,設為6,執行過程及結果如下:


最終的錯誤率是2.0%,即隨著k值的增大錯誤率在增加。
(3)改變k值大小,設定為2,執行結果如下:


最終的錯誤率是1.4%,錯誤率增加了。

因此選擇合適的k值可以有效的降低錯誤,提高識別的正確率。