از مدل‌های TF1.x در گردش‌های کاری TF2 استفاده کنید

مشاهده در TensorFlow.org در Google Colab اجرا شود در GitHub مشاهده کنید دانلود دفترچه یادداشت

این راهنما یک نمای کلی و نمونه‌هایی از شیم کد مدل‌سازی را ارائه می‌کند که می‌توانید برای استفاده از مدل‌های TF1.x موجود خود در گردش‌های کاری TF2 مانند اجرای مشتاقانه، tf.function و استراتژی‌های توزیع با حداقل تغییرات در کد مدل‌سازی خود استفاده کنید.

دامنه استفاده

شیم توضیح داده شده در این راهنما برای مدل های TF1.x طراحی شده است که به موارد زیر متکی هستند:

  1. tf.compat.v1.get_variable و tf.compat.v1.variable_scope برای کنترل ایجاد و استفاده مجدد متغیر، و
  2. APIهای مبتنی بر گراف مانند tf.compat.v1.global_variables() , tf.compat.v1.trainable_variables , tf.compat.v1.losses.get_regularization_losses() و tf.compat.v1.get_collection() برای پیگیری کاهش وزن و تنظیم

این شامل اکثر مدل‌های ساخته شده روی tf.compat.v1.layer ، tf.contrib.layers API و TensorFlow-Slim می‌شود.

شیم برای مدل های TF1.x زیر ضروری نیست :

  1. مدل‌های کراس مستقل که قبلاً تمام وزن‌های قابل تمرین و تلفات منظم خود را به ترتیب از طریق model.trainable_weights و model.losses می‌کنند.
  2. tf.Module هایی که قبلاً تمام وزن های قابل آموزش خود را از طریق 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.Layer و tf.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 در متد تزئین شده ایجاد شده یا به آن دسترسی پیدا کرده‌اند، ردیابی کند.

علاوه بر ردیابی خود وزن ها در زیر لایه استاندارد/ module.variable layer.variable etc. خواص، اگر متد متعلق به یک tf.keras.layers.Layer ، آنگاه هر ضرر تنظیمی که از طریق آرگومان های تنظیم کننده get_variable یا tf.compat.v1.layers مشخص شده باشد توسط لایه تحت خاصیت layer.losses استاندارد ردیابی می شود.

این مکانیسم ردیابی امکان استفاده از کلاس‌های بزرگی از کدهای مدل-گذر به جلو به سبک TF1.x را در داخل لایه‌های Keras یا 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>]

به‌روزرسانی‌های عادی‌سازی دسته‌ای و args 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 نیاز دارد (به طور کلی هنگام استفاده از لایه های عادی سازی دسته ای TF-Slim is_training نامیده می شود)

در TF2، به دلیل اجرای مشتاقانه و وابستگی های کنترل خودکار، به روز رسانی های میانگین متحرک نرمال سازی دسته ای بلافاصله اجرا می شود. نیازی به جمع آوری جداگانه آنها از مجموعه به روز رسانی ها و اضافه کردن آنها به عنوان وابستگی های کنترل صریح نیست.

به‌علاوه، اگر به روش عبور به جلو tf.keras.layers.Layer یک آرگومان training بدهید، Keras می‌تواند فاز آموزشی فعلی و هر لایه‌ی تودرتو را به آن منتقل کند، درست مانند هر لایه دیگر. برای اطلاعات بیشتر در مورد اینکه Keras چگونه آرگومان training را مدیریت می کند، به اسناد API برای tf.keras.Model مراجعه کنید.

اگر روش‌های 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 دارد. این درست است تا زمانی که شما حداقل یک محدوده بیرونی غیر خالی برای هر tf.compat.v1.layers با نام های تولید شده خودکار، همانطور که در بالا ذکر شد، داشته باشید.

اجرای مشتاق و tf.function

همانطور که در بالا مشاهده شد، متدهای تزئین شده برای tf.keras.layers.Layer و tf.Module در داخل اجرای مشتاق اجرا می شوند و همچنین با tf.function سازگار هستند. این به این معنی است که می توانید از pdf و سایر ابزارهای تعاملی برای عبور از پاس خود در حین اجرا استفاده کنید.

