日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

用BP人工神经网络识别手写数字——《Python也可以》之三

發布時間:2025/3/21 python 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用BP人工神经网络识别手写数字——《Python也可以》之三 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

賴勇浩(http://laiyonghao.com)

這是我讀工程碩士的時候完成課程作業時做的,放在 dropbox 的角落中生塵已經有若干年頭了,最近 @shugelee 同學突然來了興致搞驗證碼識別,問到我的時候我記起自己做過一點點東西,特發上來給他參考,并趁機補充了一下《Python也可以》系列。

圖像預處理

使用下圖(后方稱為 SAMPLE_BMP)作為訓練和測試數據來源,下文將講述如何將圖像轉換為訓練數據。

灰度化和二值化

在字符識別的過程中,識別算法不需要關心圖像的彩色信息。因此,需要將彩色圖像轉化為灰度圖像。經過灰度化處理后的圖像中還包含有背景信息。因此,我們還得進一步處理,將背景噪聲屏蔽掉,突顯出字符輪廓信息。二值化處理就能夠將其中的字符顯現出來,并將背景去除掉。在一個[0,255]灰度級的灰度圖像中,我們取 196 為該灰度圖像的歸一化值,代碼如下:
[python] view plain copy
  • def?convert_to_bw(im):??
  • ????im?=?im.convert("L")??
  • ????im.save("sample_L.bmp")??
  • ????im?=?im.point(lambda?x:?WHITE?if?x?>?196?else?BLACK)??
  • ????im?=?im.convert('1')??
  • ????im.save("sample_1.bmp")??
  • ????return?im??
  • 下圖是灰度化的圖像,可以看到背景仍然比較明顯,有一層淡灰色:

    下圖是二值化的圖像,可以看到背景已經完全去除:

    圖片的分割和規范化:

    通過二值化圖像,我們可以分割出每一個字符為一個單獨的圖片,然后再計算相應的特征值,如下圖所示:

    這些圖片是由程序自動進行分割而成,其中用到的代碼片段如下:
    [python] view plain copy
  • def?split(im):??
  • ????assert?im.mode?==?'1'??
  • ????result?=?[]??
  • ????w,?h?=?im.size??
  • ????data?=?im.load()??
  • ????xs?=?[0,?23,?57,?77,?106,?135,?159,?179,?205,?228,?w]??
  • ????ys?=?[0,?22,?60,?97,?150,?h]??
  • ????for?i,?x?in?enumerate(xs):??
  • ????????if?i?+?1?>=?len(xs):??
  • ????????????break??
  • ????????for?j,?y?in?enumerate(ys):??
  • ????????????if?j?+?1?>=?len(ys):??
  • ????????????????break??
  • ????????????box?=?(x,?y,?xs[i+1],?ys[j+1])??
  • ????????????t?=?im.crop(box).copy()??
  • ????????????box?=?box?+?((i?+?1)?%?10,?)??
  • #???????????save_32_32(t,?'num_%d_%d_%d_%d_%d'%box)??
  • ????????????result.append((normalize_32_32(t,?'num_%d_%d_%d_%d_%d'%box),?(i?+?1)?%?10))??
  • ????return?result??
  • 其中的 xs 和 ys 分別是橫向和豎向切割的分界點,由手工測試后指定,t = im.crop(box).copy() 代碼行是從指定的區域中“摳”出圖片,然后通過 normalize_32_32 進行規范化。進行規范化是為了產生規則的訓練和測試數據集,也是為了更容易地地計算出特征碼。

    產生訓練數據集和測試數據集

    為簡單起見,我們使用了最簡單的圖像特征——黑色像素在圖像中的分布來進行訓練和測試。首先,我們把圖像規范化為 32*32 像素的圖片,然后按 2*2 分切成 16*16 共 256 個子區域,然后統計這 4 個像素中黑色像素的個數,組成 256 維的特征矢量,如下是數字 2 的一個特征矢量:
    0 0 4 4 4 2 0 0 0 0 0 0 0 0 2 4 0 0 4 4 4 2 0 0 0 0 0 0 0 0 2 4 2 2 4 4 2 1 0 0 0 0 0 0 1 2 3 4 4 4 4 4 0 0 0 0 0 0 0 0 2 4 4 4 4 4 4 4 0 0 0 0 0 0 0 0 2 4 4 4 4 4 0 0 0 0 0 0 0 0 0 0 2 4 4 4 4 4 0 0 0 0 0 0 0 0 0 0 2 4 4 4 4 4 0 0 0 0 0 0 0 4 4 4 4 4 4 4 4 4 0 0 0 0 0 0 0 4 4 4 4 4 4 4 4 4 2 2 2 2 2 2 2 4 4 2 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 0 2 4 4 4 2 2 2 2 4 3 2 2 2 2 2 0 2 4 4 4 0 0 0 0 4 2 0 0 0 0 0 0 2 4 4 4 0 0 0 0 4 2 0 0 0 0 0 0 2 4 4 4 0 0 0 0 0 0 0 0 0 0 0 0 2 4 4 4 0 0 0 0 0 0 0 0 0 0 0 0 2 4 4 4
    相應地,因為我們只需要識別 0~9 共 10 個數字,所以創建一個 10 維的矢量作為結果,數字相應的維置為 1 值,其它值為 0。數字 2 的結果如下:0 0 1 0 0 0 0 0 0 0
    我們特征矢量和結果矢量通過以下代碼計算出來后,按 FANN 的格式把它們存到 train.data 中去:
    [python] view plain copy
  • f?=?open('train.data',?'wt')??
  • print?>>f,?len(result),?256,?10??
  • for?input,?output?in?result:??
  • ????print?>>f,?input??
  • ????print?>>f,?output??
  • BP神經網絡

    利用神經網絡識別字符是本文的另外一個關鍵階段,良好的網絡性能是識別結果可靠性的重要保證。這里就介紹如何利用BP 神經網絡來識別字符。反向傳播網絡(即:Back-Propagation Networks ,簡稱:BP 網絡)是對非線性可微分函數進行權值訓練的多層前向網絡。在人工神經網絡的實際應用中,80%~90%的模型采用 BP 網絡。它主要用在函數逼近,模式識別,分類,數據壓縮等幾個方面,體現了人工神經網絡的核心部分。

    網絡結構

    網絡結構的設計是根據輸入結點和輸出結點的個數和網絡性能來決定的,如下圖。本實驗中的標準待識別字符的大小為 32*32 的二值圖像,即將 1024 個像素點的圖像轉化為一個 256 維的列向量作為輸入。由于本實驗要識別出10 個字符,可以將目標輸出的值設定為一個10 維的列向量,其中與字符相對應那個位為1,其他的全為0 。根據實際經驗和試驗確定,本文中的網絡隱含層結點數目為64。因此,本文中的BP 網絡的結構為 256-64-10。

    訓練結果

    本實驗中的采用的樣本個數為 50 個,將樣本圖像進行預處理,得到處理后的樣本向量P,再設定好對應的網絡輸出目標向量T,把樣本向量 P 和網絡輸出目標向量 T 都保存到 train.data 文件中。設置好網絡訓練參數,對網絡進行訓練和測試,并將最佳的一個網絡權值保存到 number_char_recognize.net 文件中。下面就將本文中設置和訓練網絡參數的程序列舉如下:
    [python] view plain copy
  • connectionRate?=?1??
  • learningRate?=?0.008??
  • desiredError?=?0.001??
  • maxIterations?=?10000??
  • iterationsBetweenReports?=?100??
  • inNum=?256??
  • hideNum?=?64??
  • outNum=10??
  • class?NeuNet(neural_net):??
  • ????def?__init__(self):??
  • ????????neural_net.__init__(self)??
  • ????????neural_net.create_standard_array(self,(inNum,?hideNum,?outNum))??
  • ??
  • ??????????
  • ????def?train_on_file(self,fileName):??
  • ????????neural_net.train_on_file(self,fileName,maxIterations,iterationsBetweenReports,desiredError)??
  • 可以從代碼中看到我們建立起一個輸出層有 256 個神經元,隱藏層有 64 個神經元,輸出層有 10 個神經元的ANN,其中神經層的連接率為 100%,學習率為 0.28,最大進行 10000 次迭代,并每隔 100 次報告一下學習結果。
    [python] view plain copy
  • if?__name__?==?"__main__":??
  • ????ann?=?NeuNet()??
  • ????ann.train_on_file("train.data")??
  • ????ann.save("number_char_recognize2.net")??
  • 按照上面的程序,對網絡進行訓練和仿真測試,保存訓練性能最好的一組網絡權值,并保存到起來。

    通過 666 次迭代之后,錯誤率已經低于 0.001,學習中止,并將結果保存起來。

    測試結果

    實驗的測試是通過從保存好的 NN 數據文件中創建 NN 的形式來實驗的,具體的代碼如下:
    [python] view plain copy
  • if?__name__?==?"__main__":??
  • ????ann?=?NeuNet()??
  • ????ann.create_from_file("number_char_recognize.net")??
  • ????data?=?read_test_data()??
  • ????for?k,?v?in?data.iteritems():??
  • ????????k?=?string_to_list(k)??
  • ????????v?=?string_to_list(v)??
  • ????????result?=?ann.run(k)??
  • ????????print?euclidean_distance(v,?result)??
  • 其實 ann.create_from_file 是從文件中讀取存檔,創建人工神經網絡,然后使用 read_test_data 函數讀取測試數據,并通過循環對每一個測試數據和相應的期望值轉換為 NN 的輸入格式,然后使用 ann.run 函數調用神經網絡測試,對測試結果與期望值進行歐氏距離計算,對其中的兩個測試用例,果如下:

    可見兩個向量的歐氏距離已經接近于 0,識別效果非常好。

    小結

    本文為該項研究的初步實驗階段,由于樣本字符的數目較少,選取了50 個樣本用來訓練,對10 個待檢數字字符進行識別和仿真,成功識別出字符的個數為9 個,識別效率為90.0%。對于神經網絡而言,在這樣少的訓練樣本的情況下,能夠取的這種效果已經比較成功,表明該方法具有較好識別性能。

    總結

    以上是生活随笔為你收集整理的用BP人工神经网络识别手写数字——《Python也可以》之三的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。