عرض على TensorFlow.org | تشغيل في Google Colab | عرض المصدر على جيثب | تحميل دفتر |
يوضح هذا الكمبيوتر الدفتري كيفية تصحيح أخطاء خط أنابيب التدريب عند الترحيل إلى TF2. يتكون من المكونات التالية:
- الخطوات المقترحة وعينات التعليمات البرمجية لتصحيح أخطاء خط أنابيب التدريب
- أدوات التصحيح
- الموارد الأخرى ذات الصلة
أحد الافتراضات هو أن لديك رمز TF1.x ونماذج مدربة للمقارنة ، وتريد إنشاء نموذج TF2 يحقق دقة تحقق مماثلة.
لا يغطي هذا الكمبيوتر الدفتري مشكلات تصحيح الأخطاء المتعلقة بسرعة التدريب / الاستدلال أو استخدام الذاكرة.
تصحيح سير العمل
يوجد أدناه سير عمل عام لتصحيح أخطاء خطوط تدريب TF2 الخاصة بك. لاحظ أنك لست بحاجة إلى اتباع هذه الخطوات بالترتيب. يمكنك أيضًا استخدام أسلوب بحث ثنائي حيث تقوم باختبار النموذج في خطوة وسيطة وتضييق نطاق التصحيح.
إصلاح أخطاء الترجمة ووقت التشغيل
التحقق من صحة المرور إلى الأمام (في دليل منفصل)
أ. على جهاز CPU واحد
- تحقق من أن المتغيرات تم إنشاؤها مرة واحدة فقط
- تحقق من تطابق الأعداد والأسماء والأشكال المتغيرة
- إعادة تعيين جميع المتغيرات ، والتحقق من التكافؤ العددي مع تعطيل جميع العشوائية
- قم بمحاذاة توليد الأرقام العشوائية ، وتحقق من التكافؤ العددي في الاستدلال
- (اختياري) يتم تحميل نقاط الفحص بشكل صحيح وتولد نماذج TF1.x / TF2 مخرجات تعريفية
ب. على جهاز GPU / TPU واحد
ج. مع استراتيجيات متعددة الأجهزة
نموذج التحقق من صحة التكافؤ العددي التدريبي لبضع خطوات (تتوفر عينات التعليمات البرمجية أدناه)
أ. خطوة تدريب واحدة للتحقق من صحة البيانات باستخدام بيانات صغيرة وثابتة على جهاز وحدة معالجة مركزية واحدة. على وجه التحديد ، تحقق من التكافؤ العددي للمكونات التالية
- حساب الخسائر
- المقاييس
- معدل التعليم
- حساب التدرج والتحديث
ب. تحقق من الإحصائيات بعد التدريب 3 خطوات أو أكثر للتحقق من سلوكيات المحسن مثل القوة الدافعة ، مع استمرار البيانات الثابتة على جهاز وحدة المعالجة المركزية الواحدة
ج. على جهاز 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()
الذي يمكن أن يجعل العمليات العشوائية ذات الحالة تستخدم نفس المصدر عبر كل من الرسوم البيانية / الجلسات 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 في وضع الرسم البياني. اجمع الإحصائيات لخطوات التدريب الثلاث الأولى لمقارنة التكافؤ العددي.
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 في الوضع الحثيث. اجمع الإحصائيات لخطوات التدريب الثلاث الأولى لمقارنة التكافؤ العددي.
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
لاختبار النماذج ذات التكوينات المختلفة. التفاصيل مع نموذج التعليمات البرمجية .
لاحظ أنه من الممكن تشغيل واجهات برمجة التطبيقات للجلسة والتنفيذ الحثيث في نفس حالة الاختبار. توضح مقتطفات التعليمات البرمجية أدناه كيف.
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
andlogging.info
فقط في وقت التتبع ، وهو غالبًا ما لا تريده. - يدعم
tf.print
أيضًا طباعة الموترات المركبة مثلtf.RaggedTensor
وtf.sparse.SparseTensor
. - يمكنك أيضًا استخدام رد الاتصال لمراقبة المقاييس والمتغيرات. يرجى التحقق من كيفية استخدام عمليات الاسترجاعات المخصصة مع سمة logs و self.model .
tf.print مقابل وظيفة الطباعة داخل tf
# `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.Sstartibility
- إذا تم تنفيذ دالة
tf.print
tf.function
العمال ، على سبيل المثال عند استخدامTPUStrategy
أوParameterServerStrategy
، فأنت بحاجة إلى التحقق من سجلات خادم العامل / المعلمة للعثور على القيم المطبوعة. -
print
أوlogging.info
، ستتم طباعة السجلات على المنسق عند استخدامParameterServerStrategy
، وستتم طباعة السجلات على STDOUT على worker0 عند استخدام TPU.
tf.keras.Model
- عند استخدام نماذج API التسلسلية والوظيفية ، إذا كنت ترغب في طباعة القيم ، على سبيل المثال ، مدخلات النموذج أو الميزات الوسيطة بعد بعض الطبقات ، فلديك الخيارات التالية.
- اكتب طبقة مخصصة
tf.print
المدخلات. - قم بتضمين المخرجات الوسيطة التي تريد فحصها في مخرجات النموذج.
- اكتب طبقة مخصصة
- طبقات
tf.keras.layers.Lambda
لها (دي) قيود التسلسل. لتجنب مشاكل تحميل نقاط التحقق ، اكتب طبقة فرعية مخصصة بدلاً من ذلك. تحقق من مستندات API لمزيد من التفاصيل. - لا يمكنك
tf.keras.callbacks.LambdaCallback
tf.print
لم يكن لديك وصول إلى القيم الفعلية ، ولكن بدلاً من ذلك فقط إلى كائنات 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
يمكنك استخدام pdb في كل من Terminal و Colab لفحص القيم الوسيطة لتصحيح الأخطاء.
تصور الرسم البياني باستخدام TensorBoard
يمكنك فحص الرسم البياني TensorFlow باستخدام TensorBoard . TensorBoard مدعوم أيضًا على colab . TensorBoard هي أداة رائعة لتصور الملخصات. يمكنك استخدامه لمقارنة معدل التعلم ، وأوزان النموذج ، ومقياس التدرج ، ومقاييس التدريب / التحقق من الصحة ، أو حتى نموذج المخرجات الوسيطة بين نموذج TF1.x ونموذج TF2 المُرحل من خلال عملية التدريب ومعرفة ما إذا كانت القيم تبدو كما هو متوقع.
ملف تعريف TensorFlow
يمكن أن يساعدك TensorFlow Profiler في تصور الجدول الزمني للتنفيذ على وحدات معالجة الرسومات / وحدات المعالجة المركزية (TPU). يمكنك التحقق من هذا العرض التوضيحي Colab لاستخدامه الأساسي.
متعدد العمليات عداء
تعد MultiProcessRunner أداة مفيدة عند تصحيح الأخطاء باستخدام MultiWorkerMirroredStrategy و ParameterServerStrategy. يمكنك إلقاء نظرة على هذا المثال الملموس لاستخدامه.
على وجه التحديد لحالات هاتين الاستراتيجيتين ، يوصى بـ 1) ليس فقط لديك اختبارات وحدة لتغطية تدفقها ، 2) ولكن أيضًا لمحاولة إعادة إنتاج الفشل باستخدامه في اختبار الوحدة لتجنب إطلاق وظيفة حقيقية موزعة في كل مرة عندما يحاولون إصلاح.