تحديد الكمي بعد التدريب

إنّ تقدير كمية البيانات بعد التدريب هو أسلوب إحالة ناجحة يمكن أن يقلّل من حجم النموذج ويحسّن أيضًا وقت استجابة وحدة المعالجة المركزية (CPU) ومسرِّع الأجهزة، مع انخفاض بسيط في دقة النموذج. يمكنك تحديد كمية نموذج TensorFlow العائم المدرَّب مسبقًا عند تحويله إلى تنسيق TensorFlow Lite باستخدام TensorFlow Lite Converter.

طرق التحسين

هناك العديد من خيارات التحديد الكمي بعد التدريب للاختيار من بينها. فيما يلي جدول ملخص للخيارات والمزايا التي تقدمها:

الأسلوب المزايا أجهزة
كمية النطاق الديناميكي أصغر بـ 4 مرات، وبسرعة أكبر 2x-3x وحدة معالجة مركزية (CPU)
تحديد الكمي الكامل للأعداد الصحيحة أصغر بـ 4 مرات، وأسرع بمقدار 3 مرات وحدة المعالجة المركزية (CPU) ووحدة معالجة الموصّلات (TPU) في متصفّح Edge ووحدات التحكّم الدقيق
كمية التعويم 16 أصغر بمرتين، مع تسريع وحدة معالجة الرسومات وحدة المعالجة المركزية (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()

لتقليل وقت الاستجابة أثناء الاستنتاج بشكل أكبر، تحدّد عوامل التشغيل ذات النطاق الديناميكي عمليات التفعيل بشكل ديناميكي استنادًا إلى نطاقها الذي يصل إلى 8 بت، وتُجري عمليات حسابية بأوزان 8 بت وعمليات تفعيل. يوفّر هذا التحسين فترات توقُّف قريبة من استنتاجات النقاط الثابتة بالكامل. ومع ذلك، لا تزال المخرجات يتم تخزينها باستخدام النقطة العائمة، لذا فإن السرعة المتزايدة لعمليات النطاق الديناميكي تكون أقل من العمليات الحسابية الكاملة للنقاط الثابتة.

التحديد الكامل للأعداد الصحيحة

يمكنك الحصول على المزيد من التحسينات في وقت الاستجابة، وخفض معدّل استخدام الذاكرة في أوقات الذروة، والتوافق مع الأجهزة أو مسرِّعات الأداء ذات الأعداد الصحيحة فقط، من خلال التأكّد من تحديد جميع العمليات الحسابية للنماذج.

للحصول على الكمية الكاملة للأعداد الصحيحة، تحتاج إلى معايرة أو تقدير النطاق، أي (الحد الأدنى، الحد الأقصى) لجميع نقاط التوتر العائمة في النموذج. لا يمكن معايرة دوال العشرات الثابتة مثل الأوزان والانحيازات، مثل مدخلات النماذج وعمليات التفعيل (مخرجات الطبقات الوسيطة) وناتج النموذج ما لم نُشغِّل بعض دورات الاستنتاج. ونتيجة لذلك، يتطلب المحول مجموعة بيانات تمثيلية لمعايرتها. يمكن أن تكون مجموعة البيانات هذه مجموعة فرعية صغيرة (حوالي 100-500 عينة) من بيانات التدريب أو بيانات التحقق من الصحة. راجِع الدالة representative_dataset() أدناه.

من الإصدار 2.7 من TensorFlow، يمكنك تحديد مجموعة البيانات التمثيلية من خلال توقيع كما يلي:

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)]

بما أنّ الإصدار 2.7 من TensorFlow، ننصح باستخدام النهج القائم على التوقيعات بدلاً من النهج المستند إلى قائمة مقياس الإدخال لأنه يمكن قلب ترتيب مترابط الإدخال بسهولة.

لأغراض الاختبار، يمكنك استخدام مجموعة بيانات وهمية على النحو التالي:

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()

العدد الصحيح فقط

إنّ إنشاء نماذج بأعداد صحيحة فقط هو من حالات الاستخدام الشائعة لـ TensorFlow Lite مع وحدات التحكّم الدقيق وCoral Edge TPUs.

