SavedModels از TF Hub در TensorFlow 2

فرمت SavedModel TensorFlow 2 روشی توصیه شده برای به اشتراک گذاری مدل های از پیش آموزش دیده و قطعات مدل در TensorFlow Hub است. این فرمت قدیمی تر TF1 Hub را جایگزین می کند و با مجموعه جدیدی از API ها عرضه می شود.

این صفحه نحوه استفاده مجدد از TF2 SavedModels را در برنامه TensorFlow 2 با API سطح پایین hub.load() و wrapper hub.KerasLayer آن توضیح می دهد. (معمولا hub.KerasLayer با tf.keras.layers دیگر ترکیب می‌شود تا یک مدل Keras یا model_fn یک برآوردگر TF2 بسازد.) این APIها همچنین می‌توانند مدل‌های قدیمی را در قالب TF1 Hub بارگیری کنند، در محدوده‌های محدود، به راهنمای سازگاری مراجعه کنید.

کاربران TensorFlow 1 می توانند به TF 1.15 آپدیت کنند و سپس از همان API ها استفاده کنند. نسخه های قدیمی تر TF1 کار نمی کنند.

استفاده از SavedModels از TF Hub

استفاده از SavedModel در Keras

Keras API سطح بالای 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"),
])

Text classification colab نمونه کاملی از نحوه آموزش و ارزیابی چنین طبقه بندی کننده ای است.

وزن های مدل در hub.KerasLayer به طور پیش فرض روی غیر قابل آموزش تنظیم شده است. برای نحوه تغییر آن به بخش تنظیم دقیق زیر مراجعه کنید. وزن‌ها بین همه برنامه‌های یک شی لایه به اشتراک گذاشته می‌شوند، طبق معمول در Keras.

استفاده از SavedModel در برآوردگر

کاربران API تخمین‌گر TensorFlow برای آموزش توزیع‌شده می‌توانند با نوشتن model_fn خود بر حسب hub.KerasLayer در میان tf.keras.layers از SavedModels از TF Hub استفاده کنند.

پشت صحنه: SavedModel بارگیری و ذخیره سازی

با استفاده از SavedModel از TensorFlow Hub (یا سایر سرورهای HTTPS که پروتکل میزبانی آن را پیاده‌سازی می‌کنند) آن را دانلود می‌کند و اگر قبلاً موجود نیست، آن را به سیستم فایل محلی از حالت فشرده خارج می‌کند. متغیر محیطی TFHUB_CACHE_DIR می‌توان طوری تنظیم کرد که مکان موقت پیش‌فرض را برای ذخیره‌سازی ذخیره‌شده‌های دانلود شده و فشرده‌نشده ذخیره‌سازی کند. برای جزئیات، به ذخیره پنهان مراجعه کنید.

استفاده از SavedModel در TensorFlow سطح پایین

دسته مدل

SavedModels را می توان از یک handle مشخص بارگیری کرد، جایی که handle یک مسیر سیستم فایل، URL مدل معتبر TFhub.dev است (به عنوان مثال "https://tfhub.dev/..."). نشانی‌های وب مدل‌های Kaggle منعکس‌کننده دسته‌بندی‌های TFhub.dev مطابق با شرایط ما و مجوز مرتبط با دارایی‌های مدل هستند، به‌عنوان مثال، «https://www.kaggle.com/...». دستگیره های Kaggle Models معادل دسته TFhub.dev مربوطه خود هستند.

تابع hub.load(handle) یک SavedModel را دانلود و از حالت فشرده خارج می کند (مگر اینکه handle قبلاً یک مسیر سیستم فایل باشد) و سپس نتیجه بارگیری آن را با تابع داخلی tf.saved_model.load() TensorFlow برمی گرداند. بنابراین، hub.load() می تواند هر SavedModel معتبری را مدیریت کند (برخلاف hub.Module قبلی خود برای TF1).

موضوع پیشرفته: پس از بارگذاری از SavedModel چه انتظاری باید داشت