استراتژی های توزیع

فراخوانی به get_variable در داخل @track_tf1_style_variables -decorated لایه یا روش های ماژول از ایجاد متغیرهای استاندارد tf.Variable در زیر هود استفاده می کند. این بدان معنی است که می توانید از آنها با استراتژی های توزیع مختلف موجود با tf.distribute مانند MirroredStrategy و TPUStrategy استفاده کنید.

tf.Variabletf.Moduletf.keras.layers و tf.keras.models در تماس های تزئین شده

تزئین تماس لایه خود در tf.compat.v1.keras.utils.track_tf1_style_variables فقط ردیابی ضمنی خودکار متغیرهای ایجاد شده (و استفاده مجدد) از طریق tf.compat.v1.get_variable را اضافه می کند. وزن‌هایی که مستقیماً توسط تماس‌های tf.Variable ایجاد می‌شوند را نمی‌گیرد، مانند وزن‌هایی که توسط لایه‌های Keras معمولی و بیشتر tf.Module . این بخش نحوه رسیدگی به این موارد تودرتو را شرح می دهد.

(کاربردهای قبلی) tf.keras.layers و tf.keras.models

برای استفاده های قبلی از لایه ها و مدل های Keras تودرتو، از tf.compat.v1.keras.utils.get_or_create_layer استفاده کنید. این فقط برای تسهیل مهاجرت استفاده‌های Keras تودرتوی موجود TF1.x توصیه می‌شود. کد جدید باید از تنظیمات مشخصه مشخص همانطور که در زیر برای 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.Variables و tf.Modules

اگر می‌خواهید تماس‌های tf.Variable یا tf.Module s را در روش‌های تزئین شده خود جاسازی کنید (به عنوان مثال، اگر مهاجرت تدریجی به APIهای غیر قدیمی TF2 که در ادامه در این راهنما توضیح داده شد را دنبال می‌کنید)، همچنان باید این موارد را به صراحت دنبال کنید. با شرایط زیر:

  • صریحاً مطمئن شوید که متغیر/ماژول/لایه فقط یک بار ایجاد شده است
  • همانطور که هنگام تعریف یک ماژول یا لایه معمولی ، آنها را به‌عنوان ویژگی‌های نمونه پیوست کنید
  • به صراحت از شی ایجاد شده در تماس های بعدی دوباره استفاده کنید

این تضمین می‌کند که وزن‌ها در هر تماس جدید ایجاد نمی‌شوند و به درستی دوباره استفاده می‌شوند. علاوه بر این، این تضمین می‌کند که وزن‌های موجود و کاهش‌های منظم ردیابی می‌شوند.

در اینجا مثالی از این است که چگونه می تواند به نظر برسد:

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 یک tf.Module غیر Keras بود، متغیرها همچنان ردیابی می‌شدند، اما تلفات منظم‌سازی به‌طور خودکار ردیابی نمی‌شد، بنابراین باید به‌صراحت آنها را جداگانه ردیابی کنید.

راهنمایی در مورد نام متغیرها

فراخوانی های صریح tf.Variable و لایه های Keras از مکانیزم تولید خودکار نام لایه / نام متغیر متفاوتی نسبت به آنچه ممکن است از ترکیب get_variable و variable_scopes کنید استفاده می کنند. اگرچه شیم نام متغیرهای شما را با متغیرهایی که توسط get_variable ایجاد می‌شوند مطابقت می‌دهد، حتی زمانی که از نمودارهای TF1.x به اجرای مشتاق TF2 و tf.function ، نمی‌تواند برای نام متغیرهای تولید شده برای تماس‌های tf.Variable و لایه‌های Keras که ایجاد می‌شوند، یکسان باشد. شما دکوراتورهای روش خود را تعبیه می کنید. حتی ممکن است چندین متغیر یک نام را در اجرای مشتاق TF2 و tf.function به اشتراک بگذارند.

