1. 程式人生 > >MachineLearning— (KNN)k Nearest Neighbor實現手寫數字識別(三)

MachineLearning— (KNN)k Nearest Neighbor實現手寫數字識別(三)

    本篇博文主要結合前兩篇的knn演算法理論部分knn理論理解(一)knn理論理解(二),做一個KNN的實現,主要是根據《機器學習實戰》這本書的內容,一個非常經典有趣的例子就是使用knn最近鄰演算法來實現對手寫數字的識別,下面將給出Python程式碼,儘量使用詳盡的解釋和註解讓大家更好地理解每一步的目的和方法,歡迎大家一起交流學習~~~

    我們使用的training資料儲存在trainingDigits當中,我們總共使用了100個樣本點資料,從0到9總共十個數字,每個數字有十個手寫資料,所以我們準備了總共100個樣本點來作為基準計算樣本;

 

而每個手寫數字則是以文字的形式儲存,每一個手寫數字都被提前進行了二值化處理,即只是用0,1兩個數字來表現手寫數字,如下所示:


這樣做的目的顯然可以方便我們將其轉化為特徵行向量進行計算,同時能夠儲存足夠的原資訊量用來進行數字識別;

而測試資料則是儲存在testDigits檔案當中,我們準備了50個樣本點用來測試識別分類效果,十個數字,每個數字有五個測試點,所以我們總共有50個樣本資料;(這裡我們要注意一下檔案的命名格式)


下面給出Python實現程式碼,程式碼主要包括三大塊吧,每一塊主要的功能分別是:

第一塊的目的是要將原本32*32大小的矩陣數字轉化為1*1024的行向量,第二塊是測試分類模組程式(獲得handwritinglabels數字標籤列表 將訓練資料儲存到大矩陣trainingMat當中去)(逐一讀取測試圖片並將其送到classify0分類器當中得出分類識別結果並最終列印結果),第三塊的目的是編寫分類主程式即knn演算法核心部分計算歐氏距離找出k近鄰點並將最多的那個作為測試樣本的識別結果;

<span style="font-size:14px;"># -*- coding: utf-8 -*-
#樣本是32*32的二值圖片,將其處理成1*1024的特徵行向量
#第一塊</span>
from numpy import *
import operator
from os import listdir

def img2vector(filename):
    returnVect = zeros((1,1024))   <span style="font-size:14px;">#產生一個數組將來用於儲存圖片資料</span>
    fr = open(filename)
    for i in range(32):
        lineStr = fr.readline()    <span style="font-size:14px;">#讀取第一行的32個二值資料</span>
        for j in range(32):
            returnVect[0,32*i+j] = int(lineStr[j])   <span style="font-size:14px;">#以32為一個迴圈 逐漸填滿1024個</span>
    return returnVect


<span style="font-size:14px;">#第二塊</span>
def handwritingClassTest():
    <span style="font-size:14px;">#載入訓練集到大矩陣trainingMat</span>
    hwLabels = []
    trainingFileList = listdir('C:\\Anaconda\\trainingDigits')           <span style="font-size:14px;">#os模組中的listdir('str')可以讀取目錄str下的所有檔名,返回一個字串列表</span>
    m = len(trainingFileList)                 <span style="font-size:14px;">#m表示總體訓練樣本個數</span>
    trainingMat = zeros((m,1024))             <span style="font-size:14px;">#用來存放m個樣本</span>
    for i in range(m):
        fileNameStr = trainingFileList[i]                  <span style="font-size:14px;">#訓練樣本的命名格式:1_120.txt 獲取檔名</span>
        fileStr = fileNameStr.split('.')[0]                <span style="font-size:14px;">#string.split('str')以字元str為分隔符切片,返回list,這裡去list[0],得到類似1_120這樣的</span>
        classNumStr = int(fileStr.split('_')[0])           <span style="font-size:14px;">#以_切片,得到1,即數字類別</span>
        hwLabels.append(classNumStr)                    <span style="font-size:14px;">#這樣hwLabels列表中儲存了m個樣本點的所有類別</span>
        trainingMat[i,:] = img2vector('C:\\Anaconda\\trainingDigits\\%s' % fileNameStr)    <span style="font-size:14px;">#將每個樣本存到m*1024矩陣</span>
        
    <span style="font-size:14px;">#逐一讀取測試圖片,同時將其分類 </span>  
    testFileList = listdir('C:\\Anaconda\\testDigits')     <span style="font-size:14px;">#測試檔名列表   </span>
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]            <span style="font-size:14px;">#獲取此刻要測試的檔名</span>
        fileStr = fileNameStr.split('.')[0]     
        classNumStr = int(fileStr.split('_')[0])          <span style="font-size:14px;">#數字標籤分類 重新生成的classNumStr 並沒有使用上面已有的classNumStr</span>
        vectorUnderTest = img2vector('C:\\Anaconda\\testDigits\\%s' % fileNameStr)  <span style="font-size:14px;">#將要測試的數字轉化為一行向量</span>
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)   <span style="font-size:14px;">#傳參</span>
        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 style="font-size:14px;">#第三塊
