استخدام نموذج TensorFlow Lite المخصّص على منصات Apple

إذا كان تطبيقك يستخدم تنسيقًا مخصّصًا TensorFlow النماذج البسيطة، يمكنك استخدام Firebase ML لنشر نماذجك. من ونشر نماذج باستخدام Firebase، يمكنك تقليل حجم التنزيل الأولي تطبيقك وتحديث نماذج تعلُّم الآلة في تطبيقك بدون طرح إصدار جديد من تطبيقك. وباستخدام Remote Config وA/B Testing، يمكنك إجراء ما يلي ديناميكيًا: نماذج مختلفة لمجموعات مختلفة من المستخدمين.

المتطلبات الأساسية

  • مكتبة MLModelDownloader متاحة فقط لنظام Swift.
  • لا يعمل TensorFlow Lite إلا على الأجهزة التي تعمل بنظام التشغيل iOS 9 والإصدارات الأحدث.

طُرز TensorFlow Lite

نماذج TensorFlow Lite هي نماذج تعلُّم الآلة التي تم تحسينها لتعمل على الأجهزة الجوّالة. الأجهزة. للحصول على نموذج TensorFlow Lite، اتّبِع الخطوات التالية:

قبل البدء

لاستخدام TensorFlowLite مع Firebase، يجب استخدام CocoaPods على أنّه TensorFlowLite. لا تتيح حاليًا إمكانية التثبيت باستخدام مدير حزم Swift. يمكنك الاطّلاع على دليل تثبيت CocoaPods في حساب تعليمات حول كيفية تثبيت MLModelDownloader.

بعد التثبيت، يمكنك استيراد Firebase وTensorFlowLite لتتمكّن من استخدامهما.

Swift

import FirebaseMLModelDownloader
import TensorFlowLite

1- نشر النموذج

انشر نماذج TensorFlow المخصّصة لديك باستخدام وحدة تحكّم "Firebase" أو حزم تطوير البرامج (SDK) الخاصة بمشرفي Firebase وهما Python وNode.js. عرض نشر النماذج المخصَّصة وإدارتها

بعد إضافة نموذج مخصّص إلى مشروعك على Firebase، يمكنك الرجوع إلى النموذج في تطبيقاتك باستخدام الاسم الذي حددته. يمكنك في أي وقت نشر نموذج TensorFlow Lite الجديد وتنزيل النموذج الجديد على الأجهزة بواسطة الاتصال بـ getModel() (انظر أدناه).

2- تنزيل النموذج على الجهاز وإعداد أداة الترجمة الفورية من TensorFlow Lite

لاستخدام نموذج TensorFlow Lite في تطبيقك، عليك أولاً استخدام حزمة تطوير البرامج (SDK) "Firebase ML" لتنزيل أحدث إصدار من الطراز على الجهاز.

لبدء تنزيل النموذج، يمكنك استدعاء طريقة getModel() لأداة تنزيل النموذج، تحديد الاسم الذي عينته للنموذج عند تحميله، سواء ترغب دائمًا في تنزيل أحدث طراز، والحالات التي بموجبها يريدون السماح بالتنزيل.

يمكنك الاختيار من بين ثلاثة سلوكيات للتنزيل:

