1. 程式人生 > 實用技巧 >【tf.keras】官方教程一 Keras overview

【tf.keras】官方教程一 Keras overview


Sequential Model:(the simplest type of model)

Getting started with the Keras Sequential model

Specifying the input shape

Compilation

Training

使用tf.keras建立一個簡易的模型

使用Numpy陣列進行訓練:

使用tf.data 資料集進行訓練

驗證和預測

使用tf.keras構建複雜模型

The functional API

模型子類化(Model subclassing)

定製層(Custom layers)

Callbacks

模型的儲存與匯入

只儲存權重

只儲存模型的配置檔案:

儲存完整的模型在一個檔案中


  之前在研讀MobileNet V3的原始碼時,其程式碼在基於TensorFlow框架中使用了tf.keras。在基於tf.keras下,模型的構建更加容易,也略顯高階。再次附上MobileNet V3程式碼:https://github.com/Bisonai/mobilenetv3-tensorflow

  官方教程:https://tensorflow.google.cn/guide/keras/overview

  tf.keras是TensorFlow實現的keras API規範。這是一個用於構建和訓練模型的高階API,包含對tensorflow特定功能的支援。

1 import tf.keras
2 # form tensorflow import keras

  Keras 2.2.5是最後一個支援TensorFlow1.的版本,也是2.2.*最後一個用Keras實現的版本。最新的版本是Keras2.3.0,其對API進行了重大的改進,並新增對TensorFlow 2.0的支援。

**************************************Keras使用基礎*****************************************

Sequential Model:(the simplest type of model)

  Sequential 模型就是多個網路層的線性堆疊

。 model.add()

1 from keras.models import Sequential
2 from keras.layers import Dense
3 model = Sequential()
4 model.add(Dense(units=64, activation="relu", input_dim=100))
5 model.add(Dense(units=10, activation="softmax"))

  一旦模型搭建完成,可以通過.compile()配置它的學習過程。

1 model.compile(loss='categorical_crossentropy',
2               optimizer='sgd',
3               metrics=['accuracy']

  如果需要,也可以優化配置,如下所述。此時,損失、優化器的設定將會顯式的呼叫方法,而不是通過某欄位:

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

  訓練階段:

  然後,可以將資料輸入模型,並進行訓練。自動將輸入資料劃分為batch進行訓練:

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

  當然,也可以手動將batch資料集輸入到模型中(這種情況通常是在需要手動建立樣本對時,如siamese network):

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)

  以上是最簡明的Keras教程。

Getting started with the Keras Sequential model

  Sequential model 就是一些層的線性堆疊。

  堆疊的方式包含兩種:

  • 通過一個由層例項構成的列表:
1 from keras.models import Sequential
2 from keras.layers import Dense, Activation
3 
4 model = Sequential([
5     Dense(32, input_shape=(784,)),
6     Activation('relu'),
7     Dense(10),
8     Activation('softmax'),
9 ])

  將由層構成的列表新增到Sequential中。

  • 簡單的通過.add()函式新增層
1 model = Sequential()
2 model.add(Dense(32, input_dim=784))
3 model.add(Activation('relu'))

  一般會直接把啟用函式新增到層中:

model.add(Dense(units=10, activation="softmax"))  

Specifying the input shape

  模型需要明確輸入形狀(就像TensorFlow中佔位符tf.placeholder()的宣告)。

  因此,序列模型中的第一層(只有第一層,因為後續層可以進行自動形狀推斷)需要接收關於其輸入形狀的資訊。Keras有幾種可能的方法來做到這一點:

  • 將input_shape引數傳遞給第一層。這是一個形狀元組(一個整數或無項的元組,其中None表示可能期望任何正整數)。在input_shape中,不包括批處理維度。
1 model = Sequential() 
2 model.add(Dense(32, input_shape=(784,)))

  如上所示,將input_shape傳遞給第一層中。

  • 一些2D層(如Dense)通過引數input_dim傳遞輸入的形狀;一些3D層支援引數input_dim和input_length。
1 model = Sequential() 
2 model.add(Dense(32, input_dim=784))

  如上所示,Dense中既包含input_dim引數的傳遞,也包含input_shape引數的傳遞。

  • 也可以將batch_size新增到輸入形狀中。batch_size=32和input_shape=(6,8)傳遞給一個層,那麼它將期望每批輸入都具有批處理形狀(32,6,8)。 --這一部分與TensorFlow幾乎一致

