Keras 2 API 文件 / 層 API / 基礎 Layer 類別

基礎 Layer 類別

[原始碼]

Layer 類別

tf_keras.layers.Layer(trainable=True, name=None, dtype=None, dynamic=False, **kwargs)

這是所有層繼承的類別。

層是一個可呼叫的物件,它接受一個或多個張量作為輸入,並輸出一個或多個張量。它涉及在 call() 方法中定義的計算,以及狀態(權重變數)。狀態可以在不同的地方建立,方便子類別實作。

  • __init__() 中;
  • 在可選的 build() 方法中,該方法由層的第一次 __call__() 呼叫,並提供輸入的形狀,這些形狀可能在初始化時未知;
  • 在第一次呼叫 call() 時,有一些如下討論的注意事項。

層是遞迴可組合的:如果你將 Layer 實例指定為另一個 Layer 的屬性,則外部層將開始追蹤內部層建立的權重。巢狀層應該在 __init__() 方法中實例化。

使用者只需實例化層,然後將其視為可呼叫的物件。

參數

  • trainable:布林值,表示層的變數是否應該是可訓練的。
  • name:層的字串名稱。
  • dtype:層的計算和權重的 dtype。也可以是 tf.keras.mixed_precision.Policy,允許計算和權重 dtype 不同。預設值 None 表示使用 tf.keras.mixed_precision.global_policy(),除非設定為其他值,否則預設為 float32 策略。
  • dynamic:如果你的層應該只以 eager 模式執行,而不應用於產生靜態計算圖,請將此設定為 True。例如,這適用於 Tree-RNN 或遞迴網路,或者通常適用於任何使用 Python 控制流操作張量的層。如果為 False,我們假設該層可以安全地用於產生靜態計算圖。

屬性

  • name:層的名稱(字串)。
  • dtype:層權重的 dtype。
  • variable_dtypedtype 的別名。
  • compute_dtype:層計算的 dtype。層會自動將輸入轉換為此 dtype,這會導致計算和輸出也以此 dtype 表示。當混合精度與 tf.keras.mixed_precision.Policy 一起使用時,此值會與 variable_dtype 不同。
  • dtype_policy:層的 dtype 策略。請參閱 tf.keras.mixed_precision.Policy 文件以了解詳細資訊。
  • trainable_weights:將包含在反向傳播中的變數列表。
  • non_trainable_weights:不應包含在反向傳播中的變數列表。
  • weights:可訓練權重列表和不可訓練權重列表的串聯(按此順序)。
  • trainable:層是否應該被訓練(布林值),即其潛在可訓練的權重是否應作為 layer.trainable_weights 的一部分傳回。
  • input_spec:可選的 (InputSpec 物件) 清單,指定層可接受的輸入約束。

我們建議 Layer 的子類別實作下列方法

  • __init__():定義自訂層屬性,並使用 add_weight() 或其他狀態建立不依賴輸入形狀的層權重。
  • build(self, input_shape):此方法可用於使用 add_weight() 或其他狀態建立依賴於輸入形狀的權重。__call__() 會自動呼叫 build() 來建立層(如果尚未建立)。
  • call(self, inputs, *args, **kwargs):在確認已呼叫 build() 後在 __call__ 中呼叫。call() 執行將層應用於 inputs 的邏輯。第一次呼叫也可能會建立無法方便地在 build() 中建立的狀態;請參閱其 docstring 以了解詳細資訊。您可以在 call() 中選擇性使用的兩個保留關鍵字參數是:- training (布林值,表示呼叫是否處於推論模式或訓練模式)。請參閱層/模型子類別化指南中的更多詳細資訊 - mask (布林張量,用於編碼輸入中被遮蔽的時間步,用於 RNN 層)。請參閱層/模型子類別化指南中的更多詳細資訊。此方法的典型簽名是 call(self, inputs),如果層需要,使用者可以選擇性地新增 trainingmask*args**kwargs 僅在未來計劃新增更多輸入參數時有用。
  • get_config(self):傳回包含用於初始化此層的組態的字典。如果鍵與 __init__ 中的引數不同,則也要覆寫 from_config(self)。當儲存層或包含此層的模型時,會使用此方法。

範例

