הוסף את 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. בחר צור פרויקט חדש ותן שם לפרויקט שלך "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 '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 כדי לעקוב אחר הדיוק של המודל שלנו. ראשית, עלינו להוסיף את Analytics ל-Podfile לפני שניתן יהיה להשתמש בו בפרויקט:

pod 'FirebaseAnalytics'

לאחר מכן ב- ViewController.swift ייבוא ​​Firebase בחלק העליון של הקובץ

import FirebaseAnalytics

והוסיפו את שורת הקוד הבאה בשיטה correctButtonPressed .

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

הפעל שוב את האפליקציה וצייר ספרה. לחץ על כפתור "כן" מספר פעמים כדי לשלוח משוב שהמסק היה מדויק.

ניתוח באגים

בדרך כלל, אירועים שנרשמו על ידי האפליקציה שלך נקבצים יחדיו על פני תקופה של כשעה אחת ומועלים יחד. גישה זו חוסכת את הסוללה במכשירי משתמשי הקצה ומפחיתה את השימוש בנתוני הרשת. עם זאת, למטרות אימות הטמעת הניתוח שלך (וכדי להציג את הניתוח שלך בדוח DebugView), אתה יכול להפעיל את מצב Debug במכשיר הפיתוח שלך כדי להעלות אירועים בהשהייה מינימלית.

כדי להפעיל מצב ניפוי באגים של Analytics במכשיר הפיתוח שלך, ציין את הארגומנט הבא של שורת הפקודה ב-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 Console.

8. פרוס מודל שני ל-Firebase ML

כשממציאים גרסה חדשה של המודל שלך, כמו אחת עם ארכיטקטורת מודל טובה יותר או גרסה שהוכשרה על מערך נתונים גדול יותר או מעודכן, אנו עשויים להתפתות להחליף את המודל הנוכחי שלנו בגרסה החדשה. עם זאת, מודל עם ביצועים טובים בבדיקה לא בהכרח מתפקד באותה מידה בייצור. לכן, בואו נעשה בדיקות A/B בייצור כדי להשוות את הדגם המקורי שלנו לדגם החדש.

אפשר Firebase Model Management API

בשלב זה, נאפשר ל-API לניהול מודלים של Firebase לפרוס גרסה חדשה של מודל 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 . לחץ על פרסם שינויים כדי להחיל את העדכונים. על ידי הכנסת שם הדגם בפרמטר התצורה המרוחקת, נוכל לבדוק מספר דגמים מבלי להוסיף פרמטר חדש עבור כל דגם שאנו רוצים לבדוק.

לאחר הוספת הפרמטר, אתה אמור לראות אותו ב-Console:

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 Testing המובנית של Firebase כדי לראות איזה משני הדגמים שלנו מניב ביצועים טובים יותר. עבור אל Analytics -> אירועים במסוף Firebase. אם אירוע correct_inference מופיע, סמן אותו כ"אירוע המרה", אם לא, אתה יכול ללכת ל-Analytics -> אירועי המרה וללחוץ על "צור אירוע המרה חדש" ולשים את correct_inference.

כעת עבור אל "תצורה מרחוק במסוף Firebase, בחר את כפתור "A/B test" מתפריט אפשרויות נוספות בפרמטר "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, עיין בתיעוד A/B Testing .

11. מסקנה

במעבדת הקוד הזה, למדת כיצד להחליף נכס tflite מאגד סטטי באפליקציה שלך במודל TFLite נטען דינמית מ-Firebase. למידע נוסף על TFLite ו-Firebase, עיין בדוגמאות אחרות של TFLite ובמדריכי ההתחלה של Firebase.

יש שאלה?

דווח על בעיות