استخدم نماذج TF1.x في مهام سير عمل TF2

عرض على TensorFlow.org تشغيل في Google Colab عرض على جيثب تحميل دفتر

يقدم هذا الدليل نظرة عامة وأمثلة لرقاقة رمز النمذجة التي يمكنك استخدامها لاستخدام نماذج TF1.x الحالية في تدفقات عمل TF2 مثل التنفيذ الجاد ، tf.function ، واستراتيجيات التوزيع مع الحد الأدنى من التغييرات في كود النمذجة.

نطاق الاستخدام

تم تصميم الرقاقة الموصوفة في هذا الدليل لنماذج TF1.x التي تعتمد على:

  1. tf.compat.v1.get_variable و tf.compat.v1.variable_scope للتحكم في الإنشاء المتغير وإعادة الاستخدام ، و
  2. واجهات برمجة التطبيقات القائمة على جمع الرسوم البيانية مثل 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 APIs و TensorFlow-Slim .

الرقاقة ليست ضرورية لنماذج TF1.x التالية:

  1. نماذج Keras المستقلة التي تتبع بالفعل جميع الأوزان القابلة للتدريب وخسائر التنظيم عبر 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 داخل الطريقة المزخرفة.

بالإضافة إلى تتبع الأوزان نفسها تحت الطبقة القياسية layer.variable / module.variable / إلخ. الخصائص ، إذا كانت الطريقة تنتمي إلى tf.keras.layers.Layer ، فسيتم تتبع أي خسائر تنظيم محددة عبر get_variable أو tf.compat.v1.layers بواسطة الطبقة الموجودة أسفل الخاصية layer.losses القياسية.

تتيح آلية التتبع هذه استخدام فئات كبيرة من رمز مرور إعادة التوجيه على غرار نموذج TF1.x داخل طبقات tf.Module أو وحدات tf في 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-Slim)

في TF2 ، نظرًا للتنفيذ الجاد وتبعيات التحكم التلقائي ، سيتم تنفيذ تحديثات متوسط ​​نقل تطبيع الدُفعة على الفور. ليست هناك حاجة لتجميعها بشكل منفصل من مجموعة التحديثات وإضافتها كاعتماديات تحكم صريحة.

بالإضافة إلى ذلك ، إذا أعطيت طريقة التمريرة الأمامية الخاصة 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. هذا صحيح طالما لديك نطاق خارجي واحد على الأقل غير فارغ لأي tf.compat.v1.layers تلقائيًا ، كما هو مذكور أعلاه.

تنفيذ حريص tf.function

كما رأينا أعلاه ، تعمل الطرق المزخرفة لـ tf.keras.layers.Layer و tf.Module داخل التنفيذ الحثيث وهي متوافقة أيضًا مع tf.function . هذا يعني أنه يمكنك استخدام pdb والأدوات التفاعلية الأخرى للمضي قدمًا خلال التمريرات الأمامية أثناء تشغيلها.

استراتيجيات التوزيع

استدعاءات get_variable داخل @track_tf1_style_variables تستخدم أساليب الطبقة أو الوحدة النمطية القياسية tf.Variable المتغير المتغير إبداعات تحت الغطاء. هذا يعني أنه يمكنك استخدامها مع استراتيجيات التوزيع المختلفة المتاحة مع توزيع tf.distribute مثل MirroredStrategy و TPUStrategy .

تداخل tf.Variable s و tf.Module s و tf.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)>

تضمن هذه الطريقة إعادة استخدام هذه الطبقات المتداخلة وتعقبها بشكل صحيح بواسطة Tensorflow. لاحظ أن مصمم @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 tf.Modules و tf.Variables

إذا كنت بحاجة إلى تضمين tf.Variable calls أو tf.Module s في طرقك المزينة (على سبيل المثال ، إذا كنت تتابع الترحيل المتزايد إلى واجهات برمجة تطبيقات 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 عبارة عن وحدة غير Keras tf.Module بدلاً من ذلك ، فسيظل تتبع المتغيرات ولكن لن يتم تتبع خسائر التنظيم تلقائيًا ، لذلك سيتعين عليك تتبعها بشكل صريح بشكل منفصل.

إرشادات بشأن أسماء المتغيرات

صريحة tf. تستخدم المكالمات المتغيرة وطبقات tf.Variable آلية توليد تلقائي لاسم طبقة / اسم متغير مختلفة عما قد تستخدمه من مجموعة get_variable و variable_scopes . على الرغم من أن الرقاقة ستجعل أسماء المتغيرات الخاصة بك مطابقة للمتغيرات التي تم إنشاؤها بواسطة get_variable حتى عند الانتقال من الرسوم البيانية tf.function إلى وظيفة TF2 ، إلا أنها لا تضمن نفس الشيء بالنسبة لأسماء المتغيرات التي تم إنشاؤها من أجل tf.Variable calls and Keras Layers التي تقوم بتضمينها في ديكورات طريقتك. حتى أنه من الممكن لمتغيرات متعددة أن تشترك في نفس الاسم في وظيفة 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_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)

الهجرة المتزايدة إلى الأصلي TF2

كما ذكرنا سابقًا ، يسمح لك track_tf1_style_variables بخلط tf.Variable / tf.keras.layers.Layer / tf.Module مع استخدام tf.compat.v1.get_variable / tf.compat.v1.layers الاستخدام داخل نفس الوحدة / الطبقة المزخرفة.

هذا يعني أنه بعد أن تجعل نموذج TF1.x الخاص بك متوافقًا تمامًا مع TF2 ، يمكنك كتابة جميع مكونات النموذج الجديدة باستخدام واجهات برمجة تطبيقات TF2 أصلية (غير tf.compat.v1 ) وجعلها تتفاعل مع الكود القديم.

