مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
این نوت بوک نحوه اشکال زدایی خط لوله آموزشی را هنگام مهاجرت به TF2 نشان می دهد. از اجزای زیر تشکیل شده است:
- مراحل پیشنهادی و نمونه کد برای خط لوله آموزشی اشکال زدایی
- ابزارهایی برای رفع اشکال
- سایر منابع مرتبط
یک فرض این است که شما کد TF1.x و مدل های آموزش دیده برای مقایسه دارید، و می خواهید یک مدل TF2 بسازید که به دقت اعتبارسنجی مشابهی دست یابد.
این نوت بوک مسائل مربوط به عملکرد اشکال زدایی را برای سرعت آموزش/استنتاج یا استفاده از حافظه پوشش نمی دهد.
اشکال زدایی گردش کار
در زیر یک گردش کار کلی برای اشکال زدایی خطوط لوله آموزشی TF2 ارائه شده است. توجه داشته باشید که لازم نیست این مراحل را به ترتیب انجام دهید. همچنین میتوانید از یک رویکرد جستجوی دودویی استفاده کنید که در آن مدل را در یک مرحله میانی آزمایش میکنید و دامنه اشکالزدایی را محدود میکنید.
رفع خطاهای کامپایل و زمان اجرا
اعتبار سنجی یک پاس رو به جلو (در یک راهنمای جداگانه)
آ. بر روی یک دستگاه CPU
- تأیید کنید که متغیرها فقط یک بار ایجاد می شوند
- تعداد متغیرها، نام ها و اشکال مطابقت را بررسی کنید
- همه متغیرها را بازنشانی کنید، معادل عددی را با غیرفعال بودن همه تصادفی بررسی کنید
- ایجاد اعداد تصادفی را تراز کنید، هم ارزی عددی را در استنتاج بررسی کنید
- (اختیاری) چک پوینت ها به درستی بارگذاری شده اند و مدل های TF1.x/TF2 خروجی یکسان تولید می کنند
ب روی یک دستگاه GPU/TPU
ج با استراتژی های چند دستگاهی
آموزش مدل اعتبار سنجی معادل سازی عددی برای چند مرحله (نمونه کد موجود در زیر)
آ. اعتبارسنجی مرحله آموزشی تک مرحله ای با استفاده از داده های کوچک و ثابت در یک دستگاه واحد CPU. به طور خاص، معادل عددی را برای اجزای زیر بررسی کنید
- محاسبه تلفات
- معیارهای
- میزان یادگیری
- محاسبه گرادیان و به روز رسانی
ب بررسی آمار پس از آموزش 3 مرحله یا بیشتر برای تأیید رفتارهای بهینهساز مانند تکانه، همچنان با دادههای ثابت در یک دستگاه CPU
ج روی یک دستگاه GPU/TPU
د با استراتژی های چند دستگاهی (مقدمه MultiProcessRunner را در پایین بررسی کنید)
تست پوشش سرتاسری روی مجموعه داده واقعی
آ. رفتارهای آموزشی را با TensorBoard بررسی کنید
- ابتدا از بهینه سازهای ساده مانند SGD و استراتژی های توزیع ساده به عنوان مثال
tf.distribute.OneDeviceStrategy
- معیارهای آموزشی
- معیارهای ارزیابی
- تحمل منطقی برای تصادفی بودن ذاتی چیست
ب معادلسازی را با بهینهساز پیشرفته/زمانبندی نرخ یادگیری/استراتژیهای توزیع بررسی کنید
ج هنگام استفاده از دقت مخلوط، هم ارزی را بررسی کنید
- ابتدا از بهینه سازهای ساده مانند SGD و استراتژی های توزیع ساده به عنوان مثال
معیارهای محصول اضافی
برپایی
pip uninstall -y -q tensorflow
# Install tf-nightly as the DeterministicRandomTestTool is only available in
# Tensorflow 2.8
pip install -q tf-nightly
اعتبار سنجی یک پاس رو به جلو
اعتبار سنجی یک پاس رو به جلو، از جمله بارگیری ایست بازرسی، در یک colab متفاوت پوشش داده شده است.
import sys
import unittest
import numpy as np
import tensorflow as tf
import tensorflow.compat.v1 as v1
مدل آموزش اعتبار سنجی هم ارزی عددی برای چند مرحله
پیکربندی مدل را تنظیم کنید و یک مجموعه داده جعلی تهیه کنید.
params = {
'input_size': 3,
'num_classes': 3,
'layer_1_size': 2,
'layer_2_size': 2,
'num_train_steps': 100,
'init_lr': 1e-3,
'end_lr': 0.0,
'decay_steps': 1000,
'lr_power': 1.0,
}
# make a small fixed dataset
fake_x = np.ones((2, params['input_size']), dtype=np.float32)
fake_y = np.zeros((2, params['num_classes']), dtype=np.int32)
fake_y[0][0] = 1
fake_y[1][1] = 1
step_num = 3
مدل TF1.x را تعریف کنید.
# Assume there is an existing TF1.x model using estimator API
# Wrap the model_fn to log necessary tensors for result comparison
class SimpleModelWrapper():
def __init__(self):
self.logged_ops = {}
self.logs = {
'step': [],
'lr': [],
'loss': [],
'grads_and_vars': [],
'layer_out': []}
def model_fn(self, features, labels, mode, params):
out_1 = tf.compat.v1.layers.dense(features, units=params['layer_1_size'])
out_2 = tf.compat.v1.layers.dense(out_1, units=params['layer_2_size'])
logits = tf.compat.v1.layers.dense(out_2, units=params['num_classes'])
loss = tf.compat.v1.losses.softmax_cross_entropy(labels, logits)
# skip EstimatorSpec details for prediction and evaluation
if mode == tf.estimator.ModeKeys.PREDICT:
pass
if mode == tf.estimator.ModeKeys.EVAL:
pass
assert mode == tf.estimator.ModeKeys.TRAIN
global_step = tf.compat.v1.train.get_or_create_global_step()
lr = tf.compat.v1.train.polynomial_decay(
learning_rate=params['init_lr'],
global_step=global_step,
decay_steps=params['decay_steps'],
end_learning_rate=params['end_lr'],
power=params['lr_power'])
optmizer = tf.compat.v1.train.GradientDescentOptimizer(lr)
grads_and_vars = optmizer.compute_gradients(
loss=loss,
var_list=graph.get_collection(
tf.compat.v1.GraphKeys.TRAINABLE_VARIABLES))
train_op = optmizer.apply_gradients(
grads_and_vars,
global_step=global_step)
# log tensors
self.logged_ops['step'] = global_step
self.logged_ops['lr'] = lr
self.logged_ops['loss'] = loss
self.logged_ops['grads_and_vars'] = grads_and_vars
self.logged_ops['layer_out'] = {
'layer_1': out_1,
'layer_2': out_2,
'logits': logits}
return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
def update_logs(self, logs):
for key in logs.keys():
model_tf1.logs[key].append(logs[key])
کلاس v1.keras.utils.DeterministicRandomTestTool
زیر یک scope()
مدیر زمینه ارائه می دهد که می تواند عملیات تصادفی حالت دار را از همان seed در هر دو نمودار/جلسات TF1 و اجرای مشتاق استفاده کند.
این ابزار دو حالت تست را ارائه می دهد:
-
constant
که از یک دانه برای هر عملیات استفاده می کند مهم نیست که چند بار فراخوانی شده باشد و -
num_random_ops
که از تعداد عملیات تصادفی حالتی مشاهده شده قبلی به عنوان دانه عملیات استفاده می کند.
این هم برای عملیات تصادفی حالتی که برای ایجاد و مقداردهی اولیه متغیرها استفاده می شود و هم برای عملیات تصادفی حالتی که در محاسبات استفاده می شود (مانند لایه های حذفی) صدق می کند.
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
WARNING:tensorflow:From /tmp/ipykernel_26769/2689227634.py:1: The name tf.keras.utils.DeterministicRandomTestTool is deprecated. Please use tf.compat.v1.keras.utils.DeterministicRandomTestTool instead.
مدل TF1.x را در حالت نمودار اجرا کنید. جمع آوری آمار برای 3 مرحله آموزش اول برای مقایسه هم ارزی عددی.
with random_tool.scope():
graph = tf.Graph()
with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
model_tf1 = SimpleModelWrapper()
# build the model
inputs = tf.compat.v1.placeholder(tf.float32, shape=(None, params['input_size']))
labels = tf.compat.v1.placeholder(tf.float32, shape=(None, params['num_classes']))
spec = model_tf1.model_fn(inputs, labels, tf.estimator.ModeKeys.TRAIN, params)
train_op = spec.train_op
sess.run(tf.compat.v1.global_variables_initializer())
for step in range(step_num):
# log everything and update the model for one step
logs, _ = sess.run(
[model_tf1.logged_ops, train_op],
feed_dict={inputs: fake_x, labels: fake_y})
model_tf1.update_logs(logs)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:14: 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/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) /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:15: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead. from ipykernel import kernelapp as app /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()
مدل TF2 را تعریف کنید.
class SimpleModel(tf.keras.Model):
def __init__(self, params, *args, **kwargs):
super(SimpleModel, self).__init__(*args, **kwargs)
# define the model
self.dense_1 = tf.keras.layers.Dense(params['layer_1_size'])
self.dense_2 = tf.keras.layers.Dense(params['layer_2_size'])
self.out = tf.keras.layers.Dense(params['num_classes'])
learning_rate_fn = tf.keras.optimizers.schedules.PolynomialDecay(
initial_learning_rate=params['init_lr'],
decay_steps=params['decay_steps'],
end_learning_rate=params['end_lr'],
power=params['lr_power'])
self.optimizer = tf.keras.optimizers.SGD(learning_rate_fn)
self.compiled_loss = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
self.logs = {
'lr': [],
'loss': [],
'grads': [],
'weights': [],
'layer_out': []}
def call(self, inputs):
out_1 = self.dense_1(inputs)
out_2 = self.dense_2(out_1)
logits = self.out(out_2)
# log output features for every layer for comparison
layer_wise_out = {
'layer_1': out_1,
'layer_2': out_2,
'logits': logits}
self.logs['layer_out'].append(layer_wise_out)
return logits
def train_step(self, data):
x, y = data
with tf.GradientTape() as tape:
logits = self(x)
loss = self.compiled_loss(y, logits)
grads = tape.gradient(loss, self.trainable_weights)
# log training statistics
step = self.optimizer.iterations.numpy()
self.logs['lr'].append(self.optimizer.learning_rate(step).numpy())
self.logs['loss'].append(loss.numpy())
self.logs['grads'].append(grads)
self.logs['weights'].append(self.trainable_weights)
# update model
self.optimizer.apply_gradients(zip(grads, self.trainable_weights))
return
مدل TF2 را در حالت مشتاق اجرا کنید. جمع آوری آمار برای 3 مرحله آموزش اول برای مقایسه هم ارزی عددی.
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
model_tf2 = SimpleModel(params)
for step in range(step_num):
model_tf2.train_step([fake_x, fake_y])
معادل عددی را برای چند مرحله اول آموزش مقایسه کنید.
همچنین می توانید برای توصیه های اضافی برای معادل سازی عددی، دفترچه صحت اعتبارسنجی و معادل سازی عددی را بررسی کنید.
np.testing.assert_allclose(model_tf1.logs['lr'], model_tf2.logs['lr'])
np.testing.assert_allclose(model_tf1.logs['loss'], model_tf2.logs['loss'])
for step in range(step_num):
for name in model_tf1.logs['layer_out'][step]:
np.testing.assert_allclose(
model_tf1.logs['layer_out'][step][name],
model_tf2.logs['layer_out'][step][name])
تست های واحد
چند نوع تست واحد وجود دارد که می تواند به اشکال زدایی کد مهاجرت شما کمک کند.
- اعتبار سنجی یک پاس رو به جلو
- مدل آموزش اعتبار سنجی هم ارزی عددی برای چند مرحله
- عملکرد استنتاج معیار
- مدل آموزش دیده پیش بینی های درستی را در نقاط داده ثابت و ساده انجام می دهد
می توانید از @parameterized.parameters
برای آزمایش مدل هایی با پیکربندی های مختلف استفاده کنید. جزئیات با نمونه کد .
توجه داشته باشید که اجرای APIهای جلسه و اجرای مشتاقانه در همان مورد آزمایشی امکان پذیر است. تکه کدهای زیر نشان می دهد که چگونه.
import unittest
class TestNumericalEquivalence(unittest.TestCase):
# copied from code samples above
def setup(self):
# record statistics for 100 training steps
step_num = 100
# setup TF 1 model
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
# run TF1.x code in graph mode with context management
graph = tf.Graph()
with graph.as_default(), tf.compat.v1.Session(graph=graph) as sess:
self.model_tf1 = SimpleModelWrapper()
# build the model
inputs = tf.compat.v1.placeholder(tf.float32, shape=(None, params['input_size']))
labels = tf.compat.v1.placeholder(tf.float32, shape=(None, params['num_classes']))
spec = self.model_tf1.model_fn(inputs, labels, tf.estimator.ModeKeys.TRAIN, params)
train_op = spec.train_op
sess.run(tf.compat.v1.global_variables_initializer())
for step in range(step_num):
# log everything and update the model for one step
logs, _ = sess.run(
[self.model_tf1.logged_ops, train_op],
feed_dict={inputs: fake_x, labels: fake_y})
self.model_tf1.update_logs(logs)
# setup TF2 model
random_tool = v1.keras.utils.DeterministicRandomTestTool(mode='num_random_ops')
with random_tool.scope():
self.model_tf2 = SimpleModel(params)
for step in range(step_num):
self.model_tf2.train_step([fake_x, fake_y])
def test_learning_rate(self):
np.testing.assert_allclose(
self.model_tf1.logs['lr'],
self.model_tf2.logs['lr'])
def test_training_loss(self):
# adopt different tolerance strategies before and after 10 steps
first_n_step = 10
# abosolute difference is limited below 1e-5
# set `equal_nan` to be False to detect potential NaN loss issues
abosolute_tolerance = 1e-5
np.testing.assert_allclose(
actual=self.model_tf1.logs['loss'][:first_n_step],
desired=self.model_tf2.logs['loss'][:first_n_step],
atol=abosolute_tolerance,
equal_nan=False)
# relative difference is limited below 5%
relative_tolerance = 0.05
np.testing.assert_allclose(self.model_tf1.logs['loss'][first_n_step:],
self.model_tf2.logs['loss'][first_n_step:],
rtol=relative_tolerance,
equal_nan=False)
ابزارهای اشکال زدایی
tf.print
tf.print در مقابل print/logging.info
- با آرگومان های قابل تنظیم،
tf.print
می تواند به صورت بازگشتی، چند عنصر اول و آخر هر بعد را برای تانسورهای چاپی نمایش دهد. برای جزئیات، اسناد API را بررسی کنید. - برای اجرای مشتاقانه، هم
print
و همtf.print
مقدار تانسور را چاپ می کنند. اماprint
ممکن است شامل کپی دستگاه به میزبان باشد که به طور بالقوه می تواند کد شما را کند کند. - برای حالت نمودار از جمله استفاده در داخل
tf.function
، باید ازtf.print
برای چاپ مقدار تانسور واقعی استفاده کنید.tf.print
در یک عملیات در نمودار کامپایل میشود، در حالی کهprint
وlogging.info
فقط در زمان ردیابی ثبت میشوند، که اغلب آن چیزی نیست که شما میخواهید. -
tf.print
همچنین از چاپ تانسورهای ترکیبی مانندtf.RaggedTensor
وtf.sparse.SparseTensor
می کند. - همچنین میتوانید از تماس برگشتی برای نظارت بر معیارها و متغیرها استفاده کنید. لطفاً نحوه استفاده از تماسهای سفارشی با ویژگی dict و self.model را بررسی کنید.
tf.print در مقابل چاپ داخل tf.function
# `print` prints info of tensor object
# `tf.print` prints the tensor value
@tf.function
def dummy_func(num):
num += 1
print(num)
tf.print(num)
return num
_ = dummy_func(tf.constant([1.0]))
# Output:
# Tensor("add:0", shape=(1,), dtype=float32)
# [2]
Tensor("add:0", shape=(1,), dtype=float32) [2]
tf.distribute.strategy
- اگر
tf.function
حاویtf.print
روی کارگران اجرا شود، به عنوان مثال هنگام استفاده ازTPUStrategy
یاParameterServerStrategy
، باید گزارشهای کارگر/پارامتر سرور را بررسی کنید تا مقادیر چاپ شده را بیابید. - برای
print
یاlogging.info
، هنگام استفاده ازParameterServerStrategy
، گزارشها روی هماهنگکننده چاپ میشوند، و هنگام استفاده از TPU، گزارشها روی STDOUT روی worker0 چاپ میشوند.
tf.keras.Model
- هنگام استفاده از مدلهای API متوالی و عملکردی، اگر میخواهید مقادیری را چاپ کنید، به عنوان مثال، ورودیهای مدل یا ویژگیهای میانی پس از چند لایه، گزینههای زیر را دارید.
- یک لایه سفارشی بنویسید که ورودی ها را
tf.print
کند. - خروجی های میانی را که می خواهید بررسی کنید در خروجی های مدل قرار دهید.
- یک لایه سفارشی بنویسید که ورودی ها را
- لایههای
tf.keras.layers.Lambda
دارای محدودیتهای (عدم) سریالسازی هستند. برای جلوگیری از مشکلات بارگیری ایست بازرسی، به جای آن یک لایه زیر کلاس سفارشی بنویسید. برای جزئیات بیشتر، اسناد API را بررسی کنید. - اگر به مقادیر واقعی دسترسی ندارید، نمیتوانید خروجیهای میانی را در
tf.print
tf.keras.callbacks.LambdaCallback
کنید، بلکه فقط به اشیاء تانسور نمادین Keras دسترسی دارید.
گزینه 1: یک لایه سفارشی بنویسید
class PrintLayer(tf.keras.layers.Layer):
def call(self, inputs):
tf.print(inputs)
return inputs
def get_model():
inputs = tf.keras.layers.Input(shape=(1,))
out_1 = tf.keras.layers.Dense(4)(inputs)
out_2 = tf.keras.layers.Dense(1)(out_1)
# use custom layer to tf.print intermediate features
out_3 = PrintLayer()(out_2)
model = tf.keras.Model(inputs=inputs, outputs=out_3)
return model
model = get_model()
model.compile(optimizer="adam", loss="mse")
model.fit([1, 2, 3], [0.0, 0.0, 1.0])
[[-0.327884018] [-0.109294668] [-0.218589336]] 1/1 [==============================] - 0s 280ms/step - loss: 0.6077 <keras.callbacks.History at 0x7f63d46bf190>
گزینه 2: خروجی های میانی را که می خواهید بررسی کنید در خروجی های مدل قرار دهید.
توجه داشته باشید که در چنین مواردی، ممکن است برای استفاده از Model.fit
نیاز به برخی تنظیمات داشته باشید.
def get_model():
inputs = tf.keras.layers.Input(shape=(1,))
out_1 = tf.keras.layers.Dense(4)(inputs)
out_2 = tf.keras.layers.Dense(1)(out_1)
# include intermediate values in model outputs
model = tf.keras.Model(
inputs=inputs,
outputs={
'inputs': inputs,
'out_1': out_1,
'out_2': out_2})
return model
پی دی بی
می توانید از pdb هم در ترمینال و هم در Colab برای بررسی مقادیر میانی برای اشکال زدایی استفاده کنید.
نمودار را با TensorBoard تجسم کنید
می توانید نمودار TensorFlow را با TensorBoard بررسی کنید. TensorBoard نیز در colab پشتیبانی می شود. TensorBoard یک ابزار عالی برای تجسم خلاصه ها است. میتوانید از آن برای مقایسه میزان یادگیری، وزن مدل، مقیاس گرادیان، معیارهای آموزشی/اعتبارسنجی، یا حتی مدلسازی خروجیهای میانی بین مدل TF1.x و مدل TF2 مهاجرتشده از طریق فرآیند آموزش استفاده کنید و ببینید آیا مقادیر مطابق انتظار هستند یا خیر.
پروفایل TensorFlow
TensorFlow Profiler می تواند به شما در تجسم جدول زمانی اجرا در GPU/TPU کمک کند. شما می توانید این نسخه ی نمایشی Colab را برای استفاده اصلی آن بررسی کنید.
MultiProcessRunner
MultiProcessRunner یک ابزار مفید هنگام اشکال زدایی با MultiWorkerMirroredStrategy و ParameterServerStrategy است. برای کاربرد آن می توانید به این مثال ملموس نگاهی بیندازید.
به طور خاص برای موارد این دو استراتژی، به شما توصیه می شود: 1) نه تنها تست های واحد را برای پوشش جریان آنها داشته باشید، 2) بلکه سعی کنید شکست ها را با استفاده از آن در تست واحد بازتولید کنید تا هر بار که تلاش می کنند کار توزیع شده واقعی را راه اندازی نکنید. یک تعمیر