عرض على TensorFlow.org | تشغيل في Google Colab | عرض على جيثب | تحميل دفتر |
يقدم هذا الدليل نظرة عامة وأمثلة لرقاقة رمز النمذجة التي يمكنك استخدامها لاستخدام نماذج TF1.x الحالية في تدفقات عمل TF2 مثل التنفيذ الجاد ، tf.function
، واستراتيجيات التوزيع مع الحد الأدنى من التغييرات في كود النمذجة.
نطاق الاستخدام
تم تصميم الرقاقة الموصوفة في هذا الدليل لنماذج TF1.x التي تعتمد على:
-
tf.compat.v1.get_variable
وtf.compat.v1.variable_scope
للتحكم في الإنشاء المتغير وإعادة الاستخدام ، و - واجهات برمجة التطبيقات القائمة على جمع الرسوم البيانية مثل
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 التالية:
- نماذج Keras المستقلة التي تتبع بالفعل جميع الأوزان القابلة للتدريب وخسائر التنظيم عبر
model.trainable_weights
وmodel.losses
على التوالي. -
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])
لاحظ أن:
- يتم تتبع تحديثات متوسط نقل تسوية الدفعات عن طريق
get_collection
والتي تم استدعاؤها بشكل منفصل عن الطبقة - يتطلب
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
. إنه يؤثر فقط على الأسماء ، ولا يتتبع المتغيرات ويعيد استخدامها.
مع وضع المؤشرات المذكورة أعلاه في الاعتبار ، توضح عينات التعليمات البرمجية التالية سير عمل يمكنك تكييفه مع التعليمات البرمجية الخاصة بك لتحديث جزء من النموذج بشكل تدريجي أثناء تحديث نقاط التحقق في نفس الوقت.
- ابدأ بتبديل
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']
- بعد ذلك ، عيِّن كائنات
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']
- أعد حفظ نقطة فحص محملة في هذه المرحلة لحفظ المسارات من خلال اسم المتغير (لـ التوافق مع الطبقات) ، أو بواسطة الرسم البياني للكائن الموجه.
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
- يمكنك الآن تبديل طبقة التوافقية الموجهة للكائنات بطبقات
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
- كرر الخطوات المذكورة أعلاه حتى تستبدل كل
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.