إضافة بيانات وصفية إلى نماذج TensorFlow Lite

توفّر البيانات الوصفية TensorFlow Lite معيارًا لأوصاف النماذج. تعد بيانات التعريف مصدرًا مهمًا للمعرفة حول ما يفعله النموذج ومعلومات الإدخال / المخرجات الخاصة به. تتكون بيانات التعريف من

  • الأجزاء التي يمكن للإنسان قراءتها والتي تنقل أفضل الممارسات عند استخدام النموذج،
  • الأجزاء القابلة للقراءة آليًا والتي يمكن الاستفادة منها من خلال أدوات إنشاء الرموز، مثل TensorFlow Lite Android code Builder وميزة Android Studio ML Binding.

تتم تعبئة جميع نماذج الصور المنشورة على نماذج Kaggle ببيانات وصفية.

نموذج بتنسيق بيانات وصفية

model_with_metadata
الشكل 1. نموذج TFLite مع البيانات الوصفية والملفات المرتبطة به.

يتم تحديد البيانات الوصفية للنموذج في metadata_schema.fbs، ملف FlatBuffer. وكما هو موضّح في الشكل 1، يتم تخزينها في حقل البيانات الوصفية ضمن مخطط نموذج TFLite، تحت الاسم "TFLITE_METADATA". قد يتم إرفاق ملفات مرتبطة ببعض النماذج، مثل ملفات التصنيفات للتصنيف. يتم ربط هذه الملفات بنهاية ملف النموذج الأصلي كملف ZIP باستخدام وضع"append" ZipFile (وضع 'a'). يمكن أن يشغّل مترجم TFLite تنسيق الملف الجديد بالطريقة نفسها كما في السابق. راجع تجميع الملفات المرتبطة للحصول على مزيد من المعلومات.

راجِع التعليمات أدناه حول كيفية تعبئة البيانات الوصفية وعرضها وقراءتها.

إعداد أدوات البيانات الوصفية

قبل إضافة بيانات التعريف إلى النموذج، ستحتاج إلى إعداد بيئة برمجة Python لتشغيل TensorFlow. يمكنك الاطّلاع هنا على دليل مفصّل حول كيفية إعداد هذه الميزة.

بعد إعداد بيئة برمجة Python، ستحتاج إلى تثبيت أدوات إضافية:

pip install tflite-support

أدوات البيانات الوصفية TensorFlow Lite تتوافق مع Python 3.

إضافة بيانات وصفية باستخدام Flatbuffers Python API

هناك ثلاثة أجزاء للبيانات الوصفية للنموذج في المخطط:

  1. معلومات عن النموذج - يعرض وصفًا عامًا للنموذج والعناصر، مثل بنود الترخيص. راجِع ModelMetadata.
    1. معلومات الإدخال - وصف المدخلات والمعالجة المسبقة المطلوبة مثل التسوية. راجِع SubGraphMetadata.input_tensor_metadata.
      1. معلومات الإخراج - وصف المخرجات والمعالجة اللاحقة المطلوبة مثل التعيين إلى التصنيفات. راجِع SubGraphMetadata.output_tensor_metadata.

بما أنّ TensorFlow Lite تتيح استخدام رسم فرعي واحد فقط في هذه المرحلة، ستستخدم كل من أداة إنشاء رموز TensorFlow Lite وميزة Android Studio ML Binding ModelMetadata.name وModelMetadata.description بدلاً من SubGraphMetadata.name وSubGraphMetadata.description عند عرض البيانات الوصفية وإنشاء الرموز.

أنواع الإدخال والإخراج المتوافقة

لم يتم تصميم البيانات الوصفية لـ TensorFlow Lite للإدخال والمخرجات مع وضع أنواع نماذج معيّنة في الاعتبار، بل مع أنواع إدخال ومخرجات. لا يهمّ وظيفة النموذج، طالما أنّ أنواع المدخلات والمخرجات تتكوّن من العناصر التالية أو مزيج منها، فهي متوافقة مع البيانات الوصفية TensorFlow Lite:

  • الميزة - الأرقام التي تكون أعدادً صحيحةً غير بعلامة أو العدد العائم32.
  • صورة: توفّر البيانات الوصفية حاليًا الصور بتنسيق أحمر أخضر أزرق (RGB) وصور بالتدرج الرمادي.
  • صندوق حدود - صناديق حدود مستطيلة الشكل. يتوافق المخطط مع مجموعة متنوعة من أنظمة الترقيم.

