Delegado de ML do TensorFlow Lite Core

O delegado de ML do TensorFlow Lite Core permite executar modelos do TensorFlow Lite no framework do Core ML, o que resulta em uma inferência de modelo mais rápida em dispositivos iOS.

Versões e dispositivos iOS compatíveis:

  • iOS 12 e mais recentes. Nas versões mais antigas do iOS, o delegado do Core ML substitui automaticamente a CPU.
  • Por padrão, o delegado do Core ML só será ativado em dispositivos com SoC A12 e versões mais recentes (iPhone Xs e versões mais recentes) para usar o Neural Engine e conseguir inferência mais rápida. Se você quiser usar o delegado do Core ML também nos dispositivos mais antigos, consulte as práticas recomendadas

Modelos compatíveis

No momento, o delegado do Core ML oferece suporte a modelos flutuantes (FP32 e FP16).

Como testar o delegado do Core ML no seu próprio modelo

O delegado do Core ML já está incluído na versão noturna do CocoaPods Lite do TensorFlow. Para usar o delegado do Core ML, altere seu pod do TensorFlow Lite para incluir o subspec CoreML em Podfile.

target 'YourProjectName'
  pod 'TensorFlowLiteSwift/CoreML', '~> 2.4.0'  # Or TensorFlowLiteObjC/CoreML

OU

# Particularily useful when you also want to include 'Metal' subspec.
target 'YourProjectName'
  pod 'TensorFlowLiteSwift', '~> 2.4.0', :subspecs => ['CoreML']

Swift

    let coreMLDelegate = CoreMLDelegate()
    var interpreter: Interpreter

    // Core ML delegate will only be created for devices with Neural Engine
    if coreMLDelegate != nil {
      interpreter = try Interpreter(modelPath: modelPath,
                                    delegates: [coreMLDelegate!])
    } else {
      interpreter = try Interpreter(modelPath: modelPath)
    }
  

Objective-C


    // Import module when using CocoaPods with module support
    @import TFLTensorFlowLite;

    // Or import following headers manually
    # import "tensorflow/lite/objc/apis/TFLCoreMLDelegate.h"
    # import "tensorflow/lite/objc/apis/TFLTensorFlowLite.h"

    // Initialize Core ML delegate
    TFLCoreMLDelegate* coreMLDelegate = [[TFLCoreMLDelegate alloc] init];

    // Initialize interpreter with model path and Core ML delegate
    TFLInterpreterOptions* options = [[TFLInterpreterOptions alloc] init];
    NSError* error = nil;
    TFLInterpreter* interpreter = [[TFLInterpreter alloc]
                                    initWithModelPath:modelPath
                                              options:options
                                            delegates:@[ coreMLDelegate ]
                                                error:&error];
    if (error != nil) { /* Error handling... */ }

    if (![interpreter allocateTensorsWithError:&error]) { /* Error handling... */ }
    if (error != nil) { /* Error handling... */ }

    // Run inference ...
  

C (até a versão 2.3.0)

    #include "tensorflow/lite/delegates/coreml/coreml_delegate.h"

    // Initialize interpreter with model
    TfLiteModel* model = TfLiteModelCreateFromFile(model_path);

    // Initialize interpreter with Core ML delegate
    TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
    TfLiteDelegate* delegate = TfLiteCoreMlDelegateCreate(NULL);  // default config
    TfLiteInterpreterOptionsAddDelegate(options, delegate);
    TfLiteInterpreterOptionsDelete(options);

    TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);

    TfLiteInterpreterAllocateTensors(interpreter);

    // Run inference ...

    /* ... */

    // Dispose resources when it is no longer used.
    // Add following code to the section where you dispose of the delegate
    // (e.g. `dealloc` of class).

    TfLiteInterpreterDelete(interpreter);
    TfLiteCoreMlDelegateDelete(delegate);
    TfLiteModelDelete(model);
      

Práticas recomendadas

Como usar o delegado do Core ML em dispositivos sem o Neural Engine

Por padrão, o delegado do Core ML só será criado se o dispositivo tiver o Neural Engine. Ele retornará null se não for criado. Se você quiser executar o delegado do Core ML em outros ambientes (por exemplo, simulador), transmita .all como uma opção ao criar o delegado no Swift. Em C++ (e Objective-C), é possível transmitir TfLiteCoreMlDelegateAllDevices. O exemplo a seguir mostra como fazer isso:

Swift

    var options = CoreMLDelegate.Options()
    options.enabledDevices = .all
    let coreMLDelegate = CoreMLDelegate(options: options)!
    let interpreter = try Interpreter(modelPath: modelPath,
                                      delegates: [coreMLDelegate])
      

Objective-C

    TFLCoreMLDelegateOptions* coreMLOptions = [[TFLCoreMLDelegateOptions alloc] init];
    coreMLOptions.enabledDevices = TFLCoreMLDelegateEnabledDevicesAll;
    TFLCoreMLDelegate* coreMLDelegate = [[TFLCoreMLDelegate alloc]
                                          initWithOptions:coreMLOptions];

    // Initialize interpreter with delegate
  

