Catch up on everthing we announced at this year's Firebase Summit. Learn more

השתמש במודל TensorFlow Lite מותאם אישית באנדרואיד

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

דגמי TensorFlow Lite

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

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

  1. אם לא עשית זאת עדיין, להוסיף Firebase לפרויקט Android שלך .
  2. באמצעות BOM אנדרואיד Firebase , להכריז על התלות עבור המודל Firebase ML Downloader הספרייה אנדרואיד במודול שלך (ברמת האפליקציה) קובץ Gradle (בדרך כלל app/build.gradle ).

    כמו כן, כחלק מהגדרת הורדת דגמי Firebase ML, עליך להוסיף את האפליקציה TensorFlow Lite SDK.

    ג'אווה

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:29.0.0')
    
        // Declare the dependency for the Firebase ML model downloader library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-modeldownloader'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    באמצעות Firebase אנדרואיד BOM , האפליקציה שלך תמיד ישתמשו גירסאות תואמות של ספריות אנדרואיד Firebase.

    (אלטרנטיבי) הצהר תלות הספרייה Firebase ללא שימוש BOM

    אם תבחר לא להשתמש ב- Firebase BoM, עליך לציין כל גרסת ספריית Firebase בשורת התלות שלה.

    שים לב שאם אתה משתמש בספריות Firebase מרובים באפליקציה, אנו ממליצים בחום להשתמש בתמונה BOM לנהל גרסאות הספרייה, אשר מבטיח כי כל הגרסאות תואמות.

    dependencies {
        // Declare the dependency for the Firebase ML model downloader library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-modeldownloader:24.0.0'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    קוטלין+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:29.0.0')
    
        // Declare the dependency for the Firebase ML model downloader library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-modeldownloader-ktx'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    באמצעות Firebase אנדרואיד BOM , האפליקציה שלך תמיד ישתמשו גירסאות תואמות של ספריות אנדרואיד Firebase.

    (אלטרנטיבי) הצהר תלות הספרייה Firebase ללא שימוש BOM

    אם תבחר לא להשתמש ב- Firebase BoM, עליך לציין כל גרסת ספריית Firebase בשורת התלות שלה.

    שים לב שאם אתה משתמש בספריות Firebase מרובים באפליקציה, אנו ממליצים בחום להשתמש בתמונה BOM לנהל גרסאות הספרייה, אשר מבטיח כי כל הגרסאות תואמות.

    dependencies {
        // Declare the dependency for the Firebase ML model downloader library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-modeldownloader-ktx:24.0.0'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }
  3. בשנת למניפסט של האפליקציה, להצהיר כי רשות לאינטרנט נדרש:
    <uses-permission android:name="android.permission.INTERNET" />

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

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

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

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

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

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

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

סוג הורדה תיאור
LOCAL_MODEL קבל את הדגם המקומי מהמכשיר. אם אין מודל מקומי זמין, מתנהג כמו זו LATEST_MODEL . השתמש בסוג הורדה זה אם אינך מעוניין לחפש עדכוני דגמים. לדוגמה, אתה משתמש ב- Config Remote כדי לאחזר שמות דגמים ותמיד אתה מעלה דגמים תחת שמות חדשים (מומלץ).
LOCAL_MODEL_UPDATE_IN_BACKGROUND השג את הדגם המקומי מהמכשיר והתחל לעדכן את הדגם ברקע. אם אין מודל מקומי זמין, מתנהג כמו זו LATEST_MODEL .
הדגם האחרון קבלו את הדגם העדכני ביותר. אם הדגם המקומי הוא הגירסה העדכנית ביותר, החזרת הדגם המקומי. אחרת, הורד את הדגם העדכני ביותר. התנהגות זו תיחסם עד להורדת הגרסה האחרונה (לא מומלץ). השתמש בהתנהגות זו רק במקרים שבהם אתה זקוק מפורשות לגרסה העדכנית ביותר.

עליך להשבית את הפונקציונליות הקשורה לדגם-למשל האפלה או הסתרת חלק ממשק המשתמש שלך-עד שתוודא שהדגם הורד.

ג'אווה

CustomModelDownloadConditions conditions = new CustomModelDownloadConditions.Builder()
    .requireWifi()  // Also possible: .requireCharging() and .requireDeviceIdle()
    .build();
FirebaseModelDownloader.getInstance()
    .getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND, conditions)
    .addOnSuccessListener(new OnSuccessListener<CustomModel>() {
      @Override
      public void onSuccess(CustomModel model) {
        // 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.
        File modelFile = model.getFile();
        if (modelFile != null) {
            interpreter = new Interpreter(modelFile);
        }
      }
    });

קוטלין+KTX

val conditions = CustomModelDownloadConditions.Builder()
        .requireWifi()  // Also possible: .requireCharging() and .requireDeviceIdle()
        .build()
FirebaseModelDownloader.getInstance()
        .getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND,
            conditions)
        .addOnSuccessListener { model: CustomModel? ->
            // 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.
            val modelFile = model?.file
            if (modelFile != null) {
                interpreter = Interpreter(modelFile)
            }
        }

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

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] ערך נקודה צופה, אתה יכול ליצור קלט ByteBuffer מתוך Bitmap אובייקט כפי שמוצג בדוגמה הבאה:

ג'אווה

Bitmap bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true);
ByteBuffer input = ByteBuffer.allocateDirect(224 * 224 * 3 * 4).order(ByteOrder.nativeOrder());
for (int y = 0; y < 224; y++) {
    for (int x = 0; x < 224; x++) {
        int px = bitmap.getPixel(x, y);

        // Get channel values from the pixel value.
        int r = Color.red(px);
        int g = Color.green(px);
        int b = Color.blue(px);

        // Normalize channel values to [-1.0, 1.0]. This requirement depends
        // on the model. For example, some models might require values to be
        // normalized to the range [0.0, 1.0] instead.
        float rf = (r - 127) / 255.0f;
        float gf = (g - 127) / 255.0f;
        float bf = (b - 127) / 255.0f;

        input.putFloat(rf);
        input.putFloat(gf);
        input.putFloat(bf);
    }
}

Kotlin+KTX

val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true)
val input = ByteBuffer.allocateDirect(224*224*3*4).order(ByteOrder.nativeOrder())
for (y in 0 until 224) {
    for (x in 0 until 224) {
        val px = bitmap.getPixel(x, y)

        // Get channel values from the pixel value.
        val r = Color.red(px)
        val g = Color.green(px)
        val b = Color.blue(px)

        // Normalize channel values to [-1.0, 1.0]. This requirement depends on the model.
        // For example, some models might require values to be normalized to the range
        // [0.0, 1.0] instead.
        val rf = (r - 127) / 255f
        val gf = (g - 127) / 255f
        val bf = (b - 127) / 255f

        input.putFloat(rf)
        input.putFloat(gf)
        input.putFloat(bf)
    }
}

ואז, להקצות ByteBuffer מספיק גדול כדי להכיל את הפלט של המודל ולהעביר את החיץ קלט חוצץ הפלט של המתורגמן לייט TensorFlow run() שיטה. לדוגמה, עבור צורה הפלט של [1 1000] ערכי נקודה צפה:

ג'אווה

int bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE;
ByteBuffer modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder());
interpreter.run(input, modelOutput);

Kotlin+KTX

val bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE
val modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder())
interpreter?.run(input, modelOutput)

אופן השימוש בפלט תלוי בדגם שבו אתה משתמש.

לדוגמה, אם אתה מבצע סיווג, כשלב הבא, תוכל למפות את אינדקס התוצאה לתוויות שהם מייצגים:

ג'אווה

modelOutput.rewind();
FloatBuffer probabilities = modelOutput.asFloatBuffer();
try {
    BufferedReader reader = new BufferedReader(
            new InputStreamReader(getAssets().open("custom_labels.txt")));
    for (int i = 0; i < probabilities.capacity(); i++) {
        String label = reader.readLine();
        float probability = probabilities.get(i);
        Log.i(TAG, String.format("%s: %1.4f", label, probability));
    }
} catch (IOException e) {
    // File not found?
}

Kotlin+KTX

modelOutput.rewind()
val probabilities = modelOutput.asFloatBuffer()
try {
    val reader = BufferedReader(
            InputStreamReader(assets.open("custom_labels.txt")))
    for (i in probabilities.capacity()) {
        val label: String = reader.readLine()
        val probability = probabilities.get(i)
        println("$label: $probability")
    }
} catch (e: IOException) {
    // File not found?
}

נספח: אבטחת דגמים

ללא קשר לאופן שבו אתה הופך את דגמי TensorFlow Lite שלך ​​לזמינים ל- Firebase ML, Firebase ML מאחסן אותם בפורמט הפרוטובופ המסודר הסטנדרטי באחסון המקומי.

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

ב API אנדרואיד ברמה 21 (Lollipop) ומעלה, המודל שהורדו לספרייה כי הוא נכלל גיבוי אוטומטי .

במישור API אנדרואיד 20 ומעלה, המודל שהורדו בשם ספרייה com.google.firebase.ml.custom.models אחסון פנימי app-פרטית. אם תאפשר גיבוי קבצים באמצעות BackupAgent , תוכל לבחור שלא לכלול במדריך זה.