ใช้โมเดล TensorFlow Lite ที่กำหนดเองใน Android

หากแอปใช้โมเดล TensorFlow Lite ที่กําหนดเอง คุณสามารถใช้ Firebase ML เพื่อทําให้โมเดลใช้งานได้ การใช้โมเดลกับ Firebase จะช่วยให้คุณลดขนาดการดาวน์โหลดครั้งแรกของแอปและอัปเดตโมเดล ML ของแอปได้โดยไม่ต้องเผยแพร่แอปเวอร์ชันใหม่ และ Remote Config และ A/B Testing จะช่วยให้คุณแสดงโมเดลที่แตกต่างกันให้กับผู้ใช้แต่ละกลุ่มได้แบบไดนามิก

โมเดล TensorFlow Lite

โมเดล TensorFlow Lite คือโมเดล ML ที่ปรับให้ทำงานบนอุปกรณ์เคลื่อนที่ได้ดีขึ้น วิธีรับโมเดล TensorFlow Lite

ก่อนเริ่มต้น

  1. เพิ่ม Firebase ลงในโปรเจ็กต์ Android หากยังไม่ได้ดำเนินการ
  2. ในไฟล์ Gradle ของโมดูล (ระดับแอป) (โดยปกติจะเป็น <project>/<app-module>/build.gradle.kts หรือ <project>/<app-module>/build.gradle) ให้เพิ่มทรัพยากร Dependency สำหรับไลบรารีเครื่องมือดาวน์โหลดโมเดล Firebase ML สำหรับ Android เราขอแนะนำให้ใช้ Firebase Android BoM เพื่อควบคุมการกำหนดเวอร์ชันของไลบรารี

    นอกจากนี้ ในการตั้งค่าเครื่องมือดาวน์โหลดโมเดล Firebase ML คุณจะต้องเพิ่ม TensorFlow Lite SDK ลงในแอปด้วย

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.10.0"))
    
        // 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 แต่ละเวอร์ชันในบรรทัดของ Dependency

    โปรดทราบว่าหากคุณใช้ไลบรารี 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")
    }
    หากกำลังมองหาโมดูลไลบรารีสำหรับ Kotlin โดยเฉพาะ ตั้งแต่เดือนตุลาคม 2023 (Firebase BoM 32.5.0) เป็นต้นไป นักพัฒนาซอฟต์แวร์ทั้ง Kotlin และ Java จะใช้โมดูลไลบรารีหลักได้ (ดูรายละเอียดได้ในคําถามที่พบบ่อยเกี่ยวกับโครงการริเริ่มนี้)
  3. ประกาศในไฟล์ Manifest ของแอปว่าจำเป็นต้องมีสิทธิ์ INTERNET
    <uses-permission android:name="android.permission.INTERNET" />

1. ทำให้โมเดลใช้งานได้

ติดตั้งใช้งานโมเดล TensorFlow ที่กําหนดเองโดยใช้Firebaseคอนโซลหรือ Firebase Admin Python และ Node.js SDK ดูหัวข้อทำให้ใช้งานได้และจัดการโมเดลที่กำหนดเอง

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

2. ดาวน์โหลดโมเดลลงในอุปกรณ์และเริ่มต้นอินเทอร์พรีเตอร์ TensorFlow Lite

หากต้องการใช้โมเดล TensorFlow Lite ในแอป ให้ใช้ Firebase ML SDK ในการดาวน์โหลดโมเดลเวอร์ชันล่าสุดลงในอุปกรณ์ก่อน จากนั้นสร้างอินสแตนซ์ของตัวแปรแปลภาษา TensorFlow Lite ด้วยโมเดล

หากต้องการเริ่มการดาวน์โหลดโมเดล ให้เรียกใช้เมธอด getModel() ของเครื่องมือดาวน์โหลดโมเดล โดยระบุชื่อที่คุณกำหนดให้กับโมเดลเมื่ออัปโหลด ระบุว่าคุณต้องการดาวน์โหลดโมเดลล่าสุดเสมอหรือไม่ และเงื่อนไขที่คุณต้องการอนุญาตให้ดาวน์โหลด

คุณเลือกลักษณะการดาวน์โหลดได้ 3 แบบดังนี้

ประเภทการดาวน์โหลด คำอธิบาย
LOCAL_MODEL รับโมเดลในเครื่องจากอุปกรณ์ หากไม่มีรูปแบบในเครื่อง รูปแบบนี้จะทํางานเหมือน LATEST_MODEL ใช้ประเภทการดาวน์โหลดนี้หากไม่สนใจที่จะตรวจสอบการอัปเดตโมเดล เช่น คุณใช้การกําหนดค่าระยะไกลเพื่อดึงข้อมูลชื่อโมเดล และอัปโหลดโมเดลภายใต้ชื่อใหม่เสมอ (แนะนํา)
LOCAL_MODEL_UPDATE_IN_BACKGROUND รับโมเดลในเครื่องจากอุปกรณ์และเริ่มอัปเดตโมเดลในเบื้องหลัง หากไม่มีรูปแบบในเครื่อง รูปแบบนี้จะทํางานเหมือน LATEST_MODEL
LATEST_MODEL ใช้รุ่นล่าสุด หากโมเดลในเครื่องเป็นเวอร์ชันล่าสุด ระบบจะแสดงผลโมเดลในเครื่อง หรือดาวน์โหลดรุ่นล่าสุด ลักษณะการทำงานนี้จะบล็อกจนกว่าจะมีการดาวน์โหลดเวอร์ชันล่าสุด (ไม่แนะนำ) ใช้ลักษณะการทำงานนี้เฉพาะในกรณีที่คุณต้องการเวอร์ชันล่าสุดอย่างชัดเจนเท่านั้น

คุณควรปิดใช้ฟังก์ชันการทำงานที่เกี่ยวข้องกับโมเดล เช่น ปิดใช้หรือซ่อน UI บางส่วน จนกว่าคุณจะยืนยันว่าดาวน์โหลดโมเดลแล้ว

KotlinJava
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)
            }
        }
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 จะรับอินพุตและสร้างเอาต์พุตเป็นอาร์เรย์มิติหลายรายการอย่างน้อย 1 รายการ อาร์เรย์เหล่านี้มีค่าเป็น 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 ดังที่แสดงในตัวอย่างต่อไปนี้

KotlinJava
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)
    }
}
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 ที่ใหญ่พอที่จะเก็บเอาต์พุตของโมเดล และส่งบัฟเฟอร์อินพุตและบัฟเฟอร์เอาต์พุตไปยังเมธอด run() ของโปรแกรมล่าม TensorFlow Lite ตัวอย่างเช่น สำหรับรูปแบบเอาต์พุตของ[1 1000]ค่าทศนิยม

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

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

ตัวอย่างเช่น หากคุณกำลังทำการแยกประเภท ขั้นตอนถัดไปอาจเป็นการกำหนดดัชนีของผลลัพธ์ให้กับป้ายกำกับที่แสดงถึงผลลัพธ์นั้น

KotlinJava
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?
}
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 ที่แปลงเป็นอนุกรมมาตรฐานในพื้นที่เก็บข้อมูลในเครื่อง

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

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

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

Firebase ML lets you add powerful machine learning features to your app with ready-to-use APIs and support for custom model deployment.

อัปเดตแล้ว Feb 28, 2025