ヘルプKaggleにTensorFlowグレートバリアリーフを保護チャレンジに参加

TF2ワークフローでTF1.xモデルを使用する

TensorFlow.orgで表示 GoogleColabで実行 GitHubで表示 ノートブックをダウンロード

このガイドでは、の概要と例を提供してモデリングコードシムを使用すると、TF2で、既存のTF1.xモデルを使用して採用することができるような熱心な実行、とワークフローtf.functionあなたのモデリングコードに最小限の変更で、及び流通戦略。

使用範囲

このガイドで説明されているシムは、以下に依存するTF1.xモデル用に設計されています。

  1. tf.compat.v1.get_variabletf.compat.v1.variable_scope 、制御変数の作成と再利用へと
  2. 以下のようなグラフ・コレクションベースのAPI tf.compat.v1.global_variables() tf.compat.v1.trainable_variablestf.compat.v1.losses.get_regularization_losses()およびtf.compat.v1.get_collection()を追跡します重みと正則化損失の

これは、ほとんどの上に構築されたモデルが含まtf.compat.v1.layertf.contrib.layers API、およびTensorFlow-スリムに

シムは、次のTF1.xモデルに必要ありません

  1. すでに経由で自分のトレーニング可能な重みと正則損失のすべてを追跡するスタンドアローンKerasモデルmodel.trainable_weightsmodel.lossesそれぞれ。
  2. tf.Module S既に経由で自分のトレーニング可能な重みのすべてを追跡することmodule.trainable_variables 、彼らがすでに作成されていない場合にのみウェイトを作成します。

これらのモデルは、熱心な実行ととTF2で動作するように思われるtf.functionのアウト・オブ・ボックス。

設定

TensorFlowとその他の依存関係をインポートします。

pip uninstall -y -q tensorflow
# Install tf-nightly as the DeterministicRandomTestTool is available only in
# Tensorflow 2.8

pip install -q tf-nightly
import tensorflow as tf
import tensorflow.compat.v1 as v1
import sys
import numpy as np

from contextlib import contextmanager

track_tf1_style_variablesデコレータ

キーシムは、このガイドで説明tf.compat.v1.keras.utils.track_tf1_style_variables 、あなたがに属するメソッド内で使用できることをデコレータtf.keras.layers.Layertf.Module TF1.xスタイルの重みを追跡することをと正則化の損失をキャプチャします。

飾るtf.keras.layers.Layerのかtf.Moduleとの通話方法tf.compat.v1.keras.utils.track_tf1_style_variablesを介して可変の作成と再利用を可能にtf.compat.v1.get_variable (および拡張によって、 tf.compat.v1.layers )必ず各呼び出しに新しい変数を作成するのではなく、装飾されたメソッドの内部を正しく動作させます。また、暗黙的に層またはモジュールを引き起こす介して作成またはアクセスした重みを追跡しますget_variable装飾されたメソッドの内部を。

標準の下に身を重みを追跡することに加えlayer.variable / module.variableの/ etc。この方法は、に属している場合の特性は、 tf.keras.layers.Layer 、次いで介して指定された任意の正則損失get_variableまたはtf.compat.v1.layers引数が、標準的な下地層によって追跡されます正則layer.lossesプロパティ。

このトラッキングメカニズムはKeras層またはのTF1.xスタイルモデルフォワードパスコードの内部の大規模なクラスの使用可能tf.Module TF2の行動が有効になっていてもTF2で秒。

使用例

以下の使用例を飾るために使用されるモデリングシム実証tf.keras.layers.Layer方法を、彼らは具体的Kerasと相互作用している場合を除いて飾るときに適用されている機能tf.Module同様の方法を。

tf.compat.v1.get_variableで構築されたレイヤー

あなたがの上に直接層を実装している想像しtf.compat.v1.get_variable次のように:

def dense(self, inputs, units):
  out = inputs
  with tf.compat.v1.variable_scope("dense"):
    # The weights are created with a `regularizer`,
    kernel = tf.compat.v1.get_variable(
        shape=[out.shape[-1], units],
        regularizer=tf.keras.regularizers.L2(),
        initializer=tf.compat.v1.initializers.glorot_normal,
        name="kernel")
    bias = tf.compat.v1.get_variable(
        shape=[units,],
        initializer=tf.compat.v1.initializers.zeros,
        name="bias")
    out = tf.linalg.matmul(out, kernel)
    out = tf.compat.v1.nn.bias_add(out, bias)
  return out

シムを使用してレイヤーに変換し、入力で呼び出します。

class DenseLayer(tf.keras.layers.Layer):

  def __init__(self, units, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.units = units

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs):
    out = inputs
    with tf.compat.v1.variable_scope("dense"):
      # The weights are created with a `regularizer`,
      # so the layer should track their regularization losses
      kernel = tf.compat.v1.get_variable(
          shape=[out.shape[-1], self.units],
          regularizer=tf.keras.regularizers.L2(),
          initializer=tf.compat.v1.initializers.glorot_normal,
          name="kernel")
      bias = tf.compat.v1.get_variable(
          shape=[self.units,],
          initializer=tf.compat.v1.initializers.zeros,
          name="bias")
      out = tf.linalg.matmul(out, kernel)
      out = tf.compat.v1.nn.bias_add(out, bias)
    return out

layer = DenseLayer(10)
x = tf.random.normal(shape=(8, 20))
layer(x)
WARNING:tensorflow:From /tmp/ipykernel_27038/795621215.py:7: The name tf.keras.utils.track_tf1_style_variables is deprecated. Please use tf.compat.v1.keras.utils.track_tf1_style_variables instead.
<tf.Tensor: shape=(8, 10), dtype=float32, numpy=
array([[-0.51018804, -0.58145535,  0.25050664, -0.09880018,  0.71741414,
        -0.08512568,  0.33404148,  0.50894034,  0.19362557,  0.03945067],
       [-0.66160053,  0.43442816, -0.6187523 ,  0.00753711,  1.3946855 ,
         0.22528797,  0.55661404, -1.6155301 ,  1.5854199 , -0.4165327 ],
       [ 0.15855707,  0.43848652,  0.04762229,  0.22020248,  0.88300526,
         0.31525093, -0.10912375,  0.03332198,  1.3462385 , -0.37986106],
       [ 0.02546233, -0.01084138,  0.0417656 ,  1.1082407 ,  0.926408  ,
         0.46938205,  1.0183189 ,  1.2039868 , -0.09619217, -0.50863194],
       [-1.6222394 ,  0.17156005, -0.07482994,  0.646423  ,  1.0284312 ,
         2.3619173 ,  0.6322627 ,  0.5350776 , -2.2700598 , -0.8211552 ],
       [-1.1044651 ,  0.7303245 ,  1.0183476 ,  1.2858934 ,  0.4575533 ,
         0.93400717,  0.5323913 , -0.01242167,  0.8308919 ,  0.03202473],
       [ 0.3880633 , -1.2345276 ,  0.7713047 , -0.33720714,  1.0418141 ,
        -1.055242  , -1.6942265 ,  1.705035  ,  0.8671215 ,  0.8162696 ],
       [ 0.02216246, -0.5235669 ,  0.01065174, -1.1682817 ,  0.44079733,
         0.25890222, -1.0779501 ,  0.37716752, -0.27636313, -0.6359312 ]],
      dtype=float32)>

