深度學習入門 基於python理論和實踐讀書筆記(五)

第三章 神經網絡 第六節

手寫數字識別

這是一個運用神經網絡來解決問題的實列
使用的數據集是MNIST手寫數字數據圖像集,由0-9的數字構成。先訓練圖形進行學習,再用學習到的模型度量能在多大程度對測試圖像進行正確的分類。
    首先我們需要講MNIST數據集下載下來,該書源碼終提供了一個下載該數據集的腳本。
讀入數據的python腳本代碼

import sys,os
sys.path.append(os.pardir)
from  dataset.mnist import load_mnist
(x_train,t_trian),(x_test,t_test) = load_mnist(flatten=True,normalize=False)
print(x_train.shape)# (60000, 784)
print(t_trian.shape)# (60000, )
print(x_test.shape)# (10000, 784)
print(t_test.shape)# (10000,)

這裏我對輸出的形狀做一個總結的理解
      x_train.shape的形狀是(60000, 784),就是由6萬行,784列。因爲有6萬個數據,然後每一張圖片的每一個像素做爲一列有28*28=784個像素所以這個形狀爲(60000, 784)。t_trian.shape是標籤的形狀,是因爲對每一張圖片都做了標籤,所以→萬張圖片就做了6萬個標籤。所以形狀是(60000, )。後面的測試數據同理
      因爲腳本mnist.py文件沒有和我們直接寫的python文件放在同樣一個文件夾中,所以用sys.path.append(os.pardir)掃描根父目錄下的文件。flatten這個參數表示的是是否把輸入的圖像展開,展開後就變成一維的了。normalize這個參數設置是否把輸入的圖像正規化讓其像素在0-1之間。我的理解是講彩色的圖片變成灰色的了。正規化就是像這樣把數據限定到某個範圍內的處理稱爲正規化
      另外還學到Python有 pickle這個便利的功能,這個功能講可以運行到程序中的對象保存爲對象。如果加載保存過的pickle文件,就不用像之前那樣等待立刻可以復原之前程序中運行的對象。
      現在我們來顯示MNIST圖像。
python代碼

import sys, os
sys.path.append(os.pardir) # 爲了導入父目錄中的文件而進行的設定
import numpy as np
from PIL import Image
from dataset.mnist import load_mnist
# 第一次調用會花費幾分鐘 ……
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True,
normalize=False)
# 輸出各個數據的形狀
img = x_train[0]
lable = t_train[0]
print(lable)
def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))
    pil_img.show()
print(img.shape)
img = img.reshape(28,28)
print(img.shape)
img_show(img)

因爲flatten=True所以我們得到的是一個一維的數組,用reshape()方法的參數指定我們需要的形狀。Image.fromarray()把圖像轉化爲PIL可以用的數據對象。np.uint8(img)就是讓圖像的通道位8位。圖片有2^8=256種顏色。

神經網絡的推理處理

      這個神經網絡輸入層有784個神經元,因爲每一個圖片有28*28=784個像素。輸出層有10個神經元。因爲從0到9有10個類別。有兩個中間層就是隱藏層,第一個隱藏層有50個神經元,第二個隱藏層有100個神經元。
第一步獲取數據

def get_data():
     (x_train, t_train), (x_test, t_test) = \
     load_mnist(normalize=True, flatten=True, one_hot_label=False)
     return x_test, t_test

獲取MNIST中的訓練數據和訓練標籤
第二步初始化權重和偏置

def init_network():
     with open("sample_weight.pkl", 'rb') as f:
         network = pickle.load(f)
     return network

sample_weight.pkl文件來裏面假設學習已經完成,所以學習到的參數被保存下來。這個文件在源碼的ch03中有。像打開看裏面的內容可以這樣子看

f = open("sample_weight.pkl", 'rb')
info = pickle.load(f)
print(info)

第三步就是通過我們設定的權重和偏置進行分類。

def predict(network, x):
     W1, W2, W3 = network['W1'], network['W2'], network['W3']
     b1, b2, b3 = network['b1'], network['b2'], network['b3']
     a1 = np.dot(x, W1) + b1
     z1 = myfuction.sigmoid(a1)
     a2 = np.dot(z1, W2) + b2
     z2 = myfuction.sigmoid(a2)
     a3 = np.dot(z2, W3) + b3
     y = myfuction.softmax(a3)
     return y

最後一步就是檢驗我們分類的準確率

x,t = get_data()
network = init_network()
accuracy_cnt = 0
for i in range(len(x)):
    y = predict(network,x[i])
    p = np.argmax(y)
    if p == t[i]:
        accuracy_cnt += 1
print("Accuracy:"+ str((float(accuracy_cnt)/len(x))))

最後把我頭文件也貼出來吧


```python
import sys, os
sys.path.append(os.pardir) # 爲了導入父目錄中的文件而進行的設定
sys.path.append('H:/pythonfile/ch01/')#爲了導入我在ch01寫的sigmoid和softmax函數
import numpy as np
import activeFunction as myfuction
from PIL import Image
import pickle
from  dataset.mnist import  load_mnist

批處理

前面寫的代碼,for循環的時候是一張一張圖片去確定是否分類正確。批處理就是一次判斷很多張圖片。而不是每一次只判斷判斷一張。
批處理只需要把前面代碼的for循環變一下即可

for i in range(0,len(x),batch_size):
    x_batch = x[i:i+batch_size]
    y_batch = predict(network,x_batch)
    p = np.argmax(y_batch,axis=1)
    accuracy_cnt += np.sum(p == t[i:i+batch_size])

range()方法裏面的參數是這樣子的range(start,end,step),始以step爲單位將數據提取爲批數據。
list( range(0, 10) ),就是[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]。如果是list( range(0, 10, 3) ),就是[0, 3, 6, 9]。
np.argmax(x, axis=1),假如矩陣x是一個m*n的矩陣,就是從第axis-1行開始尋找每一行的最大數的下標(索引)。比如:
x = np.array([[0.1, 0.8, 0.1], [0.3, 0.1, 0.6],[0.2, 0.5, 0.3], [0.8, 0.1, 0.1]])
y = np.argmax(x, axis=1)
print(y)
[1 2 1 0]
最後的== 運算是這樣子的的
y = np.array([1, 2, 1, 0])
t = np.array([1, 2, 0, 0])
print(y== t)
[True True False True]
np.sum(y==t)
3
嗯整批處理代碼,就這樣子的,作者書上說,批處理很常用,也很重要喔。加油向下一章出發。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章