4. 使用Keras-神經網絡來進行MNIST手寫數字分類

程序

  • 導入庫
import numpy as np
import keras

from keras.datasets import mnist # mnist數據集
from keras.utils import np_utils # kerass提供的工具包
from keras.models import Sequential
from keras.layers import Dense,Activation
from keras.optimizers import SGD
  • 加載數據集
    程序會去指定目錄下(默認是: .\keras\examples) 查看是否有mnist.npz數據集。如果沒有,則去 https://s3.amazonaws.com/img-datasets/mnist.npz 進行下載的。不過目前好像要用梯子。所以可以參考以下博客,他們提供了百度網盤鏈接供下載參考1參考2
# 導入數據集
# dataset_path = 'C:\Users\Administrator\.keras\datasets\mnist.npz'
# (x_train, y_train), (x_test, y_test) = mnist.load_data(path=dataset) # 不指定路徑,則默認聯網下載到userhome\.keras\datasets\mnist.npz
(x_train, y_train), (x_test, y_test) = mnist.load_data()

print('x_train:',x_train.shape) # (60000, 28, 28)
print('y_train:',y_train.shape) # (60000,)
print('x_test:',x_test.shape) # (10000, 28, 28)
print('y_test:',y_test.shape) # (10000,)
  • 數據預處理
# 數據集預處理(不要多次運行)

# 將x_train(6000, 28, 28)->(6000, 784)->歸一化
x_train = x_train.reshape(x_train.shape[0], -1)/255.0
x_test = x_test.reshape(x_test.shape[0], -1)/255.0
print('x_train:',x_train.shape)  # (60000, 784)

# 將label轉成 one-hot 格式(代碼不能多次執行,否則維數爲增加)
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)
print('y_shape:',y_train.shape)  # (60000, 10)
  • 建立模型+訓練模型
    在compile時加入metrics = ['accuracy'] 來計算訓練過程中的準確率。
    使用model.fit來訓練模型。
# 建立模型
model = Sequential([
        Dense(units=10, input_dim=784, activation='softmax')  # softmax將輸出轉成概率
    ])

# 定義優化器
sgd = SGD(lr=0.2)

# 定義優化器,loss function,訓練過程中計算準確率
model.compile(
    optimizer = sgd,
    loss = 'mse',
    metrics = ['accuracy'],
)

# 訓練模型(與以前的for語句寫的循環訓練模型代碼等價)
model.fit(x_train, y_train, batch_size=32, epochs=10) # 一次訓練32張圖片,一個週期要訓練60000/32次,共訓練10個週期

# 評估模型(用測試集測試)
loss, accuracy = model.evaluate(x_test, y_test)

print("loss: ", loss)
print("accuracy: ", accuracy)

在這裏插入圖片描述
由於模型的約束,識別率只能達到91%左右。

優化一:損失函數:使用交叉熵替代均方差

loss = 'mse', 替換成 loss='categorical_crossentropy',

model = Sequential([
        Dense(units=10, input_dim=784,bias_initializer='one', activation='softmax')
    ])