標準のKerasレイヤーのように、追跡された変数とキャプチャされた正則化損失にアクセスします。

layer.trainable_variables
layer.losses
2021-12-04 02:24:42.941890: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
[<tf.Tensor: shape=(), dtype=float32, numpy=0.10789324>]

レイヤーを呼び出すたびに重みが再利用されることを確認するには、すべての重みをゼロに設定して、レイヤーを再度呼び出します。

print("Resetting variables to zero:", [var.name for var in layer.trainable_variables])

for var in layer.trainable_variables:
  var.assign(var * 0.0)

# Note: layer.losses is not a live view and
# will get reset only at each layer call
print("layer.losses:", layer.losses)
print("calling layer again.")
out = layer(x)
print("layer.losses: ", layer.losses)
out
Resetting variables to zero: ['dense/bias:0', 'dense/kernel:0']
layer.losses: [<tf.Tensor: shape=(), dtype=float32, numpy=0.0>]
calling layer again.
layer.losses:  [<tf.Tensor: shape=(), dtype=float32, numpy=0.0>]
<tf.Tensor: shape=(8, 10), dtype=float32, numpy=
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>

変換されたレイヤーは、Keras機能モデルの構築でも直接使用できます。

inputs = tf.keras.Input(shape=(20))
outputs = DenseLayer(10)(inputs)
model = tf.keras.Model(inputs=inputs, outputs=outputs)

x = tf.random.normal(shape=(8, 20))
model(x)

# Access the model variables and regularization losses
model.weights
model.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.1345337>]

モデルで構築されたtf.compat.v1.layers

レイヤーやモデルがの上に直接実装されてい想像tf.compat.v1.layers次のように:

def model(self, inputs, units):
  with tf.compat.v1.variable_scope('model'):
    out = tf.compat.v1.layers.conv2d(
        inputs, 3, 3,
        kernel_regularizer="l2")
    out = tf.compat.v1.layers.flatten(out)
    out = tf.compat.v1.layers.dense(
        out, units,
        kernel_regularizer="l2")
    return out

シムを使用してレイヤーに変換し、入力で呼び出します。

class CompatV1LayerModel(tf.keras.layers.Layer):

  def __init__(self, units, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.units = units

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs):
    with tf.compat.v1.variable_scope('model'):
      out = tf.compat.v1.layers.conv2d(
          inputs, 3, 3,
          kernel_regularizer="l2")
      out = tf.compat.v1.layers.flatten(out)
      out = tf.compat.v1.layers.dense(
          out, self.units,
          kernel_regularizer="l2")
      return out

layer = CompatV1LayerModel(10)
x = tf.random.normal(shape=(8, 5, 5, 5))
layer(x)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:12: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
  if sys.path[0] == '':
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/convolutional.py:575: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  return layer.apply(inputs)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:13: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead.
  del sys.path[0]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/core.py:541: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  return layer.apply(inputs)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:16: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
  app.launch_new_instance()
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/core.py:261: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  return layer.apply(inputs)
<tf.Tensor: shape=(8, 10), dtype=float32, numpy=
array([[ 2.4439096 , -0.2912227 ,  1.5531251 ,  1.284059  ,  0.10077369,
        -0.4231838 ,  1.0458903 , -0.01530766,  0.07358164, -0.6108157 ],
       [-0.4576063 ,  0.34942552,  2.3044965 ,  1.1483003 , -1.2211238 ,
         0.5634397 ,  0.73821646, -0.07581732,  0.5747937 , -0.66470885],
       [-2.2948585 , -2.709268  ,  1.7494816 , -0.9808065 , -2.9099958 ,
         0.5067346 , -1.011502  ,  2.559535  , -3.0888772 ,  0.3522656 ],
       [ 1.7788265 ,  0.8846102 ,  0.45562026,  0.01498583, -0.12482446,
        -0.32868862, -0.7743829 ,  2.3106992 , -0.0997327 , -0.7715093 ],
       [ 0.40295708,  0.04771695, -0.21336336, -0.13069987,  2.279875  ,
         2.7284563 ,  0.6444641 , -1.1919906 ,  0.96321577,  1.0182515 ],
       [ 0.47900966,  0.04906505,  1.1335449 ,  0.2907704 ,  0.7732022 ,
         0.68217   ,  0.51932573, -0.45156685,  2.081223  ,  1.068861  ],
       [ 0.10084352,  1.6456002 ,  0.63820475,  1.5959243 ,  0.22463399,
         0.07713126,  0.7467398 , -1.5435244 ,  1.2494736 , -0.07683721],
       [ 2.1396816 ,  1.5613532 , -1.1726325 , -0.88917583,  1.6447946 ,
        -1.0071977 , -1.8496083 ,  1.1887017 ,  2.1971662 ,  2.1175954 ]],
      dtype=float32)>

標準のKerasレイヤーのように、追跡された変数とキャプチャされた正則化損失にアクセスします。

layer.trainable_variables
layer.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.03623246>,
 <tf.Tensor: shape=(), dtype=float32, numpy=0.14618248>]

レイヤーを呼び出すたびに重みが再利用されることを確認するには、すべての重みをゼロに設定して、レイヤーを再度呼び出します。

print("Resetting variables to zero:", [var.name for var in layer.trainable_variables])

for var in layer.trainable_variables:
  var.assign(var * 0.0)