تجميع الملفات المرتبطة

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

يمكن الآن تجميع الملفات المرتبطة مع النموذج من خلال مكتبة البيانات الوصفية في بايثون. سيصبح نموذج TensorFlow Lite الجديد ملفًا مضغوطًا يحتوي على كل من النموذج والملفات المرتبطة به. يمكن فك ضغطها باستخدام أدوات zip الشائعة. يواصل تنسيق النموذج الجديد هذا استخدام امتداد الملف نفسه، .tflite. وهو متوافق مع إطار عمل TFLite الحالي ومترجم فوري. راجع حزمة البيانات الوصفية والملفات المرتبطة في النموذج للحصول على مزيد من التفاصيل.

يمكن تسجيل معلومات الملفات ذات الصلة في البيانات الوصفية. بناءً على نوع الملف والمكان الذي يتم إرفاق الملف به (أي ModelMetadata وSubGraphMetadata وTensorMetadata)، قد يطبّق أداة إنشاء الرموز على Android TensorFlow Lite تلقائيًا عمليات المعالجة السابقة أو اللاحقة على العنصر. راجع القسم <Codegen use> لكل نوع من أنواع الملفات المقترنة في المخطط للحصول على مزيد من التفاصيل.

مَعلمات التسوية والتحديد الكمي

التسوية هي أسلوب شائع للمعالجة المسبقة للبيانات في تعلُّم الآلة. الهدف من التسوية هو تغيير القيم إلى مقياس مشترك، دون تشويه الاختلافات في نطاقات القيم.

قياس كمّي النماذج هو أسلوب يتيح تمثيلاً دقيقًا للقيم التقديرية، وبشكل اختياري، عمليات التفعيل لكلّ من التخزين والحساب.

من حيث المعالجة المسبقة وما بعد المعالجة، تعتبر التسوية والتحديد الكمي خطوتين مستقلتين. في ما يلي التفاصيل.

التسوية الكمية

مثال على قيم المَعلَمات لصورة الإدخال في MobileNet للنماذج العائمة والكميّة، على التوالي.
النموذج العائم:
- المتوسط: 127.5
- std: 127.5
النموذج الكمّي:
- المتوسط: 127.5
- std: 127.5
النموذج العائم:
- نقطة الصفر: 0
- المقياس: 1.0
النموذج الكمي:
- نقطة الصفر: 128.0
- المقياس:0.0078125f




متى يتم الاستدعاء؟


الإدخالات: في حال تسوية بيانات المدخلات خلال التدريب، يجب تسوية بيانات المدخلات الخاصة بالاستنتاج وفقًا لذلك.
المخرجات: لن تتم تسوية بيانات المخرجات بشكل عام.
لا تحتاج النماذج العائمة إلى تحديد الكمي.
قد يحتاج النموذج الكمي أو لا يحتاج إلى تحديد الكميات في المعالجة السابقة/البعدية. يعتمد ذلك على نوع بيانات منسقات الإدخال/الإخراج.
- الأعداد العائمة: لا حاجة إلى الكمّي في المعالجة السابقة/البعدية. يتم تعمق عمليتَي العمليات والتحديد الكمّي في الرسم البياني للنموذج.
- int8/uint8 tensors: يحتاج إلى التحديد الكمي في المعالجة السابقة/اللاحق.


الصيغة


normalized_input = (input - mean) / std
تحديد كمية الإدخالات:
q = f / المقياس + zeroPoint
تحديد قيمة المخرجات:
f = (q - zeroPoint) * مقياس

أين توضع المعلمات
يملأه منشئ النموذج ويتم تخزينه في البيانات الوصفية للنموذج، باسم NormalizationOptions. يتم ملؤها تلقائيًا بواسطة محوّل TFLite، وتخزينها في ملف نموذج tflite.
كيف يمكن الحصول على المعلمات؟ من خلال MetadataExtractor API [2] من خلال واجهة برمجة التطبيقات TFLite Tensor [1] أو من خلال MetadataExtractor API [2]
هل تشترك النماذج العائمة والكمية في نفس القيمة؟ نعم، للنماذج العائمة والنماذج الكمّية معلمات التسوية نفسها لا، النموذج العائم لا يحتاج إلى تحديد الكمي.
هل يتم إنشاؤه تلقائيًا في معالجة البيانات من خلال أداة إنشاء TFLite Code أو ربط ربط تعلّم الآلة في Android Studio؟
نعم

