Firebase را به برنامه iOS مجهز به TFLite خود اضافه کنید

1. بررسی اجمالی

اهداف

Firebase ML شما را قادر می سازد تا مدل خود را در هوا پخش کنید. این به شما امکان می دهد اندازه برنامه را کوچک نگه دارید و فقط در صورت نیاز مدل ML را دانلود کنید، چندین مدل را آزمایش کنید یا مدل ML خود را بدون نیاز به انتشار مجدد کل برنامه به روز کنید.

در این کد لبه شما یک برنامه iOS را با استفاده از یک مدل TFLite ثابت به یک برنامه با استفاده از مدلی که به صورت پویا از Firebase ارائه می شود، تبدیل می کنید. شما یاد خواهید گرفت که چگونه:

  1. مدل های TFLite را در Firebase ML مستقر کنید و از برنامه خود به آنها دسترسی داشته باشید
  2. معیارهای مربوط به مدل را با Analytics ثبت کنید
  3. انتخاب کنید کدام مدل از طریق Remote Config بارگیری شود
  4. مدل های مختلف A/B را تست کنید

پیش نیازها

قبل از شروع این کد لبه مطمئن شوید که نصب کرده اید:

  • Xcode 11 (یا بالاتر)
  • CocoaPods 1.9.1 (یا بالاتر)

2. پروژه کنسول Firebase را ایجاد کنید

Firebase را به پروژه اضافه کنید

  1. به کنسول Firebase بروید.
  2. Create New Project را انتخاب کنید و نام پروژه خود را "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 در پنل ناوبری سمت چپ کلیک کنید. سپس به "Custom" رفته و بر روی دکمه "Add Model" کلیک کنید.

هنگامی که از شما خواسته شد، یک نام توصیفی مانند mnist_v1 به مدل بدهید و فایل را از دایرکتوری پروژه codelab آپلود کنید.

3c3c50e6ef12b3b.png

5. دانلود مدل از Firebase ML

انتخاب زمان دانلود مدل از راه دور از Firebase در برنامه شما می تواند مشکل باشد زیرا مدل های TFLite می توانند نسبتاً بزرگ شوند. در حالت ایده‌آل، می‌خواهیم از بارگیری مدل بلافاصله هنگام راه‌اندازی برنامه جلوگیری کنیم، زیرا اگر مدل ما فقط برای یک ویژگی استفاده شود و کاربر هرگز از آن ویژگی استفاده نکند، بدون دلیل حجم قابل توجهی از داده‌ها را دانلود کرده‌ایم. همچنین می‌توانیم گزینه‌های دانلود مانند واکشی مدل‌ها را هنگام اتصال به وای‌فای تنظیم کنیم. اگر می‌خواهید مطمئن شوید که مدل حتی بدون اتصال به شبکه نیز در دسترس است، باید مدل را به عنوان بخشی از برنامه به‌عنوان یک نسخه پشتیبان نیز قرار دهید.

برای سادگی، مدل پیش‌فرض همراه را حذف می‌کنیم و همیشه با شروع برنامه، مدلی را از 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))
          }
  }
}

در ViewController.swift 's viewDidLoad ، فراخوانی اولیه 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 را برای ردیابی دقت مدل خود ثبت کنیم. ابتدا باید Analytics را به Podfile اضافه کنیم تا بتوان از آن در پروژه استفاده کرد:

pod 'FirebaseAnalytics'

سپس در ViewController.swift Firebase را در بالای فایل وارد کنید

import FirebaseAnalytics

و خط کد زیر را در متد correctButtonPressed اضافه کنید.

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

دوباره برنامه را اجرا کنید و یک رقم بکشید. دکمه «بله» را چند بار فشار دهید تا بازخورد درستی استنباط ارسال شود.

تجزیه و تحلیل اشکال زدایی

به طور کلی، رویدادهای ثبت‌شده توسط برنامه شما در مدت تقریباً یک ساعت با هم جمع می‌شوند و با هم آپلود می‌شوند. این رویکرد باعث صرفه جویی در باتری دستگاه های کاربران نهایی و کاهش مصرف داده های شبکه می شود. با این حال، به منظور تأیید اجرای تجزیه و تحلیل خود (و برای مشاهده تجزیه و تحلیل خود در گزارش DebugView)، می توانید حالت Debug را در دستگاه توسعه خود فعال کنید تا رویدادها را با حداقل تاخیر بارگذاری کند.

برای فعال کردن حالت Analytics Debug در دستگاه توسعه خود، آرگومان خط فرمان زیر را در Xcode مشخص کنید:

-FIRDebugEnabled