out = layer(x)
print("layer.losses: ", layer.losses)
out
Resetting variables to zero: ['model/conv2d/bias:0', 'model/conv2d/kernel:0', 'model/dense/bias:0', 'model/dense/kernel:0']
layer.losses:  [<tf.Tensor: shape=(), dtype=float32, numpy=0.0>, <tf.Tensor: shape=(), dtype=float32, numpy=0.0>]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:12: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
  if sys.path[0] == '':
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:13: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead.
  del sys.path[0]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:16: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
  app.launch_new_instance()
<tf.Tensor: shape=(8, 10), dtype=float32, numpy=
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>

変換されたレイヤーは、Keras機能モデルの構築でも直接使用できます。

inputs = tf.keras.Input(shape=(5, 5, 5))
outputs = CompatV1LayerModel(10)(inputs)
model = tf.keras.Model(inputs=inputs, outputs=outputs)

x = tf.random.normal(shape=(8, 5, 5, 5))
model(x)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:12: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
  if sys.path[0] == '':
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/base.py:573: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  _add_elements_to_collection(self.updates, tf.compat.v1.GraphKeys.UPDATE_OPS)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:13: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead.
  del sys.path[0]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:16: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
  app.launch_new_instance()
<tf.Tensor: shape=(8, 10), dtype=float32, numpy=
array([[ 0.19487001,  0.54727787,  1.1044168 , -0.6613899 , -0.26437742,
        -1.1580509 , -0.24707682,  0.97752655,  0.59436107,  0.13125825],
       [ 0.48974586, -1.3510125 ,  0.7186962 , -0.8996632 , -0.60448873,
         0.06332532,  0.31494308,  0.23021704, -1.9166642 ,  0.3890404 ],
       [-0.06499191, -0.21485235,  0.01158494,  1.4407377 , -0.0488929 ,
        -0.37594396, -0.4386894 , -0.08751169,  1.0905663 , -1.5450519 ],
       [-2.2749739 , -2.4603422 , -1.3834419 , -2.8800466 ,  0.8954872 ,
        -3.0429187 , -0.7885461 ,  1.6037437 , -3.1845028 , -1.0725503 ],
       [ 0.98735195, -0.45159122,  0.892656  ,  0.477053  ,  0.31193537,
        -0.44723228, -0.01815075, -0.47465172, -1.665448  , -2.105824  ],
       [-2.5408387 , -1.7552321 , -1.924145  , -0.6395873 ,  0.4081779 ,
        -0.48731515, -3.2637763 , -1.4409767 , -2.032539  ,  0.10204412],
       [ 2.1583526 ,  0.78955674, -0.07266375,  0.06652926,  2.1300716 ,
        -1.6256162 ,  0.56154627, -0.76179224,  2.2985756 , -1.5504618 ],
       [ 2.062847  ,  0.971378  , -1.0830508 ,  1.8224751 , -0.3542943 ,
         0.74113446, -0.6204865 ,  1.4503044 , -0.4979878 , -0.4383126 ]],
      dtype=float32)>
# Access the model variables and regularization losses
model.weights
model.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.03079858>,
 <tf.Tensor: shape=(), dtype=float32, numpy=0.12991619>]

キャプチャバッチ正規の更新とモデルのtraining引数

TF1.xでは、次のようにバッチ正規化を実行します。

  x_norm = tf.compat.v1.layers.batch_normalization(x, training=training)

  # ...

  update_ops = tf.compat.v1.get_collection(tf.GraphKeys.UPDATE_OPS)
  train_op = optimizer.minimize(loss)
  train_op = tf.group([train_op, update_ops])

ご了承ください:

  1. 平均更新を移動バッチ正規化によって追跡さget_collection層とは別に呼び出されました
  2. tf.compat.v1.layers.batch_normalization必要training (一般的に呼ばれる引数is_training TF-スリムバッチ正規化層を使用する場合)を

TF2では、原因に熱心実行し、自動制御依存性、平均更新を移動バッチの正規化はすぐに実行されます。それらをupdatesコレクションから個別に収集し、明示的なコントロールの依存関係として追加する必要はありません。

あなたが与える場合はさらに、 tf.keras.layers.Layerの往路方法にtraining引数を、Kerasは、それが他の層の場合と同じように、それに現在のトレーニング相とネストされたレイヤーを渡すことができるようになります。以下のためのAPIドキュメントを参照してくださいtf.keras.Model Kerasがどのように処理するかの詳細については、 trainingの引数を。

あなたが装飾されている場合tf.Module方法を、手動ですべて合格することを確認する必要がありtraining 、必要に応じて引数を。ただし、バッチ正規化移動平均更新は、明示的な制御依存関係を必要とせずに自動的に適用されます。

次のコードスニペットは、(に適用Kerasモデルの作品にそれを使用してシムで、どのように埋め込むバッチ正規層に方法を示しtf.keras.layers.Layer )。

class CompatV1BatchNorm(tf.keras.layers.Layer):

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs, training=None):
    print("Forward pass called with `training` =", training)
    with v1.variable_scope('batch_norm_layer'):
      return v1.layers.batch_normalization(x, training=training)
print("Constructing model")
inputs = tf.keras.Input(shape=(5, 5, 5))
outputs = CompatV1BatchNorm()(inputs)
model = tf.keras.Model(inputs=inputs, outputs=outputs)

print("Calling model in inference mode")
x = tf.random.normal(shape=(8, 5, 5, 5))
model(x, training=False)

print("Moving average variables before training: ",
      {var.name: var.read_value() for var in model.non_trainable_variables})

# Notice that when running TF2 and eager execution, the batchnorm layer directly
# updates the moving averages while training without needing any extra control
# dependencies
print("calling model in training mode")
model(x, training=True)

print("Moving average variables after training: ",
      {var.name: var.read_value() for var in model.non_trainable_variables})
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:7: UserWarning: `tf.layers.batch_normalization` is deprecated and will be removed in a future version. Please use `tf.keras.layers.BatchNormalization` instead. In particular, `tf.control_dependencies(tf.GraphKeys.UPDATE_OPS)` should not be used (consult the `tf.keras.layers.BatchNormalization` documentation).
  import sys
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/normalization.py:463: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  return layer.apply(inputs, training=training)
Constructing model
Forward pass called with `training` = None
Calling model in inference mode
Forward pass called with `training` = False
Moving average variables before training:  {'batch_norm_layer/batch_normalization/moving_mean:0': <tf.Tensor: shape=(5,), dtype=float32, numpy=array([0., 0., 0., 0., 0.], dtype=float32)>, 'batch_norm_layer/batch_normalization/moving_variance:0': <tf.Tensor: shape=(5,), dtype=float32, numpy=array([1., 1., 1., 1., 1.], dtype=float32)>}
calling model in training mode
Forward pass called with `training` = True
Moving average variables after training:  {'batch_norm_layer/batch_normalization/moving_mean:0': <tf.Tensor: shape=(5,), dtype=float32, numpy=
array([-0.00177554, -0.00036542, -0.00099426, -0.00112544,  0.0008541 ],
      dtype=float32)>, 'batch_norm_layer/batch_normalization/moving_variance:0': <tf.Tensor: shape=(5,), dtype=float32, numpy=
array([1.0005339, 1.0003369, 0.9976748, 1.0001523, 1.0009514],
      dtype=float32)>}

