אם האפליקציה שלכם משתמשת במודלים מותאמים אישית של TensorFlow Lite, תוכלו להשתמש ב-Firebase ML כדי לפרוס את המודלים. על ידי באמצעות Firebase, תוכלו להפחית את גודל ההורדה הראשוני של את האפליקציה ולעדכן את המודלים של למידת המכונה באפליקציה בלי לפרסם גרסה חדשה של באפליקציה שלך. וגם, בעזרת Remote Config ו-A/B Testing, אפשר באופן דינמי כדי להציג מודלים שונים לקבוצות שונות של משתמשים.
דגמים של TensorFlow Lite
מודלים של TensorFlow Lite הם מודלים של למידת מכונה שעברו אופטימיזציה להפעלה בנייד מכשירים. כדי לקבל מודל TensorFlow Lite:
- להשתמש במודל מוגדר מראש, כמו אחד רשמי דגמים של TensorFlow Lite.
- המרת מודל TensorFlow, מודל Keras או פונקציה קונקרטית ל-TensorFlow Lite
לפני שמתחילים
- אם עדיין לא עשיתם זאת, מוסיפים את Firebase לפרויקט Android.
-
בקובץ Gradle של המודול (ברמת האפליקציה)
(בדרך כלל
<project>/<app-module>/build.gradle.kts
או<project>/<app-module>/build.gradle
), מוסיפים את התלות בספריית הורדת המודלים Firebase ML ל-Android. מומלץ להשתמש Firebase Android BoM כדי לשלוט בניהול גרסאות של ספריות.בנוסף, כחלק מהגדרת Firebase ML model downloader, צריך להוסיף את TensorFlow Lite SDK לאפליקציה.
dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:33.5.1")) // Add 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 add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0") }כשמשתמשים ב-Firebase Android BoM, האפליקציה תמיד תשתמש בגרסאות תואמות של ספריות Firebase ל-Android.
(חלופה) מוסיפים יחסי תלות לספריות של Firebase בלי להשתמש ב-BoM
אם בוחרים לא להשתמש ב-Firebase BoM, צריך לציין את כל הגרסאות של ספריות Firebase בשורת התלות שלהן.
שימו לב: אם האפליקציה שלכם משתמשת במספר ספריות של Firebase, מומלץ מומלץ להשתמש בפקודה BoM כדי לנהל גרסאות של ספריות, וכך להבטיח שכל הגרסאות תואמת.
dependencies { // Add 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:25.0.1")
// Also add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0") } - במניפסט של האפליקציה, צריך להצהיר שנדרשת הרשאת INTERNET:
<uses-permission android:name="android.permission.INTERNET" />
1. פריסת המודל
פורסים מודלים מותאמים אישית של TensorFlow באמצעות המסוף Firebase או את ערכות ה-SDK של Firebase Admin עבור Python ו-Node.js. צפייה פריסה וניהול של מודלים בהתאמה אישית.
אחרי שמוסיפים מודל מותאם אישית לפרויקט Firebase, אפשר להפנות למודל באפליקציות באמצעות השם שציינתם. בכל שלב אפשר לפרוס
מודל TensorFlow Lite חדש ולהוריד את המודל החדש מכשירים לפי
התקשרות אל getModel()
(הסבר בהמשך).
2. צריך להוריד את המודל למכשיר ולהפעיל תרגום של TensorFlow Lite
כדי להשתמש במודל TensorFlow Lite באפליקציה, קודם צריך להשתמש ב-SDK של Firebase ML כדי להוריד למכשיר את הגרסה האחרונה של המודל. לאחר מכן יוצרים מכונה של מפרש TensorFlow Lite עם המודל.כדי להתחיל את הורדת המודל, צריך להפעיל את השיטה getModel()
של ה-downloader של המודל, לציין את השם שהקציתם למודל כשהעליתם אותו, לציין אם אתם רוצים להוריד תמיד את המודל העדכני ביותר ואת התנאים שבהם אתם רוצים לאפשר את ההורדה.
אתם יכולים לבחור מבין שלוש התנהגויות של הורדות:
סוג הורדה | תיאור |
---|---|
LOCAL_MODEL | אחזור הדגם המקומי מהמכשיר.
אם אין מודל מקומי זמין, הפונקציה מתנהגת כמו LATEST_MODEL . כדאי להשתמש בסוג ההורדה הזה אם אתם לא רוצים לבדוק אם יש עדכונים למדגם. לדוגמה, אתם משתמשים ב-Remote Config כדי לאחזר שמות של מודלים, ותמיד מעלים מודלים בשמות חדשים (מומלץ). |
LOCAL_MODEL_UPDATE_IN_BACKGROUND | מקבלים את הדגם המקומי מהמכשיר
מתחילים לעדכן את המודל ברקע.
אם אין מודל מקומי זמין, הפונקציה מתנהגת כמו LATEST_MODEL . |
LATEST_MODEL | רכישת הדגם העדכני ביותר. אם המודל המקומי הוא את הגרסה העדכנית ביותר, מחזירה את הערך מודל טרנספורמר. אחרת, צריך להוריד את הגרסה העדכנית ביותר מודל טרנספורמר. ההתנהגות הזו תחסום את האפשרות להורדת הגרסה העדכנית ביותר (לא מומלץ). שימוש בהתנהגות הזו רק במקרים שבהם צריך באופן מפורש את הגרסה העדכנית ביותר . |
עליך להשבית פונקציונליות שקשורה למודלים, לדוגמה להסתיר חלק מממשק המשתמש עד שתאשרו שהמודל הורד.
Kotlin+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)
}
}
Java
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);
}
}
});
אפליקציות רבות מתחילות את משימת ההורדה בקוד האתחול שלהן, אבל אפשר לעשות זאת בכל שלב לפני שתצטרכו להשתמש במודל.
3. ביצוע היסק על נתוני הקלט
קבלת צורות הקלט והפלט של המודל
רכיב התרגום של מודל TensorFlow Lite מקבל כקלט ומפיק כפלט
מערך רב-מימדי אחד או יותר. המערכי האלה מכילים את הערכים byte
, int
, long
או float
. לפני שתוכלו להעביר נתונים למודל או להשתמש בתוצאה שלו, אתם צריכים לדעת
המספר והמאפיינים ("הצורה") של המערכים שבהם המודל משתמש.
אם בנית את המודל בעצמך, או אם פורמט הקלט והפלט של המודל לתעד, ייתכן שכבר יש לכם את המידע הזה. אם אתם לא יודעים מהם הצורה וסוג הנתונים של הקלט והפלט של המודל, תוכלו להשתמש במפרסם של TensorFlow Lite כדי לבדוק את המודל. לדוגמה:
Python
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
, כפי שמתואר בדוגמה הבאה:
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)
}
}
Java
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);
}
}
לאחר מכן, צריך להקצות ByteBuffer
גדול מספיק כדי להכיל את הפלט של המודל,
להעביר את מאגר הקלט וחוצץ הפלט ל-TensorFlow Lite
run()
. לדוגמה, עבור צורת פלט של [1 1000]
ערכים של נקודה צפה:
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)
Java
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
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?
}
Java
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?
}
נספח: אבטחת מודל
בלי קשר לאופן שבו המודלים של TensorFlow Lite יהיו זמינים Firebase ML, Firebase ML מאחסן אותם בפורמט Protobuf סריאלי סטנדרטי ב אחסון מקומי.
בתיאוריה, המשמעות היא שכל אחד יכול להעתיק את המודל שלכם. אבל, לפעמים בפועל, רוב המודלים הם ספציפיים לאפליקציה ומעורפלים (obfuscated) והסיכון הזה דומה לזה של מתחרים פירוק שימוש חוזר בקוד. עם זאת, חשוב להיות מודעים לסיכון זה לפני השימוש מודל מותאם אישית באפליקציה.
ב-Android API ברמה 21 (Lollipop) ואילך, הורדת המודל מתבצעת ספרייה שהיא לא נכלל בגיבוי האוטומטי.
ברמת Android API 20 וגרסאות קודמות, המודל מוריד לספרייה בשם com.google.firebase.ml.custom.models
באחסון הפנימי הפרטי של האפליקציה. אם הפעלת גיבוי קבצים באמצעות BackupAgent
,
שאולי בוחרים להחריג את הספרייה הזו.