深度學習框架Keras學習系列(三):Keras神經網絡框架

Keras官方網站

Introduction

Keras是一個高級的神經網絡API,用Python實現,並可以基於TensorFlow,CNTK與Theano等計算框架運行。

Keras的核心是神經網絡,它的意義主要在於使得神經網絡的實現更加方便快捷,因此它本質上是在一些知名的計算框架上進行了一層簡化的封裝,只對Keras使用者暴露出一些簡單易用的接口,使用者可以很快了解並上手實現複雜的神經網絡架構,而不用關心底層的實現細節。

Keras作爲一個深度學習的庫,有以下顯著特徵:

  • 簡單、快速地構造原型(兼具用戶友好性、模塊性以及可擴展性)
  • 支持卷積網路和循環網絡,包括二者的結合體
  • 可以無縫在CPU和GPU上運行

Installation

首先需要選擇Keras的底層框架:TensorFlow,CNTK或Theano。(鑑於Bengio已經宣佈將停止繼續維護Theano,故推薦使用Google的TensorFlow),並進行安裝,然後再安裝Keras的庫。另外,Keras默認以TensorFlow作爲底層計算框架,如果使用CNTK或者Theano的話,則需要在Keras的配置文件中進行修改

具體參考官方說明

Fast Overview

我們知道,神經網絡中最基本的構成單元是神經元(neuron),而若干神經元可以組成一個層(layer),若干層(輸入層+隱藏層+輸出層)就構成了一個神經網絡的原型。而Keras中最核心的數據結構就是model,我們便是基於model來進行神經網絡層(layers)的組裝。而model最簡單的一種類型便是Sequential,它對層進行線性堆疊。

通過以下代碼便能實例化一個Sequential:

from keras.models import Sequential

model = Sequential()

而要往Sequential上面疊加層,只需使用.add()方法:

from keras.layers import Dense

model.add(Dense(units=64, activation='relu', input_dim=100))
model.add(Dense(units=10, activation='softmax'))

如上是先後加了兩層。第一層是Dense層(全連接層),共64個神經元(units=64),激活函數爲ReLU(activation=’relu’),輸入的是維度爲1*100的列向量(input_dim=100)。第二層是也是一個Dense層,10個神經元,激活函數爲softmax,輸入的是前一層的輸出向量,即維度爲1*64的列向量。

第一層默認爲神經網絡的隱藏層第一層,故需要指定輸入向量的維度,即輸入的特徵向量的維度。

Once your model looks good, configure its learning process with .compile():

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

有需要的話,我們也可以自定義優化器(optimizer)。Keras最核心的設計理念就是在最大化保證易用性的同時,提供給使用者充分的自由去對模型進行全面地控制。

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.SGD(lr=0.01, momentum=0.9, nesterov=True))