変数スコープベースの変数の再利用

基づいて往路内の任意の変数の作品get_variable 、変数のスコープがTF1.x.に持っているのと同じ変数の命名と再利用のセマンティクスを維持しますこれは長い間、あなたが任意のための少なくとも1つの非空で外側のスコープ持っているとしてとして真であるtf.compat.v1.layers上述したように、自動生成された名前を持つが。

イーガー実行& tf.function

上記から分かるように、方法飾らtf.keras.layers.Layertf.Module熱心な実行の実行の内部を、またと互換性がありtf.function 。この手段を使用でき、PDB 、それが実行されているとして、あなたの往路を通じてのステップにして、他の対話型ツールを。

流通戦略

呼び出しget_variableの内部@track_tf1_style_variables -decorated層またはモジュール方法は、標準的な使用tf.Variableフード下変数作品を。これは、あなたがで使用できるさまざまな流通戦略でそれらを使用できることを意味しますtf.distributeなどMirroredStrategyTPUStrategy

ネストtf.Variable秒、 tf.Module秒、 tf.keras.layerstf.keras.models飾ら通話中

であなたの層のコールを飾るtf.compat.v1.keras.utils.track_tf1_style_variablesのみを使用して作成(および再利用)変数の自動暗黙の追跡を追加しますtf.compat.v1.get_variable 。それは直接によって作成された重みをキャプチャしませんtf.Variable典型的なKeras層と最もによって使用されるものとして呼び出し、 tf.Module秒。このセクションでは、これらのネストされたケースを処理する方法について説明します。

(プレ既存の用途) tf.keras.layerstf.keras.models

ネストされたKeras層とモデルの既存の用途のために、使用しtf.compat.v1.keras.utils.get_or_create_layer 。これは、既存のTF1.xネストされたKerasの使用法の移行を容易にする場合にのみ推奨されます。新しいコードでは、tf.Variablesとtf.Modulesについて以下で説明する明示的な属性設定を使用する必要があります。

使用するにはtf.compat.v1.keras.utils.get_or_create_layer 、方法にあなたのネストされたモデルを構築するコードをラップし、メソッドに渡します。例:

class NestedModel(tf.keras.Model):

  def __init__(self, units, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.units = units

  def build_model(self):
    inp = tf.keras.Input(shape=(5, 5))
    dense_layer = tf.keras.layers.Dense(
        10, name="dense", kernel_regularizer="l2",
        kernel_initializer=tf.compat.v1.ones_initializer())
    model = tf.keras.Model(inputs=inp, outputs=dense_layer(inp))
    return model

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs):
    # Get or create a nested model without assigning it as an explicit property
    model = tf.compat.v1.keras.utils.get_or_create_layer(
        "dense_model", self.build_model)
    return model(inputs)

layer = NestedModel(10)
layer(tf.ones(shape=(5,5)))
<tf.Tensor: shape=(5, 10), dtype=float32, numpy=
array([[5., 5., 5., 5., 5., 5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5., 5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5., 5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5., 5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5., 5., 5., 5., 5., 5.]], dtype=float32)>

このメソッドは、これらのネストされたレイヤーがテンソルフローによって正しく再利用および追跡されることを保証します。ことを注意@track_tf1_style_variablesデコレータがまだ適切な方法で必要とされます。渡されるモデルビルダー方法get_or_create_layer (この場合は、 self.build_model )、引数を取るべきではありません。

重みが追跡されます:

assert len(layer.weights) == 2
weights = {x.name: x for x in layer.variables}

assert set(weights.keys()) == {"dense/bias:0", "dense/kernel:0"}

layer.weights
[<tf.Variable 'dense/kernel:0' shape=(5, 10) dtype=float32, numpy=
 array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float32)>,
 <tf.Variable 'dense/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>]

そして正則化の損失も:

tf.add_n(layer.losses)
<tf.Tensor: shape=(1,), dtype=float32, numpy=array([0.5], dtype=float32)>

段階的な移行: tf.Variablestf.Modules

あなたは埋め込む必要がある場合はtf.Variableコールやtf.Module (たとえば、あなたが非レガシーTF2 APIへの段階的な移行を以下している場合は、このガイドで後述する)あなたの装飾が施された方法でsのを、あなたはまだ明示的にこれらを追跡する必要があります、次の要件があります。

  • 変数/モジュール/レイヤーが1回だけ作成されることを明示的に確認してください
  • インスタンスはあなたが定義するだろうというときと同じように属性として明示的にそれらを添付する典型的なモジュールまたは層を
  • 後続の呼び出しで、作成済みのオブジェクトを明示的に再利用します

これにより、ウェイトが呼び出しごとに新しく作成されたり、正しく再利用されたりすることがなくなります。さらに、これにより、既存の重みと正則化の損失が確実に追跡されます。

これがどのように見えるかの例を次に示します。

class NestedLayer(tf.keras.layers.Layer):

  def __init__(self, units, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.units = units

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def __call__(self, inputs):
    out = inputs
    with tf.compat.v1.variable_scope("inner_dense"):
      # The weights are created with a `regularizer`,
      # so the layer should track their regularization losses
      kernel = tf.compat.v1.get_variable(
          shape=[out.shape[-1], self.units],
          regularizer=tf.keras.regularizers.L2(),
          initializer=tf.compat.v1.initializers.glorot_normal,
          name="kernel")
      bias = tf.compat.v1.get_variable(
          shape=[self.units,],
          initializer=tf.compat.v1.initializers.zeros,
          name="bias")
      out = tf.linalg.matmul(out, kernel)
      out = tf.compat.v1.nn.bias_add(out, bias)
    return out

class WrappedDenseLayer(tf.keras.layers.Layer):

  def __init__(self, units, **kwargs):
    super().__init__(**kwargs)
    self.units = units
    # Only create the nested tf.variable/module/layer/model
    # once, and then reuse it each time!
    self._dense_layer = NestedLayer(self.units)

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs):
    with tf.compat.v1.variable_scope('outer'):
      outputs = tf.compat.v1.layers.dense(inputs, 3)
      outputs = tf.compat.v1.layers.dense(inputs, 4)
      return self._dense_layer(outputs)

