您現在的位置是:首頁 > 垂釣
程式碼詳解:用TensorFlow的Keras API建立多層神經網路
- 由 讀芯術 發表于 垂釣
- 2022-12-08
mmflow解壓碼怎麼用
全文共
6538
字,預計學習時長
20
分鐘或更長
圖片來源:unsplash。com/@herfrenchnes
本文將介紹如何利用TensorFlow的高階API-Keras建立並訓練多層感知器。
Keras自2015年初不斷髮展,如今已成為基於Theano和TensorFlow的最受歡迎且應用最廣的深度學習庫之一。Keras最顯著的一個特徵是其具有非常直觀且便於使用的API,使用者只需寫幾行程式碼就能執行神經網路。
Keras 1。1。0。及以上的版本均可植入TensorFlow,作為其中的contrib 模板(包含由參與者開發給TensorFlow的資料包,為實驗性程式碼)的一部分。
本教程將從以下幾方面介紹該TensorFlow的高階 API:
· 前饋神經網路的基礎知識
· 載入並準備時下流行的MNIST資料集的方法
· 建立影象分類器的操作
· 訓練神經網路和評估其準確性的方法
本教程改編自Next Tech《Python機器學習》叢書系列的第四部分。從零開始教會你Python的機器學習和深度學習演算法。教程也涉及到瀏覽器內沙盒環境,其中包含所有必要軟體、需要預安裝的資料庫,以及使用公共資料集的專案。
多層感知器
多層前饋神經網路是一種獨特的具有多個單一神經元的完全連線網路,也被稱為多層感知器( MultilayerPerceptrons, MLP)。下圖展示了由三個層級組成的MLP的概念:
上圖所示的MLP有一個輸入層、一個隱藏層以及一個輸出層。隱藏層的單元均與輸入層連線,輸出層的單元也全部與隱藏層連線。具有多個隱藏層的網路被稱為深層人工神經網路。
給MLP新增任意數量的隱藏層,來建立更深層的網路結構。實際上,新增的層級和單元的數量可被視為對既定問題任務進行最佳化的額外超引數。
正如上圖所示,將第i層中的第i個啟用單位標誌為i^(l)。為了使數學和程式碼執行更加直觀,給輸入層使用in上標,隱藏層用h上標,輸出層用o上標。
例如,i^(in)表示輸入層中的第i個單元,i^(h)代表隱藏層中的第i個單元,i^(out)則表示輸出層中的第i個單元。此處,_0^(in) 和_0^(out)啟用單元是偏置項,設為等同於1。啟用輸入層的單元只需輸入單元和偏置項。
l層的每個單元均透過權重係數與l + 1 層的所有單元連線。比方說,l層的第k個單元與l + 1 層的第j個單元的連線寫為w_{k, j}^(l)。再看回上一個圖,將連線輸入層和隱藏層的權重矩陣標誌為 W^(h),連線隱藏層和輸出層的權重矩陣標誌為 W^(out)。
將連線輸入層和隱藏層的權重矩陣彙總為:
此處,d表示隱藏層單元的數量,m表示輸入層中包括偏置項的單元數量。由於徹底理解該表示法對於掌握本教程後面的概念非常重要,我們在下圖簡化的3–4–3多層感知器的描述性說明中總結一下剛剛學到的內容:
MNIST資料集
混合美國國家標準技術研究所(Mixed National Institute ofStandards and Technology,MNIST)資料庫是時下非常流行的針對機器學習演算法的基準資料集。為了研究神經網路訓練透過tensorflow。keras (tf。keras)高階API運作的情況,需要執行多層感知器來區分手寫數字和MNIST資料集中的數字。
要依照本教程的程式碼片段,請使用該Next Tech 沙盒,裡面設定有MNIST資料集合所有必需的資料包。或者也可以在本地環境下下載資料集。
MNIST資料集有四個部分,所示如下:
· 訓練組影象:train-images-idx3-ubyte。gz-60000個樣本
· 訓練組標籤:train-labels-idx1-ubyte。gz-60000個標籤
· 測試組影象:t10k-images-idx3-ubyte。gz-10000個樣本
· 測試組標籤:t10k-labels-idx1-ubyte。gz-10000個標籤
訓練組包含250名人士(50%為高中學生,50%為Census Bureau員工)的手寫數字。測試組包含不同人寫的數字。
請注意TensorFlow也提供相同的資料集,如下所示:
import tensorflow as tf
from tensorflow。examples。tutorials。mnist import input_data
然而,本教程使用MNIST資料集作為外部資料集來分別學習資料預處理的所有步驟。依照這個方式便可學會如何使用自己的資料集。
第一步是透過在終端執行以下命令來解壓縮 MNIST 資料集的四個部分:
cd mnist/
gzip *ubyte。gz -d
import os
import struct
def load_mnist(path, kind=‘train’):
“”“Load MNIST data from`path`”“”
labels_path = os。path。join(
path, f‘{kind}-labels-idx1-ubyte’
)
images_path = os。path。join(
path, f‘{kind}-images-idx3-ubyte’
)
with open(labels_path, ‘rb’) as lbpath:
magic, n = struct。unpack(‘>II’,lbpath。read(8))
labels = np。fromfile(lbpath,dtype=np。uint8)
with open(images_path, ‘rb’) as imgpath:
magic, num, rows, cols =struct。unpack(“>IIII”, imgpath。read(16))
images = np。fromfile(imgpath,dtype=np。uint8)。reshape(len(labels), 784)
images = ((images / 255。) - 。5) * 2
return images,labels
load_mnist函式返回兩個陣列。第一個陣列是 n x m維度的NumPy 陣列(影象)。其中,n 表示樣本數,mis表示要點值(此處為畫素)。MNIST 資料集中的影象為28 x 28 畫素,每個畫素由灰度強度值表示。在此將 28 x 28 畫素影象展開為單維行向量,表示影象陣列中的行(每行或每圖的數值為784)。load_mnist 函式返回的第二個陣列(標籤)包含相應的目標變數,即手寫數字的類標籤(整數 0-9)。
然後,按照如下方式載入和準備資料集:
# loading the data
X_train, y_train = load_mnist(‘。/mnist/’, kind=‘train’)
print(f‘Rows: {X_train。shape[0]}, Columns: {X_train。shape[1]}’)
X_test, y_test = load_mnist(‘。/mnist/’, kind=‘t10k’)
print(f‘Rows: {X_test。shape[0]}, Columns: {X_test。shape[1]}’)
# mean centering and normalization:
mean_vals = np。mean(X_train, axis=0)
std_val = np。std(X_train)
X_train_centered = (X_train - mean_vals)/std_val
X_test_centered = (X_test - mean_vals)/std_val
del X_train, X_test
print(X_train_centered。shape, y_train。shape)
print(X_test_centered。shape, y_test。shape)
[Out:]
Rows: 60000, Columns: 784
Rows: 10000, Columns: 784
(60000, 784) (60000,)
(10000, 784) (10000,)
為了瞭解MNIST中這些影象的情況,透過Matplotlib的imshow函式來看看數字0-9的示例:
import matplotlib。pyplot as plt
fig, ax = plt。subplots(nrows=2, ncols=5,
sharex=True, sharey=True)
ax = ax。flatten()
for i in range(10):
img = X_train_centered[y_train == i][0]。reshape(28, 28)
ax[i]。imshow(img, cmap=‘Greys’)
ax[0]。set_yticks([])
ax[0]。set_xticks([])
plt。tight_layout()
plt。show()
現在可以看到2 x 5 的子圖片,展示了每個不同數字的代表影象。
現在開始建立自己的模型!
使用TensorFlow的Keras API建立一個MLP
首先,為NumPy和TensorFlow設定隨機種子數,獲得如下相同結果:
import tensorflow。contrib。keras as keras
np。random。seed(123)
tf。set_random_seed(123)
繼續準備訓練資料,將類標籤(整數0-9)轉化為獨熱形式。幸運的是,Keras為實現該操作提供了便利的工具:
y_train_onehot = keras。utils。to_categorical(y_train)
print(‘First 3 labels: ’, y_train[:3])
print(‘\nFirst 3 labels (one-hot):\n’, y_train_onehot[:3])
First 3labels: [5 0 4]
First 3 labels(one-hot):
[[0。 0。 0。 0。 0。 1。 0。 0。 0。 0。]
[1。 0。 0。 0。 0。 0。 0。 0。 0。 0。]
[0。 0。 0。 0。 1。 0。 0。 0。 0。 0。]]
現在開始執行神經網路!簡單來說,網路包含三個層級。前兩個層(輸入層和隱藏層)各有50個具有tanh啟用函式的單元。最後一個層(輸出層)有針對10個類標籤的10個層級,能使用softmax來傳遞每類標籤的操作可能性。Keras 讓這些任務變得異常簡單:
# initialize model
model = keras。models。Sequential()
# add input layer
model。add(keras。layers。Dense(
units=50,
input_dim=X_train_centered。shape[1],
kernel_initializer=‘glorot_uniform’,
bias_initializer=‘zeros’,
activation=‘tanh’)
)
# add hidden layer
model。add(
keras。layers。Dense(
units=50,
input_dim=50,
kernel_initializer=‘glorot_uniform’,
bias_initializer=‘zeros’,
activation=‘tanh’)
)
# add output layer
model。add(
keras。layers。Dense(
units=y_train_onehot。shape[1],
input_dim=50,
kernel_initializer=‘glorot_uniform’,
bias_initializer=‘zeros’,
activation=‘softmax’)
)
# define SGD optimizer
sgd_optimizer = keras。optimizers。SGD(
lr=0。001, decay=1e-7, momentum=0。9
)
# compile model
model。compile(
optimizer=sgd_optimizer,
loss=‘categorical_crossentropy’
)
首先,使用Sequential 類初始化新模型來執行前饋神經網路。然後,根據自身喜好新增層級。但是,因為新增的第一個層是輸入層,需要確保input_dim 屬性與訓練組中的要點數(列數)相配(神經網路執行時有784個要點或畫素)。
同時也要確保兩個連續層中的輸出單元數(units)和輸入單元數(input_dim)相符。頭兩個層級各有50個單元以及1個偏置項。輸出層中的單元數應等同於特殊類標籤的數量,即獨熱編碼類標籤陣列中的列數。
請注意本教程使用glorot_uniform作為權重矩陣的初始化演算法。Glorotinitialization對啟用深度神經網路而言更加有效。偏差被初始化為零,這是常見設定,實際上也是Keras中的預設設定。
在編寫模型之前,還需定義最佳化器。在此選擇隨機梯度下降最佳化法。此外,還可設定權重衰減常數和衝量學習的值,從而調整每個階段的學習率。最後,將成本(損失)函式設定為分類交叉熵。
二元交叉熵是邏輯迴歸中成本函式的專業術語,分類交叉熵則是透過softmax進行多類預測的概括。
編寫完成後,可呼叫擬合方法來訓練模型。此處採用小批次隨機梯度方法,批次大小為每批64個訓練模板。訓練MLP次數超過50次,並透過設定 verbose=1來跟蹤訓練過程中成本函式的最佳化。
validation_split引數尤其便於操作。因為它會在每次訓練後保留10%的訓練資料(此處為6,000個樣本)用以驗證,這樣就便於監控模型在訓練期間是否過度擬合:
# train model
history = model。fit(
X_train_centered, y_train_onehot,
batch_size=64, epochs=50,
verbose=1, validation_split=0。1
)
訓練期間列印成本函式的值非常有用,可以快速發現訓練期間成本是否下降,並提前停止演算法。否則就需要調整超引數值。
為了預測類標籤,可以使用 predict_classes方法直接將類標籤作為整數返回:
y_train_pred = model。predict_classes(X_train_centered, verbose=0)
print(‘First 3 predictions: ’, y_train_pred[:3])
First 3 predictions: [5 0 4]
最後,在訓練和測試組中印出模型準確性:
# calculate training accuracy
y_train_pred = model。predict_classes(X_train_centered, verbose=0)
correct_preds = np。sum(y_train == y_train_pred, axis=0)
train_acc = correct_preds / y_train。shape[0]
print(f‘Training accuracy: {(train_acc * 100):。2f}’)
# calculate testing accuracy
y_test_pred = model。predict_classes(X_test_centered, verbose=0)
correct_preds = np。sum(y_test == y_test_pred, axis=0)
test_acc = correct_preds / y_test。shape[0]
print(f‘Test accuracy: {(test_acc * 100):。2f}’)
Training accuracy: 98。81
Test accuracy: 96。27
本教程簡述如何使用TensorFlow的keras API建立和訓練多層神經網路來進行影象分類。請注意這只是一個非常簡單的神經網路,沒有最佳化的調整引數。
實踐過程中,需要弄清楚如何透過調整學習率、衝量、權值衰減,以及隱藏單元的數量來最佳化模型。還需要學習如何處理梯度消失的問題,其中隨著更多層被新增到網路中,誤差梯度會變得越來越小。
留言 點贊 關注
我們一起分享AI學習與發展的乾貨
歡迎關注全平臺AI垂類自媒體 “讀芯術”