هنگام دنبال کردن بخش های مربوط به تأیید صحت و نقشه برداری از نقاط بازرسی TF1.x در آینده در این راهنما، باید مراقب این موضوع باشید.

استفاده از tf.compat.v1.make_template در روش تزئین شده

به شدت توصیه می شود به جای استفاده از tf.compat.v1.make_template مستقیماً از tf.compat.v1.keras.utils.track_tf1_style_variables استفاده کنید، زیرا لایه نازک تری در بالای TF2 است.

دستورالعمل‌های این بخش را برای کد TF1.x قبلی که قبلاً به tf.compat.v1.make_template متکی بود، دنبال کنید.

از آنجایی که tf.compat.v1.make_template را می پیچد که از get_variable استفاده می کند، دکوراتور track_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)

مهاجرت افزایشی به Native TF2

همانطور که قبلاً ذکر شد، track_tf1_style_variables به شما امکان می دهد که tf.Variable / tf.keras.layers.Layer / tf.Module شی گرا سبک TF2 را با tf.Variable / tf.keras.layers.Layer tf.Module قدیمی tf.compat.v1.get_variable tf.compat.v1.layers . استفاده در داخل همان ماژول/لایه تزئین شده.

این بدان معناست که پس از اینکه مدل TF1.x خود را کاملاً با TF2 سازگار کردید، می توانید تمام اجزای مدل جدید را با API های بومی (non tf.compat.v1 ) TF2 بنویسید و از آنها بخواهید با کدهای قدیمی شما همکاری کنند.

با این حال، اگر به اصلاح مؤلفه‌های مدل قدیمی‌تر خود ادامه می‌دهید، می‌توانید استفاده از tf.compat.v1 به سبک قدیمی خود را نیز به‌صورت تدریجی به APIهای شی‌گرا کاملاً بومی که برای کد TF2 جدید نوشته شده توصیه می‌شوند، تغییر دهید.

استفاده از tf.compat.v1.get_variable را می‌توان با تماس‌های self.add_weight در صورتی که یک لایه/مدل Keras تزئین می‌کنید، یا با تماس‌های tf.Variable اگر در حال تزئین اشیاء Keras یا tf.Module s هستید، جایگزین کرد.

هر دو لایه tf.keras.layers tf.compat.v1.layers بدون نیاز به تغییر آرگومان جایگزین شوند.

همچنین می‌توانید بخش‌هایی از مدل یا الگوهای رایج خود را در طول حرکت تدریجی خود به APIهای کاملاً بومی، که ممکن است خودشان از track_tf1_style_variables استفاده کنند، در لایه‌ها/ماژول‌های جداگانه در نظر بگیرید.

یادداشتی در مورد لایه های Slim و contrib

مقدار زیادی از کدهای قدیمی TF 1.x از کتابخانه Slim استفاده می کند که با TF 1.x به عنوان tf.contrib.layers بسته بندی شده است. تبدیل کد با استفاده از Slim به Native TF 2 بیشتر از تبدیل v1.layers . در واقع، ممکن است منطقی باشد که ابتدا کد Slim خود را به v1.layers تبدیل کنید، سپس به Keras تبدیل کنید. در زیر چند راهنمایی کلی برای تبدیل کد اسلیم آورده شده است.

  • اطمینان حاصل کنید که همه استدلال ها صریح هستند. در صورت امکان arg_scopes را حذف کنید. اگر همچنان نیاز به استفاده از آنها دارید، normalizer_fn و activation_fn را به لایه های خود تقسیم کنید.
  • لایه‌های تبدیل قابل تفکیک به یک یا چند لایه Keras مختلف (لایه‌های Keras به صورت عمقی، نقطه‌ای و قابل جداسازی) نگاشت می‌شوند.
  • Slim و v1.layers نام‌های آرگومان و مقادیر پیش‌فرض متفاوتی دارند.
  • توجه داشته باشید که برخی از استدلال ها مقیاس های مختلفی دارند.

مهاجرت به Native 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