layer = WrappedDenseLayer(10)

layer(tf.ones(shape=(5, 5)))
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:38: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:39: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
<tf.Tensor: shape=(5, 10), dtype=float32, numpy=
array([[-0.4987283 ,  0.06630042, -0.09875254,  0.20954818,  0.03599668,
         0.3980474 ,  0.11181635,  0.6891558 , -0.33903462,  0.15674731],
       [-0.4987283 ,  0.06630042, -0.09875254,  0.20954818,  0.03599668,
         0.3980474 ,  0.11181635,  0.6891558 , -0.33903462,  0.15674731],
       [-0.4987283 ,  0.06630042, -0.09875254,  0.20954818,  0.03599668,
         0.3980474 ,  0.11181635,  0.6891558 , -0.33903462,  0.15674731],
       [-0.4987283 ,  0.06630042, -0.09875254,  0.20954818,  0.03599668,
         0.3980474 ,  0.11181635,  0.6891558 , -0.33903462,  0.15674731],
       [-0.4987283 ,  0.06630042, -0.09875254,  0.20954818,  0.03599668,
         0.3980474 ,  0.11181635,  0.6891558 , -0.33903462,  0.15674731]],
      dtype=float32)>

それが飾られていても、ネストされたモジュールの明示的なトラッキングが必要であることに注意してくださいtrack_tf1_style_variablesデコレータ。これは、装飾されたメソッドを持つ各モジュール/レイヤーに独自の変数ストアが関連付けられているためです。

重みは正しく追跡されます:

assert len(layer.weights) == 6
weights = {x.name: x for x in layer.variables}

assert set(weights.keys()) == {"outer/inner_dense/bias:0",
                               "outer/inner_dense/kernel:0",
                               "outer/dense/bias:0",
                               "outer/dense/kernel:0",
                               "outer/dense_1/bias:0",
                               "outer/dense_1/kernel:0"}

layer.trainable_weights
[<tf.Variable 'outer/inner_dense/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>,
 <tf.Variable 'outer/inner_dense/kernel:0' shape=(4, 10) dtype=float32, numpy=
 array([[-0.20786692,  0.14702448, -0.2577947 ,  0.1885891 ,  0.28935957,
          0.02086618, -0.20579144, -0.7509229 , -0.23490003,  0.00370591],
        [ 0.09247629, -0.37428686, -0.6002815 , -0.2702465 ,  0.20350575,
          0.34964404, -0.32633537,  0.50722903, -0.0419833 , -0.61815673],
        [ 0.24821116,  0.15504731, -0.12409697, -0.2506969 ,  0.22316858,
         -0.44847375, -0.08295754, -0.8262154 ,  0.7674222 , -0.40613693],
        [-0.7447006 ,  0.2992331 , -0.45639235,  0.0669547 ,  0.39443025,
          0.3182467 ,  0.10884362,  0.5395837 ,  0.32210502, -0.30076835]],
       dtype=float32)>,
 <tf.Variable 'outer/dense/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>,
 <tf.Variable 'outer/dense/kernel:0' shape=(5, 3) dtype=float32, numpy=
 array([[ 0.6283595 , -0.80413634, -0.5471641 ],
        [ 0.25296038, -0.7657203 ,  0.5884425 ],
        [-0.7180575 , -0.29509914,  0.44014376],
        [ 0.81024987,  0.39888996,  0.80002993],
        [-0.32921118, -0.7010279 ,  0.820375  ]], dtype=float32)>,
 <tf.Variable 'outer/dense_1/bias:0' shape=(4,) dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>,
 <tf.Variable 'outer/dense_1/kernel:0' shape=(5, 4) dtype=float32, numpy=
 array([[ 0.7941524 , -0.58552563,  0.46828055, -0.44095916],
        [-0.16019303,  0.27973688, -0.60373306, -0.20117629],
        [ 0.6345844 ,  0.30732214,  0.18921828,  0.37930095],
        [-0.50815696, -0.2471816 , -0.10282421,  0.21441567],
        [-0.71987414,  0.18304104, -0.5701992 ,  0.4926386 ]],
       dtype=float32)>]

正則化の損失と同様に:

layer.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.058749676>]

場合ことを注意NestedLayer非Kerasたtf.Module代わりに、変数がまだ追跡するだろうが、あなたが明示的にそれらを個別に追跡する必要がありますので、正則損失を自動的に追跡されません。

変数名に関するガイダンス

明示的なtf.VariableコールとKeras層を使用すると、の組み合わせからに使用することができるとは異なる層名/変数名の自動生成メカニズムを使用get_variablevariable_scopes 。シムは、あなたの変数名により作成変数に対して一致するようになりますが、 get_variable TF1.xグラフからTF2熱心実行&に行くときにもtf.function 、それがために生成された変数名に対して同じことを保証することはできませんtf.VariableことをコールとKeras層メソッドデコレータ内に埋め込みます。複数の変数がTF2熱心実行と同じ名前を共有することさえ可能ですtf.function

このガイドの後半で、正確性の検証とTF1.xチェックポイントのマッピングに関するセクションに従う場合は、これに特に注意する必要があります。

使用tf.compat.v1.make_template飾ら方法で

非常にあなたが直接使用することをお勧めしますtf.compat.v1.keras.utils.track_tf1_style_variables代わりに使用してのtf.compat.v1.make_template 、それがTF2の上に薄い層があるとして、。

すでにに頼った前TF1.xコードについては、このセクションのガイダンスに従ってtf.compat.v1.make_template

のでtf.compat.v1.make_template使用するラップコードget_variabletrack_tf1_style_variablesデコレータを使用すると、レイヤーの呼び出しでこれらのテンプレートを使用して成功した重みと正則損失を追跡することができます。

しかし、コールに確認してくださいmake_template一度だけして、それぞれの層の呼び出しで同じテンプレートを再利用します。それ以外の場合は、新しい変数のセットとともにレイヤーを呼び出すたびに、新しいテンプレートが作成されます。

