کوانتیزاسیون پس از آموزش یک تکنیک تبدیلی است که می تواند اندازه مدل را کاهش دهد و در عین حال تاخیر CPU و شتاب دهنده سخت افزار را با کاهش کمی در دقت مدل بهبود بخشد. هنگامی که با استفاده از مبدل LiteRT آن را به قالب LiteRT تبدیل میکنید، میتوانید یک مدل TensorFlow شناور را که قبلاً آموزش دیدهاید، کمی کنید.
روش های بهینه سازی
چندین گزینه کمی سازی پس از آموزش وجود دارد که می توانید از بین آنها انتخاب کنید. در اینجا جدول خلاصه ای از انتخاب ها و مزایایی که آنها ارائه می دهند آورده شده است:
تکنیک | مزایا | سخت افزار |
---|---|---|
کوانتیزاسیون دامنه دینامیکی | 4 برابر کوچکتر، 2x-3 برابر سرعت | CPU |
کوانتیزاسیون کامل اعداد صحیح | 4 برابر کوچکتر، 3 برابر افزایش سرعت | CPU، Edge TPU، میکروکنترلرها |
کوانتیزاسیون Float16 | 2 برابر کوچکتر، شتاب GPU | CPU، GPU |
درخت تصمیم زیر می تواند به تعیین اینکه کدام روش کوانتیزاسیون پس از آموزش برای مورد استفاده شما بهترین است کمک کند:
بدون کوانتیزاسیون
تبدیل به یک مدل TFLite بدون کوانتیزاسیون یک نقطه شروع توصیه شده است. این یک مدل TFLite شناور ایجاد می کند.
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) tflite_quant_model = converter.convert()
توصیه میکنیم این کار را به عنوان گام اولیه انجام دهید تا تأیید کنید که اپراتورهای مدل TF اصلی با TFLite سازگار هستند و همچنین میتوانند بهعنوان پایهای برای اشکالزدایی خطاهای کمیسازی معرفیشده توسط روشهای کوانتیسازی بعدی پس از آموزش استفاده شوند. به عنوان مثال، اگر یک مدل TFLite کوانتیزه شده نتایج غیرمنتظره ای تولید کند، در حالی که مدل TFLite شناور دقیق باشد، می توانیم مشکل را به خطاهای معرفی شده توسط نسخه کوانتیزه شده عملگرهای TFLite محدود کنیم.
کوانتیزاسیون دامنه دینامیکی
کوانتیزهسازی محدوده دینامیکی استفاده از حافظه را کاهش میدهد و محاسبات سریعتر را بدون نیاز به ارائه یک مجموعه داده نماینده برای کالیبراسیون فراهم میکند. این نوع کوانتیزه کردن به صورت ایستا فقط وزن ها را از نقطه شناور به عدد صحیح در زمان تبدیل کوانتیزه می کند که دقت 8 بیتی را ارائه می دهد:
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] tflite_quant_model = converter.convert()
برای کاهش بیشتر تأخیر در حین استنتاج، عملگرهای «محدوده پویا» به صورت پویا فعالسازیها را بر اساس محدوده آنها تا ۸ بیت کوانته میکنند و محاسبات را با وزنها و فعالسازیهای ۸ بیتی انجام میدهند. این بهینهسازی تأخیرهایی نزدیک به استنتاج با نقطه کاملاً ثابت ارائه میکند. با این حال، خروجیها همچنان با استفاده از نقطه شناور ذخیره میشوند، بنابراین سرعت افزایش یافته عملیاتهای محدوده دینامیکی کمتر از یک محاسبه کامل نقطه ثابت است.
کوانتیزاسیون کامل اعداد صحیح
با اطمینان از اینکه تمام ریاضیات مدل کوانتیزه شده اند، می توانید بهبودهای بیشتری در تأخیر، کاهش در استفاده از حافظه اوج و سازگاری با دستگاه های سخت افزاری یا شتاب دهنده های فقط عدد صحیح دریافت کنید.
برای کوانتیزاسیون کامل اعداد صحیح، باید محدوده، یعنی (حداکثر، حداکثر) همه تانسورهای ممیز شناور در مدل را کالیبره یا تخمین بزنید. برخلاف تانسورهای ثابت مانند وزن ها و بایاس ها، تانسورهای متغیر مانند ورودی مدل، فعال سازی ها (خروجی های لایه های میانی) و خروجی مدل نمی توانند کالیبره شوند مگر اینکه چند چرخه استنتاج را اجرا کنیم. در نتیجه، مبدل به یک مجموعه داده نماینده برای کالیبره کردن آنها نیاز دارد. این مجموعه داده می تواند یک زیرمجموعه کوچک (حدود 100-500 نمونه) از داده های آموزشی یا اعتبار سنجی باشد. به تابع representative_dataset()
در زیر مراجعه کنید.
از نسخه TensorFlow 2.7، می توانید مجموعه داده نماینده را از طریق یک امضا به عنوان مثال زیر مشخص کنید:
def representative_dataset(): for data in dataset: yield { "image": data.image, "bias": data.bias, }
اگر بیش از یک امضا در مدل TensorFlow داده شده وجود دارد، می توانید مجموعه داده های متعدد را با تعیین کلیدهای امضا مشخص کنید:
def representative_dataset(): # Feed data set for the "encode" signature. for data in encode_signature_dataset: yield ( "encode", { "image": data.image, "bias": data.bias, } ) # Feed data set for the "decode" signature. for data in decode_signature_dataset: yield ( "decode", { "image": data.image, "hint": data.hint, }, )
شما می توانید مجموعه داده نماینده را با ارائه یک لیست تانسور ورودی ایجاد کنید:
def representative_dataset(): for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100): yield [tf.dtypes.cast(data, tf.float32)]
از آنجایی که TensorFlow نسخه 2.7 است، توصیه می کنیم از رویکرد مبتنی بر امضا بر روی رویکرد مبتنی بر فهرست تانسور ورودی استفاده کنید زیرا ترتیب تانسور ورودی به راحتی قابل تغییر است.
برای اهداف آزمایشی، می توانید از یک مجموعه داده ساختگی به صورت زیر استفاده کنید:
def representative_dataset(): for _ in range(100): data = np.random.rand(1, 244, 244, 3) yield [data.astype(np.float32)]
عدد صحیح با بازگشتی شناور (با استفاده از ورودی/خروجی شناور پیشفرض)
برای اینکه یک مدل را به طور کامل به عدد صحیح تبدیل کنید، اما از عملگرهای شناور زمانی که پیاده سازی عدد صحیح ندارند استفاده کنید (برای اطمینان از اینکه تبدیل به راحتی انجام می شود)، از مراحل زیر استفاده کنید:
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_dataset tflite_quant_model = converter.convert()
فقط عدد صحیح
ایجاد مدلهای فقط عدد صحیح یک مورد رایج برای LiteRT برای میکروکنترلرها و TPUهای Coral Edge است.
علاوه بر این، برای اطمینان از سازگاری با دستگاههای فقط عدد صحیح (مانند میکروکنترلرهای 8 بیتی) و شتابدهندهها (مانند Coral Edge TPU)، میتوانید با استفاده از مراحل زیر، کوانتیزهسازی کامل اعداد صحیح را برای همه عملیاتها از جمله ورودی و خروجی اعمال کنید:
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_dataset converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.inference_input_type = tf.int8 # or tf.uint8 converter.inference_output_type = tf.int8 # or tf.uint8 tflite_quant_model = converter.convert()
کوانتیزاسیون Float16
شما می توانید اندازه یک مدل ممیز شناور را با کمی کردن وزن ها به float16 کاهش دهید، استاندارد IEEE برای اعداد ممیز شناور 16 بیتی. برای فعال کردن کوانتیزه کردن وزنها با float16، از مراحل زیر استفاده کنید:
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_types = [tf.float16] tflite_quant_model = converter.convert()
مزایای کوانتیزاسیون float16 به شرح زیر است:
- اندازه مدل را تا نصف کاهش می دهد (زیرا همه وزنه ها نصف اندازه اصلی خود می شوند).
- کمترین افت را در دقت ایجاد می کند.
- برخی از نمایندگان (مثلاً نماینده GPU) را پشتیبانی می کند که می توانند مستقیماً روی داده های float16 کار کنند و در نتیجه اجرای سریعتر از محاسبات float32 را به همراه دارند.
معایب کوانتیزاسیون float16 به شرح زیر است:
- به اندازه یک کوانتیزه کردن به ریاضیات نقطه ثابت تأخیر را کاهش نمی دهد.
- بهطور پیشفرض، یک مدل کوانتیزهشده float16 مقادیر وزنها را هنگام اجرا بر روی CPU به float32 «کمکمسازی» میکند. (توجه داشته باشید که نماینده GPU این کمسنجی را انجام نمیدهد، زیرا میتواند روی دادههای float16 کار کند.)
فقط عدد صحیح: فعال سازی 16 بیتی با وزن 8 بیتی (تجربی)
این یک طرح کوانتیزاسیون تجربی است. این شبیه به طرح "فقط عدد صحیح" است، اما فعالسازیها بر اساس محدوده آنها تا 16 بیت، وزنها در عدد صحیح 8 بیتی و بایاس به عدد صحیح 64 بیتی کوانتیزه میشوند. این به عنوان کوانتیزاسیون 16x8 بیشتر نامیده می شود.
مزیت اصلی این کوانتیزاسیون این است که می تواند دقت را به طور قابل توجهی بهبود بخشد، اما فقط کمی اندازه مدل را افزایش می دهد.
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.representative_dataset = representative_dataset converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8] tflite_quant_model = converter.convert()
اگر کوانتیزاسیون 16x8 برای برخی از عملگرها در مدل پشتیبانی نمیشود، مدل همچنان میتواند کوانتیزه شود، اما عملگرهای پشتیبانینشده در شناور نگه داشته میشوند. گزینه زیر باید به target_spec اضافه شود تا این امکان فراهم شود.
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) converter.representative_dataset = representative_dataset converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8, tf.lite.OpsSet.TFLITE_BUILTINS] tflite_quant_model = converter.convert()
نمونه هایی از موارد استفاده که در آن بهبود دقت ارائه شده توسط این طرح کوانتیزاسیون عبارتند از:
- وضوح فوق العاده،
- پردازش سیگنال صوتی مانند حذف نویز و شکل دهی پرتو،
- حذف نویز تصویر،
- بازسازی HDR از یک تصویر واحد.
عیب این کوانتیزاسیون این است:
- در حال حاضر به دلیل عدم اجرای بهینه هسته، استنتاج به طور قابل توجهی کندتر از عدد صحیح کامل 8 بیتی است.
- در حال حاضر با نمایندگان TFLite تسریع شده سخت افزاری موجود ناسازگار است.
آموزش این حالت کوانتیزاسیون را می توانید در اینجا بیابید.
دقت مدل
از آنجایی که وزنهها پس از تمرین کوانتیزه میشوند، به خصوص برای شبکههای کوچکتر میتوان دقت را کاهش داد. مدل های کاملاً کوانتیزه شده از پیش آموزش دیده برای شبکه های خاص در مدل های Kaggle ارائه شده است. بررسی دقت مدل کوانتیزه شده برای تأیید اینکه هر گونه کاهش دقت در محدوده قابل قبول است، مهم است. ابزارهایی برای ارزیابی دقت مدل LiteRT وجود دارد.
از طرف دیگر، اگر افت دقت خیلی زیاد است، استفاده از آموزش آگاهی از کوانتیزاسیون را در نظر بگیرید. با این حال، انجام این کار به تغییراتی در طول آموزش مدل نیاز دارد تا گرههای کوانتیزهسازی جعلی اضافه شود، در حالی که تکنیکهای کوانتیزاسیون پس از آموزش در این صفحه از یک مدل از پیش آموزشدیده موجود استفاده میکنند.
نمایشی برای تانسورهای کوانتیزه
کوانتیزاسیون 8 بیتی مقادیر ممیز شناور را با استفاده از فرمول زیر تقریب می زند.
\[real\_value = (int8\_value - zero\_point) \times scale\]
نمایندگی دارای دو بخش اصلی است:
وزنهای هر محور (معروف به هر کانال) یا وزنهای هر تانسور که با مقادیر مکمل int8 two در محدوده [-127، 127] با نقطه صفر برابر با 0 نشان داده میشوند.
فعالسازی/ورودیهای هر تانسور که با مقادیر مکمل int8 two در محدوده [-128، 127]، با نقطه صفر در محدوده [-128، 127] نشان داده میشوند.
برای مشاهده دقیق طرح کوانتیزاسیون ما، لطفاً مشخصات کمی سازی ما را ببینید. فروشندگان سخت افزاری که می خواهند به رابط نماینده TensorFlow Lite متصل شوند، تشویق می شوند تا طرح کوانتیزاسیون را که در آنجا توضیح داده شده است، پیاده سازی کنند.