علاوة على ذلك، ولضمان التوافق مع الأجهزة ذات الأعداد الصحيحة فقط (مثل وحدات التحكم الدقيقة ذات 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()

كمية التعويم 16

يمكنك تقليل حجم نموذج النقطة العائمة عن طريق قياس القيم الترجيحية لتكون عائمة 16، وهو معيار معهد هندسة المعلومات (IEEE) لأرقام النقاط العائمة 16 بت. لتفعيل تحديد الكميات العشري للأوزان، اتّبِع الخطوات التالية:

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()

في ما يلي مزايا التجميع العائم 16:

  • ويقلل حجم النموذج إلى النصف (حيث تصبح جميع الأوزان نصف حجمها الأصلي).
  • تسبب الحد الأدنى من الفقدان في الدقة.
  • وهو يتوافق مع بعض المفوَّضين (مثل المفوَّضين بوحدة معالجة الرسومات) الذين يمكنهم العمل مباشرةً على بيانات العدد العشري 16، ما يؤدي إلى تنفيذ أسرع من العمليات الحسابية العائمة32.

وفي ما يلي عيوب تقدير الكمّ float16:

  • ولا تقلّل هذه الدالة وقت الاستجابة بقدر ما يقلل من سرعة حساب النقاط الثابتة.
  • بشكل تلقائي، سيعمل النموذج الكمي float16 على "تحديد كمية" قيم الترجيح إلى float32 عند تشغيله على وحدة المعالجة المركزية (CPU). (يُرجى العلم أنّ تفويض وحدة معالجة الرسومات لن يُجري عملية تحديد الكمّية، لأنّه يمكن أن يعمل على بيانات 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()

إذا لم يكن قياس الكمية 16×8 متاحًا لبعض عوامل التشغيل في النموذج، فلا يزال من الممكن قياس النموذج، ولكن مع الاحتفاظ بالعوامل غير المتوافقة في عدد عائم. يجب إضافة الخيار التالي إلى 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()

ومن أمثلة حالات الاستخدام التي يتم فيها تحسين الدقة التي يوفّرها مخطط الكمّ هذا:

  • super-resolution,
  • معالجة الإشارات الصوتية مثل إلغاء الضوضاء والإنشاء الشعاعي،
  • إزالة تشويش الصور
  • إعادة إنشاء النطاق العالي الديناميكية من صورة واحدة.

عيب هذا الكم هو:

  • يكون الاستنتاج حاليًا أبطأ بشكل ملحوظ من عدد صحيح كامل بمعدّل 8 بت بسبب عدم توفّر تنفيذ نواة محسَّنة.
  • وهو غير متوافق حاليًا مع تفويضات TFLite الحالية التي مسرَّعة على الأجهزة.

يمكنك العثور هنا على دليل توجيهي لوضع الكمية هذا.

دقة النموذج

نظرًا لأن التقديرات هي تدريب ما بعد الكمي، فقد يكون هناك انخفاض في الدقة، وخاصة في الشبكات الأصغر. يتم توفير نماذج مجمَّعة مدرّبة مسبقًا لشبكات محددة على نماذج Kaggle . ومن المهم التحقق من دقة النموذج الكمي للتحقق من أن أي انخفاض في الدقة ضمن الحدود المقبولة. تتوفّر أدوات لتقييم دقة نموذج TensorFlow Lite.

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

تمثيل عوامل العشرات الكَمية

يعمل قياس 8 بت إلى تقريب قيم النقطة العائمة باستخدام الصيغة التالية.

\[real\_value = (int8\_value - zero\_point) \times scale\]

يتكون التمثيل من جزأين رئيسيين:

  • معاملات الترجيح لكل محور (أي لكل قناة) أو لكل متسابق التي تمثلها قيم التكامل لـ int8 two في النطاق [-127, 127] بنقطة صفرية تساوي 0.

  • عمليات التفعيل/الإدخالات لكل متسابق يتم تمثيلها بقيم التكملة لـ int8 two في النطاق [-128، 127]، مع نقطة صفرية في النطاق [-128، 127].

للحصول على عرض تفصيلي لنظام الكمية، يُرجى الاطّلاع على مواصفات الكمّية. نشجّع مورّدي الأجهزة الذين يريدون استخدام واجهة التفويض في TensorFlow Lite على تنفيذ نظام الكمية الموضَّح هناك.