Google 致力于为黑人社区推动种族平等。查看具体举措
หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

ใช้แบบจำลอง TensorFlow Lite สำหรับการอนุมานด้วย ML Kit บน Android

คุณสามารถใช้ ML Kit เพื่อทำการอนุมานบนอุปกรณ์ด้วย โมเดล TensorFlow Lite

API นี้ต้องใช้ Android SDK ระดับ 16 (Jelly Bean) หรือใหม่กว่า

ก่อนที่คุณจะเริ่ม

  1. เพิ่ม Firebase ในโปรเจ็กต์ Android ของคุณ หากยังไม่ได้ ทำ
  2. เพิ่มการอ้างอิงสำหรับไลบรารี ML Kit Android ไปยังโมดูลของคุณ (ระดับแอป) ไฟล์ 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 ดู TOCO: TensorFlow Lite Optimizing Converter

โฮสต์หรือรวมโมเดลของคุณ

ก่อนที่คุณจะสามารถใช้โมเดล TensorFlow Lite สำหรับการอนุมานในแอปของคุณคุณต้องทำให้โมเดลนั้นพร้อมใช้งานสำหรับ ML Kit ML Kit สามารถใช้โมเดล TensorFlow Lite ที่โฮสต์จากระยะไกลโดยใช้ Firebase ที่มาพร้อมกับไบนารีของแอปหรือทั้งสองอย่าง

การโฮสต์โมเดลบน Firebase ทำให้คุณอัปเดตโมเดลได้โดยไม่ต้องเปิดตัวแอปเวอร์ชันใหม่และใช้การกำหนดค่าระยะไกลและการทดสอบ A / B เพื่อให้บริการโมเดลต่างๆแบบไดนามิกแก่ผู้ใช้กลุ่มต่างๆ

หากคุณเลือกที่จะให้โมเดลโดยโฮสต์กับ Firebase เท่านั้นและไม่รวมเข้ากับแอปของคุณคุณสามารถลดขนาดการดาวน์โหลดครั้งแรกของแอปได้ อย่างไรก็ตามโปรดทราบว่าหากโมเดลไม่ได้มาพร้อมกับแอปของคุณฟังก์ชันที่เกี่ยวข้องกับโมเดลจะไม่สามารถใช้งานได้จนกว่าแอปของคุณจะดาวน์โหลดโมเดลเป็นครั้งแรก

ด้วยการรวมโมเดลของคุณเข้ากับแอปคุณจะมั่นใจได้ว่าฟีเจอร์ ML ของแอปจะยังคงใช้งานได้เมื่อไม่มีโมเดลที่โฮสต์โดย Firebase

โฮสต์โมเดลบน Firebase

ในการโฮสต์โมเดล TensorFlow Lite ของคุณบน Firebase:

  1. ในส่วน ML Kit ของ คอนโซล Firebase ให้คลิกแท็บ กำหนดเอง
  2. คลิก เพิ่มโมเดลที่กำหนดเอง (หรือ เพิ่มโมเดลอื่น )
  3. ระบุชื่อที่จะใช้เพื่อระบุโมเดลของคุณในโปรเจ็กต์ Firebase จากนั้นอัปโหลดไฟล์โมเดล TensorFlow Lite (โดยปกติจะลงท้ายด้วย. .tflite หรือ . .lite )
  4. ในรายการแอปของคุณประกาศว่าจำเป็นต้องได้รับอนุญาตจากอินเทอร์เน็ต:
    <uses-permission android:name="android.permission.INTERNET" />
    

หลังจากที่คุณเพิ่มโมเดลที่กำหนดเองลงในโปรเจ็กต์ Firebase ของคุณคุณสามารถอ้างอิงโมเดลในแอปของคุณโดยใช้ชื่อที่คุณระบุ คุณสามารถอัปโหลดโมเดล TensorFlow Lite ใหม่ได้ตลอดเวลาจากนั้นแอปของคุณจะดาวน์โหลดโมเดลใหม่และเริ่มใช้งานเมื่อแอปรีสตาร์ทครั้งถัดไป คุณสามารถกำหนดเงื่อนไขของอุปกรณ์ที่จำเป็นสำหรับแอปของคุณในการพยายามอัปเดตโมเดล (ดูด้านล่าง)

รวมโมเดลเข้ากับแอพ

หากต้องการรวมโมเดล TensorFlow Lite เข้ากับแอปของคุณให้คัดลอกไฟล์โมเดล (โดยปกติจะลงท้ายด้วย. .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 โดยระบุชื่อที่คุณกำหนดโมเดลเมื่อคุณอัปโหลด:

Java

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

โคตรลิน + KTX

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

จากนั้นเริ่มงานดาวน์โหลดโมเดลโดยระบุเงื่อนไขที่คุณต้องการอนุญาตให้ดาวน์โหลด หากโมเดลไม่ได้อยู่ในอุปกรณ์หรือหากมีรุ่นที่ใหม่กว่านี้งานจะดาวน์โหลดโมเดลจาก Firebase แบบอะซิงโครนัส:

Java

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.
            }
        });

