تبدیل TensorFlow RNN به LiteRT

نمای کلی

LiteRT از تبدیل مدل‌های TensorFlow RNN به عملیات LSTM ادغام‌شده‌ی LiteRT پشتیبانی می‌کند. عملیات ادغام‌شده برای به حداکثر رساندن عملکرد پیاده‌سازی‌های هسته‌ی زیربنایی خود و همچنین ارائه رابط سطح بالاتر برای تعریف تبدیل‌های پیچیده مانند کوانتیزه‌سازی وجود دارند.

از آنجایی که انواع مختلفی از APIهای RNN در TensorFlow وجود دارد، رویکرد ما دو جنبه داشته است:

  1. پشتیبانی بومی برای APIهای استاندارد TensorFlow RNN مانند Keras LSTM ارائه دهید. این گزینه توصیه می‌شود.
  2. یک رابط کاربری در زیرساخت تبدیل برای پیاده‌سازی‌های RNN تعریف‌شده توسط کاربر فراهم کنید تا به LiteRT متصل شده و تبدیل شوند. ما چند نمونه آماده از چنین تبدیلی را با استفاده از رابط‌های RNN LSTMCellSimple و LayerNormalizedLSTMCellSimple از lingvo ارائه می‌دهیم.

رابط برنامه‌نویسی مبدل

این ویژگی بخشی از نسخه ۲.۳ تنسورفلو است. همچنین از طریق tf-nightly pip یا از طریق head در دسترس است.

این قابلیت تبدیل هنگام تبدیل به LiteRT از طریق یک SavedModel یا مستقیماً از مدل Keras در دسترس است. به مثال‌های کاربردی مراجعه کنید.

از مدل ذخیره شده

# build a saved model. Here concrete_function is the exported function
# corresponding to the TensorFlow model containing one or more
# Keras LSTM layers.
saved_model, saved_model_dir = build_saved_model_lstm(...)
saved_model.save(saved_model_dir, save_format="tf", signatures=concrete_func)

# Convert the model.
converter = TFLiteConverter.from_saved_model(saved_model_dir)
tflite_model = converter.convert()

از مدل کراس

# build a Keras model
keras_model = build_keras_lstm(...)

# Convert the model.
converter = TFLiteConverter.from_keras_model(keras_model)
tflite_model = converter.convert()

مثال

نرم‌افزار Keras LSTM to LiteRT Colab نحوه‌ی استفاده‌ی سرتاسری از مفسر LiteRT را نشان می‌دهد.

API های TensorFlow RNN پشتیبانی می شوند

ما از تبدیل آماده‌ی Keras LSTM به LiteRT پشتیبانی می‌کنیم. برای جزئیات بیشتر در مورد نحوه‌ی کار، لطفاً به رابط Keras LSTM مراجعه کنید. و به منطق تبدیل اینجا .

همچنین مهم است که قرارداد LSTM مربوط به LiteRT را با توجه به تعریف عملیات Keras برجسته کنیم:

  1. بُعد ۰ تانسور ورودی ، اندازه دسته (batch size) است.
  2. بُعد ۰ تانسور recurrent_weight تعداد خروجی‌ها است.
  3. تنسورهای weight و recurrent_kernel جابجا شده‌اند.
  4. تانسورهای وزن جابجا شده، recurrent_kernel جابجا شده و بایاس به ۴ تانسور با اندازه مساوی در امتداد بعد ۰ تقسیم می‌شوند. این تانسورها مربوط به دروازه ورودی، دروازه فراموشی، سلول و دروازه خروجی هستند.

انواع Keras LSTM

رشته تحصیلی زمان

کاربران می‌توانند زمان اصلی یا بدون زمان اصلی را انتخاب کنند. Keras LSTM یک ویژگی زمان اصلی را در ویژگی‌های تعریف تابع اضافه می‌کند. برای LSTM توالی یک‌طرفه، می‌توانیم به سادگی به ویژگی زمان اصلی unidirecional_sequence_lstm نگاشت کنیم.

LSTM دوطرفه

LSTM دوطرفه را می‌توان با دو لایه Keras LSTM پیاده‌سازی کرد، یکی برای جلو و دیگری برای عقب، به مثال‌ها اینجا مراجعه کنید. وقتی ویژگی go_backward را می‌بینیم، آن را به عنوان LSTM عقب‌رو تشخیص می‌دهیم، سپس LSTM جلورو و عقب‌رو را با هم گروه‌بندی می‌کنیم. این کار آینده است. در حال حاضر، این دو عملیات UnidirectionalSequenceLSTM در مدل LiteRT ایجاد می‌کند.

مثال‌های تبدیل LSTM تعریف‌شده توسط کاربر

LiteRT همچنین راهی برای تبدیل پیاده‌سازی‌های LSTM تعریف‌شده توسط کاربر ارائه می‌دهد. در اینجا ما از LSTM مربوط به Lingvo به عنوان مثالی از چگونگی پیاده‌سازی آن استفاده می‌کنیم. برای جزئیات بیشتر، لطفاً به رابط lingvo.LSTMCellSimple و منطق تبدیل آن در اینجا مراجعه کنید. ما همچنین مثالی برای یکی دیگر از تعاریف LSTM مربوط به Lingvo در رابط lingvo.LayerNormalizedLSTMCellSimple و منطق تبدیل آن در اینجا ارائه می‌دهیم.