例えば、

class CompatV1TemplateScaleByY(tf.keras.layers.Layer):

  def __init__(self, **kwargs):
    super().__init__(**kwargs)
    def my_op(x, scalar_name):
      var1 = tf.compat.v1.get_variable(scalar_name,
                            shape=[],
                            regularizer=tf.compat.v1.keras.regularizers.L2(),
                            initializer=tf.compat.v1.constant_initializer(1.5))
      return x * var1
    self.scale_by_y = tf.compat.v1.make_template('scale_by_y', my_op, scalar_name='y')

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs):
    with tf.compat.v1.variable_scope('layer'):
      # Using a scope ensures the `scale_by_y` name will not be incremented
      # for each instantiation of the layer.
      return self.scale_by_y(inputs)

layer = CompatV1TemplateScaleByY()

out = layer(tf.ones(shape=(2, 3)))
print("weights:", layer.weights)
print("regularization loss:", layer.losses)
print("output:", out)
weights: [<tf.Variable 'layer/scale_by_y/y:0' shape=() dtype=float32, numpy=1.5>]
regularization loss: [<tf.Tensor: shape=(), dtype=float32, numpy=0.022499999>]
output: tf.Tensor(
[[1.5 1.5 1.5]
 [1.5 1.5 1.5]], shape=(2, 3), dtype=float32)

ネイティブTF2への増分移行

前述したように、 track_tf1_style_variablesあなたがTF2スタイルのオブジェクト指向ミックスすることができますtf.Variable / tf.keras.layers.Layer / tf.Moduleレガシーでの使用tf.compat.v1.get_variable / tf.compat.v1.layersスタイルを同じ装飾されたモジュール/レイヤー内での使用。

あなたはTF1.xモデルが完全に-TF2互換行った後、あなたはネイティブ(非ですべての新しいモデルのコンポーネントを書くことができることをこれは意味tf.compat.v1 )TF2 APIとそれらをあなたの古いコードとの相互運用性があります。

あなたは、古いモデルのコンポーネントを変更し続ける場合は、あなたはまた、インクリメンタルレガシースタイルの切り替えすることもできますtf.compat.v1書き下ろしTF2コードのために推奨されている純粋なネイティブオブジェクト指向のAPIに上の使用状況を。

tf.compat.v1.get_variable使い方はどちらかと交換することができるself.add_weightあなたはKeras層/モデルを飾るか、とされている場合の通話tf.Variable呼び出しあなたが飾っている場合Kerasオブジェクトまたはtf.Module秒。

機能的なスタイルとオブジェクト指向の両方tf.compat.v1.layers 、一般的に同等に置き換えることができtf.keras.layers必要な引数なしの変化を有する層。

あなたはまた、自身が使用することができ、純粋に、ネイティブAPIへのごインクリメンタル移動中に、個々の層/モジュールにあなたのモデルや一般的なパターンの塊の部分を考慮することができるtrack_tf1_style_variables

Slimとcontrib.layersに関するメモ

古いTF 1.xのコードの大量使用スリムとしてTFの1.1と一緒にパッケージ化されたライブラリ、 tf.contrib.layers 。ネイティブTF 2にスリムを使用してコードを変換する変換よりも複雑であるv1.layers 。実際には、それはあなたにスリムコードを変換しても意味がありv1.layers Kerasに変換、その後、最初に。以下は、スリムコードを変換するための一般的なガイダンスです。

  • すべての引数が明示的であることを確認してください。削除arg_scopes可能な場合。あなたはまだそれらを使用する必要がある場合は、分割normalizer_fnactivation_fn自身の層に。
  • 分離可能なconvレイヤーは、1つ以上の異なるKerasレイヤー(深さ方向、点方向、および分離可能なKerasレイヤー)にマップされます。
  • スリムでv1.layers異なる引数名とデフォルト値を持っています。
  • 一部の引数のスケールが異なることに注意してください。

チェックポイントの互換性を無視したネイティブTF2への移行

次のコードサンプルは、チェックポイントの互換性を考慮せずに、モデルを純粋にネイティブなAPIに段階的に移行する方法を示しています。

class CompatModel(tf.keras.layers.Layer):

  def __init__(self, units, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.units = units

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs, training=None):
    with tf.compat.v1.variable_scope('model'):
      out = tf.compat.v1.layers.conv2d(
          inputs, 3, 3,
          kernel_regularizer="l2")
      out = tf.compat.v1.layers.flatten(out)
      out = tf.compat.v1.layers.dropout(out, training=training)
      out = tf.compat.v1.layers.dense(
          out, self.units,
          kernel_regularizer="l2")
      return out

次に、交換compat.v1区分的に、ネイティブオブジェクト指向の当量のAPIを。畳み込みレイヤーを、レイヤーコンストラクターで作成されたKerasオブジェクトに切り替えることから始めます。

class PartiallyMigratedModel(tf.keras.layers.Layer):

  def __init__(self, units, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.units = units
    self.conv_layer = tf.keras.layers.Conv2D(
      3, 3,
      kernel_regularizer="l2")

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs, training=None):
    with tf.compat.v1.variable_scope('model'):
      out = self.conv_layer(inputs)
      out = tf.compat.v1.layers.flatten(out)
      out = tf.compat.v1.layers.dropout(out, training=training)
      out = tf.compat.v1.layers.dense(
          out, self.units,
          kernel_regularizer="l2")
      return out

使用v1.keras.utils.DeterministicRandomTestToolこの増分変化の葉前と同じ振る舞いを持つモデルであることを確認するためにクラスを。

random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  layer = CompatModel(10)

  inputs = tf.random.normal(shape=(10, 5, 5, 5))
  original_output = layer(inputs)

  # Grab the regularization loss as well
  original_regularization_loss = tf.math.add_n(layer.losses)

print(original_regularization_loss)
tf.Tensor(0.17953834, shape=(), dtype=float32)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:12: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
  if sys.path[0] == '':
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:13: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead.
  del sys.path[0]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:14: UserWarning: `tf.layers.dropout` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dropout` instead.
  
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/core.py:413: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  return layer.apply(inputs, training=training)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:17: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  layer = PartiallyMigratedModel(10)

  inputs = tf.random.normal(shape=(10, 5, 5, 5))
  migrated_output = layer(inputs)

  # Grab the regularization loss as well
  migrated_regularization_loss = tf.math.add_n(layer.losses)

print(migrated_regularization_loss)
tf.Tensor(0.17953834, shape=(), dtype=float32)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:14: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead.
  
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:15: UserWarning: `tf.layers.dropout` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dropout` instead.
  from ipykernel import kernelapp as app
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:18: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
# Verify that the regularization loss and output both match
np.testing.assert_allclose(original_regularization_loss.numpy(), migrated_regularization_loss.numpy())
np.testing.assert_allclose(original_output.numpy(), migrated_output.numpy())

