مشاهده در TensorFlow.org | در Google Colab اجرا شود | در GitHub مشاهده کنید | دانلود دفترچه یادداشت |
این راهنما یک نمای کلی و نمونههایی از شیم کد مدلسازی را ارائه میکند که میتوانید برای استفاده از مدلهای TF1.x موجود خود در گردشهای کاری TF2 مانند اجرای مشتاقانه، tf.function
و استراتژیهای توزیع با حداقل تغییرات در کد مدلسازی خود استفاده کنید.
دامنه استفاده
شیم توضیح داده شده در این راهنما برای مدل های TF1.x طراحی شده است که به موارد زیر متکی هستند:
-
tf.compat.v1.get_variable
وtf.compat.v1.variable_scope
برای کنترل ایجاد و استفاده مجدد متغیر، و - APIهای مبتنی بر گراف مانند
tf.compat.v1.global_variables()
,tf.compat.v1.trainable_variables
,tf.compat.v1.losses.get_regularization_losses()
وtf.compat.v1.get_collection()
برای پیگیری کاهش وزن و تنظیم
این شامل اکثر مدلهای ساخته شده روی tf.compat.v1.layer
، tf.contrib.layers
API و TensorFlow-Slim میشود.
شیم برای مدل های TF1.x زیر ضروری نیست :
- مدلهای کراس مستقل که قبلاً تمام وزنهای قابل تمرین و تلفات منظم خود را به ترتیب از طریق
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
در متد تزئین شده ایجاد شده یا به آن دسترسی پیدا کردهاند، ردیابی کند.
علاوه بر ردیابی خود وزن ها در زیر لایه استاندارد/ module.variable
layer.variable
etc. خواص، اگر متد متعلق به یک tf.keras.layers.Layer
، آنگاه هر ضرر تنظیمی که از طریق آرگومان های تنظیم کننده get_variable
یا tf.compat.v1.layers
مشخص شده باشد توسط لایه تحت خاصیت layer.losses
استاندارد ردیابی می شود.
این مکانیسم ردیابی امکان استفاده از کلاسهای بزرگی از کدهای مدل-گذر به جلو به سبک TF1.x را در داخل لایههای Keras یا tf.Module
در TF2 حتی با فعال بودن رفتارهای TF2 را ممکن میسازد.
نمونه های استفاده
مثالهای استفاده زیر، شیمهای مدلسازی مورد استفاده برای تزئین روشهای tf.keras.layers.Layer
را نشان میدهند، اما به جز مواردی که بهطور خاص با ویژگیهای Keras تعامل دارند، هنگام تزئین روشهای tf.Module
نیز قابل استفاده هستند.
لایه ساخته شده با tf.compat.v1.get_variable
تصور کنید یک لایه دارید که مستقیماً در بالای tf.compat.v1.get_variable
به صورت زیر پیاده سازی شده است:
def dense(self, inputs, units):
out = inputs
with tf.compat.v1.variable_scope("dense"):
# The weights are created with a `regularizer`,
kernel = tf.compat.v1.get_variable(
shape=[out.shape[-1], units],
regularizer=tf.keras.regularizers.L2(),
initializer=tf.compat.v1.initializers.glorot_normal,
name="kernel")
bias = tf.compat.v1.get_variable(
shape=[units,],
initializer=tf.compat.v1.initializers.zeros,
name="bias")
out = tf.linalg.matmul(out, kernel)
out = tf.compat.v1.nn.bias_add(out, bias)
return out
از شیم برای تبدیل آن به یک لایه و فراخوانی آن در ورودی استفاده کنید.
class DenseLayer(tf.keras.layers.Layer):
def __init__(self, units, *args, **kwargs):
super().__init__(*args, **kwargs)
self.units = units
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs):
out = inputs
with tf.compat.v1.variable_scope("dense"):
# The weights are created with a `regularizer`,
# so the layer should track their regularization losses
kernel = tf.compat.v1.get_variable(
shape=[out.shape[-1], self.units],
regularizer=tf.keras.regularizers.L2(),
initializer=tf.compat.v1.initializers.glorot_normal,
name="kernel")
bias = tf.compat.v1.get_variable(
shape=[self.units,],
initializer=tf.compat.v1.initializers.zeros,
name="bias")
out = tf.linalg.matmul(out, kernel)
out = tf.compat.v1.nn.bias_add(out, bias)
return out
layer = DenseLayer(10)
x = tf.random.normal(shape=(8, 20))
layer(x)
WARNING:tensorflow:From /tmp/ipykernel_27038/795621215.py:7: The name tf.keras.utils.track_tf1_style_variables is deprecated. Please use tf.compat.v1.keras.utils.track_tf1_style_variables instead. <tf.Tensor: shape=(8, 10), dtype=float32, numpy= array([[-0.51018804, -0.58145535, 0.25050664, -0.09880018, 0.71741414, -0.08512568, 0.33404148, 0.50894034, 0.19362557, 0.03945067], [-0.66160053, 0.43442816, -0.6187523 , 0.00753711, 1.3946855 , 0.22528797, 0.55661404, -1.6155301 , 1.5854199 , -0.4165327 ], [ 0.15855707, 0.43848652, 0.04762229, 0.22020248, 0.88300526, 0.31525093, -0.10912375, 0.03332198, 1.3462385 , -0.37986106], [ 0.02546233, -0.01084138, 0.0417656 , 1.1082407 , 0.926408 , 0.46938205, 1.0183189 , 1.2039868 , -0.09619217, -0.50863194], [-1.6222394 , 0.17156005, -0.07482994, 0.646423 , 1.0284312 , 2.3619173 , 0.6322627 , 0.5350776 , -2.2700598 , -0.8211552 ], [-1.1044651 , 0.7303245 , 1.0183476 , 1.2858934 , 0.4575533 , 0.93400717, 0.5323913 , -0.01242167, 0.8308919 , 0.03202473], [ 0.3880633 , -1.2345276 , 0.7713047 , -0.33720714, 1.0418141 , -1.055242 , -1.6942265 , 1.705035 , 0.8671215 , 0.8162696 ], [ 0.02216246, -0.5235669 , 0.01065174, -1.1682817 , 0.44079733, 0.25890222, -1.0779501 , 0.37716752, -0.27636313, -0.6359312 ]], dtype=float32)>
مانند یک لایه استاندارد Keras به متغیرهای ردیابی شده و تلفات منظم سازی ثبت شده دسترسی داشته باشید.
layer.trainable_variables
layer.losses
2021-12-04 02:24:42.941890: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. [<tf.Tensor: shape=(), dtype=float32, numpy=0.10789324>]
برای اینکه ببینید وزنها هر بار که لایه را فرا میخوانید دوباره استفاده میشوند، همه وزنها را صفر کنید و دوباره لایه را فراخوانی کنید.
print("Resetting variables to zero:", [var.name for var in layer.trainable_variables])
for var in layer.trainable_variables:
var.assign(var * 0.0)
# Note: layer.losses is not a live view and
# will get reset only at each layer call
print("layer.losses:", layer.losses)
print("calling layer again.")
out = layer(x)
print("layer.losses: ", layer.losses)
out
Resetting variables to zero: ['dense/bias:0', 'dense/kernel:0'] layer.losses: [<tf.Tensor: shape=(), dtype=float32, numpy=0.0>] calling layer again. layer.losses: [<tf.Tensor: shape=(), dtype=float32, numpy=0.0>] <tf.Tensor: shape=(8, 10), dtype=float32, numpy= array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>
شما می توانید لایه تبدیل شده را مستقیماً در ساخت مدل عملکردی Keras نیز استفاده کنید.
inputs = tf.keras.Input(shape=(20))
outputs = DenseLayer(10)(inputs)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
x = tf.random.normal(shape=(8, 20))
model(x)
# Access the model variables and regularization losses
model.weights
model.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.1345337>]
مدل ساخته شده با tf.compat.v1.layers
تصور کنید یک لایه یا مدل دارید که مستقیماً در بالای tf.compat.v1.layers
به صورت زیر پیاده سازی شده است:
def model(self, inputs, units):
with tf.compat.v1.variable_scope('model'):
out = tf.compat.v1.layers.conv2d(
inputs, 3, 3,
kernel_regularizer="l2")
out = tf.compat.v1.layers.flatten(out)
out = tf.compat.v1.layers.dense(
out, units,
kernel_regularizer="l2")
return out
از شیم برای تبدیل آن به یک لایه و فراخوانی آن در ورودی استفاده کنید.
class CompatV1LayerModel(tf.keras.layers.Layer):
def __init__(self, units, *args, **kwargs):
super().__init__(*args, **kwargs)
self.units = units
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs):
with tf.compat.v1.variable_scope('model'):
out = tf.compat.v1.layers.conv2d(
inputs, 3, 3,
kernel_regularizer="l2")
out = tf.compat.v1.layers.flatten(out)
out = tf.compat.v1.layers.dense(
out, self.units,
kernel_regularizer="l2")
return out
layer = CompatV1LayerModel(10)
x = tf.random.normal(shape=(8, 5, 5, 5))
layer(x)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:12: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. if sys.path[0] == '': /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/convolutional.py:575: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead. return layer.apply(inputs) /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:13: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead. del sys.path[0] /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/core.py:541: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead. return layer.apply(inputs) /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:16: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. app.launch_new_instance() /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/core.py:261: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead. return layer.apply(inputs) <tf.Tensor: shape=(8, 10), dtype=float32, numpy= array([[ 2.4439096 , -0.2912227 , 1.5531251 , 1.284059 , 0.10077369, -0.4231838 , 1.0458903 , -0.01530766, 0.07358164, -0.6108157 ], [-0.4576063 , 0.34942552, 2.3044965 , 1.1483003 , -1.2211238 , 0.5634397 , 0.73821646, -0.07581732, 0.5747937 , -0.66470885], [-2.2948585 , -2.709268 , 1.7494816 , -0.9808065 , -2.9099958 , 0.5067346 , -1.011502 , 2.559535 , -3.0888772 , 0.3522656 ], [ 1.7788265 , 0.8846102 , 0.45562026, 0.01498583, -0.12482446, -0.32868862, -0.7743829 , 2.3106992 , -0.0997327 , -0.7715093 ], [ 0.40295708, 0.04771695, -0.21336336, -0.13069987, 2.279875 , 2.7284563 , 0.6444641 , -1.1919906 , 0.96321577, 1.0182515 ], [ 0.47900966, 0.04906505, 1.1335449 , 0.2907704 , 0.7732022 , 0.68217 , 0.51932573, -0.45156685, 2.081223 , 1.068861 ], [ 0.10084352, 1.6456002 , 0.63820475, 1.5959243 , 0.22463399, 0.07713126, 0.7467398 , -1.5435244 , 1.2494736 , -0.07683721], [ 2.1396816 , 1.5613532 , -1.1726325 , -0.88917583, 1.6447946 , -1.0071977 , -1.8496083 , 1.1887017 , 2.1971662 , 2.1175954 ]], dtype=float32)>
مانند یک لایه استاندارد Keras به متغیرهای ردیابی شده و تلفات منظم سازی ثبت شده دسترسی داشته باشید.
layer.trainable_variables
layer.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.03623246>, <tf.Tensor: shape=(), dtype=float32, numpy=0.14618248>]
برای اینکه ببینید وزنها هر بار که لایه را فرا میخوانید دوباره استفاده میشوند، همه وزنها را صفر کنید و دوباره لایه را فراخوانی کنید.
print("Resetting variables to zero:", [var.name for var in layer.trainable_variables])
for var in layer.trainable_variables:
var.assign(var * 0.0)
out = layer(x)
print("layer.losses: ", layer.losses)
out
Resetting variables to zero: ['model/conv2d/bias:0', 'model/conv2d/kernel:0', 'model/dense/bias:0', 'model/dense/kernel:0'] layer.losses: [<tf.Tensor: shape=(), dtype=float32, numpy=0.0>, <tf.Tensor: shape=(), dtype=float32, numpy=0.0>] /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:12: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. if sys.path[0] == '': /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:13: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead. del sys.path[0] /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:16: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. app.launch_new_instance() <tf.Tensor: shape=(8, 10), dtype=float32, numpy= array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>
شما می توانید لایه تبدیل شده را مستقیماً در ساخت مدل عملکردی Keras نیز استفاده کنید.
inputs = tf.keras.Input(shape=(5, 5, 5))
outputs = CompatV1LayerModel(10)(inputs)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
x = tf.random.normal(shape=(8, 5, 5, 5))
model(x)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:12: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. if sys.path[0] == '': /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/base.py:573: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically. _add_elements_to_collection(self.updates, tf.compat.v1.GraphKeys.UPDATE_OPS) /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:13: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead. del sys.path[0] /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:16: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. app.launch_new_instance() <tf.Tensor: shape=(8, 10), dtype=float32, numpy= array([[ 0.19487001, 0.54727787, 1.1044168 , -0.6613899 , -0.26437742, -1.1580509 , -0.24707682, 0.97752655, 0.59436107, 0.13125825], [ 0.48974586, -1.3510125 , 0.7186962 , -0.8996632 , -0.60448873, 0.06332532, 0.31494308, 0.23021704, -1.9166642 , 0.3890404 ], [-0.06499191, -0.21485235, 0.01158494, 1.4407377 , -0.0488929 , -0.37594396, -0.4386894 , -0.08751169, 1.0905663 , -1.5450519 ], [-2.2749739 , -2.4603422 , -1.3834419 , -2.8800466 , 0.8954872 , -3.0429187 , -0.7885461 , 1.6037437 , -3.1845028 , -1.0725503 ], [ 0.98735195, -0.45159122, 0.892656 , 0.477053 , 0.31193537, -0.44723228, -0.01815075, -0.47465172, -1.665448 , -2.105824 ], [-2.5408387 , -1.7552321 , -1.924145 , -0.6395873 , 0.4081779 , -0.48731515, -3.2637763 , -1.4409767 , -2.032539 , 0.10204412], [ 2.1583526 , 0.78955674, -0.07266375, 0.06652926, 2.1300716 , -1.6256162 , 0.56154627, -0.76179224, 2.2985756 , -1.5504618 ], [ 2.062847 , 0.971378 , -1.0830508 , 1.8224751 , -0.3542943 , 0.74113446, -0.6204865 , 1.4503044 , -0.4979878 , -0.4383126 ]], dtype=float32)>
# Access the model variables and regularization losses
model.weights
model.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.03079858>, <tf.Tensor: shape=(), dtype=float32, numpy=0.12991619>]
بهروزرسانیهای عادیسازی دستهای و args training
مدل را ضبط کنید
در TF1.x، نرمال سازی دسته ای را به صورت زیر انجام می دهید:
x_norm = tf.compat.v1.layers.batch_normalization(x, training=training)
# ...
update_ops = tf.compat.v1.get_collection(tf.GraphKeys.UPDATE_OPS)
train_op = optimizer.minimize(loss)
train_op = tf.group([train_op, update_ops])
توجه داشته باشید که:
- به روز رسانی میانگین متحرک نرمال سازی دسته ای توسط
get_collection
که جدا از لایه فراخوانی شده است ردیابی می شود -
tf.compat.v1.layers.batch_normalization
به یک آرگومانtraining
نیاز دارد (به طور کلی هنگام استفاده از لایه های عادی سازی دسته ای TF-Slimis_training
نامیده می شود)
در TF2، به دلیل اجرای مشتاقانه و وابستگی های کنترل خودکار، به روز رسانی های میانگین متحرک نرمال سازی دسته ای بلافاصله اجرا می شود. نیازی به جمع آوری جداگانه آنها از مجموعه به روز رسانی ها و اضافه کردن آنها به عنوان وابستگی های کنترل صریح نیست.
بهعلاوه، اگر به روش عبور به جلو tf.keras.layers.Layer
یک آرگومان training
بدهید، Keras میتواند فاز آموزشی فعلی و هر لایهی تودرتو را به آن منتقل کند، درست مانند هر لایه دیگر. برای اطلاعات بیشتر در مورد اینکه Keras چگونه آرگومان training
را مدیریت می کند، به اسناد API برای tf.keras.Model
مراجعه کنید.
اگر روشهای tf.Module
را تزئین میکنید، باید مطمئن شوید که تمام آرگومانهای training
را در صورت نیاز به صورت دستی پاس میکنید. با این حال، بهروزرسانیهای میانگین متحرک عادی سازی دستهای همچنان بهطور خودکار بدون نیاز به وابستگیهای کنترل صریح اعمال میشوند.
تکههای کد زیر نحوه جاسازی لایههای نرمالسازی دستهای در شیم و نحوه استفاده از آن در مدل Keras را نشان میدهند (قابل استفاده برای tf.keras.layers.Layer
).
class CompatV1BatchNorm(tf.keras.layers.Layer):
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs, training=None):
print("Forward pass called with `training` =", training)
with v1.variable_scope('batch_norm_layer'):
return v1.layers.batch_normalization(x, training=training)
print("Constructing model")
inputs = tf.keras.Input(shape=(5, 5, 5))
outputs = CompatV1BatchNorm()(inputs)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
print("Calling model in inference mode")
x = tf.random.normal(shape=(8, 5, 5, 5))
model(x, training=False)
print("Moving average variables before training: ",
{var.name: var.read_value() for var in model.non_trainable_variables})
# Notice that when running TF2 and eager execution, the batchnorm layer directly
# updates the moving averages while training without needing any extra control
# dependencies
print("calling model in training mode")
model(x, training=True)
print("Moving average variables after training: ",
{var.name: var.read_value() for var in model.non_trainable_variables})
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:7: UserWarning: `tf.layers.batch_normalization` is deprecated and will be removed in a future version. Please use `tf.keras.layers.BatchNormalization` instead. In particular, `tf.control_dependencies(tf.GraphKeys.UPDATE_OPS)` should not be used (consult the `tf.keras.layers.BatchNormalization` documentation). import sys /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/normalization.py:463: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead. return layer.apply(inputs, training=training) Constructing model Forward pass called with `training` = None Calling model in inference mode Forward pass called with `training` = False Moving average variables before training: {'batch_norm_layer/batch_normalization/moving_mean:0': <tf.Tensor: shape=(5,), dtype=float32, numpy=array([0., 0., 0., 0., 0.], dtype=float32)>, 'batch_norm_layer/batch_normalization/moving_variance:0': <tf.Tensor: shape=(5,), dtype=float32, numpy=array([1., 1., 1., 1., 1.], dtype=float32)>} calling model in training mode Forward pass called with `training` = True Moving average variables after training: {'batch_norm_layer/batch_normalization/moving_mean:0': <tf.Tensor: shape=(5,), dtype=float32, numpy= array([-0.00177554, -0.00036542, -0.00099426, -0.00112544, 0.0008541 ], dtype=float32)>, 'batch_norm_layer/batch_normalization/moving_variance:0': <tf.Tensor: shape=(5,), dtype=float32, numpy= array([1.0005339, 1.0003369, 0.9976748, 1.0001523, 1.0009514], dtype=float32)>}
استفاده مجدد از متغیر مبتنی بر دامنه متغیر
هر متغیری که در گذر به جلو بر اساس get_variable
ایجاد میشود، همان نامگذاری متغیر و معنایی استفاده مجدد را حفظ میکند که دامنه متغیر در TF1.x دارد. این درست است تا زمانی که شما حداقل یک محدوده بیرونی غیر خالی برای هر tf.compat.v1.layers
با نام های تولید شده خودکار، همانطور که در بالا ذکر شد، داشته باشید.
اجرای مشتاق و tf.function
همانطور که در بالا مشاهده شد، متدهای تزئین شده برای tf.keras.layers.Layer
و tf.Module
در داخل اجرای مشتاق اجرا می شوند و همچنین با tf.function
سازگار هستند. این به این معنی است که می توانید از pdf و سایر ابزارهای تعاملی برای عبور از پاس خود در حین اجرا استفاده کنید.
استراتژی های توزیع
فراخوانی به get_variable
در داخل @track_tf1_style_variables
-decorated لایه یا روش های ماژول از ایجاد متغیرهای استاندارد tf.Variable
در زیر هود استفاده می کند. این بدان معنی است که می توانید از آنها با استراتژی های توزیع مختلف موجود با tf.distribute
مانند MirroredStrategy
و TPUStrategy
استفاده کنید.
tf.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)>
این روش تضمین می کند که این لایه های تو در تو به درستی مورد استفاده مجدد قرار می گیرند و توسط تنسورفلو ردیابی می شوند. توجه داشته باشید که دکوراتور @track_tf1_style_variables
همچنان در روش مناسب مورد نیاز است. متد سازنده مدل ارسال شده به get_or_create_layer
(در این مورد self.build_model
)، نباید هیچ آرگومانی داشته باشد.
وزن ها ردیابی می شوند:
assert len(layer.weights) == 2
weights = {x.name: x for x in layer.variables}
assert set(weights.keys()) == {"dense/bias:0", "dense/kernel:0"}
layer.weights
[<tf.Variable 'dense/kernel:0' shape=(5, 10) dtype=float32, numpy= array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]], dtype=float32)>, <tf.Variable 'dense/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>]
و همچنین از دست دادن منظم سازی:
tf.add_n(layer.losses)
<tf.Tensor: shape=(1,), dtype=float32, numpy=array([0.5], dtype=float32)>
مهاجرت افزایشی: tf.Variables
و tf.Modules
اگر میخواهید تماسهای tf.Variable
یا tf.Module
s را در روشهای تزئین شده خود جاسازی کنید (به عنوان مثال، اگر مهاجرت تدریجی به APIهای غیر قدیمی TF2 که در ادامه در این راهنما توضیح داده شد را دنبال میکنید)، همچنان باید این موارد را به صراحت دنبال کنید. با شرایط زیر:
- صریحاً مطمئن شوید که متغیر/ماژول/لایه فقط یک بار ایجاد شده است
- همانطور که هنگام تعریف یک ماژول یا لایه معمولی ، آنها را بهعنوان ویژگیهای نمونه پیوست کنید
- به صراحت از شی ایجاد شده در تماس های بعدی دوباره استفاده کنید
این تضمین میکند که وزنها در هر تماس جدید ایجاد نمیشوند و به درستی دوباره استفاده میشوند. علاوه بر این، این تضمین میکند که وزنهای موجود و کاهشهای منظم ردیابی میشوند.
در اینجا مثالی از این است که چگونه می تواند به نظر برسد:
class NestedLayer(tf.keras.layers.Layer):
def __init__(self, units, *args, **kwargs):
super().__init__(*args, **kwargs)
self.units = units
@tf.compat.v1.keras.utils.track_tf1_style_variables
def __call__(self, inputs):
out = inputs
with tf.compat.v1.variable_scope("inner_dense"):
# The weights are created with a `regularizer`,
# so the layer should track their regularization losses
kernel = tf.compat.v1.get_variable(
shape=[out.shape[-1], self.units],
regularizer=tf.keras.regularizers.L2(),
initializer=tf.compat.v1.initializers.glorot_normal,
name="kernel")
bias = tf.compat.v1.get_variable(
shape=[self.units,],
initializer=tf.compat.v1.initializers.zeros,
name="bias")
out = tf.linalg.matmul(out, kernel)
out = tf.compat.v1.nn.bias_add(out, bias)
return out
class WrappedDenseLayer(tf.keras.layers.Layer):
def __init__(self, units, **kwargs):
super().__init__(**kwargs)
self.units = units
# Only create the nested tf.variable/module/layer/model
# once, and then reuse it each time!
self._dense_layer = NestedLayer(self.units)
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs):
with tf.compat.v1.variable_scope('outer'):
outputs = tf.compat.v1.layers.dense(inputs, 3)
outputs = tf.compat.v1.layers.dense(inputs, 4)
return self._dense_layer(outputs)
layer = WrappedDenseLayer(10)
layer(tf.ones(shape=(5, 5)))
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:38: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:39: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. <tf.Tensor: shape=(5, 10), dtype=float32, numpy= array([[-0.4987283 , 0.06630042, -0.09875254, 0.20954818, 0.03599668, 0.3980474 , 0.11181635, 0.6891558 , -0.33903462, 0.15674731], [-0.4987283 , 0.06630042, -0.09875254, 0.20954818, 0.03599668, 0.3980474 , 0.11181635, 0.6891558 , -0.33903462, 0.15674731], [-0.4987283 , 0.06630042, -0.09875254, 0.20954818, 0.03599668, 0.3980474 , 0.11181635, 0.6891558 , -0.33903462, 0.15674731], [-0.4987283 , 0.06630042, -0.09875254, 0.20954818, 0.03599668, 0.3980474 , 0.11181635, 0.6891558 , -0.33903462, 0.15674731], [-0.4987283 , 0.06630042, -0.09875254, 0.20954818, 0.03599668, 0.3980474 , 0.11181635, 0.6891558 , -0.33903462, 0.15674731]], dtype=float32)>
توجه داشته باشید که ردیابی صریح ماژول تودرتو مورد نیاز است حتی اگر با دکوراتور track_tf1_style_variables
تزئین شده باشد. این به این دلیل است که هر ماژول/لایه با متدهای تزئین شده، ذخیره متغیر مربوط به خود را دارد.
وزن ها به درستی ردیابی می شوند:
assert len(layer.weights) == 6
weights = {x.name: x for x in layer.variables}
assert set(weights.keys()) == {"outer/inner_dense/bias:0",
"outer/inner_dense/kernel:0",
"outer/dense/bias:0",
"outer/dense/kernel:0",
"outer/dense_1/bias:0",
"outer/dense_1/kernel:0"}
layer.trainable_weights
[<tf.Variable 'outer/inner_dense/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>, <tf.Variable 'outer/inner_dense/kernel:0' shape=(4, 10) dtype=float32, numpy= array([[-0.20786692, 0.14702448, -0.2577947 , 0.1885891 , 0.28935957, 0.02086618, -0.20579144, -0.7509229 , -0.23490003, 0.00370591], [ 0.09247629, -0.37428686, -0.6002815 , -0.2702465 , 0.20350575, 0.34964404, -0.32633537, 0.50722903, -0.0419833 , -0.61815673], [ 0.24821116, 0.15504731, -0.12409697, -0.2506969 , 0.22316858, -0.44847375, -0.08295754, -0.8262154 , 0.7674222 , -0.40613693], [-0.7447006 , 0.2992331 , -0.45639235, 0.0669547 , 0.39443025, 0.3182467 , 0.10884362, 0.5395837 , 0.32210502, -0.30076835]], dtype=float32)>, <tf.Variable 'outer/dense/bias:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>, <tf.Variable 'outer/dense/kernel:0' shape=(5, 3) dtype=float32, numpy= array([[ 0.6283595 , -0.80413634, -0.5471641 ], [ 0.25296038, -0.7657203 , 0.5884425 ], [-0.7180575 , -0.29509914, 0.44014376], [ 0.81024987, 0.39888996, 0.80002993], [-0.32921118, -0.7010279 , 0.820375 ]], dtype=float32)>, <tf.Variable 'outer/dense_1/bias:0' shape=(4,) dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>, <tf.Variable 'outer/dense_1/kernel:0' shape=(5, 4) dtype=float32, numpy= array([[ 0.7941524 , -0.58552563, 0.46828055, -0.44095916], [-0.16019303, 0.27973688, -0.60373306, -0.20117629], [ 0.6345844 , 0.30732214, 0.18921828, 0.37930095], [-0.50815696, -0.2471816 , -0.10282421, 0.21441567], [-0.71987414, 0.18304104, -0.5701992 , 0.4926386 ]], dtype=float32)>]
و همچنین از دست دادن منظم سازی:
layer.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.058749676>]
توجه داشته باشید که اگر NestedLayer
یک tf.Module
غیر Keras بود، متغیرها همچنان ردیابی میشدند، اما تلفات منظمسازی بهطور خودکار ردیابی نمیشد، بنابراین باید بهصراحت آنها را جداگانه ردیابی کنید.
راهنمایی در مورد نام متغیرها
فراخوانی های صریح tf.Variable
و لایه های Keras از مکانیزم تولید خودکار نام لایه / نام متغیر متفاوتی نسبت به آنچه ممکن است از ترکیب get_variable
و variable_scopes
کنید استفاده می کنند. اگرچه شیم نام متغیرهای شما را با متغیرهایی که توسط get_variable
ایجاد میشوند مطابقت میدهد، حتی زمانی که از نمودارهای TF1.x به اجرای مشتاق TF2 و tf.function
، نمیتواند برای نام متغیرهای تولید شده برای تماسهای tf.Variable
و لایههای Keras که ایجاد میشوند، یکسان باشد. شما دکوراتورهای روش خود را تعبیه می کنید. حتی ممکن است چندین متغیر یک نام را در اجرای مشتاق TF2 و tf.function
به اشتراک بگذارند.
هنگام دنبال کردن بخش های مربوط به تأیید صحت و نقشه برداری از نقاط بازرسی TF1.x در آینده در این راهنما، باید مراقب این موضوع باشید.
استفاده از tf.compat.v1.make_template
در روش تزئین شده
به شدت توصیه می شود به جای استفاده از tf.compat.v1.make_template
مستقیماً از tf.compat.v1.keras.utils.track_tf1_style_variables
استفاده کنید، زیرا لایه نازک تری در بالای TF2 است.
دستورالعملهای این بخش را برای کد TF1.x قبلی که قبلاً به tf.compat.v1.make_template
متکی بود، دنبال کنید.
از آنجایی که tf.compat.v1.make_template
را می پیچد که از get_variable
استفاده می کند، دکوراتور track_tf1_style_variables
به شما امکان می دهد از این الگوها در تماس های لایه استفاده کنید و وزن ها و تلفات منظم سازی را با موفقیت پیگیری کنید.
با این حال، مطمئن شوید که make_template
را فقط یک بار فراخوانی کرده و سپس از همان الگو در هر تماس لایه استفاده مجدد کنید. در غیر این صورت، هر بار که لایه را فراخوانی می کنید، یک قالب جدید به همراه مجموعه جدیدی از متغیرها ایجاد می شود.
مثلا،
class CompatV1TemplateScaleByY(tf.keras.layers.Layer):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def my_op(x, scalar_name):
var1 = tf.compat.v1.get_variable(scalar_name,
shape=[],
regularizer=tf.compat.v1.keras.regularizers.L2(),
initializer=tf.compat.v1.constant_initializer(1.5))
return x * var1
self.scale_by_y = tf.compat.v1.make_template('scale_by_y', my_op, scalar_name='y')
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs):
with tf.compat.v1.variable_scope('layer'):
# Using a scope ensures the `scale_by_y` name will not be incremented
# for each instantiation of the layer.
return self.scale_by_y(inputs)
layer = CompatV1TemplateScaleByY()
out = layer(tf.ones(shape=(2, 3)))
print("weights:", layer.weights)
print("regularization loss:", layer.losses)
print("output:", out)
weights: [<tf.Variable 'layer/scale_by_y/y:0' shape=() dtype=float32, numpy=1.5>] regularization loss: [<tf.Tensor: shape=(), dtype=float32, numpy=0.022499999>] output: tf.Tensor( [[1.5 1.5 1.5] [1.5 1.5 1.5]], shape=(2, 3), dtype=float32)
مهاجرت افزایشی به Native TF2
همانطور که قبلاً ذکر شد، track_tf1_style_variables
به شما امکان می دهد که tf.Variable / tf.keras.layers.Layer / tf.Module شی گرا سبک TF2 را با tf.Variable
/ tf.keras.layers.Layer
tf.Module
قدیمی tf.compat.v1.get_variable
tf.compat.v1.layers
. استفاده در داخل همان ماژول/لایه تزئین شده.
این بدان معناست که پس از اینکه مدل TF1.x خود را کاملاً با TF2 سازگار کردید، می توانید تمام اجزای مدل جدید را با API های بومی (non tf.compat.v1
) TF2 بنویسید و از آنها بخواهید با کدهای قدیمی شما همکاری کنند.
با این حال، اگر به اصلاح مؤلفههای مدل قدیمیتر خود ادامه میدهید، میتوانید استفاده از tf.compat.v1
به سبک قدیمی خود را نیز بهصورت تدریجی به APIهای شیگرا کاملاً بومی که برای کد TF2 جدید نوشته شده توصیه میشوند، تغییر دهید.
استفاده از tf.compat.v1.get_variable
را میتوان با تماسهای self.add_weight
در صورتی که یک لایه/مدل Keras تزئین میکنید، یا با تماسهای tf.Variable
اگر در حال تزئین اشیاء Keras یا tf.Module
s هستید، جایگزین کرد.
هر دو لایه tf.keras.layers
tf.compat.v1.layers
بدون نیاز به تغییر آرگومان جایگزین شوند.
همچنین میتوانید بخشهایی از مدل یا الگوهای رایج خود را در طول حرکت تدریجی خود به APIهای کاملاً بومی، که ممکن است خودشان از track_tf1_style_variables
استفاده کنند، در لایهها/ماژولهای جداگانه در نظر بگیرید.
یادداشتی در مورد لایه های Slim و contrib
مقدار زیادی از کدهای قدیمی TF 1.x از کتابخانه Slim استفاده می کند که با TF 1.x به عنوان tf.contrib.layers
بسته بندی شده است. تبدیل کد با استفاده از Slim به Native TF 2 بیشتر از تبدیل v1.layers
. در واقع، ممکن است منطقی باشد که ابتدا کد Slim خود را به v1.layers
تبدیل کنید، سپس به Keras تبدیل کنید. در زیر چند راهنمایی کلی برای تبدیل کد اسلیم آورده شده است.
- اطمینان حاصل کنید که همه استدلال ها صریح هستند. در صورت امکان
arg_scopes
را حذف کنید. اگر همچنان نیاز به استفاده از آنها دارید،normalizer_fn
وactivation_fn
را به لایه های خود تقسیم کنید. - لایههای تبدیل قابل تفکیک به یک یا چند لایه Keras مختلف (لایههای Keras به صورت عمقی، نقطهای و قابل جداسازی) نگاشت میشوند.
- Slim و
v1.layers
نامهای آرگومان و مقادیر پیشفرض متفاوتی دارند. - توجه داشته باشید که برخی از استدلال ها مقیاس های مختلفی دارند.
مهاجرت به Native TF2 با نادیده گرفتن سازگاری ایست بازرسی
نمونه کد زیر حرکت تدریجی یک مدل را به APIهای کاملاً بومی بدون در نظر گرفتن سازگاری ایست بازرسی نشان می دهد.
class CompatModel(tf.keras.layers.Layer):
def __init__(self, units, *args, **kwargs):
super().__init__(*args, **kwargs)
self.units = units
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs, training=None):
with tf.compat.v1.variable_scope('model'):
out = tf.compat.v1.layers.conv2d(
inputs, 3, 3,
kernel_regularizer="l2")
out = tf.compat.v1.layers.flatten(out)
out = tf.compat.v1.layers.dropout(out, training=training)
out = tf.compat.v1.layers.dense(
out, self.units,
kernel_regularizer="l2")
return out
سپس، API های compat.v1
را با معادل های شی گرا بومی آن ها به صورت تکه ای جایگزین کنید. با تغییر لایه پیچشی به یک شی Keras که در سازنده لایه ایجاد شده است، شروع کنید.
class PartiallyMigratedModel(tf.keras.layers.Layer):
def __init__(self, units, *args, **kwargs):
super().__init__(*args, **kwargs)
self.units = units
self.conv_layer = tf.keras.layers.Conv2D(
3, 3,
kernel_regularizer="l2")
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs, training=None):
with tf.compat.v1.variable_scope('model'):
out = self.conv_layer(inputs)
out = tf.compat.v1.layers.flatten(out)
out = tf.compat.v1.layers.dropout(out, training=training)
out = tf.compat.v1.layers.dense(
out, self.units,
kernel_regularizer="l2")
return out
از کلاس v1.keras.utils.DeterministicRandomTestTool
استفاده کنید تا بررسی کنید که این تغییر افزایشی باعث می شود مدل همان رفتار قبلی را داشته باشد.
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
layer = CompatModel(10)
inputs = tf.random.normal(shape=(10, 5, 5, 5))
original_output = layer(inputs)
# Grab the regularization loss as well
original_regularization_loss = tf.math.add_n(layer.losses)
print(original_regularization_loss)
tf.Tensor(0.17953834, shape=(), dtype=float32) /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:12: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. if sys.path[0] == '': /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:13: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead. del sys.path[0] /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:14: UserWarning: `tf.layers.dropout` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dropout` instead. /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/core.py:413: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead. return layer.apply(inputs, training=training) /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:17: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
layer = PartiallyMigratedModel(10)
inputs = tf.random.normal(shape=(10, 5, 5, 5))
migrated_output = layer(inputs)
# Grab the regularization loss as well
migrated_regularization_loss = tf.math.add_n(layer.losses)
print(migrated_regularization_loss)
tf.Tensor(0.17953834, shape=(), dtype=float32) /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:14: UserWarning: `tf.layers.flatten` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Flatten` instead. /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:15: UserWarning: `tf.layers.dropout` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dropout` instead. from ipykernel import kernelapp as app /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:18: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
# Verify that the regularization loss and output both match
np.testing.assert_allclose(original_regularization_loss.numpy(), migrated_regularization_loss.numpy())
np.testing.assert_allclose(original_output.numpy(), migrated_output.numpy())
شما اکنون تمامی لایه های compat.v1.layers
.را با لایه های بومی Keras جایگزین کرده اید.
class NearlyFullyNativeModel(tf.keras.layers.Layer):
def __init__(self, units, *args, **kwargs):
super().__init__(*args, **kwargs)
self.units = units
self.conv_layer = tf.keras.layers.Conv2D(
3, 3,
kernel_regularizer="l2")
self.flatten_layer = tf.keras.layers.Flatten()
self.dense_layer = tf.keras.layers.Dense(
self.units,
kernel_regularizer="l2")
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs):
with tf.compat.v1.variable_scope('model'):
out = self.conv_layer(inputs)
out = self.flatten_layer(out)
out = self.dense_layer(out)
return out
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
layer = NearlyFullyNativeModel(10)
inputs = tf.random.normal(shape=(10, 5, 5, 5))
migrated_output = layer(inputs)
# Grab the regularization loss as well
migrated_regularization_loss = tf.math.add_n(layer.losses)
print(migrated_regularization_loss)
tf.Tensor(0.17953834, shape=(), dtype=float32)
# Verify that the regularization loss and output both match
np.testing.assert_allclose(original_regularization_loss.numpy(), migrated_regularization_loss.numpy())
np.testing.assert_allclose(original_output.numpy(), migrated_output.numpy())
در نهایت، استفاده از variable_scope
باقیمانده (که دیگر مورد نیاز نیست) و خود دکوراتور track_tf1_style_variables
را حذف کنید.
اکنون نسخه ای از مدل برای شما باقی مانده است که از API های کاملاً بومی استفاده می کند.
class FullyNativeModel(tf.keras.layers.Layer):
def __init__(self, units, *args, **kwargs):
super().__init__(*args, **kwargs)
self.units = units
self.conv_layer = tf.keras.layers.Conv2D(
3, 3,
kernel_regularizer="l2")
self.flatten_layer = tf.keras.layers.Flatten()
self.dense_layer = tf.keras.layers.Dense(
self.units,
kernel_regularizer="l2")
def call(self, inputs):
out = self.conv_layer(inputs)
out = self.flatten_layer(out)
out = self.dense_layer(out)
return out
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
layer = FullyNativeModel(10)
inputs = tf.random.normal(shape=(10, 5, 5, 5))
migrated_output = layer(inputs)
# Grab the regularization loss as well
migrated_regularization_loss = tf.math.add_n(layer.losses)
print(migrated_regularization_loss)
tf.Tensor(0.17953834, shape=(), dtype=float32)
# Verify that the regularization loss and output both match
np.testing.assert_allclose(original_regularization_loss.numpy(), migrated_regularization_loss.numpy())
np.testing.assert_allclose(original_output.numpy(), migrated_output.numpy())
حفظ سازگاری ایست بازرسی در طول مهاجرت به Native TF2
فرآیند انتقال بالا به APIهای بومی TF2 هم نام متغیرها را تغییر داد (از آنجایی که APIهای Keras نامهای وزنی بسیار متفاوتی تولید میکنند)، و هم مسیرهای شی گرا که به وزنهای مختلف در مدل اشاره میکنند. تأثیر این تغییرات این است که آنها هر دو پست بازرسی مبتنی بر نام به سبک TF1 یا ایست های بازرسی شی گرا به سبک TF2 را شکسته اند.
با این حال، در برخی موارد، ممکن است بتوانید ایست بازرسی مبتنی بر نام اصلی خود را بردارید و با رویکردهایی مانند آنچه در راهنمای استفاده مجدد از TF1.x در راهنمای نقاط بازرسی توضیح داده شده است، نگاشت متغیرها را به نام جدیدشان بیابید.
برخی از نکات برای تحقق این امر به شرح زیر است:
- همه متغیرها هنوز هم یک آرگومان
name
دارند که می توانید تنظیم کنید. - مدلهای Keras نیز آرگومان
name
را به عنوان پیشوند برای متغیرهای خود تنظیم میکنند. - تابع
v1.name_scope
می تواند برای تنظیم پیشوندهای نام متغیر استفاده شود. این باtf.variable_scope
بسیار متفاوت است. این فقط بر نام ها تأثیر می گذارد و متغیرها و استفاده مجدد را ردیابی نمی کند.
با در نظر گرفتن نکات بالا، نمونه کدهای زیر جریان کاری را نشان میدهند که میتوانید با کد خود مطابقت دهید تا بهطور تدریجی بخشی از یک مدل را بهروزرسانی کنید و همزمان نقاط بازرسی را بهروزرسانی کنید.
- با تغییر لایه های
tf.compat.v1.layers
-style به نسخه های شی گرا شروع کنید.
class FunctionalStyleCompatModel(tf.keras.layers.Layer):
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs, training=None):
with tf.compat.v1.variable_scope('model'):
out = tf.compat.v1.layers.conv2d(
inputs, 3, 3,
kernel_regularizer="l2")
out = tf.compat.v1.layers.conv2d(
out, 4, 4,
kernel_regularizer="l2")
out = tf.compat.v1.layers.conv2d(
out, 5, 5,
kernel_regularizer="l2")
return out
layer = FunctionalStyleCompatModel()
layer(tf.ones(shape=(10, 10, 10, 10)))
[v.name for v in layer.weights]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:8: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:11: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. # This is added back by InteractiveShellApp.init_path() /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:14: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. ['model/conv2d/bias:0', 'model/conv2d/kernel:0', 'model/conv2d_1/bias:0', 'model/conv2d_1/kernel:0', 'model/conv2d_2/bias:0', 'model/conv2d_2/kernel:0']
- سپس، اشیاء compat.v1.layer و هر متغیر ایجاد شده توسط
compat.v1.get_variable
را به عنوان ویژگی های شیtf.keras.layers.Layer
/tf.Module
که روش آن باtrack_tf1_style_variables
تزئین شده است، اختصاص دهید (توجه داشته باشید که هر TF2 شی گرا اکنون چک پوینتهای سبک هم یک مسیر را با نام متغیر و هم مسیر شی گرا جدید را ذخیره میکنند.
class OOStyleCompatModel(tf.keras.layers.Layer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.conv_1 = tf.compat.v1.layers.Conv2D(
3, 3,
kernel_regularizer="l2")
self.conv_2 = tf.compat.v1.layers.Conv2D(
4, 4,
kernel_regularizer="l2")
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs, training=None):
with tf.compat.v1.variable_scope('model'):
out = self.conv_1(inputs)
out = self.conv_2(out)
out = tf.compat.v1.layers.conv2d(
out, 5, 5,
kernel_regularizer="l2")
return out
layer = OOStyleCompatModel()
layer(tf.ones(shape=(10, 10, 10, 10)))
[v.name for v in layer.weights]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:19: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. ['model/conv2d/kernel:0', 'model/conv2d/bias:0', 'model/conv2d_1/kernel:0', 'model/conv2d_1/bias:0', 'model/conv2d_2/bias:0', 'model/conv2d_2/kernel:0']
- برای ذخیره مسیرها با نام متغیر (برای compat.v1.layers) یا با گراف شی گرا، یک چک پوینت بارگذاری شده را در این نقطه دوباره ذخیره کنید.
weights = {v.name: v for v in layer.weights}
assert weights['model/conv2d/kernel:0'] is layer.conv_1.kernel
assert weights['model/conv2d_1/bias:0'] is layer.conv_2.bias
- اکنون میتوانید لایههای شی گرا
compat.v1.layers
.را با لایههای Keras بومی تعویض کنید، در حالی که همچنان میتوانید نقطه بازرسی اخیراً ذخیره شده را بارگیری کنید. مطمئن شوید که نام متغیرها را برای لایههای compat.v1. باقیمانده با ضبطcompat.v1.layers
variable_scopes
خودکار لایههای جایگزین شده، حفظ کنید. این لایه ها/متغیرهای سوئیچ شده اکنون به جای مسیر نام متغیر، فقط از مسیر ویژگی شی برای متغیرهای موجود در چک پوینت استفاده می کنند.
به طور کلی، میتوانید استفاده از compat.v1.get_variable
در متغیرهای متصل به ویژگیها جایگزین کنید:
- آنها را به استفاده از
tf.Variable
، OR تغییر دهید - به روز رسانی آنها با استفاده از
tf.keras.layers.Layer.add_weight
. توجه داشته باشید که اگر همه لایهها را به یکباره تغییر نمیدهید، ممکن است نامگذاری لایه/متغیر بهطور خودکار برایcompat.v1.layers
. باقیمانده که آرگومانname
ندارند، تغییر کند. اگر چنین است، باید نام متغیرها را برای باقیماندهcompat.v1.layers
. با باز و بسته کردن دستیvariable_scope
scope مربوط به نام دامنه تولید شده حذف شدهcompat.v1.layer
، یکسان نگه دارید. در غیر این صورت مسیرهای پست های بازرسی موجود ممکن است با هم تداخل داشته باشند و بارگذاری ایست بازرسی نادرست رفتار کند.
def record_scope(scope_name):
"""Record a variable_scope to make sure future ones get incremented."""
with tf.compat.v1.variable_scope(scope_name):
pass
class PartiallyNativeKerasLayersModel(tf.keras.layers.Layer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.conv_1 = tf.keras.layers.Conv2D(
3, 3,
kernel_regularizer="l2")
self.conv_2 = tf.keras.layers.Conv2D(
4, 4,
kernel_regularizer="l2")
@tf.compat.v1.keras.utils.track_tf1_style_variables
def call(self, inputs, training=None):
with tf.compat.v1.variable_scope('model'):
out = self.conv_1(inputs)
record_scope('conv2d') # Only needed if follow-on compat.v1.layers do not pass a `name` arg
out = self.conv_2(out)
record_scope('conv2d_1') # Only needed if follow-on compat.v1.layers do not pass a `name` arg
out = tf.compat.v1.layers.conv2d(
out, 5, 5,
kernel_regularizer="l2")
return out
layer = PartiallyNativeKerasLayersModel()
layer(tf.ones(shape=(10, 10, 10, 10)))
[v.name for v in layer.weights]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:26: UserWarning: `tf.layers.conv2d` is deprecated and will be removed in a future version. Please Use `tf.keras.layers.Conv2D` instead. ['partially_native_keras_layers_model/model/conv2d_13/kernel:0', 'partially_native_keras_layers_model/model/conv2d_13/bias:0', 'partially_native_keras_layers_model/model/conv2d_14/kernel:0', 'partially_native_keras_layers_model/model/conv2d_14/bias:0', 'model/conv2d_2/bias:0', 'model/conv2d_2/kernel:0']
ذخیره یک چک پوینت در این مرحله پس از ساخت متغیرها باعث می شود که فقط مسیرهای شی موجود در حال حاضر را در خود داشته باشد.
مطمئن شوید که محدوده لایههای compat.v1. حذفشده را ضبط کردهاید تا نام وزنهای تولید شده خودکار برای باقیماندههای compat.v1.layers
compat.v1.layers
شود.
weights = set(v.name for v in layer.weights)
assert 'model/conv2d_2/kernel:0' in weights
assert 'model/conv2d_2/bias:0' in weights
- مراحل بالا را تا زمانی که تمام
compat.v1.layers
وcompat.v1.get_variable
های مدل خود را با معادل های کاملاً بومی جایگزین کنید، تکرار کنید.
class FullyNativeKerasLayersModel(tf.keras.layers.Layer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.conv_1 = tf.keras.layers.Conv2D(
3, 3,
kernel_regularizer="l2")
self.conv_2 = tf.keras.layers.Conv2D(
4, 4,
kernel_regularizer="l2")
self.conv_3 = tf.keras.layers.Conv2D(
5, 5,
kernel_regularizer="l2")
def call(self, inputs, training=None):
with tf.compat.v1.variable_scope('model'):
out = self.conv_1(inputs)
out = self.conv_2(out)
out = self.conv_3(out)
return out
layer = FullyNativeKerasLayersModel()
layer(tf.ones(shape=(10, 10, 10, 10)))
[v.name for v in layer.weights]
['fully_native_keras_layers_model/model/conv2d_16/kernel:0', 'fully_native_keras_layers_model/model/conv2d_16/bias:0', 'fully_native_keras_layers_model/model/conv2d_17/kernel:0', 'fully_native_keras_layers_model/model/conv2d_17/bias:0', 'fully_native_keras_layers_model/model/conv2d_18/kernel:0', 'fully_native_keras_layers_model/model/conv2d_18/bias:0']
به یاد داشته باشید که تست کنید تا مطمئن شوید که ایست بازرسی بهروزرسانی شده همچنان همانطور که انتظار دارید رفتار میکند. تکنیک های توضیح داده شده در راهنمای صحت عددی تأیید اعتبار را در هر مرحله افزایشی این فرآیند به کار ببرید تا مطمئن شوید کد انتقال داده شده شما به درستی اجرا می شود.
مدیریت تغییرات رفتاری TF1.x به TF2 که توسط شیم های مدل سازی پوشش داده نمی شود
شیمهای مدلسازی که در این راهنما توضیح داده شدهاند میتوانند مطمئن شوند که متغیرها، لایهها و تلفات منظمسازی ایجاد شده با get_variable
، tf.compat.v1.layers
و variable_scope
، بدون نیاز به استفاده از eager execution و tf.function
، مانند قبل کار میکنند. به مجموعه ها تکیه کنید
این همه معنایی خاص TF1.x را که ممکن است مدل شما بر آن تکیه کند، پوشش نمی دهد. در برخی موارد، شیم ها ممکن است برای اجرای خود به خود پاس مدل به جلو در TF2 کافی نباشد. راهنمای رفتارهای TF1.x در مقابل TF2 را بخوانید تا درباره تفاوت های رفتاری بین TF1.x و TF2 بیشتر بدانید.