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

برای استنباط با ML Kit در Android از مدل TensorFlow Lite استفاده کنید

شما می توانید ML کیت به انجام بر روی دستگاه استنتاج با استفاده TensorFlow بازگشت به محتوا | مدل.

این API به Android SDK سطح 16 (Jelly Bean) یا جدیدتر نیاز دارد.

قبل از اینکه شروع کنی

  1. اگر شما در حال حاضر، اضافه فایربیس به پروژه آندروید خود را .
  2. اضافه کردن نیازمندی های کتابخانه ML Kit آندروید به ماژول خود را (در سطح برنامه) فایل Gradle (معمولا app/build.gradle ):
    apply plugin: 'com.android.application'
    apply plugin: 'com.google.gms.google-services'
    
    dependencies {
      // ...
    
      implementation 'com.google.firebase:firebase-ml-model-interpreter:22.0.3'
    }
    
  3. مدل TensorFlow را که می خواهید استفاده کنید به فرمت TensorFlow Lite تبدیل کنید. مشاهده TensorFlow بازگشت به محتوا | بهینه سازی تبدیل: TOCO .

مدل خود را میزبانی یا بسته بندی کنید

قبل از استفاده از مدل TensorFlow Lite برای نتیجه گیری در برنامه خود ، باید مدل را در دسترس ML Kit قرار دهید. ML Kit می تواند از مدلهای TensorFlow Lite که از راه دور با استفاده از Firebase میزبانی شده اند ، همراه با برنامه باینری یا هر دو استفاده کند.

با میزبانی یک مدل در Firebase ، می توانید مدل را بدون انتشار نسخه جدید برنامه به روز کنید ، و می توانید از Remote Config و A/B Testing برای ارائه پویا مدل های مختلف به مجموعه های مختلف کاربران استفاده کنید.

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

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

مدلهای میزبان در Firebase

برای میزبانی مدل TensorFlow Lite خود در Firebase:

  1. در بخش ML کیت از فایربیس کنسول ، روی زبانه های سفارشی.
  2. کلیک کنید اضافه کردن مدل های سفارشی (و یا اضافه کردن مدل های دیگری).
  3. تعیین نام که استفاده می شود برای شناسایی مدل خود را در پروژه فایربیس خود را آپلود فایل مدل TensorFlow بازگشت به محتوا | (معمولا در پایان دادن به .tflite یا .lite ).
  4. در برنامه خود را آشکار، اعلام کردند که اجازه به اینترنت مورد نیاز است:
    <uses-permission android:name="android.permission.INTERNET" />
    

پس از افزودن یک مدل سفارشی به پروژه Firebase خود ، می توانید مدل را در برنامه های خود با استفاده از نامی که مشخص کرده اید ارجاع دهید. در هر زمان ، می توانید یک مدل جدید TensorFlow Lite را بارگذاری کنید ، و برنامه شما مدل جدید را بارگیری می کند و با راه اندازی مجدد برنامه ، شروع به استفاده از آن می کند. شما می توانید شرایط دستگاه مورد نیاز برای برنامه خود را برای تلاش برای به روز رسانی مدل تعریف کنید (به پایین مراجعه کنید).

بسته بندی مدلها با یک برنامه

به بسته نرم افزاری مدل TensorFlow آرشیو خود را با برنامه خود، کپی فایل مدل (که معمولا در پایان دادن به .tflite یا .lite ) به برنامه خود را assets/ پوشه. (شما ممکن است نیاز به ایجاد پوشه برای اولین بار توسط کلیک راست روی app/ پوشه، سپس کلیک کردن جدید> پوشه> دارایی پوشه.)

سپس، اضافه کردن زیر به برنامه خود را build.gradle فایل برای اطمینان از Gradle کند مدل های فشرده سازی نیست در هنگام ساخت برنامه:

android {

    // ...

    aaptOptions {
        noCompress "tflite"  // Your model's file extension: "tflite", "lite", etc.
    }
}

فایل مدل در بسته برنامه گنجانده شده و به عنوان دارایی خام در اختیار ML Kit قرار می گیرد.

مدل را بارگذاری کنید

