أضف Firebase إلى تطبيق iOS الذي يعمل بنظام TFLite

1. نظرة عامة

الأهداف

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

في هذا الدرس التطبيقي حول التعليمات البرمجية، ستقوم بتحويل تطبيق iOS باستخدام نموذج TFLite ثابت إلى تطبيق باستخدام نموذج يتم تقديمه ديناميكيًا من Firebase. سوف تتعلم كيفية:

  1. انشر نماذج TFLite على Firebase ML وقم بالوصول إليها من تطبيقك
  2. قم بتسجيل المقاييس المتعلقة بالنموذج باستخدام Analytics
  3. حدد النموذج الذي سيتم تحميله من خلال Remote Config
  4. اختبار أ/ب لنماذج مختلفة

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

قبل البدء بهذا الدرس التطبيقي حول الترميز، تأكد من أنك قمت بتثبيت:

  • Xcode 11 (أو أعلى)
  • CocoaPods 1.9.1 (أو أعلى)

2. إنشاء مشروع وحدة تحكم Firebase

أضف Firebase إلى المشروع

  1. انتقل إلى وحدة تحكم Firebase .
  2. حدد إنشاء مشروع جديد وقم بتسمية مشروعك "Firebase ML iOS Codelab".

3. احصل على نموذج المشروع

قم بتنزيل الكود

ابدأ باستنساخ نموذج المشروع وتشغيل pod update في دليل المشروع:

git clone https://github.com/FirebaseExtended/codelab-digitclassifier-ios.git
cd codelab-digitclassifier-ios
pod install --repo-update

إذا لم يكن git مثبتًا لديك، فيمكنك أيضًا تنزيل نموذج المشروع من صفحة GitHub الخاصة به أو بالنقر فوق هذا الرابط . بمجرد تنزيل المشروع، قم بتشغيله في Xcode والتلاعب بمصنف الأرقام للتعرف على كيفية عمله.

قم بإعداد Firebase

اتبع الوثائق لإنشاء مشروع Firebase جديد. بمجرد حصولك على مشروعك، قم بتنزيل ملف GoogleService-Info.plist الخاص بمشروعك من وحدة تحكم Firebase واسحبه إلى جذر مشروع Xcode.

f06cb08d48de7e10.png

أضف Firebase إلى ملف Podfile الخاص بك وقم بتشغيل تثبيت pod.

pod 'FirebaseMLModelDownloader', '9.3.0-beta'

في طريقة didFinishLaunchingWithOptions الخاصة بـ AppDelegate ، قم باستيراد Firebase في الجزء العلوي من الملف

import FirebaseCore

وأضف مكالمة لتكوين Firebase.

FirebaseApp.configure()

قم بتشغيل المشروع مرة أخرى للتأكد من تكوين التطبيق بشكل صحيح وعدم تعطله عند التشغيل.

4. نشر نموذج على Firebase ML

يعد نشر نموذج في Firebase ML مفيدًا لسببين رئيسيين:

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

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

لتبسيط الأمور، سنستخدم نموذج TensorFlow Lite الموجود بالفعل في تطبيقنا. أولاً، افتح Firebase وانقر على Machine Learning في لوحة التنقل اليمنى. ثم انتقل إلى "مخصص" وانقر على زر "إضافة نموذج".

عندما يُطلب منك ذلك، قم بتسمية النموذج باسمًا وصفيًا مثل mnist_v1 وقم بتحميل الملف من دليل مشروع Codelab.

3c3c50e6ef12b3b.png

5. قم بتنزيل النموذج من Firebase ML

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

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

في الجزء العلوي من ModelLoader.swift ، قم باستيراد وحدة Firebase.

import FirebaseCore
import FirebaseMLModelDownloader

ثم قم بتنفيذ الطريقة التالية.

