النماذج المحفوظة من TF Hub في TensorFlow 2

يعد تنسيق SavedModel الخاص بـ TensorFlow 2 هو الطريقة الموصى بها لمشاركة النماذج المدربة مسبقًا وقطع النماذج على TensorFlow Hub. إنه يحل محل تنسيق TF1 Hub الأقدم ويأتي مع مجموعة جديدة من واجهات برمجة التطبيقات.

تشرح هذه الصفحة كيفية إعادة استخدام TF2 SavedModels في برنامج TensorFlow 2 باستخدام واجهة برمجة تطبيقات hub.load() ذات المستوى المنخفض ومجمع hub.KerasLayer الخاص بها. (عادةً، يتم دمج hub.KerasLayer مع tf.keras.layers أخرى لإنشاء نموذج Keras أو model_fn لمقدر TF2.) يمكن لواجهات برمجة التطبيقات هذه أيضًا تحميل النماذج القديمة بتنسيق TF1 Hub، ضمن الحدود، راجع دليل التوافق .

يمكن لمستخدمي TensorFlow 1 التحديث إلى TF 1.15 ثم استخدام نفس واجهات برمجة التطبيقات. الإصدارات الأقدم من TF1 لا تعمل.

استخدام SavedModels من TF Hub

باستخدام SavedModel في Keras

Keras هي واجهة برمجة تطبيقات TensorFlow عالية المستوى لبناء نماذج التعلم العميق من خلال تكوين كائنات طبقة Keras. توفر مكتبة tensorflow_hub فئة hub.KerasLayer التي تتم تهيئتها باستخدام عنوان URL (أو مسار نظام الملفات) الخاص بـ SavedModel ثم توفر الحساب من SavedModel، بما في ذلك أوزانها المدربة مسبقًا.

فيما يلي مثال على استخدام تضمين نص تم تدريبه مسبقًا:

import tensorflow as tf
import tensorflow_hub as hub

hub_url = "https://tfhub.dev/google/nnlm-en-dim128/2"
embed = hub.KerasLayer(hub_url)
embeddings = embed(["A long sentence.", "single-word", "http://example.com"])
print(embeddings.shape, embeddings.dtype)

من هنا، يمكن بناء مصنف النص بطريقة Keras المعتادة:

model = tf.keras.Sequential([
    embed,
    tf.keras.layers.Dense(16, activation="relu"),
    tf.keras.layers.Dense(1, activation="sigmoid"),
])

يعد كولاب تصنيف النص مثالاً كاملاً لكيفية تدريب وتقييم مثل هذا المصنف.

يتم تعيين أوزان النموذج في hub.KerasLayer على غير قابلة للتدريب بشكل افتراضي. راجع القسم الخاص بالضبط الدقيق أدناه لمعرفة كيفية تغيير ذلك. تتم مشاركة الأوزان بين جميع التطبيقات لنفس كائن الطبقة، كما هو معتاد في Keras.

استخدام SavedModel في المقدر

يمكن لمستخدمي واجهة برمجة التطبيقات Estimator API الخاصة بـ TensorFlow للتدريب الموزع استخدام SavedModels من TF Hub عن طريق كتابة model_fn الخاص بهم من حيث hub.KerasLayer من بين tf.keras.layers الأخرى.

خلف الكواليس: تنزيل SavedModel وتخزينه مؤقتًا

يؤدي استخدام SavedModel من TensorFlow Hub (أو خوادم HTTPS الأخرى التي تنفذ بروتوكول الاستضافة الخاص بها) إلى تنزيله وفك ضغطه إلى نظام الملفات المحلي إذا لم يكن موجودًا بالفعل. يمكن تعيين متغير البيئة TFHUB_CACHE_DIR لتجاوز الموقع المؤقت الافتراضي للتخزين المؤقت للنماذج المحفوظة التي تم تنزيلها وغير المضغوطة. لمزيد من التفاصيل، راجع التخزين المؤقت .

استخدام SavedModel في TensorFlow ذو المستوى المنخفض

مقابض النموذج

يمكن تحميل SavedModels من handle محدد، حيث يكون handle عبارة عن مسار نظام ملفات، وعنوان URL صالح لنموذج TFhub.dev (على سبيل المثال "https://tfhub.dev/..."). تعكس عناوين URL الخاصة بـ Kaggle Models مقابض TFhub.dev وفقًا لشروطنا والترخيص المرتبط بأصول النموذج، على سبيل المثال، "https://www.kaggle.com/...". المقابض من Kaggle Models تعادل مقبض TFhub.dev المقابل لها.

تقوم الدالة hub.load(handle) بتنزيل SavedModel وفك ضغطه (ما لم يكن handle هو مسار نظام ملفات بالفعل) ثم تُرجع نتيجة تحميله باستخدام وظيفة TensorFlow المضمنة tf.saved_model.load() . لذلك، يمكن لـ hub.load() التعامل مع أي SavedModel صالح (على عكس hub.Module السابق لـ TF1).

موضوع متقدم: ما يمكن توقعه من SavedModel بعد التحميل