نعم

[1] واجهة برمجة تطبيقات TensorFlow Lite Java وواجهة برمجة التطبيقات TensorFlow Lite C++.
[2] مكتبة أداة استخراج البيانات الوصفية

عند معالجة بيانات الصور لنماذج uint8، يتم أحيانًا تخطّي عملية التسوية والكمّي. لا بأس في إجراء ذلك عندما تكون قيم البكسل في النطاق [0, 255]. ولكن بشكل عام، يجب عليك دائمًا معالجة البيانات وفقًا لمعلمات التسوية والتقدير عند الاقتضاء.

أمثلة

يمكنك العثور على أمثلة حول كيفية تعبئة بيانات التعريف لأنواع مختلفة من النماذج هنا:

تصنيف الصور

يمكنك تنزيل النص البرمجي هنا، الذي يملأ البيانات الوصفية في mobilenet_v1_0.75_160_quantized.tflite. قم بتشغيل البرنامج النصي على النحو التالي:

python ./metadata_writer_for_image_classifier.py \
    --model_file=./model_without_metadata/mobilenet_v1_0.75_160_quantized.tflite \
    --label_file=./model_without_metadata/labels.txt \
    --export_directory=model_with_metadata

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

نظرة تفصيلية على مثال تصنيف الصور

معلومات الطراز

تبدأ البيانات الوصفية بإنشاء نموذج جديد لمعلومات:

from tflite_support import flatbuffers
from tflite_support import metadata as _metadata
from tflite_support import metadata_schema_py_generated as _metadata_fb

""" ... """
"""Creates the metadata for an image classifier."""

# Creates model info.
model_meta = _metadata_fb.ModelMetadataT()
model_meta.name = "MobileNetV1 image classifier"
model_meta.description = ("Identify the most prominent object in the "
                          "image from a set of 1,001 categories such as "
                          "trees, animals, food, vehicles, person etc.")
model_meta.version = "v1"
model_meta.author = "TensorFlow"
model_meta.license = ("Apache License. Version 2.0 "
                      "http://www.apache.org/licenses/LICENSE-2.0.")

معلومات الإدخال / الإخراج

يوضح لك هذا القسم كيفية وصف توقيع إدخال ومخرجات النموذج. يمكن استخدام هذه البيانات الوصفية من خلال أدوات إنشاء الرموز التلقائية لإنشاء رموز قبل وبعد المعالجة. لإنشاء معلومات مدخلات أو إخراج حول أداة Tenor:

# Creates input info.
input_meta = _metadata_fb.TensorMetadataT()

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()

إدخال الصورة

الصور هي نوع إدخال شائع لتعلُّم الآلة. تتيح البيانات الوصفية TensorFlow Lite استخدام معلومات مثل "مساحة الألوان" ومعلومات المعالجة المسبقة، مثل التسوية. لا يتطلب أبعاد الصورة مواصفات يدوية لأنّه يتم توفيرها من خلال شكل "مؤشر الإدخال" ويمكن استنتاجه تلقائيًا.

input_meta.name = "image"
input_meta.description = (
    "Input image to be classified. The expected image is {0} x {1}, with "
    "three channels (red, blue, and green) per pixel. Each value in the "
    "tensor is a single byte between 0 and 255.".format(160, 160))
input_meta.content = _metadata_fb.ContentT()
input_meta.content.contentProperties = _metadata_fb.ImagePropertiesT()
input_meta.content.contentProperties.colorSpace = (
    _metadata_fb.ColorSpaceType.RGB)
input_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.ImageProperties)
input_normalization = _metadata_fb.ProcessUnitT()
input_normalization.optionsType = (
    _metadata_fb.ProcessUnitOptions.NormalizationOptions)
input_normalization.options = _metadata_fb.NormalizationOptionsT()
input_normalization.options.mean = [127.5]
input_normalization.options.std = [127.5]
input_meta.processUnits = [input_normalization]
input_stats = _metadata_fb.StatsT()
input_stats.max = [255]
input_stats.min = [0]
input_meta.stats = input_stats

ناتج التصنيف

