Tensorflow自定義模型與訓練超詳細講解
前言
Tensorflow的核心與NumPy非常相似,但具有GPU支持;
Tensorflow支持分布式計算(跨多個設備和服務器)。
像NumPy一樣使用TensorFlow
@運算符是在Python 3.5 中添加的,用于矩陣乘法,等效于 tf.matmul() 函數(shù)。
Keras的底層API
Keras API在keras.backend中有自己的底層API,如果要編寫可移植到其他Keras實現(xiàn)中的代碼,則應使用這些Keras函數(shù)。
from tensorflow import keras K = keras.backend K.square(K.transpose(t)) + 10
當從NumPy數(shù)組創(chuàng)建張量時,需設置 dtype=tf.float32;
定制模型和訓練算法
自定義損失函數(shù)
實現(xiàn)Huber損失:
def huber_fn(y_true, y_pred): error = y_true - y_pred is_small_error = tf.abs(error) < 1 squared_loss = tf.square(error) / 2 linear_loss = tf.abs(error) - 0.5 return tf.where(is_small_error, squared_loss, linear_loss)
編譯Keras模型,訓練模型:
model.compile(loss=huber_fn, optimizer="nadam") model.fit(X_train, y_train, [...])
保存和加載包含自定義組件的模型
當加載包含自定義對象的模型時,需要將名稱映射到對象。
model = keras.models.load_model("my_model_with_a_custom_loss.h5",custom_objects={<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->"huber_fn": huber_fn})
創(chuàng)建一個函數(shù),該函數(shù)創(chuàng)建已配置的損失函數(shù):
def create_huber(threshold=1.0): def huber_fn(y_true, y_pred): error = y_true - y_pred is_small_error = tf.abs(error) < threshold squared_loss = tf.square(error) / 2 linear_loss = threshold * tf.abs(error) - threshold**2 / 2 return tf.where(is_small_error, squared_loss, linear_loss) return huber_fn model.compile(loss=create_huber(2.0), optimizer="nadam")
在加載模型的時候必須指定閾值:
model = keras.models.load_model("my_model_with_a_custom_loss.h5",custom_objects={"huber_fn": create_huber(2.0)})
通過創(chuàng)建 keras.losses.Loss 類的子類,然后實現(xiàn)其 get_config() 方法來解決此問題:
class HuberLoss(keras.losses.Loss): def __init__(self, threshold=1.0, **kwargs): self.threshold = threshold super().__init__(**kwargs) def call(self, y_true, y_pred): error = y_true - y_pred is_small_error = tf.abs(error) < self.threshold squared_loss = tf.square(error) / 2 linear_loss = self.threshold * tf.abs(error) - self.threshold**2 / 2 return tf.where(is_small_error, squared_loss, linear_loss) def get_config(self): base_config = super().get_config() return {**base_config, "threshold": self.threshold}
以上父類構(gòu)造函數(shù)處理標準超參數(shù):損失的name和用于聚合單個實例損失的reduction算法。
get_config() 方法返回一個字典,將每個超參數(shù)映射到其值。首先調(diào)用父類的get_config() 方法,然后將新的超參數(shù)添加到此字典中。
可在編譯模型時使用此類的任何實例:
model.compile(loss=HuberLoss(2.),optimizer="nadam")
當保存模型的時候,閾值會同時一起保存。在加載模型時,只需要將類名映射到類本身:
model = keras.models.load_model("my_model_with_a_custom_loss.h5",custom_objects={<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->"HuberLoss": HuberLoss})
保存模型時,Keras會調(diào)用損失實例的 get_config() 方法,并將配置以 JSON 格式保存到 HDF5 文件中。
自定義激活函數(shù)與初始化與正則化和約束
編寫簡單的函數(shù)進行自定義
def my_softplus(z): return tf.math.log(tf.exp(z)+1.0) def my_glorot_initializer(shape, dtype=tf.float32): stddev = tf.sqrt(2. / (shape[0] + shape[1])) return tf.random.normal(shape, stddev=stddev, dtype=dtype) def my_l1_regularizer(weights): return tf.reduce_sum(tf.abs(0.01 * weights)) def my_positive_weights(weights): # return value is just tf.nn.relu(weights) return tf.where(weights < 0., tf.zeros_like(weights), weights)
使用這些自定義函數(shù)
layer = keras.layers.Dense(30, activation=my_softplus, kernel_initializer=my_glorot_initializer, kenel_regularizer=my_l1_regularizer, kenel_constraint=my_positive_weights)
在每個訓練步驟中,權(quán)重將傳遞給正則化函數(shù),以計算正則化損失,并將其添加到主要損失中得到用于訓練的最終損失。
必須為損失、層(包括激活函數(shù))和模型實現(xiàn) call() 方法,或者為正則化、初始化和約束實現(xiàn) __call__()方法。
自定義指標
可以將創(chuàng)建的損失函數(shù)作為指標。
model.compile(loss="mse", optimizer="nadam", metrics=[create_huber(2.0)])
流式指標(狀態(tài)指標)是逐批次更新的。
自定義層
創(chuàng)建不帶任何權(quán)重的自定義層:
exponential_layer = keras.layers.Lambda(lambda x: tf.exp(x))
- 當要預測的值具有非常不同的標度(例如0.001、10、1000)時,有時會在回歸模型的輸出層中使用指數(shù)層。
- 構(gòu)建自定義的有狀態(tài)層(即具有權(quán)重的層):
class MyDense(keras.layers.Layer): # 將所有超參數(shù)用作參數(shù) def __init__(self, units, activation=None, **kwargs): super().__init__(**kwargs) self.units = units self.activation = keras.activations.get(activation) # 創(chuàng)建層的變量 def build(self, batch_input_shape): self.kernel = self.add_weight( name="kernel", shape=[batch_input_shape[-1], self.units], initializer="glorot_normal") self.bias = self.add_weight( name="bias", shape=[self.units], initializer="zeros") super().build(batch_input_shape) # must be at the end # 調(diào)用父類方法,告訴keras這一層被構(gòu)建了,設置 self.built=true def call(self, X): return self.activation(X @ self.kernel + self.bias) def compute_output_shape(self, batch_input_shape): return tf.TensorShape(batch_input_shape.as_list()[:-1] + [self.units]) def get_config(self): base_config = super().get_config() return {**base_config, "units": self.units, "activation": keras.activation.serialize(self.activation) }
創(chuàng)建多輸入,多輸出的層:
class MyMultiLayer(keras.layers.Layer): def call(self, X): X1, X2 = X return [X1 + X2, X1 * X2, X1 / X2] def compute_output_shape(self, batch_input_shape): b1, b2 = batch_input_shape return [b1, b1, b1]
如果層在訓練期間和測試期間需要具有不同的行為,比如,創(chuàng)建一個在訓練期間(用于正則化)添加高斯噪聲,但在測試期間不執(zhí)行任何操作:
class MyGaussianNoise(keras.layers.Layer): def __init__(self, stddev, **kwargs): super().__init__(**kwargs) self.stddev = stddev def call(self, X, training=None): if training: noise = tf.random.normal(tf.shape(X), stddev=self.stddev) return X + noise else: return X def compute_output_shape(self, batch_input_shape): return batch_input_shape
自定義模型
首先創(chuàng)建一個 ResidualBlock 層:
class ResidualBlock(keras.layers.Layer): def __init__(self, n_layers, n_nerons, **kwargs): super().__init__(**kwargs) self.hidden = [keras.layers.Dense(n_nerons, activation="elu", kenel_initializer="he_normal") for _ in range(n_layers)] def call(self, inputs): Z = inputs for layer in self.hidden: Z = layer(Z) return inputs + Z
使用子類API定義模型:
class ResidualRegressor(keras.Model): def __init__(self, output_dim, **kwargs): super().__init__(**kwargs) self.hidden1 = keras.layers.Dense(30, activation="elu", kernel_initializer="he_normal") self.block1 = ResidualBlock(2, 30) self.block2 = ResidualBlock(2, 30) self.out = keras.layers.Dense(output_dim) def call(self, inputs): Z = self.hidden1(inputs) for _ in range(1 + 3): Z = self.block1(Z) Z = self.block2(Z) return self.out(Z)
- 在構(gòu)造函數(shù)中創(chuàng)建層,在call()方法中使用它們。
- 帶有自定義重建損失的自定義模型,此自定義模型在上部隱藏層的頂部有輔助輸出,與該輔助輸出相關的損失稱為重建損失。
class ReconstructingRegressor(keras.Model): def __init__(self, output_dim, **kwargs): super().__init__(**kwargs) self.hidden = [keras.layers.Dense(30, activation="selu", kernel_initializer = "lecun_normal") for _ in range(5)] self.out = keras.layers.Dense(output_dim) def build(self, batch_input_shape): n_inputs = batch_input_shape[-1] self.reconstruct = keras.layers.Dense(n_inputs) # 該層用于重建模型的輸入 super().build(batch_input_shape) def call(self, inputs): Z = inputs for layer in self.hidden: Z = layer(Z) reconstruction = self.reconstruct(Z) recon_loss = tf.reduce_mean(tf.square(reconstruction - inputs)) self.add_loss(0.05 * recon_loss) return self.out(Z)
正則化,在輸入變化不大時懲罰那些變化很大的激活。
到此這篇關于Tensorflow自定義模型與訓練超詳細講解的文章就介紹到這了,更多相關Tensorflow自定義模型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
十個Python練手的實戰(zhàn)項目,學會這些Python就基本沒問題了(推薦)
這篇文章主要介紹了Python實戰(zhàn)項目,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04Python OpenCV調(diào)用攝像頭檢測人臉并截圖
這篇文章主要為大家詳細介紹了Python OpenCV調(diào)用攝像頭檢測人臉并截圖,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-07-07Python?pydash庫處理大規(guī)模數(shù)據(jù)集執(zhí)行復雜操作
在數(shù)據(jù)處理和分析領域,Python一直是一種強大的編程語言,然而,在處理大規(guī)模數(shù)據(jù)集和執(zhí)行復雜操作時,有時候需要更高效的工具,在本文中,我們將深入探討pydash庫,這是一個專注于提高Python代碼性能的工具2023-12-12Tensorflow 自帶可視化Tensorboard使用方法(附項目代碼)
這篇文章主要介紹了Tensorflow 自帶可視化Tensorboard使用方法(附項目代碼),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02