static func downloadModel(named name: String,
                          completion: @escaping (CustomModel?, DownloadError?) -> Void) {
  guard FirebaseApp.app() != nil else {
    completion(nil, .firebaseNotInitialized)
    return
  }
  guard success == nil && failure == nil else {
    completion(nil, .downloadInProgress)
    return
  }
  let conditions = ModelDownloadConditions(allowsCellularAccess: false)
  ModelDownloader.modelDownloader().getModel(name: name, downloadType: .localModelUpdateInBackground, conditions: conditions) { result in
          switch (result) {
          case .success(let customModel):
                  // Download complete.
                  // The CustomModel object contains the local path of the model file,
                  // which you can use to instantiate a TensorFlow Lite classifier.
                  return completion(customModel, nil)
          case .failure(let error):
              // Download was unsuccessful. Notify error message.
            completion(nil, .downloadFailed(underlyingError: error))
          }
  }
}

في viewDidLoad الخاص بـ ViewController.swift ، استبدل استدعاء تهيئة DigitClassifier بطريقة تنزيل النموذج الجديدة الخاصة بنا.

    // Download the model from Firebase
    print("Fetching model...")
    ModelLoader.downloadModel(named: "mnist_v1") { (customModel, error) in
      guard let customModel = customModel else {
        if let error = error {
          print(error)
        }
        return
      }

      print("Model download complete")
      
      // Initialize a DigitClassifier instance
      DigitClassifier.newInstance(modelPath: customModel.path) { result in
      switch result {
        case let .success(classifier):
          self.classifier = classifier
        case .error(_):
          self.resultLabel.text = "Failed to initialize."
        }
      }
    }

أعد تشغيل تطبيقك. بعد بضع ثوانٍ، يجب أن تشاهد سجل دخول إلى Xcode يشير إلى أنه تم تنزيل النموذج البعيد بنجاح. حاول رسم رقم وتأكد من أن سلوك التطبيق لم يتغير.

6. تتبع تعليقات المستخدم والتحويل لقياس دقة النموذج

سنقوم بقياس دقة النموذج من خلال تتبع تعليقات المستخدمين على تنبؤات النموذج. إذا نقر المستخدم على "نعم"، فسوف يشير ذلك إلى أن التنبؤ كان دقيقًا.

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

pod 'FirebaseAnalytics'

ثم في ViewController.swift قم باستيراد Firebase في الجزء العلوي من الملف

import FirebaseAnalytics

وأضف السطر التالي من التعليمات البرمجية بالطريقة correctButtonPressed .

Analytics.logEvent("correct_inference", parameters: nil)

قم بتشغيل التطبيق مرة أخرى وارسم رقمًا. اضغط على الزر "نعم" عدة مرات لإرسال تعليقات تفيد بأن الاستدلال كان دقيقًا.

تحليلات التصحيح

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

لتمكين وضع Analytics Debug على جهاز التطوير الخاص بك، حدد وسيطة سطر الأوامر التالية في Xcode:

-FIRDebugEnabled

قم بتشغيل التطبيق مرة أخرى وارسم رقمًا. اضغط على الزر "نعم" عدة مرات لإرسال تعليقات تفيد بأن الاستدلال كان دقيقًا. يمكنك الآن عرض أحداث السجل في الوقت الفعلي تقريبًا عبر عرض تصحيح الأخطاء في وحدة تحكم Firebase. انقر على Analytics > DebugView من شريط التنقل الأيسر.

5276199a086721fd.png

7. تتبع وقت الاستدلال باستخدام أداء Firebase

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

لقياس الوقت المستغرق لتشغيل الاستدلال، قم أولاً باستيراد Firebase في DigitClassifier.swift:

import FirebasePerformance

ثم ابدأ تتبع الأداء في أسلوب التصنيف وأوقف التتبع عند اكتمال الاستدلال. تأكد من إضافة أسطر التعليمات البرمجية التالية داخل إغلاق DispatchQueue.global.async وليس أسفل إعلان الطريقة مباشرة.

let inferenceTrace = Performance.startTrace(name: "tflite inference")
defer {
  inferenceTrace?.stop()
}

إذا كنت مهتمًا، فيمكنك تمكين تسجيل تصحيح الأخطاء عبر الإرشادات الواردة هنا للتأكد من تسجيل تتبعات أدائك. وبعد فترة من الوقت، ستكون آثار الأداء مرئية في Firebase Console أيضًا.

8. نشر نموذج ثانٍ على Firebase ML

