數據挖掘入門系列教程(十一)之keras入門使用以及構建DNN網絡識別MNIST

簡介

在上一篇博客:數據挖掘入門系列教程(十點五)之DNN介紹及公式推導中,詳細的介紹了DNN,並對其進行了公式推導。原本這篇博客是準備直接介紹CNN的,可是想了一下,以爲仍是使用keras構建一個DNN網絡,而後進行必定的分類操做,這樣可以更加的直觀一點。html

在這篇博客中將介紹:python

  • keras的基本使用
  • 使用keras構建DNN對MNIST數據集進行預測

使用前準備

此次咱們將使用keras庫去構建神經網絡,而後默認使用tensorflow做爲後端,我是用的python庫版本以下:git

  • keras:version 2.3.1
  • tensorflow:version 2.1.0

這篇博客並不會講keras,tensorflow的安裝,不過值得注意的是,若是本身電腦有英偉達的顯卡就儘可能去裝gpu版本的tensorflow,而後安裝對應版本的cuda。通常來講使用GPU可以大幅度提升程序計算的速度(個人mx250哭暈在廁所)。至於AMD的顯卡,emm,我就不知道支不支持了。github

關於keras的具體使用,能夠去看一看官方文檔,可是目前官方文檔的目錄欄有一點問題,所以建議你們去看這個keras 中文文檔,這個是根據官方文檔生成的。算法

準備數據集

這裏咱們使用keras提供MNIST數據集,訓練集爲 60,000 張$ 28\times 28 = 784$像素灰度圖像,測試集爲 10,000 同規格圖像,總共 10 類數字標籤。後端

from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

而後咱們能夠看一看數據集的shape:網絡

print(x_train.shape, 'x_train samples')
print(x_test.shape, 'x_test samples')
print(y_train.shape, 'y_trian samples')
print(y_test.shape, 'Y_test samples')

此時,咱們就已經加載好數據集了。咱們能夠稍微的看一看數據集長什麼樣子:函數

import matplotlib.pyplot as plt
%matplotlib inline
plt.figure(figsize=(12,10))
x, y = 8, 6
for i in range(x*y):  
    plt.subplot(y, x, i+1)
    plt.imshow(x_train[i],interpolation='nearest')
plt.show()

由於數據集並不能可以直接進行訓練或者訓練效果很差,在這裏咱們將數據進行一下變換。好比說歸一化,onehot編碼(這個必須作)。測試

數據集的變換

首先,咱們的DNN的設計以下:優化

輸入層是由784個神經元構成的,可是在前面咱們已經知道x_train.shape(6000,28,28)。輸出層由10個神經元構成,而y_train.shape(6000,),毋庸置疑,咱們須要對x,y數據進行編碼。

對於x數據來講,咱們須要將它變成(6000,784)的類型,對於y咱們進行onehot編碼就好了(one hot編碼在前面已經介紹過了,這裏就很少作介紹了),同時在這裏咱們還將數據進行歸一化(能夠提升模型的準確率)。

import keras
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
# 將數據變成float類型,這樣可以被255除
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

# one hot 編碼,將類向量(整數)轉換爲二進制類矩陣。
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

構建DNN網絡

首先咱們導入Sequential

from keras.models import Sequential

Sequential是一個順序模型:多個網絡層的線性堆疊,每一層接受上一層的輸入,向下一層進行輸出,示意圖以下:

這裏,再說一個概念,全鏈接層,很簡單理解,就是某一層用數學公式來表達就是\(output = W\times input\),好比說下圖中的layer2和layer3就是全鏈接的,也就是說layer2是全鏈接層。在keras中,可使用Dense去建立一個全鏈接層。

關於Dense的參數,截取官方文檔以下:

參數

  • units: 正整數,輸出空間維度。
  • activation: 激活函數 (詳見 activations)。 若不指定,則不使用激活函數 (即,「線性」激活: a(x) = x)。
  • use_bias: 布爾值,該層是否使用偏置向量。
  • kernel_initializer: kernel 權值矩陣的初始化器 (詳見 initializers)。
  • bias_initializer: 偏置向量的初始化器 (see initializers).
  • kernel_regularizer: 運用到 kernel 權值矩陣的正則化函數 (詳見 regularizer)。
  • bias_regularizer: 運用到偏置向的的正則化函數 (詳見 regularizer)。
  • activity_regularizer: 運用到層的輸出的正則化函數 (它的 "activation")。 (詳見 regularizer)。
  • kernel_constraint: 運用到 kernel 權值矩陣的約束函數 (詳見 constraints)。
  • bias_constraint: 運用到偏置向量的約束函數 (詳見 constraints)。