sgd = SGD(lr=0.2)
model.compile(optimizer=sgd, 
              loss='categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, batch_size=32, epochs=10)

loss,accuracy = model.evaluate(x_test,y_test)
print('\ntest loss',loss)
print('accuracy',accuracy)

在這裏插入圖片描述
優點:
迭代速度快
精確度提高

優化二:添加隱藏層(提高模型的複雜性,但容易過擬合),Dropout(預防過擬合)

只添加隱藏層:

# 創建模型(添加隱藏層,增加網絡模型的複雜度)
model = Sequential([
        Dense(units=200,input_dim=784,bias_initializer='one',activation='tanh'),
        Dense(units=100,bias_initializer='one',activation='tanh'), #加入中間隱藏層
        Dense(units=10,bias_initializer='one',activation='softmax') # 最後輸出層
    ])

# 定義優化器
sgd = SGD(lr=0.2)

# 定義優化器,loss function,訓練過程中計算準確率
model.compile(
    optimizer = sgd,
    loss = 'categorical_crossentropy',
    metrics=['accuracy'],
)

# 訓練模型
model.fit(x_train,y_train,batch_size=32,epochs=10)

# 評估模型(測試集)
loss,accuracy = model.evaluate(x_test,y_test)
print('\ntest loss',loss)
print('test accuracy',accuracy)

# 評估模型(訓練集)
loss,accuracy = model.evaluate(x_train,y_train)
print('train loss',loss)
print('train accuracy',accuracy)

在這裏插入圖片描述
可以看到模型在訓練集上表現極好,測試集上略差。表示模型存在過擬合現象(所以需要使用dropout)

添加隱藏層+Dropout層(需要導入庫:from keras.layers import Dense,Dropout)

# 創建模型(添加隱藏層,增加網絡模型的複雜度)
model = Sequential([
        Dense(units=200,input_dim=784,bias_initializer='one',activation='tanh'),
        Dropout(0.4),
        Dense(units=100,bias_initializer='one',activation='tanh'),
        Dropout(0.4),
        Dense(units=10,bias_initializer='one',activation='softmax')
    ])

# 定義優化器
sgd = SGD(lr=0.2)

# 定義優化器,loss function,訓練過程中計算準確率
model.compile(
    optimizer = sgd,
    loss = 'categorical_crossentropy',
    metrics=['accuracy'],
)

# 訓練模型
model.fit(x_train,y_train,batch_size=32,epochs=10)

# 評估模型(測試集)
loss,accuracy = model.evaluate(x_test,y_test)
print('\ntest loss',loss)
print('test accuracy',accuracy)

# 評估模型(訓練集)
loss,accuracy = model.evaluate(x_train,y_train)
print('train loss',loss)
print('train accuracy',accuracy)

在這裏插入圖片描述
精確度下降是因爲網絡節點不再全連接的了,而是會忽略一半的特徵檢測器(讓一半的隱層節點值爲0),具體可以參考:神經網絡之dropout層
還有一點就是,可以看到模型在訓練集上的預測結果和測試集上的結果相差不大了,即一定程度上避免了過擬合現象

優化三:添加正則化項

導入庫:from keras.regularizers import l2 # 引入 L2 正則項
正則化器允許在優化過程中對層的參數或層的激活情況進行懲罰。 網絡優化的損失函數也包括這些懲罰項。

# 創建模型
model = Sequential([
        # 添加了正則化項的模型
        Dense(units=200,input_dim=784,bias_initializer='one',activation='tanh',kernel_regularizer=l2(0.0003)),
        Dense(units=100,bias_initializer='one',activation='tanh',kernel_regularizer=l2(0.0003)),
        Dense(units=10,bias_initializer='one',activation='softmax',kernel_regularizer=l2(0.0003))
    ])

# 定義優化器
sgd = SGD(lr=0.2)

# 定義優化器,loss function,訓練過程中計算準確率
model.compile(
    optimizer = sgd,
    loss = 'categorical_crossentropy',
    metrics=['accuracy'],
)

# 訓練模型
model.fit(x_train,y_train,batch_size=32,epochs=10)

# 評估模型
loss,accuracy = model.evaluate(x_test,y_test)
print('\ntest loss',loss)
print('test accuracy',accuracy)

loss,accuracy = model.evaluate(x_train,y_train)
print('train loss',loss)
print('train accuracy',accuracy)

在這裏插入圖片描述
可以看到過擬合現象也不是特別嚴重,正則化項的應用要看具體情況而定

優化四:優化器的應用

引入庫:from keras.optimizers import SGD,Adam
大多數情況下:adam比sgd效果要比較好,且優化速度比較快
下面程序在使用交叉熵後的代碼上進行修改(使用adam替換sgd)的:

# 創建模型,輸入784個神經元,輸出10個神經元
model = Sequential([
        Dense(units=10,input_dim=784,bias_initializer='one',activation='softmax')
    ])

# 定義優化器
sgd = SGD(lr=0.2)
adam = Adam(lr=0.001)  # 定義adam優化器

# 定義優化器,loss function,訓練過程中計算準確率
model.compile(
    optimizer = adam, # 使用Adam優化器
    loss = 'categorical_crossentropy',
    metrics=['accuracy'],
)

# 訓練模型
model.fit(x_train,y_train,batch_size=32,epochs=10)

# 評估模型
loss,accuracy = model.evaluate(x_test,y_test)

print('\ntest loss',loss)
print('accuracy',accuracy)

在這裏插入圖片描述

其他優化。。。。。。

參考:

視頻: 覃秉豐老師的“Keras入門”:http://www.ai-xlab.com/course/32
博客參考:https://www.cnblogs.com/XUEYEYU/tag/keras%E5%AD%A6%E4%B9%A0/

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