這裏,我們的損失函數選擇的是交叉熵(loss=keras.losses.categorical_crossentropy),優化器選擇的是學習率爲0.01,動量爲0.9的隨機梯度下降(optimizer=keras.optimizers.SGD(lr=0.01, momentum=0.9),並啓用Nesterov動量(不同的優化方法可參考這裏)。

現在我們就可以以batch的形式來迭代訓練我們的模型了:

# x_train and y_train are Numpy arrays --just like in the Scikit-Learn API.

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

我們也可以手動地把batch分批餵給模型訓練:

model.train_on_batch(x_batch, y_batch)

一行代碼便能獲得訓練好的模型的性能評估:

loss_and_metrics = model.evaluate(x_test, y_test, batch_size=128)

讓模型對新的數據進行預測:

classes = model.predict(x_test, batch_size=128)

無論是想建立一個問題回答系統,一個圖像分類模型,一個神經圖靈機,還是任何機器模型,都可以儘可能快。這些深度學習背後的思想都很簡單,所以爲什麼它們的實現過程要那麼痛苦呢?這就是存在的意義。

Sequential model

序列模型(Sequential model)是對神經層的堆疊,而要構建一個序列模型也和容易,通過將List形式組織的layer實例給序列類的構造器即可:

from keras.models import Sequential
from keras.layers import Dense, Activation

model = Sequential([
    Dense(32, input_shape=(784,)),
    Activation('relu'),
    Dense(10),
    Activation('softmax'),
])

也可以用.add()方法來僅僅加上一層:

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

Specifying the Input Shape

序貫模型需要知道所預期給它的輸入的形狀(shape),而也只有模型的第一層需要手動指明input_shape(後面的層會自己進行形狀推斷)。

對於Dense這樣的2D層,也可以用參數input_dim來直接聲明input shape,而像一些3D層就同時支持input_dim和input_length參數。

而如果我們需要聲明一個固定大小的batch的輸入(這在狀態循環網絡會用到),我們可以傳遞參數batch_size給某個層。如果我們同時傳遞了batch_size=32和input_shape=(6,8)給某個層,那麼該層就會預期之後每一次傳入的batch輸入都具備batch形狀(32,6,8)。

如下,兩種方式是等價的:

model = Sequential()
model.add(Dense(32, input_shape=(784,)))
model = Sequential()
model.add(Dense(32, input_dim=784))

Compilation

在訓練一個模型前,我們需要配置它的學習過程,這通過方法compile來完成。compile方法接受三個參數:

  • 一個優化器(optimizer):用字符串形式指定一個keras已有的優化器名稱即可(比如rmsprop或者adagrad),或者傳遞一個Optimizer類的實例也可以。(參見optimizers
  • 一個損失函數(loss function):這是模型將會盡力去最小化的目標。它也可以是字符串形式指定的keras中已有的損失函數類型(比如交叉熵(categorical_crossentropy)或者最小均方誤差(mse)),也可以直接是目標方法名稱。(參見losses
  • 一個指標列表(a list of metrics):對任意分類問題,其指標都應該是metrics=[‘accuracy’]。一個指標可以是字符串形式指定的已存在的一種指標,也可以是自定義的指標計算函數。

下面是一些示例:

# For a multi-class classification problem 多分類問題
model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# For a binary classification problem 二分類問題
model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy'])

# For a mean squared error regression problem 以mse爲損失函數的迴歸
model.compile(optimizer='rmsprop',
              loss='mse')

# For custom metrics 自定義指標
import keras.backend as K

def mean_pred(y_true, y_pred):
    return K.mean(y_pred)

model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy', mean_pred])

Training

keras中的模型要求訓練數據以及相應的標籤以Numpy中的arrays類型的方式來組織。

一般用fit()函數來訓練一個模型:


# For a single-input model with 2 classes (binary classification):

model = Sequential()
model.add(Dense(32, activation='relu', input_dim=100))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy'])

# Generate dummy data
import numpy as np
data = np.random.random((1000, 100))
labels = np.random.randint(2, size=(1000, 1))

# Train the model, iterating on the data in batches of 32 samples
model.fit(data, labels, epochs=10, batch_size=32)
# For a single-input model with 10 classes (categorical classification):

model = Sequential()
model.add(Dense(32, activation='relu', input_dim=100))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# Generate dummy data
import numpy as np
data = np.random.random((1000, 100))
labels = np.random.randint(10, size=(1000, 1))

# Convert labels to categorical one-hot encoding
one_hot_labels = keras.utils.to_categorical(labels, num_classes=10)

# Train the model, iterating on the data in batches of 32 samples
model.fit(data, one_hot_labels, epochs=10, batch_size=32)

Examples

keras提供了許多參考的示例,我們可以在開始動手搭建自己的網絡前先看一下這些範例。

Example 1: minist_mlp (A simple deep multi-layer perceptron on the MNIST dataset)

# 注意,這裏的代碼是針對Keras2.0版本的代碼,而官網提供的是Keras1.0版本的代碼,所以一些模塊已經做了調整,包括後面的代碼也有一些調整

'''Trains a simple deep NN on the MNIST dataset.
Gets to 98.40% test accuracy after 20 epochs
(there is *a lot* of margin for parameter tuning).
2 seconds per epoch on a K520 GPU.
'''

from __future__ import print_function

import keras
# keras有一個datasets模塊,自帶了許多經典數據集,包括mnist
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop


batch_size = 128  # batch的大小爲128個樣例
num_classes = 10  # 一共0-9是個數字,對應10個類別
epochs = 20  # 訓練的epochs爲20

# the data, shuffled and split between train and test sets
# 注意load_data()方法會首先看當前文件夾下有木有數據源,如果沒有,則去指定地址下載
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# mnist的數據都是28*28=784維(像素)的灰度圖像
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-255)統一除以255以歸一化,方便計算
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 = np_utils.to_categorical(y_train, num_classes)
y_test = np_utils.to_categorical(y_test, num_classes)

# 三層全連接層,前兩層使用Dropout,最後一層是輸出層
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()

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

history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    nb_epoch=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])

這裏進行模型訓練和評估時的verbose參數說一下:

verbose的取值只能是0、1或2,表示模型訓練或評估時的狀況輸出模式:0=不輸出, 1=進度條, 2=每個epoch輸出一行。

Example 2: Simple Convolutional Neural Network (convnet) on the MNIST dataset

'''Trains a simple convnet on the MNIST dataset.
Gets to 99.25% test accuracy after 12 epochs
(there is still a lot of margin for parameter tuning).
16 seconds per epoch on a GRID K520 GPU.
'''

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

batch_size = 128
num_classes = 10
epochs = 12

# input image dimensions
img_rows, img_cols = 28, 28

# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
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)


# 一層卷積,32個3*3的過濾器
# 一層最大池化層
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

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])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章