1. 程式人生 > >Tensorflow keras入門教程

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.kerasKeras API的Tensorflow實現,是一個用於構建和訓練模型的高階API,其中包括對TensorFlow特定功能的一流支援,例如Eager Executiontf.data PipelineEstimatorstf.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_initializerbias_initializer:分別指定層的核(原文是Kernel,可以理解為weights)和偏置(bias)的初始化器(initializer)。 引數是名稱或可呼叫物件。 預設為“Glorot uniform”初始化器。
  • kernel_regularizerbias_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.AdamOptimizertf.train.RMSPropOptimizertf.train.GradientDescentOptimizer
  • loss:在優化期間最小化的函式。 常見的選擇包括均方誤差(mse),categorical_crossentropybinary_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'])

可以注意到,上面的程式中第一個的lossmetrics傳的是字串,第二種傳的是可呼叫的物件。

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.evaluatetf.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.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、僅儲存權重

參考tf.keras.Model.save_weights

# 把權重儲存為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