Menggunakan model TensorFlow Lite kustom di platform Apple

Jika aplikasi Anda menggunakan model TensorFlow Lite kustom, Anda dapat menggunakan Firebase ML untuk men-deploy model. Dengan men-deploy model menggunakan Firebase, Anda dapat memperkecil ukuran download awal aplikasi dan mengupdate model ML aplikasi tanpa merilis versi baru aplikasi. Selain itu, dengan Remote Config dan A/B Testing, Anda dapat menyalurkan berbagai model secara dinamis ke berbagai kelompok pengguna yang berbeda.

Prasyarat

  • Library MLModelDownloader hanya tersedia untuk Swift.
  • TensorFlow Lite hanya berjalan di perangkat yang menggunakan iOS 9 dan yang lebih baru.

Model TensorFlow Lite

Model TensorFlow Lite adalah model ML yang dioptimalkan untuk berjalan di perangkat seluler. Untuk mendapatkan model TensorFlow Lite:

Sebelum memulai

Untuk menggunakan TensorFlowLite dengan Firebase, Anda harus menggunakan CocoaPods karena TensorFlow Lite saat ini tidak mendukung penginstalan dengan Swift Package Manager. Lihat panduan penginstalan CocoaPods untuk mengetahui petunjuk cara menginstal MLModelDownloader.

Setelah diinstal, impor Firebase dan TensorFlowLite untuk menggunakannya.

Swift

import FirebaseMLModelDownloader
import TensorFlowLite

1. Deploy model Anda

Deploy model TensorFlow kustom Anda menggunakan Firebase console atau Firebase Admin Python dan Node.js SDK. Lihat Men-deploy dan mengelola model kustom.

Setelah menambahkan model kustom ke project Firebase, Anda dapat mereferensikan model tersebut di aplikasi menggunakan nama yang Anda tentukan. Anda dapat men-deploy model TensorFlow Lite baru kapan saja dan mendownload model baru tersebut ke perangkat pengguna dengan memanggil getModel() (lihat di bawah).

2. Download model ke perangkat dan lakukan inisialisasi penafsir TensorFlow Lite

Untuk menggunakan model TensorFlow Lite di aplikasi Anda, pertama-tama gunakan Firebase ML SDK untuk mendownload versi terbaru model ke perangkat.

Untuk mulai mendownload model, panggil metode getModel() downloader model, dengan menentukan nama yang Anda tetapkan untuk model saat menguploadnya, apakah Anda ingin selalu mendownload model terbaru, dan kondisi yang Anda inginkan untuk mengizinkan download.

Anda dapat memilih di antara tiga perilaku download:

Jenis download Deskripsi
localModel Mendapatkan model lokal dari perangkat. Jika tidak ada model lokal yang tersedia, jenis ini akan berperilaku seperti latestModel. Gunakan jenis download ini jika Anda tidak ingin memeriksa update model. Misalnya, Anda menggunakan Remote Config untuk mengambil nama model dan Anda selalu mengupload model dengan nama baru (direkomendasikan).
localModelUpdateInBackground Mendapatkan model lokal dari perangkat dan mulai mengupdate model di latar belakang. Jika tidak ada model lokal yang tersedia, jenis ini akan berperilaku seperti latestModel.
latestModel Mendapatkan model terbaru. Jika model lokal adalah versi terbaru, jenis ini akan menggunakan model lokal. Jika bukan, model terbaru akan didownload. Perilaku ini akan memblokir model hingga versi terbarunya didownload (tidak direkomendasikan). Gunakan perilaku ini hanya jika Anda memerlukan versi terbaru secara eksplisit.

Anda harus menonaktifkan fungsionalitas terkait model, misalnya menyamarkan atau menyembunyikan sebagian UI, hingga Anda mengonfirmasi model tersebut telah didownload.

Swift

let conditions = ModelDownloadConditions(allowsCellularAccess: false)
ModelDownloader.modelDownloader()
    .getModel(name: "your_model",
              downloadType: .localModelUpdateInBackground,
              conditions: conditions) { result in
        switch (result) {
        case .success(let customModel):
            do {
                // 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.
                let interpreter = try Interpreter(modelPath: customModel.path)
            } catch {
                // Error. Bad model file?
            }
        case .failure(let error):
            // Download was unsuccessful. Don't enable ML features.
            print(error)
        }
}

Banyak aplikasi memulai tugas download dalam kode inisialisasinya, tetapi Anda dapat melakukannya kapan saja sebelum menggunakan model.

3. Lakukan inferensi pada data input

Mendapatkan bentuk input dan output model Anda

