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

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

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

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

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

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

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

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

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

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

pip install tflite-support

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

إضافة بيانات وصفية باستخدام واجهة برمجة تطبيقات Flatbuffers Python

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

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

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

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

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

  • الميزة - الأرقام التي تكون أعدادًا صحيحة بدون علامة أو float32.
  • الصور - البيانات الوصفية تتوافق حاليًا مع الصور بنموذج أحمر أخضر أزرق والصور بتدرج الرمادي.
  • مربّع الربط - مربّعات حدود مستطيلة الشكل يتوافق المخطط مع مجموعة متنوعة من مخططات الترقيم.

إنشاء حزمة للملفات المرتبطة

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

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

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

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

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

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

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

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

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




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


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


الصيغة


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

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

نعم

[1] TensorFlow Lite Java API وTensorFlow Lite C++ API.
[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.")

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

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

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

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

بعد إنشاء Flatbuffers للبيانات الوصفية، تتمّ كتابة البيانات الوصفية وملف التسمية في ملف 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، لا يعني ذلك بالضرورة تعطُّل التوافق مع الأنظمة القديمة. لذلك، نستخدم تعريف ملف Flatbuffers، وهو file_identifier، للإشارة إلى التوافق الحقيقي لمخطط البيانات الوصفية. يتألف معرف الملف من 4 أحرف بالضبط. وهو ثابت على مخطط بيانات وصفية معين ولا يخضع للتغيير من قبل المستخدمين. في حال كان يجب تعطيل التوافق مع الأنظمة القديمة لمخطط البيانات الوصفية لسبب ما، سترتفع قيمة file_identifier، على سبيل المثال، من "M001" إلى "M002". ومن المتوقع أن يتم تغيير File_identifier بوتيرة أقل بكثير من data_version.

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

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

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

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

قراءة البيانات الوصفية بلغة 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. قد يتعذّر الإعداد إذا كان معرّف ملف Flatbuffers للبيانات الوصفية للنموذج غير مطابق لمعرّف محلّل البيانات الوصفية. يمكنك الاطّلاع على إصدارات البيانات الوصفية لمزيد من المعلومات.

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

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 حاليًا استخدام رسم بياني فرعي واحد. لذلك، تحذف 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;