ومع ذلك ، إذا واصلت تعديل مكونات النموذج الأقدم ، فيمكنك أيضًا اختيار التبديل التدريجي لاستخدام tf.compat.v1 ذي النمط القديم إلى واجهات برمجة التطبيقات الأصلية الموجهة للكائن والتي يوصى بها لكود TF2 المكتوب حديثًا.

يمكن استبدال tf.compat.v1.get_variable باستخدام مكالمات self.add_weight إذا كنت تقوم بتزيين طبقة / نموذج tf.Variable أو بمكالمات متغيرة إذا كنت تزين كائنات Keras أو tf.Module s.

يمكن استبدال كل من tf.compat.v1.layers ذات النمط الوظيفي والموجّه للكائنات بشكل عام بطبقة tf.keras.layers المكافئة دون الحاجة إلى إجراء تغييرات في الوسيطة.

يمكنك أيضًا التفكير في أجزاء متقطعة من نموذجك أو أنماط شائعة في طبقات / وحدات فردية أثناء انتقالك المتزايد إلى واجهات برمجة التطبيقات الأصلية البحتة ، والتي قد تستخدم هي نفسها track_tf1_style_variables .

ملاحظة على Slim و Contrib.layer

يستخدم عدد كبير من كود TF 1.x الأقدم مكتبة Slim ، والتي تم تعبئتها مع TF 1.x مثل tf.contrib.layers . يعتبر تحويل الكود باستخدام Slim إلى أصلي TF 2 أكثر تعقيدًا من تحويل v1.layers . في الواقع ، قد يكون من المنطقي تحويل كود Slim الخاص بك إلى v1.layers أولاً ، ثم التحويل إلى Keras. فيما يلي بعض الإرشادات العامة لتحويل كود Slim.

  • تأكد من أن جميع الحجج صريحة. قم بإزالة arg_scopes إن أمكن. إذا كنت لا تزال بحاجة إلى استخدامها ، فقسّم normalizer_fn و activation_fn إلى طبقاتهما الخاصة.
  • ترسم طبقات التحويل المنفصلة إلى طبقة Keras مختلفة أو أكثر (طبقات Keras في العمق والنقطة وقابلة للفصل).
  • Slim و v1.layers لها أسماء وسيطات مختلفة وقيم افتراضية.
  • لاحظ أن بعض الحجج لها مقاييس مختلفة.

الهجرة إلى Native TF2 مع تجاهل توافق نقاط التفتيش

يوضح نموذج التعليمات البرمجية التالي نقلًا تزايديًا لنموذج إلى واجهات برمجة التطبيقات الأصلية البحتة دون مراعاة توافق نقاط التحقق.

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 واجهات برمجة تطبيقات التوافق مع نظيراتها الأصلية الموجهة للكائنات بطريقة متعددة الأجزاء. ابدأ بتبديل طبقة الالتفاف إلى كائن 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 الأصلية.

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 decorator نفسه.

لديك الآن إصدار من النموذج يستخدم واجهات برمجة تطبيقات أصلية بالكامل.

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 الأصلي

غيرت عملية الترحيل المذكورة أعلاه إلى واجهات برمجة تطبيقات TF2 الأصلية كلاً من أسماء المتغيرات (حيث تنتج Keras APIs أسماء أوزان مختلفة جدًا) والمسارات الموجهة للكائنات التي تشير إلى أوزان مختلفة في النموذج. إن تأثير هذه التغييرات هو أنها ستكسر كل من نقاط التفتيش القائمة على الاسم على غرار TF1 أو نقاط التفتيش القائمة على الكائنات على غرار TF2.

ومع ذلك ، في بعض الحالات ، قد تكون قادرًا على أخذ نقطة التحقق الأصلية القائمة على الاسم والعثور على تعيين للمتغيرات لأسمائها الجديدة باستخدام مناهج مثل تلك المفصلة في دليل Reuse TF1.x checkpoints .

فيما يلي بعض النصائح لجعل ذلك ممكنًا:

  • لا تزال جميع المتغيرات تحتوي على وسيطة 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. بعد ذلك ، عيِّن كائنات tf.Module وأي متغيرات تم إنشاؤها track_tf1_style_variables compat.v1.get_variable tf.keras.layers.Layer ستحفظ نقاط فحص النمط الآن كلا من المسار باسم المتغير والمسار الجديد الموجه للكائنات).
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. أعد حفظ نقطة فحص محملة في هذه المرحلة لحفظ المسارات من خلال اسم المتغير (لـ التوافق مع الطبقات) ، أو بواسطة الرسم البياني للكائن الموجه.
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 الأصلية بينما لا تزال قادرًا على تحميل نقطة التفتيش المحفوظة مؤخرًا. تأكد من أنك تحتفظ بأسماء متغيرة 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 يدويًا يتوافق مع اسم النطاق الذي تم إنشاؤه من برنامج 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.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 النطاق تستمر في العمل كما كان من قبل عند استخدام التنفيذ tf.function ، دون الحاجة إلى ذلك الاعتماد على المجموعات.

لا يغطي هذا جميع الدلالات الخاصة بـ TF1.x والتي قد تعتمد عليها التصاريح إلى الأمام في نموذجك. في بعض الحالات ، قد تكون الحشوات غير كافية لتشغيل التمريرات الأمامية لطرازك في TF2 من تلقاء نفسها. اقرأ دليل السلوكيات TF1.x vs TF2 لمعرفة المزيد حول الاختلافات السلوكية بين TF1.x و TF2.