TensorFlow2.0(11):tf.keras建模三部曲
注:本系列所有部落格將持續更新併發布在github上,您可以通過github下載本系列所有文章筆記檔案。
Keras是一個基於Python編寫的高層神經網路API,憑藉使用者友好性、模組化以及易擴充套件等有點大受好評,考慮到Keras的優良特性以及它的受歡迎程度,TensorFlow2.0中將Keras的程式碼吸收了進來,化身為tf.keras模組供使用者使用。
使用tf.keras提供的高層API,可以輕鬆得完成建模三部曲——模型構建、訓練、評估等工作。下面我們分別來說說如何使用tf.keras完成這三部曲。
1 模型構建¶
我們知道,神經網路模型就是層的堆疊,tf.keras提供的Sequential類物件就是層容器,可以輕鬆實現對層的堆疊,建立網路模型。用Sequential建立一個全連線網路模型:
In [3]:import tensorflow as tf from tensorflow import keras # 為方便使用,keras一般單獨匯入 from tensorflow.keras import layersIn [2]:
model = tf.keras.Sequential() # 往模型中新增一個有64個神經元組成的層,啟用函式為relu: model.add(layers.Dense(64, activation='relu')) # 再新增一個: model.add(layers.Dense(64, activation='relu')) # 新增一個有10個神經元的softmax層作為輸出層: model.add(layers.Dense(10, activation='softmax'))
也可以在使用Sequential例項化模型時,通過傳入由層組成的列表來新增層。我們換一種方式實現上面的模型構建過程,兩種方式是完全等效的:
In [6]:model = tf.keras.Sequential([ layers.Dense(64, activation='relu'), layers.Dense(64, activation='relu'), layers.Dense(10, activation='softmax')] )
你看,用tf.keras建立一個模型,就是這麼簡單,只需要往Sequential中傳入一個個tf.keras.layers定義的層就好了。進一步的,我們研究一下tf.keras.layers怎麼個性化地建立層。
定義神經網路層通過tf.keras.layers模組中的Dense類實現,Dense類構造引數如下:
- units:指定神經元個數,必須是一個正整數。
- activation:啟用函式,可以是可以是一個可呼叫物件或標識一個物件的字串
- use_bias:布林型,是否使用是否使用偏置項
- kernel_initializer和bias_initializer:權值、偏置初始化方法,可以是一個可呼叫物件或標識一個物件的字串
- kernel_regularizer和bias_regularizer:對權值、偏置進行正則化的方法,可以是一個可呼叫物件或標識一個物件的字串
- activity_regularizer:對層的輸出進行正則化的方法,可以是一個可呼叫物件或標識一個物件的字串
- kernel_constraint和bias_constraint:對權值矩陣、偏置矩陣的約束方法,可以是一個可呼叫物件或標識一個物件的字串
# 有64個神經元,啟用函式為sigmoid的層 layers.Dense(64, activation='sigmoid') # 或者: layers.Dense(64, activation=tf.keras.activations.sigmoid) # 對權值矩陣進行正則化: layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l1(0.01)) # 對偏置向量進行正則化: layers.Dense(64, bias_regularizer=tf.keras.regularizers.l2(0.01)) # 指定權值隨機正交初始化: layers.Dense(64, kernel_initializer='orthogonal') # 指定偏置為常數: layers.Dense(64, bias_initializer=tf.keras.initializers.Constant(2.0))Out[6]:
<tensorflow.python.keras.layers.core.Dense at 0x7f486247abd0>
2 訓練模型¶
2.1 配置:compile()¶
建立好模型之後,接下來當然是要進行訓練模型了。不過,在訓練前還需要做一些配置工作,例如指定優化器、損失函式、評估指標等,這些配置引數的過程一般通過tf.keras.Model.compile方法進行,先來熟悉一下tf.keras.Model.compile方法的三個常用引數:
- optimizer:tf.keras.optimizers模組中的優化器例項化物件,例如 tf.keras.optimizers.Adam或 tf.keras.optimizers.SGD的例項化物件,當然也可以使用字串來指代優化器,例如'adam'和'sgd'。
- loss:損失函式,例如交叉熵、均方差等,通常是tf.keras.losses模組中定義的可呼叫物件,也可以用用於指代損失函式的字串。
- metrics:元素為評估方法的list,通常是定義在tf.keras.metrics模組中定義的可呼叫物件,也可以用於指代評估方法的字串。
在知道怎麼配置模型訓練引數後,就可以根據實際應用情況合理選擇優化器、損失函式、評估方法等:
In [7]:# 迴歸模型 model.compile(optimizer=tf.keras.optimizers.Adam(0.01), # 指定優化器,學習率為0.01 loss='mse', # 指定均方差作為損失函式 metrics=['mae']) # 新增絕對值誤差作為評估方法 # 分類模型 model.compile(optimizer=tf.keras.optimizers.RMSprop(0.01), loss=tf.keras.losses.CategoricalCrossentropy(), # 分類模型多用交叉熵作為損失函式 metrics=[tf.keras.metrics.CategoricalAccuracy()])
通過compile()配置好模型後,就可以開始訓練了。tf.keras中提供了fit()方法對模型進行訓練,先來看看fit()方法的主要引數:
- x和y:訓練資料和目標資料
- epochs:訓練週期數,每一個週期都是對訓練資料集的一次完整迭代
- batch_size:簇的大小,一般在資料集是numpy陣列型別時使用
- validation_data:驗證資料集,模型訓練時,如果你想通過一個額外的驗證資料集來監測模型的效能變換,就可以通過這個引數傳入驗證資料集
- verbose:日誌顯示方式,verbose=0為不在標準輸出流輸出日誌資訊,verbose=1為輸出進度條記錄,verbose=2為每個epoch輸出一行記錄
- callbacks:回撥方法組成的列表,一般是定義在tf.keras.callbacks中的方法
- validation_split:從訓練資料集抽取部分資料作為驗證資料集的比例,是一個0到1之間的浮點數。這一引數在輸入資料為dataset物件、生成器、keras.utils.Sequence物件是無效。
- shuffle:是否在每一個週期開始前打亂資料
下面分別說說如何使用fit()方法結合numpy資料和tf.data.Dataset資料進行模型訓練。
In [8]:import numpy as np data = np.random.random((1000, 32)) labels = np.random.random((1000, 10)) model.fit(data, labels, epochs=10, batch_size=32)
Train on 1000 samples Epoch 1/10 1000/1000 [==============================] - 1s 554us/sample - loss: 206.2688 - categorical_accuracy: 0.1050 Epoch 2/10 1000/1000 [==============================] - 0s 34us/sample - loss: 911.8347 - categorical_accuracy: 0.0990 Epoch 3/10 1000/1000 [==============================] - 0s 30us/sample - loss: 1879.7505 - categorical_accuracy: 0.0980 Epoch 4/10 1000/1000 [==============================] - 0s 28us/sample - loss: 3141.3959 - categorical_accuracy: 0.0940 Epoch 5/10 1000/1000 [==============================] - 0s 36us/sample - loss: 4673.7791 - categorical_accuracy: 0.1010 Epoch 6/10 1000/1000 [==============================] - 0s 36us/sample - loss: 6526.8757 - categorical_accuracy: 0.0960 Epoch 7/10 1000/1000 [==============================] - 0s 31us/sample - loss: 8571.8533 - categorical_accuracy: 0.1020 Epoch 8/10 1000/1000 [==============================] - 0s 33us/sample - loss: 11070.1039 - categorical_accuracy: 0.0970 Epoch 9/10 1000/1000 [==============================] - 0s 36us/sample - loss: 13533.4661 - categorical_accuracy: 0.1050 Epoch 10/10 1000/1000 [==============================] - 0s 25us/sample - loss: 17259.2291 - categorical_accuracy: 0.1000Out[8]:
<tensorflow.python.keras.callbacks.History at 0x7f74a4755650>
如何使用驗證資料集的話,可以這樣:
In [10]:import numpy as np data = np.random.random((1000, 32)) labels = np.random.random((1000, 10)) val_data = np.random.random((100, 32)) val_labels = np.random.random((100, 10)) model.fit(data, labels, epochs=10, batch_size=32, validation_data=(val_data, val_labels)) # 驗證資料集以元組的形式傳入
Train on 1000 samples, validate on 100 samples Epoch 1/10 1000/1000 [==============================] - 0s 34us/sample - loss: 67219.8359 - categorical_accuracy: 0.0960 - val_loss: 55306.6777 - val_categorical_accuracy: 0.1000 Epoch 2/10 1000/1000 [==============================] - 0s 32us/sample - loss: 73732.5724 - categorical_accuracy: 0.0920 - val_loss: 89920.2088 - val_categorical_accuracy: 0.1100 Epoch 3/10 1000/1000 [==============================] - 0s 50us/sample - loss: 79956.1480 - categorical_accuracy: 0.1020 - val_loss: 101092.6750 - val_categorical_accuracy: 0.1000 Epoch 4/10 1000/1000 [==============================] - 0s 36us/sample - loss: 84322.9844 - categorical_accuracy: 0.0970 - val_loss: 117610.5700 - val_categorical_accuracy: 0.1000 Epoch 5/10 1000/1000 [==============================] - 0s 38us/sample - loss: 91992.0751 - categorical_accuracy: 0.1130 - val_loss: 94200.0838 - val_categorical_accuracy: 0.1000 Epoch 6/10 1000/1000 [==============================] - 0s 38us/sample - loss: 97189.2044 - categorical_accuracy: 0.0910 - val_loss: 89020.5294 - val_categorical_accuracy: 0.1100 Epoch 7/10 1000/1000 [==============================] - 0s 33us/sample - loss: 107109.9905 - categorical_accuracy: 0.0930 - val_loss: 102350.4259 - val_categorical_accuracy: 0.1200 Epoch 8/10 1000/1000 [==============================] - 0s 41us/sample - loss: 114450.2496 - categorical_accuracy: 0.1010 - val_loss: 102719.3653 - val_categorical_accuracy: 0.1100 Epoch 9/10 1000/1000 [==============================] - 0s 41us/sample - loss: 124694.8415 - categorical_accuracy: 0.0950 - val_loss: 142269.8362 - val_categorical_accuracy: 0.1100 Epoch 10/10 1000/1000 [==============================] - 0s 44us/sample - loss: 131952.7791 - categorical_accuracy: 0.0800 - val_loss: 158925.8294 - val_categorical_accuracy: 0.0900Out[10]:
<tensorflow.python.keras.callbacks.History at 0x7f749c548810>
3 評估與預測¶
是騾子是馬,拉出來溜溜就知道了,訓練好的模型效能如何,評估測試一下就知道了。可以使用模型自帶的evaluate()方法和predict()方法對模型進行評估和預測。
In [12]:# 如果是numpy資料,可以這麼使用 data = np.random.random((1000, 32)) labels = np.random.random((1000, 10)) model.evaluate(data, labels, batch_size=32)
1000/1 [=================================================] - 0s 17us/sample - loss: 161163.7180 - categorical_accuracy: 0.0930Out[12]:
[153591.27975, 0.093]In [13]:
# 如果數Dataset物件,可以這麼使用 dataset = tf.data.Dataset.from_tensor_slices((data, labels)) dataset = dataset.batch(32) model.evaluate(dataset)
32/32 [==============================] - 0s 579us/step - loss: 153946.2378 - categorical_accuracy: 0.0930Out[13]:
[153946.23779296875, 0.093]
使用predict()方法進行預測:
In [14]:# numpy資料 result = model.predict(data, batch_size=32) print(result.shape)
(1000, 10)In [16]:
# dataset資料 result = model.predict(dataset) print(result.shape)
(1000, 10)<