Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

השתמש במודל TensorFlow Lite מותאם אישית ב- iOS

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

תנאים מוקדמים

  • MLModelDownloader הספרייה זמינה רק עבור סוויפט.
  • TensorFlow Lite פועל רק במכשירים המשתמשים ב- iOS 9 ואילך.

דגמי TensorFlow Lite

דגמי TensorFlow Lite הינם דגמי ML המותאמים להפעלה במכשירים ניידים. כדי לקבל דגם TensorFlow Lite:

לפני שאתה מתחיל

  1. אם לא כבר הוסיף Firebase באפליקציה, לעשות זאת על ידי ביצוע השלבים במדריך להפעלה .
  2. כלול את Firebase ב- Podfile שלך:

    מָהִיר

    pod 'Firebase/MLModelDownloader'
    pod 'TensorFlowLiteSwift'
    
    לאחר התקנת או לעדכן שקיקים של הפרויקט שלך, הקפד לפתוח פרויקט Xcode שלך באמצעות שלה .xcworkspace .
  3. באפליקציה שלך, ייבא את Firebase:

    מָהִיר

    import Firebase
    import TensorFlowLite
    

1. לפרוס את המודל שלך

פריס את דגמי TensorFlow המותאמים אישית שלך באמצעות מסוף Firebase או מסמכי הניהול של Python ו- Node.js של מנהל Firebase. ראה לפרוס ולנהל מודלים מותאמים אישית .

לאחר הוספת דגם מותאם אישית לפרויקט Firebase שלך, תוכל להתייחס לדגם באפליקציות שלך באמצעות השם שציינת. בכל עת, תוכל לפרוס מודל חדש TensorFlow לייט ולהוריד את הדגם החדש על המכשירים של המשתמשים על ידי התקשרות getModel() (ראה להלן).

2. הורד את הדגם למכשיר ואתחל מתורגמן TensorFlow Lite

כדי להשתמש בדגם TensorFlow Lite שלך ​​באפליקציה שלך, תחילה השתמש ב- Firebase ML SDK כדי להוריד את הגירסה העדכנית ביותר של הדגם למכשיר.

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

אתה יכול לבחור מתוך שלוש התנהגויות הורדה:

סוג הורדה תיאור
localModel קבל את הדגם המקומי מהמכשיר. אם אין מודל מקומי זמין, מתנהג כמו זו latestModel . השתמש בסוג הורדה זה אם אינך מעוניין לחפש עדכוני דגמים. לדוגמה, אתה משתמש ב- Config Remote כדי לאחזר שמות דגמים ותמיד אתה מעלה דגמים תחת שמות חדשים (מומלץ).
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()

אתה יכול לקבל את ouput של המודל על ידי קריאה של המתורגמן 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 באחסון מקומי.

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