keras深度學習實戰(一)-----mnist數字識別

多層感知機(MLP)

導語:

通過簡單的BP神經單元我們可以表示任何線性組合,目前的四則運算都屬於線性組合的範疇。那麼當現實中的一些特徵間的關係是非線性的時候該用什麼表示呢?這就是感知機的功用,一般是用來解決分類問題,即對於輸入x能能分段導向。往往相當於進行了一個激活函數的運算,激活函數就是非線性的,從而滿足了表示非線性關係的需求。

常見的激活函數:

  • sigmoid: f(x)=11+exf(x)=\frac{1}{1+e^{-x}}
    漸近線:y=0y=0y=1y=1
    sigmoid函數的特點:f(x)=f(x)(1f(x))f'(x)=f(x)*(1-f(x)),這一點在反向傳播時大大簡化了計算。
  • relu:f(x)={0,x<0x,x>=0f(x)=\begin{cases} 0,x<0\\ x,x>=0\\ \end{cases}
  • tanh:f(x)=sinhxcoshx=exexex+exf(x)=\frac{sinhx}{coshx}=\frac{e^x-e^{-x}}{e^x+e^{-x}}
    漸近線:y=1y=-1y=1y=1

常見優化器:

  • SGD隨機梯度下降法
  • RMSPROP
  • ADAM:計算梯度的一階矩估計和二階矩估計而爲不同的參數設計獨立的自適應性學習率
    備註:Adam 算法的提出者描述其爲兩種隨機梯度下降擴展式的優點集合,即:
    適應性梯度算法(AdaGrad)爲每一個參數保留一個學習率以提升在稀疏梯度(即自然語言和計算機視覺問題)上的性能。
    均方根傳播(RMSProp)基於權重梯度最近量級的均值爲每一個參數適應性地保留學習率。這意味着算法在非穩態和在線問題上有很有優秀的性能。

一些技巧:

數字編碼:One-hot編碼 [0,0,0,0,1,0,0,0,0][0,0,0,0,1,0,0,0,0]表示的是4
dropout增加普適性
正則化:l1,l2l1,l2正則化和彈性網絡

分步解析

1、數據的預處理,讀取mnist裏的數據,mnist裏的圖片大小爲28*28,我們分別讀取訓練集和測試集後需要歸一化處理,使得所有的影響因子在初始時的權重一致。輸出到二值類矩陣相當於完成one-hot編碼

(X_train,Y_train),(X_test,Y_test)=mnist.load_data()
#X_train是60000個28*28
RESHAPED=784 #28*28

X_train=X_train.reshape(60000,RESHAPED)
X_test=X_test.reshape(10000,RESHAPED)
X_train=X_train.astype('float32')
X_test=X_test.astype('float32')

#歸一化
X_train/=255
X_test/=255
print(X_train.shape[0],'train samples')
print(X_test.shape[0],'test samples')

#將類向量轉化爲二值類別矩陣
Y_train=np_utils.to_categorical(Y_train,NB_CLASSES)
Y_test=np_utils.to_categorical(Y_test,NB_CLASSES)

2、然後就是用keras搭建網絡了,這裏都是Dense全連接,有一層輸入、一層輸出和兩層隱藏層,注意,在隱藏層用到了Dropout函數,這樣刪去部分值反而會讓模型在測試集上能得到較好的效果,但使用它的前提是你的訓練集已經訓練“好”了,有時測試集上表現不好不一定是因爲在訓練集上過擬合了,也有可能時訓練集就沒有訓練好,所以要多觀察輸出。
model.evaluate()得到的score[0]是loss損失函數的結果,一般有以下幾種形式:MSE(均方誤差),RMSE(均方根誤差)等。score[1]是精確度,這些都是在這個函數裏面定義的。
建立網絡並設定編譯原則如下:

model=Sequential()
model.add(Dense(N_HIDDEN,input_shape=(RESHAPED,)))
model.add(Activation('relu'))
model.add(Dropout(DROPOUT))
model.add(Dense(N_HIDDEN))
model.add((Activation('relu')))
model.add(Dropout(DROPOUT))
model.add(Dense(NB_CLASSES))
model.add(Activation('softmax'))
model.summary()

model.compile(loss='categorical_crossentropy',optimizer=OPTIMIZER,metrics=['accuracy'])

3、擬合和評估

history=model.fit(X_train,Y_train,batch_size=BATCH_SIZE,epochs=NB_EPOCH,verbose=VERBOSE,validation_split=VALIDATION_SPLIT)

score=model.evaluate(X_test,Y_test,verbose=VERBOSE)
print("Test score:",score[0])
print("Test accuracy:",score[1])

下面給出在keras中完成mnist數字識別的整體代碼:

import numpy as np
from keras.models import Sequential
from keras.datasets import mnist
from keras.layers.core import Dense,Activation,Dropout
from keras.optimizers import SGD
from keras.utils import np_utils

np.random.seed(1671) #重複性設置

NB_EPOCH=200 #訓練次數
BATCH_SIZE=128 #訓練集大小
VERBOSE=1#verbose:日誌顯示
#verbose = 0 爲不在標準輸出流輸出日誌信息
#verbose = 1 爲輸出進度條記錄
#verbose = 2 爲每個epoch輸出一行記錄

NB_CLASSES=10
OPTIMIZER=SGD() #SGD優化器    //RMSprop Adam

N_HIDDEN=128 #隱藏層單元個數
VALIDATION_SPLIT=0.2 #訓練集中用作測試的比例
DROPOUT=0.3 #隱藏層丟棄一些值,整體表現會更好

(X_train,Y_train),(X_test,Y_test)=mnist.load_data()
#X_train是60000個28*28
RESHAPED=784 #28*28

X_train=X_train.reshape(60000,RESHAPED)
X_test=X_test.reshape(10000,RESHAPED)
X_train=X_train.astype('float32')
X_test=X_test.astype('float32')

#歸一化
X_train/=255
X_test/=255
print(X_train.shape[0],'train samples')
print(X_test.shape[0],'test samples')

#將類向量轉化爲二值類別矩陣
Y_train=np_utils.to_categorical(Y_train,NB_CLASSES)
Y_test=np_utils.to_categorical(Y_test,NB_CLASSES)

model=Sequential()
model.add(Dense(N_HIDDEN,input_shape=(RESHAPED,)))
model.add(Activation('relu'))
model.add(Dropout(DROPOUT))
model.add(Dense(N_HIDDEN))
model.add((Activation('relu')))
model.add(Dropout(DROPOUT))
model.add(Dense(NB_CLASSES))
model.add(Activation('softmax'))
model.summary()

#引入正則化
#from keras import regularizers
#model.add(Dense(64,input_dim=64,kernel_regularizer=regularizers.l2(0.02)))

model.compile(loss='categorical_crossentropy',optimizer=OPTIMIZER,metrics=['accuracy'])
#metrics評估標準
#檢查點的使用:快照用於系統恢復到某一個狀態
#from keras.callbacks import ModelCheckpoint
#import os
#MODEL_DIR="/tmp"
#checkpoint=ModelCheckpoint(filepath=os.path.join(MODEL_DIR,"model-{epoch:02d}.h5"))
#最後model.fit(+callbacks=[checkpoint])
history=model.fit(X_train,Y_train,batch_size=BATCH_SIZE,epochs=NB_EPOCH,verbose=VERBOSE,validation_split=VALIDATION_SPLIT)

score=model.evaluate(X_test,Y_test,verbose=VERBOSE)
print("Test score:",score[0])
print("Test accuracy:",score[1])

#使用tensorBoard保存不同層的激活的柱狀圖
from keras.callbacks import TensorBoard
TensorBoard(log_dir='./logs',histogram_freq=0,write_graph=True,write_images=False)
#tensorboard --logdir=/(path to log)

下面給出的是完整代碼下運行的結果:
PS:激活函數、優化器對學習率調整、網絡深度、Dropout函數等都會對最終的精確度產生影響。可以通過上述影響因子來繼續調試模型使其能達到更好的性能。
在這裏插入圖片描述
之後,會探索DCNN(深度卷積神經網絡)的實現。

參考:
《Keras深度學習實戰》

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