برای استفاده از مدل TensorFlow Lite خود در برنامه ، ابتدا ML Kit را با مکان هایی که مدل شما در دسترس است پیکربندی کنید: از راه دور با استفاده از Firebase ، در ذخیره سازی محلی یا هر دو. اگر هم مدل محلی و هم راه دور را مشخص کنید ، می توانید از مدل از راه دور در صورت موجود بودن آن استفاده کنید و اگر مدل از راه دور در دسترس نیست دوباره به مدل ذخیره شده محلی بازگردید.

پیکربندی مدل میزبانی شده Firebase

اگر شما مدل خود را با Firebase میزبانی، ایجاد یک FirebaseCustomRemoteModel شی، تعیین نام شما مدل اختصاص داده زمانی که شما آن را آپلود:

جاوا

FirebaseCustomRemoteModel remoteModel =
        new FirebaseCustomRemoteModel.Builder("your_model").build();

Kotlin+KTX

val remoteModel = FirebaseCustomRemoteModel.Builder("your_model").build()

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

جاوا

FirebaseModelDownloadConditions conditions = new FirebaseModelDownloadConditions.Builder()
        .requireWifi()
        .build();
FirebaseModelManager.getInstance().download(remoteModel, conditions)
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                // Success.
            }
        });

Kotlin+KTX

val conditions = FirebaseModelDownloadConditions.Builder()
    .requireWifi()
    .build()
FirebaseModelManager.getInstance().download(remoteModel, conditions)
    .addOnCompleteListener {
        // Success.
    }

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

یک مدل محلی را پیکربندی کنید

اگر شما این مدل را با برنامه خود را، ایجاد یک FirebaseCustomLocalModel شی، تعیین نام فایل از مدل TensorFlow مطلب:

جاوا

FirebaseCustomLocalModel localModel = new FirebaseCustomLocalModel.Builder()
        .setAssetFilePath("your_model.tflite")
        .build();

Kotlin+KTX

val localModel = FirebaseCustomLocalModel.Builder()
    .setAssetFilePath("your_model.tflite")
    .build()

از مدل خود یک مترجم ایجاد کنید

بعد از اینکه شما منابع مدل خود را پیکربندی کنید، ایجاد یک FirebaseModelInterpreter شی از یکی از آنها.

اگر شما فقط یک مدل به صورت محلی همراه داشته باشد، فقط یک مترجم از خود را ایجاد کنید FirebaseCustomLocalModel شی:

جاوا

FirebaseModelInterpreter interpreter;
try {
    FirebaseModelInterpreterOptions options =
            new FirebaseModelInterpreterOptions.Builder(localModel).build();
    interpreter = FirebaseModelInterpreter.getInstance(options);
} catch (FirebaseMLException e) {
    // ...
}

Kotlin+KTX

val options = FirebaseModelInterpreterOptions.Builder(localModel).build()
val interpreter = FirebaseModelInterpreter.getInstance(options)

اگر مدل میزبانی از راه دور دارید ، قبل از اجرا باید بررسی کنید که بارگیری شده است. شما می توانید وضعیت از کار مدل دانلود با استفاده از مدیر مدل را بررسی کنید isModelDownloaded() روش.

اگرچه شما فقط باید قبل از اجرای مترجم این موضوع را تأیید کنید ، اگر هم از مدل میزبانی شده از راه دور و هم از مدل محلی استفاده می کنید ، انجام این بررسی هنگام استفاده از مترجم مدل منطقی به نظر می رسد: در صورت ایجاد یک مترجم از مدل از راه دور بارگیری شده است ، و در غیر این صورت از مدل محلی.

جاوا

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener(new OnSuccessListener<Boolean>() {
            @Override
            public void onSuccess(Boolean isDownloaded) {
                FirebaseModelInterpreterOptions options;
                if (isDownloaded) {
                    options = new FirebaseModelInterpreterOptions.Builder(remoteModel).build();
                } else {
                    options = new FirebaseModelInterpreterOptions.Builder(localModel).build();
                }
                FirebaseModelInterpreter interpreter = FirebaseModelInterpreter.getInstance(options);
                // ...
            }
        });

Kotlin+KTX

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
    .addOnSuccessListener { isDownloaded -> 
    val options =
        if (isDownloaded) {
            FirebaseModelInterpreterOptions.Builder(remoteModel).build()
        } else {
            FirebaseModelInterpreterOptions.Builder(localModel).build()
        }
    val interpreter = FirebaseModelInterpreter.getInstance(options)
}

