基於Keras搭建MLP

Keras是一套基於Tensorflow、Theano及CNTK後端的高層神經網絡API,能夠很是友好地支持快速實驗,本文從零開始介紹瞭如何使用Keras搭建MLP並給出兩個示例。linux

Keras

基於Ubuntu安裝Keras

具體安裝過程在官方中英文文檔中有詳細說明
中文 https://keras-cn.readthedocs.io/en/latest/for_beginners/keras_linux/
英文 https://keras.io/#installationshell

Keras基礎知識

Sequential models

能夠認爲Keras中的所謂模型(models)就是某個具體的網絡結構,如MLP、CNN、LSTM等,在Keras中它們被分爲兩種:序貫模型(Sequential)和函數式模型(Model)。ubuntu

Sequential模型就是一個直接由若干網絡層線性堆疊起來的網絡,使用以下代碼建立一個Sequential對象:後端

from keras.models import Sequential

model = Sequential()

Sequential的構造函數能夠接收一個由layer組成的list,用以初始化該model網絡

model = Sequential([
    Dense(32, input_shape=(784,)),#一個Dense層
    Activation('relu'),#爲上一個Dense層附加激活函數
    Dense(10),#再添加一個Dense層
    Activation('softmax'),#爲上一個Dense層附加激活函數
])

也可使用.add()方法對該model初始化:dom

model.add(Dense(32, input_shape=(784,)))
model.add(Activation('relu'))

Dense layer

Dense layer即全鏈接層,構造方法以下:函數

keras.layers.core.Dense(
  units,
  activation=None,
  use_bias=True,
  kernel_initializer='glorot_uniform',
  bias_initializer='zeros',
  kernel_regularizer=None,
  bias_regularizer=None,
  activity_regularizer=None,
  kernel_constraint=None,
  bias_constraint=None)

units:大於0的整數,表示該層輸出維度。
activation:激活函數。
use_bias:是否使用偏置。
kernel_initializer:權值矩陣初始化方法。
bias_initializer:偏置的初始化方法。
regularizer與constraint:正則項與約束項。學習

咱們可使用前文提到的.add()方法爲model添加全鏈接層,只有輸入層須要指定輸入數據維度,以後的層不需再指定前一層的維度。測試

compile & fit

model的結構設置好以後使用compile方法編譯:優化

model.compile(
  self,
  optimizer,
  loss,
  metrics=None,
  sample_weight_mode=None)

optimizer:預約義的優化器名稱或自定義的優化器對象。
loss:預約義的損失函數名稱或自定義的目標函數。

編譯後使用fit方法訓練模型:

model.fit(
  self,
  x,
  y,
  batch_size=32,
  epochs=10,
  verbose=1,
  callbacks=None,
  validation_split=0.0,
  validation_data=None,
  shuffle=True,
  class_weight=None,
  sample_weight=None,
  initial_epoch=0)

x:做爲輸入數據的numpy array。
y:做爲標籤的numpy array。
batch_size:梯度降低時每一個batch包含的樣本數。
epochs:訓練總輪數。
verbose:日誌顯示,0爲不在標準輸出流輸出日誌信息,1爲輸出進度條記錄,2爲每一個epoch輸出一行記錄。

訓練一個線性迴歸模型

一個線性迴歸模型能夠被認爲是一個MLP的特例,即一個輸入與輸出只有1維且沒有激活函數(或激活函數爲線性函數a(x)=x)的MLP,咱們首先生成一些離散的點,使這些點大體成線性關係,再構建一個Sequential model,最後在這些點上訓練該model以獲得它們的線性關係。

import numpy as np

from keras.models import Sequential
from keras.layers import Dense
from keras import optimizers

data_size = 50 # 生成的數據集大小
batch_size = 40
learning_rate = 0.01
epochs = 300

# 在正負1之間均勻產生data_size個點
x_train = np.linspace(-1, 1, data_size)
# 使得數據點呈y=3x+5的關係,添加小範圍正態隨機數以得到數據的隨機波動效果
y_train = 3 * x_train + 5 + np.random.rand(*x_train.shape)*0.3

# 建立一個Sequential模型
model = Sequential()
# 添加一個全鏈接層,輸入數據維度爲1,含一個輸出單元,RandomUniform表示權值在正負0.05間均勻隨機初始化
model.add(Dense(units=1, input_dim=1, kernel_initializer='RandomUniform'))