然咱們來看一看具體的使用(裏面涉及的幾個激活函數隨便去網上搜一下就知道了):

from keras.layers import Dense, Dropout
# 建立一個網絡模型
model = Sequential()
# 建立輸入層 512表明的是輸出維度爲512,也就是第二層神經元有512個,輸入維度爲(784,),激活函數爲Relu
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))

# 建立layer2,而後向下層輸出的空間維度爲512
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))

# 輸出層,由於只有10個數字,因此輸出空間維度爲10,激活函數爲softmax。
model.add(Dense(10, activation='softmax'))

# 網絡模型的介紹
print(model.summary())

Dropout 應用於輸入。Dropout 包括在訓練中每次更新時, 將輸入單元的按比率隨機設置爲 0, 這有助於防止過擬合

簡單點來講,他就是這樣的,隨機(按比率)將某一個輸入值變成0,這樣他就沒辦法向下一層傳遞信息。

打印的網絡結構模型以下所示,仍是有蠻多參數的:

接着咱們就來說一下如何配置這個模型,在keras中,配置一個模型至少須要兩個參數lossoptimizer。其中loss就是損失函數optimizer就是優化器,也就是前篇博客提到的優化方法,好比說梯度降低法,牛頓法等等,metrics表明在訓練和測試期間的模型評估標準。

from keras.optimizers import RMSprop

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

這裏咱們選擇RMSprop,具體內容能夠參考Day 69: rmsprop,而後loss咱們選擇categorical_crossentropy,由於它是多分類任務。其表達式爲:

\(C E(x)=-\sum_{i=1}^{C} y_{i} \log f_{i}(x)\)
其中, \(x\)表示輸入樣本, \(C\)爲待分類的類別總數。 \(y_{i}\) 爲第\(i\)個類別對應的真實標籤, \(f_{i}(x)\) 爲對應的模 型輸出值。

開始訓練

最後咱們可使用這個模型來訓練數據了,代碼:

# history保存了每一次訓練的loss,accuracy
history = model.fit(x_train, y_train,
                    batch_size=128,
                    epochs=32,
                    verbose=1,
                    validation_data=(x_test, y_test))

x_train, y_train這個就不必解釋了,很簡單,就是訓練的數據集。

  • batch_size表明每一次梯度更新的樣本數,默認32。如何理解這個這一個參數呢?意思就是說每次一訓練的時候訓練batch_size個樣本,針對每個樣本咱們均可以求出它對應的loss,而後咱們求和而後取平均\(C E(x)_{\text {final}}=\frac{\sum_{b=1}^{batch\_size} C E\left(x^{(b)}\right)}{N}\),而後再使用BP算法。
  • epochs: 訓練模型迭代輪次。
  • verbose: 0, 1 或 2。日誌顯示模式。 0 = 安靜模式, 1 = 進度條, 2 = 每輪一行。
  • validation_data:用來評估損失,以及在每輪結束時的任何模型度量指標。 模型將不會在這個數據上進行訓練。

部分打印數據以下:

在個人筆記本i5十代u,mx250的狀況下,訓練了大概1分多鐘,畢竟數據集仍是比較小的,而後參數也不是不少。

進行評估

# 這裏的verbose和fit中的含義同樣
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

最後結果以下圖:

訓練過程的accuracy和loss

這裏咱們將每一次輪訓練以及測試對應的loss和accuracy畫出來:

# 繪製訓練過程當中訓練集和測試集合的準確率值
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

# 繪製訓練過程當中訓練集和測試集合的損失值
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

總結

ok,這篇博客就結束了。總的來講仍是蠻順利的,由於不須要去推數學公式,基本上沒有什麼難度(固然,若是想更好的提升準確率仍是蠻難的,能夠去kaggle裏面看一下大佬的解決方案)。這篇博客簡單的介紹了keras使用,我力求將每個用到的函數都講清楚,可是實際上很難,由於可能我認爲講清楚了,可是實際上你可能仍是沒有明白。這個時候能夠去多看一下官方文檔,或者別人的博客,固然,私信我也是🆗的。

項目地址:Github

參考

相關文章
相關標籤/搜索