C

    TfLiteCoreMlDelegateOptions options;
    options.enabled_devices = TfLiteCoreMlDelegateAllDevices;
    TfLiteDelegate* delegate = TfLiteCoreMlDelegateCreate(&options);
    // Initialize interpreter with delegate
      

O delegado do Metal(GPU) está sendo usado como substituto.

Quando o delegado do Core ML não é criado, como alternativa, você ainda pode usar Delegado do metal para ter benefícios de desempenho. O exemplo a seguir mostra como fazer isso:

Swift

    var delegate = CoreMLDelegate()
    if delegate == nil {
      delegate = MetalDelegate()  // Add Metal delegate options if necessary.
    }

    let interpreter = try Interpreter(modelPath: modelPath,
                                      delegates: [delegate!])
  

Objective-C

    TFLDelegate* delegate = [[TFLCoreMLDelegate alloc] init];
    if (!delegate) {
      // Add Metal delegate options if necessary
      delegate = [[TFLMetalDelegate alloc] init];
    }
    // Initialize interpreter with delegate
      

C

    TfLiteCoreMlDelegateOptions options = {};
    delegate = TfLiteCoreMlDelegateCreate(&options);
    if (delegate == NULL) {
      // Add Metal delegate options if necessary
      delegate = TFLGpuDelegateCreate(NULL);
    }
    // Initialize interpreter with delegate
      

A lógica de criação delegada lê o ID de máquina do dispositivo (por exemplo, iPhone11,1) para determinar a disponibilidade do Neural Engine. Veja o código para mais detalhes. Como alternativa, você pode implementar seu próprio conjunto de dispositivos da lista de bloqueio usando outras bibliotecas, como o DeviceKit.

Como usar uma versão mais antiga do Core ML

Embora o iOS 13 seja compatível com o Core ML 3, o modelo pode funcionar melhor quando for convertido com a especificação de modelo do Core ML 2. A versão da conversão de destino é definida para a versão mais recente por padrão, mas é possível mudar isso definindo coreMLVersion (no Swift, coreml_version na API C) na opção delegada para a versão mais antiga.

Operações compatíveis

As operações a seguir têm suporte do delegado do Core ML.

  • Adicionar
    • Apenas algumas formas podem ser transmitidas. No layout do tensor do Core ML, as formas de tensores a seguir são transmitidas. [B, C, H, W], [B, C, 1, 1], [B, 1, H, W], [B, 1, 1, 1].
  • GrupoMédio2D
  • Concat
    • A concatenação precisa ser feita ao longo do eixo do canal.
  • Conv2D
    • Os pesos e o viés devem ser constantes.
  • DepthwiseConv2D
    • Os pesos e o viés devem ser constantes.
  • Totalmente conectado (também conhecido como Dense ou InnerProduct)
    • Os pesos e o viés (se presentes) devem ser constantes.
    • Dá suporte apenas a casos de lote único. As dimensões de entrada precisam ser 1, exceto a última dimensão.
  • Hardswish
  • Logística (também conhecida como sigmoide)
  • MaxPool2D
  • MirrorPad
    • Somente a entrada 4D com o modo REFLECT é aceita. O padding precisa ser constante e só é permitido para dimensões H e W.
  • Mul
    • Apenas algumas formas podem ser transmitidas. No layout do tensor do Core ML, as formas de tensores a seguir são transmitidas. [B, C, H, W], [B, C, 1, 1], [B, 1, H, W], [B, 1, 1, 1].
  • Pad e PadV2
    • Somente a entrada 4D é compatível. O padding precisa ser constante e só é permitido para as dimensões H e W.
  • Relu
  • ReluN1To1
  • Relu6
  • Remodelamento
    • Compatível apenas quando a versão de destino do Core ML é 2. Ela não é aceita ao destinar o Core ML 3.
  • ResizeBilinear
  • SoftMax
  • Bronzea
  • TransposeConv
    • Os pesos devem ser constantes.

Feedback

Se for possível, crie um problema do GitHub com todos os detalhes necessários para reproduzir.

Perguntas frequentes

  • O delegado do CoreML aceitará substituto para a CPU se um gráfico contiver operações sem suporte?
    • Sim
  • O delegado do CoreML funciona no simulador de iOS?
    • Sim. A biblioteca inclui destinos x86 e x86_64 para que possa ser executada em um simulador, mas você não notará aumento de desempenho sobre a CPU.
  • O TensorFlow Lite e o delegado do CoreML oferecem suporte ao MacOS?
    • O TensorFlow Lite só é testado no iOS, mas não no MacOS.
  • Há suporte para as operações personalizadas do TF Lite?
    • Não, o delegado CoreML não é compatível com operações personalizadas e elas serão substitutas para a CPU.

APIs