ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
非同期予測によるCore ML統合の改善方法
Core ML実行エンジンの最新の改善点を活用してアプリの機械学習機能を高速化する方法を学びましょう。推論とモデルの高速な読み込みに役立つ、積極的なアセットのキャッシングの活用方法を紹介します。応答性の高いアプリを作成するために、最新の非同期予測のオプションや、パフォーマンスと全体的なメモリ使用量のバランスを考慮する方法を紹介します。モデルのハードウェア稼働率を理解し、その最大化に役立つAPIを紹介します。Core MLモデルの使用を最適化する方法については、WWDC23の「Use Core ML Tools for machine learning model compression」をご覧ください。
リソース
関連ビデオ
WWDC22
WWDC21
-
ダウンロード
♪ ♪
こんにちは Core MLチームの エンジニア Ben Levineです 本日は アプリへの Core MLの統合に関する 新機能についてお話します アプリでのインテリジェントな体験の構築は これまでになく簡単になりました Xcode SDKは 機械学習による 機能を活用してデプロイするための 強力な土台を提供します ドメインに特化した一連のフレームワークは シンプルなAPIを通じ ビルトイン インテリジェンスへのアクセスを提供します Appleがトレーニングと最適化を行った モデルにより これらの機能を提供します これらのモデルは Core MLを介して実行されます Core MLフレームワークは デバイス上で機械学習モデルを実行する エンジンを提供します これにより アプリ用にカスタマイズされた モデルを簡単にデプロイできます AccelerateとMetalの フレームワークファミリーの 助けを借りて Appleシリコンの高性能な 計算機能を活用し ハードウェアの詳細を抽象化します Core MLの使命は 機械学習モデルを アプリに統合するお手伝いをすることです 今年のCore MLはパフォーマンスと 柔軟性に重点を置きました ワークフロー APIサーフェス そして基礎となる 推論エンジンを改善しました Core ML統合を最適化する 新たな機会を提供する ワークフローを解説する前に 最新のOSにアップデートするだけで 自動的に得られる パフォーマンスに関する 潜在的な利点を紹介します
iOS 16と17の相対的な予測時間を比較すると 多くのモデルでiOS 17の方が 単純に高速なことが分かります この推論エンジンの高速化は OSによるもので モデルの再コンパイルや コードの変更は必要ありません これは他のプラットフォームでも同様です 当然ながら 高速化の度合いは モデルやハードウェアに依存します 本題に戻り Core MLをアプリに統合する際の ワークフローの概要を説明します その過程で ワークフローの 様々な部分における 最適化の機会についても取り上げます 次に モデルの統合に焦点を当て 演算の可用性 モデルのライフサイクル 非同期予測に関する 新しいAPIとその動作について説明します まず Core MLワークフローの 概要から説明します Core MLをアプリに組み込むには 2つの段階があります 1つ目はモデルの開発 2つ目はアプリ内でモデルを使うことです モデルの開発には いくつかの選択肢があります 独自のモデルを開発する上で最も便利なのは Create MLを使う方法です Create MLは 一般的な機械学習 タスクのための様々なテンプレートを提供し OSに組み込まれている 高度に最適化されたモデルを活用できます モデル開発のワークフローをガイドし 結果をインタラクティブに評価できます 詳細については 今年の Create MLに関する動画をご覧ください
モデルを開発するもう1つの方法は Python機械学習フレームワークを使って モデルをトレーニングすることです そして CoreMLTools pythonパッケージを 使って Core MLモデル形式に変換します 最後に Appleのハードウェア上での精度と パフォーマンスの両面から モデルを評価することが重要です 評価で得たフィードバックを使用して モデルをさらに最適化するために これらのステップのいくつかを 再検討することはよくあります これらのステップには 最適化の機会がたくさんあります トレーニングでは トレーニングデータを 収集し選択する方法が重要です モデルがデプロイされ ユーザーの手に渡った時に モデルに渡されるデータと 一貫性が無ければなりません モデルアーキテクチャの選択も重要です 複数の選択肢を検討することに なるでしょうが それぞれが トレーニングデータの要件 精度 サイズ 性能の間でトレードオフの関係にあります これらのトレードオフの多くは トレーニングの時点では完全には分からず 開発フロー全体を通じて 数回の反復作業が必要となる場合があります 次はモデルの変換です Core ML Toolsは 変換されたモデルの精度 フットプリント 計算コスト最適化のための 様々なオプションを提供します アプリのデータフローに最適な 入出力形式を選択し 不要なコピーを避けることができます 入力形状が変化する可能性がある場合 1つの形状だけを選択したり 複数の形状別モデルを 切り替えるのではなく その変化を指定することができます 演算精度は モデル全体または個々の演算に対して 明示的に設定することもできます Float32とFloat16の両方が使用可能です 演算の精度に加えて モデルパラメータの表現も ある程度コントロールできます Core ML Toolsには トレーニング後の 重みの量子化と圧縮のための ユーティリティが付属しています これらのユーティリティは モデルのフットプリントを大幅に削減し デバイス上での パフォーマンス向上に役立ちます しかし このような利点を得るために 精度にトレードオフが生じます この分野で役立つ新しいツールがあります CoreMLToolsパッケージに 新しい最適化サブモジュールがあります これはトレーニング後 圧縮ユーティリティを統合して更新し PyTorch用に量子化を考慮した 新しいトレーニング拡張機能を追加します これにより トレーニング中に量子化されたモデルの 精度の維持を助ける データ駆動型 最適化機能を利用できるようになります これは Core MLの ML Programモデルタイプにおける アクティベーション量子化をサポートする 新しい操作に連動します 詳しくは Core MLを使った 機械学習モデルの圧縮に関する 今年のセッションをご覧ください
次は評価についてです モデルを評価するオプションの1つは Core ML Toolsを使って 変換されたモデルの予測を Pythonコードから直接実行することです これは 皆さんのアプリの コードが使用するのと同じCore MLの 推論スタックを使用し モデル変換時の選択がモデルの精度と パフォーマンスにどう影響するかを 素早く確認できます Xcodeは モデルの評価と 探索に関する便利なツールも いくつか提供しています モデルプレビューは 多くの一般的な モデルタイプで利用可能です これは モデルにいくつかの サンプル入力を提供し コードを書くことなく 予測される出力をプレビューできます Core MLのパフォーマンスレポートでは 接続されたデバイスでのロード時間 予測時間 コンパイル時間など モデルの計算パフォーマンスの 内訳をみることができます これは モデルのトレーニング前でも アーキテクチャを 評価するのに役立ちます 全体のワークフローに戻りましょう 次のトピックはモデルの統合についてです モデルの統合はアプリ開発の一部です アプリで使用する他のリソースと同様に Core MLモデルの使用方法を 注意深く管理し 最適化することが大切です
モデルの統合には3つのステップがあります まず モデルを使用するための アプリのコードを書きます いつどこでモデルを読み込むか モデルの入力データを どのように用意し 予測を行い 結果をどう使うかに関するコードです
次に このコードをモデルと 共にコンパイルします そして3つ目は アプリの中で実行される モデルのテスト 実行 プロファイリングです プロファイリングに関しては Core MLと Neural Engineの Instrumentsが役に立つでしょう これは 配信準備が整うまで 設計と最適化を 繰り返すプロセスでもあります 今年は モデル統合の最適化に役立つ 新機能もいくつか追加されました 1つ目はコンピュータの可用性です Core MLはAppleのすべての プラットフォームでサポートされており デフォルトでは 利用可能なすべての コンピュータを考慮して実行を最適化します これにはCPU GPU および利用可能な場合は Neural Engineが含まれます ただし これらの演算デバイスの パフォーマンス特性と可用性は アプリが実行される可能性のある サポート されるハードウェアによって異なります これは MLが提供する機能を利用する ユーザーの体験に影響を与えたり モデルや構成の選択に 影響を与える可能性があります たとえば いくつかの体験では パフォーマンスや消費電力の 要件を満たすために Neural Engine上で 動作するモデルが必要な場合もあります そして 演算デバイスの可用性を実行中に 検査する新しいAPIが利用可能になりました MLComputeDevice enumは 演算デバイスの種類と 関連する値を持つ 特定の演算デバイスの プロパティをキャプチャします MLModelの availableComputeDevicesプロパティで Core MLで使用可能なデバイスを 調べることができます たとえば このコードはNeural Engineが 利用可能かどうかを確認します 具体的には 利用可能な すべての演算デバイスの一覧に タイプがNeural Engineのものが 含まれるかどうかを確認します モデル統合の次のトピックは モデルライフサイクルを理解することです まず モデルアセットタイプの 確認から始めます ソースモデルと コンパイル済み モデルの2種類があります ソースモデルのファイル拡張子は MLModel またはMLPackageです 構築と編集のために設計された オープンフォーマットです コンパイル済みモデルの ファイル拡張子はMLModelCです ランタイムアクセス用に設計されています ほとんどの場合 アプリのターゲットに ソースモデルを追加すると Xcodeはモデルをコンパイルして アプリのリソースに追加します 実行する際 モデルを使用するために MLModelをインスタンス化します
Instantiate関数は コンパイル済みフォームのURLと オプションの設定を受け取ります その結果 MLModelは 指定された設定と デバイス固有のハードウェア機能に基づいて 最適な推論に必要な すべてのリソースをロードします では ロード中に何が起こるかを 詳しく見てみましょう まず Core MLはキャッシュをチェックし 設定とデバイスに基づいてモデルを すでに特殊化しているかどうかを確認します キャッシュがあれば 必要なリソースをロードして戻ります これをCached loadと呼びます この設定がキャッシュで見つからない場合 デバイス特化型コンパイルが トリガーされます このプロセスが完了すると 出力がキャッシュに追加され そこからロードを終了します これをUncached loadと呼びます 特定のモデルでは Uncached loadに かなりの時間が掛かることがあります しかし モデルをデバイスに最適化し その後のロードを可能な限り 高速化することに重点を置いています
デバイスの特殊化の際 Core MLはまずモデルを解析し 一般的な最適化パスを適用します その後 推定される性能と ハードウェアの可用性に基づき 特定の演算デバイスのために 一連の処理をセグメント化します このセグメント化は その後キャッシュされます 最後のステップは 各セグメントが割り当てられた 演算デバイスのために デバイス固有のコンパイルを行うことです このコンパイルは 特定の演算デバイスのための さらなる最適化を含め 演算デバイスが実行できる アーティファクトを出力します 完了すると Core MLはこれらの アーティファクトをキャッシュし 以降のモデル読み込みに使用します
Core MLは特殊化されたアセットを ディスク上にキャッシュします これらはモデルのパスと 設定に関連付けられます これらのアセットは アプリの起動や デバイスの再起動後も持続します デバイスの空きディスク容量が不足したり システムアップデートが行われたり コンパイル済みモデルが 削除または変更されると オペレーティングシステムは キャッシュを削除します この場合 次のモデルロードで デバイスの特殊化が再度実行されます
モデルのロードがキャッシュに ヒットしているか調べるには Core ML Instrumentでアプリをトレースし ロードイベントを見ます “prepare and cache”のラベルがあれば Uncached loadなので Core MLはデバイスの特殊化を行い その結果をキャッシュします ロードイベントに“cached”という ラベルがある場合 cached loadであり デバイスの特殊化は行われていません これはMLProgramモデルに 特化した新機能です Core MLパフォーマンスリポートでは ロードのコストを可視化出来ます デフォルトでは cached load時間の 中央値が表示されます
Uncached loadのロード時間を表示する オプションも追加されました モデルのロードは レイテンシとメモリに 負荷が掛かる可能性があるため 一般的なベストプラクティスを紹介します
まず UIスレッドでアプリを起動している 最中に モデルをロードしないでください 代わりに 非同期ロードAPIを使用するか 遅延ロードを検討してください 次に アプリが連続して 多くの予測を実行する可能性がある場合 一連の予測ごとにモデルを 再ロードするのではなく モデルをロードしたままにしましょう 最後に アプリがしばらくの間モデルを 使用しない場合は アンロードできます これはメモリの圧迫の回避に役立ちます キャッシュのおかげで その後のロードも速くなるでしょう モデルをロードしたら 次はそのモデルを使って 予測を実行することを考えます 新しい非同期オプションのデモを紹介します
新しい非同期予測APIの解説用に 画像のギャラリーを表示し 画像にフィルタを適用するアプリを使います グレースケール画像を入力し その画像をカラー化し出力する Core MLモデルを使った フィルターに焦点を当てます これがアプリの動作の例です グレースケールの元の画像を読み込みます そして カラー化画像モードを選択すると Core MLを使って画像をカラー化します 下にスクロールすると 確かにモデルは動作しているのですが 思っていたよりも少し遅いです また ずっと下にスクロールすると 画像のカラー化にかなり時間が 掛かることに気づきます
上にスクロールを戻すと 途中のすべての画像を カラー化して時間が掛かっていたようです ですがSwiftUIのコードでは LazyVGridを使って画像を保持しています なので 画面外に出た タスクはキャンセルされるはずです 現在の実装を見て なぜパフォーマンスが低いのか なぜタスクが キャンセルされないのか確認しましょう このように実装されています 同期予測APIはスレッドセーフでは無いので アプリはモデル上で 順番に予測を行わなければなりません これはColorizingServiceをactorにして 一度にcolorizeメソッドを1つだけ 呼び出すことで実現できます このactorは アプリにバンドルされる モデル用に自動生成される インターフェイスである colorizerModelを所有しています colorizeメソッドは 現在2つの操作を行っています 1つ目はモデルの入力の準備です これはモデルの入力サイズに合わせて 画像サイズを変更することを含みます その後 モデルを通して入力を実行し カラー化された出力を取得します Core ML Instrumentsテンプレートで 実行されているアプリの Instrumentsトレースをキャプチャしました
Instrumentsの トレースを見ると 予測はactorの 分離によって 順番に行われていることが分かります しかし 次の予測が実行される前に 各実行間にギャップがあり パフォーマンス不足の一因となっています これはactorの分離が モデル予測だけでなく 入力の準備にも適用された結果です 改善策の1つとして 入力準備を 非分離メソッドとしてマークし 次のcolorizeリクエストがactorに 入らないようブロックする方法があります これは役に立ちますが Core ML予測自体は シリアル化されており 処理のボトルネックになっています Core ML予測自体の並列性を利用するために バッチ予測APIの使用を検討します 入力のバッチを受け取り モデルを通して実行します その裏で Core MLは可能な限り 並列処理を行います colorizeメソッドのバッチバージョンを 作るのはとても簡単です しかし難しいのは 入力をバッチに集め このメソッドに渡す方法を考えることです 実はこのユースケースには バッチ予測APIの使用を難しくしている 複数の側面があります バッチAPIは 仕事量があらかじめ 分かっている時に最も効果を発揮します この場合 処理する画像の量は固定ではなく 画面サイズとスクロール量の関数になります バッチサイズは自分で決められますが バッチサイズに満たないケースでも 処理が必要です また 画像を一括でカラー化するため これまでと違ったUI体験になります 最後に ユーザーがスクロールしても バッチのキャンセルはできません
このような課題があり 私は一度に1つの予測を 処理するAPIをキープしたいのです そこで 新しい非同期予測APIが とても役に立ちます スレッドセーフで Swiftの並行処理と Core MLがうまく動作します 非同期の設計に切り替えるため 最初にカラー化メソッドを非同期にします そして APIの新しい 非同期バージョンを使用するために 予測呼び出しの前に awaitキーワードを追加します そして ColorizingServiceを actorからクラスに変更します こうすることで 複数の画像を 同時にカラー化出来ます 最後に メソッドの最初に キャンセルのチェックを追加します 非同期予測APIは 特に複数の予測が 同時に要求された場合 キャンセルに対応するよう 最善を尽くしますが この場合 最初に追加のチェックを 入れるのが最善です こうすることで カラー化 メソッドを入力する前に タスクがキャンセルされた場合 入力の準備が避けられます では これらの変更を行い アプリを再実行します
先程と同じように Colorizedモードに設定します すでに 画像のカラー化が かなり速くなっているのが分かります 下まで一気にスクロールすると 画像はほぼ即時に読み込まれます 少し上にスクロールすると スクロールに伴い 画像がカラー化されていることが分かります つまり 最初に下までスクロールした時に カラー化の呼び出しが うまくキャンセルされたということです この新しい非同期設計を 使用したトレースを見ると 予測が複数の画像で 同時に行われているのが分かります これは 複数の予測インターバルが縦に スタックされていることで示されています このモデルは 部分的に Neural Engine上で動作するため Neural Engine Instrumentでも 見ることができます 画像を順番にカラー化する 初期の実装では スクロール無しでも 画像の初期ビューの カラー化に約2秒掛かっていました
画像を同時にカラー化する 非同期実装に切り替えたところ その時間は半分の約1秒に短縮されました 全体として 非同期予測APIと Colorizerモデルの 並行処理を利用することで 総スループットを約2倍改善できました しかし モデルやユースケースが 並行処理により受けられる恩恵は いくつかの要因に大きく 依存することに注意が必要です その要因には モデルのオペレーション 演算ユニットとハードウェアの組み合わせ 演算デバイスが行っている 他の作業などが含まれます また MLプログラムと パイプラインモデルタイプは 予測を同時に実行することで パフォーマンスを最大限に改善します
全般的に アプリで並行処理を行う場合は ワークロードを注意深く分析し ユースケースにとって有益かご確認ください
アプリに並行処理を追加する際に 注意すべき もう1つの重要な点は メモリ使用量です 多くのモデルの入力と出力が 同時にメモリにロードされると アプリのピークメモリ使用量が 大幅に増大する可能性があります これはCore ML Instrumentと Allocations Instrumentを 組み合わせることで分析できます
カラー化モデルを実行するために 多くの入力をメモリに ロードしているため アプリの メモリ使用量が急激に上昇しています
潜在的な問題として このコードのカラー化 メソッドにはフロー制御が無いため 同時にカラー化される画像の量に 決まった制限が無いことが挙げられます モデルの入力と出力が小さければ 問題は無いかもしれません しかし 入出力が大きく 多くのセットが メモリに同時に読み込まれると アプリのピークメモリ使用量が 大幅に増加する可能性があります
これを改善する方法は 実行中の予測の最大量を 制限するロジックを追加することです これにより 同時にメモリにロードされる 入力と出力が減り 予測実行中の ピークメモリ使用量が減少します この例では すでに2つの作業項目がある場合 前の作業項目が完了するまで 新しい作業項目を延期しています 最適な戦略は ユースケースによって異なります たとえば カメラからデータを ストリーミングする場合 作業を延期する代わりに 単純にドロップしたい場合があります こうすることで フレームが蓄積したり 時間的に 関連性のない作業を行うことを避けられます 少し戻って 異なる予測APIを いつ使うかについて 一般的なガイダンスを紹介します
もし同期的なコンテキストで 各入力が利用可能になるまでの時間が モデルのレイテンシより長い場合 同期予測APIはうまく機能します 入力がバッチで利用可能になる場合 バッチ予測APIが最適でしょう
もし 非同期的なコンテキストで 大量の入力が時間と共に個別に 利用可能になるのであれば 非同期APIが最も役に立つでしょう まとめると Core ML ワークフローを進める上で モデル開発とモデル統合の両方で 最適化出来る機会は数多くあります 新しいcompute availability APIは デバイス上で利用可能な ハードウェアに基づいて 実行時に決定を下すのに役立ちます モデルのライフサイクルと キャッシュの動作を理解することは どこでモデルをロードし アンロード するかを決定する際に役に立ちます そして最後に 非同期予測APIはCore MLを 他の非同期Swiftコードと統合し 同期予測をサポートすることで スループットの向上に貢献します 以上 Core MLチームのBenがお届けしました AIじゃないですよ
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。