اگر فقط یک مدل میزبانی از راه دور دارید ، باید عملکرد مربوط به مدل را غیرفعال کنید-به عنوان مثال ، خاکستری شدن یا پنهان کردن بخشی از UI خود-تا زمانی که تأیید کنید مدل بارگیری شده است. شما می توانید با اتصال یک شنونده را به بدهید مدل انجام download() روش:

جاوا

FirebaseModelManager.getInstance().download(remoteModel, conditions)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void v) {
              // Download complete. Depending on your app, you could enable
              // the ML feature, or switch from the local model to the remote
              // model, etc.
            }
        });

Kotlin+KTX

FirebaseModelManager.getInstance().download(remoteModel, conditions)
    .addOnCompleteListener {
        // Download complete. Depending on your app, you could enable the ML
        // feature, or switch from the local model to the remote model, etc.
    }

ورودی و خروجی مدل را مشخص کنید

بعد ، فرمت های ورودی و خروجی مترجم مدل را پیکربندی کنید.

یک مدل TensorFlow Lite ورودی می گیرد و یک یا چند آرایه چند بعدی را به عنوان خروجی تولید می کند. این آرایه های حاوی byte ، int ، long ، و یا float ارزش. شما باید ML Kit را با تعداد و ابعاد ("شکل") آرایه هایی که مدل شما استفاده می کند پیکربندی کنید.

اگر شکل و نوع داده ورودی و خروجی مدل خود را نمی دانید ، می توانید از مترجم TensorFlow Lite Python برای بررسی مدل خود استفاده کنید. مثلا:

import tensorflow as tf

interpreter = tf.lite.Interpreter(model_path="my_model.tflite")
interpreter.allocate_tensors()

# Print input shape and type
print(interpreter.get_input_details()[0]['shape'])  # Example: [1 224 224 3]
print(interpreter.get_input_details()[0]['dtype'])  # Example: <class 'numpy.float32'>

# Print output shape and type
print(interpreter.get_output_details()[0]['shape'])  # Example: [1 1000]
print(interpreter.get_output_details()[0]['dtype'])  # Example: <class 'numpy.float32'>

پس از فرمت های ورودی و خروجی مدل شما تعیین کرده اند، شما می توانید مترجم مدل برنامه خود را با ایجاد یک پیکربندی FirebaseModelInputOutputOptions شی.

به عنوان مثال، یک تصویر مدل طبقه بندی ممیز شناور ممکن است به عنوان ورودی یک را N x224x224x3 مجموعه ای از float ارزش ها، به نمایندگی از یک دسته ای از N 224x224 سه کانال (RGB) تصاویر و تولید به عنوان خروجی یک لیست از 1000 float ارزش ها، هر یک نماینده ی احتمالاً تصویر یکی از 1000 دسته ای است که مدل پیش بینی کرده است.

برای چنین مدلی ، ورودی و خروجی مترجم را مطابق شکل زیر پیکربندی کنید:

جاوا

FirebaseModelInputOutputOptions inputOutputOptions =
        new FirebaseModelInputOutputOptions.Builder()
                .setInputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 224, 224, 3})
                .setOutputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 5})
                .build();

Kotlin+KTX

val inputOutputOptions = FirebaseModelInputOutputOptions.Builder()
        .setInputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 224, 224, 3))
        .setOutputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 5))
        .build()

استنتاج در مورد داده های ورودی را انجام دهید

در نهایت ، برای انجام استنتاج با استفاده از مدل ، داده های ورودی خود را دریافت کرده و هرگونه تغییر روی داده ها را که برای بدست آوردن یک آرایه ورودی از شکل مناسب برای مدل شما ضروری است ، انجام دهید.

برای مثال، اگر شما یک مدل طبقه بندی تصویر را با یک شکل ورودی [1 224 224 3] مقادیر اعشاری، شما می توانید یک آرایه ورودی از یک تولید Bitmap شی همانطور که در مثال زیر نشان داده شده:

جاوا

Bitmap bitmap = getYourInputImage();
bitmap = Bitmap.createScaledBitmap(bitmap, 224, 224, true);