عند التوصل إلى إصدار جديد من النموذج الخاص بك، مثل الإصدار الذي يتمتع ببنية نموذجية أفضل أو الإصدار الذي تم تدريبه على مجموعة بيانات أكبر أو محدثة، قد نشعر بالرغبة في استبدال نموذجنا الحالي بالإصدار الجديد. ومع ذلك، فإن النموذج الذي يؤدي أداءً جيدًا في الاختبار لا يؤدي بالضرورة أداءً جيدًا بنفس القدر في الإنتاج. لذلك، دعونا نقوم بإجراء اختبار A/B في الإنتاج لمقارنة نموذجنا الأصلي والنموذج الجديد.

تفعيل واجهة برمجة تطبيقات إدارة نماذج Firebase

في هذه الخطوة، سنقوم بتمكين Firebase Model Management API لنشر إصدار جديد من نموذج TensorFlow Lite الخاص بنا باستخدام كود Python.

قم بإنشاء دلو لتخزين نماذج ML الخاصة بك

في وحدة تحكم Firebase الخاصة بك، انتقل إلى التخزين وانقر على البدء. fbbea78f0eb3dc9f.png

اتبع الحوار لإعداد الدلو الخاص بك.

19517c0d6d2aa14d.png

تمكين Firebase ML API

انتقل إلى صفحة Firebase ML API على Google Cloud Console وانقر على "تمكين".

2414fd5cced6c984.png حدد تطبيق Digit Classifier عندما يُطلب منك ذلك.

سنقوم الآن بتدريب إصدار جديد من النموذج باستخدام مجموعة بيانات أكبر، وسنقوم بعد ذلك بنشره برمجيًا مباشرةً من دفتر التدريب باستخدام Firebase Admin SDK.

قم بتنزيل المفتاح الخاص لحساب الخدمة

قبل أن نتمكن من استخدام Firebase Admin SDK، سنحتاج إلى إنشاء حساب خدمة. افتح لوحة حسابات الخدمة في وحدة تحكم Firebase بالنقر فوق هذا الرابط ثم انقر فوق الزر لإنشاء حساب خدمة جديد لـ Firebase Admin SDK. عندما يُطلب منك ذلك، انقر فوق الزر "إنشاء مفتاح خاص جديد". سنستخدم مفتاح حساب الخدمة لمصادقة طلباتنا من دفتر colab.

c3b95de1e5508516.png

الآن يمكننا تدريب ونشر النموذج الجديد.

  1. افتح دفتر ملاحظات colab هذا واعمل نسخة منه ضمن Drive الخاص بك.
  2. قم بتشغيل الخلية الأولى "تدريب نموذج TensorFlow Lite المحسّن" من خلال النقر على زر التشغيل الموجود على يسارها. سيؤدي هذا إلى تدريب نموذج جديد وقد يستغرق بعض الوقت.
  3. سيؤدي تشغيل الخلية الثانية إلى إنشاء مطالبة بتحميل الملف. قم بتحميل ملف json الذي قمت بتنزيله من Firebase Console عند إنشاء حساب الخدمة الخاص بك.

71e847c6a85423b3.png

  1. قم بتشغيل الخليتين الأخيرتين.

بعد تشغيل دفتر colab، يجب أن تشاهد نموذجًا ثانيًا في وحدة تحكم Firebase. تأكد من تسمية النموذج الثاني mnist_v2 .

c316683bb4d75d57.png

9. حدد نموذجًا عبر Remote Config

الآن بعد أن أصبح لدينا نموذجان منفصلان، سنضيف معلمة لتحديد النموذج الذي سيتم تنزيله في وقت التشغيل. ستحدد قيمة المعلمة التي يتلقاها العميل النموذج الذي سيقوم بتنزيله. أولاً، افتح وحدة تحكم Firebase وانقر على زر Remote Config في قائمة التنقل اليسرى. ثم انقر على زر "إضافة معلمة".

قم بتسمية المعلمة الجديدة model_name وأعطها القيمة الافتراضية mnist_v1 . انقر فوق نشر التغييرات لتطبيق التحديثات. من خلال وضع اسم النموذج في معلمة التكوين عن بعد، يمكننا اختبار نماذج متعددة دون إضافة معلمة جديدة لكل نموذج نريد اختباره.

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