Penafsir model TensorFlow Lite mengambil satu atau beberapa array multidimensi sebagai input dan menghasilkannya sebagai output. Array ini berisi nilai byte, int, long, atau float. Sebelum dapat meneruskan data ke model atau menggunakan hasilnya, Anda harus mengetahui jumlah dan dimensi ("bentuk") array yang digunakan oleh model Anda.

Jika model Anda build sendiri, atau jika format input dan output model didokumentasikan, Anda mungkin sudah memiliki informasi ini. Jika tidak mengetahui bentuk dan jenis data input serta output model, Anda dapat menggunakan penafsir TensorFlow Lite untuk memeriksa model Anda. Contoh:

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']))

Contoh output:

1 input(s):
[  1 224 224   3] <class 'numpy.float32'>

1 output(s):
[1 1000] <class 'numpy.float32'>

Menjalankan penafsir

Setelah Anda menentukan format input dan output model, dapatkan data input dan jalankan transformasi pada data yang diperlukan untuk mendapatkan input bentuk yang tepat untuk model Anda.

Misalnya, jika model Anda memproses gambar, dan memiliki dimensi input dari nilai floating point [1, 224, 224, 3], Anda mungkin harus menyesuaikan nilai warna gambar ke rentang floating point seperti pada contoh berikut ini:

Swift

let image: CGImage = // Your input image
guard let context = CGContext(
  data: nil,
  width: image.width, height: image.height,
  bitsPerComponent: 8, bytesPerRow: image.width * 4,
  space: CGColorSpaceCreateDeviceRGB(),
  bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
) else {
  return false
}

context.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height))
guard let imageData = context.data else { return false }

var inputData = Data()
for row in 0 ..&lt; 224 {
  for col in 0 ..&lt; 224 {
    let offset = 4 * (row * context.width + col)
    // (Ignore offset 0, the unused alpha channel)
    let red = imageData.load(fromByteOffset: offset+1, as: UInt8.self)
    let green = imageData.load(fromByteOffset: offset+2, as: UInt8.self)
    let blue = imageData.load(fromByteOffset: offset+3, as: UInt8.self)

    // Normalize channel values to [0.0, 1.0]. This requirement varies
    // by model. For example, some models might require values to be
    // normalized to the range [-1.0, 1.0] instead, and others might
    // require fixed-point values or the original bytes.
    var normalizedRed = Float32(red) / 255.0
    var normalizedGreen = Float32(green) / 255.0
    var normalizedBlue = Float32(blue) / 255.0

    // Append normalized values to Data object in RGB order.
    let elementSize = MemoryLayout.size(ofValue: normalizedRed)
    var bytes = [UInt8](repeating: 0, count: elementSize)
    memcpy(&amp;bytes, &amp;normalizedRed, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
    memcpy(&amp;bytes, &amp;normalizedGreen, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
    memcpy(&ammp;bytes, &amp;normalizedBlue, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
  }
}

Kemudian, salin NSData input Anda ke penafsir dan jalankan:

Swift

try interpreter.allocateTensors()
try interpreter.copy(inputData, toInputAt: 0)
try interpreter.invoke()

Anda bisa mendapatkan output model dengan memanggil metode output(at:) penafsir. Cara penggunaan output bergantung pada model yang Anda gunakan.

Misalnya, jika melakukan klasifikasi, sebagai langkah berikutnya, Anda mungkin dapat memetakan indeks hasil ke label yang diwakilinya:

Swift

let output = try interpreter.output(at: 0)
let probabilities =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: 1000)
output.data.copyBytes(to: probabilities)

guard let labelPath = Bundle.main.path(forResource: "retrained_labels", ofType: "txt") else { return }
let fileContents = try? String(contentsOfFile: labelPath)
guard let labels = fileContents?.components(separatedBy: "\n") else { return }

for i in labels.indices {
    print("\(labels[i]): \(probabilities[i])")
}

Lampiran: Keamanan model

Terlepas dari cara Anda menyediakan model TensorFlow Lite untuk Firebase ML, Firebase ML akan menyimpannya dalam format protobuf serial standar di penyimpanan lokal.

Secara teori, ini artinya siapa saja dapat menyalin model Anda. Namun, dalam praktiknya, sebagian besar model bersifat spesifik aplikasi dan di-obfuscate melalui pengoptimalan sehingga risikonya serupa dengan jika pesaing membongkar dan menggunakan kembali kode Anda. Meskipun demikian, Anda harus menyadari risiko ini sebelum menggunakan model kustom di aplikasi Anda.