Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

ใช้รุ่น TensorFlow Lite แบบกำหนดเองบน Android

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

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

รุ่น TensorFlow Lite

รุ่น TensorFlow Lite เป็นรุ่น ML ที่ได้รับการปรับแต่งให้ทำงานบนอุปกรณ์เคลื่อนที่ ในการรับรุ่น TensorFlow Lite:

ก่อนจะเริ่ม

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

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

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:30.5.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 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:24.0.5'
    // Also add the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:30.5.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-ktx'
    // 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-ktx:24.0.5'
    // Also add the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }
  3. ในไฟล์ Manifest ของแอป ให้ประกาศว่าต้องได้รับอนุญาตจากอินเทอร์เน็ต:
    <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() ของโปรแกรมดาวน์โหลดโมเดล โดยระบุชื่อที่คุณกำหนดโมเดลเมื่อคุณอัปโหลด ไม่ว่าคุณจะต้องการดาวน์โหลดโมเดลล่าสุดเสมอหรือไม่ และเงื่อนไขที่คุณต้องการอนุญาตให้ดาวน์โหลด

คุณสามารถเลือกพฤติกรรมการดาวน์โหลดได้สามแบบ:

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

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

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

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

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

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 ดังที่แสดงในตัวอย่างต่อไปนี้:

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

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

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

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

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

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

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

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 จะจัดเก็บโมเดลเหล่านี้ไว้ในรูปแบบโปรโตบัฟแบบอนุกรมมาตรฐานในที่จัดเก็บในเครื่อง

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

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

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