سپس، API های compat.v1 را با معادل های شی گرا بومی آن ها به صورت تکه ای جایگزین کنید. با تغییر لایه پیچشی به یک شی 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())

حفظ سازگاری ایست بازرسی در طول مهاجرت به Native TF2

فرآیند انتقال بالا به APIهای بومی TF2 هم نام متغیرها را تغییر داد (از آنجایی که APIهای Keras نام‌های وزنی بسیار متفاوتی تولید می‌کنند)، و هم مسیرهای شی گرا که به وزن‌های مختلف در مدل اشاره می‌کنند. تأثیر این تغییرات این است که آنها هر دو پست بازرسی مبتنی بر نام به سبک TF1 یا ایست های بازرسی شی گرا به سبک TF2 را شکسته اند.

با این حال، در برخی موارد، ممکن است بتوانید ایست بازرسی مبتنی بر نام اصلی خود را بردارید و با رویکردهایی مانند آنچه در راهنمای استفاده مجدد از TF1.x در راهنمای نقاط بازرسی توضیح داده شده است، نگاشت متغیرها را به نام جدیدشان بیابید.

برخی از نکات برای تحقق این امر به شرح زیر است:

  • همه متغیرها هنوز هم یک آرگومان name دارند که می توانید تنظیم کنید.
  • مدل‌های Keras نیز آرگومان name را به عنوان پیشوند برای متغیرهای خود تنظیم می‌کنند.
  • تابع v1.name_scope می تواند برای تنظیم پیشوندهای نام متغیر استفاده شود. این با tf.variable_scope بسیار متفاوت است. این فقط بر نام ها تأثیر می گذارد و متغیرها و استفاده مجدد را ردیابی نمی کند.

با در نظر گرفتن نکات بالا، نمونه کدهای زیر جریان کاری را نشان می‌دهند که می‌توانید با کد خود مطابقت دهید تا به‌طور تدریجی بخشی از یک مدل را به‌روزرسانی کنید و همزمان نقاط بازرسی را به‌روزرسانی کنید.

  1. با تغییر لایه های tf.compat.v1.layers -style به نسخه های شی گرا شروع کنید.
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. باقی‌مانده با ضبط compat.v1.layers variable_scopes خودکار لایه‌های جایگزین شده، حفظ کنید. این لایه ها/متغیرهای سوئیچ شده اکنون به جای مسیر نام متغیر، فقط از مسیر ویژگی شی برای متغیرهای موجود در چک پوینت استفاده می کنند.

به طور کلی، می‌توانید استفاده از compat.v1.get_variable در متغیرهای متصل به ویژگی‌ها جایگزین کنید:

  • آنها را به استفاده از tf.Variable ، OR تغییر دهید
  • به روز رسانی آنها با استفاده از tf.keras.layers.Layer.add_weight . توجه داشته باشید که اگر همه لایه‌ها را به یکباره تغییر نمی‌دهید، ممکن است نام‌گذاری لایه/متغیر به‌طور خودکار برای compat.v1.layers . باقی‌مانده که آرگومان name ندارند، تغییر کند. اگر چنین است، باید نام متغیرها را برای باقیمانده compat.v1.layers . با باز و بسته کردن دستی variable_scope 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. حذف‌شده را ضبط کرده‌اید تا نام وزن‌های تولید شده خودکار برای باقی‌مانده‌های 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.layers و compat.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_variable ، tf.compat.v1.layers و variable_scope ، بدون نیاز به استفاده از eager execution و tf.function ، مانند قبل کار می‌کنند. به مجموعه ها تکیه کنید

این همه معنایی خاص TF1.x را که ممکن است مدل شما بر آن تکیه کند، پوشش نمی دهد. در برخی موارد، شیم ها ممکن است برای اجرای خود به خود پاس مدل به جلو در TF2 کافی نباشد. راهنمای رفتارهای TF1.x در مقابل TF2 را بخوانید تا درباره تفاوت های رفتاری بین TF1.x و TF2 بیشتر بدانید.