«شبکه عصبی بازگشتی تنسورفلو خودتان را به LiteRT بیاورید»

اگر رابط RNN کاربر با رابط‌های استاندارد پشتیبانی‌شده متفاوت باشد، چند گزینه وجود دارد:

گزینه ۱: نوشتن کد آداپتور در پایتون TensorFlow برای تطبیق رابط RNN با رابط Keras RNN. این به معنای یک tf.function با حاشیه‌نویسی tf_implements روی تابع رابط RNN تولید شده است که با تابع تولید شده توسط لایه Keras LSTM یکسان است. پس از این، همان API تبدیل مورد استفاده برای Keras LSTM کار خواهد کرد.

گزینه ۲: اگر مورد بالا امکان‌پذیر نیست (مثلاً Keras LSTM فاقد برخی از قابلیت‌هایی است که در حال حاضر توسط نرمال‌سازی لایه LSTM ترکیبی LiteRT در معرض دید قرار می‌گیرد)، مبدل LiteRT را با نوشتن کد تبدیل سفارشی گسترش دهید و آن را در MLIR-pass به prepare-composite-functions در اینجا وارد کنید. رابط تابع باید مانند یک قرارداد API در نظر گرفته شود و باید شامل آرگومان‌های مورد نیاز برای تبدیل به عملیات LSTM ترکیبی LiteRT باشد - یعنی ورودی، بایاس، وزن‌ها، تصویرسازی، نرمال‌سازی لایه و غیره. ترجیح داده می‌شود که تانسورهای ارسالی به عنوان آرگومان به این تابع، رتبه شناخته شده‌ای داشته باشند (یعنی RankedTensorType در MLIR). این امر نوشتن کد تبدیلی را که می‌تواند این تانسورها را به عنوان RankedTensorType فرض کند و به تبدیل آنها به تانسورهای رتبه‌بندی شده مربوط به عملوندهای عملگر LiteRT ترکیبی کمک کند، بسیار آسان‌تر می‌کند.

یک مثال کامل از چنین جریان تبدیلی، تبدیل LSTMCellSimple به LiteRT از Lingvo است.

LSTMCellSimple در Lingvo در اینجا تعریف شده است. مدل‌های آموزش دیده با این سلول LSTM را می‌توان به صورت زیر به LiteRT تبدیل کرد:

  1. تمام کاربردهای LSTMCellSimple را در یک tf.function با حاشیه‌نویسی tf_implements که به این صورت برچسب‌گذاری شده است، قرار دهید (مثلاً lingvo.LSTMCellSimple نام حاشیه‌نویسی خوبی در اینجا خواهد بود). مطمئن شوید که tf.function تولید شده با رابط تابع مورد انتظار در کد تبدیل مطابقت دارد. این قراردادی بین نویسنده مدل که حاشیه‌نویسی را اضافه می‌کند و کد تبدیل است.
  2. مسیر prepare-composite-functions را گسترش دهید تا یک عملیات ترکیبی سفارشی به تبدیل عملیات LSTM ترکیب‌شده با LiteRT اضافه شود. به کد تبدیل LSTMCellSimple مراجعه کنید.

    قرارداد تبدیل:

  3. تانسورهای وزن و تصویر جابجا شده‌اند.

  4. ورودی، بازگشتی به {سلول، گیت ورودی، گیت فراموشی، گیت خروجی} با برش تانسور وزن جابه‌جا شده استخراج می‌شوند.

  5. بایاس {بایاس} به {سلول، گیت ورودی، گیت فراموشی، گیت خروجی} با برش تانسور بایاس استخراج می‌شوند.

  6. تصویر با برش دادن تانسور تصویر جابجا شده استخراج می‌شود.

  7. تبدیل مشابهی برای LayerNormalizedLSTMCellSimple نوشته شده است.

  8. بقیه زیرساخت تبدیل LiteRT، شامل تمام گذرگاه‌های MLIR تعریف‌شده و همچنین خروجی نهایی به بافر مسطح LiteRT، قابل استفاده مجدد هستند.

مشکلات/محدودیت‌های شناخته‌شده

  1. در حال حاضر فقط از تبدیل Keras LSTM بدون حالت (رفتار پیش‌فرض در Keras) پشتیبانی می‌شود. تبدیل Keras LSTM با حالت، موضوع کارهای آینده است.
  2. هنوز هم می‌توان یک لایه Keras LSTM با وضعیت را با استفاده از لایه Keras LSTM بدون وضعیت زیرین و مدیریت وضعیت به طور صریح در برنامه کاربر مدل‌سازی کرد. چنین برنامه TensorFlow همچنان می‌تواند با استفاده از ویژگی شرح داده شده در اینجا به LiteRT تبدیل شود.
  3. LSTM دوطرفه در حال حاضر به صورت دو عملیات UnidirectionalSequenceLSTM در LiteRT مدل‌سازی می‌شود. این عملیات با یک عملیات BidirectionalSequenceLSTM جایگزین خواهد شد.