#分類主程式,計算歐式距離,選擇距離最小的前k個,返回k箇中出現頻次最高的類別作為分類別
#inX是所要測試的向量
#dataSet是訓練樣本集,一行對應一個樣本,dataSet對應的標籤向量為labels
#k是所選的最近鄰數</span>
def classify0(inX, dataSet, labels, k):      <span style="font-size:14px;">#引數和上面的一一對應</span>
    dataSetSize = dataSet.shape[0]                       <span style="font-size:14px;">#shape[0]得出dataSet的行數,即訓練樣本個數
    diffMat = tile(inX, (dataSetSize,1)) - dataSet       #tile(A,(m,n))將陣列A作為元素構造m行n列的陣列 100*1024的陣列
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)                  #array.sum(axis=1)按行累加,axis=0為按列累加
    distances = sqDistances**0.5                        #就是sqrt的結果
    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
    #classCount的形式:{5:3,0:6,1:7,2:1}
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) #sorted()函式,按照第二個元素即value的次序逆向(reverse=True)排序
                                                         #sorted第一個引數表示要排序的物件 iteritems代表鍵值對 
    return sortedClassCount[0][0]                        #經過sorted後的字典變成了[(),()]形式的鍵值對列表</span>


測試結果:
import knn

knn.handwritingClassTest()
the classifier came back with: 0, the real answer is: 0
the classifier came back with: 0, the real answer is: 0
the classifier came back with: 0, the real answer is: 0
the classifier came back with: 0, the real answer is: 0
the classifier came back with: 0, the real answer is: 0
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 4, the real answer is: 4
the classifier came back with: 4, the real answer is: 4
the classifier came back with: 4, the real answer is: 4
the classifier came back with: 4, the real answer is: 4
the classifier came back with: 4, the real answer is: 4
the classifier came back with: 5, the real answer is: 5
the classifier came back with: 5, the real answer is: 5
the classifier came back with: 5, the real answer is: 5
the classifier came back with: 5, the real answer is: 5
the classifier came back with: 5, the real answer is: 5
the classifier came back with: 6, the real answer is: 6
the classifier came back with: 6, the real answer is: 6
the classifier came back with: 6, the real answer is: 6
the classifier came back with: 6, the real answer is: 6
the classifier came back with: 6, the real answer is: 6
the classifier came back with: 7, the real answer is: 7
the classifier came back with: 7, the real answer is: 7
the classifier came back with: 7, the real answer is: 7
the classifier came back with: 7, the real answer is: 7
the classifier came back with: 7, the real answer is: 7
the classifier came back with: 8, the real answer is: 8
the classifier came back with: 8, the real answer is: 8
the classifier came back with: 8, the real answer is: 8
the classifier came back with: 8, the real answer is: 8
the classifier came back with: 8, the real answer is: 8
the classifier came back with: 9, the real answer is: 9
the classifier came back with: 9, the real answer is: 9
the classifier came back with: 9, the real answer is: 9
the classifier came back with: 9, the real answer is: 9
the classifier came back with: 9, the real answer is: 9

the total number of errors is: 0

the total error rate is: 0.000000

我們發現準確率還是挺高的,沒有一個錯誤的,原因是我們使用的資料量比較小,恰巧沒有一個錯誤的;

相關推薦

MachineLearning— (KNN)k Nearest Neighbor實現數字識別

    本篇博文主要結合前兩篇的knn演算法理論部分knn理論理解(一)和knn理論理解(二),做一個KNN的實現,主要是根據《機器學習實戰》這本書的內容,一個非常經典有趣的例子就是使用knn最近鄰演算法來實現對手寫數字的識別,下面將給出Python程式碼,儘量使用詳盡的解

MNIST數字識別應用優化

本篇的主要內容 應用三種優化方式,對之前的模型進行優化 介紹一些在程式中用到的函式 學習於《TensorFlow實戰Google深度學習框架》一書 程式 相比於第一次的簡單邏輯迴歸模型,這一次的調整了網路結構,添加了一個500個節點的隱藏層,在結構中,設定了

基於tensorflow的MNIST數字識別--神經網路篇

想想還是要說點什麼     抱歉啊,第三篇姍姍來遲,確實是因為我懶,而不是忙什麼的,所以這次再加點料,以表示我的歉意。廢話不多說,我就直接開始講了。 加入神經網路的意義     前面也講到了,使用普通的訓練方法,也可以進行識別,但是識別的精度不夠高,

Matlab實現數字識別PCA+KNN

</pre><pre name="code" class="plain">clear; addpath('../data/'); % images_train = loadMNISTImages('train-images-idx3-ubyte')'

KNN演算法——實現數字識別Sklearn實現

KNN專案實戰——手寫數字識別 1、資料集介紹 需要識別的數字已經使用圖形處理軟體,處理成具有相同的色彩和大小:寬高是32畫素x32畫素的黑白影象。儘管採用本文格式儲存影象不能有效地利用記憶體空間,但是為了方便理解,我們將圖片轉換為文字格式。 數字的文字格式如下:

MNIST資料集實現數字識別基於tensorflow

主要應用了下面幾個方法來提高準確率; 使用隨機梯度下降(batch) 使用Relu啟用函式去線性化 使用正則化避免過擬合 使用帶指數衰減的學習率 使用滑動平均模型 使用交叉熵損失函式來刻畫預測值和真實值之間的差距的損失函式 第一步,匯入MNIST資料集 from

MNIST數字識別幾種模型優化方式介紹

本篇的主要內容有: 動態衰減法設定可變學習率 為損失函式新增正則項 滑動平均模型介紹 為了讓MNIST數字識別模型更準確,學習幾種常用的模型優化手段: 學習率的優化 學習率的設定一定程度上也會影響模型的訓練,如果學習率過小,那麼將會經過很長時間才會收斂到想要

基於tensorflow的MNIST數字識別--入門篇

一、本文的意義       因為谷歌官方其實已經寫了MNIST入門和深入兩篇教程了,那我寫這些文章又是為什麼呢,只是抄襲?那倒並不是,更準確的說應該是筆記吧,然後用更通俗的語言來解釋,並且補充

數字識別

在學習識別手寫輸入數字時,初始化矩陣那裡,有點不理解。原始碼是這樣的:self.biases=[np.random.randn(y,1) for y in sizes[1:]] '''建立一個偏差向量''' self.weights=[np.random.ra

MNIST 數字識別

MNIST 手寫數字識別模型建立與優化 本篇的主要內容有: TensorFlow 處理MNIST資料集的基本操作 建立一個基礎的識別模型 介紹 SoftmaxSoftmaxSoftmax迴歸以及交叉熵等 MNIST是一個很有名的手寫數字識別資料集(基本可以算

機器學習--k-近鄰演算法kNN實現數字識別

這裡的手寫數字以0,1的形式儲存在文字檔案中,大小是32x32.目錄trainingDigits有1934個樣本。0-9每個數字大約有200個樣本,命名規則如下: 下劃線前的數字代表是樣本0-9的

MachineLearning— (KNN)k Nearest Neighbor之最近鄰法原理舉例理解

K近鄰法(k-nearest neighbor)是機器學習當中較為簡單理解的一種基本分類與迴歸方法,KNN輸入的是例項的特徵向量,也就是特徵空間上的點;輸出的是其對應的類別標籤,KNN的訓練資料集的

一看就懂的K近鄰演算法(KNN),K-D樹,並實現數字識別

1. 什麼是KNN 1.1 KNN的通俗解釋 何謂K近鄰演算法,即K-Nearest Neighbor algorithm,簡稱KNN演算法,單從名字來猜想,可以簡單粗暴的認為是:K個最近的鄰居,當K=1時,演算法便成了最近鄰演算法,即尋找最近的那個鄰居。 用官方的話來說,所謂K近鄰演算法,即是給定一個訓練資

各種機器學習方法線性迴歸、支援向量機、決策樹、樸素貝葉斯、KNN演算法、邏輯迴歸實現數字識別並用準確率、召回率、F1進行評估

本文轉自:http://blog.csdn.net/net_wolf_007/article/details/51794254 前面兩章對資料進行了簡單的特徵提取及線性迴歸分析。識別率已經達到了85%, 完成了數字識別的第一步:資料探測。 這一章要做的就各

學習KNNKNN+HOG實現數字識別

在學習KNN(二)KNN演算法手寫數字識別的OpenCV實現我們直接將畫素值作為特徵,實現了KNN演算法的手寫數字識別問題,並得到了較好的準確率,但是就像其他機器學習演算法一樣,KNN的物件同樣是特徵,所以我們可以用一種特徵提取演算法配合KNN實現手寫數字識

第二節,TensorFlow 使用前饋神經網絡實現數字識別

com net config return pyplot dataset 運行 算法 但是 一 感知器 感知器學習筆記:https://blog.csdn.net/liyuanbhu/article/details/51622695 感知器(Percep

第三節,TensorFlow 使用CNN實現數字識別

啟用 out min 灰度 HA 打破 gre 大量 gray 上一節,我們已經講解了使用全連接網絡實現手寫數字識別,其正確率大概能達到98%,著一節我們使用卷積神經網絡來實現手寫數字識別, 其準確率可以超過99%,程序主要包括以下幾塊內容 [1]: 導入數據,即測試集和

TensorFlow(九):卷積神經網絡實現數字識別以及可視化

writer orm true 交叉 lar write 執行 one 界面 上代碼: import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist =

TensorFlow(十二):使用RNN實現數字識別

rop mea pre rnn ext ini tro truncate tutorial 上代碼: import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #

10 行程式碼,實現數字識別

識別手寫的阿拉伯數字,對於人類來說十分簡單,但是對於程式來說還是有些複雜的。   不過隨著機器學習技術的普及,使用10幾行程式碼,實現一個能夠識別手寫數字的程式,並不是一件難事。這是因為有太多的機器學習模型可以拿來直接用,比如tensorflow、caffe,在python下