Compilation

  在訓練模型之前,需要配置訓練過程的一些引數,通過compile函式完成。必需傳遞的三個引數:

  optimizer

  可以使用現存優化器的字串或者是一個優化器類的例項來識別。

 1 from keras import optimizers
 2 
 3 model = Sequential()
 4 model.add(Dense(64, kernel_initializer='uniform', input_shape=(10,)))
 5 model.add(Activation('softmax'))
 6 # 情形1: 類的例項
 7 sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
 8 model.compile(loss='mean_squared_error', optimizer=sgd)
 9 # 情形2:字串
10 model.compile(loss='mean_squared_error', optimizer='sgd')

  優化器中可以新增clipnorm和clipvalue引數梯度進行截斷

1 from keras import optimizers
2 
3 # All parameter gradients will be clipped to
4 # a maximum norm of 1.
5 sgd = optimizers.SGD(lr=0.01, clipnorm=1.)
1 from keras import optimizers
2 
3 # All parameter gradients will be clipped to
4 # a maximum value of 0.5 and
5 # a minimum value of -0.5.
6 sgd = optimizers.SGD(lr=0.01, clipvalue=0.5)

  常用的優化方式包括SGD、RMSprop、Adagrad、Adadelta、Adam、Adamax、Nadam。具體使用詳見:https://keras.io/optimizers/

loss funtion:

  同樣可以通過字串或類例項來識別。

1 from keras import losses
2 # 情形1 字串
3 model.compile(loss='mean_squared_error', optimizer='sgd')
4 # 情形2 類例項
5 model.compile(loss=losses.mean_squared_error, optimizer='sgd')

  可以獲取到的損失函式詳見:https://keras.io/losses/

metrics:

  對於任何分類問題,需要設定一些metrics=['accuracy'],也是通過字串和類例項識別。

1 from keras import metrics
2 # 情形1 字串
3 model.compile(loss='mean_squared_error',
4               optimizer='sgd',
5               metrics=['mae', 'acc'])
6 # 情形2 類例項
7 model.compile(loss='mean_squared_error',
8               optimizer='sgd',
9               metrics=[metrics.mae, metrics.categorical_accuracy])

  可以獲得的metrics詳見:https://keras.io/metrics/

Training

  Keras訓練通過Numpy陣列作為輸入資料

 1 # For a single-input model with 2 classes (binary classification):
 2 
 3 model = Sequential()
 4 model.add(Dense(32, activation='relu', input_dim=100))
 5 model.add(Dense(1, activation='sigmoid'))
 6 model.compile(optimizer='rmsprop',
 7               loss='binary_crossentropy',
 8               metrics=['accuracy'])
 9 
10 # Generate dummy data
11 import numpy as np
12 data = np.random.random((1000, 100))
13 labels = np.random.randint(2, size=(1000, 1))
14 
15 # Train the model, iterating on the data in batches of 32 samples
16 model.fit(data, labels, epochs=10, batch_size=32)

  one-hot操作:

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

  更多Keras中函式引數使用詳見:https://keras.io/models/sequential/

  後端使用詳見:https://keras.io/backend/

  ************************************************************************************************************

  上面介紹了一些關於Keras的使用,這是使用tf.keras的基礎。

  言歸正傳,回到tf.keras的道路上...

  tf.keras是TensorFlow實現的keras API規範。這是一個用於構建和訓練模型的高階API,包括對tensorflow特定功能(如eager execution、tf.data和Estimators) tf.keras使TensorFlow更易於使用,同時又不犧牲靈活性和效能。

  eager execution、tf.data和Estimators會在TensorFlow的介紹中詳細解讀,tf.keras中暫不作詳述。

  首先,匯入需要的一些設定:

1 from __future__ import absolute_import, division, print_function, unicode_literals
2 import tensorflow as tf
3 from tensorflow import keras 

  tf.keras中可以執行與Keras相容的任意程式碼,但需要注意的是:

  • 版本是否相容,需要通過tf.keras.version確認版本資訊
  • 模型儲存問題,tf.keras預設使用 checkpoint format格式,而keras模型的儲存格式HDF5需要借用函式save_format='h5'

使用tf.keras建立一個簡易的模型

  仿照Keras中的Sequential()方法,此時,在TensorFlow中也可以使用這種線性堆疊的方法:tf.keras.Sequentials()

 1 import tensorflow as tf
 2 from tensorflow.keras import layers
 3 
 4 model = tf.keras.Sequential()
 5 # Adds a densely-connected layer with 64 units to the model:
 6 model.add(layers.Dense(64, activation='relu'))
 7 # Add another:
 8 model.add(layers.Dense(64, activation='relu'))
 9 # Add an output layer with 10 output units:
