用python實現數字圖片識別神經網絡--啓動網絡的自我訓練流程,展現網絡數字圖片識別效果

上一節,咱們完成了網絡訓練代碼的實現,還有一些問題須要作進一步的確認。網絡的最終目標是,輸入一張手寫數字圖片後,網絡輸出該圖片對應的數字。因爲網絡須要從0到9一共十個數字中挑選出一個,因而咱們的網絡最終輸出層應該有十個節點,每一個節點對應一個數字。假設圖片對應的是數字0,那麼輸出層網絡中,第一個節點應該輸出一個高百分比,其餘節點輸出低百分比,若是圖片對應的數字是9,那麼輸出層最後一個節點應該輸出高百分比,其餘節點輸出低百分比,例以下圖:node

屏幕快照 2018-05-07 下午5.10.59.png數組

高比率,若是網絡認爲圖片對應的數字是0,那麼編號爲0的節點輸出0.95的高比率。最後一個例子是頗有意思,編號爲4和9的神經元都輸出一個不低的比率,這代表圖片對應的數字很像4和9,但神經網絡認爲是9的機率是4的機率的兩倍以上。網絡

還記得上一節咱們準備好要輸入網絡的數據嗎:app

這裏寫圖片描述函數

數據的第一個值表明圖片對應的數字,咱們須要把這種對應信息經過代碼表現出來:學習

#最外層有10個輸出節點onodes = 10
targets = numpy.zeros(onodes) + 0.01
targets[int(all_values[0])] = 0.99print(targets)

上面代碼的輸出結果爲:測試

image.png大數據

targets第8個元素的值是0.99,這表示圖片對應的數字是7,記住數組是從編號0開始的。根據這種作法,咱們就能把輸入圖片給對應的正確數字創建聯繫,這種聯繫就能夠用於輸入到網絡中,進行訓練。因爲一張圖片總共有28*28 = 764個數值,所以咱們須要讓網絡的輸入層具有764個輸入節點,因而網絡的初始化以及將數據輸入網絡進行訓練的實現代碼爲:人工智能