あなたは今、個々のすべて交換したcompat.v1.layersネイティブKeras層で。

class NearlyFullyNativeModel(tf.keras.layers.Layer):

  def __init__(self, units, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.units = units
    self.conv_layer = tf.keras.layers.Conv2D(
      3, 3,
      kernel_regularizer="l2")
    self.flatten_layer = tf.keras.layers.Flatten()
    self.dense_layer = tf.keras.layers.Dense(
      self.units,
      kernel_regularizer="l2")

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs):
    with tf.compat.v1.variable_scope('model'):
      out = self.conv_layer(inputs)
      out = self.flatten_layer(out)
      out = self.dense_layer(out)
      return out
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  layer = NearlyFullyNativeModel(10)

  inputs = tf.random.normal(shape=(10, 5, 5, 5))
  migrated_output = layer(inputs)

  # Grab the regularization loss as well
  migrated_regularization_loss = tf.math.add_n(layer.losses)

print(migrated_regularization_loss)
tf.Tensor(0.17953834, shape=(), dtype=float32)
# Verify that the regularization loss and output both match
np.testing.assert_allclose(original_regularization_loss.numpy(), migrated_regularization_loss.numpy())
np.testing.assert_allclose(original_output.numpy(), migrated_output.numpy())

最後に、残りの(非長い必要)の両方削除variable_scope使用とtrack_tf1_style_variables自身をデコレータです。

これで、完全にネイティブAPIを使用するモデルのバージョンが残ります。

class FullyNativeModel(tf.keras.layers.Layer):

  def __init__(self, units, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.units = units
    self.conv_layer = tf.keras.layers.Conv2D(
      3, 3,
      kernel_regularizer="l2")
    self.flatten_layer = tf.keras.layers.Flatten()
    self.dense_layer = tf.keras.layers.Dense(
      self.units,
      kernel_regularizer="l2")

  def call(self, inputs):
    out = self.conv_layer(inputs)
    out = self.flatten_layer(out)
    out = self.dense_layer(out)
    return out
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
  layer = FullyNativeModel(10)

  inputs = tf.random.normal(shape=(10, 5, 5, 5))
  migrated_output = layer(inputs)

  # Grab the regularization loss as well
  migrated_regularization_loss = tf.math.add_n(layer.losses)

print(migrated_regularization_loss)
tf.Tensor(0.17953834, shape=(), dtype=float32)
# Verify that the regularization loss and output both match
np.testing.assert_allclose(original_regularization_loss.numpy(), migrated_regularization_loss.numpy())
np.testing.assert_allclose(original_output.numpy(), migrated_output.numpy())

ネイティブTF2への移行中にチェックポイントの互換性を維持する

上記のネイティブTF2APIへの移行プロセスでは、変数名(Keras APIが非常に異なる重み名を生成するため)と、モデル内の異なる重みを指すオブジェクト指向パスの両方が変更されました。これらの変更の影響は、既存のTF1スタイルの名前ベースのチェックポイントまたはTF2スタイルのオブジェクト指向チェックポイントの両方を破壊することです。

しかし、いくつかのケースでは、あなたの元の名前ベースのチェックポイントを取り、で詳述したようなアプローチとその新しい名前に変数のマッピングを見つけることができるかもしれない再利用TF1.xチェックポイントガイド

これを実現するためのヒントは次のとおりです。

  • 変数は、まだすべて持っているnameユーザーが設定できる引数を。
  • Kerasモデルも取るname彼らは、変数の接頭辞として設定されているとして、引数を。
  • v1.name_scope関数は、変数名の接頭辞を設定するために使用することができます。これは非常に異なっているtf.variable_scope 。名前にのみ影響し、変数の追跡や再利用は行いません。

上記のポインタを念頭に置いて、次のコードサンプルは、チェックポイントを同時に更新しながら、モデルの一部を段階的に更新するためにコードに適応できるワークフローを示しています。

  1. 機能的なスタイルの切り替えによって開始tf.compat.v1.layersそのオブジェクト指向のバージョンに。
class FunctionalStyleCompatModel(tf.keras.layers.Layer):

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs, training=None):
    with tf.compat.v1.variable_scope('model'):
      out = tf.compat.v1.layers.conv2d(
          inputs, 3, 3,
          kernel_regularizer="l2")
      out = tf.compat.v1.layers.conv2d(
          out, 4, 4,
          kernel_regularizer="l2")
      out = tf.compat.v1.layers.conv2d(
          out, 5, 5,
          kernel_regularizer="l2")
      return out

layer = FunctionalStyleCompatModel()
layer(tf.ones(shape=(10, 10, 10, 10)))
[v.name for v in layer.weights]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:8: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
  
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:11: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
  # This is added back by InteractiveShellApp.init_path()
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:14: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
['model/conv2d/bias:0',
 'model/conv2d/kernel:0',
 'model/conv2d_1/bias:0',
 'model/conv2d_1/kernel:0',
 'model/conv2d_2/bias:0',
 'model/conv2d_2/kernel:0']
  1. 次は、によって作成compat.v1.layerオブジェクトと任意の変数割り当てcompat.v1.get_variableのプロパティとしてtf.keras.layers.Layer / tf.Module方法で装飾されているオブジェクトtrack_tf1_style_variables (注その任意のオブジェクト指向TF2スタイルチェックポイントは、変数名によるパスと新しいオブジェクト指向パスの両方を保存するようになりました)。
class OOStyleCompatModel(tf.keras.layers.Layer):

  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.conv_1 = tf.compat.v1.layers.Conv2D(
          3, 3,
          kernel_regularizer="l2")
    self.conv_2 = tf.compat.v1.layers.Conv2D(
          4, 4,
          kernel_regularizer="l2")

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs, training=None):
    with tf.compat.v1.variable_scope('model'):
      out = self.conv_1(inputs)
      out = self.conv_2(out)
      out = tf.compat.v1.layers.conv2d(
          out, 5, 5,
          kernel_regularizer="l2")
      return out