10 model.add(layers.Dense(10))

  tf.keras.layers中提供了一些可用的層,詳見:https://tensorflow.google.cn/api_docs/python/tf/keras/layers

  這些層會包含一些共同的引數:

  • activation: 設定啟用函式。 預設情況下為無啟用函式。
  • kernel_initializerbias_initializer:初始化權重和偏執。通過這個操作,便不再需要手動為每一層的權重和偏執進行初始化。預設情況下是"Glorot uniform"初始化方式這個在tensorflow的slim API中會包含。
  • kernel_regularizer bias_regularizer : 權重和偏執正則化。通過這個操作,可以實現神經網路結構的正則化,防止過擬合的現象,可以使用L1正則化和L2正則化。預設情況下是不新增正則化。這個在tensorflow 的 slim API中也會包含。 --- 這個是需要手動新增的
 1 # 建立一個啟用函式是relu的全連線層:
 2 layers.Dense(64, activation='relu')
 3 # 也可以通過 類例項 設定啟用函式:
 4 layers.Dense(64, activation=tf.nn.relu)
 5 
 6 # 建立一個對權重使用L1正則化,並且引數為0.01的全連線層:
 7 layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l1(0.01))
 8 
 9 # 建立一個對偏執使用L2正則化,並且引數為0.01的全連線層:
10 layers.Dense(64, bias_regularizer=tf.keras.regularizers.l2(0.01))
11 
12 # 對權重選擇orthogonal的初始化方式
13 layers.Dense(64, kernel_initializer='orthogonal')
14 
15 # 將偏執初始化為2.0
16 layers.Dense(64, bias_initializer=tf.keras.initializers.Constant(2.0))

  在模型搭建完成後,便可以配置訓練過程的引數,這些過程與Keras一致,只不過是通過tf.keras來呼叫。

1 model.compile(optimizer=tf.keras.optimizers.Adam(0.01),
2               loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
3               metrics=['accuracy'])

  在compile可以設定run_eager=True ,to make sure the model trains and evaluates eagerly。

使用Numpy陣列進行訓練:

  不需要將資料喂到張量中,可以直接將資料輸入到.fit()函式中。

