ML Kit を使用して推論に TensorFlow Lite モデルを使用する(iOS)

ML Kit を使用すると、TensorFlow Lite モデルを使用して端末上で推論を実行できます。

ML Kit は、iOS 9 以降を実行する端末上でのみ、TensorFlow Lite モデルを使用できます。

この API の使用例については、GitHub の ML Kit クイックスタート サンプルをご覧ください。

準備

  1. まだアプリに Firebase を追加していない場合は、スタートガイドの手順に沿って追加してください。
  2. Podfile に ML Kit ライブラリを含めます。
    pod 'Firebase/Core'
    pod 'Firebase/MLModelInterpreter'
    
    プロジェクトのポッドをインストールまたは更新した後に、.xcworkspace を使用して Xcode プロジェクトを開くようにしてください。
  3. アプリに Firebase をインポートします。

    Swift

    import Firebase

    Objective-C

    @import Firebase;
  4. 使用する TensorFlow モデルを TensorFlow Lite(tflite)形式に変換します。TOCO: TensorFlow Lite 最適化コンバーターをご覧ください。

モデルをホストまたはバンドルする

アプリの推論に TensorFlow Lite モデルを使用するには、事前に ML Kit でモデルを利用可能にしておく必要があります。ML Kit は、Firebase を使用してリモートにホストされている TensorFlow Lite モデル、端末にローカルに保存されている TensorFlow Lite モデルのいずれか、またはその両方を使用できます。

モデルを Firebase にホストし、ローカルにも保存すると、モデルの最新バージョンが利用可能な場合にそのバージョンを常に利用できます。Firebase にホストされたモデルが利用できない場合でも、アプリの ML 機能は引き続き動作します。

モデルのセキュリティ

TensorFlow Lite モデルを ML Kit で利用可能にする方法を問わず、ML Kit はそれらのモデルを標準のシリアル化された protobuf 形式でローカル ストレージに格納します。

理論上、これは誰でもモデルをコピーできることを意味します。ただし、実際には、ほとんどのモデルはアプリケーションに固有であり、最適化により難読化されています。このため、リスクは、競合他社がコードを逆アセンブルして再利用する場合と同程度です。それでもやはり、アプリでカスタムモデルを使用する前に、このリスクを認識しておく必要があります。

モデルを Firebase でホストする

TensorFlow Lite モデルを Firebase でホストするには:

  1. Firebase コンソールの [ML Kit] セクションで、[カスタム] タブをクリックします。
  2. [カスタムモデルを追加](または [別のモデルを追加])をクリックします。
  3. Firebase プロジェクトでモデルを識別するための名前を指定し、.tflite ファイルをアップロードします。

Firebase プロジェクトにカスタムモデルを追加した後は、指定した名前を使用してアプリ内でモデルを参照できます。モデルの新しい .tflite ファイルはいつでもアップロードできます。アプリは、次回の起動時に新しいモデルをダウンロードして使い始めます。アプリがモデルを更新するために必要な端末の条件を定義できます(以下を参照)。

モデルをローカルで使用可能にする

TensorFlow Lite モデルをローカルで使用可能にするには、モデルをアプリにバンドルするか、実行時に各自のサーバーからモデルをダウンロードします。

TensorFlow Lite モデルをアプリにバンドルするには、Xcode プロジェクトに .tflite ファイルを追加します。その際、[Copy bundle resources] を忘れずに選択します。.tflite ファイルがアプリのバンドルに含められ、ML Kit で使用可能になります。

独自のサーバーにモデルをホストする場合は、アプリの中で適切なタイミングでモデルをローカル ストレージにダウンロードできます。その後、モデルはローカル ファイルとして ML Kit で使用可能になります。

モデルを読み込む

TensorFlow Lite モデルを推論に使用するには、最初に .tflite ファイルの場所を指定します。

Firebase でモデルをホストする場合は、CloudModelSource オブジェクトを登録します。その際に、モデルをアップロードしたときに割り当てた名前、ML Kit が最初にモデルをダウンロードする条件、更新が利用可能になった場合にそれをダウンロードする条件を指定します。

Swift

let conditions = ModelDownloadConditions(wiFiRequired: true, idleRequired: true)
let cloudModelSource = CloudModelSource(
  modelName: "my_cloud_model",
  enableModelUpdates: true,
  initialConditions: conditions,
  updateConditions: conditions
)
let registrationSuccessful = ModelManager.modelManager().register(cloudModelSource)

Objective-C

FIRModelDownloadConditions *conditions =
    [[FIRModelDownloadConditions alloc] initWithWiFiRequired:YES
                                                idleRequired:YES];
FIRCloudModelSource *cloudModelSource =
    [[FIRCloudModelSource alloc] initWithModelName:@"my_cloud_model"
                                enableModelUpdates:YES
                                 initialConditions:conditions
                                  updateConditions:conditions];
  BOOL registrationSuccess =
      [[FIRModelManager modelManager] registerCloudModelSource:cloudModelSource];

アプリにモデルをバンドルした場合や、実行時に独自のホストからモデルをダウンロードした場合は、LocalModelSource オブジェクトを登録します。その際に、.tflite モデルのローカルパスを指定し、アプリ内で識別できる固有名をローカルソースに割り当てます。