699b3fd32acce887.png

في الكود الخاص بنا، سنحتاج إلى إضافة علامة اختيار عند تحميل النموذج البعيد. عندما نتلقى المعلمة من Remote Config، سنقوم بإحضار النموذج البعيد بالاسم المقابل؛ وإلا فسنحاول تحميل mnist_v1 . قبل أن نتمكن من استخدام Remote Config، علينا إضافته إلى مشروعنا عن طريق تحديده باعتباره تابعًا في ملف Podfile:

pod 'FirebaseRemoteConfig'

قم بتشغيل pod install وأعد فتح مشروع Xcode. في ModelLoader.swift ، قم بتنفيذ طريقة fetchParameterizedModel .

static func fetchParameterizedModel(completion: @escaping (CustomModel?, DownloadError?) -> Void) {
  RemoteConfig.remoteConfig().fetchAndActivate { (status, error) in
    DispatchQueue.main.async {
      if let error = error {
        let compositeError = DownloadError.downloadFailed(underlyingError: error)
        completion(nil, compositeError)
        return
      }

      let modelName: String
      if let name = RemoteConfig.remoteConfig().configValue(forKey: "model_name").stringValue {
        modelName = name
      } else {
        let defaultName = "mnist_v1"
        print("Unable to fetch model name from config, falling back to default \(defaultName)")
        modelName = defaultName
      }
      downloadModel(named: modelName, completion: completion)
    }
  }
}

أخيرًا، في ViewController.swift ، استبدل استدعاء downloadModel بالطريقة الجديدة التي طبقناها للتو.

// Download the model from Firebase
print("Fetching model...")
ModelLoader.fetchParameterizedModel { (customModel, error) in
  guard let customModel = customModel else {
    if let error = error {
      print(error)
    }
    return
  }

  print("Model download complete")
  
  // Initialize a DigitClassifier instance
  DigitClassifier.newInstance(modelPath: customModel.path) { result in
  switch result {
    case let .success(classifier):
      self.classifier = classifier
    case .error(_):
      self.resultLabel.text = "Failed to initialize."
    }
  }
}

أعد تشغيل التطبيق وتأكد من أنه لا يزال يقوم بتحميل النموذج بشكل صحيح.

10. اختبار أ/ب للنموذجين

أخيرًا، يمكننا استخدام سلوك اختبار A/B المدمج في Firebase لمعرفة أي من النموذجين لدينا يحقق أداءً أفضل. انتقل إلى التحليلات -> الأحداث في وحدة تحكم Firebase. إذا كان حدث correct_inference ظاهرًا، فضع علامة عليه باعتباره "حدث تحويل"، وإذا لم يكن الأمر كذلك، فيمكنك الانتقال إلى Analytics -> أحداث التحويل والنقر على "إنشاء حدث تحويل جديد" وإدراج correct_inference.

انتقل الآن إلى "Remote Config" في وحدة تحكم Firebase، وحدد زر "اختبار A/B" من قائمة المزيد من الخيارات في المعلمة "model_name" التي أضفناها للتو.

fad5ea36969d2aeb.png

في القائمة التالية، قم بقبول الاسم الافتراضي.

d7c006669ace6e40.png

حدد تطبيقك من القائمة المنسدلة وقم بتغيير معايير الاستهداف إلى 50% من المستخدمين النشطين.

6246dd7c660b53fb.png

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

1ac9c94fb3159271.png

أخيرًا، في شاشة المتغيرات، قم بتعيين متغير مجموعة التحكم الخاصة بك لاستخدام mnist_v1 ومجموعة البديل A لاستخدام mnist_v2 .

e4510434f8da31b6.png

انقر فوق الزر "مراجعة" في الزاوية اليمنى السفلية.

تهانينا، لقد نجحت في إنشاء اختبار أ/ب للنموذجين المنفصلين لديك! اختبار A/B حاليًا في حالة مسودة ويمكن البدء به في أي وقت بالنقر فوق الزر "بدء التجربة".

لإلقاء نظرة فاحصة على اختبار A/B، راجع وثائق اختبار A/B .

11. الاستنتاج

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

لدي سؤال؟

الإبلاغ عن المشكلات