#初始化網絡input_nodes = 784hidden_nodes = 100output_nodes = 10learning_rate = 0.3n = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)#讀入訓練數據#open函數裏的路徑根據數據存儲的路徑來設定training_data_file = open("/Users/chenyi/Documents/人工智能/mnist_train_100.csv")
trainning_data_list = training_data_file.readlines()
training_data_file.close()#把數據依靠','區分,並分別讀入for record in trainning_data_list:
    all_values = record.split(',')
    inputs = (numpy.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01
    #設置圖片與數值的對應關係
    targets = numpy.zeros(output_nodes) + 0.01
    targets[int(all_values[0])] = 0.99
    n.train(inputs, targets)

這裏須要注意的是,中間層的節點咱們選擇了100個神經元,這個選擇實際上是經驗值,也就是中間層的節點數其實沒有專門的辦法去規定,其數量會根據不一樣的問題而變化,肯定中間層神經元節點數最好的辦法是實驗,你不停的選取各類數量,看看那種數量能使得網絡的表現最好就行。spa

上面代碼把一百條數據輸入網絡進行訓練,如今咱們看看訓練後的網絡它的表現怎樣。咱們先從加載另外一組數據,取出其中一張手寫數字圖片,將其輸入到網絡中,看看網絡的判斷結果如何:

test_data_file = open("/Users/chenyi/Documents/人工智能/mnist_test_10.csv")
test_data_list = test_data_file.readlines()
test_data_file.close()import numpyimport matplotlib.pyplot
%matplotlib inline#把數據依靠','區分,並分別讀入all_values = data_list[0].split(',')#第一個值對應的是圖片的表示的數字,因此咱們讀取圖片數據時要去掉第一個數值image_array = numpy.asfarray(all_values[1:]).reshape((28, 28))
matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None')

這段代碼咱們在上一節講解過,咱們把測試數據裏面的第一張手寫數字圖片先繪製出來,代碼運行結果以下:

 

這裏寫圖片描述

經過人眼觀察,咱們基本肯定這種圖片對應的是數字7,那麼網絡識別它的結果如何呢,咱們將這張圖片的數字輸入到網絡看看其識別結果:

n.query(numpy.asfarray(all_values[1:]) / 255.0  * 0.99 + 0.01)

上面這行代碼運行後結果以下:

 

這裏寫圖片描述

前面咱們討論過最外層節點輸出的意義,最外層節點有十個,分別對應0到9十個數字,哪一個節點輸出的數值高,那意味着網絡認爲圖片對應哪一個數字,咱們看到網絡輸出中,對應編號爲7的節點輸出值最大,爲0.68,也就是說網絡把圖片識別爲數字7,這與咱們的觀察是一致的,這麼說咱們辛辛苦苦打造的網絡是有效的,前面那麼多的鋪墊到如今終於有了收穫。

咱們原來給網絡輸入的訓練數據來自trainning_set,而如今給網絡判斷的圖片來自testing_set,所以網絡從未見過這張圖片,它能識別這張圖片是數字7,這種能力是經過分析訓練圖片,不斷改進鏈路權重值的結果。實現網絡的Python代碼不過百來行,他竟然就能實現了咱們所認爲的人工智能,如此看來人工智能彷佛並不是那麼神祕。

接着咱們把全部測試圖片都輸入網絡,看看它檢測的效果如何,代碼以下:

scores = []for record in test_data_list:
    all_values = record.split(',')
    correct_number = int(all_values[0])    print("該圖片對應的數字爲:",correct_number)    #預處理數字圖片
    inputs = (numpy.asfarray(all_values[1:])) / 255.0 * 0.99 + 0.01    #讓網絡判斷圖片對應的數字
    outputs = n.query(inputs)    #找到數值最大的神經元對應的編號
    label = numpy.argmax(outputs)    print("out put reslut is : ", label)    #print("網絡認爲圖片的數字是:", label)
    if label == correct_number:
        scores.append(1)    else:
        scores.append(0)print(scores)

上面代碼把測試數據集裏的10張圖片所有加載,而後輸入到網絡中,看看網絡對每張數字圖片的識別效果如何,上面代碼運行後結果以下:

這裏寫圖片描述

從輸出結果看,有些圖片網絡仍是識別錯了,最後代碼打印出一個數組,裏面的1表示識別正確,0表示識別錯誤,從數組內容看,有4張圖片網絡給出了錯誤答案。此次的結果多少使人有些沮喪,咱們計算一下圖片判斷的成功率:

scores_array = numpy.asarray(scores)print("perfermance = ", scores_array.sum() / scores_array.size)

代碼運行後結果以下:

這裏寫圖片描述

由此看來,網絡識別的成功率只有六成。爲了提高成功率,咱們必須加大網絡的訓練力度,原來咱們訓練網絡時只使用了100條數據,如今咱們使用60000條數據,而後用10000條數據做爲測試集,咱們從如下兩個連接獲取相應的數據集:

http://www.pjreddie.com/media/files/mnist_train.csvhttp://www.pjreddie.com/media/files/mnist_test.csv

而後咱們把原來代碼作一點小修改,加載上面的數據來對網絡進行訓練和測試:

#初始化網絡input_nodes = 784
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.3
n = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate)#讀入訓練數據#open函數裏的路徑根據數據存儲的路徑來設定training_data_file = open("/Users/chenyi/Documents/人工智能/mnist_train.csv")
trainning_data_list = training_data_file.readlines()print(len(trainning_data_list))
training_data_file.close()#把數據依靠','區分,並分別讀入for record in trainning_data_list:
    all_values = record.split(',')
    inputs = (numpy.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01    #設置圖片與數值的對應關係
    targets = numpy.zeros(output_nodes) + 0.01
    targets[int(all_values[0])] = 0.99
    n.train(inputs, targets)
    
test_data_file = open("/Users/chenyi/Documents/人工智能/mnist_test.csv")
test_data_list = test_data_file.readlines()
test_data_file.close()
scores = []for record in test_data_list:
    all_values = record.split(',')
    correct_number = int(all_values[0])    #預處理數字圖片
    inputs = (numpy.asfarray(all_values[1:])) / 255.0 * 0.99 + 0.01    #讓網絡判斷圖片對應的數字
    outputs = n.query(inputs)    #找到數值最大的神經元對應的編號
    label = numpy.argmax(outputs)    if label == correct_number:
        scores.append(1)    else:
        scores.append(0)
scores_array = numpy.asarray(scores)print("perfermance = ", scores_array.sum() / scores_array.size)

上面代碼跟之前是同樣的,只不過加載的數據文件不一樣而已,此次咱們用60000條數據來訓練網絡,而後用10000條數據來檢測網絡的準確性,上面代碼執行後結果以下:

 

這裏寫圖片描述

從結果上看,當訓練網絡的數據流增大後,網絡識別的正確性由原來的0.6提高到0.9,咱們再次用新訓練後的網絡識別原來那十張數字圖片,獲得結果以下:

這裏寫圖片描述

通過大數據訓練後的網絡,對圖片的識別率達到了百分之百,這意味着當用於訓練網絡的數據越多,網絡識別的效果就越好,這就是爲什麼在某種程度上說,人工智能也是大公司的大殺器,由於只有大公司才能擁有足量的數據。

在整個過程,咱們一直保持着學習率不變,實際上學習率的大小對網絡的訓練效果有很大影響,你們能夠把該參數改爲0.6,0.1等不一樣的值去看看結果,另外也能夠修改中間層的節點數看看有什麼效果。二手叉車哪家好

這裏咱們引入在第一節時提到的一個概念叫epocs,它表示網絡進行幾回訓練循環,對其使用的代碼以下:

#加入epocs,設定網絡的訓練循環次數epochs = 10for e in range(epochs):    #把數據依靠','區分,並分別讀入
    for record in trainning_data_list:
        all_values = record.split(',')
        inputs = (numpy.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01
        #設置圖片與數值的對應關係
        targets = numpy.zeros(output_nodes) + 0.01
        targets[int(all_values[0])] = 0.99
        n.train(inputs, targets)

也就是在原來網絡訓練的基礎上再加上一層外循環,上面代碼運行後執行的對於普通電腦而言執行的時間會很長。通常來講,epochs 的數值越大,網絡被訓練的就越精準,但若是超過一個閾值,網絡就會引起一個過渡擬合的問題,也就是網絡會對老數據識別的很精準,但對新數據識別的效率反而變得愈來愈低,你們能夠自行嘗試一下不一樣的學習率和epochs組合,看看網絡的識別精度是否有所提升,另外你們也能夠修改中間層的節點數看看其對網絡的識別精度是否有顯著影響,在我電腦上把epochs設置成7時,成功率能提高到95%。

相關文章
相關標籤/搜索