Swift

guard let modelPath = Bundle.main.path(
  forResource: "my_model",
  ofType: "tflite"
) else {
  // Invalid model path
  return
}
let localModelSource = LocalModelSource(modelName: "my_local_model",
                                        path: modelPath)
let registrationSuccessful = ModelManager.modelManager().register(localModelSource)

Objective-C

NSString *modelPath = [NSBundle.mainBundle pathForResource:@"my_model"
                                                    ofType:@"tflite"];
FIRLocalModelSource *localModelSource =
    [[FIRLocalModelSource alloc] initWithModelName:@"my_local_model"
                                              path:modelPath];
BOOL registrationSuccess =
      [[FIRModelManager modelManager] registerLocalModelSource:localModelSource];

次に、Cloud ソース、ローカルソース、またはその両方を使用して ModelOptions オブジェクトを作成し、それを使用して ModelInterpreter のインスタンスを取得します。ソースが 1 つのみである場合は、使用しないソースタイプに nil を指定します。

Swift

let options = ModelOptions(
  cloudModelName: "my_cloud_model",
  localModelName: "my_local_model"
)
let interpreter = ModelInterpreter(options: options)

Objective-C

FIRModelOptions *options = [[FIRModelOptions alloc] initWithCloudModelName:@"my_cloud_model"
                                                            localModelName:@"my_local_model"];
FIRModelInterpreter *interpreter = [FIRModelInterpreter modelInterpreterWithOptions:options];

クラウドモデルとローカルモデルの両方のソースを指定すると、モデル インタープリタはクラウドモデルが使用できる場合はそれを使用し、使用できない場合はローカルモデルを使用します。

モデルの入力と出力を指定する

次に、ModelInputOutputOptions オブジェクトを作成して、モデルの入力と出力の形式を指定する必要があります。

TensorFlow Lite モデルは、1 つ以上の多次元配列を入力として受け取り、出力として生成します。これらの配列には、UInt8Int32Int64、または Float32 のいずれかが含まれます。モデルで使用する配列の数と次元(「シェイプ」)で ML Kit を構成する必要があります。

たとえば、画像分類モデルは、1 つの 640 x 480 トゥルーカラー(24 ビット)画像を表す 1 x 640 x 480 x 3 バイトの配列を入力として受け取り、画像がモデルによって予測される 1000 カテゴリのいずれかのメンバーである確率をそれぞれ表す 1000 個の Float32 値のリストを出力として生成します。

Swift

let ioOptions = ModelInputOutputOptions()
do {
  try ioOptions.setInputFormat(index: 0, type: .uInt8, dimensions: [1, 640, 480, 3])
  try ioOptions.setOutputFormat(index: 0, type: .float32, dimensions: [1, 1000])
} catch let error as NSError {
  print("Failed to set input or output format with error: \(error.localizedDescription)")
}

Objective-C

FIRModelInputOutputOptions *ioOptions = [[FIRModelInputOutputOptions alloc] init];
NSError *error;
[ioOptions setInputFormatForIndex:0
                             type:FIRModelElementTypeUInt8
                       dimensions:@[@1, @640, @480, @3]
                            error:&error];
if (error != nil) { return; }
[ioOptions setOutputFormatForIndex:0
                              type:FIRModelElementTypeFloat32
                        dimensions:@[@1, @1000]
                             error:&error];
if (error != nil) { return; }

入力データの推論を行う

最後に、モデルを使用して推論を行うために、モデルの入力データを使用して ModelInputs オブジェクトを作成し、そのオブジェクトとモデルの入出力オプションをモデル インタープリタrun(inputs:options:) メソッドに渡します。最高のパフォーマンスを得るには、モデルの入力データを DataNSData )オブジェクトとして渡します。

Swift

let input = ModelInputs()
do {
  var data: Data  // or var data: Array
  // Store input data in `data`
  // ...
  try input.addInput(data)
  // Repeat as necessary for each input index
} catch let error as NSError {
  print("Failed to add input: \(error.localizedDescription)")
}

interpreter.run(inputs: input, options: ioOptions) { outputs, error in
  guard error == nil, let outputs = outputs else { return }
  // Process outputs
  // ...
}

Objective-C

FIRModelInputs *inputs = [[FIRModelInputs alloc] init];
NSData *data;  // Or NSArray *data;
// ...
[inputs addInput:data error:&error];  // Repeat as necessary.
if (error != nil) { return; }
[interpreter runWithInputs:inputs
                   options:ioOptions
                completion:^(FIRModelOutputs * _Nullable outputs,
                             NSError * _Nullable error) {
  if (error != nil || outputs == nil) {
    return;
  }
  // Process outputs
  // ...
}];

返されたオブジェクトの output(index:) メソッドを呼び出すことで、出力を取得できます。次に例を示します。

Swift

// Get first and only output of inference with a batch size of 1
let probabilities = try? outputs.output(index: 0)

Objective-C

// Get first and only output of inference with a batch size of 1
NSError *outputError;
[outputs outputAtIndex:0 error:&outputError];

出力の使い方は、使用しているモデルによって異なります。たとえば、分類を実行する場合は、次のステップとして結果のインデックスを、それらが表すラベルにマッピングできます。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。