# 打印查看當前的權重
print(model.layers[0].get_weights())

# 建立一個SGD對象以調整學習速率
sgd = optimizers.SGD(lr=learning_rate)
# 編譯model,優化器使用剛建立的SGD對象,損失函數使用最小均方差mse
model.compile(optimizer=sgd, loss='mse')
# 使用以前生成的數據訓練
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1)

# 再次打印權重,能夠看到其值在3與5附近
print(model.layers[0].get_weights())

結果:

...
Epoch 298/300
50/50 [==============================] - 0s 36us/step - loss: 0.0325
Epoch 299/300
50/50 [==============================] - 0s 45us/step - loss: 0.0264
Epoch 300/300
50/50 [==============================] - 0s 56us/step - loss: 0.0260
[array([[2.9937706]], dtype=float32), array([5.0084023], dtype=float32)]

有趣的是,當咱們調整數據點的範圍,將

x_train = np.linspace(-1, 1, data_size)

改成

x_train = np.linspace(-25, 25, data_size)

保持其餘部分不變,再次運行程序訓練,loss會振盪到無窮到致使訓練失敗,這是學習率過大形成的,將learning_rate由0.01改成0.003,再次訓練,便可獲得正確結果。

咱們還能夠加入一個隱層,調整學習率與epochs後也能夠獲得很好的訓練結果:

import numpy as np

from keras.models import Sequential
from keras.layers import Dense
from keras import optimizers

data_size = 50
batch_size = 40
learning_rate = 0.0003
epochs = 500

x_train = np.linspace(-25, 25, data_size)
y_train = 3 * x_train + 5 + np.random.rand(*x_train.shape)*0.3

model = Sequential()
#這裏的units爲4,即隱層單元個數爲4
model.add(Dense(units=4, input_dim=1, kernel_initializer='RandomUniform'))
#再添加輸出層,維度爲1
model.add(Dense(units=1, kernel_initializer='RandomUniform'))

print(model.layers[0].get_weights())
print(model.layers[1].get_weights())


sgd = optimizers.SGD(lr=learning_rate)
model.compile(optimizer=sgd, loss='mse')
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1)

print(model.layers[0].get_weights())
print(model.layers[1].get_weights())

結果:

Epoch 498/500
50/50 [==============================] - 0s 119us/step - loss: 0.0169
Epoch 499/500
50/50 [==============================] - 0s 156us/step - loss: 0.0168
Epoch 500/500
50/50 [==============================] - 0s 85us/step - loss: 0.0182
[array([[ 0.8122992 , -0.08030439, -0.05526135, -1.0514123 ]],
      dtype=float32), array([ 1.110988  , -0.11047827, -0.07585457, -1.4386528 ], dtype=float32)]
[array([[ 1.3721825 ],
       [-0.13642032],
       [-0.09367472],
       [-1.7768502 ]], dtype=float32), array([0.968823], dtype=float32)]

結果中兩個list中的第一個array是權值,第二個array是偏置。

訓練一個用於識別MNIST的MLP

在Keras安裝路徑下的examples文件夾中能夠找到mnist_mlp.py:

from __future__ import print_function

import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop

batch_size = 128
num_classes = 10
epochs = 20

#讀取mnist的訓練與測試數據
(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
#整型轉爲浮點型
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
#歸一到(0,1)區間內
x_train /= 255
x_test /= 255
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

#使用了兩個隱層,每一個隱層512個單元,激活函數選用relu,添加了Dropout防止過擬合,最後經過softmax輸出
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))

model.summary()

#損失函數選用多分類對數損失函數,優化器選用RMSprop
model.compile(loss='categorical_crossentropy',
              optimizer=RMSprop(),
              metrics=['accuracy'])

history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

結果:

...
59392/60000 [============================>.] - ETA: 0s - loss: 0.0183 - acc: 0.99
59776/60000 [============================>.] - ETA: 0s - loss: 0.0182 - acc: 0.99
60000/60000 [==============================] - 15s 253us/step - loss: 0.0182 - acc: 0.9953 - val_loss: 0.1072 - val_acc: 0.9842
Test loss: 0.10721807914278024
Test accuracy: 0.9842
相關文章
相關標籤/搜索