這是一個基本範例:具有兩個變數 wb 的層,傳回 y = w . x + b。它顯示如何實作 build()call()。設定為層屬性的變數會被追蹤為層的權重 (在 layer.weights 中)。

class SimpleDense(Layer):

  def __init__(self, units=32):
      super(SimpleDense, self).__init__()
      self.units = units

  def build(self, input_shape):  # Create the state of the layer (weights)
    w_init = tf.random_normal_initializer()
    self.w = tf.Variable(
        initial_value=w_init(shape=(input_shape[-1], self.units),
                             dtype='float32'),
        trainable=True)
    b_init = tf.zeros_initializer()
    self.b = tf.Variable(
        initial_value=b_init(shape=(self.units,), dtype='float32'),
        trainable=True)

  def call(self, inputs):  # Defines the computation from inputs to outputs
      return tf.matmul(inputs, self.w) + self.b

# Instantiates the layer.
linear_layer = SimpleDense(4)

# This will also call `build(input_shape)` and create the weights.
y = linear_layer(tf.ones((2, 2)))
assert len(linear_layer.weights) == 2

# These weights are trainable, so they're listed in `trainable_weights`:
assert len(linear_layer.trainable_weights) == 2

請注意,add_weight() 方法提供建立權重的捷徑。

class SimpleDense(Layer):

  def __init__(self, units=32):
      super(SimpleDense, self).__init__()
      self.units = units

  def build(self, input_shape):
      self.w = self.add_weight(shape=(input_shape[-1], self.units),
                               initializer='random_normal',
                               trainable=True)
      self.b = self.add_weight(shape=(self.units,),
                               initializer='random_normal',
                               trainable=True)

  def call(self, inputs):
      return tf.matmul(inputs, self.w) + self.b

除了在訓練期間透過反向傳播更新的可訓練權重外,層還可以具有不可訓練的權重。這些權重旨在在 call() 期間手動更新。以下是一個計算其輸入運行總和的範例層

class ComputeSum(Layer):

  def __init__(self, input_dim):
      super(ComputeSum, self).__init__()
      # Create a non-trainable weight.
      self.total = tf.Variable(initial_value=tf.zeros((input_dim,)),
                               trainable=False)

  def call(self, inputs):
      self.total.assign_add(tf.reduce_sum(inputs, axis=0))
      return self.total

my_sum = ComputeSum(2)
x = tf.ones((2, 2))

y = my_sum(x)
print(y.numpy())  # [2. 2.]

y = my_sum(x)
print(y.numpy())  # [4. 4.]

assert my_sum.weights == [my_sum.total]
assert my_sum.non_trainable_weights == [my_sum.total]
assert my_sum.trainable_weights == []

有關建立層的更多資訊,請參閱指南透過子類別化建立新層和模型


weights 屬性

tf_keras.layers.Layer.weights

傳回所有層變數/權重的清單。

傳回

變數的清單。


trainable_weights 屬性

tf_keras.layers.Layer.trainable_weights

此層追蹤的所有可訓練權重清單。

可訓練權重在訓練期間透過梯度下降更新。

傳回

可訓練變數的清單。


non_trainable_weights 屬性

tf_keras.layers.Layer.non_trainable_weights

此層追蹤的所有不可訓練權重清單。

不可訓練權重在訓練期間不會更新。它們預期會在 call() 中手動更新。

傳回

不可訓練變數的清單。


[原始碼]

add_weight 方法

Layer.add_weight(
    name=None,
    shape=None,
    dtype=None,
    initializer=None,
    regularizer=None,
    trainable=None,
    constraint=None,
    use_resource=None,
    synchronization=tf.VariableSynchronization.AUTO,
    aggregation=tf.VariableSynchronization.NONE,
    **kwargs
)

向層新增新的變數。