نوع عملية التنزيل الوصف
localModel الحصول على الطراز المحلي من الجهاز في حال عدم توفُّر نموذج محلي، سيتم يتصرف مثل latestModel. استخدام هذه المسودة نوع التنزيل إذا لم تكن مهتمًا البحث عن تحديثات النموذج. على سبيل المثال: تستخدم "الإعداد عن بُعد" لاسترداد أسماء النماذج ودائمًا تحميل النماذج تحت أسماء جديدة (يُنصح بهذا الخيار)
localModelUpdateInBackground الحصول على الطراز المحلي من الجهاز تحديث النموذج في الخلفية. في حال عدم توفُّر نموذج محلي، سيتم يتصرف مثل latestModel.
latestModel احصل على أحدث طراز. إذا كان النموذج المحلي يعرض أحدث إصدار، الأمثل. أو يمكنك تنزيل أحدث إصدار الأمثل. سيتم حظر هذا السلوك حتى تنزيل أحدث إصدار (ليس (يوصى به). لا تستخدم هذا السلوك إلا في الحالات التي تحتاج فيها صراحة إلى أحدث .

ينبغي لك تعطيل الوظائف المتعلقة بالنموذج، على سبيل المثال، الوضع الرمادي أو إخفاء جزء من واجهة المستخدم — إلى أن تتأكد من تنزيل النموذج.

Swift

let conditions = ModelDownloadConditions(allowsCellularAccess: false)
ModelDownloader.modelDownloader()
    .getModel(name: "your_model",
              downloadType: .localModelUpdateInBackground,
              conditions: conditions) { result in
        switch (result) {
        case .success(let customModel):
            do {
                // Download complete. Depending on your app, you could enable the ML
                // feature, or switch from the local model to the remote model, etc.

                // The CustomModel object contains the local path of the model file,
                // which you can use to instantiate a TensorFlow Lite interpreter.
                let interpreter = try Interpreter(modelPath: customModel.path)
            } catch {
                // Error. Bad model file?
            }
        case .failure(let error):
            // Download was unsuccessful. Don't enable ML features.
            print(error)
        }
}

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

3- إجراء استنتاج على بيانات الإدخال

الحصول على أشكال المدخلات والمخرجات لنموذجك

يستخدم مترجم النموذج TensorFlow Lite كمدخل وينتج كمخرج. واحدة أو أكثر من الصفائف متعددة الأبعاد. تحتوي هذه الصفائف على byte أو int أو long أو float القيم. قبل أن تتمكن من تمرير البيانات إلى نموذج أو استخدام نتيجته، يجب أن تعرف عدد الصفائف التي يستخدمها نموذجك وأبعادها ("الشكل").

إذا كنت قد صممت النموذج بنفسك، أو إذا كان تنسيق مدخلات ومخرجات النموذج موثقة، فقد تكون لديك هذه المعلومات بالفعل. إذا كنت لا تعرف شكل ونوع البيانات لمدخل ومخرجات النموذج، يمكنك استخدام أداة الترجمة الفورية من TensorFlow Lite لفحص النموذج. على سبيل المثال:

Python

import tensorflow as tf

interpreter = tf.lite.Interpreter(model_path="your_model.tflite")
interpreter.allocate_tensors()

# Print input shape and type
inputs = interpreter.get_input_details()
print('{} input(s):'.format(len(inputs)))
for i in range(0, len(inputs)):
    print('{} {}'.format(inputs[i]['shape'], inputs[i]['dtype']))

# Print output shape and type
outputs = interpreter.get_output_details()
print('\n{} output(s):'.format(len(outputs)))
for i in range(0, len(outputs)):
    print('{} {}'.format(outputs[i]['shape'], outputs[i]['dtype']))

مثال على الإخراج:

1 input(s):
[  1 224 224   3] <class 'numpy.float32'>

1 output(s):
[1 1000] <class 'numpy.float32'>

تشغيل ميزة "الترجمة الفورية"

بعد تحديد تنسيق مدخلات ومخرجات النموذج، احصل على إدخال البيانات وإجراء أي عمليات تحويل على البيانات الضرورية للحصول على مدخلاً للشكل المناسب لنموذجك.

على سبيل المثال، إذا كان نموذجك يعالج الصور، وكان نموذجك يحتوي على أبعاد إدخال من [1, 224, 224, 3] قيمة النقطة العائمة، قد تضطر إلى قياسها قيم لون الصورة إلى نطاق نقطة عائمة كما في المثال التالي:

Swift

let image: CGImage = // Your input image
guard let context = CGContext(
  data: nil,
  width: image.width, height: image.height,
  bitsPerComponent: 8, bytesPerRow: image.width * 4,
  space: CGColorSpaceCreateDeviceRGB(),
  bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
) else {
  return false
}

context.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height))
guard let imageData = context.data else { return false }

var inputData = Data()
for row in 0 ..&lt; 224 {
  for col in 0 ..&lt; 224 {
    let offset = 4 * (row * context.width + col)
    // (Ignore offset 0, the unused alpha channel)
    let red = imageData.load(fromByteOffset: offset+1, as: UInt8.self)
    let green = imageData.load(fromByteOffset: offset+2, as: UInt8.self)
    let blue = imageData.load(fromByteOffset: offset+3, as: UInt8.self)

    // Normalize channel values to [0.0, 1.0]. This requirement varies
    // by model. For example, some models might require values to be
    // normalized to the range [-1.0, 1.0] instead, and others might
    // require fixed-point values or the original bytes.
    var normalizedRed = Float32(red) / 255.0
    var normalizedGreen = Float32(green) / 255.0
    var normalizedBlue = Float32(blue) / 255.0

    // Append normalized values to Data object in RGB order.
    let elementSize = MemoryLayout.size(ofValue: normalizedRed)
    var bytes = [UInt8](repeating: 0, count: elementSize)
    memcpy(&amp;bytes, &amp;normalizedRed, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
    memcpy(&amp;bytes, &amp;normalizedGreen, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
    memcpy(&ammp;bytes, &amp;normalizedBlue, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
  }
}

بعد ذلك، انسخ إدخالك NSData إلى أداة الترجمة وشغِّله:

Swift

try interpreter.allocateTensors()
try interpreter.copy(inputData, toInputAt: 0)
try interpreter.invoke()

يمكنك الحصول على نتائج النموذج من خلال استدعاء طريقة output(at:) الخاصة بالمترجم الفوري. وتعتمد كيفية استخدامك للمخرجات على النموذج الذي تستخدمه.

على سبيل المثال، إذا كنت بصدد إجراء التصنيف، كخطوة تالية، يمكنك: وتعيين فهارس النتيجة بالتسميات التي تمثلها:

Swift

let output = try interpreter.output(at: 0)
let probabilities =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: 1000)
output.data.copyBytes(to: probabilities)

guard let labelPath = Bundle.main.path(forResource: "retrained_labels", ofType: "txt") else { return }
let fileContents = try? String(contentsOfFile: labelPath)
guard let labels = fileContents?.components(separatedBy: "\n") else { return }

for i in labels.indices {
    print("\(labels[i]): \(probabilities[i])")
}

الملحق: أمان النموذج

بغض النظر عن كيفية إتاحة طُرز TensorFlow Lite Firebase ML، يخزنها Firebase ML بتنسيق النموذج الأوّلي المتسلسل القياسي في التخزين المحلي.

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