โคตรลิน + KTX

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

แอพจำนวนมากเริ่มงานดาวน์โหลดในรหัสเริ่มต้น แต่คุณสามารถทำได้เมื่อใดก็ได้ก่อนที่คุณจะต้องใช้โมเดล

กำหนดค่าโมเดลภายใน

หากคุณรวมโมเดลเข้ากับแอปของคุณให้สร้างออบเจ็กต์ FirebaseCustomLocalModel โดยระบุชื่อไฟล์ของโมเดล TensorFlow Lite:

Java

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

โคตรลิน + KTX

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

สร้างล่ามจากแบบจำลองของคุณ

หลังจากกำหนดค่าแหล่งที่มาของโมเดลแล้วให้สร้างออบเจ็กต์ FirebaseModelInterpreter จากหนึ่งในนั้น

หากคุณมีโมเดลที่รวมในเครื่องเพียงสร้างล่ามจากออบเจ็กต์ FirebaseCustomLocalModel ของคุณ:

Java

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

โคตรลิน + KTX

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

หากคุณมีโมเดลที่โฮสต์จากระยะไกลคุณจะต้องตรวจสอบว่าได้ดาวน์โหลดแล้วก่อนที่จะเรียกใช้ คุณสามารถตรวจสอบสถานะของงานดาวน์โหลดโมเดลโดยใช้ isModelDownloaded() ของตัวจัดการโมเดล

แม้ว่าคุณจะต้องยืนยันสิ่งนี้ก่อนที่จะรันล่าม แต่ถ้าคุณมีทั้งโมเดลที่โฮสต์จากระยะไกลและโมเดลที่รวมในเครื่องคุณควรทำการตรวจสอบนี้เมื่อสร้างอินสแตนซ์ตัวแปลโมเดล: สร้างล่ามจากโมเดลระยะไกล มันถูกดาวน์โหลดและจากโมเดลภายในเครื่อง

Java

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);
                // ...
            }
        });

โคตรลิน + 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 ของคุณจนกว่าคุณจะยืนยันว่าได้ดาวน์โหลดโมเดลแล้ว คุณสามารถทำได้โดยแนบ Listener เข้ากับวิธี download() ของ model manager:

Java

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.
            }
        });

โคตรลิน + 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) และสร้างรายการค่า float 1,000 ค่าโดยแต่ละรายการจะแสดงค่า ความน่าจะเป็นที่รูปภาพเป็นสมาชิกของหนึ่งใน 1,000 หมวดหมู่ที่แบบจำลองคาดการณ์

สำหรับรุ่นดังกล่าวคุณต้องกำหนดค่าอินพุตและเอาต์พุตของตัวแปลโมเดลดังที่แสดงด้านล่าง:

Java

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

โคตรลิน + 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 ดังที่แสดงในตัวอย่างต่อไปนี้

Java

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;
    }
}

โคตรลิน + 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 ของตัว แปลโมเดล :

Java

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
                        // ...
                    }
                });

โคตรลิน + 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() ของอ็อบเจ็กต์ที่ส่งผ่านไปยังตัวรับฟังความสำเร็จ ตัวอย่างเช่น:

Java

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

โคตรลิน + KTX

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

วิธีการใช้เอาต์พุตขึ้นอยู่กับรุ่นที่คุณใช้

ตัวอย่างเช่นหากคุณกำลังดำเนินการจัดหมวดหมู่ในขั้นตอนต่อไปคุณอาจจับคู่ดัชนีของผลลัพธ์กับป้ายกำกับที่แสดง:

Java

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]));
}

โคตรลิน + 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 แบบอนุกรมมาตรฐานในที่จัดเก็บในตัวเครื่อง

ในทางทฤษฎีหมายความว่าใคร ๆ ก็ลอกแบบของคุณได้ อย่างไรก็ตามในทางปฏิบัติโมเดลส่วนใหญ่มีลักษณะเฉพาะของแอปพลิเคชันและถูกทำให้สับสนโดยการปรับแต่งให้เหมาะสมซึ่งความเสี่ยงจะคล้ายกับของคู่แข่งที่แยกชิ้นส่วนและนำโค้ดของคุณไปใช้ซ้ำ อย่างไรก็ตามคุณควรตระหนักถึงความเสี่ยงนี้ก่อนใช้โมเดลที่กำหนดเองในแอปของคุณ

ใน Android API ระดับ 21 (Lollipop) และใหม่กว่าโมเดลจะถูกดาวน์โหลดไปยังไดเร็กทอรีที่ ไม่รวม อยู่ใน การสำรองข้อมูลอัตโนมัติ

ใน Android API ระดับ 20 ขึ้นไปโมเดลจะดาวน์โหลดไปยังไดเร็กทอรีชื่อ com.google.firebase.ml.custom.models ในที่จัดเก็บข้อมูลภายในส่วนตัวของแอป หากคุณเปิดใช้งานการสำรองไฟล์โดยใช้ BackupAgent คุณอาจเลือกที่จะไม่รวมไดเร็กทอรีนี้