دوباره برنامه را اجرا کنید و یک رقم بکشید. دکمه «بله» را چند بار فشار دهید تا بازخورد درستی استنباط ارسال شود. اکنون می توانید رویدادهای گزارش را در زمان واقعی از طریق نمای اشکال زدایی در کنسول Firebase مشاهده کنید. روی Analytics > DebugView از نوار ناوبری سمت چپ کلیک کنید.

5276199a086721fd.png

7. زمان استنتاج را با Firebase Performance پیگیری کنید

هنگام آزمایش مدل شما، معیارهای عملکردی که در دستگاه‌های توسعه‌دهنده ایجاد می‌شوند برای نمایش عملکرد مدل در دست کاربران شما کافی نیستند، زیرا تشخیص اینکه کاربران سخت‌افزاری برنامه شما را اجرا می‌کنند دشوار است. خوشبختانه، می توانید با Firebase Performance عملکرد مدل خود را در دستگاه های کاربران اندازه گیری کنید تا تصویر بهتری از عملکرد مدل خود داشته باشید.

برای اندازه گیری زمان لازم برای اجرای استنتاج، ابتدا Firebase را در DigitClassifier.swift وارد کنید:

import FirebasePerformance

سپس یک ردیابی عملکرد را در روش طبقه بندی شروع کنید و پس از اتمام استنتاج، ردیابی را متوقف کنید. مطمئن شوید که خطوط کد زیر را در قسمت بسته شدن DispatchQueue.global.async اضافه کرده اید و مستقیماً زیر اعلان متد نیست.

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

اگر کنجکاو هستید، می توانید ثبت اشکال زدایی را از طریق دستورالعمل های اینجا فعال کنید تا تأیید کنید که ردیابی های عملکرد شما ثبت شده است. پس از مدتی، ردهای عملکرد در کنسول Firebase نیز قابل مشاهده خواهد بود.

8. یک مدل دوم را در Firebase ML مستقر کنید

هنگامی که نسخه جدیدی از مدل خود را ارائه می کنید، مانند نسخه ای با معماری مدل بهتر یا نسخه ای که روی مجموعه داده بزرگتر یا به روز آموزش دیده است، ممکن است وسوسه شویم که مدل فعلی خود را با نسخه جدید جایگزین کنیم. با این حال، مدلی که در آزمایش خوب عمل می کند، لزوماً در تولید به همان اندازه خوب عمل نمی کند. بنابراین، بیایید تست A/B را در تولید انجام دهیم تا مدل اصلی خود را با مدل جدید مقایسه کنیم.

Firebase Model Management API را فعال کنید

در این مرحله، API مدیریت مدل Firebase را فعال می‌کنیم تا نسخه جدیدی از مدل TensorFlow Lite را با استفاده از کد پایتون اجرا کند.

یک سطل برای ذخیره مدل های ML خود ایجاد کنید

در کنسول Firebase خود، به Storage بروید و روی شروع کار کلیک کنید. fbbea78f0eb3dc9f.png

گفتگو را دنبال کنید تا سطل خود را راه اندازی کنید.

19517c0d6d2aa14d.png

Firebase ML API را فعال کنید

به صفحه Firebase ML API در Google Cloud Console بروید و روی Enable کلیک کنید.

2414fd5cced6c984.png در صورت درخواست، برنامه Digit Classifier را انتخاب کنید.

اکنون نسخه جدیدی از مدل را با استفاده از مجموعه داده بزرگتر آموزش خواهیم داد و سپس آن را به صورت برنامه نویسی مستقیماً از نوت بوک آموزشی با استفاده از Firebase Admin SDK اجرا خواهیم کرد.

کلید خصوصی را برای حساب سرویس بارگیری کنید

قبل از اینکه بتوانیم از Firebase Admin SDK استفاده کنیم، باید یک حساب سرویس ایجاد کنیم. با کلیک بر روی این لینک ، پنل Service Accounts کنسول Firebase را باز کنید و روی دکمه ایجاد یک حساب سرویس جدید برای Firebase Admin SDK کلیک کنید. وقتی از شما خواسته شد، روی دکمه Generate New Private Key کلیک کنید. ما از کلید حساب سرویس برای احراز هویت درخواست‌هایمان از دفترچه یادداشت colab استفاده می‌کنیم.

c3b95de1e5508516.png

اکنون می توانیم مدل جدید را آموزش و اجرا کنیم.

  1. این دفترچه یادداشت colab را باز کنید و یک کپی از آن در Drive خودتان تهیه کنید.
  2. با کلیک بر روی دکمه پخش در سمت چپ آن، اولین سلول "Train an advanced TensorFlow Lite model" را اجرا کنید. این یک مدل جدید را آموزش می دهد و ممکن است کمی طول بکشد.
  3. اجرای سلول دوم، یک اعلان آپلود فایل ایجاد می کند. هنگام ایجاد حساب سرویس خود، فایل json را که از کنسول Firebase دانلود کرده اید آپلود کنید.