1 import numpy as np
2 
3 data = np.random.random((1000, 32))
4 labels = np.random.random((1000, 10))
5 
6 model.fit(data, labels, epochs=10, batch_size=32

  tf.keras.Model.fit()函式中包含3個重要引數:

  • epochs: 訓練代數
  • batch_size:一個批次的資料量。當傳遞NumPy資料時,模型將資料分割成更小的批。這個值指定每個批處理的大小。請注意,如果樣本總數不能被批次大小整除,那麼最後一批可能會很小
  • validation_data:在構建模型原型時,希望在某些驗證資料上方便地監視它的效能。傳遞這個引數(輸入和標籤的元組)允許模型在每個epoch結束時以推理模式顯示傳遞的資料的損失和度量。 當然,不設定也可以。 ---- 此處應該有推理代數的設定,每個epoch結束都進行驗證,會延長訓練時間,而且實際上也沒有必要。
 1 import numpy as np
 2 
 3 data = np.random.random((1000, 32))
 4 labels = np.random.random((1000, 10))
 5 
 6 val_data = np.random.random((100, 32))
 7 val_labels = np.random.random((100, 10))
 8 
 9 model.fit(data, labels, epochs=10, batch_size=32,
10           validation_data=(val_data, val_labels))

使用tf.data 資料集進行訓練

  此處只是簡單的介紹,tf.data是讀取資料的API,可以實現資料在多裝置上的訓練。可以通過tf.data.Dataset例項獲取資料,並將資料傳入到 .fit 方法中。

  詳見:https://tensorflow.google.cn/guide/data

1 dataset = tf.data.Dataset.from_tensor_slices((data, labels))
2 dataset = dataset.batch(32)
3 
4 model.fit(dataset, epochs=10)

  由於Dataset生成(yeild)批量資料,因此model.fit()中不再需要batch_size引數的設定。同時,Dataset也可以用於驗證資料的生成:

1 dataset = tf.data.Dataset.from_tensor_slices((data, labels))
2 dataset = dataset.batch(32)
3 
4 val_dataset = tf.data.Dataset.from_tensor_slices((val_data, val_labels))
5 val_dataset = val_dataset.batch(32)
6 
7 model.fit(dataset, epochs=10,
8           validation_data=val_dataset)

驗證和預測

  tf.keras.Model.evaluatetf.keras.Model.predict方法可以使用Numpy資料tf.data.Dataset資料進行驗證和預測

  .evaluate

 1 # With Numpy arrays
 2 data = np.random.random((1000, 32))
 3 labels = np.random.random((1000, 10))
 4 
 5 model.evaluate(data, labels, batch_size=32)
 6 
 7 # With a Dataset
 8 dataset = tf.data.Dataset.from_tensor_slices((data, labels))
 9 dataset = dataset.batch(32)   # 此處按照batch劃分
10 
11 model.evaluate(dataset)  # 此處不再需要batch引數

  .predict

1 result = model.predict(data, batch_size=32) 
2 print(result.shape)

  詳見:https://tensorflow.google.cn/guide/keras/train_and_evaluate

使用tf.keras構建複雜模型

  也許在上面的介紹中,你可能會覺得這只是在tensorflow中呼叫keras,搞出來了一個tf.keras這麼個東東,還不如直接用Keras來的實惠。這只是建立簡單的模型,在本節中,將會見到tf.keras的奇妙之處,也是在MobileNet V3原始碼中廣泛使用的模型子類化(Model subclassing)和自定義層(Custom layers) ,一起揭開其神祕的面紗。

The functional API

  使用tf.keras.Sequential構建模型是一種層與層之間簡單堆疊式的方式,其不能表徵任意的模型。使用Keras functional API可以建立複雜的模型,例如:

  • 多輸入模型
  • 多輸出模型
  • 擁有共享層的模型(同一層被呼叫多次)
  • 不具有序列化輸入的模型(殘差網路的連線)

  建立一個由functional API 構建的模型需要如下幾步:

  1. 層例項是可以呼叫的,並且返回一個張量;
  2. 輸入張量和輸出張量用於定義tf.keras.Model例項。
  3. 模型訓練的方式如同Sequential 模型。

  下面的全連線網路例項便是使用的the functional API,在其中,可以隱約的看到keras版的YOLO v3的影子:

 1 inputs = tf.keras.Input(shape=(32,))  # Returns an input placeholder
 2 
 3 # 1. 層例項可以回撥一個張量,也可以返回一個張量   --- 完成模型的構建
 4 x = layers.Dense(64, activation='relu')(inputs) 
 5 x = layers.Dense(64, activation='relu')(x)
 6 predictions = layers.Dense(10)(x)
 7 # 2. 通過給定輸出 輸出 例項化一個模型
 8 model = tf.keras.Model(inputs=inputs, outputs=predictions)
 9 
10 # 3. 通過與sequential模型相同的訓練方式訓練模型
11 model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
12               loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
13               metrics=['accuracy'])
14 
15 # Trains for 5 epochs
16 model.fit(data, labels, batch_size=32, epochs=5)

模型子類化(Model subclassing)

  通過tf.keras.Model子類化定義前向過程的方式完全自主的建立model。在_init__方法中建立層,並將它們設定為類例項的屬性。在call方法中定義前向過程。

  當啟用了立即執行時,模型子類化特別有用,因為它允許強制地編寫正向傳遞。

  下面的例項中展示了一個使用子類化tf.keras.Model,並且自定義前向過程的模型:

 1 class MyModel(tf.keras.Model):
 2 
 3   def __init__(self, num_classes=10):
 4     super(MyModel, self).__init__(name='my_model')
 5     self.num_classes = num_classes
 6     # Define your layers here.
 7     self.dense_1 = layers.Dense(32, activation='relu')   # __init__中定義層
 8     self.dense_2 = layers.Dense(num_classes)
 9 
10   def call(self, inputs):   # call 函式中定義前向過程
11     # Define your forward pass here,
12     # using layers you previously defined (in `__init__`).
13     x = self.dense_1(inputs)
14     return self.dense_2(x)

  例項化建立的MyModel類,那並進行編譯訓練:

1 model = MyModel(num_classes=10)
2 
3 # The compile step specifies the training configuration.
4 model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
5               loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
6               metrics=['accuracy'])
7 
8 # Trains for 5 epochs.
9 model.fit(data, labels, batch_size=32, epochs=5)

  上面的使用過程可以描述為以下幾個步驟:

  1. 為模型建立一個類;
  2. 模型中層的定義在__init__函式中;
  3. 前向的過程在call函式中定義;
  4. 例項化類,並使用與sequential相同的方式編譯 訓練模型。

