Tensorflow keras入門教程
目錄
- 1、Tensorflow與Keras
- 2、安裝內建Keras的Tensorflow
- 3、Tensorflow內建的Keras教程
1、Tensorflow與Keras
Tensorflow和Keras原本是兩個深度學習的框架。Keras有著更高階的API,構建模型要比Tensorflow簡單許多;Keras有許多後端(backend)可以選,Tensorflow就是其中一種後端。
2017年01月17日,Keras的作者、谷歌AI研究員Francois Chollet宣佈了一條激動人心的訊息:Keras將會成為第一個被新增到TensorFlow核心中的高級別框架,這將會讓Keras變成Tensorflow的預設API。也就是說Tensorflow內建Keras了。
2、安裝內建Keras的Tensorflow
最新版Tensorflow已經內建了Keras模組(最新的Tensorflow版本是1.11.0),其對應的Keras的版本為2.1.6-tf,只要安裝了Tensorflow 1.11.0及以上版本,就已經能使用Tensorflow內建的Keras了。
3、Tensorflow內建的Keras教程
此部分文件是官分文件的翻譯,根據自己的理解進行了翻譯,幫助大家入門。原文連結Tensorflow Keras
3.1、匯入tf.keras
tf.keras是Keras API的Tensorflow實現,是一個用於構建和訓練模型的高階API,其中包括對TensorFlow特定功能的一流支援,例如Eager Execution,tf.data Pipeline和Estimators。 tf.keras使TensorFlow更易於使用,而不會犧牲靈活性和效能。
匯入tf.keras的程式碼為:
import tensorflow as tf
from tensorflow.keras import layers
# 列印Tensorflow和內建的Keras版本
print(tf.VERSION)
print(tf.keras.__version__)
tf.keras可以執行任何與Keras相容的程式碼,但請記住:
- 最新TensorFlow版本中的tf.keras版本可能與PyPI的最新keras版本不同。 可列印tf.keras.version來檢查版本。
- 儲存模型的權重時,tf.keras預設為檢查點格式( checkpoint format)。 要使用HDF5儲存權重時,傳入引數save_format =‘h5’。
3.2、建立一個簡單的模型
3.2.1、順序模型(Sequential model)
在Keras中,您可以組裝層(Layer)來構建模型(Model)。 最常見的模型型別是層的堆疊:tf.keras.Sequential模型。
構建一個簡單的,完全連線的網路(即多層感知器):
model = tf.keras.Sequential()
# 新增一個有64個單元全連線層到模型
# 順便說一句,densely-connected layer=fully-connected layer
model.add(layers.Dense(64, activation='relu'))
# 再新增一個
model.add(layers.Dense(64, activation='relu'))
# 新增一個有10個輸出單元的softmax層
model.add(layers.Dense(10, activation='softmax'))
3.2.2、設定keras層(layer)
tf.keras.layers一些常見的建構函式引數:
- activation:設定層的啟用函式。 此引數由內建函式的名稱或可呼叫物件指定。 預設情況下,不使用任何啟用。
- kernel_initializer和bias_initializer:分別指定層的核(原文是Kernel,可以理解為weights)和偏置(bias)的初始化器(initializer)。 引數是名稱或可呼叫物件。 預設為“Glorot uniform”初始化器。
- kernel_regularizer和bias_regularizer:分別指定層的核(Kernel)和偏置(bias)的正則化方案,例如L1或L2正則化。 預設情況下,不使用正則化。
下面使用建構函式引數例項化tf.keras.layers.Dense的一些例子:
# 建立一個sigmoid層:
layers.Dense(64, activation='sigmoid')
# 另外一種方法
layers.Dense(64, activation=tf.sigmoid)
# 定義一個線性層(linear layer),核矩陣(kernel matrix)使用一個因子為0.01的L1正則化器
layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l1(0.01))
# 定義一個線性層,偏置向量( bias vector)使用一個因子為0.01的L2正則化器
layers.Dense(64, bias_regularizer=tf.keras.regularizers.l2(0.01))
# 定義了一個線性層,核使用的初始化器為orthogonal(核會被初始化為一個隨機正交矩陣)
layers.Dense(64, kernel_initializer='orthogonal')
# 定義了一個線性層,偏置向量的初始化去器為constant(偏置向量的所有元素都會被初始化為2.0)
layers.Dense(64, bias_initializer=tf.keras.initializers.constant(2.0))
3.3、訓練和評估
3.3.1、配置訓練
構建模型後,通過呼叫compile函式編譯(原文為configure,我這裡翻譯為編譯):
model = tf.keras.Sequential([
# 新增一個有64個單元的全連線層,啟用函式為relu
layers.Dense(64, activation='relu'),
# 再新增一個
layers.Dense(64, activation='relu'),
# 新增一個有10個輸出單元的softmax層
layers.Dense(10, activation='softmax')])
model.compile(optimizer=tf.train.AdamOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
tf.keras.Model.compile有三個重要引數(建議參考下Keras compile document):
- optimizer:指定優化器。 從tf.train模組傳遞優化器例項,例如tf.train.AdamOptimizer,tf.train.RMSPropOptimizer或tf.train.GradientDescentOptimizer。
- loss:在優化期間最小化的函式。 常見的選擇包括均方誤差(mse),categorical_crossentropy和binary_crossentropy。 損失函式由名稱或通過從tf.keras.losses模組傳遞可呼叫物件來指定。
- metrics:設定訓練中要輸出的指標(原文為metrics,我這裡翻譯為指標)組成的列表,上面的程式碼中就只有準確率(accuracy)。 指標是來自tf.keras.metrics模組的字串名稱或可呼叫物件組成的list。
以下顯示了編譯模型的幾個示例:
# 編譯均方誤差迴歸模型(a model for mean-squared error regression)
model.compile(optimizer=tf.train.AdamOptimizer(0.01),
loss='mse', # 最小均方誤差(mean squared error)
metrics=['mae']) # 平均絕對誤差(mean absolute error)
# 編譯一個分類模型(a model for categorical classification)
# 多元分類問題例子,比如手寫數字識別
model.compile(optimizer=tf.train.RMSPropOptimizer(0.01),
loss=tf.keras.losses.categorical_crossentropy,
metrics=[tf.keras.metrics.categorical_accuracy])
# 和上面的相同
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 二元分類例子
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
可以注意到,上面的程式中第一個的loss和metrics傳的是字串,第二種傳的是可呼叫的物件。
3.3.2、使用NumPy資料作為訓練資料
對於小型資料集,請使用記憶體中的NumPy陣列來訓練和評估模型。 使用fit方法將模型“擬合”到訓練資料:
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)
tf.keras.Model.fit有三個重要引數:
- epoch:訓練多少個epoch。 一個epoch是對整個訓練資料集的一次訓練(這是以較小的批次完成的)。
- batch_size:當傳遞NumPy資料時,模型將資料分成較小的批次(batch),並在訓練期間訓練這些批次。 此整數指定每個批次的大小。 請注意,如果樣本總數不能被批次大小整除,則最後一批可能會更小。
- validation_data:在對模型進行原型設計時,若要監控其在某些驗證資料集上的效能。 傳遞由(輸入,標籤)組成的元組, 模型在每個epoch的末尾顯示損失和指標。
這是使用validation_data的示例:
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))
3.3.3、使用 tf.data作為訓練資料
若要使用大型資料集或多裝置訓練,要使用Dateset API ,將tf.data.Dataset例項傳遞給fit方法:
# 例項化玩具資料集例項:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32)
dataset = dataset.repeat()
# 在資料集上呼叫`fit`時,不要忘記指定`steps_per_epoch`
model.fit(dataset, epochs=10, steps_per_epoch=30)
這裡,fit方法函式steps_per_epoch引數 - 這是模型在訓練集上訓練一遍(也就是一個epoch)的訓練步數。 由於Dataset生成批次資料,因此此程式碼段不需要batch_size。
如果要傳入驗證集:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32).repeat()
val_dataset = tf.data.Dataset.from_tensor_slices((val_data, val_labels))
val_dataset = val_dataset.batch(32).repeat()
model.fit(dataset, epochs=10, steps_per_epoch=30,
validation_data=val_dataset,
validation_steps=3)
3.3.4、評估和預測
tf.keras.Model.evaluate和tf.keras.Model.predict函式可以使用NumPy陣列和tf.data.Dataset作為引數。
如果要評估(evaluate)所提供資料的模型的損失和指標(也就是深度學習中評估測試集的損失loss和前面compile函式中metrics指定的指標),程式碼如下:
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
model.evaluate(data, labels, batch_size=32)
model.evaluate(dataset, steps=30)
NumPy陣列作為引數,輸出模型最後一層的輸出(也就是預測一個樣本):
result = model.predict(data, batch_size=32)
print(result.shape)
3.4、構建高階模型
3.4.1、函式式API
tf.keras.Sequential模型是一個簡單的層的堆疊,不能構建任意模型。 使用Keras函式式API構建複雜的模型,例如:
- 多輸入模型,
- 多輸出模型,
- 具有共享層的模型(同一層被呼叫多次),
- 具有非順序資料流的模型(例如,residual connections)。
使用函式式API構建模型的方法如下:
- 呼叫層例項,並且返回張量(tensor)。
- 輸入張量和輸出張量用於定義tf.keras.Model例項。
- 這個模型的訓練就像Sequential模型一樣。
以下示例使用函式式API構建一個簡單,全連線(fully-connected)的網路:
inputs = tf.keras.Input(shape=(32,)) # Returns a placeholder tensor
# 層的例項可呼叫,引數為tensor,返回一個tensor
x = layers.Dense(64, activation='relu')(inputs)
x = layers.Dense(64, activation='relu')(x)
predictions = layers.Dense(10, activation='softmax')(x)
例項化指定輸入和輸出的模型
model = tf.keras.Model(inputs=inputs, outputs=predictions)
# 編譯這個步驟指定了訓練的配置(the training configuration)
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# 訓練5個epoch
model.fit(data, labels, batch_size=32, epochs=5)
3.4.2、模型子類化(Model subclassing)
通過繼承tf.keras.Model並定義自己的前向傳播來構建完全可自定義的模型。 在__init__
函式中建立圖層並將它們設定為類例項的屬性。 在call函式中定義前向傳播。
當啟用Eager Execution時,模型子類化特別有用(原文說很有用,但我還不知道)。
- 關鍵點: 雖然模型子類化提供了靈活性,但其代價是更高的複雜性和更多的編碼錯誤可能性。 如果可能,請選擇函式式API(也就是3.4.1節中提到的方法)。
以下示例顯示了繼承tf.keras.Model,使用自定義前向傳播:
class MyModel(tf.keras.Model):
def __init__(self, num_classes=10):
super(MyModel, self).__init__(name='my_model')
self.num_classes = num_classes
# 在__init__函式中定義層
self.dense_1 = layers.Dense(32, activation='relu')
self.dense_2 = layers.Dense(num_classes, activation='sigmoid')
def call(self, inputs):
# 在call函式中定義前向傳播
# 使用在__init__中定義的層
x = self.dense_1(inputs)
return self.dense_2(x)
def compute_output_shape(self, input_shape):
# 如果你需要把這個子類化的模型當作一個函式式模型的一部分,那麼你需要過載這個函式。
# 否則,這個函式是可選的
shape = tf.TensorShape(input_shape).as_list()
shape[-1] = self.num_classes
return tf.TensorShape(shape)
例項化上述模型的程式碼為:
model = MyModel(num_classes=10)
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, labels, batch_size=32, epochs=5)
3.4.3、自定義層
要自定義層,需要繼承 tf.keras.layers.Layer並且實現如下幾個函式:
- build:建立圖層的權重。 使用add_weight函式來建立。
- call:定義前向傳播。
- compute_output_shape:計算在給定的輸入的shape時,計算出輸出的shape。
- 可以通過實現get_config方法和from_config方法來序列化層。不過是可選的。
下面是自定義層的示例,它實現了一個使輸入(Input)和核(Kernel)矩陣相乘(matmul):
class MyLayer(layers.Layer):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super(MyLayer, self).__init__(**kwargs)
def build(self, input_shape):
shape = tf.TensorShape((input_shape[1], self.output_dim))
# 為此層建立一個可訓練的權重
self.kernel = self.add_weight(name='kernel',
shape=shape,
initializer='uniform',
trainable=True)
# 確保在函式結束時呼叫下面的語句
super(MyLayer, self).build(input_shape)
def call(self, inputs):
# 這裡定義了這層要實現的操作,也就是前向傳播的操作
return tf.matmul(inputs, self.kernel)
def compute_output_shape(self, input_shape):
# 計算輸出tensor的shape
shape = tf.TensorShape(input_shape).as_list()
shape[-1] = self.output_dim
return tf.TensorShape(shape)
def get_config(self):
base_config = super(MyLayer, self).get_config()
base_config['output_dim'] = self.output_dim
return base_config
@classmethod
def from_config(cls, config):
return cls(**config)
使用自定義層:
model = tf.keras.Sequential([
MyLayer(10),
layers.Activation('softmax')])
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, labels, batch_size=32, epochs=5)
3.5、回撥
回撥是傳遞給模型的物件,用於在訓練模型期間自定義和擴充套件其行為。 可以編寫自己的自定義回撥,或使用以下內建的tf.keras.callbacks:
- tf.keras.callbacks.ModelCheckpoint:定期儲存模型的檢查點(checkpoint)。
- tf.keras.callbacks.LearningRateScheduler:動態改變學習率。
- tf.keras.callbacks.EarlyStopping:在校驗集的效能停止提升時,中斷訓練。
- tf.keras.callbacks.TensorBoard:使用TensorBoard監控模型的行為。
若要使用tf.keras.callbacks.Callback,請將其傳遞給模型的fit方法:
callbacks = [
# 如果`val_loss`在超過兩個epoch都沒有提升,那麼中斷訓練
tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),
# 把TensorBoard的日誌寫入資料夾`./logs`
tf.keras.callbacks.TensorBoard(log_dir='./logs')
]
model.fit(data, labels, batch_size=32, epochs=5, callbacks=callbacks,
validation_data=(val_data, val_labels))
3.6、儲存與載入
3.6.1、僅儲存權重
# 把權重儲存為TensorFlow Checkpoint檔案
model.save_weights('./weights/my_model')
# 載入權重。要求模型和儲存權重的模型具有相同的架構
model.load_weights('./weights/my_model')
如果要把權重儲存為Keras的HDF5格式,可使用如下程式碼
# 把權重儲存為HDF5這種格式的檔案
model.save_weights('my_model.h5', save_format='h5')
# 載入權重
model.load_weights('my_model.h5')
3.6.2、僅儲存配置
模型的配置(原文為model’s configuration,可以理解為模型的結構)是可以儲存的。 這可以在沒有任何權重的情況下序列化模型體系結構。 即使沒有定義原始模型的程式碼,儲存的配置也可以重新建立和初始化相同的模型。 Keras支援JSON和YAML序列化格式:
把模型序列化為json字串
json_string = model.to_json()
print(json_string)
從json字串恢復模型:
fresh_model = tf.keras.models.model_from_json(json_string)
把模型序列化為YAML格式:
yaml_string = model.to_yaml()
print(yaml_string)
從YAML字串恢復模型:
fresh_model = tf.keras.models.model_from_yaml(yaml_string)
- 注意:子類化模型不可序列化,因為它們的體系結構由call函式中的Python程式碼定義。
3.6.3、儲存整個模型
如果儲存模型結構與權重(甚至還包括優化器的配置),下次可以恢復模型結構和權重接著訓練且不需要訪問原始程式碼。
# 建立一個簡單的模型
model = tf.keras.Sequential([
layers.Dense(10, activation='softmax', input_shape=(32,)),
layers.Dense(10, activation='softmax')
])
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, labels, batch_size=32, epochs=5)
# 將整個模型儲存到HDF5檔案
model.save('my_model.h5')
# 重新建立完全相同的模型,包括權重和優化器。
model = tf.keras.models.load_model('my_model.h5')
3.7、Eager execution
Eager execution是一個必要的程式設計環境,可以立即評估操作。 這對於Keras不是必需的,但是由tf.keras支援,對於檢查程式和除錯很有用。
所有tf.keras API都與Eager execution相容。 雖然可以使用順序模型和函式式API,但是Eager execution尤其有利於模型子類化和構建自定義層 。
有關使用具有自定義訓練和tf.GradientTape的Keras模型的示例,請參閱Eager execution 指南。
3.8、分散式訓練
3.8.1 、Estimators
Estimators API用於分散式環境的訓練模型的API。 可以匯出模型進行大型資料集的分散式訓練,並得到可以商用的模型。
使用tf.keras.estimator.model_to_estimator將模型轉換為tf.estimator.Estimator物件,就可以使用tf.estimator API訓練tf.keras.Model。 請參閱Creating Estimators from Keras models。
model = tf.keras.Sequen