بسته به محتویات SavedModel، نتیجه obj = hub.load(...) را می توان به روش های مختلفی فراخوانی کرد (همانطور که با جزئیات بیشتر در راهنمای SavedModel TensorFlow توضیح داده شده است:

  • امضاهای ارائه شده SavedModel (در صورت وجود) به عنوان فرهنگ لغت توابع مشخص نشان داده می شوند و می توان آنها را مانند tensors_out = obj.signatures["serving_default"](**tensors_in) نامید، با فرهنگ لغت تانسورها که با ورودی و خروجی مربوطه کلید می شوند. نام ها و تابع شکل امضا و محدودیت های نوع d.

  • روش‌های @tf.function -decorated شی ذخیره‌شده (در صورت وجود) به‌عنوان اشیاء tf.function بازیابی می‌شوند که می‌توانند با تمام ترکیب‌های آرگومان‌های Tensor و non-Tensor که تابع tf.قبل از ذخیره‌سازی برای آنها ردیابی شده است، فراخوانی شوند. به طور خاص، اگر یک متد obj.__call__ با ردیابی مناسب وجود داشته باشد، خود obj را می توان مانند یک تابع پایتون فراخوانی کرد. یک مثال ساده می تواند شبیه output_tensor = obj(input_tensor, training=False) باشد.

این آزادی زیادی در رابط هایی که SavedModels می تواند پیاده سازی کند، باقی می گذارد. رابط کاربری SavedModels قابل استفاده مجدد برای obj قراردادهایی را ایجاد می کند که کد مشتری، از جمله آداپتورهایی مانند hub.KerasLayer ، بدانند چگونه از SavedModel استفاده کنند.

برخی از SavedModel ها ممکن است از این قرارداد پیروی نکنند، به خصوص مدل های کامل که قرار نیست در مدل های بزرگتر مورد استفاده مجدد قرار گیرند، و فقط امضاهای ارائه می دهند.

متغیرهای قابل آموزش در یک SavedModel به‌عنوان قابل آموزش بارگذاری مجدد می‌شوند و tf.GradientTape آنها را به‌طور پیش‌فرض تماشا می‌کند. برای برخی از اخطارها، بخش تنظیم دقیق زیر را ببینید و برای شروع از آن اجتناب کنید. حتی اگر می‌خواهید تنظیم دقیق کنید، ممکن است بخواهید ببینید آیا obj.trainable_variables توصیه می‌کند که فقط زیرمجموعه‌ای از متغیرهای قابل آموزش اولیه را دوباره آموزش دهید.

ایجاد SavedModels برای TF Hub

بررسی اجمالی

SavedModel فرمت سریال سازی استاندارد TensorFlow برای مدل های آموزش دیده یا قطعات مدل است. وزن های آموزش دیده مدل را همراه با عملیات TensorFlow دقیق برای انجام محاسبات ذخیره می کند. می توان آن را مستقل از کدی که آن را ایجاد کرده استفاده کرد. به طور خاص، می‌توان آن را در میان APIهای مختلف ساخت مدل سطح بالا مانند Keras استفاده مجدد کرد، زیرا عملیات TensorFlow زبان اصلی مشترک آنهاست.

پس انداز از Keras

شروع با TensorFlow 2، tf.keras.Model.save() و tf.keras.models.save_model() به طور پیش فرض به فرمت SavedModel (نه HDF5). SavedModel های به دست آمده که می توانند با hub.load() , hub.KerasLayer و آداپتورهای مشابه برای دیگر API های سطح بالا به محض در دسترس شدن استفاده شوند.

برای به اشتراک گذاشتن یک مدل کامل 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_ex/t.f. مراجعه کنید. ).

صرفه جویی از 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 like

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 و غیره)

رابط مدلی را انتخاب کنید که به خوبی با جریان گرادیان بازی کند، به عنوان مثال، logits خروجی به جای احتمالات softmax یا پیش‌بینی‌های top-k.

اگر مدل از روش‌های انصرافی، نرمال‌سازی دسته‌ای یا تکنیک‌های آموزشی مشابهی استفاده می‌کند که شامل فراپارامترها می‌شود، آن‌ها را روی مقادیری تنظیم کنید که در بسیاری از مشکلات هدف مورد انتظار و اندازه‌های دسته‌ای منطقی هستند. (از زمان نگارش این مقاله، صرفه جویی در Keras به مصرف کنندگان اجازه نمی دهد آنها را تنظیم کنند.)

تنظیم‌کننده‌های وزن در لایه‌های جداگانه ذخیره می‌شوند (با ضرایب قدرت منظم‌سازی آنها)، اما تنظیم وزن از داخل بهینه‌ساز (مانند tf.keras.optimizers.Ftrl.l1_regularization_strength=...) از بین می‌رود. بر این اساس به مصرف کنندگان SavedModel خود توصیه کنید.