71e847c6a85423b3.png

  1. دو سلول آخر را اجرا کنید.

پس از اجرای نوت بوک colab، باید مدل دوم را در کنسول Firebase مشاهده کنید. مطمئن شوید که مدل دوم mnist_v2 نام دارد.

c316683bb4d75d57.png

9. یک مدل را از طریق Remote Config انتخاب کنید

اکنون که دو مدل مجزا داریم، یک پارامتر برای انتخاب مدلی که در زمان اجرا دانلود کنیم اضافه می کنیم. مقدار پارامتری که مشتری دریافت می کند تعیین می کند که مشتری کدام مدل را دانلود کند. ابتدا کنسول Firebase را باز کرده و روی دکمه Remote Config در منوی ناوبری سمت چپ کلیک کنید. سپس بر روی دکمه "افزودن پارامتر" کلیک کنید.

پارامتر جدید را model_name نامگذاری کنید و مقدار پیش فرض mnist_v1 را به آن بدهید. برای اعمال به‌روزرسانی‌ها، روی انتشار تغییرات کلیک کنید. با قرار دادن نام مدل در پارامتر remote config، می‌توانیم چندین مدل را بدون افزودن پارامتر جدید برای هر مدلی که می‌خواهیم آزمایش کنیم، آزمایش کنیم.

پس از افزودن پارامتر، باید آن را در کنسول ببینید:

699b3fd32acce887.png

در کد ما، هنگام بارگیری مدل از راه دور، باید یک چک اضافه کنیم. هنگامی که پارامتر را از Remote Config دریافت می کنیم، مدل راه دور را با نام مربوطه واکشی می کنیم. در غیر این صورت سعی می کنیم mnist_v1 بارگیری کنیم. قبل از اینکه بتوانیم از Remote Config استفاده کنیم، باید آن را با تعیین آن به عنوان یک وابستگی در Podfile به پروژه خود اضافه کنیم:

pod 'FirebaseRemoteConfig'

نصب پاد را اجرا کنید و پروژه 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 دو مدل را تست کنید

در نهایت، می‌توانیم از رفتار تست A/B داخلی Firebase استفاده کنیم تا ببینیم کدام یک از دو مدل ما عملکرد بهتری دارند. به Analytics -> Events در کنسول Firebase بروید. اگر رویداد correct_inference نشان داده می‌شود، آن را به‌عنوان «رویداد تبدیل» علامت‌گذاری کنید، اگر نه، می‌توانید به Analytics -> رویدادهای تبدیل بروید و روی «ایجاد یک رویداد تبدیل جدید» کلیک کنید و correct_inference.

اکنون به "Remote Config در کنسول Firebase" بروید، دکمه "A/B test" را از منوی گزینه های بیشتر در پارامتر "model_name" که به تازگی اضافه کردیم، انتخاب کنید.

fad5ea36969d2aeb.png

در منوی زیر، نام پیش فرض را بپذیرید.

d7c006669ace6e40.png

برنامه خود را در منوی کشویی انتخاب کنید و معیارهای هدف را به 50 درصد از کاربران فعال تغییر دهید.

6246dd7c660b53fb.png

اگر قبلاً توانستید رویداد correct_inference را به عنوان تبدیل تنظیم کنید، از این رویداد به عنوان معیار اصلی برای ردیابی استفاده کنید. در غیر این صورت، اگر نمی خواهید منتظر بمانید تا رویداد در Analytics نشان داده شود، می توانید correct_inference به صورت دستی اضافه کنید.

1ac9c94fb3159271.png

در نهایت، در صفحه Variants، نوع گروه کنترل خود را برای استفاده از mnist_v1 و گروه Variant A خود را برای استفاده از mnist_v2 تنظیم کنید.

e4510434f8da31b6.png

روی دکمه Review در گوشه سمت راست پایین کلیک کنید.

تبریک می گویم، شما با موفقیت یک تست A/B برای دو مدل جداگانه خود ایجاد کردید! تست A/B در حال حاضر در حالت پیش‌نویس است و می‌تواند در هر زمان با کلیک کردن روی دکمه "شروع آزمایش" شروع شود.

برای نگاهی دقیق تر به تست A/B، مستندات تست A/B را بررسی کنید.

11. نتیجه گیری

در این کد لبه، یاد گرفتید که چگونه یک دارایی tflite با بسته‌بندی ثابت را در برنامه خود با یک مدل TFLite بارگذاری شده پویا از Firebase جایگزین کنید. برای کسب اطلاعات بیشتر در مورد TFLite و Firebase، به سایر نمونه های TFLite و راهنمای شروع Firebase نگاهی بیندازید.

سوالی دارید؟

گزارش مسائل