keras實現mnist數據集手寫數字識別

經過幾天的爬坑,“東搞西搞”終於把深度學習的“HELLO,WORLD”做出來了,以下是自己的實戰過程:

關於keras識別手寫數字的入門準備:

1.Keras是一個高層神經網絡API,Keras由純Python編寫而成並基TensorflowTheano以及CNTK後端。所以在安裝keras的前面,要先搭建tensorflow環境和安裝https://www.tensorflow.org/install/install_windows(這裏是官方的安裝過程)

2.Mnist數據集的準備

3.導入數據集測試

4.實現baseline模型:

5.實現簡單的卷積神經網絡

 

一. Tensorflow環境的安裝

這裏我們只講CPU版本,使用 Anaconda 進行安裝

a.首先我們要安裝 Anaconda

鏈接:https://pan.baidu.com/s/1AxdGi93oN9kXCLdyxOMnRA 密碼:79ig

過程如下:

第一步:點擊next

第二步:I Agree

第三步:Just ME

第四步:自己選擇一個恰當位置放它就好

第五步:建議只選擇第二個

 

第六步:就直接install啦啦啦啦,然後你就可以上手萬能庫了

 

b.找到Anaconda prompt,然後

 

以管理員的身份打開終端

c.按照以下步驟在 Anaconda 環境中安裝 TensorFlow:

  1. 通過調用以下命令創建名爲 tensorflow 的 conda 環境:

C:> conda create -n tensorflow pip python=3.5

  1. 通過發出以下命令激活 conda 環境:

C:> activate tensorflow (tensorflow)C:> # Your prompt should change

  1. 發出相應命令以在 conda 環境中安裝 TensorFlow。要安裝僅支持 CPU 的 TensorFlow 版本,請輸入以下命令:

(tensorflow)C:> pip install --ignore-installed --upgrade tensorflow

 

d.測試tensorflow的安裝

啓動Anaconda prompt(同樣是以管理員身份打開)終端。

如果您是通過 Anaconda 進行安裝,請激活您的 Anaconda 環境。

終端輸入 activate tensorflow即可

然後再輸入python

如:

 

在 Python 交互式 shell 中輸入以下幾行簡短的程序代碼:

>>> import tensorflow as tf

>>> hello = tf.constant('Hello, TensorFlow!')

>>> sess = tf.Session()

>>> print(sess.run(hello))

如果系統輸出以下內容,說明您可以開始編寫 TensorFlow 程序了:

Hello, TensorFlow!

 

 

完成以上步驟,你就把tensorflow搭建好了......

 

二.安裝keras

a.首先,擔心我們anaconda裏面各個包未更新到最新,所以我們以管理員的身份打開Anaconda終端,輸入 conda update conda,執行完後,再輸入:conda update --all

b.然後我們激活我們的tensorflow環境:activate tensorflow

c.然後我們就可以輸入:pip install keras

 

三.完成上述步驟,我們就可以來試下加載keras裏面的mnist數據集了

# Plot ad hoc mnist instances
from keras.datasets import mnist
import matplotlib.pyplot as plt
# load (downloaded if needed) the MNIST dataset
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# plot 4 images as gray scale
plt.subplot(221)
plt.imshow(X_train[0], cmap=plt.get_cmap('gray'))
plt.subplot(222)
plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))
plt.subplot(223)
plt.imshow(X_train[2], cmap=plt.get_cmap('gray'))
plt.subplot(224)
plt.imshow(X_train[3], cmap=plt.get_cmap('gray'))
# show the plot
plt.show()

 

上面的代碼加載了數據集並畫出了前4個圖片: 
這裏寫圖片描述

好了接下來我們對上述代碼進行進一步的解釋:

from keras.datasets import mnist 這裏是從keras的datasets中導入mnist數據集
import matplotlib.pyplot as plt  這裏是將matplotlib.pyplot重名爲plt
(X_train, y_train), (X_test, y_test) = mnist.load_data()#
所以這裏返回的是手寫圖片的兩個tuple,第一個tuple存儲的是我們已經人工分類好的圖片,也就是每一張圖片都有自己對應的標籤,然後可以拿來訓練,第二個tuple存儲的是我們還沒分類的圖片,在第一個tuple訓練完後,我們可以把第二個tuple利用神經網絡進行分類,根據實驗結果的真實值與我們的預測值進行對比得到相應的損失值,再利用反向傳播進行參數更新,再進行分類,然後重複前述步驟直至損失值最小
# plot 4 images as gray scale
plt.subplot(331)
這個subplot函數的作用是確定圖像的位置以及圖像的個數,前兩個3的意思是可以放9張圖片,如果變成221的話,就是可以放4張圖片,然後後面的1,是確定圖像的位置,處於第一個,以下的subplot同理
plt.imshow(X_test[0], cmap=plt.get_cmap('gray'))
這裏個把圖片顯示出來
X_train存儲的是圖像的像素點組成的list數據類型,這裏面又由一個二維的list(28 x 28的像素點值)和一個對應的標籤list組成,y_train存儲的是對應圖像的標籤,也就是該圖像代表什麼數字
plt.subplot(332)
plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))
plt.subplot(333)
plt.imshow(X_train[2], cmap=plt.get_cmap('gray'))
plt.subplot(334)
plt.imshow(X_train[3], cmap=plt.get_cmap('gray'))
plt.subplot(335)
plt.imshow(X_train[4], cmap=plt.get_cmap('gray'))
plt.subplot(336)
plt.imshow(X_train[5], cmap=plt.get_cmap('gray'))
plt.subplot(337)
plt.imshow(X_train[6], cmap=plt.get_cmap('gray'))
plt.subplot(338)
plt.imshow(X_train[7], cmap=plt.get_cmap('gray'))
plt.subplot(339)
plt.imshow(X_train[8], cmap=plt.get_cmap('gray'))
在這裏imshow函數的官方文檔:https://matplotlib.org/api/_as_gen/matplotlib.pyplot.imshow.html#matplotlib.pyplot.imshow
我們這裏第一個參數是圖片的像素點值組成的數組(列表),第二個參數是指明圖片的色彩
# show the plot
plt.show()最後這裏官方文檔是這樣說的:Display a figure. When running in ipython with its pylab mode, display all figures and return to the ipython prompt.,所以我們可以知道show函數是把所有圖片都展示出來。

上述代碼展示的結果是:

 

多層感知機的baseline模型

在實現卷積神經網絡這種複雜的模型之前,先實現一個簡單但效果也不錯的模型:多層感知機。這種模型也叫含隱層的神經網絡。模型的效果可以使錯誤率達到1.87%。 

import numpy   #導入數據庫
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.utils import np_utils

seed = 7   #設置隨機種子
numpy.random.seed(seed)

(X_train, y_train), (X_test, y_test) = mnist.load_data() #加載數據

num_pixels = X_train.shape[1] * X_train.shape[2]
X_train = X_train.reshape(X_train.shape[0], num_pixels).astype('float32')
X_test = X_test.reshape(X_test.shape[0], num_pixels).astype('float32')
#數據集是3維的向量(instance length,width,height).對於多層感知機,模型的輸入是二維的向量,因此這
#裏需要將數據集reshape,即將28*28的向量轉成784長度的數組。可以用numpy的reshape函數輕鬆實現這個過
#程。

#給定的像素的灰度值在0-255,爲了使模型的訓練效果更好,通常將數值歸一化映射到0-1。
X_train = X_train / 255
X_test = X_test / 255

#最後,模型的輸出是對每個類別的打分預測,對於分類結果從0-9的每個類別都有一個預測分值,表示將模型
#輸入預測爲該類的概率大小,概率越大可信度越高。由於原始的數據標籤是0-9的整數值,通常將其表示成#0ne-hot向量。如第一個訓練數據的標籤爲5,one-hot表示爲[0,0,0,0,0,1,0,0,0,0]。

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]

#現在需要做得就是搭建神經網絡模型了,創建一個函數,建立含有一個隱層的神經網絡。
# define baseline model
def baseline_model():
    # create model
    model = Sequential()
    model.add(Dense(num_pixels, input_dim=num_pixels, kernel_initializer='normal', activation='relu'))
    model.add(Dense(num_classes, kernel_initializer='normal', activation='softmax'))
    # Compile model
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

#型的隱含層含有784個節點,接受的輸入長度也是784(28*28),最後用softmax函數將預測結果轉換爲標籤
#的概率值。 
#將訓練數據fit到模型,設置了迭代輪數,每輪200個訓練樣本,將測試集作爲驗證集,並查看訓練的效果。

# build the model
model = baseline_model()
# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))

訓練和測試結果如下:

Train on 60000 samples, validate on 10000 samples 
Epoch 1/10 
6s - loss: 0.2789 - acc: 0.9210 - val_loss: 0.1416 - val_acc: 0.9578 
Epoch 2/10 
5s - loss: 0.1117 - acc: 0.9677 - val_loss: 0.0917 - val_acc: 0.9707 
Epoch 3/10 
5s - loss: 0.0717 - acc: 0.9796 - val_loss: 0.0787 - val_acc: 0.9767 
Epoch 4/10 
6s - loss: 0.0502 - acc: 0.9859 - val_loss: 0.0741 - val_acc: 0.9767 
Epoch 5/10 
5s - loss: 0.0372 - acc: 0.9890 - val_loss: 0.0681 - val_acc: 0.9788 
Epoch 6/10 
5s - loss: 0.0269 - acc: 0.9925 - val_loss: 0.0625 - val_acc: 0.9808 
Epoch 7/10 
5s - loss: 0.0208 - acc: 0.9948 - val_loss: 0.0619 - val_acc: 0.9814 
Epoch 8/10 
6s - loss: 0.0140 - acc: 0.9970 - val_loss: 0.0639 - val_acc: 0.9799 
Epoch 9/10 
5s - loss: 0.0108 - acc: 0.9978 - val_loss: 0.0597 - val_acc: 0.9812 
Epoch 10/10 
5s - loss: 0.0080 - acc: 0.9985 - val_loss: 0.0591 - val_acc: 0.9813 
Baseline Error: 1.87%

簡單的卷積神經網絡

前面介紹瞭如何加載訓練數據並實現一個簡單的單隱層神經網絡,並在測試集上取得了不錯的效果。現在要實現一個卷積神經網絡,想要在MNIST問題上取得更好的效果。

卷積神經網絡(CNN)是一種深度神經網絡,與單隱層的神經網絡不同的是它還包含卷積層、池化層、Dropout層等,這使得它在圖像分類的問題上有更優的效果。詳細的CNN教程可以參見斯坦福大學的cs231n課程講義,中文版鏈接

第一步依然是導入需要的函數庫

import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
K.set_image_dim_ordering('th')

設定隨機數種子

seed = 7
numpy.random.seed(seed)
  •  

將數據reshape,CNN的輸入是4維的張量(可看做多維的向量),第一維是樣本規模,第二維是像素通道,第三維和第四維是長度和寬度。並將數值歸一化和類別標籤向量化。

# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# reshape to be [samples][pixels][width][height]
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32')

X_train = X_train / 255
X_test = X_test / 255
# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]
  •  

接下來構造CNN。

  1. 第一層是卷積層。該層有32個feature map,或者叫濾波器,作爲模型的輸入層,接受[pixels][width][height]大小的輸入數據。feature map的大小是5*5,其輸出接一個‘relu’激活函數。
  2. 下一層是pooling層,使用了MaxPooling,大小爲2*2。
  3. 下一層是Dropout層,該層的作用相當於對參數進行正則化來防止模型過擬合。
  4. 接下來是全連接層,有128個神經元,激活函數採用‘relu’。
  5. 最後一層是輸出層,有10個神經元,每個神經元對應一個類別,輸出值表示樣本屬於該類別的概率大小。
def baseline_model():
    # create model
    model = Sequential()
    model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dense(num_classes, activation='softmax'))
    # Compile model
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

接着開始訓練模型

# build the model
model = baseline_model()
# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))

訓練和測試結果如下:

Train on 60000 samples, validate on 10000 samples 
Epoch 1/10 
137s - loss: 0.2329 - acc: 0.9340 - val_loss: 0.0820 - val_acc: 0.9742 
Epoch 2/10 
140s - loss: 0.0736 - acc: 0.9781 - val_loss: 0.0466 - val_acc: 0.9842 
Epoch 3/10 
138s - loss: 0.0531 - acc: 0.9839 - val_loss: 0.0432 - val_acc: 0.9860 
Epoch 4/10 
145s - loss: 0.0404 - acc: 0.9876 - val_loss: 0.0389 - val_acc: 0.9872 
Epoch 5/10 
135s - loss: 0.0335 - acc: 0.9893 - val_loss: 0.0341 - val_acc: 0.9886 
Epoch 6/10 
133s - loss: 0.0275 - acc: 0.9915 - val_loss: 0.0308 - val_acc: 0.9893 
Epoch 7/10 
133s - loss: 0.0233 - acc: 0.9926 - val_loss: 0.0363 - val_acc: 0.9880 
Epoch 8/10 
137s - loss: 0.0204 - acc: 0.9937 - val_loss: 0.0320 - val_acc: 0.9889 
Epoch 9/10 
139s - loss: 0.0167 - acc: 0.9945 - val_loss: 0.0294 - val_acc: 0.9893 
Epoch 10/10 
139s - loss: 0.0143 - acc: 0.9957 - val_loss: 0.0310 - val_acc: 0.9907 
Baseline Error: 0.93%

可以看出相對於單隱層神經網絡,CNN的效果有很大提升,error rate 從1.87%降到了0.93%。

上面實現了一個只含有一層卷積層和pooling層的CNN,爲了實現更好的分類效果,可以添加多層的Convolution2D和MaxPooling2D,CNN會自動提取特徵,學習到更好的分類效果。

 

 

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