定製層(Custom layers)

  通過子類化tf.keras.layers建立一個自定義層。使用以下方法實現:

  • __init__ :可選地定義此層要使用的子層(類的繼承);
  • build:生成層的權重,使用add_weights方法新增權重;
  • call:定義前向過程;
  • 可選地,可以通過實現get_config方法from_config類方法來序列化層。 (引數的儲存與匯入)

  下面是一個自定義層的例子,它實現了一個帶有核矩陣的輸入矩陣:

 1 class MyLayer(layers.Layer):
 2 
 3   def __init__(self, output_dim, **kwargs):
 4     self.output_dim = output_dim   # 輸出個數的定義
 5     super(MyLayer, self).__init__(**kwargs)  # 初始化layers.Layer變數。
 6 
 7   def build(self, input_shape):  # 新增權重矩陣
 8     # Create a trainable weight variable for this layer.
 9     self.kernel = self.add_weight(name='kernel',
10                                   shape=(input_shape[1], self.output_dim),
11                                   initializer='uniform',
12                                   trainable=True)   
13 
14   def call(self, inputs):   # 定義前向過程
15     return tf.matmul(inputs, self.kernel)
16 
17   def get_config(self):
18     base_config = super(MyLayer, self).get_config()
19     base_config['output_dim'] = self.output_dim
20     return base_config
21 
22   @classmethod
23   def from_config(cls, config):
24     return cls(**config)

  使用自定義的層,建立一個模型:

 1 model = tf.keras.Sequential([
 2     MyLayer(10)])
 3 
 4 # The compile step specifies the training configuration
 5 model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
 6               loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
 7               metrics=['accuracy'])
 8 
 9 # Trains for 5 epochs.
10 model.fit(data, labels, batch_size=32, epochs=5)

  更加細緻的內容詳見: https://tensorflow.google.cn/guide/keras/custom_layers_and_models

Callbacks

  回撥是傳遞給模型的物件,用於在訓練期間自定義和擴充套件其行為。編寫自己的自定義回撥,或者使用內建的tf.keras.callbacks,包括: ---- callbacks 引數是在.fit()中應用。

  • tf.keras.callbacks.ModelCheckpoint:每個一定代數定期的儲存權重;
  • tf.keras.callbacks.LearningRateScheduler: 動態地改變學習率 lr;
  • tf.keras.callbacks.EarlyStopping: 關於earlystop的設定
  • tf.keras.callbacks.TensorBoard: 關於tensorboard的設定;
1 callbacks = [
2   # Interrupt training if `val_loss` stops improving for over 2 epochs
3   tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),
4   # Write TensorBoard logs to `./logs` directory
5   tf.keras.callbacks.TensorBoard(log_dir='./logs')
6 ]
7 model.fit(data, labels, batch_size=32, epochs=5, callbacks=callbacks,
8           validation_data=(val_data, val_labels))

模型的儲存與匯入

只儲存權重

  • tf.keras.Model.save_weights()儲存權重;
  • tf.keras.Model.load_weights()匯入權重
1 # Save weights to a TensorFlow Checkpoint file
2 model.save_weights('./weights/my_model')
3 
4 # Restore the model's state,
5 # this requires a model with the same architecture.
6 model.load_weights('./weights/my_model')

  上述函式預設儲存的模型權重是TensorFlow的checkpoint(.ckpt)格式。也可以儲存為Keras版的HDF5格式,只需要修改儲存格式引數即可:

1 # Save weights to a HDF5 file
2 model.save_weights('my_model.h5', save_format='h5')
3 
4 # Restore the model's state
5 model.load_weights('my_model.h5')

只儲存模型的配置檔案:

  非訓練過程調整的引數儲存,如yolo中的cfg檔案。可以儲存為JSON和YAML兩種格式:

1 # Serialize a model to JSON format
2 json_string = model.to_json()   # 儲存  為json
3 yaml_string = model.to_yaml()   # 儲存 為yaml

  匯入

1 import json
2 import pprint
3 pprint.pprint(json.loads(json_string))

  復現模型:

1 fresh_model = tf.keras.models.model_from_json(json_string)   # 由json復現
2 fresh_model = tf.keras.models.model_from_yaml(yaml_string)   # 由yaml復現

儲存完整的模型在一個檔案中

1 # Save entire model to a HDF5 file
2 model.save('my_model')
3 
4 # Recreate the exact same model, including weights and optimizer.
5 model = tf.keras.models.load_model('my_model')

  更多關於儲存模型內容詳見:https://tensorflow.google.cn/guide/keras/save_and_serialize

  下一篇連結:https://www.cnblogs.com/monologuesmw/p/13534871.html

        https://tensorflow.google.cn/guide/keras