اعتمادًا على محتويات SavedModel، يمكن استدعاء نتيجة obj = hub.load(...) بطرق مختلفة (كما هو موضح بمزيد من التفصيل في دليل SavedModel الخاص بـ TensorFlow:

  • يتم تمثيل توقيعات الخدمة الخاصة بـ SavedModel (إن وجدت) كقاموس للوظائف الملموسة ويمكن استدعاؤها مثل tensors_out = obj.signatures["serving_default"](**tensors_in) ، مع قواميس الموترات التي يتم التحكم فيها بواسطة المدخلات والمخرجات المعنية الأسماء وتخضع لشكل التوقيع وقيود نوع dtype.

  • تتم استعادة الأساليب @tf.function -decorated للكائن المحفوظ (إن وجدت) ككائنات tf.function التي يمكن استدعاؤها بواسطة جميع مجموعات الوسائط Tensor وغير Tensor التي تم تتبع الدالة tf.من أجلها قبل الحفظ. على وجه الخصوص، إذا كان هناك أسلوب obj.__call__ بتتبعات مناسبة، فيمكن استدعاء obj نفسه مثل دالة Python. يمكن أن يبدو المثال البسيط مثل output_tensor = obj(input_tensor, training=False) .

وهذا يترك حرية هائلة في الواجهات التي يمكن لـ SavedModels تنفيذها. تنشئ واجهة SavedModels القابلة لإعادة الاستخدام لـ obj اصطلاحات مثل تعليمات العميل البرمجية، بما في ذلك المحولات مثل hub.KerasLayer ، التي تعرف كيفية استخدام SavedModel.

قد لا تتبع بعض النماذج المحفوظة هذه الاتفاقية، خاصة النماذج الكاملة التي لا يُقصد إعادة استخدامها في نماذج أكبر، وتوفر فقط توقيعات الخدمة.

تتم إعادة تحميل المتغيرات القابلة للتدريب في SavedModel باعتبارها متغيرات قابلة للتدريب، وسيراقبها tf.GradientTape افتراضيًا. راجع القسم الخاص بالضبط الدقيق أدناه للتعرف على بعض التحذيرات، وفكر في تجنب ذلك كبداية. حتى إذا كنت ترغب في الضبط الدقيق، فقد ترغب في معرفة ما إذا كانت obj.trainable_variables تنصح بإعادة تدريب مجموعة فرعية فقط من المتغيرات الأصلية القابلة للتدريب.

إنشاء نماذج محفوظة لـ TF Hub

ملخص

SavedModel هو تنسيق التسلسل القياسي لـ TensorFlow للنماذج المدربة أو قطع النماذج. يقوم بتخزين الأوزان المدربة للنموذج مع عمليات TensorFlow الدقيقة لإجراء العمليات الحسابية الخاصة به. يمكن استخدامه بشكل مستقل عن الكود الذي أنشأه. على وجه الخصوص، يمكن إعادة استخدامه عبر واجهات برمجة التطبيقات المختلفة عالية المستوى لبناء النماذج مثل Keras، لأن عمليات TensorFlow هي لغتهم الأساسية المشتركة.

الحفظ من كيراس

بدءًا من TensorFlow 2، يتم تعيين tf.keras.Model.save() و tf.keras.models.save_model() بشكل افتراضي على تنسيق SavedModel (وليس HDF5). النماذج المحفوظة الناتجة والتي يمكن استخدامها مع hub.load() و hub.KerasLayer والمحولات المماثلة لواجهات برمجة التطبيقات الأخرى عالية المستوى عندما تصبح متاحة.

لمشاركة نموذج Keras كاملاً، ما عليك سوى حفظه باستخدام include_optimizer=False .

لمشاركة قطعة من نموذج Keras، اجعل القطعة نموذجًا في حد ذاتها ثم احفظها. يمكنك إما وضع الكود بهذه الطريقة من البداية ....

piece_to_share = tf.keras.Model(...)
full_model = tf.keras.Sequential([piece_to_share, ...])
full_model.fit(...)
piece_to_share.save(...)

...أو قم بقص القطعة لمشاركتها بعد حدوثها (إذا كانت تتماشى مع طبقات النموذج الكامل الخاص بك):

full_model = tf.keras.Model(...)
sharing_input = full_model.get_layer(...).get_output_at(0)
sharing_output = full_model.get_layer(...).get_output_at(0)
piece_to_share = tf.keras.Model(sharing_input, sharing_output)
piece_to_share.save(..., include_optimizer=False)

تستخدم نماذج TensorFlow على GitHub النهج السابق لـ BERT (راجع nlp/tools/export_tfhub_lib.py ، ولاحظ الانقسام بين core_model للتصدير pretrainer لاستعادة نقطة التفتيش) والأسلوب الأخير لـ ResNet (راجع Legacy/image_classification/tfhub_export.py ).

الحفظ من TensorFlow ذو المستوى المنخفض

يتطلب هذا معرفة جيدة بدليل SavedModel الخاص بـ TensorFlow.

إذا كنت تريد تقديم أكثر من مجرد توقيع تقديم، فيجب عليك تنفيذ واجهة SavedModel القابلة لإعادة الاستخدام . من الناحية النظرية، يبدو هذا

class MyMulModel(tf.train.Checkpoint):
  def __init__(self, v_init):
    super().__init__()
    self.v = tf.Variable(v_init)
    self.variables = [self.v]
    self.trainable_variables = [self.v]
    self.regularization_losses = [
        tf.function(input_signature=[])(lambda: 0.001 * self.v**2),
    ]

  @tf.function(input_signature=[tf.TensorSpec(shape=None, dtype=tf.float32)])
  def __call__(self, inputs):
    return tf.multiply(inputs, self.v)

tf.saved_model.save(MyMulModel(2.0), "/tmp/my_mul")

layer = hub.KerasLayer("/tmp/my_mul")
print(layer([10., 20.]))  # [20., 40.]
layer.trainable = True
print(layer.trainable_weights)  # [2.]
print(layer.losses)  # 0.004

الكون المثالى

يُطلق على تدريب المتغيرات التي تم تدريبها بالفعل لنموذج SavedModel المستورد مع متغيرات النموذج المحيط به اسم الضبط الدقيق لـ SavedModel. يمكن أن يؤدي هذا إلى جودة أفضل، ولكنه غالبًا ما يجعل التدريب أكثر تطلبًا (قد يستغرق وقتًا أطول، ويعتمد بشكل أكبر على المحسن ومعلماته الفائقة، ويزيد من خطر التجهيز الزائد ويتطلب زيادة مجموعة البيانات، خاصة بالنسبة لشبكات CNN). ننصح عملاء SavedModel بالنظر في الضبط الدقيق فقط بعد إنشاء نظام تدريب جيد، وفقط إذا أوصى ناشر SavedModel بذلك.

يؤدي الضبط الدقيق إلى تغيير معلمات النموذج "المستمر" التي يتم تدريبها. ولا يغير التحويلات ذات الترميز الثابت، مثل ترميز إدخال النص وتعيين الرموز المميزة للإدخالات المقابلة لها في مصفوفة التضمين.

للمستهلكين SavedModel

إنشاء hub.KerasLayer مثل

layer = hub.KerasLayer(..., trainable=True)

يتيح الضبط الدقيق للنموذج SavedModel الذي تم تحميله بواسطة الطبقة. فهو يضيف الأوزان القابلة للتدريب ومنظمي الوزن المعلنين في SavedModel إلى نموذج Keras، ويقوم بتشغيل حساب SavedModel في وضع التدريب (فكر في التسرب وما إلى ذلك).

يحتوي كولاب تصنيف الصور على مثال شامل مع ضبط اختياري.

إعادة تصدير نتيجة الضبط الدقيق

قد يرغب المستخدمون المتقدمون في حفظ نتائج الضبط الدقيق مرة أخرى في SavedModel الذي يمكن استخدامه بدلاً من النموذج الذي تم تحميله في الأصل. يمكن القيام بذلك باستخدام رمز مثل

loaded_obj = hub.load("https://tfhub.dev/...")
hub_layer = hub.KerasLayer(loaded_obj, trainable=True, ...)

model = keras.Sequential([..., hub_layer, ...])
model.compile(...)
model.fit(...)

export_module_dir = os.path.join(os.getcwd(), "finetuned_model_export")
tf.saved_model.save(loaded_obj, export_module_dir)

لمبدعي SavedModel

عند إنشاء SavedModel للمشاركة على TensorFlow Hub، فكر مسبقًا فيما إذا كان يجب على المستهلكين تحسينه وكيف، وقدم التوجيه في الوثائق.

الحفظ من نموذج Keras يجب أن يجعل جميع آليات الضبط الدقيق تعمل (توفير خسائر تنظيم الوزن، وإعلان المتغيرات القابلة للتدريب، وتتبع __call__ لكل من training=True training=False ، وما إلى ذلك)

اختر واجهة نموذج تعمل بشكل جيد مع تدفق التدرج، على سبيل المثال، سجلات الإخراج بدلاً من احتمالات softmax أو تنبؤات top-k.

إذا كان النموذج يستخدم التسرب، أو تسوية الدُفعة، أو تقنيات تدريب مماثلة تتضمن معلمات مفرطة، فقم بتعيينها على قيم منطقية عبر العديد من المشكلات المستهدفة المتوقعة وأحجام الدُفعات. (حتى كتابة هذه السطور، فإن التوفير من Keras لا يجعل من السهل السماح للمستهلكين بتعديلها.)

يتم حفظ أدوات تنظيم الوزن على الطبقات الفردية (مع معاملات قوة التنظيم الخاصة بها)، ولكن يتم فقدان تنظيم الوزن من داخل المحسن (مثل tf.keras.optimizers.Ftrl.l1_regularization_strength=...) ). تقديم المشورة للمستهلكين بشأن SavedModel الخاص بك وفقًا لذلك.