Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

Usa un modelo personalizado de TensorFlow Lite en iOS

Si su aplicación utiliza personalizados TensorFlow Lite modelos, puede utilizar Firebase ML para desplegar sus modelos. Al implementar modelos con Firebase, puede reducir el tamaño de descarga inicial de su aplicación y actualizar los modelos de AA de su aplicación sin lanzar una nueva versión de su aplicación. Además, con Remote Config y A / B Testing, puede entregar de forma dinámica diferentes modelos a diferentes conjuntos de usuarios.

Prerrequisitos

  • El MLModelDownloader biblioteca sólo está disponible para Swift.
  • TensorFlow Lite solo se ejecuta en dispositivos con iOS 9 y versiones posteriores.

Modelos de TensorFlow Lite

Los modelos de TensorFlow Lite son modelos de aprendizaje automático que están optimizados para ejecutarse en dispositivos móviles. Para obtener un modelo de TensorFlow Lite:

Antes de que empieces

  1. Si aún no lo ha añadido Firebase a su aplicación, hacerlo siguiendo los pasos de la guía de instalación inicial .
  2. Incluya Firebase en su Podfile:

    Rápido

    pod 'Firebase/MLModelDownloader'
    pod 'TensorFlowLiteSwift'
    
    Después de instalar o actualizar las vainas de su proyecto, asegúrese de abrir su proyecto Xcode utilizando su .xcworkspace .
  3. En su aplicación, importe Firebase:

    Rápido

    import Firebase
    import TensorFlowLite
    

1. Implemente su modelo

Implementa tus modelos personalizados de TensorFlow con Firebase console o los SDK de Firebase Admin Python y Node.js. Ver desplegar y gestionar modelos personalizados .

Después de agregar un modelo personalizado a su proyecto de Firebase, puede hacer referencia al modelo en sus aplicaciones con el nombre que especificó. En cualquier momento, puede implementar un nuevo modelo TensorFlow Lite y descargar el nuevo modelo en los dispositivos de los usuarios llamando getModel() (véase más adelante).

2. Descarga el modelo en el dispositivo e inicializa un intérprete de TensorFlow Lite.

Para usar su modelo de TensorFlow Lite en su aplicación, primero use el SDK de Firebase ML para descargar la última versión del modelo en el dispositivo.

Para iniciar el modelo de descarga, llamar el modelo de programa de descarga getModel() método, especificando el nombre que le asignó el modelo cuando se lo ha descargado, si desea descargar siempre el último modelo, y las condiciones bajo las cuales desea permitir la descarga.

Puede elegir entre tres comportamientos de descarga:

Tipo de descarga Descripción
localModel Obtenga el modelo local del dispositivo. Si no existe un modelo local disponible, este se comporta como latestModel . Utilice este tipo de descarga si no está interesado en buscar actualizaciones del modelo. Por ejemplo, estás usando Remote Config para recuperar nombres de modelos y siempre subes modelos con nombres nuevos (recomendado).
localModelUpdateInBackground Obtenga el modelo local del dispositivo y comience a actualizar el modelo en segundo plano. Si no existe un modelo local disponible, este se comporta como latestModel .
latestModel Obtenga el último modelo. Si el modelo local es la última versión, devuelve el modelo local. De lo contrario, descargue el último modelo. Este comportamiento se bloqueará hasta que se descargue la última versión (no recomendado). Utilice este comportamiento solo en los casos en los que necesite explícitamente la última versión.

Debe deshabilitar la funcionalidad relacionada con el modelo, por ejemplo, atenuar u ocultar parte de la interfaz de usuario, hasta que confirme que se ha descargado el modelo.

Rápido

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

Muchas aplicaciones inician la tarea de descarga en su código de inicialización, pero puede hacerlo en cualquier momento antes de que necesite usar el modelo.

3. Realizar inferencias sobre los datos de entrada.

Obtenga las formas de entrada y salida de su modelo

El intérprete de modelos de TensorFlow Lite toma como entrada y produce como salida una o más matrices multidimensionales. Estas matrices contienen o bien byte , int , long , o float valores. Antes de que pueda pasar datos a un modelo o usar su resultado, debe conocer el número y las dimensiones ("forma") de las matrices que usa su modelo.

Si construyó el modelo usted mismo, o si el formato de entrada y salida del modelo está documentado, es posible que ya tenga esta información. Si no conoce la forma y el tipo de datos de la entrada y salida de su modelo, puede usar el intérprete de TensorFlow Lite para inspeccionar su modelo. Por ejemplo:

Pitón

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

Salida de ejemplo:

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

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

Ejecuta el intérprete

Una vez que haya determinado el formato de entrada y salida de su modelo, obtenga sus datos de entrada y realice cualquier transformación en los datos que sea necesaria para obtener una entrada de la forma correcta para su modelo.

Por ejemplo, si el modelo procesa las imágenes, y su modelo tiene dimensiones de entrada de [1, 224, 224, 3] valores de punto flotante, puede que tenga que escalar los valores de color de la imagen para una gama de punto flotante como en el siguiente ejemplo :

Rápido

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

A continuación, copie su entrada NSData al intérprete y ejecutarlo:

Rápido

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

Puede obtener ouput del modelo llamando al intérprete de output(at:) método. La forma de utilizar la salida depende del modelo que esté utilizando.

Por ejemplo, si está realizando una clasificación, como paso siguiente, puede asignar los índices del resultado a las etiquetas que representan:

Rápido

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

Apéndice: seguridad del modelo

Independientemente de cómo pongas tus modelos de TensorFlow Lite a disposición de Firebase ML, Firebase ML los almacena en el formato protobuf serializado estándar en el almacenamiento local.

En teoría, esto significa que cualquiera puede copiar su modelo. Sin embargo, en la práctica, la mayoría de los modelos son tan específicos de la aplicación y están tan confusos por las optimizaciones que el riesgo es similar al de los competidores que desensamblan y reutilizan su código. Sin embargo, debe tener en cuenta este riesgo antes de utilizar un modelo personalizado en su aplicación.