يمكن ربط التصنيف بأداة مترابط الإخراج من خلال ملف مرتبط باستخدام TENSOR_AXIS_LABELS.

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()
output_meta.name = "probability"
output_meta.description = "Probabilities of the 1001 labels respectively."
output_meta.content = _metadata_fb.ContentT()
output_meta.content.content_properties = _metadata_fb.FeaturePropertiesT()
output_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.FeatureProperties)
output_stats = _metadata_fb.StatsT()
output_stats.max = [1.0]
output_stats.min = [0.0]
output_meta.stats = output_stats
label_file = _metadata_fb.AssociatedFileT()
label_file.name = os.path.basename("your_path_to_label_file")
label_file.description = "Labels for objects that the model can recognize."
label_file.type = _metadata_fb.AssociatedFileType.TENSOR_AXIS_LABELS
output_meta.associatedFiles = [label_file]

إنشاء مخازن ثابتة للبيانات الوصفية

يجمع الرمز التالي بين معلومات النموذج ومعلومات المدخلات والمخرجات:

# Creates subgraph info.
subgraph = _metadata_fb.SubGraphMetadataT()
subgraph.inputTensorMetadata = [input_meta]
subgraph.outputTensorMetadata = [output_meta]
model_meta.subgraphMetadata = [subgraph]

b = flatbuffers.Builder(0)
b.Finish(
    model_meta.Pack(b),
    _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)
metadata_buf = b.Output()

تجميع البيانات الوصفية والملفات المرتبطة في النموذج

بعد إنشاء الموارد الثابتة للبيانات الوصفية، تتم كتابة البيانات الوصفية وملف التصنيف في ملف TFLite باستخدام طريقة populate:

populator = _metadata.MetadataPopulator.with_model_file(model_file)
populator.load_metadata_buffer(metadata_buf)
populator.load_associated_files(["your_path_to_label_file"])
populator.populate()

يمكنك تجميع أي عدد تريده من الملفات المرتبطة في النموذج من خلال load_associated_files. ومع ذلك، يلزم تجميع ما لا يقل عن هذه الملفات الموثقة في بيانات التعريف. في هذا المثال، يُعد تعبئة ملف التسمية إلزاميًا.

تصور البيانات الوصفية

يمكنك استخدام Netron لعرض بياناتك الوصفية، أو يمكنك قراءة البيانات الوصفية من نموذج TensorFlow Lite بتنسيق json باستخدام MetadataDisplayer:

displayer = _metadata.MetadataDisplayer.with_model_file(export_model_path)
export_json_file = os.path.join(FLAGS.export_directory,
                                os.path.splitext(model_basename)[0] + ".json")
json_file = displayer.get_metadata_json()
# Optional: write out the metadata as a json file
with open(export_json_file, "w") as f:
  f.write(json_file)

يتيح "استوديو Android" أيضًا عرض البيانات الوصفية من خلال ميزة ربط تعلُّم الآلة في "استوديو Android".

تحديد إصدارات البيانات الوصفية

يتم إصدار مخطط البيانات الوصفية باستخدام رقم الإصدار الدلالي الذي يتتبّع تغييرات ملف المخطط، ومن خلال تعريف ملف Flatbuffers، الذي يشير إلى التوافق الحقيقي مع الإصدار.

رقم الإصدار الدلالي

يتم تحديد نسخة من مخطط البيانات الوصفية باستخدام رقم إصدار المعنى الدلالي، مثل MAJOR.MINOR.PATCH. ويتتبّع تغييرات المخطط وفقًا للقواعد هنا. اطّلِع على سجلّ الحقول التي تمت إضافتها بعد الإصدار 1.0.0.

تحديد ملف Flatbuffers

تضمن صيغ الدلالة التوافق في حال اتّباع القواعد، ولكنها لا تشير إلى عدم التوافق الحقيقي. عند تغيير رقم MAJOR، لا يعني ذلك بالضرورة أنّ التوافق مع الأنظمة القديمة معطَّل. ولذلك، نستخدم تحديد ملف المخزن المؤقت، file_identifier، للإشارة إلى التوافق الحقيقي لمخطط البيانات الوصفية. يبلغ معرف الملف 4 أحرف بالضبط. فهي ثابتة وفقًا لمخطط بيانات تعريف معينة ولا تخضع للتغيير من قبل المستخدمين. إذا اضطررنا إلى تعطُّل التوافق مع الأنظمة القديمة لمخطط البيانات الوصفية لسبب ما، سيرتفع قيمة file_identifier من "M001" مثلاً إلى "M002". ومن المتوقّع أن يتم تغيير قيمة File_identifier بوتيرة أقل بكثير من data_version.

