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

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

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

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

نماذج TensorFlow لايت

نماذج TensorFlow Lite هي نماذج ML تم تحسينها للتشغيل على الأجهزة المحمولة. للحصول على نموذج TensorFlow Lite:

قبل ان تبدأ

لاستخدام TensorFlowLite مع Firebase، يجب عليك استخدام CocoaPods لأن TensorFlowLite لا يدعم حاليًا التثبيت مع Swift Package Manager. راجع دليل تثبيت CocoaPods للحصول على إرشادات حول كيفية تثبيت MLModelDownloader .

بمجرد التثبيت، قم باستيراد Firebase وTensorFlowLite لاستخدامهما.

سويفت

import FirebaseMLModelDownloader
import TensorFlowLite

1. انشر النموذج الخاص بك

انشر نماذج TensorFlow المخصصة لديك باستخدام إما وحدة تحكم Firebase أو Firebase Admin Python وNode.js SDKs. راجع نشر النماذج المخصصة وإدارتها .

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

2. قم بتنزيل النموذج على الجهاز وقم بتهيئة مترجم TensorFlow Lite

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

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

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

نوع التنزيل وصف
localModel احصل على النموذج المحلي من الجهاز. إذا لم يكن هناك نموذج محلي متاح، فسيعمل هذا مثل latestModel . استخدم نوع التنزيل هذا إذا لم تكن مهتمًا بالتحقق من تحديثات النموذج. على سبيل المثال، أنت تستخدم Remote Config لاسترداد أسماء النماذج وتقوم دائمًا بتحميل النماذج بأسماء جديدة (مستحسن).
localModelUpdateInBackground احصل على النموذج المحلي من الجهاز وابدأ في تحديث النموذج في الخلفية. إذا لم يكن هناك نموذج محلي متاح، فسيعمل هذا مثل latestModel .
latestModel احصل على أحدث طراز. إذا كان النموذج المحلي هو الإصدار الأحدث، فسيتم إرجاع النموذج المحلي. بخلاف ذلك، قم بتنزيل أحدث طراز. سيتم حظر هذا السلوك حتى يتم تنزيل الإصدار الأحدث (غير مستحسن). استخدم هذا السلوك فقط في الحالات التي تحتاج فيها بشكل صريح إلى الإصدار الأحدث.

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

سويفت

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 لفحص النموذج الخاص بك. على سبيل المثال:

بايثون

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] ، فقد يتعين عليك قياس قيم ألوان الصورة إلى نطاق الفاصلة العائمة كما في المثال التالي :

سويفت

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 المدخلات الخاصة بك إلى المترجم وقم بتشغيلها:

سويفت

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

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

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

سويفت

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 يخزنها بتنسيق protobuf المتسلسل القياسي في التخزين المحلي.

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