參數

  • name:變數名稱。
  • shape:變數形狀。如果未指定,則預設為純量。
  • dtype:變數的類型。預設為 self.dtype
  • initializer:初始化器實例 (可呼叫)。
  • regularizer:正規化器實例 (可呼叫)。
  • trainable:布林值,表示變數是否應屬於層的「trainable_variables」(例如,變數、偏差)或「non_trainable_variables」(例如,BatchNorm 平均值和變異數)。請注意,如果 synchronization 設定為 ON_READ,則 trainable 不能為 True
  • constraint:約束實例 (可呼叫)。
  • use_resource:是否使用 ResourceVariable。請參閱本指南以了解更多資訊。
  • synchronization:指示何時會聚合分散式變數。接受的值是在 tf.VariableSynchronization 類別中定義的常數。預設情況下,同步設定為 AUTO,目前的 DistributionStrategy 會選擇何時同步。如果 synchronization 設定為 ON_READ,則 trainable 不得設定為 True
  • aggregation:指示如何聚合分散式變數。接受的值是在 tf.VariableAggregation 類別中定義的常數。
  • **kwargs:其他關鍵字引數。接受的值為 gettercollectionsautocastexperimental_autocastcaching_device

傳回

建立的變數。

引發

  • ValueError:當給定不支援的 dtype 且沒有初始化器,或當 trainable 設定為 True 且同步設定為 ON_READ 時。

trainable 屬性

tf_keras.layers.Layer.trainable

[原始碼]

get_weights 方法

Layer.get_weights()

以 NumPy 陣列的形式傳回層的目前權重。

層的權重代表層的狀態。此函式會傳回與此層關聯的可訓練和不可訓練權重值,以 NumPy 陣列列表的形式,這些權重值可以反過來用於將狀態載入類似參數化的層。

例如,Dense 層會傳回兩個值的列表:核心矩陣和偏差向量。這些可用於設定另一個 Dense 層的權重。

>>> layer_a = tf.keras.layers.Dense(1,
...   kernel_initializer=tf.constant_initializer(1.))
>>> a_out = layer_a(tf.convert_to_tensor([[1., 2., 3.]]))
>>> layer_a.get_weights()
[array([[1.],
       [1.],
       [1.]], dtype=float32), array([0.], dtype=float32)]
>>> layer_b = tf.keras.layers.Dense(1,
...   kernel_initializer=tf.constant_initializer(2.))
>>> b_out = layer_b(tf.convert_to_tensor([[10., 20., 30.]]))
>>> layer_b.get_weights()
[array([[2.],
       [2.],
       [2.]], dtype=float32), array([0.], dtype=float32)]
>>> layer_b.set_weights(layer_a.get_weights())
>>> layer_b.get_weights()
[array([[1.],
       [1.],
       [1.]], dtype=float32), array([0.], dtype=float32)]

傳回

權重值,以 NumPy 陣列的列表表示。


[原始碼]

set_weights 方法

Layer.set_weights(weights)

從 NumPy 陣列設定層的權重。

層的權重代表層的狀態。此函式會從 numpy 陣列設定權重值。權重值應該按照它們由層建立的順序傳遞。請注意,在呼叫此函式之前,必須先透過呼叫層來實例化層的權重。

例如,Dense 層會傳回兩個值的列表:核心矩陣和偏差向量。這些可用於設定另一個 Dense 層的權重。

>>> layer_a = tf.keras.layers.Dense(1,
...   kernel_initializer=tf.constant_initializer(1.))
>>> a_out = layer_a(tf.convert_to_tensor([[1., 2., 3.]]))
>>> layer_a.get_weights()
[array([[1.],
       [1.],
       [1.]], dtype=float32), array([0.], dtype=float32)]
>>> layer_b = tf.keras.layers.Dense(1,
...   kernel_initializer=tf.constant_initializer(2.))
>>> b_out = layer_b(tf.convert_to_tensor([[10., 20., 30.]]))
>>> layer_b.get_weights()
[array([[2.],
       [2.],
       [2.]], dtype=float32), array([0.], dtype=float32)]
>>> layer_b.set_weights(layer_a.get_weights())
>>> layer_b.get_weights()
[array([[1.],
       [1.],
       [1.]], dtype=float32), array([0.], dtype=float32)]

參數

  • weights:NumPy 陣列的列表。陣列的數量及其形狀必須符合層權重的維度數量(即,它應該與 get_weights 的輸出匹配)。

引發

  • ValueError:如果提供的權重列表與層的規格不符。

[原始碼]

get_config 方法

Model.get_config()

傳回 Model 的組態。