layer = OOStyleCompatModel()
layer(tf.ones(shape=(10, 10, 10, 10)))
[v.name for v in layer.weights]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:19: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
['model/conv2d/kernel:0',
 'model/conv2d/bias:0',
 'model/conv2d_1/kernel:0',
 'model/conv2d_1/bias:0',
 'model/conv2d_2/bias:0',
 'model/conv2d_2/kernel:0']
  1. この時点でロードされたチェックポイントを再保存して、変数名(compat.v1.layersの場合)またはオブジェクト指向オブジェクトグラフの両方でパスを保存します。
weights = {v.name: v for v in layer.weights}
assert weights['model/conv2d/kernel:0'] is layer.conv_1.kernel
assert weights['model/conv2d_1/bias:0'] is layer.conv_2.bias
  1. これで、オブジェクト指向のスワップアウトすることができますcompat.v1.layersまだ最近保存されたチェックポイントをロードすることができるというながらネイティブKeras層のために。あなたは残りのための変数名保つことを確認してくださいcompat.v1.layersまだ自動生成記録することにより、 variable_scopes置き換え層のを。これらの切り替えられたレイヤー/変数は、変数名パスではなく、チェックポイント内の変数へのオブジェクト属性パスのみを使用するようになりました。

一般的に、あなたはの使い方置き換えることができcompat.v1.get_variableすることによってプロパティに添付の変数に:

  • 使用してそれらを切り替えtf.Variable 、OR
  • 使用してそれらを更新tf.keras.layers.Layer.add_weight 。 1が行くには、あなたがすべての層をスイッチングしていない場合、これは残りのために自動生成層/変数の命名を変更することがありますcompat.v1.layers不足しているname引数を。そのような場合は、残りのための変数名に保つ必要がありますcompat.v1.layers手動で開くことによって同じと閉じvariable_scope削除に対応するcompat.v1.layerの生成スコープ名を。そうしないと、既存のチェックポイントからのパスが競合し、チェックポイントの読み込みが正しく動作しない可能性があります。
def record_scope(scope_name):
  """Record a variable_scope to make sure future ones get incremented."""
  with tf.compat.v1.variable_scope(scope_name):
    pass

class PartiallyNativeKerasLayersModel(tf.keras.layers.Layer):

  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.conv_1 = tf.keras.layers.Conv2D(
          3, 3,
          kernel_regularizer="l2")
    self.conv_2 = tf.keras.layers.Conv2D(
          4, 4,
          kernel_regularizer="l2")

  @tf.compat.v1.keras.utils.track_tf1_style_variables
  def call(self, inputs, training=None):
    with tf.compat.v1.variable_scope('model'):
      out = self.conv_1(inputs)
      record_scope('conv2d') # Only needed if follow-on compat.v1.layers do not pass a `name` arg
      out = self.conv_2(out)
      record_scope('conv2d_1') # Only needed if follow-on compat.v1.layers do not pass a `name` arg
      out = tf.compat.v1.layers.conv2d(
          out, 5, 5,
          kernel_regularizer="l2")
      return out

layer = PartiallyNativeKerasLayersModel()
layer(tf.ones(shape=(10, 10, 10, 10)))
[v.name for v in layer.weights]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:26: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead.
['partially_native_keras_layers_model/model/conv2d_13/kernel:0',
 'partially_native_keras_layers_model/model/conv2d_13/bias:0',
 'partially_native_keras_layers_model/model/conv2d_14/kernel:0',
 'partially_native_keras_layers_model/model/conv2d_14/bias:0',
 'model/conv2d_2/bias:0',
 'model/conv2d_2/kernel:0']

変数を作成した後、この段階でのチェックポイントを保存すると、それだけで現在利用可能なオブジェクトのパスを含むようになります。

あなたが削除のスコープ記録を確認しcompat.v1.layers 、残りの自動生成された重み名を維持するためにcompat.v1.layers

weights = set(v.name for v in layer.weights)
assert 'model/conv2d_2/kernel:0' in weights
assert 'model/conv2d_2/bias:0' in weights
  1. あなたはすべて交換したまで、上記の手順を繰り返しcompat.v1.layerscompat.v1.get_variable完全にネイティブ同等物を使用して、モデル内の秒。
class FullyNativeKerasLayersModel(tf.keras.layers.Layer):

  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.conv_1 = tf.keras.layers.Conv2D(
          3, 3,
          kernel_regularizer="l2")
    self.conv_2 = tf.keras.layers.Conv2D(
          4, 4,
          kernel_regularizer="l2")
    self.conv_3 = tf.keras.layers.Conv2D(
          5, 5,
          kernel_regularizer="l2")


  def call(self, inputs, training=None):
    with tf.compat.v1.variable_scope('model'):
      out = self.conv_1(inputs)
      out = self.conv_2(out)
      out = self.conv_3(out)
      return out

layer = FullyNativeKerasLayersModel()
layer(tf.ones(shape=(10, 10, 10, 10)))
[v.name for v in layer.weights]
['fully_native_keras_layers_model/model/conv2d_16/kernel:0',
 'fully_native_keras_layers_model/model/conv2d_16/bias:0',
 'fully_native_keras_layers_model/model/conv2d_17/kernel:0',
 'fully_native_keras_layers_model/model/conv2d_17/bias:0',
 'fully_native_keras_layers_model/model/conv2d_18/kernel:0',
 'fully_native_keras_layers_model/model/conv2d_18/bias:0']

新しく更新されたチェックポイントが期待どおりに動作することを確認するためにテストすることを忘れないでください。記載された技術の適用検証数値の正確ガイド正しく移行されたコードの実行を確実にするために、このプロセスの各増分ステップでは。

モデリングシムでカバーされていないTF1.xからTF2への動作変更の処理

モデリングシムは、変数、層、及びで作成した正則損失ことを確認することができ、このガイドで説明get_variabletf.compat.v1.layers 、およびvariable_scopeセマンティクスが熱心に実行し、使用するときに以前のように仕事を続けるtf.functionすることなく、コレクションに依存します。

これは、モデル、前方パスが頼ることができることをすべてTF1.x固有のセマンティクスをカバーしていません。場合によっては、シムだけではモデルのフォワードパスをTF2で実行するには不十分なことがあります。読むTF2行動ガイド対TF1.xをTF1.xとTF2間の動作の違いについての詳細を学ぶために。