int batchNum = 0;
float[][][][] input = new float[1][224][224][3];
for (int x = 0; x < 224; x++) {
    for (int y = 0; y < 224; y++) {
        int pixel = bitmap.getPixel(x, y);
        // Normalize channel values to [-1.0, 1.0]. This requirement varies by
        // model. For example, some models might require values to be normalized
        // to the range [0.0, 1.0] instead.
        input[batchNum][x][y][0] = (Color.red(pixel) - 127) / 128.0f;
        input[batchNum][x][y][1] = (Color.green(pixel) - 127) / 128.0f;
        input[batchNum][x][y][2] = (Color.blue(pixel) - 127) / 128.0f;
    }
}

Kotlin+KTX

val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true)

val batchNum = 0
val input = Array(1) { Array(224) { Array(224) { FloatArray(3) } } }
for (x in 0..223) {
    for (y in 0..223) {
        val pixel = bitmap.getPixel(x, y)
        // Normalize channel values to [-1.0, 1.0]. This requirement varies by
        // model. For example, some models might require values to be normalized
        // to the range [0.0, 1.0] instead.
        input[batchNum][x][y][0] = (Color.red(pixel) - 127) / 255.0f
        input[batchNum][x][y][1] = (Color.green(pixel) - 127) / 255.0f
        input[batchNum][x][y][2] = (Color.blue(pixel) - 127) / 255.0f
    }
}

سپس، ایجاد FirebaseModelInputs شی با داده های ورودی خود را، و تصویب آن و ورودی و خروجی مشخصات مدل به مترجم مدل را run روش:

جاوا

FirebaseModelInputs inputs = new FirebaseModelInputs.Builder()
        .add(input)  // add() as many input arrays as your model requires
        .build();
firebaseInterpreter.run(inputs, inputOutputOptions)
        .addOnSuccessListener(
                new OnSuccessListener<FirebaseModelOutputs>() {
                    @Override
                    public void onSuccess(FirebaseModelOutputs result) {
                        // ...
                    }
                })
        .addOnFailureListener(
                new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        // Task failed with an exception
                        // ...
                    }
                });

Kotlin+KTX

val inputs = FirebaseModelInputs.Builder()
        .add(input) // add() as many input arrays as your model requires
        .build()
firebaseInterpreter.run(inputs, inputOutputOptions)
        .addOnSuccessListener { result ->
            // ...
        }
        .addOnFailureListener { e ->
            // Task failed with an exception
            // ...
        }

اگر پاسخ موفق شود، شما می توانید خروجی را با تماس با گرفتن getOutput() روش از جسم است که به شنونده موفقیت منتقل می شود. مثلا:

جاوا

float[][] output = result.getOutput(0);
float[] probabilities = output[0];

Kotlin+KTX

val output = result.getOutput<Array<FloatArray>>(0)
val probabilities = output[0]

نحوه استفاده از خروجی بستگی به مدل مورد استفاده شما دارد.

به عنوان مثال ، اگر در حال انجام طبقه بندی هستید ، در مرحله بعد ، ممکن است نمایه های نتیجه را برچسب هایی که نشان می دهند قرار دهید:

جاوا

BufferedReader reader = new BufferedReader(
        new InputStreamReader(getAssets().open("retrained_labels.txt")));
for (int i = 0; i < probabilities.length; i++) {
    String label = reader.readLine();
    Log.i("MLKit", String.format("%s: %1.4f", label, probabilities[i]));
}

Kotlin+KTX

val reader = BufferedReader(
        InputStreamReader(assets.open("retrained_labels.txt")))
for (i in probabilities.indices) {
    val label = reader.readLine()
    Log.i("MLKit", String.format("%s: %1.4f", label, probabilities[i]))
}

پیوست: امنیت مدل

صرف نظر از اینکه چگونه مدلهای TensorFlow Lite خود را در دسترس ML Kit قرار می دهید ، ML Kit آنها را در قالب استاندارد protobuf سریالی در ذخیره سازی محلی ذخیره می کند.

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

در اندیشه API سطح 21 (اب نبات چوبی) و جدیدتر، مدل را در یک دایرکتوری است که دانلود از پشتیبان گیری خودکار از مطالعه حذف شدند .

در اندیشه API سطح 20 و بالاتر است، و مدل به یک دایرکتوری با نام دانلود com.google.firebase.ml.custom.models در حافظه داخلی نرم افزار و خصوصی است. اگر شما فایل پشتیبان را فعال کنید با استفاده از BackupAgent ، شما ممکن است را انتخاب کنید تا حذف این شاخه.