組態是一個 Python 字典(可序列化),其中包含物件的配置,在此情況下為 Model。這允許稍後從此配置重新實例化 Model(無需其訓練權重)。

請注意,get_config() 不保證每次呼叫都會傳回字典的全新副本。呼叫者如果想要修改字典,應複製傳回的字典。

建議子類別化的 Model 開發人員覆寫此方法,並繼續從 super(MyModel, self).get_config() 更新字典,以提供此 Model 的正確配置。如果初始參數為基本類型,則預設組態將傳回初始參數的組態字典。在子類別化模型需要自訂 get_config() 實作的情況下,會引發 NotImplementedError

傳回

包含此 Model 配置的 Python 字典。


[原始碼]

add_loss 方法

Layer.add_loss(losses, **kwargs)

新增損失張量,可能依賴於層輸入。

某些損失(例如,活動正規化損失)可能依賴於呼叫層時傳入的輸入。因此,當在不同輸入 ab 上重複使用同一層時,layer.losses 中的某些條目可能依賴於 a,而某些則依賴於 b。此方法會自動追蹤依賴關係。

此方法可用於子類別化的層或模型的 call 函式內,在此情況下,losses 應為張量或張量列表。

範例

class MyLayer(tf.keras.layers.Layer):
  def call(self, inputs):
    self.add_loss(tf.abs(tf.reduce_mean(inputs)))
    return inputs

相同的程式碼適用於分散式訓練:add_loss() 的輸入被視為正規化損失,並由訓練迴圈(內建 Model.fit() 和相容的自訂訓練迴圈)在副本之間進行平均。

add_loss 方法也可以在建構期間直接在 Functional Model 上呼叫。在這種情況下,傳遞給此模型的任何損失張量都必須是符號式的,並且能夠追溯到模型的 Input。這些損失會成為模型拓撲的一部分,並在 get_config 中追蹤。

範例

inputs = tf.keras.Input(shape=(10,))
x = tf.keras.layers.Dense(10)(inputs)
outputs = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, outputs)
# Activity regularization.
model.add_loss(tf.abs(tf.reduce_mean(x)))

如果您的損失不是這種情況(例如,您的損失引用模型其中一層的 Variable),您可以將您的損失包裝在一個零引數 lambda 中。這些損失不會被追蹤為模型拓撲的一部分,因為它們無法序列化。

範例

inputs = tf.keras.Input(shape=(10,))
d = tf.keras.layers.Dense(10)
x = d(inputs)
outputs = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, outputs)
# Weight regularization.
model.add_loss(lambda: tf.reduce_mean(d.kernel))

參數

  • losses:損失張量,或張量列表/元組。損失也可以是零引數的可呼叫物件,用於建立損失張量,而非張量。
  • **kwargs:僅用於向後相容性。

losses 屬性

tf_keras.layers.Layer.losses

使用 add_loss() API 新增的損失列表。

變數正規化張量在存取此屬性時建立,因此是 eager 安全的:在 tf.GradientTape 下存取 losses 將會將梯度傳播回對應的變數。

範例

>>> class MyLayer(tf.keras.layers.Layer):
...   def call(self, inputs):
...     self.add_loss(tf.abs(tf.reduce_mean(inputs)))
...     return inputs
>>> l = MyLayer()
>>> l(np.ones((10, 1)))
>>> l.losses
[1.0]
>>> inputs = tf.keras.Input(shape=(10,))
>>> x = tf.keras.layers.Dense(10)(inputs)
>>> outputs = tf.keras.layers.Dense(1)(x)
>>> model = tf.keras.Model(inputs, outputs)
>>> # Activity regularization.
>>> len(model.losses)
0
>>> model.add_loss(tf.abs(tf.reduce_mean(x)))
>>> len(model.losses)
1
>>> inputs = tf.keras.Input(shape=(10,))
>>> d = tf.keras.layers.Dense(10, kernel_initializer='ones')
>>> x = d(inputs)
>>> outputs = tf.keras.layers.Dense(1)(x)
>>> model = tf.keras.Model(inputs, outputs)
>>> # Weight regularization.
>>> model.add_loss(lambda: tf.reduce_mean(d.kernel))
>>> model.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=1.0>]

傳回

張量的列表。