الحد الأدنى اللازم لإصدار محلل البيانات الوصفية

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

قراءة البيانات الوصفية من النماذج

مكتبة استخراج البيانات الوصفية هي أداة ملائمة لقراءة البيانات الوصفية والملفات المرتبطة بها من نماذج عبر أنظمة أساسية مختلفة (يمكنك الاطّلاع على إصدار Java وإصدار C++). يمكنك إنشاء أداة استخراج البيانات الوصفية بلغات أخرى باستخدام مكتبة التخزين المؤقت الثابت.

قراءة البيانات الوصفية بلغة Java

لاستخدام مكتبة "أداة استخراج البيانات الوصفية" في تطبيق Android، ننصحك باستخدام TensorFlow Lite Metadata AAR الذي تتم استضافته على MavenCentral. وتتضمّن الفئة MetadataExtractor، بالإضافة إلى عمليات ربط FlatBuffers Java لمخطط البيانات الوصفية ومخطط النموذج.

يمكنك تحديد ذلك في اعتماديات build.gradle على النحو التالي:

dependencies {
    implementation 'org.tensorflow:tensorflow-lite-metadata:0.1.0'
}

لاستخدام اللقطات الليلية، تأكَّد من إضافة مستودع لقطات Sonatype.

يمكنك إعداد كائن MetadataExtractor باستخدام ByteBuffer يشير إلى النموذج:

public MetadataExtractor(ByteBuffer buffer);

ويجب ألّا تتغيّر السمة ByteBuffer طوال فترة بقاء الكائن MetadataExtractor. قد يتعذّر إتمام الإعداد إذا لم يتطابق معرّف ملف المخزن المؤقت للبيانات الوصفية للنموذج مع معرّف محلّل البيانات الوصفية. راجِع إصدارات البيانات الوصفية للاطّلاع على مزيد من المعلومات.

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

public final boolean isMinimumParserVersionSatisfied();

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

public boolean hasMetadata();

توفّر MetadataExtractor دوالّ ملائمة للحصول على البيانات الوصفية لمستّرات الإدخال/الإخراج. على سبيل المثال:

public int getInputTensorCount();
public TensorMetadata getInputTensorMetadata(int inputIndex);
public QuantizationParams getInputTensorQuantizationParams(int inputIndex);
public int[] getInputTensorShape(int inputIndex);
public int getoutputTensorCount();
public TensorMetadata getoutputTensorMetadata(int inputIndex);
public QuantizationParams getoutputTensorQuantizationParams(int inputIndex);
public int[] getoutputTensorShape(int inputIndex);

على الرغم من أنّ مخطط نموذج TensorFlow Lite يتيح استخدام رسومات بيانية فرعية متعددة، يمكن حاليًا استخدام رسم بياني فرعي واحد فقط من خلال TFLite Instanter. لذلك، يحذف MetadataExtractor الفهرس الفرعي كوسيطة إدخال في طرقه.

قراءة الملفات المرتبطة من النماذج

نموذج TensorFlow Lite الذي يحتوي على البيانات الوصفية والملفات المرتبطة هو في الأساس ملف ZIP يمكن فك ضغطه باستخدام أدوات ZIP الشائعة للحصول على الملفات المرتبطة. على سبيل المثال، يمكنك فك ضغط mobilenet_v1_0.75_160_quantized واستخراج ملف التصنيف في النموذج على النحو التالي:

$ unzip mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
Archive:  mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
 extracting: labels.txt

يمكنك أيضًا قراءة الملفات المرتبطة من خلال مكتبة استخراج البيانات الوصفية.

في Java، أدخِل اسم الملف في الطريقة MetadataExtractor.getAssociatedFile:

public InputStream getAssociatedFile(String fileName);

وبالمثل، في C++، يمكن القيام بذلك باستخدام الطريقة، ModelMetadataExtractor::GetAssociatedFile:

tflite::support::StatusOr<absl::string_view> GetAssociatedFile(
      const std::string& filename) const;