Web ニューラルネットワーク API

W3C 勧告候補草案,

この文書の詳細
このバージョン:
https://www.w3.org/TR/2026/CRD-webnn-20261021/
最新の公開バージョン:
https://www.w3.org/TR/webnn/
編集者草案:
https://webmachinelearning.github.io/webnn/
以前のバージョン:
履歴:
https://www.w3.org/standards/history/webnn/
実装報告:
https://wpt.fyi/results/webnn?label=master&label=experimental&aligned&q=webnn
テストスイート:
https://github.com/web-platform-tests/wpt/tree/master/webnn
フィードバック:
GitHub
仕様内に記載
編集者:
Ningxin Hu (Intel Corporation)
Dwayne Robinson (Microsoft Corporation)
元編集者:
Chai Chaoweeraprasit (Microsoft Corporation)
その他:
実装状況, 解説, サンプル

概要

この文書では、ニューラルネットワーク推論のハードウェアアクセラレーション用に特化した低レベル API について説明します。

この文書のステータス

このセクションでは、この文書の公開時点におけるステータスについて説明します。現在の W3C 公開文書の一覧およびこの技術報告書の最新版は、W3C 標準および草案の索引にあります。

この文書は、 Web Machine Learning ワーキンググループによって 勧告 トラックを使用した候補勧告草案として公開されました。

候補勧告としての公開は、W3C およびそのメンバーによる承認を意味するものではありません。候補 勧告草案には、ワーキンググループが後続の候補勧告スナップショットに 含めることを意図している、以前の候補勧告からの変更が統合されています。

これは草案文書であり、いつでも他の文書によって更新、置換、または廃止される可能性があります。この文書を 作業中の文書以外として引用することは不適切です。

Web Machine Learning ワーキンググループは、グループがまだ対処していないすべてのバグ 報告の一覧を管理しています。 未解決の問題に対する仕様テキストの提案を含むプルリクエストを強く推奨します。

この文書は、 W3C 特許ポリシーの下で活動するグループによって作成されました。 W3C は、グループの成果物に関連して行われた すべての 特許開示の公開一覧を管理しています。そのページには、 特許を開示するための手順も含まれています。ある個人が、 必須 クレームを含むと考える特許について実際の知識を有する場合、その個人は W3C 特許ポリシーの セクション 6に従ってその情報を開示しなければなりません。

この文書は、2025 年 8 月 18 日版 W3C プロセス文書によって管理されます。

候補勧告スナップショット 2024 年 4 月 11 日から 2026 年 1 月 22 日までの間に、WebNN 仕様は 100 件を超える重要な変更を伴う大幅な進化を遂げました。特に注目すべき 追加には、Transformer のサポートを強化する第 3 波の演算子、バッファ 共有用の MLTensor API、および新しい抽象デバイス選択メカニズムが含まれます。API サーフェスは最新化され、 より幅広い実装経験と開発者からの フィードバックに基づいて相互運用性が改善されました。このバージョンの仕様では、 フィンガープリンティング対策を含むセキュリティおよびプライバシー上の考慮事項が強化され、新しいアクセシビリティ上の考慮事項も追加されています。これらの変更は、 開発者の利便性の向上、より幅広いバックエンド 互換性、および標準への適合性を備え、製品利用に向けて仕様が成熟していることを反映しています。詳細については、§ 14 変更を参照してください。

この文書は常時保守および更新されています。この文書の一部は作業中であり、 今後の改善が改訂された候補勧告草案およびスナップショットに反映されることが期待されています。

勧告案への移行を要求する前に、 ワーキンググループは、以下を実証することを目指します。

1. はじめに

Web Neural Network API は、オペレーティングシステムおよび基盤となるハードウェアプラットフォームの 機械学習機能を、プラットフォーム固有の機能に依存することなく利用できる、 Web に適したハードウェア非依存の抽象化レイヤーを定義します。この抽象化レイヤーは、主要な機械学習 JavaScript フレームワークの要件に対応し、ML 分野に精通した Web 開発者がライブラリの助けを借りずに カスタムコードを記述することも可能にします。

図解による概要については、解説文書を参照してください。

2. ユース ケース

2.1. アプリケーションのユースケース

このセクションでは、ニューラルネットワーク推論の ハードウェアアクセラレーションに関するアプリケーションレベルのユースケースを示します。これらのユースケースに含まれるすべてのアプリケーションは、 事前学習済みのディープニューラルネットワーク (DNN) [models] 上に構築できます。

注: ここで説明するユースケースの一部は、 その性質上、プライバシーを侵害する可能性があることに注意してください。このようなユースケースで API を使用することを計画している開発者は、 API がユーザーの利益のために、ユーザーが理解し承認した目的で使用されることを 確保すべきです。また、 Web 機械学習の倫理原則 [webmachinelearning-ethics] を適用し、透明性、データ最小化、ユーザーによる制御などの 適切なプライバシーリスク軽減策を実装すべきです。

注: § 3 アクセシビリティ上の 考慮事項では、これらのユースケースのアクセシビリティを向上させる方法に関する指針を提供しています。

2.1.1. 人物検出

ユーザーが Web ベースのビデオ会議アプリケーションを開いていますが、一時的に 部屋を離れます。アプリケーションは、物体検出を使用して、ユーザーが PC の前にいるかどうかを監視します(たとえば、単一の DNN を使用する [SSD] や [YOLO] などの物体検出手法を使用して)、 カメラ入力フレーム内の人物を含む領域を 検出します。

ユーザーが戻ると、アプリケーションは自動的にそのユーザーを検出し、 他のオンラインユーザーに、そのユーザーが現在アクティブであることを通知します。

2.1.2. セマンティックセグメンテーション

オフィス内に利用可能な会議室がないため、ユーザーは自分のデスクから Web ベースのビデオ会議アプリケーションを介して 電話会議に参加します。電話会議中、 ユーザーは自分の部屋や背景にいる人々が 見えることを望みません。他の人々や周囲のプライバシーを保護するため、 アプリケーションは [DeepLabv3+]、 [MaskR-CNN] または [SegAny] などの機械学習モデルを実行して、 画像を意味的にセグメントへ分割し、 他の人物や背景を表すセグメントを別の画像で置き換えます。

2.1.3. 骨格検出

Web ベースのビデオ会議アプリケーションは、 [PoseNet] などのリアルタイム人物姿勢 推定を可能にする機械学習モデルを実行してユーザーの骨格姿勢を追跡し、そのユーザーの ジェスチャーやボディランゲージを認識します。ユーザーが 手を上げると、マイクのミュートが自動的に解除され、電話会議で 発言を開始できます。

2.1.4. 顔認識

会議室には複数の人がおり、Web ベースのビデオ会議アプリケーションを使用して オンライン会議に参加します。アプリケーションは、 物体検出(たとえば、[SSD] などの物体検出手法)を使用して参加者の顔を検出し、 [FaceNet] など、 2 つの顔が同一であるかどうかを検証する機械学習モデルを実行して、各顔が 前回の会議に存在していたかどうかを確認します。

2.1.5. 顔ランドマーク検出

ユーザーはオンライン眼鏡店で、自分によく似合う新しい眼鏡を 探したいと考えています。オンラインストアは、Face Alignment Network [FAN] などの機械学習モデルを実行する Web ベースの試着シミュレーターを提供し、 目、鼻、口などの顔ランドマークを検出します。ユーザーが眼鏡を選択すると、シミュレーターは 顔画像上で検出された目の位置に、選択した眼鏡を 適切に描画します。

2.1.6. スタイル変換

ユーザーがオンラインストアで化粧品を探しており、どの色が 自分の顔に合うかを考えています。オンラインストアは化粧品の顔メイクのサンプル画像を表示し、 [ContextualLoss] や [PairedCycleGAN] などの機械学習モデルを実行して、サンプルのメイク画像の メイクスタイルをユーザーの顔画像へ転送するメイクシミュレーターを提供します。ユーザーはシミュレーターで、 選択したメイクが自分の顔でどのように見えるかを確認できます。

2.1.7. 超解像

Web ベースのビデオ会議アプリケーションが相手からビデオストリームを受信していますが、 ネットワークの輻輳によりビデオの解像度が低下します。知覚される 映像品質の低下を防ぐため、アプリケーションは [SRGAN] などの超解像用機械学習モデルを実行して、 より高解像度のビデオフレームを生成します。

2.1.8. 画像キャプショニング

アクセシビリティを向上させるため、Web ベースのプレゼンテーションアプリケーションは、 [im2txt] など、プレゼンテーションスライドの説明文を予測する機械学習モデルを実行して、 自動画像キャプショニングを提供します。

2.1.9. テキストから画像への変換

画像は現代の Web 体験の中核をなす要素です。プライバシーを保護する方法で テキスト入力に基づいて画像を生成できる機能は、Web アプリケーションやコンテンツの視覚的な パーソナライズおよび適応を可能にします。たとえば、Web アプリケーションは、Web ページ上の自然言語による説明、 またはユーザーがテキストプロンプト内で提供した説明を入力として使用し、その テキストの説明に一致する画像を生成できます。このテキストから画像へのユースケースは、 潜在拡散モデルアーキテクチャ [LDM] によって実現され、追加の テキストから画像へのユースケースの基盤となります。たとえば、Web ページ上の既存の 画像の一部を新たに生成したコンテンツを使用して選択的に変更するインペインティングや、 その逆で、元の画像を元の 寸法を超えて拡張し、空いた領域を生成コンテンツで埋めるアウトペインティングがあります。

2.1.10. 機械翻訳

さまざまな国の複数の人々が、Web ベースのリアルタイム テキストチャットアプリケーションを介して会話しています。アプリケーションは、 [GNMT] や [OpenNMT] など、 各テキストを異なる言語へ翻訳する 機械学習モデルを使用して会話を翻訳します。

2.1.11. 感情分析

ユーザーが Web ベースのリアルタイムテキストチャットアプリケーションを介して友人と会話していますが、 友人の顔を見ることができないため、その友人がどのように感じているのか 気になっています。アプリケーションは、 [DeepMoji] など、入力テキストから感情を推論する機械学習 モデルを使用して友人の感情を分析し、推定された感情を表す 絵文字を表示します。

2.1.12. 動画要約

Web ベースのビデオ会議アプリケーションは受信したビデオストリームを記録し、 保存する録画映像データを削減する必要があります。アプリケーションは、 [Video-Summarization-with-LSTM] などの 動画要約用機械学習モデルを使用して、録画映像の短縮版を生成します。

2.1.13. ノイズ抑制

Web ベースのビデオ会議アプリケーションは受信した音声ストリームを記録しますが、 通常、背景ノイズは至るところに存在します。アプリケーションは、 [RNNoise] などのリカレントニューラルネットワークを使用したリアルタイム ノイズ抑制を活用して、赤ちゃんの泣き声や犬の鳴き声などの背景にある動的ノイズを 抑制し、ビデオ会議における 音声体験を改善します。

2.1.14. 音声認識

音声認識は、speech to text とも呼ばれ、話された言語を認識して テキストへ変換することを可能にします。音声認識の用途例には、 文字起こし、自動翻訳、マルチモーダルインタラクション、 リアルタイム字幕、仮想アシスタントなどがあります。音声認識は 音声コンテンツのアクセシビリティを向上させ、そのような コンテンツをプライバシーを保護する方法でテキスト形式として扱えるようにします。一般的な ユースケースの例には、リアルタイム字幕を使用して動画を視聴したりオンライン会議に参加したりすることが 含まれます。[Whisper] などのモデルは、精度 と堅牢性において人間に近づいており、このようなユースケースのアクセシビリティを向上させるうえで適しています。

2.1.15. テキスト生成

さまざまなテキスト生成ユースケースは、大規模言語モデル (LLM) によって実現されます。LLM は、 テキスト列における次の要素を予測する一般的な能力が 必要となるタスクを実行できます。この種類のモデルは、テキストを翻訳したり、テキスト入力に基づいて 質問に回答したり、大量のテキストを要約したり、テキスト入力に基づいて テキスト出力を生成したりできます。LLM は、RNN、CNN、LSTM アーキテクチャに基づく 従来のモデルと比べて優れた性能を実現し、このセクションで説明する その他の多くのユースケースの性能もさらに向上させます。 LLM の例には、[t5-small]、 [m2m100_418M]、[gpt2]、および [llama-2-7b] があります。

2.1.16. 偽動画の検出

ユーザーが Web 上で「ディープフェイク」によって生成されたリアルな偽動画にさらされています。 偽動画では、話者の顔を大統領の顔に差し替えて、 ユーザーを政治的に扇動したり、ユーザーの意見を操作したりすることがあります。 [FaceForensics++] などのディープフェイク検出 アプリケーションは動画を分析し、ユーザーを 偽動画や偽画像から保護します。ユーザーが Web 上で偽動画を視聴すると、 検出アプリケーションはリアルタイムでその偽動画について警告します。

2.2. フレームワークのユースケース

このセクションでは、ニューラルネットワーク推論のハードウェアアクセラレーション用に特化した低レベル API の フレームワークレベルのユースケースをまとめます。機械学習 フレームワークが Web Neural Network API (WebNN API) の主要な利用者となり、WebNN API を通じて公開される低レベルの詳細は 一般的な Web 開発者から抽象化されることが想定されています。ただし、 機械学習に特別な関心と能力を持つ Web 開発者は、 高レベルの ML フレームワークではなく、WebNN API と直接連携したいと考えることも想定されています。

2.2.1. カスタムレイヤー

Web アプリケーション開発者が WebNN API 上で DNN モデルを実行したいと考えています。しかし、 [LeakyReLU]、[ELU] などの一部の活性化関数が WebNN API に含まれていないことが分かりました。この問題に対処するため、 WebNN API 上に追加の活性化関数の カスタムレイヤーを構築します。 カスタムレイヤーの範囲には、活性化だけでなく畳み込み、正規化 なども含まれ得ることに注意してください。

2.2.2. ネットワーク連結

Web アプリケーションが DNN モデルを使用しており、その上位の畳み込み レイヤーと下位の全結合レイヤーのモデルデータは別々のファイルに保存されています。これは、 全結合レイヤーのモデルデータがサーバー側でのファイン チューニングにより定期的に更新されるためです。

そのため、アプリケーションは最初に両方の部分モデルファイルをダウンロードし、 それらを単一のモデルに連結します。モデルが更新されると、 アプリケーションはモデルのファインチューニング済み部分をダウンロードし、 全結合レイヤーだけをそれで置き換えます。

2.2.3. 性能適応

Web アプリケーション開発者は、モバイルデバイス上での DNN モデルの性能を 懸念しています。GPU アクセラレーションを備えていないモバイルデバイスでは 動作が遅すぎる可能性があることを確認しました。この問題に対処するため、Web アプリケーションは WebNN API を参照してアクセラレーションが利用可能かどうかを確認し、 アクセラレーションのないデバイスに対して警告を表示できるようにします。

数週間後、開発者は CPU 上でも実行可能な 小型 DNN モデルを開発しました。CPU 実行に対応するため、 CPU のみのデバイスの場合には小型モデルを読み込むよう アプリケーションを変更します。

2.2.4. 演算レベルの実行

JavaScript ML フレームワークは、ML モデルの読み込み、解釈、実行を担当します。モデルの 実行フェーズでは、フレームワークはモデルの演算を順に処理し、各演算を CPU、GPU、ML アクセラレーターなどのハードウェアデバイス上で実行します。デバイス間の不要なデータコピーを避けるため、 フレームワークは同じデバイスを選択して演算を実行します。2D 畳み込みや 行列乗算など、計算負荷の高い演算については、フレームワークは WebNN API を使用し、選択したデバイスで利用可能な ML 固有のアクセラレーションを使用して実行します。

2.2.5. リアルタイム動画処理との統合

WebRTC ベースのビデオ会議のユーザー体験は、リアルタイム動画処理を使用して向上させることができます。たとえば、 § 2.1.2 セマンティック セグメンテーションモデルを使用して実装された背景ぼかしは、ユーザーのライブカメラ映像の背景をぼかします。このユースケースの性能 要件を満たすため、WebNN API は、メディアパイプラインを構成する他の Web API のプリミティブと統合され、 WebNN API に基づくリアルタイム動画ストリームの変換を可能にします。

3. アクセシビリティ上の考慮事項

このセクションでは、ニューラルネットワーク推論の ハードウェアアクセラレーションによって実現される § 2.1 アプリケーションのユースケース のアクセシビリティを向上させる方法について、Web 制作者に指針を提供します。この指針は、この 仕様で概説する特定のユースケースを超えて一般化できるものであり、Web 制作者には、さらなるアクセシビリティ指針について [wcag] を、 また倫理原則の文脈におけるデジタルアクセシビリティについて § 6 倫理上の考慮事項 を参照することを推奨します。

§ 2.1.8 画像キャプショニングは、キャプションが スクリーンリーダーおよびその他の支援技術 (AT) のユーザーに提示されることを確保することで改善できます。Web 制作者には、 生成された画像キャプションを、それぞれ対応する画像に標準の alt 属性、またはページの初回読み込み時に説明が更新されるのか、 その後ユーザー操作の結果として更新されるのかに応じたその他の手段によって、意味的に関連付けることを推奨します。

§ 2.1.11 感情分析はユーザーに誤ったラベルを付け、それによって誤分類し、 差別的な体験につながる可能性があります。Web 制作者には信頼度スコアを公開し、ユーザーに この機能をオフにする選択肢を提供することを推奨します。

§ 2.1.13 ノイズ抑制で強力なフィルターを使用すると、 構音障害のあるユーザーの発話まで除去され、字幕や認識が失敗する可能性があります。Web 制作者には、 バイパスまたは感度調整機能を公開し、ライブ字幕が有効なときにはノイズ抑制を固定的に適用しないことを推奨します。

§ 2.2.5 リアルタイム動画処理との統合における 背景ぼかしを利用したセグメンテーションは注意をそらす要素の除去に役立ちますが、 読唇やライブ字幕を損なうほど大きな遅延を追加する可能性があります。Web 制作者には、ユーザー向けにキーボード およびスクリーンリーダーで操作可能な「背景ぼかしオン/オフ」コントロールを、他のアクセシビリティ/メディア 設定の近くに表示する機能を提供することを推奨します。

§ 7.2 デバイス選択により、Web 制作者は 実行速度と消費電力に関する優先設定を示すことができます。実装者には、 低性能またはバッテリー消費に敏感なデバイスを使用している人でも、 特に携帯型 AAC や視線入力 環境で、字幕やその他の重要なアクセシビリティ機能の応答性を維持できるよう、ブラウザー UI で Web 制作者のヒントをユーザーが上書きできるようにすることを推奨します。

4. セキュリティ上の考慮事項

この仕様は、ニューラルネットワーク推論のハードウェアアクセラレーション用の低レベル API を定義します。この API は、 ユーザーのコンピューターへの低レベルアクセスを許可するため、強力な機能 [POWERFUL-FEATURES] とみなされます。強力な機能に求められる 認証および機密性の要件を満たし、中間者 攻撃を防止するため、この仕様で定義されるすべてのインターフェイスはセキュアコンテキストでのみ利用できます。

この API は、§ 7.5 Permissions Policy との統合を使用するすべてのクロスオリジンフレームでデフォルトで無効です。これにより、 埋め込み元ページが許可を与えるポリシーを明示的に設定しない限り、 サードパーティコンテンツがこの API を使用することを防ぎます。

この API では、WebGPU 仕様で定義された GPUDevice から MLContext を作成できます。 このコンテキストのセキュリティ特性の詳細については、WebGPU のセキュリティ上の考慮事項を参照してください。

この API は GPU、CPU、および専用 ML アクセラレーターハードウェアを横断する抽象化を提供します。GPU を使用する場合は、WebGPU と同様の サービス拒否に関する考慮事項が 適用されます。CPU または専用 ML アクセラレーターを使用する場合、潜在的なリソース競合の種類は 異なり、その軽減策は実装および構成に依存します。実装は、 サイトが不当に大量のシステム リソースを使用することを防ぐためにプラットフォームで利用可能なあらゆる仕組みを使用すべきです。これらの計算ユニットは共有リソースであり、どのような計算 API の使用も、 完全に負荷のかかったシステムでは全体的な性能に影響します。

グラフが完全に構築されコンパイルされると、グラフ内の各演算への入力形状が 推論され確定します。境界チェックは、実際のデータに対してグラフを実行する compute メソッドが呼び出されたときに行われます。この段階より前には、実際のデータはコンパイル済みグラフに結び付けられません。その時点までに 推論済みのデータ形状に対して適切な境界チェックが行われることを保証する責任は、 実装にあります。

実装者への指針として、 範囲外アクセスの影響を受けやすい演算を文書化する。

実装は、定数とみなされるデータの変更に基づく制御フロー攻撃を防御しなければなりません。 たとえば、基盤プラットフォームの最適化では、計算全体を通して重みが変更されないことを前提とする場合があります。 API が、計算中に重みを保持するバッファの内容を変更することを許可した場合、 その最適化の前提は無効になり、基盤 プラットフォームで未定義の動作が発生します。この API は常にバッファをコピーまたは転送することで、スクリプトからのこの種の攻撃を軽減しますが、 実装は、定数と仮定されるデータのプロセス分離などの追加の防御も検討すべきです。

将来への備えとして、API 設計では、一般的にエミュレート可能な特定の演算を、 互換性を損なうことなく、セキュリティ、性能、またはその他の理由で非推奨にできます。これは、 この仕様で定義されるより小さなプリミティブ演算を用いて定義される高レベル関数によって可能になります。 これにより、高レベル関数のネイティブ実装を polyfill 実装に置き換えることができます。

CPU がレンダラーを実行するプロセス間で共有されている 現在の状態を考慮し、サイドチャネル攻撃の 実現可能性を調査する。

攻撃者が欠陥を含む可能性のある特定の実装を標的にできないようにするため、§ 7.2 デバイス選択メカニズムはヒントにすぎず、 具体的なデバイス選択は実装に委ねられます。たとえばユーザーエージェントは、 既知の脆弱性を持つデバイスではモデルを決して実行しないことを選択できます。さらなる軽減策として、デバイス列挙メカニズムは 定義されていません。

ヒントにより懸念は部分的に 軽減される。追加の軽減策を調査する。

API 設計は、コンパイル済み計算グラフの攻撃対象領域を最小限にします。さまざまな演算を保持する MLGraphBuilder インターフェイスはデータ定義 API であり、それ自体は何も実行せず、 データを構築するだけです。したがって、攻撃の可能性は、MLContext.dispatch() メソッドを呼び出して実行する前にデータをグラフへ結び付けるときに限定されます。これにより実装者は、MLContext.dispatch() メソッドの堅牢化に集中できます。たとえば、データ境界を遵守し、境界が 守られていない場合に適切に失敗することを保証できます。

高解像度時間を測定するために特別に設計された Web API は、 解像度の低減、ジッターの追加、不正使用の検出、API 呼び出しのスロットリングなどの手法を使用してタイミング攻撃を軽減します [hr-time-3]。WebNN 実装の 実際の展開では、タイミング攻撃を 非現実的なものにするのに十分なジッターが生じる可能性があります(たとえば IPC を使用するため)が、実装者には、 タイミング攻撃に対して実装を検討し、テストすることを推奨します。

注: Unicode シーケンスに関連するセキュリティリスクについては、 label USVString の定義の文脈で説明されています。

4.1. 新しい演算のガイドライン

このセクションは非規範的です。

この仕様で定義される演算を安全に実装できる形で設計するため、 このセクションには、潜在的な 実装上の問題を減らすために演算をどのように定義することが期待されるかについてのガイドラインを含めます。これらのガイドラインは、業界のベスト プラクティスに合わせて時間とともに進化することが期待されます。

一般に、新しい機能を追加する際には、 Technical Architecture Group および Privacy Interest Group による [security-privacy-questionnaire] に文書化されているセキュリティとプライバシーへの影響を常に考慮してください。

5. プライバシー上の考慮事項

この API は、機密性の高いユーザー データをブラウザーのサンドボックス内に保持することで、クラウドベースの推論手段よりもプライバシーを向上させます。画像、音声、ビデオストリーム、その他の個人 情報などの入力データはユーザーのデバイスから一切外部へ送信されず、リモート サーバーへのデータ送信やサードパーティによるデータ処理に関連するリスクを排除します。

ただし、ハードウェアアクセラレーション機能と密接に連携する強力なローカル計算 API として、 WebNN API は性能最適化とプライバシー保護のバランスを取る必要があります。この API には、 効果的な機械 学習推論機能を可能にしながらフィンガープリンティングを軽減する、複数のプライバシー保護措置が含まれています。

5.1. フィンガープリンティング

設計上、この API は、特定された § 2 ユースケースに、最良の性能と結果の信頼性で対応するために必要な最小限の情報のみを公開することを目的としています。まず、この API は 標準化によってフィンガープリンティングを軽減します。すなわち、多様な プラットフォーム API 間で一貫した動作を定義し、適合実装間で基盤ハードウェアの差異に関する 情報漏えいを最小限にします。これは以下によって実現されます。

全体的な設計により、実装は異なるプラットフォーム間で一貫したインターフェイスを維持しながら、 必要な機能を提供できます。プラットフォーム固有の詳細を抽象化することで、API は、 基盤となるアクセラレーションが CPU、GPU、または専用 ML ハードウェアのいずれによって提供されるかにかかわらず、プライバシーを保護する予測可能な動作を提供できます。

注: MLContextOptions は現在活発に開発中であり、その設計は、さらなる実装 経験や、より広範な Web コミュニティからの新しいユースケースを踏まえて変更されることが見込まれています。

MLGraph.devices API 拡張は、グラフが完全に構築され コンパイルされた後、実行に実際に選択されたデバイスを公開するために提案されています。この API 拡張のプライバシーへの影響は 調査中です。[Issue #836]

5.2. 実行時間分析

演算のタイミング特性は、基盤ハードウェアの 性能に関する一定の間接情報を提供する可能性があり、これはあらゆる計算 API に内在する特性です。特定の状況では、実行時間分析によって、 ある基盤プラットフォームのニューラルネットワークハードウェアアクセラレーション 機能の性能を、別の基盤プラットフォームとの比較で間接的に明らかにできる場合があります。タイミング攻撃に関する詳細については、§ 4 セキュリティ上の 考慮事項も参照してください。

注: グループは、提案されている 実行時間分析のフィンガープリンティングベクトルおよび軽減策について、さらなる意見を歓迎しています。

5.3. WebGPU との比較

WebGPU とは異なり、この API は本質的にカスタムシェーダーの作成をサポートしません。そのため、 シェーダーキャッシュやその他の永続データに依存するタイミング攻撃の影響を受けにくくなっています。この API は、既存の シェーダーおよびブラウザーまたは基盤 OS の低レベルプリミティブ上に構築されます。 GPUDevice と連携する Web 開発者は、WebGPU コンパイルキャッシュに関する考慮事項を認識していることが期待されます。

WebGPU API は、マシン固有のアーティファクトを プライバシー上の考慮事項として特定しています。同様に、WebNN API の計算ユニットのスケジューリングも、特定の状況では フィンガープリントを生じさせる可能性があります。ただし、WebGPU と同様に、このようなフィンガープリントは各ベンダーのほとんどまたはすべての デバイスで同一であるため、懸念は軽減されます。さらに、ソフトウェア実装を使用して このようなアーティファクトをさらに除去できます。

一般に、この API の実装者は、適用可能な場合には WebGPU のプライバシー上の考慮事項を実装に適用することが期待されます。

6. 倫理上の考慮事項

ワーキンググループは、Web 上で機械学習を使用することに関連する倫理上の問題の文書化を開始しており、 規範的な仕様で考慮すべき軽減策を特定する助けとしています。ワーキンググループは、 Web 機械学習の倫理原則に関する文書 [webmachinelearning-ethics] を公開および維持し、 専用の GitHub リポジトリを通じて、より広範なコミュニティからの貢献を受け付けています。

7. プログラミングモデル

7.1. 概要

ニューラルネットワークの中心には、数学的演算の 計算グラフがあります。 これらの演算は、コンピュータービジョン、自然言語処理、ロボティクスにおける 現代の機械学習技術の構成要素です。 WebNN API は、ニューラルネットワークの計算 グラフを構築、コンパイル、実行するための仕様です。

MLGraph インターフェイスは、不変のコンパイル済み計算グラフ(つまりモデル)を表します。

MLGraphBuilder インターフェイスは、計算グラフ(その グラフ) を構築するためのビルダー(ファクトリー)として機能し、その後コンパイルされて MLGraph が作成されます。

WebNN では、計算グラフは、データに作用しグラフのノードとなる 演算子で構成されます。MLOperand は、 計算グラフ内を流れるデータの表現であり、グラフのエッジです。MLOperand には、 計算グラフの、推論用の 入力値、推論に使用される 定数(学習済み重みを含む)、 推論中に計算される中間値(多くの場合、活性化と呼ばれます)、および推論の出力 値が含まれます。演算子の 入力は 1 つ以上の MLOperand です。 演算子の 出力は 1 つ以上の MLOperand です。演算子には、その動作を制御する演算子固有の パラメーターがあり、0 個以上の 活性化関数を含む場合があります。

MLGraphBuilder インターフェイスの重要な部分は、gemm() や relu() などのメソッドであり、計算の実行時に入力データに対して実行する実際の演算を表す 演算子を作成し、新しい MLOperand を返してその演算子を保持します。MLOperand を作成するメソッドは、あらゆる 入力と 活性化を 演算子へ接続します。各メソッド呼び出しは、他の MLOperand の値を変更することなく、個別の新しい値を返します。

演算子は ラベルを持ちます。これは、例外メッセージなどの診断情報に含めることができる文字列です。演算子が作成されると、その ラベルは 実装定義の方法で初期化され、渡された label を含む場合があります。

dispatch() 中にエラーを報告するためのメカニズムの追加を検討する。 [Issue #778]

推論時には、すべての MLOperand が テンソル(実際のデータ)にバインドされます。テンソルは本質的には多次元配列です。 テンソルの表現は実装依存ですが、通常は何らかのバッファ (メモリ)に保存された配列データと、その配列データを記述するメタデータ(形状など)を含みます。

計算グラフ内の演算は関数的意味論を持ちます。これにより実装は、 複数のテンソル間で配列データを共有できる可能性があります。たとえば、 reshape や slice などの演算の実装は、入力テンソルと同じバッファを共有する 入力テンソルのビューを返す場合があります。(reshape の場合、 データ全体が共有されますが、slice の場合は入力データの一部が共有されます。) 実装は、上記のようなビューを中間値に使用する場合があります。

実行前に、指定された 1 つ以上の出力を計算するために使用される計算グラフを 変換、コンパイル、最適化する必要があります。コンパイル手順の主な目的は、 演算やループの融合など、2 つ以上の演算にまたがる最適化を可能にすることです。ユーザーエージェントは、 グラフ変換中にもこれらの最適化を実行する場合があります。

MLGraphBuilder.build() メソッドは、呼び出し元スレッドをブロックせずにバックグラウンドでグラフをコンパイルし、MLGraph に解決される Promise を返します。各 MLGraphBuilder が構築できる MLGraph は最大 1 つです。

MLGraph の基盤実装は、MLGraphBuilder の 演算子および MLOperand に対応する、プラットフォーム固有の演算子とオペランドの表現で 構成されますが、それらはスクリプトからは見えず、スクリプトによって構築された グラフの合成または分解である場合があります。

MLGraph が構築されると、MLContext.dispatch() メソッドは、CPU 実行の場合には別個のワーカー スレッド上の並列タイムラインで、GPU の場合には GPU コマンドキュー上の GPU タイムラインで、グラフの実行を非同期に行います。このメソッドは、 実際の実行が別のタイムラインへオフロードされる間、呼び出し元スレッドをブロックせず 即座に返ります。呼び出し元は MLNamedTensors を使用して入力値を提供し、入力 MLOperand を それぞれの値へバインドします。呼び出し元は出力 MLOperand 用の MLNamedTensors も提供します。これらには、成功した場合にグラフ実行の結果が格納され、その結果は MLContext.readTensor(tensor) メソッドを使用してスクリプトから読み戻すことができます。この種類の実行は CPU、GPU、NPU デバイスをサポートします。

7.2. デバイス選択

MLContext インターフェイスは、ニューラルネットワーク実行のグローバル状態を表します。重要なコンテキスト状態の 1 つは、 リソースを管理し、ニューラルネットワークグラフのコンパイルおよび最終的な 実行を容易にする基盤実行デバイスです。MLContextOptions を使用するデフォルトの作成方法に加えて、MLContext は、アプリケーションですでに使用中の特定の GPUDevice から作成することもできます。

GPU コンテキストが、システムメモリ内に ArrayBufferView として存在する定数または入力を含むグラフを実行する場合、 入力内容はシステムメモリから GPU メモリへ自動的にアップロードされ、グラフ実行の終了時には ArrayBufferView の出力バッファのシステムメモリへダウンロードされます。このデータのアップロードおよびダウンロードサイクルは、 GPU の場合のように、実行デバイスがデータをシステムメモリからコピーし、再び システムメモリへ戻す必要がある場合にのみ発生します。デバイスが CPU デバイスの場合には発生しません。さらに、 グラフ実行の結果は既知のレイアウト形式になります。実行中、グラフ内の中間結果について ネイティブメモリアクセスパターン向けに最適化される場合がありますが、グラフの最後の演算の出力は、 呼び出し元から見た期待される動作を維持するため、グラフの最後で内容を 既知のレイアウト形式へ戻す必要があります。

MLContext が MLContextOptions を使用して作成される場合、ユーザーエージェントはこれらのオプションを考慮して、 基盤となる実行デバイスを選択して作成します。

基盤プラットフォームに応じて、ユーザーエージェントは CPU、NPU、GPU デバイスの異なる 組み合わせを選択する場合があります。

この設計の経緯と根拠については、デバイス 選択の解説文書を参照してください。

7.3. 演算子

このセクションは非規範的です。

WebNN API は、主要な § 2.1 アプリケーションのユースケースに対応する、 よく知られた CNN、RNN、Transformer、および生成 モデルで必要となる一連の演算子を定義します。各演算子の詳細は、この仕様の規範的なセクションで、演算子 名のアルファベット順に定義されています。これらの演算子は、API サーフェスの機能的な概要を示すため、 以下の非規範的な表でその機能に基づいてカテゴリに分類されています。

注: 一部の演算子は複数のカテゴリに属します。たとえば、 clamp() は数学関数であると同時に、活性化としても使用されます。

カテゴリ別の演算子
カテゴリ 演算子​
テンソル作成 input(), constant()
テンソル操作 concat(), expand(), gather(), gatherElements(), scatterElements(), gatherND(), scatterND(), where(), pad(), reshape(), slice(), split(), transpose(), resample2d(), reverse(), tile(), triangular()
テンソル量子化 quantizeLinear(), dequantizeLinear()
テンソルキャスト cast()
数学 add(), sub(), mul(), div(), max(), min(), clamp(), pow(), abs(), ceil(), cos(), erf(), exp(), floor(), identity(), log(), neg(), reciprocal(), roundEven(), sin(), sqrt(), tan(), tanh(), sign(), clamp()
論理 equal(), notEqual(), greater(), greaterOrEqual(), lesser(), lesserOrEqual(), logicalNot(), logicalAnd(), logicalOr(), logicalXor(), isNaN(), isInfinite()
行列乗算 matmul(), gemm()
畳み込み conv2d(), convTranspose2d()
プーリング averagePool2d(), l2Pool2d(), maxPool2d()
活性化 clamp(), elu(), gelu(), hardSigmoid(), hardSwish(), leakyRelu(), linear(), prelu(), relu(), sigmoid(), softmax(), softplus(), softsign(), tanh()
正規化 batchNormalization(), instanceNormalization(), layerNormalization()
リダクション argMin(), argMax(), reduceL1(), reduceL2(), reduceLogSum(), reduceLogSumExp(), reduceMax(), reduceMean(), reduceMin(), reduceProduct(), reduceSum(), reduceSumSquare(), cumulativeSum()
リカレントニューラルネットワーク gruCell(), gru(), lstmCell(), lstm()

7.4. タスクソース

ML タスクソースは、 MLGraph の非同期コンパイルおよび実行、ならびに MLContext の作成に関連するすべての タスクに使用される タスクソースです。

グローバルオブジェクト global と一連の手順 steps が与えられたとき、ML タスクをキューに入れるには、global および steps を指定して、ML タスクソース上で グローバルタスクをキューに入れます。

7.5. Permissions Policy との統合

この仕様は、 "webnn" という文字列によって識別される ポリシー制御機能を定義します。 その デフォルト許可リストは 'self' です。

8. API

8.1. navigator.ml インターフェイス

ML オブジェクトは、 Window および WorkerGlobalScope コンテキストで、それぞれ Navigator および WorkerNavigator インターフェイスを介して利用でき、navigator.ml を通じて公開されます。

interface mixin NavigatorML {
  [SecureContext, SameObject] readonly attribute ML ml;
};
Navigator includes NavigatorML;
WorkerNavigator includes NavigatorML;

8.2. ML インターフェイス

enum MLPowerPreference {
  "default",
  "high-performance",
  "low-power"
};

dictionary MLContextOptions {
  MLPowerPreference powerPreference = "default";
  boolean accelerated = true;
};

[SecureContext, Exposed=(Window, Worker)]
interface ML {
  Promise<MLContext> createContext(optional MLContextOptions options = {});
  Promise<MLContext> createContext(GPUDevice gpuDevice);
};

8.2.1. MLContextOptions

注: MLContextOptions は現在活発に開発中であり、さらなる実装 経験や、より広範な Web コミュニティからの新しいユースケースを踏まえて設計が変更されることが見込まれています。ワーキンググループは、 フォールバックデバイス、優先順位を持つ複数のデバイス、または特定のデバイスの 除外を定義できるようにする追加の API 制御を検討しています。議論中のその他の考慮事項には、エラー処理、最終的な フォールバック、および量子化演算子が含まれます。これらの設計上の考慮事項に関する Web 開発者、ライブラリ作者、OS およびハードウェアベンダー、その他の関係者からのフィードバックを GitHub で歓迎します。フィンガープリンティングに関する 追加の議論については § 5 プライバシー上の考慮事項を参照してください。

powerPreference オプションは MLPowerPreference であり、消費電力に関するアプリケーションの 優先設定を示します。これは次のいずれかです。

"default"
ユーザーエージェントに最も適した動作を選択させます。
"high-performance"
消費電力よりも実行速度を優先します。
"low-power"
実行速度などの他の考慮事項よりも消費電力を優先します。

accelerated オプションは、大規模並列アクセラレーションに関するアプリケーションの 優先設定を示します。このオプションの優先度は powerPreference より低くなります。 true(デフォルト)に設定すると、基盤プラットフォームは、powerPreference にも応じて、GPU や NPU など、利用可能な 大規模並列アクセラレーターの使用を試みます。 false に設定すると、アプリケーションは CPU 推論を優先することを示します。たとえば powerPreference が "high-performance" であり、accelerated が false である場合のように入力が矛盾している場合、実装は基盤 プラットフォームで利用可能な最良の一致を選択します(たとえば高性能 CPU モードを使用するか、accelerated は powerPreference より優先度が低いため無視します)。

8.2.2. createContext()

引数: 戻り値:MLContext。
レルム realm および options(GPUDevice または MLContextOptions) が与えられたときに コンテキストを 作成するには、次の手順を実行します。
  1. context を realm 内の新しい MLContext とします。

  2. options が GPUDevice オブジェクトである場合、次を行います。

    1. context.[[contextType]] を "webgpu" に設定します。

    2. context.[[powerPreference]] を "default" に設定します。

    3. context.[[accelerated]] を true に設定します。

  3. それ以外の場合:

    1. context.[[contextType]] を "default" に設定します。

    2. context.[[lost]] を realm 内の 新しい promise に設定します。

    3. options["powerPreference"] が存在する場合、context.[[powerPreference]] を options["powerPreference"] に設定します。

    4. それ以外の場合、context.[[powerPreference]] を "default" に設定します。

    5. options["accelerated"] が存在する場合、context.[[accelerated]] を options["accelerated"] に設定します。

    6. それ以外の場合、context.[[accelerated]] を true に設定します。

  4. ユーザーエージェントが context.[[contextType]] をサポートできない場合、失敗を返します。

  5. context を返します。

createContext(options) の手順は次のとおりです。
  1. global を this の関連グローバルオブジェクトとします。

  2. realm を this の関連レルムとします。

  3. global の関連付けられた Document が webnn 機能の使用を許可されていない場合、realm 内で "SecurityError" DOMException によって拒否された新しい promise を返します。

  4. promise を realm 内の新しい promise とします。

  5. 次の手順を並列に実行します。

    1. context を、realm と options が与えられたときにコンテキストを作成した結果とします。それが失敗を返した場合、 global で ML タスクをキューに入れ、 promise を "NotSupportedError" DOMException で拒否し、この手順を中止します。

    2. global で ML タスクをキューに入れ、promise を context で解決します。

  6. promise を返します。

createContext(gpuDevice) メソッドの 手順は次のとおりです。
  1. global を this の関連グローバルオブジェクトとします。

  2. realm を this の関連レルムとします。

  3. global の関連付けられた Document が webnn 機能の使用を許可されていない場合、realm 内で "SecurityError" DOMException によって拒否された新しい promise を返します。

  4. promise を realm 内の新しい promise とします。

  5. 次の手順を並列に実行します。

    1. context を、realm と gpuDevice が与えられたときにコンテキストを作成した結果とします。それが失敗を返した場合、 global で ML タスクをキューに入れ、 promise を "NotSupportedError" DOMException で拒否し、この手順を中止します。

    2. global で ML タスクをキューに入れ、promise を context で解決します。

  6. promise を返します。

8.3. MLContext インターフェイス

MLContext インターフェイスは、ニューラルネットワークの計算ワークロードおよび実行プロセスのグローバル状態を表します。各 MLContext オブジェクトには、 関連付けられた コンテキスト型および MLPowerPreference があります。
typedef record<USVString, MLTensor> MLNamedTensors;

dictionary MLContextLostInfo {
  DOMString message;
};

[SecureContext, Exposed=(Window, Worker)]
interface MLContext {
  undefined dispatch(MLGraph graph, MLNamedTensors inputs, MLNamedTensors outputs);

  Promise<MLTensor> createTensor(MLTensorDescriptor descriptor);
  Promise<MLTensor> createExportableTensor(
    MLTensorDescriptor descriptor, GPUDevice gpuDevice);
  Promise<MLTensor> createConstantTensor(
    MLOperandDescriptor descriptor, AllowSharedBufferSource inputData);

  Promise<ArrayBuffer> readTensor(MLTensor tensor);
  Promise<undefined> readTensor(MLTensor tensor, AllowSharedBufferSource outputData);

  undefined writeTensor(MLTensor tensor, AllowSharedBufferSource inputData);

  GPUBuffer exportToGPU(MLTensor tensor);

  MLOpSupportLimits opSupportLimits();

  undefined destroy();

  readonly attribute boolean accelerated;
  readonly attribute Promise<MLContextLostInfo> lost;
};
MLContext には次の内部スロットがあります。
[[contextType]]、型は コンテキスト型。

MLContext の コンテキスト型。

[[powerPreference]]、 型は MLPowerPreference。

MLContext の MLPowerPreference。

[[accelerated]]、型は boolean。

MLContext の 処理タイプ(CPU または大規模並列処理)。

[[lost]]、型は Promise<MLContextLostInfo>。

MLContext の 基盤となる実行デバイスが利用できなくなったときに解決される Promise。

[[timeline]]

MLContext の計算ユニット上での演算の実行に関連付けられたタイムライン。 これらの演算には、計算グラフ上での推論、および MLTensor の [[data]] の変更が含まれます。

このタイムラインを より厳密に定義する。[Issue #529]

コンテキスト型は、 リソースを管理し、ニューラルネットワークグラフのコンパイルと実行を容易にする 実行コンテキストの型です。

"default"
ユーザーの優先オプションに従って作成されたコンテキスト。
"webgpu"
WebGPU デバイスから作成されたコンテキスト。
accelerated getter の手順は、this.[[accelerated]] を返すことです。
AllowSharedBufferSource bufferSource および MLOperandDescriptor descriptor が与えられたときに descriptor を用いて buffer を検証するには、次の手順を実行します。
  1. bufferSource のバイト長が descriptor のバイト長と等しくない場合、false を返します。

  2. bufferSource の型に応じて切り替えます。

    ArrayBuffer

    true を返します。

    SharedArrayBuffer

    true を返します。

    ArrayBufferView
    1. bufferSource が Uint8Array オブジェクトである場合、true を返します。

    2. bufferSource が、この 表に従って descriptor の dataType と一致する場合、true を返します。

    3. false を返します。

注: descriptor の dataType に関係なく Uint8Array を使用することは、たとえば WebAssembly.Memory インスタンスの一部など、ArrayBuffer の一部分を表現する汎用的な方法としてサポートされています。開発者には、WebNN コードを記述する際、 可読性と保守性のために、より具体的なビュー型を使用することを推奨します。

record<USVString, MLOperandDescriptor> namedDescriptors とともに MLNamedTensors namedTensors が与えられたときに descriptor を用いて tensor を検証するには:
  1. namedTensors のサイズが namedDescriptors のサイズと等しくない場合、 false を返します。

  2. namedTensors の各 name → tensor について反復します。

    1. tensor.[[isConstant]] が true の場合、false を返します。

    2. namedDescriptors[name] が存在しない場合、 false を返します。

    3. tensor.[[descriptor]] が namedDescriptors[name] と等しくない場合、false を返します。

  3. true を返します。

8.3.1. dispatch()

コンパイル済み MLGraph の計算ワークロードを、 MLContext の [[timeline]] 上にスケジュールします。

引数:

戻り値: undefined。

注: dispatch() 自体は、 グラフの実行が完了したことを示すシグナルを提供しません。代わりに、呼び出し元は出力テンソルの読み戻し結果を await できます。 以下の § 8.3.1.1 例を参照してください。

dispatch(graph, inputs, outputs) メソッドの手順は次のとおりです。
  1. graph.[[context]] が this でない場合、TypeError をスローします。

  2. graph.[[isDestroyed]] が true の場合、"InvalidStateError" DOMException をスローします。

  3. allTensors を、inputs の値を outputs の値で拡張して構成される、MLTensor のリストとします。

  4. allTensors に重複する項目が含まれている場合、TypeError をスローします。

  5. allTensors の各 tensor について反復します。

    1. tensor.[[context]] が this でない場合、TypeError をスローします。

    2. tensor.[[isDestroyed]] が true の場合、TypeError をスローします。

    3. tensor がエクスポート済みの場合、TypeError をスローします。

  6. inputs と graph.[[inputDescriptors]] が与えられたときのdescriptor を用いた tensor の検証が false を返した場合、TypeError をスローします。

  7. outputs と graph.[[outputDescriptors]] が与えられたときのdescriptor を用いた tensor の検証が false を返した場合、TypeError をスローします。

  8. 次の手順を graph.[[context]].[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、this が失われた場合は中止します。

      1. inputs と outputs を指定して、graph.[[implementation]] に計算要求を発行します。

        グラフ実行中のエラーを報告するためのメカニズムを追加する。[Issue #778]

tensor を使用して定数オペランドを作成する場合、build が完了した後にその tensor を破棄することは許可されています。 実装は、そのような破棄によってコンパイル済みグラフの有効性が損なわれず、影響も受けないことを保証することが期待されます。

8.3.1.1. 例
次のコードは、MLTensor を使用して MLGraph を実行する例を示しています。
const descriptor = {
  dataType: 'float32',
  shape: [2, 2]
};
const context = await navigator.ml.createContext();
const builder = new MLGraphBuilder(context);

// 1. 計算グラフ 'C = 0.2 * A + B' を作成する。
const constant = builder.constant(descriptor, new Float32Array(4).fill(0.2));
const A = builder.input('A', descriptor);
const B = builder.input('B', descriptor);
const C = builder.add(builder.mul(A, constant), B);

// 2. グラフをコンパイルする。
const graph = await builder.build({'C': C});

// 3. 再利用可能な入力および出力 tensor を作成する。
const [inputTensorA, inputTensorB, outputTensorC] = await Promise.all([
  context.createTensor({dataType: A.dataType, shape: A.shape, writable: true}),
  context.createTensor({dataType: B.dataType, shape: B.shape, writable: true}),
  context.createTensor({dataType: C.dataType, shape: C.shape, readable: true})
]);

// 4. 入力を初期化する。
context.writeTensor(inputTensorA, new Float32Array(4).fill(1.0));
context.writeTensor(inputTensorB, new Float32Array(4).fill(0.8));

// 5. グラフを実行する。
const inputs = {
  'A': inputTensorA,
  'B': inputTensorB
};
const outputs = {
  'C': outputTensorC
};
context.dispatch(graph, inputs, outputs);

// 6. 計算結果を読み戻す。
const result = await context.readTensor(outputTensorC);
console.log('出力値:', new Float32Array(result));  // [1, 1, 1, 1]

8.3.2. createTensor()

この MLContext に関連付けられた MLTensor を作成します。

引数:

戻り値: Promise<MLTensor>。

createTensor(descriptor) メソッドの手順は 次のとおりです。
  1. global を this の関連グローバルオブジェクトとします。

  2. realm を this の関連レルムとします。

  3. this が失われている場合、realm 内で "InvalidStateError" DOMException によって拒否された新しい promise を返します。

  4. tensor を、this と descriptor が与えられたときに MLTensor を作成した結果とします。

  5. promise を realm 内の新しい promise とします。

  6. 次の手順を this.[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、this が失われた場合は中止します。

      1. descriptor を指定して tensor.[[data]] を作成し、すべてのバイトを 0 に初期化します。

      2. それが失敗した場合、global で ML タスクをキューに入れ、 promise を "UnknownError" DOMException で拒否し、この手順を中止します。

      3. それ以外の場合、global で ML タスクをキューに入れ、 promise を tensor で解決します。

    2. 中止された場合、global で ML タスクをキューに入れ、 promise を "InvalidStateError" DOMException で拒否します。

  7. promise を返します。

8.3.3. createExportableTensor()

この MLContext に関連付けられ、exportToGPU() を使用して指定された GPUDevice にエクスポートできる MLTensor を作成します。

引数:

戻り値: Promise<MLTensor>。

createExportableTensor(descriptor, gpuDevice) メソッドの手順は次のとおりです。
  1. global を this の関連グローバルオブジェクトとします。

  2. realm を this の関連レルムとします。

  3. this が失われている場合、realm 内で "InvalidStateError" DOMException によって拒否された新しい promise を返します。

  4. gpuDevice が失われている場合、realm 内で "InvalidStateError" DOMException によって拒否された新しい promise を返します。

  5. this が MLTensor を gpuDevice にエクスポートすることをサポートできない場合、realm 内で "NotSupportedError" DOMException によって拒否された新しい promise を返します。

    注: MLContext が特定の GPUDevice へのエクスポートをサポートするかどうかは実装定義であり、MLContext の コンテキスト型および 基盤プラットフォームに依存する場合があります。

  6. tensor を、this、 descriptor、および gpuDevice が与えられたときにエクスポート可能な MLTensor を作成した結果とします。

  7. promise を realm 内の新しい promise とします。

  8. 次の手順を this.[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、this が失われた場合は中止します。

      1. descriptor を指定して tensor.[[data]] を作成し、すべてのバイトを 0 に初期化します。

      2. それが失敗した場合、global で ML タスクをキューに入れ、 promise を "UnknownError" DOMException で拒否し、この手順を中止します。

      3. それ以外の場合、global で ML タスクをキューに入れ、 promise を tensor で解決します。

    2. 中止された場合、global で ML タスクをキューに入れ、 promise を "InvalidStateError" DOMException で拒否します。

  9. promise を返します。

8.3.4. createConstantTensor()

この MLContext に関連付けられた定数 MLTensor を作成します。

引数:

戻り値: Promise<MLTensor>。

createConstantTensor(descriptor, inputData) メソッドの手順は次のとおりです。
  1. global を this の関連グローバルオブジェクトとします。

  2. realm を this の関連レルムとします。

  3. this が失われている場合、realm 内で "InvalidStateError" DOMException によって拒否された新しい promise を返します。

  4. descriptor が与えられたときの次元のチェックが false を返した場合、realm 内で TypeError によって拒否された新しい promise を返します。

  5. inputData と descriptor が与えられたときのdescriptor を用いた buffer の検証が false を返した場合、realm 内で TypeError によって拒否された新しい promise を返します。

  6. bytes を、inputData が与えられたときにbuffer source が保持するバイトのコピーを取得した結果とします。

  7. 表明: bytes の長さは descriptor のバイト長と等しい。

  8. tensor を、this と descriptor が与えられたときに定数 MLTensor を作成した結果とします。

  9. promise を realm 内の新しい promise とします。

  10. 次の手順を this.[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、this が失われた場合は中止します。

      1. descriptor を指定して tensor.[[data]] を作成します。

      2. それが失敗した場合、global で ML タスクをキューに入れ、 promise を "UnknownError" DOMException で拒否し、この手順を中止します。

      3. bytes を tensor.[[data]] にコピーします。

      4. それが失敗した場合、global で ML タスクをキューに入れ、 promise を "UnknownError" DOMException で拒否し、この手順を中止します。

      5. それ以外の場合、global で ML タスクをキューに入れ、 promise を tensor で解決します。

    2. 中止された場合、global で ML タスクをキューに入れ、 promise を "InvalidStateError" DOMException で拒否します。

  11. promise を返します。

8.3.5. readTensor(tensor)

MLTensor の [[data]] を MLContext.[[timeline]] からスクリプトへ読み戻します。

引数:

戻り値: Promise<ArrayBuffer>。 読み取り結果を含むバッファです。

readTensor(tensor) メソッドの手順は次のとおりです。
  1. global を this の関連グローバルオブジェクトとします。

  2. realm を this の関連レルムとします。

  3. tensor.[[context]] が this でない場合、realm 内で TypeError によって拒否された新しい promise を返します。

  4. tensor.[[isDestroyed]] が true の場合、realm 内で TypeError によって拒否された新しい promise を返します。

  5. tensor.[[descriptor]].readable が false の場合、realm 内で TypeError によって拒否された新しい promise を返します。

  6. tensor がエクスポート済みの場合、realm 内で TypeError によって拒否された新しい promise を返します。

  7. promise を realm 内の新しい promise とします。

  8. promise を tensor.[[pendingPromises]] に追加します。

  9. 次の手順を tensor.[[context]].[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、this が失われた場合は中止します。

      1. bytes を、tensor.[[data]] のコピーを含むバイト列とします。

      2. それが失敗した場合、global で ML タスクをキューに入れ、 次の手順を実行します。

        1. promise を tensor.[[pendingPromises]] から削除します。

        2. promise を "UnknownError" DOMException で拒否し、この手順を中止します。

      3. それ以外の場合、global で ML タスクをキューに入れ、 次の手順を実行します。

        1. promise を tensor.[[pendingPromises]] から削除します。

        2. buffer を、realm 内で bytes から ArrayBuffer を作成した結果とします。

        3. promise を buffer で解決します。

    2. 中止された場合、global で ML タスクをキューに入れ、 promise を "InvalidStateError" DOMException で拒否します。

  10. promise を返します。

8.3.6. readTensor(tensor, outputData)

readTensor(tensor) の Bring-your-own-buffer バリアントです。 MLTensor の [[data]] を、指定されたバッファへ読み戻します。

引数:

戻り値: Promise<undefined>。

readTensor(tensor, outputData) メソッドの手順は次のとおりです。
  1. global を this の関連グローバルオブジェクトとします。

  2. realm を this の関連レルムとします。

  3. tensor.[[context]] が this でない場合、realm 内で TypeError によって拒否された新しい promise を返します。

  4. tensor.[[isDestroyed]] が true の場合、realm 内で TypeError によって拒否された新しい promise を返します。

  5. tensor.[[descriptor]].readable が false の場合、realm 内で TypeError によって拒否された新しい promise を返します。

  6. tensor がエクスポート済みの場合、realm 内で TypeError によって拒否された新しい promise を返します。

  7. outputData と tensor.[[descriptor]] が与えられたときのdescriptor を用いた buffer の検証が false を返した場合、realm 内で TypeError によって拒否された新しい promise を返します。

  8. promise を realm 内の新しい promise とします。

  9. promise を tensor.[[pendingPromises]] に追加します。

  10. 次の手順を tensor.[[context]].[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、this が失われた場合は中止します。

      1. bytes を、tensor.[[data]] のコピーを含むバイト列とします。

      2. それが失敗した場合、global で ML タスクをキューに入れ、 次の手順を実行します。

        1. promise を tensor.[[pendingPromises]] から削除します。

        2. promise を "UnknownError" DOMException で拒否し、この手順を中止します。

      3. それ以外の場合、global で ML タスクをキューに入れ、 次の手順を実行します。

        1. promise を tensor.[[pendingPromises]] から削除します。

        2. outputData が切り離されている場合、promise を TypeError で拒否し、この手順を中止します。

          注: 上記のdescriptor を用いた buffer の検証は、outputData が切り離されている場合に失敗しますが、 その手順とこの手順の間に outputData が切り離される可能性があります。

        3. bytes を outputData に書き込みます。

        4. promise を undefined で解決します。

    2. 中止された場合、global で ML タスクをキューに入れ、 promise を "InvalidStateError" DOMException で拒否します。

  11. promise を返します。

8.3.7. writeTensor()

MLTensor の [[data]] に、MLContext の [[timeline]] 上でデータを書き込みます。

引数:

戻り値: undefined。

writeTensor(tensor, inputData) メソッドの手順は次のとおりです。
  1. tensor.[[context]] が this でない場合、TypeError をスローします。

  2. tensor.[[isDestroyed]] が true の場合、TypeError をスローします。

  3. tensor.[[descriptor]].writable が false の場合、TypeError をスローします。

  4. tensor がエクスポート済みの場合、TypeError をスローします。

  5. inputData と tensor.[[descriptor]] が与えられたときのdescriptor を用いた buffer の検証が false を返した場合、TypeError をスローします。

  6. bytes を、inputData が与えられたときにbuffer source が保持するバイトのコピーを取得した結果とします。

  7. 表明: bytes の長さは tensor.[[descriptor]] の バイト長と等しい。

  8. 次の手順を tensor.[[context]].[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、this が失われた場合は中止します。

      1. bytes を tensor.[[data]] にコピーします。

        tensor への書き込み中に発生するエラーを報告するためのメカニズムを追加する。[Issue #778]

注: dispatch() と同様に、 writeTensor() 自体は書き込みが完了したことを示すシグナルを提供しません。tensor の内容を確認するには、 呼び出し元は tensor の読み戻し結果を await できます。

8.3.8. exportToGPU()

エクスポート可能な MLTensor を、関連付けられた GPUDevice へ GPUBuffer としてエクスポートし、返された GPUBuffer が破棄されるまで、その GPUDevice に貸し出します。

引数:

戻り値: GPUBuffer。

MLTensor がエクスポートされている間、 [[gpuDevice]] は MLTensor の内容への排他的アクセス権を持ち、MLTensor に依存するすべての WebNN 演算 — dispatch()、 readTensor(tensor)、 readTensor(tensor, outputData)、 および writeTensor() — は TypeError をスローします。

返される GPUBuffer は、usage が GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST、size が MLTensor の [[descriptor]] の バイト長と等しい状態で作成されます。返された GPUBuffer が破棄されると、MLTensor は MLContext に返却され、再び WebNN 演算で使用できます。

注: MLTensor のエクスポートが ゼロコピーになる保証はありません。MLTensor を支えるメモリに [[gpuDevice]] からアクセスできない場合、エクスポートには MLTensor の 内容を返される GPUBuffer へコピーし、GPUBuffer が破棄された時点でそれらをコピーし戻す必要がある場合があります。

exportToGPU(tensor) メソッドの手順は次のとおりです。
  1. tensor.[[context]] が this でない場合、TypeError をスローします。

  2. tensor.[[isDestroyed]] が true の場合、TypeError をスローします。

  3. tensor.[[exportableToGPU]] が false の場合、TypeError をスローします。

  4. realm を this の関連レルムとします。

  5. gpuDevice を tensor.[[gpuDevice]] とします。

  6. gpuDevice が失われている場合、"InvalidStateError" DOMException をスローします。

  7. tensor がエクスポート済みの場合、tensor.[[exportedBuffer]] を返します。

  8. usage を GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST とします。

  9. buffer を、gpuDevice に関連付けられた realm 内の新しい GPUBuffer とします。その size は tensor.[[descriptor]] の バイト長であり、その usage は usage です。

  10. 次の手順を tensor.[[context]].[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、this が失われた場合は中止します。

      1. buffer の内容が tensor.[[data]] を反映するようにします。

        注: エクスポートが ゼロコピーの場合、buffer と tensor.[[data]] は同じメモリによって支えられており、コピーは行われません。

  11. tensor.[[exportedBuffer]] を buffer に設定します。

  12. buffer を返します。

ユーザーエージェントは、buffer の内容が tensor.[[data]] を反映するようにするため、上記でエンキューされた手順が完了する前に、buffer から読み取る、または buffer へ書き込む gpuDevice の GPUQueue にエンキューされた演算が実行されないことを確保しなければなりません。

注: この順序保証はユーザーエージェント内部のものであり、 アプリケーション側で観測可能な同期を必要としません。アプリケーションは exportToGPU() が返った直後に、buffer を使用する GPUQueue の作業を安全に記録して送信できます。

exportToGPU() によって返された GPUBuffer が破棄された場合、ユーザーエージェントは、それがエクスポートされた元の MLTensor を指定してエクスポートされた MLTensor を返却しなければなりません。

注: MLTensor またはその MLContext を、それがエクスポート されている間に破棄しても、返された GPUBuffer は無効になりません。 GPUBuffer は破棄されるまで [[gpuDevice]] から引き続き使用できます。

注: MLTensor がエクスポートされている間に [[gpuDevice]] が失われた場合、返された GPUBuffer は暗黙的には破棄されず、MLTensor は、アプリケーションが destroy() を呼び出すまでエクスポートされたままです (したがって WebNN 演算では使用できません)。destroy() は gpuDevice が失われた後でも引き続き有効に呼び出せます。

8.3.8.1. 例
次のコードは、エクスポート可能な tensor を使用する最小限の WebNN から WebGPU へのフローを示します。
// 1. WebGPU および WebNN コンテキストを作成する。
const gpuAdapter = await navigator.gpu.requestAdapter();
const gpuDevice = await gpuAdapter.requestDevice();
const context = await navigator.ml.createContext();

// 2. 単純なグラフを構築する: y = x + 1。
const builder = new MLGraphBuilder(context);
const descriptor = {dataType: 'float32', shape: [4]};
const x = builder.input('x', descriptor);
const one = builder.constant(descriptor, new Float32Array([1, 1, 1, 1]));
const y = builder.add(x, one);
const graph = await builder.build({y});

// 3. エクスポート可能な tensor を作成し、WebNN dispatch を実行する。
const inputTensor = await context.createExportableTensor(
    {dataType: 'float32', shape: [4], writable: true}, gpuDevice);
const outputTensor = await context.createExportableTensor(
    {dataType: 'float32', shape: [4], readable: true}, gpuDevice);
context.writeTensor(inputTensor, new Float32Array([1, 2, 3, 4]));
context.dispatch(graph, {x: inputTensor}, {y: outputTensor});

// 4. WebGPU にエクスポートし、GPU コマンドで使用する。
const gpuBuffer = context.exportToGPU(outputTensor);
// ... WebGPU の compute/render 処理で gpuBuffer を使用する ...

// 5. tensor を WebNN に返却し、その後 WebNN から再び読み取る。
gpuBuffer.destroy();
const result = new Float32Array(await context.readTensor(outputTensor));
console.log(result);  // [2, 3, 4, 5]

8.3.9. opSupportLimits()

opSupportLimits() は、演算子レベルで実装ごとに異なるサポートの程度を公開します。WebNN API の利用者には、 各対象プラットフォームに展開する最適なモデルアーキテクチャを決定するため、opSupportLimits() を使用して機能のサポートレベルを調査することを推奨します。

注: opSupportLimits() API は、ブラウザーのフィンガープリンティングに追加のエントロピーを提供することを意図したものではありません。現在の実装では、 この機能サポート情報は OS とブラウザーのバージョンだけから推測できます。将来の実装の多様性によって必要になった場合、この API は、 エントロピーを低減するために WebGPU と同様に機能をバケット化するなど、将来の実装が新しいプライバシー軽減策を 追加できるようにします。

フィンガープリンティングに関する追加の議論については、§ 5 プライバシー上の考慮事項を参照してください。

8.3.9.1. MLOpSupportLimits 辞書
MLOpSupportLimits には次のトップレベルメンバーがあります。これらに加えて、各 演算子には、そのビルダーメソッドで定義された対応するメンバーがあります。
dictionary MLOpSupportLimits {
  MLInputOperandLayout preferredInputLayout;
  [EnforceRange] unsigned long long maxTensorByteLength;
  MLTensorLimits input;
  MLTensorLimits constant;
  MLTensorLimits output;
};
preferredInputLayout, 型は MLInputOperandLayout

conv2d() など、レイアウトに依存する演算子の優先入力レイアウト。

maxTensorByteLength, 型は unsigned long long

サポートされる tensor の最大長(バイト単位)。

input, 型は MLTensorLimits

MLGraph の入力 MLOperand のサポート制限。

constant, 型は MLTensorLimits

MLGraph の定数 MLOperand のサポート制限。

output, 型は MLTensorLimits

MLGraph の出力 MLOperand のサポート制限。

8.3.9.2. MLRankRange 辞書
dictionary MLRankRange {
  unsigned long min;
  unsigned long max;
};
min, 型は unsigned long

サポートされる最小ランク。

max, 型は unsigned long

サポートされる最大ランク。

8.3.9.3. MLTensorLimits 辞書
typedef sequence<MLOperandDataType> MLDataTypeList;

dictionary MLTensorLimits {
  MLDataTypeList dataTypes;
  MLRankRange rankRange;
};
dataTypes, 型は MLDataTypeList

サポートされるデータ型。

rankRange, 型は MLRankRange

サポートされる最小および最大ランク。

8.3.9.4. MLBinarySupportLimits 辞書
dictionary MLBinarySupportLimits {
  MLTensorLimits a;
  MLTensorLimits b;
  MLTensorLimits output;
};
a, 型は MLTensorLimits

a オペランドの MLTensorLimits。

b, 型は MLTensorLimits

b オペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

8.3.9.5. MLSingleInputSupportLimits 辞書
dictionary MLSingleInputSupportLimits {
  MLTensorLimits input;
  MLTensorLimits output;
};
input, 型は MLTensorLimits

入力オペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

8.3.10. destroy()

destroy() メソッドを呼び出して、コンテキストに関連付けられたすべてのリソースを解放できます。未処理の計算要求 および MLTensor の作成/読み取り/書き込み要求はすべて失敗します。

destroy() メソッドの手順は次のとおりです。
  1. this が失われている場合、この手順を中止します。

  2. 実装定義のメッセージを使用して、this を失わせる手順を実行します。

    注: destroy() が呼び出されたことを示すメッセージは、開発者がコンテキスト喪失の原因を区別するのに役立ちます。

8.3.11. エラー

ユーザーエージェントが MLContext が 要求を処理するために利用できなくなったと判断した場合、そのコンテキストに対してコンテキスト喪失手順を実行しなければなりません。

MLContext context に対する コンテキスト喪失 手順は次のとおりです。
  1. global を context の関連グローバルオブジェクトとします。

  2. global で ML タスクをキューに入れ、次の手順を実行します。

    1. 失わせる context を、実装定義のメッセージで。

MLContext context を DOMString message で 失わせるには:
  1. info を新しい MLContextLostInfo とします。

  2. info.message を message に設定します。

  3. context.[[lost]] を info で解決します。

  4. graph.[[context]] が this と等しい各 MLGraph graph について:

    1. graph を this として、graph に対する destroy() メソッドの手順を実行します。

  5. tensor.[[context]] が this と等しい各 MLTensor tensor について:

    1. tensor を this として、tensor に対する destroy() メソッドの手順を実行します。

message, 型は DOMString

発生したエラーに関する情報を提供する実装定義のメッセージ。

lost getter の手順は、this の [[lost]] Promise を返すことです。

MLContext は、その [[lost]] Promise が 確定済みである場合、失われています。

8.4. MLGraph インターフェイス

MLGraph インターフェイスは、コンパイル済みの計算グラフを表します。コンパイル済みグラフは一度構築されると不変であり、 その後変更することはできません。
[SecureContext, Exposed=(Window, Worker)]
interface MLGraph {
  undefined destroy();
};
MLGraph には 次の内部スロットがあります。
[[context]]、型は MLContext

この MLGraph に関連付けられた、型 MLContext のコンテキスト。

[[inputDescriptors]]、 型は record<USVString, MLOperandDescriptor>

この MLGraph のすべての入力 MLOperand について、入力 MLOperand の名前をその MLOperandDescriptor にマッピングします。

[[outputDescriptors]]、 型は record<USVString, MLOperandDescriptor>

この MLGraph のすべての出力 MLOperand について、出力 MLOperand の名前をその MLOperandDescriptor にマッピングします。

[[implementation]]

ユーザーエージェントによって提供される基盤実装。

[[isDestroyed]]、型は boolean

MLGraph.destroy() メソッドの手順が実行されたかどうか。一度破棄されると、MLGraph はそれ以上使用できません。

8.4.1. destroy()

destroy() メソッドを呼び出して、グラフに関連付けられたすべてのリソースを解放できます。

destroy() メソッドの手順は次のとおりです。
  1. this.[[isDestroyed]] が true の場合、この手順を中止します。

  2. this.[[isDestroyed]] を true に設定します。

  3. this.[[context]].[[timeline]] 上に、このグラフが所有するリソースを解放可能としてマークするタスクをキューに入れます。

注: このグラフを使用してこれ以上ワークロードをエンキューできないため、 実装は、このグラフを使用して以前に送信されたすべてのワークロードが完了した後、このグラフに関連付けられた追加の リソース割り当てを解放できます。

8.5. MLOperandDescriptor 辞書

MLOperandDescriptor はオペランドの形状(次元)とデータ型を記述します。これらは MLGraph の入力と 定数を記述するために使用され、すべての MLOperand は内部に MLOperandDescriptor を持ちます。

enum MLInputOperandLayout {
  "nchw",
  "nhwc"
};

enum MLOperandDataType {
  "float32",
  "float16",
  "int32",
  "uint32",
  "int64",
  "uint64",
  "int8",
  "uint8",
  "bfloat16",
  "float8e4m3"
};

dictionary MLOperandDescriptor {
  required MLOperandDataType dataType;
  required sequence<[EnforceRange] unsigned long> shape;
};
dataType, 型は MLOperandDataType

オペランドのデータ型。

shape, 型は sequence<[EnforceRange] unsigned long>

オペランドの次元のリスト。スカラーオペランドの場合は空です。

MLOperandDataType 列挙型は、オペランドの各要素のデータ型を指定する:

float32

32 ビット浮動小数点。 [IEEE-754-2019]の binary32 交換形式を使用する。

float16

16 ビット浮動小数点。 [IEEE-754-2019]の binary16 交換形式を使用する。

int32

2 の補数表現による 32 ビット符号付き整数。

uint32

32 ビット符号なし整数。

int64

2 の補数表現による 64 ビット符号付き整数。

uint64

64 ビット符号なし整数。

int8

2 の補数表現による 8 ビット符号付き整数。

uint8

8 ビット符号なし整数。

bfloat16

符号 1 ビット、指数部 8 ビット(指数バイアス 127)、後続仮数部 7 ビットからなる 16 ビットの「brain」浮動小数点。指数範囲は "float32"と同じであり、無限大、NaN、符号付きゼロ、非正規化数は [IEEE-754-2019]の二進交換形式と同じ方法で表現される。この形式の値のビット配置は、同じ値の binary32 符号化における上位 16 ビットと一致する。

float8e4m3

OCP 8 ビット浮動小数点仕様 [OCP-OFP8]の E4M3 形式による 8 ビット浮動小数点。符号 1 ビット、指数部 4 ビット(指数バイアス 7)、後続仮数部 3 ビットからなる。他の浮動小数点データ型とは異なり、この形式には無限大の表現がない。有限値の絶対値の最大値は 448 であり、NaN は指数部と仮数部のすべてのビットを 1 にして符号化される。符号付きゼロと非正規化数がサポートされる。この形式への変換では飽和処理が行われる。無限大を含め、絶対値が 448 を超える値は、同じ符号で絶対値が最大の有限値に変換される。 cast()を参照。

"bfloat16" および "float8e4m3" は、どの演算でも 必須データ型 に含まれない。演算ごとのサポート状況は opSupportLimits()で問い合わせることができる。

注: "float8e4m3" 形式は、PyTorch の float8_e4m3fn 型および ONNX の FLOAT8E4M3FN 型に対応する。無限大用の符号を予約する E4M3 符号化や、負のゼロを持たない「FNUZ」派生形式とは異なり、この列挙型はそれらのいずれも表さない。

注: "float8e4m3" での量子化計算は、 dequantizeLinear() と quantizeLinear() を演算の前後に配置して表現する。その演算のオペランドは "float32"、 "float16" または "bfloat16"であり、この場合、 "float8e4m3" は算術演算自体のオペランドの型ではなく、そのような部分グラフの量子化された入力、重み、出力のデータ型となる。 "float8e4m3" 演算をネイティブにサポートするプラットフォーム上の実装では、量子化および逆量子化の演算を、その前後で囲まれている演算に融合し、 "float8e4m3"で実行することが推奨される。例えば、 "float8e4m3" matmul()として実行する。他の実装は、それらを明示的に実行する。一方、一部の演算の 許可されるデータ型 は 任意である。これには、 reshape() や concat()などのデータ移動演算だけでなく、 add() や clamp()などの算術演算も含まれる。グラフの構築時には、これらの演算の "float8e4m3" オペランドは拒否されず、実装がそれらをサポートするかどうかは opSupportLimits()によって報告される。

注: ArrayBufferView 型には "bfloat16" と "float8e4m3"に対応する型がないため、それぞれの生のビット列は Uint16Array と Uint8Array を介して渡される。 § 12.1 MLOperandDataType と ArrayBufferView の互換性を参照。これらのデータ型をネイティブにサポートしないプラットフォーム上の実装でも、特定の位置であればサポートできる場合がある。例えば、 constant() オペランドが cast() または dequantizeLinear() 演算への入力となる場合、グラフの実行前にそのオペランドを変換することが考えられる。この方法ではモデルの重みのダウンロードサイズの削減は維持されるが、低精度形式によるメモリ使用量の削減や計算上の利点は得られない。

MLOperandDescriptor A は、A.dataType が B.dataType と等しく、かつ A.shape が B.shape と等しい場合、MLOperandDescriptor B と 等しいです。
MLOperandDataType dataType と リスト shape が与えられたときに MLOperandDescriptor を 作成するには、次の手順を実行します。
  1. descriptor を新しい MLOperandDescriptor とします。

  2. descriptor.dataType を dataType に設定します。

  3. descriptor.shape を shape の複製に設定します。

  4. もし 寸法を検査するに descriptorを与えた結果が false を返す場合、投げる TypeError。

  5. descriptor を返します。

MLOperandDescriptor desc の バイト長は、次の手順によって返される値です。
  1. elementLength を 1 とします。

  2. desc.shape の各 dimension について反復します。

    1. elementLength を elementLength * dimension に設定します。

  3. elementSize を、この 表に従って desc.dataType と一致する ArrayBufferView 型のいずれかの要素サイズとします。

  4. elementLength * elementSize を返します。

MLOperandDescriptor desc の 要素数は、次の手順によって返される値です。
  1. elementCount を 1 とします。

  2. desc.shape の各 dimension について反復します。

    1. elementCount を elementCount * dimension に設定します。

  3. elementCount を返します。

有効な次元とは、 0 より大きく、long の範囲内にある整数です。実装は、より小さい上限を課す場合があります。

有効な tensor 数とは、0 より大きく 8192 以下の整数です。実装は、 より小さい上限を課す場合があります。

サイズ 0 の次元を サポートすべきか? [Issue #391]

MLOperandDescriptor descriptor が与えられたときに 次元をチェックするには、次の手順を実行します。
  1. descriptor.shape のいずれかの項目が有効な 次元でない場合、false を返します。

  2. descriptor.shape の サイズが実装でサポートするには大きすぎる場合、 false を返します。

    オペランドの次元数の最大値は 定義されていませんが、ネイティブ ML API には通常、サポートされる最大 サイズがあります。[Issue #456]

  3. descriptor の要素数が有効な 次元でない場合、false を返します。

  4. descriptor のバイト長が実装でサポートされていない場合、false を返します。

  5. true を返します。

8.6. MLOperand インターフェイス

MLOperand は、演算の各部分を完全に合成された演算へ合成した結果として構築される途中のグラフを表します。

たとえば、MLOperand は、 演算へ供給される定数、または複数の定数を演算内で結合した結果を表すことができます。 § 7 プログラミングモデルも参照してください。

[SecureContext, Exposed=(Window, Worker)]
interface MLOperand {
  readonly attribute MLOperandDataType dataType;
  readonly attribute FrozenArray<unsigned long> shape;
};

dictionary MLOperatorOptions {
  USVString label = "";
};

typedef (bigint or unrestricted double) MLNumber;
MLOperand には次の内部スロットがあります。
[[builder]]、型は MLGraphBuilder

MLOperand に 関連付けられた builder オブジェクト。

[[descriptor]]、型は MLOperandDescriptor

MLOperand の descriptor。

[[name]]、型は 文字列

MLOperand の 名前(入力オペランドの場合のみ)。

[[operator]]、型は 演算子

MLOperand に 対応する演算子への参照。

[[constantTensor]]、型は MLTensor

MLOperand の tensor(定数オペランドの場合のみ)。

MLOperand の dataType は、その [[descriptor]].dataType です。

MLOperand の shape は、その [[descriptor]].shape です。

MLOperand の ランクは、そのshape のサイズです。

dataType のgetter 手順は、this のdataType を返すことです。

shape のgetter 手順は、this のshape を返すことです。

[[builder]] オブジェクトは MLGraphBuilder() コンストラクターによって MLContext オブジェクトに結び付けられるため、MLOperand も 常に同じ MLContext オブジェクトに結び付けられます。

演算が MLOperandDataType の一部のみをサポートする場合、 位置引数とオプションの両方を含む演算の各入力オペランドに対する 許可されるデータ 型は、MLOperandDataType の明示的なリスト、 またはオペランドの dataType が別の入力オペランドの dataType と 同じでなければならないという制約、または任意の MLOperandDataType を許可する 任意として指定されます。

実装は、オペランドについて指定されたものより少ないデータ型をサポートしてもよいですが、少なくとも指定された 必須データ 型をサポートしなければなりません。各演算のサポートは、MLContext の opSupportLimits() メソッドを使用し、現在の Chromium プロトタイプにおける ONNX Runtime、LiteRT、および CoreML バックエンド全体で、 演算に対応するメンバーの dataTypes 値を調べることで問い合わせることができます。

必須データ 型の集合は、開発者がこれらのデータ型のみを使用するようモデルを設計することで相互運用可能なコンテンツを作成できるよう、 幅広いプラットフォームでの実装経験に基づいて決定されています。この仕様の Web Platform Tests は、この機能検出メカニズムを使用して、すべての許可されるデータ 型に対する正しい動作を検証しますが、必須データ型のみをサポートしていても合格できます。

演算が特定のランクを持つ入力オペランドを必要とする場合、位置引数とオプションの両方を含む 演算の各入力オペランドに対する 許可されるランクは、明示的なランク(例: 1)、任意の次元数を許可する N、または別のオペランドと 同じとして指定されます。入力オペランドの shape が別の入力オペランドに対して単方向にブロードキャスト可能でなければならない場合や、別の入力オペランドと双方向にブロードキャスト可能でなければならない場合など、より具体的な制約も一般的です。 このような場合、許可される ランクは範囲として列挙され、具体的な検証は演算内の手順として示されます。

実装は、オペランドのランクについて、指定されたものより制限の厳しい下限および/または上限を課してもよいですが、少なくとも指定された 必須ランクをサポートしなければなりません。各演算のサポートは、MLContext の opSupportLimits() メソッドを使用し、現在の Chromium プロトタイプにおける ONNX Runtime、LiteRT、および CoreML バックエンド全体で、 演算に対応するメンバーの rankRange.min および rankRange.max の値を調べることで問い合わせることができます。

必須ランクの集合は、 開発者がこれらのランクのみを持つ入力オペランドから構成されるモデルを設計することで相互運用可能なコンテンツを 作成できるよう、幅広いプラットフォームでの実装経験に基づいて決定されています。

MLOperatorOptions には次のメンバーがあります。

label, 型は USVString、デフォルトは ""

演算子が MLOperand を作成する MLGraphBuilder メソッドを使用して作成されるときに、必要に応じて指定されます。 実装は、この値を使用して演算子のラベルを初期化する場合があります。

注: ラベルは自然言語の 文字列として使用することを意図したものではありません。これは、変数名やエラーコードと同様の、言語に依存しない識別子であり、 "mul#1234" のようなものです。

注: 実装には、開発者が提供する label を使用してエラーメッセージを強化し、グラフ構築中の同期 エラーと、非同期の build() メソッド中に発生するエラーの両方を含め、デバッグ容易性を向上させることを推奨します。

label を介して開発者が提供したラベルをデバッグツール、ログ、またはエラーメッセージに表示する場合、実装は 悪意のある Unicode シーケンスの注入などのセキュリティリスクを防ぐため、出力をサニタイズすべきです(例: 双方向テキスト スプーフィング [UTR36]、ソースコードスプーフィング [UTS55]、 その他の懸念事項)。たとえば、実装は制御文字(例: U+202A から U+202E、U+2066 から U+2069)をエスケープまたはフィルタリングするか、安全なレンダリングメカニズムを使用して潜在的な スプーフィングを無効化すべきです。

8.6.1. MLOperand の作成

MLOperand オブジェクトは、MLGraphBuilder のメソッドによって、 内部的に次のアルゴリズムを使用して作成されます。
MLGraphBuilder builder と MLOperandDescriptor desc が与えられたときに MLOperand を 作成するには、次の手順を実行します。
  1. realm を builder の関連レルムとします。

  2. operand を realm 内の新しい MLOperand とします。

  3. operand.[[builder]] を builder に設定します。

  4. operand.[[descriptor]] を desc に設定します。

  5. operand を返します。

MLOperand operand が与えられたときに MLOperand を コピーするには、次の手順を実行します。
  1. builder を operand.[[builder]] とします。

  2. realm を builder の関連レルムとします。

  3. result を realm 内の新しい MLOperand とします。

  4. result.[[builder]] を builder に設定します。

  5. result.[[descriptor]] を operand.[[descriptor]] に設定します。

  6. operand.[[name]] が存在する場合、result.[[name]] を operand.[[name]] に設定します。

  7. result を返します。

MLGraphBuilder builder と MLOperand operand が与えられたときに オペランドを検証するには、operand.[[builder]] が builder であれば true を、それ以外の場合は false を返します。

8.6.1.1. MLNumber

MLNumber は、64 ビット整数型("uint64" および "int64") と 32 ビット浮動小数点("float32") の両方を含む、任意の MLOperandDataType になり得る MLOperand に対する数値オプションの型を指定するときに使用されます。 実装は、対応する MLOperandDataType に従って値を処理します。たとえば、clamp(input, options) が dataType "uint32" の MLOperand で呼び出された場合、 MLNumber パラメーターは明示的に unsigned long にキャストされます。

オプションを double として指定すると、253 を超える値を渡す際に精度が失われ、long long として指定すると 263 を超える値が許可されません。

bigint と数値型の union のサポートは [WEBIDL] では新しく、実装によるサポートも限定的です。 プロトタイプ実装には、このアプローチに関するフィードバックを提供することを推奨します。[whatwg/webidl Issue #1388]

8.7. MLTensorDescriptor 辞書

MLTensorDescriptor は MLTensor の特性と機能を記述します。

dictionary MLTensorDescriptor : MLOperandDescriptor {
  boolean readable = false;
  boolean writable = false;
};
readable, 型は boolean、デフォルトは false

tensor の内容を readTensor(tensor) または readTensor(tensor, outputData) を介して読み取れるかどうか。

writable, 型は boolean、デフォルトは false

tensor の内容に writeTensor() を介して書き込めるかどうか。

8.8. MLTensor インターフェイス

MLTensor インターフェイスは、MLGraph の入力または出力として使用できる tensor を表します。MLTensor を支える メモリは、その作成に使用された MLContext および MLTensorDescriptor の要件に従って、実装定義の方法で割り当てるべきです。MLTensor の [[data]] に関する演算は、関連付けられた MLContext の [[timeline]] 上で行われます。

MLTensor の割り当て方法に関する実装定義の要件には、 メモリを特定のバイトアラインメントで割り当てることや、特定のメモリプール内に割り当てることなどの制約が含まれる場合があります。

[SecureContext, Exposed=(Window, Worker)]
interface MLTensor {
  readonly attribute MLOperandDataType dataType;
  readonly attribute FrozenArray<unsigned long> shape;
  readonly attribute boolean readable;
  readonly attribute boolean writable;
  readonly attribute boolean constant;

  undefined destroy();
};
MLTensor には 次の内部スロットがあります。
[[context]]、型は MLContext

MLTensor に 関連付けられたコンテキスト。

[[descriptor]]、型は MLTensorDescriptor

MLTensor の descriptor。

[[pendingPromises]]、 型は Promise の集合

進行中でまだ解決されていない MLContext.readTensor(tensor) メソッド呼び出しに対応する Promise。MLTensor が破棄されると、保留中のすべての promise は拒否されます。

[[isDestroyed]]、型は boolean

MLTensor.destroy() の手順が実行されたかどうか。一度破棄されると、MLTensor はそれ以上使用できません。

[[data]]、実装定義の型

MLTensor を支えるバイト。 このデータは [[context]].[[timeline]] からのみアクセスまたは変更できます。

[[isConstant]]、型は boolean

MLTensor が定数 MLTensor を作成することによって作成されたかどうか。

[[exportableToGPU]]、 型は boolean

MLTensor がエクスポート可能な MLTensor を作成することによって作成され、exportToGPU() を使用して GPUDevice にエクスポートできるかどうか。

[[gpuDevice]]、型は GPUDevice または null

MLTensor をエクスポートできる GPUDevice、 または MLTensor がエクスポート可能でない場合は null。[[exportableToGPU]] が true の場合にのみ設定されます。

[[exportedBuffer]]、型は GPUBuffer または null

exportToGPU() の結果として、現在 [[gpuDevice]] に貸し出されている GPUBuffer、 または MLTensor が現在エクスポートされていない場合は null。

MLTensor の dataType は、その [[descriptor]] の dataType です。

MLTensor の shape は、その [[descriptor]] の shape です。

dataType のgetter 手順は、 this のdataType を返すことです。

shape のgetter 手順は、 this のshape を返すことです。

readable のgetter 手順は、 this.[[descriptor]].readable を返すことです。

writable のgetter 手順は、 this.[[descriptor]].writable を返すことです。

constant のgetter 手順は、 this の [[isConstant]] を返すことです。

MLTensor は、その [[exportedBuffer]] が null でない場合、エクスポートされています。

8.8.1. MLTensor の作成

MLTensor は、 関連付けられた MLContext によって作成されます。

MLContext context および MLTensorDescriptor descriptor が与えられたときに MLTensor を 作成するには、次の手順を実行します。
  1. realm を context の関連レルムとします。

  2. tensor を realm 内の新しい MLTensor とします。

  3. tensor.[[context]] を context に設定します。

  4. tensor.[[descriptor]] を descriptor に設定します。

  5. tensor.[[isDestroyed]] を false に設定します。

  6. tensor.[[isConstant]] を false に設定します。

  7. tensor.[[exportableToGPU]] を false に設定します。

  8. tensor.[[gpuDevice]] を null に設定します。

  9. tensor.[[exportedBuffer]] を null に設定します。

  10. tensor を返します。

MLContext context、MLTensorDescriptor descriptor、および GPUDevice gpuDevice が与えられたときに エクスポート可能な MLTensor を作成するには、次の手順を実行します。
  1. tensor を、context および descriptor が与えられたときに MLTensor を作成した結果とします。

  2. tensor.[[exportableToGPU]] を true に設定します。

  3. tensor.[[gpuDevice]] を gpuDevice に設定します。

  4. tensor を返します。

MLTensor tensor が与えられたときに エクスポートされた MLTensor を返却するには、次の手順を実行します。
  1. tensor がエクスポートされていない場合、この手順を中止します。

  2. buffer を tensor.[[exportedBuffer]] とします。

  3. tensor.[[exportedBuffer]] を null に設定します。

  4. tensor.[[isDestroyed]] が true の場合、この手順を中止します。

  5. 次の手順を tensor.[[context]].[[timeline]] にエンキューします。

    1. 次の手順を実行しますが、tensor.[[context]] が失われた場合は中止します。

      1. tensor.[[data]] が buffer の内容を反映するようにします。

        注: エクスポートが ゼロコピーであった場合、buffer と tensor.[[data]] は同じメモリによって支えられており、コピーは行われません。

ユーザーエージェントは、tensor.[[data]] が buffer の内容を反映するようにする上記のエンキューされた手順が、buffer から読み取る、または buffer に書き込む、 gpuDevice の GPUQueue に以前エンキューされたすべての演算が完了する前に実行されないことを確保しなければなりません。

8.8.2. destroy()

MLTensor に関連付けられたリソースを解放します。この メソッドは冪等です。

戻り値: undefined。
destroy() メソッドの手順は次のとおりです。
  1. this.[[isDestroyed]] を true に設定します。

  2. this.[[pendingPromises]] 内の各 promise について反復します。

    1. promise を this.[[pendingPromises]] から削除します。

    2. promise を "InvalidStateError" DOMException で拒否します。

  3. 次の手順を this.[[context]].[[timeline]] にエンキューします。

    1. this.[[data]] を解放します。

注: この tensor を使用してこれ以上演算をエンキューできないため、 実装は、この tensor を使用して以前に送信されたすべての演算が完了した後、この tensor に関連付けられた追加のリソース割り当てを 解放できます。

8.8.3. 定数 MLTensor の作成

定数 MLTensor は、 関連付けられた MLContext によって作成されます。

MLContext context、MLOperandDescriptor inputDescriptor が与えられたときに 定数 MLTensor を作成するには、次の手順を実行します。
  1. realm を context の関連レルムとします。

  2. tensor を realm 内の新しい MLTensor とします。

  3. tensor.[[context]] を context に設定します。

  4. tensorDescriptor を新しい MLTensorDescriptor とします。

  5. tensorDescriptor.readable を false に設定します。

  6. tensorDescriptor.writable を false に設定します。

  7. tensorDescriptor.dataType を inputDescriptor.dataType に設定します。

  8. tensorDescriptor.shape を inputDescriptor.shape に設定します。

  9. tensor.[[descriptor]] を tensorDescriptor に設定します。

  10. tensor.[[isDestroyed]] を false に設定します。

  11. tensor.[[isConstant]] を true に設定します。

  12. tensor.[[exportableToGPU]] を false に設定します。

  13. tensor.[[gpuDevice]] を null に設定します。

  14. tensor.[[exportedBuffer]] を null に設定します。

  15. tensor を返します。

8.9. MLGraphBuilder インターフェイス

MLGraphBuilder インターフェイスは、§ 2 ユースケースで特定された、計算グラフへ 合成できる一連の演算を定義します。また、グラフ構築セッションの中間状態も表します。

typedef record<USVString, MLOperand> MLNamedOperands;

[SecureContext, Exposed=(Window, Worker)]
interface MLGraphBuilder {
  // コンテキストからグラフビルダーを構築する。
  constructor(MLContext context);

  // グラフ入力用のオペランドを作成する。
  MLOperand input(USVString name, MLOperandDescriptor descriptor);

  // グラフ定数用のオペランドを作成する。
  MLOperand constant(MLOperandDescriptor descriptor,
                     AllowSharedBufferSource buffer);

  // 指定された型の指定された数値からスカラーオペランドを作成する。
  MLOperand constant(MLOperandDataType dataType, MLNumber value);

  // 指定された定数 tensor からオペランドを作成する。
  MLOperand constant(MLTensor tensor);

  // 指定された出力オペランドまでのグラフを非同期にコンパイルする。
  Promise<MLGraph> build(MLNamedOperands outputs);
};
MLGraphBuilder.build() メソッドは、グラフビルダーの状態を指定された出力オペランドまで、その作成元となる MLContext の型に従って コンパイル済みグラフへコンパイルします。MLContext の [[contextType]] が "default" に設定されている場合、コンパイル済みグラフは MLGraph が 返される直前に初期化されます。このグラフ初期化段階は、その後のグラフ 実行で最適な性能を得るために重要です。通常は「重みの前処理」と呼ばれる処理を伴い、グラフへのすべての定数入力を 前処理し、その後のグラフ実行呼び出しのためにオペレーティングシステムレベルでキャッシュします。 初期化用の入力は通常、グラフ構築時に constant() メソッドを通じて定数オペランドとして指定された定数の重みデータです。
MLGraphBuilder には次の内部スロットがあります。
[[context]]、型は MLContext

この MLGraphBuilder に関連付けられた、型 MLContext のコンテキスト。

[[hasBuilt]]、型は boolean

MLGraphBuilder.build() が呼び出されたかどうか。一度ビルドされると、MLGraphBuilder はそれ以上演算子を作成したり、MLGraph をコンパイルしたりできません。

MLGraphBuilder は、その [[hasBuilt]] が false であり、その [[context]] が失われていない場合、ビルドできます。

8.9.1. MLGraphBuilder コンストラクター

引数:
new MLGraphBuilder(context) コンストラクターの手順は次のとおりです。
  1. this の関連グローバルオブジェクトの関連付けられた Document が webnn 機能の使用を許可されていない場合、"SecurityError" DOMException をスローします。

  2. context が失われている場合、"InvalidStateError" DOMException をスローします。

  3. this.[[context]] を context に設定します。

  4. this.[[hasBuilt]] を false に設定します。

8.9.2. 入力オペランド

descriptor に基づいて、入力として使用できる名前付き MLOperand を作成します。

引数: 戻り値:MLOperand。
input(name, descriptor) メソッドの手順は次のとおりです。
  1. もし this が 構築できない場合、投げるのは "InvalidStateError" DOMException。

  2. もし name が空の場合、投げるのは TypeError。

  3. もし this の グラフの 入力に含まれる MLOperand のいずれかが、 [[name]] に name と等しい値を持つ場合、投げるのは TypeError。

  4. もし descriptor を与えて 次元を検査した結果が false を返す場合、投げるのは TypeError。

  5. グラフの接続を作成する:

    1. operand を、MLOperand を 作成する処理に this と descriptor を与えた結果とする。

    2. operand.[[name]] を name に設定する。

    3. operand を this の グラフの 入力に追加する。

  6. operand を返す。

MLGraphBuilder API では、入力オペランドなしで MLGraph を作成できます。 基盤プラットフォームがそれをサポートしない場合、実装はダミー入力を追加するか、 定数をグラフへの入力として渡すことができます。

8.9.3. 定数オペランド

MLGraphBuilder メソッドで使用できる定数 MLOperand を作成します。
8.9.3.1. constant(descriptor, buffer)
初期化データを含む、指定されたデータ型と shape の定数 MLOperand を作成します。
引数: 戻り値:MLOperand。 定数出力 tensor。
constant(descriptor, buffer) メソッドの手順は次のとおりです。
  1. もし this が 構築できない場合、投げるのは "InvalidStateError" DOMException。

  2. もし 次元を検査する処理に descriptor を与えた結果が false を返す場合、投げるのは TypeError。

  3. もし 記述子を使用してバッファーを検証する処理に buffer と descriptor を与えた結果が false を返す場合、投げるのは TypeError。

  4. グラフの接続を作成する:

    1. operand を、MLOperand を 作成する処理に this と descriptor を与えた結果とする。

    2. bytes を、バッファーソースが保持するバイト列の コピーを取得する処理に buffer を与えた結果とする。

    3. operand を this の グラフの 定数に、bytes を 値として追加する。

  5. operand を返す。

8.9.3.2. constant(tensor)
初期化済みデータを含む、指定されたデータ型と shape の定数 MLOperand を作成します。
引数: 戻り値:MLOperand。 定数出力 tensor。
constant(tensor) メソッドの手順 は次のとおりです。
  1. もし tensor.[[context]] が this.[[context]] でない 場合、投げるのは TypeError。

  2. もし tensor.[[isDestroyed]] が true の場合、投げるのは TypeError。

  3. もし tensor.[[isConstant]] が false の場合、投げるのは TypeError。

  4. もし this が 構築できない場合、投げるのは "InvalidStateError" DOMException。

  5. グラフの接続を作成する:

    1. operand を、MLOperand を 作成する処理に this と tensor.[[descriptor]] を与えた結果とする。

    2. operand.[[constantTensor]] を tensor に設定する。

    3. operand を this の グラフの 定数に、tensor を 値として追加する。

  6. operand を返す。

8.9.3.3. constant(dataType, value)
指定された値とデータ型のスカラー定数 MLOperand を 作成する。
指定された値が指定された出力データ型の範囲を超える場合、データの切り捨てが発生する。たとえば、 浮動小数点値が "int8" データ型に割り当てられた場合などである。
引数: 戻り値:MLOperand。定数 出力。
constant(dataType, value) メソッドの手順は次のとおり:
  1. this がビルドできない場合、throw で "InvalidStateError" DOMException を送出する。

  2. value を、value を dataType にキャストした結果に設定する。

  3. descriptor を、dataType と « » を与えて MLOperandDescriptor を 作成した結果とする。

  4. グラフ接続を作成する:

    1. operand を、MLOperand を 作成する際に this と descriptor を与えた結果とする。

    2. operand を、value を 値として this のグラフの定数に追加する。

  5. operand を返す。

8.9.4. build メソッド

指定された出力オペランドまでの合成グラフを、計算グラフとして非同期に構築する。
引数: 戻り値: Promise<MLGraph>。
build(outputs) メソッドの手順は次のとおり:
  1. realm を this の 関連するレルム とする。

  2. this が 構築できない 場合、新しい Promise を realm 内で 拒否 したものを返す。拒否理由は "InvalidStateError" DOMException とする。

  3. outputs が空の場合、新しい Promise を realm 内で 拒否 したものを返す。理由は TypeError とする。

  4. それぞれについて、outputs の name → operand を処理する:

    1. name が空の場合、新しい Promise を realm 内で 拒否 したものを返す。理由は TypeError とする。

    2. オペランドの検証 に this と operand を渡した結果が false の場合、新しい Promise を realm 内で 拒否 したものを返す。理由は TypeError とする。

    3. operand が this の グラフ の 入力 または 定数 に含まれる場合、新しい Promise を realm 内で 拒否 したものを返す。理由は TypeError とする。

    4. operand.[[constantTensor]] が存在し、かつ operand.[[constantTensor]].[[isDestroyed]] が true の場合、新しい Promise を realm 内で 拒否 したものを返す。理由は TypeError とする。

  5. operands を新しい空の 集合 とする。

  6. operators を新しい空の 集合 とする。

  7. inputs を新しい空の 集合 とする。

  8. queue を、outputs の キュー に格納される 値 を含む新しいキューとする。

  9. queue が 空でない 状態にある 間、次を繰り返す:

    1. デキュー により operand を queue から取り出す。

    2. 追加 により operand を operands に加える。

    3. 追加 により operand.[[operator]] を operators に加える。

    4. operand が this の グラフ の 入力 に含まれる場合、追加 により operand を inputs に加える。

    5. 各 input を operand.[[operator]] の 入力 から順に処理する:

      1. エンキュー により input を queue に追加する。

  10. global を this の 関連するグローバルオブジェクト とする。

  11. graph を新しい MLGraph とし、realm 内で作成する。

  12. graph.[[context]] に this.[[context]] を設定する。

  13. graph.[[isDestroyed]] を false に設定する。

  14. 各 operand(inputs 内)について:

    1. graph.[[inputDescriptors]][operand.[[name]]] に operand.[[descriptor]] を設定する。

  15. それぞれについて、name → operand を outputs から取り出して処理する:

    1. graph.[[outputDescriptors]][name] に operand.[[descriptor]] を設定する。

  16. this.[[hasBuilt]] を true に設定する。

  17. promise を 新しい Promise とし、realm 内で作成する。

  18. 次の手順を graph.[[context]].[[timeline]] にエンキューする:

    1. 次の手順を実行する。ただし、次の場合に 中止する:graph.[[context]] が 失われて いる 場合:

      1. graphImpl を、this の グラフ を operands、 operators、inputs、outputs の 値、さらに graph.[[context]].[[powerPreference]] および graph.[[context]].[[accelerated]] を用いて 実装定義 の形式に変換した結果とする。その形式は 基盤となるプラットフォームが解釈できるものである。

      2. 前の手順が失敗した場合、ML タスクをキューに入れ、global を用いて 拒否 する。対象は promise であり、理由は "OperationError" DOMException とする。 その後、これらの手順を中止する。

      3. graph.[[implementation]] に graphImpl を設定する。

      4. ML タスクをキューに入れ、global を用いて 解決 する。promise に graph を渡す。

    2. 中止された場合、ML タスクをキューに入れ、 global を用いて 拒否 する。対象は promise であり、理由は "InvalidStateError" DOMException とする。

  19. promise を返す。

注記: 入力 オペランドまたは 定数 オペランドをグラフの 出力 として指定するとエラーになる。これは通常、API の誤った使用方法に当たるためである。呼び出し側は identity() 演算子を導入することで、これを回避できる。

8.9.5. argMin/argMax 演算

軸に沿ったすべての入力値のうち、最小値または最大値のインデックス位置を返す。同値の場合、 戻り値がどれになるかは実装依存である。
dictionary MLArgMinMaxOptions : MLOperatorOptions {
  boolean keepDimensions = false;
  MLOperandDataType outputDataType = "int32";
};
partial interface MLGraphBuilder {
  MLOperand argMin(MLOperand input, [EnforceRange] unsigned long axis,
                    optional MLArgMinMaxOptions options = {});
  MLOperand argMax(MLOperand input, [EnforceRange] unsigned long axis,
                    optional MLArgMinMaxOptions options = {});
};
partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits argMin;
  MLSingleInputSupportLimits argMax;
};

MLArgMinMaxOptions には次のメンバーがある:

keepDimensions, 型は boolean、既定値は false

true の場合、縮約された次元をサイズ 1 のまま保持する。

outputDataType, 型は MLOperandDataType、既定値は "int32"

MLOperandDataType。 出力データ型。

引数:

戻り値: MLOperand。 keepDimensions が true の場合は input の ランクと等しいランクを持ち、keepDimensions が false の場合は input の ランク - 1 の 出力 N 次元テンソル。値は outputDataType 型で、[0, N-1] の範囲でなければならず、ここで N は axis で指定された入力次元のサイズである。

argMin()/argMax() のテンソル制限
オペランド 許可されるデータ 型 必須の データ型 許可されるランク 必須のランク
input 任意 "float32", "float16", "int32" 1 から N 1 から 5
出力 "int32", "int64" "int32" N 0 から 5

MLOpSupportLimits には argMin() および argMax() 用の次のメンバーがある:

argMin, 型は MLSingleInputSupportLimits

argMin() 演算子のサポート制限。

argMax, 型は MLSingleInputSupportLimits

argMax() 演算子のサポート制限。

文字列 op、MLOperand input、unsigned long axis、および MLArgMinMaxOptions options を与えて argMin/argMax 演算を作成するには、次の手順を実行する:
  1. Assert: op は "argMin"、"argMax" のいずれかである。

  2. this がビルドできない場合、throw で "InvalidStateError" DOMException を送出する。

  3. オペランドを検証する際に this と input を与えた結果が false の場合、throw で TypeError を送出する。

  4. axis が input のランク以上の場合、throw で TypeError を送出する。

  5. options.outputDataType が出力テンソルの許可されるデータ型ではない場合(この表による)、throw で TypeError を送出する。

  6. input の形状[axis] が options.outputDataType の 最大値より大きい場合、throw で TypeError を送出する。

  7. outputShape を、input の形状、« axis »、および options.keepDimensions を与えて縮約出力 サイズを計算した結果とする。 それが失敗を返した場合、throw で TypeError を送出する。

  8. desc を、options.outputDataType と outputShape を与えて MLOperandDescriptor を作成した結果とする。

  9. グラフ接続を作成する:

    1. operator を、options を与えた op 演算用の演算子とする。

    2. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  10. output を返す。

次の argMin/argMax アルゴリズムがサポートされる。
argMin(input, axis, options) メソッドの手順は次のとおり:
  1. output を、"argMin"、input、axis、および options を与えて argMin/argMax 演算を 作成した結果とする。

    1. それがエラーをthrow した場合、そのエラーを再度throw する。

  2. output を返す。

argMax(input, axis, options) メソッドの手順は次のとおり:
  1. output を、"argMax"、input、axis、および options を与えて argMin/argMax 演算を作成した結果とする。

    1. それがエラーをthrow した場合、そのエラーを再度throw する。

  2. output を返す。

8.9.6. batchNormalization

[Batch-Normalization] を使用して入力テンソルの値を正規化する。 各入力特徴量について、モデルの学習中にバッチ次元のすべてのサンプルにわたって、その特徴量の平均値と分散値が 計算される。これらの平均値と分散値は、その後、モデルの推論時にこの演算に 与えられる。
dictionary MLBatchNormalizationOptions : MLOperatorOptions {
  MLOperand scale;
  MLOperand bias;
  [EnforceRange] unsigned long axis = 1;
  double epsilon = 1e-5;
};

partial interface MLGraphBuilder {
  MLOperand batchNormalization(MLOperand input, MLOperand mean, MLOperand variance,
                               optional MLBatchNormalizationOptions options = {});
};

dictionary MLBatchNormalizationSupportLimits {
  MLTensorLimits input;
  MLTensorLimits mean;
  MLTensorLimits variance;
  MLTensorLimits scale;
  MLTensorLimits bias;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLBatchNormalizationSupportLimits batchNormalization;
};

MLBatchNormalizationOptions には次のメンバーがある:

scale, 型は MLOperand

スケーリング値の一次元テンソル。そのサイズは、 axis で示される入力次元のサイズに等しい。

bias, 型は MLOperand

バイアス値の一次元テンソル。そのサイズは、 axis で示される入力次元のサイズに等しい。

axis, 型は unsigned long、既定値は 1

平均値と分散値が対応する入力形状の特徴量数次元のインデックス。 その値は [0, N-1] の範囲内でなければならず、ここで N は入力テンソルのランクである。既定 値は 1 であり、"nchw" データレイアウトのチャネル("c")次元に対応する。

epsilon, 型は double、既定値は 1e-5

ゼロ除算による計算エラーを防ぐための小さな値。

引数:

戻り値: MLOperand。 input と同じ形状を持つバッチ正規化済み N 次元テンソル。

batchNormalization() のテンソル制限
オペランド 許可されるデータ 型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" 1 から N 3 から 5
mean 同じ型 input "float32", "float16" 1 1
variance 同じ型 input "float32", "float16" 1 1
scale 同じ型 input "float32", "float16" 1 1
bias 同じ型 input "float32", "float16" 1 1
出力 同じ型 input "float32", "float16" 同じランク input 3 から 5

MLBatchNormalizationSupportLimits には次のメンバーがある:

input, 型は MLTensorLimits

入力オペランドの MLTensorLimits。

mean, 型は MLTensorLimits

平均値オペランドの MLTensorLimits。

variance, 型は MLTensorLimits

分散値オペランドの MLTensorLimits。

scale, 型は MLTensorLimits

スケールオペランドの MLTensorLimits。

bias, 型は MLTensorLimits

バイアスオペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には batchNormalization() 用の次のメンバーがある:

batchNormalization, 型は MLBatchNormalizationSupportLimits

batchNormalization() 演算子のサポート制限。

batchNormalization(input, mean, variance, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、mean、 variance、options.scale (存在する場合)、および options.bias (存在する場合)のいずれかを与えた結果が false なら、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. options.axis が 0 から input のランクまでの範囲(上限を含まない)にない場合、送出するのは TypeError である。

  5. mean のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  6. mean の形状が « input の形状[options.axis] » と等しくない場合、送出するのは TypeError である。

  7. variance のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  8. variance の形状が « input の形状[options.axis] » と等しくない場合、送出するのは TypeError である。

  9. options.epsilon を、options.epsilon を input のdataType にキャストした結果に設定する。

  10. options.scale が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « input の形状[options.axis] » と等しくない場合、送出するのは TypeError である。

  11. options.bias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « input の形状[options.axis] » と等しくない場合、送出するのは TypeError である。

  12. グラフ接続を作成する:

    1. operator を、input、mean、variance、および options を与えた "batchNormalization" 演算用の演算子とする。

    2. output を、MLOperand を 作成する際に this と input.[[descriptor]] を与えた結果とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input、mean、および variance に設定する。

    5. options.scale が存在する場合、それを operator の入力に追加する。

    6. options.bias が存在する場合、それを operator の入力に追加する。

    7. operator の出力を output に設定する。

  13. output を返す。

入力テンソルが "nchw" レイアウトの 4-D である場合のこの演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、ユーザー エージェントは通常、より効率的な実装を備えています。この分解は説明のための例であり、 参照実装ではありません。アルゴリズムや中間結果の精度を規定するものでは ありません。基盤となるプラットフォームが演算を直接サポートしていない場合、 この分解を実装の指針となるテンプレートとして使用できます。
function batchNormalization(builder, input, mean, variance, options) {
  const shape = [1, input.shape[options.axis], 1, 1];
  return builder.add(
    builder.mul(
      builder.reshape(options.scale, shape),
      builder.div(
        builder.sub(input, builder.reshape(mean, shape)),
        builder.sqrt(builder.add(
          builder.reshape(variance, shape),
          builder.constant(input.dataType, options.epsilon))))),
    builder.reshape(options.bias, shape));
}

8.9.7. cast

入力テンソルの各要素を対象のデータ型にキャストする。
partial interface MLGraphBuilder {
  MLOperand cast(MLOperand input,
                 MLOperandDataType dataType,
                 optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits cast;
};
引数:

戻り値: MLOperand。 input と同じ形状を持ち、 各要素が変換先のデータ型にキャストされた N 次元テンソル。

cast() のテンソル制限
オペランド 許可されるデータ 型 必須の データ型 許可されるランク 必須のランク
input 任意 "float32", "float16", "int32", "int8", "uint8" N 0 から 5
出力 任意 "float32", "float16", "int32", "int8", "uint8" 同じランク input 0 から 5

MLOpSupportLimits には cast() 用の次のメンバーがある:

cast, 型は MLSingleInputSupportLimits

cast() 演算子のサポート制限。

MLOperandDataType 間のキャストは、 次の表に従い、一部の場合は規定され、その他の場合は実装定義となる:

cast() 演算に、input の dataType(行) と変換先の dataType (列)を与えた場合の動作。
変換先の型 入力の型 "float32", "float16", "bfloat16" "float8e4m3" "int32", "uint32", "int64", "uint64", "int8", "uint8"
"float32", "float16", "bfloat16", "float8e4m3" 範囲内の場合、最も近い表現可能な値。

範囲外の場合、+/-Infinity。

NaN の場合は NaN。

範囲内の場合は、最も近い表現可能な値。

範囲外または無限大の場合は、同じ符号で絶対値が最大の有限値。

NaN の場合は NaN。

範囲内の場合、切り捨てる。

範囲外の場合、実装定義。

NaN の場合は、 実装定義。

"int32", "uint32", "int64", "uint64", "int8", "uint8" 範囲内の場合、最も近い表現可能な値。

範囲外の場合、+/-Infinity。

範囲内の場合は、最も近い表現可能な値。

範囲外の場合は、同じ符号で絶対値が最大の有限値。

範囲内の場合、同じ値。

範囲外の場合、下位 N ビットを変換先の型として再解釈する。符号付き型では 2 の補数表現を仮定する。

注: 例えば、-1 を "int8" から "uint8" へキャストすると 255 になると規定されている。しかし、-1 を "float32" から "uint8" へキャストした場合の結果は 実装定義である。 "float8e4m3" には無限大の表現がないため、1000 または +Infinity を "float32" から "float8e4m3" へキャストすると 448 に飽和する。これは "float8e4m3" の最大の有限値である。この動作は [OCP-OFP8]の飽和変換モードに対応し、NaN を生成する非飽和モードは使用しない。

cast(input, dataType, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. dataType が出力テンソルの許可されるデータ型ではない場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. operator を、dataType と options を与えた "cast" 演算用の演算子とする。

    2. output を、input を与えて MLOperand をコピーした結果とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

8.9.8. clamp

入力テンソルの各要素を、最小値と最大値で指定された範囲内に制限する。
dictionary MLClampOptions : MLOperatorOptions {
  MLNumber minValue;
  MLNumber maxValue;
};

partial interface MLGraphBuilder {
  MLOperand clamp(MLOperand input, optional MLClampOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits clamp;
};

MLClampOptions には次のメンバーがある:

minValue, 型は MLNumber

範囲の最小値。指定されていない場合、範囲の下限に対するクランプ処理は 実行されない。

maxValue, 型は MLNumber

範囲の最大値。指定されていない場合、範囲の上限に対するクランプ処理は 実行されない。

引数: 戻り値:
clamp() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input 任意 "float32", "float16" N 0 から 5
出力 同じ型 input "float32", "float16" 同じランク input 0 から 5

MLOpSupportLimits には clamp() 用の次のメンバーがある:

clamp, 型は MLSingleInputSupportLimits

clamp() 演算子のサポート制限。

clamp(input, options) メソッドの 手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. minValue を、指定されている場合は options.minValue、 そうでなければ Infinity とする。

  4. options.minValue を、minValue を input のdataType にキャストした結果に設定する。

  5. maxValue を、指定されている場合は options.maxValue、 そうでなければ -Infinity とする。

  6. options.maxValue を、maxValue を input のdataType にキャストした結果に設定する。

  7. options.minValue が options.maxValue より大きい場合、 送出するのは TypeError である。

  8. グラフ接続を作成する:

    1. output を、input を与えて MLOperand をコピーした結果とする。

    2. operator を、options を与えた "clamp" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  9. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function clamp(builder, input, options) {
  if (options.minValue === undefined) {
    if (options.maxValue === undefined) {
      return input;
    } else {
      return builder.min(
        input, builder.constant(input.dataType, options.maxValue));
    }
  } else {
    if (options.maxValue === undefined) {
      return builder.max(
        input, builder.constant(input.dataType, options.minValue));
    } else {
      return builder.min(
        builder.max(input, builder.constant(input.dataType, options.minValue)),
        builder.constant(input.dataType, options.maxValue));
    }
  }
}

8.9.9. concat

指定された軸に沿って入力テンソルを連結する。
partial interface MLGraphBuilder {
  MLOperand concat(sequence<MLOperand> inputs,
                   [EnforceRange] unsigned long axis,
                   optional MLOperatorOptions options = {});
};

dictionary MLConcatSupportLimits {
  MLTensorLimits inputs;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLConcatSupportLimits concat;
};
引数:

戻り値: MLOperand。 すべての入力を axis に沿って連結したテンソル。 出力テンソルは、すべての入力が連結された次元を除き、 同じ形状を持つ。その次元のサイズは、 同じ次元におけるすべての入力サイズの合計として計算される。

concat() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
inputs の 項目 任意 "float32", "float16", "int32" 1 から N 1 から 5
出力 同じ型 inputs の 項目 "float32", "float16", "int32" 同じランク inputs の 項目 1 から 5

MLConcatSupportLimits には次のメンバーがある:

inputs, 型は MLTensorLimits

すべての入力オペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には concat() 用の次のメンバーがある:

concat, 型は MLConcatSupportLimits

concat() 演算子のサポート制限。

concat(inputs, axis, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と inputs 内の任意の項目 を与えた結果が false の場合、送出するのは TypeError である。

  3. inputs のサイズが有効なテンソル数ではない場合、送出するのは TypeError である。

  4. first を inputs[0] とする。

  5. axis が first のランク以上の場合、送出するのは TypeError である。

  6. outputShape を、first の形状のクローンとする。

  7. 1 から inputs のサイズまでの範囲(上限を含まない)内の 各 index について:

    1. input を inputs[index] とする。

    2. input のdataType が first のdataType と等しくない場合、送出するのは TypeError である。

    3. input のランクが first のランクと等しくない場合、 送出するのは TypeError である。

    4. 0 から input のランクまでの範囲(上限を含まない)内の 各 dim について:

      axis で指定された次元を除き、オペランドの対応する各次元の形状と型が 同じでない場合は失敗する。
      1. dim が axis と等しくなく、かつ input の形状[dim] が first の形状[dim] と等しくない場合、送出するのは TypeError である。

      2. dim が axis と等しい場合:

        1. size を outputShape[axis] と input の形状[dim] の合計とする。

        2. size が有効な 次元でない場合、送出するのは TypeError である。

        3. outputShape[axis] を size に設定する。

  8. desc を、first のdataType と outputShape を与えてMLOperandDescriptor を 作成した結果とする。

  9. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、inputs、axis、および options を与えた "concat" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を inputs に設定する。

    5. operator の出力を output に設定する。

  10. output を返す。

8.9.10. conv2d

4-D の入力テンソルとフィルターテンソルから 2-D 畳み込みを計算します
enum MLConv2dFilterOperandLayout {
  "oihw",
  "hwio",
  "ohwi",
  "ihwo"
};

dictionary MLConv2dOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> padding;
  sequence<[EnforceRange] unsigned long> strides;
  sequence<[EnforceRange] unsigned long> dilations;
  [EnforceRange] unsigned long groups = 1;
  MLInputOperandLayout inputLayout = "nchw";
  MLConv2dFilterOperandLayout filterLayout = "oihw";
  MLOperand bias;
};

partial interface MLGraphBuilder {
  MLOperand conv2d(MLOperand input,
                   MLOperand filter,
                   optional MLConv2dOptions options = {});
};

dictionary MLConv2dSupportLimits {
  MLTensorLimits input;
  MLTensorLimits filter;
  MLTensorLimits bias;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLConv2dSupportLimits conv2d;
};

MLConv2dOptions には次のメンバーがあります。

padding, 型は sequence<[EnforceRange] unsigned long>

長さ 4 のリスト: [beginningHeight, endingHeight, beginningWidth, endingWidth]。 畳み込み入力の各空間次元の先頭と末尾に追加される行および列を指定します。 デフォルト値は [0, 0, 0, 0] です。

strides, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト: [strideHeight, strideWidth]。 畳み込み入力の各空間次元に対するスライディングウィンドウのストライドを指定します。 デフォルト値は [1, 1] です。

dilations, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト: [dilationHeight, dilationWidth]。畳み込みフィルター(カーネル)に適用される各 空間次元の dilation 係数を指定します。 デフォルト値は [1, 1] です。

groups, 型は unsigned long、デフォルトは 1

入力チャンネルと出力チャンネルを分割するグループ数。

inputLayout, 型は MLInputOperandLayout、デフォルトは "nchw"

入力テンソルおよび出力テンソルのレイアウト形式を次のように指定します。

  • "nchw"

    • 入力テンソル: [batches, inputChannels, height, width]

    • 出力テンソル: [batches, outputChannels, height, width]

  • "nhwc":

    • 入力テンソル: [batches, height, width, inputChannels]

    • 出力テンソル: [batches, height, width, outputChannels]

filterLayout, 型は MLConv2dFilterOperandLayout、デフォルトは "oihw"

フィルターテンソルのレイアウト形式を次のように指定します。

  • "oihw": [outputChannels, inputChannels/groups, height, width]

  • "hwio": [height, width, inputChannels/groups, outputChannels]

  • "ohwi": [outputChannels, height, width, inputChannels/groups]

  • "ihwo": [inputChannels/groups, height, width, outputChannels]

bias, 型は MLOperand

shape が [outputChannels] で、その値が畳み込み結果に加算される追加の 1-D テンソル。

引数:

戻り値: MLOperand。 畳み込み結果を含む出力 4-D テンソル。出力 shape は inputLayout に従って解釈されます。 より具体的には、"nchw" 入力レイアウトにおける出力テンソルの空間次元、すなわち最後の 2 次元のサイズは、 次のように計算できます。

outputSize = 1 + (inputSize - (filterSize - 1) * dilation - 1 + beginningPadding + endingPadding) / stride

conv2d() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" 4 4
filter input と同じ "float32", "float16" 4 4
bias input と同じ "float32", "float16" 1 1
出力 input と同じ "float32", "float16" 4 4

MLConv2dSupportLimits には次のメンバーがあります。

input, 型は MLTensorLimits

入力オペランドの MLTensorLimits。

filter, 型は MLTensorLimits

filter オペランドの MLTensorLimits。

bias, 型は MLTensorLimits

bias オペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には conv2d() 用の次のメンバーがあります。

conv2d, 型は MLConv2dSupportLimits

conv2d() 演算子のサポート制限。

depthwise conv2d 演算は、MobileNet のようなモデルで使用される grouped convolution の一種であり、groups = inputChannels = outputChannels で、フィルターテンソルの shape は [options.groups, 1, height, width] ("oihw" レイアウトの場合)、[height, width, 1, options.groups]("hwio" レイアウトの場合)、[options.groups, height, width, 1]("ohwi" レイアウトの場合)、および [1, height, width, options.groups]("ihwo" レイアウトの場合)です。
符号なし整数 inputSize、filterSize、beginningPadding、 endingPadding、stride および dilation が与えられたときに、conv 出力サイズを計算するには、次の手順を実行します。数値を返します。
  1. effectiveFilterSize を ( filterSize - 1 ) * dilation + 1 とします。

  2. outputSize を ( inputSize - effectiveFilterSize + beginningPadding + endingPadding ) / stride + 1 とします。

  3. outputSize を返します。

符号なし整数 inputHeight、inputWidth、filterHeight および filterWidth、4 個の符号なし整数のリスト padding、2 個の符号なし整数のリスト strides、および 2 個の符号なし整数のリスト dilations が与えられたときに、conv2d 出力サイズを計算するには、次の手順を実行します。 2 個の数値のリストを返します。
  1. outputHeight を、inputHeight、filterHeight、padding[0]、 padding[1]、strides[0] および dilations[0] が与えられたときに conv 出力サイズを計算した結果とします。

  2. outputWidth を、inputWidth、filterWidth、padding[2]、 padding[3]、strides[1] および dilations[1] が与えられたときに conv 出力サイズを計算した結果とします。

  3. « outputHeight, outputWidth » を返します。

conv2d(input, filter, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、filter、および options.bias (存在する場合)のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. input のランクが許可されるランクでない場合、送出するのは TypeError である。

  5. filter のランクが許可されるランクでない場合、送出するのは TypeError である。

  6. filter のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  7. options.padding が存在しない場合、それをリスト « 0, 0, 0, 0 » に設定する。

  8. そうでなく、options.padding の サイズが 4 でない場合、送出するのは TypeError である。

  9. options.strides が存在しない場合、それをリスト « 1, 1 » に設定する。

  10. そうでなく、options.strides の サイズが 2 でない場合、送出するのは TypeError である。

  11. options.strides 内の いずれかの項目が 0 に等しい場合、送出するのは TypeError である。

  12. options.dilations が存在しない場合、それをリスト « 1, 1 » に設定する。

  13. そうでなく、options.dilations の サイズが 2 でない場合、送出するのは TypeError である。

  14. options.dilations 内の いずれかの項目が 0 に等しい場合、送出するのは TypeError である。

  15. options.groups が 0 の場合、送出するのは TypeError である。

  16. 出力形状を計算する:

    1. inputShape を input の形状とする。

    2. options.inputLayout に応じて分岐する:

      "nchw"

      « batches, inputChannels, inputHeight, inputWidth » を inputShape とする。

      "nhwc"

      « batches, inputHeight, inputWidth, inputChannels » を inputShape とする。

    3. filterShape を filter の形状とする。

    4. options.filterLayout に応じて分岐する:

      "hwio"

      « filterHeight, filterWidth, filterInputChannels, outputChannels » を filterShape とする。

      "ohwi"

      « outputChannels, filterHeight, filterWidth, filterInputChannels » を filterShape とする。

      "ihwo"

      « filterInputChannels, filterHeight, filterWidth, outputChannels » を filterShape とする。

      "oihw"

      « outputChannels, filterInputChannels, filterHeight, filterWidth » を filterShape とする。

    5. inputChannels % options.groups が 0 でない場合、送出するのは TypeError である。

    6. そうでなく、inputChannels / options.groups が filterInputChannels と等しくない場合、送出するのは TypeError である。

    7. outputChannels % options.groups が 0 でない場合、送出するのは TypeError である。

    8. options.bias が存在する場合:

      1. その形状が « outputChannels » と等しくない場合、送出するのは TypeError である。

      2. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    9. « outputHeight, outputWidth » を、inputHeight、inputWidth、 filterHeight、filterWidth、options.padding、 options.strides、 および options.dilations を与えてconv2d 出力 サイズを計算した結果とする。

    10. outputHeight を floor( outputHeight ) に設定する。

    11. outputWidth を floor( outputWidth ) に設定する。

    12. outputHeight または outputWidth のいずれかが有効な 次元でない場合、送出するのは TypeError である。

    13. options.inputLayout に応じて分岐する:

      "nchw"

      outputShape を « batches, outputChannels, outputHeight, outputWidth » とする。

      "nhwc"

      outputShape を « batches, outputHeight, outputWidth, outputChannels » とする。

    14. desc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  17. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、options と filter を与えた "conv2d" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input と filter に設定する。

    5. options.bias が存在する場合、それを operator の入力に追加する。

    6. operator の出力を output に設定する。

  18. output を返す。

8.9.11. convTranspose2d

四次元の入力テンソルとフィルターテンソルを与えて二次元の転置畳み込みを計算する。
enum MLConvTranspose2dFilterOperandLayout {
  "iohw",
  "hwoi",
  "ohwi"
};

dictionary MLConvTranspose2dOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> padding;
  sequence<[EnforceRange] unsigned long> strides;
  sequence<[EnforceRange] unsigned long> dilations;
  sequence<[EnforceRange] unsigned long> outputPadding;
  sequence<[EnforceRange] unsigned long> outputSizes;
  [EnforceRange] unsigned long groups = 1;
  MLInputOperandLayout inputLayout = "nchw";
  MLConvTranspose2dFilterOperandLayout filterLayout = "iohw";
  MLOperand bias;
};

partial interface MLGraphBuilder {
  MLOperand convTranspose2d(MLOperand input, MLOperand filter,
                            optional MLConvTranspose2dOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLConv2dSupportLimits convTranspose2d;
};

MLConvTranspose2dOptions には次のメンバーがある:

padding, 型は sequence<[EnforceRange] unsigned long>

長さ 4 のリスト: [beginningHeight, endingHeight, beginningWidth, endingWidth]。 畳み込み入力の各空間次元の先頭と末尾に追加される行と列を 指定する。 既定値は [0, 0, 0, 0] である。

strides, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト: [strideHeight, strideWidth]。 畳み込み入力の各空間次元に対するスライディングウィンドウのストライドを指定する。 既定値は [1, 1] である。

dilations, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト: [dilationHeight, dilationWidth]。畳み込み フィルター(カーネル)に適用する各空間次元の膨張係数を指定する。 既定値は [1, 1] である。

outputPadding, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト。 出力テンソルの各空間次元に適用するパディング値を指定する。明示的な パディング値は、strides の値が 1 より大きい場合に、転置畳み込みの出力テンソルの形状を一意に決定するために必要となる。

これらの値は必要に応じて出力形状を一意に決定するためにのみ使用され、必ずしも 出力テンソルにパディング値が書き込まれるわけではないことに注意。

既定値は [0, 0] である。

outputSizes, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト。 出力テンソルの最後の二つの次元のサイズを指定する。出力サイズが 明示的に指定されている場合、outputPadding 内の出力パディング値は無視される。

指定されていない場合、出力サイズは自動的に計算される。

groups, 型は unsigned long、既定値は 1

入力チャネルと出力チャネルを分割するグループの数。

inputLayout, 型は MLInputOperandLayout、既定値は "nchw"

入力テンソルと出力テンソルのレイアウト形式を次のように指定する:

  • "nchw"

    • 入力テンソル: [batches, inputChannels, height, width]

    • 出力テンソル: [batches, outputChannels, height, width]

  • "nhwc":

    • 入力テンソル: [batches, height, width, inputChannels]

    • 出力テンソル: [batches, height, width, outputChannels]

filterLayout, 型は MLConvTranspose2dFilterOperandLayout、 既定値は "iohw"

フィルターテンソルのレイアウト形式を次のように指定する:

  • "iohw": [inputChannels, outputChannels/groups, height, width]

  • "hwoi": [height, width, outputChannels/groups, inputChannels]

  • "ohwi": [outputChannels/groups, height, width, inputChannels]

bias, 型は MLOperand

畳み込み結果に値を加算する、形状が [outputChannels] の追加の一次元テンソル。

引数:

戻り値: MLOperand。 転置畳み込みの結果を含む出力四次元テンソル。出力形状は inputLayout に従って解釈される。 より具体的には、outputSizes が明示的に指定されていない限り、outputPadding は、次のように出力テンソルの空間次元の値を計算するために必要となる:

outputSize = (inputSize - 1) * stride + (filterSize - 1) * dilation + 1 - beginningPadding - endingPadding + outputPadding

convTranspose2d() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" 4 4
filter 同じ型 input "float32", "float16" 4 4
bias 同じ型 input "float32", "float16" 1 1
出力 同じ型 input "float32", "float16" 4 4

MLOpSupportLimits には convTranspose2d() 用の次のメンバーがある:

convTranspose2d, 型は MLConv2dSupportLimits

convTranspose2d() 演算子のサポート制限。

符号なし整数 inputSize、filterSize、beginningPadding、 endingPadding、stride、および dilation を与えて 転置畳み込みの出力サイズを計算するには、次の手順を実行する。これらは 数値を返す。
  1. effectiveFilterSize を ( filterSize - 1 ) * dilation + 1 とする。

  2. outputSize を ( inputSize - 1 ) * stride + effectiveFilterSize - beginningPadding - endingPadding とする。

  3. outputSize を返す。

convTranspose2d(input, filter, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、filter、および options.bias (存在する場合)のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input のランクが許可されるランクでない場合、送出するのは TypeError である。

  4. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  5. filter のランクが許可されるランクでない場合、送出するのは TypeError である。

  6. filter のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  7. options.padding が存在しない場合、それをリスト « 0, 0, 0, 0 » に設定する。

  8. そうでなく、options.padding の サイズが 4 でない場合、送出するのは TypeError である。

  9. options.strides が存在しない場合、それをリスト « 1, 1 » に設定する。

  10. そうでなく、options.strides の サイズが 2 でない場合、送出するのは TypeError である。

  11. options.strides 内の いずれかの項目が 0 に等しい場合、送出するのは TypeError である。

  12. options.dilations が存在しない場合、それをリスト « 1, 1 » に設定する。

  13. そうでなく、options.dilations の サイズが 2 でない場合、送出するのは TypeError である。

  14. options.dilations 内の いずれかの項目が 0 に等しい場合、送出するのは TypeError である。

  15. options.outputPadding が存在しない場合、それをリスト « 0, 0 » に設定する。

  16. そうでなく、options.outputPadding の サイズが 2 でない場合、送出するのは TypeError である。

  17. options.outputSizes が存在する場合:

    1. そのサイズが 2 でない場合、送出するのは TypeError である。

  18. そうでない場合:

    1. options.outputPadding[0] が options.strides[0] 以上、 または options.outputPadding[1] が options.strides[1] 以上の場合、 送出するのは TypeError である。

  19. options.groups が 0 の場合、送出するのは TypeError である。

  20. 出力形状を計算する:

    1. inputShape を input の形状とする。

    2. options.inputLayout に応じて分岐する:

      "nchw"

      « batches, inputChannels, inputHeight, inputWidth » を inputShape とする。

      "nhwc"

      « batches, inputHeight, inputWidth, inputChannels » を inputShape とする。

    3. filterShape を filter の形状とする。

    4. options.filterLayout に応じて分岐する:

      "iohw"

      « filterInputChannels, filterOutputChannels, filterHeight, filterWidth » を filterShape とする。

      "hwoi"

      « filterHeight, filterWidth, filterOutputChannels, filterInputChannels » を filterShape とする。

      "ohwi"

      « filterOutputChannels, filterHeight, filterWidth, filterInputChannels » を filterShape とする。

    5. inputChannels が filterInputChannels と等しくない場合、送出するのは TypeError である。

    6. outputChannels を filterOutputChannels * options.groups とする。

    7. outputChannels が有効な次元でない場合、送出するのは TypeError である。

    8. options.bias が存在する場合:

      1. その形状が « outputChannels » と等しくない場合、送出するのは TypeError である。

      2. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    9. calculatedOutputHeight を、inputHeight、filterHeight、 padding[0]、padding[1]、strides[0]、および dilations[0] を与えて転置畳み込みの 出力サイズを計算した結果とする。

    10. calculatedOutputWidth を、inputWidth、filterWidth、 padding[2]、padding[3]、strides[1]、および dilations[1] を与えて転置畳み込みの 出力サイズを計算した結果とする。

    11. options.outputSizes が存在する場合:

      1. « outputHeight, outputWidth » を options.outputSizes とする。

      2. outputHeight が calculatedOutputHeight より小さいか、または outputHeight が calculatedOutputHeight + strides[0] 以上の場合、送出するのは TypeError である。

      3. outputWidth が calculatedOutputWidth より小さいか、または outputWidth が calculatedOutputWidth + strides[1] 以上の場合、送出するのは TypeError である。

    12. そうでない場合:

      1. outputHeight を calculatedOutputHeight + options.outputPadding[0] とする。

      2. outputWidth を calculatedOutputWidth + options.outputPadding[1] とする。

    13. outputHeight または outputWidth のいずれかが有効な 次元でない場合、送出するのは TypeError である。

    14. options.inputLayout に応じて分岐する:

      "nchw"

      outputShape を « batches, outputChannels, floor( outputHeight ), floor( outputWidth ) » とする。

      "nhwc"

      outputShape を « batches, floor( outputHeight ), floor( outputWidth ), outputChannels » とする。

    15. desc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  21. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、options と filter を与えた "convTranspose2d" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input と filter に設定する。

    5. options.bias が存在する場合、それを operator の入力に追加する。

    6. operator の出力を output に設定する。

  22. output を返す。

8.9.12. cumulativeSum

指定された軸に沿って、現在の値を含めるか除外するかに応じて、一連の値の累積和を計算する。
dictionary MLCumulativeSumOptions : MLOperatorOptions {
  boolean exclusive = false;
  boolean reversed = false;
};

partial interface MLGraphBuilder {
  MLOperand cumulativeSum(MLOperand input,
                          unsigned long axis,
                          optional MLCumulativeSumOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits cumulativeSum;
};
cumulativeSum() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16", "int32", "uint32", "int64", "uint64" "float32", "float16", "int32" 1 から N 1 から 5
出力 同じ型 input "float32", "float16", "int32" 同じランク input 1 から 5

MLCumulativeSumOptions には次のメンバーがある:

exclusive, 型は boolean、既定値は false

現在の値を出力に含めるか除外するかを指定する。つまり、包含的な前置和か 排他的な前置和かを指定する [Prefix-sum]。入力 [1,2,3,4] の場合、包含的な累積和の 出力は [1,3,6,10]、排他的な累積和の出力は [0,1,3,6] となる。既定値 は包含的である。

reversed, 型は boolean、既定値は false

対象軸に沿った加算方向を反転し、大きい座標から小さい 座標へ加算するかどうかを指定する。入力 [1,2,3,4] の場合、包含的な順方向累積和の 出力は [1,3,6,10]、包含的な逆方向累積和の出力は [10,9,7,4] となる。既定値は順方向である。

引数:

戻り値:

MLOpSupportLimits には cumulativeSum() 用の次のメンバーがある:

cumulativeSum, 型は MLSingleInputSupportLimits

cumulativeSum() 演算子のサポート制限。

cumulativeSum(input, axis, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. axis が input のランク以上の場合、送出するのは TypeError である。

  5. グラフ接続を作成する:

    1. output を、input を与えて MLOperand をコピーした結果とする。

    2. operator を、"cumulativeSum" 演算と options に対応する演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  6. output を返す。

8.9.13. 要素単位の二項演算

2 つの入力テンソルについて、要素単位の加算、減算、乗算、除算、累乗、最大値、および最小値を 計算します。

演算は ブロードキャスト されます。これは [numpy-broadcasting-rule] に従います。入力テンソルは双方向にブロードキャスト可能でなければなりません。出力テンソルのランクは 入力テンソルのランクの 最大値です。出力テンソルの各次元について、そのサイズは入力テンソルのその次元に沿った最大サイズです。

partial interface MLGraphBuilder {
  MLOperand add(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand sub(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand mul(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand div(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand max(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand min(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand pow(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLBinarySupportLimits add;
  MLBinarySupportLimits sub;
  MLBinarySupportLimits mul;
  MLBinarySupportLimits div;
  MLBinarySupportLimits max;
  MLBinarySupportLimits min;
  MLBinarySupportLimits pow;
};
引数:

戻り値: MLOperand。 2 つの入力テンソルの要素単位の二項演算結果を 含む出力テンソル。

演算の種類:
要素単位の二項演算のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
a 任意 "float32", "float16", "int32" N 0 から 5
b a と同じ "float32", "float16", "int32" N 0 から 5
出力 a と同じ "float32", "float16", "int32" N 0 から 5

MLOpSupportLimits には要素単位の二項演算用の次のメンバーがあります。

add, 型は MLBinarySupportLimits

add() 演算子のサポート制限。

sub, 型は MLBinarySupportLimits

sub() 演算子のサポート制限。

mul, 型は MLBinarySupportLimits

mul() 演算子のサポート制限。

div, 型は MLBinarySupportLimits

div() 演算子のサポート制限。

max, 型は MLBinarySupportLimits

max() 演算子のサポート制限。

min, 型は MLBinarySupportLimits

min() 演算子のサポート制限。

pow, 型は MLBinarySupportLimits

pow() 演算子のサポート制限。

文字列 op、MLOperand a、MLOperand b、および MLOperatorOptions options を与えて 要素ごとの 二項演算を作成するには、次の手順を実行する:
  1. Assert: op は "add"、"sub"、"mul"、"div"、"max"、 "min"、"pow" のいずれかである。

  2. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  3. オペランドを検証する際に this と a または b のいずれかを与えた結果が false の場合、 送出するのは TypeError である。

  4. a のdataType が b のdataType と等しくない場合、送出するのは TypeError である。

  5. outputShape を、a の形状と b の形状を双方向にブロードキャストした結果とする。

    1. それが失敗を返した場合、送出するのは TypeError である。

  6. descriptor を、a のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  7. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と descriptor を与えた結果とする。

    2. operator を、a、b、および options を与えた op 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を a と b に設定する。

    5. operator の出力を output に設定する。

  8. output を返す。

要素ごとの二項演算アルゴリズムは、次のように要素ごとの二項演算を作成する 手順を呼び出す。
add(a, b, options) メソッドの手順は次のとおり:
  1. output を、"add"、a、b、および options を与えて要素ごとの二項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

sub(a, b, options) メソッドの手順は次のとおり:
  1. output を、"sub"、a、b、および options を与えて要素ごとの二項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

mul(a, b, options) メソッドの手順は次のとおり:
  1. output を、"mul"、a、b、および options を与えて要素ごとの二項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

div(a, b, options) メソッドの手順は次のとおり:
  1. output を、"div"、a、b、および options を与えて要素ごとの二項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

max(a, b, options) メソッドの手順は次のとおり:
  1. output を、"max"、a、b、および options を与えて要素ごとの二項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

min(a, b, options) メソッドの手順は次のとおり:
  1. output を、"min"、a、b、および options を与えて要素ごとの二項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

pow(a, b, options) メソッドの手順は次のとおり:
  1. output を、"pow"、a、b、および options を与えて要素ごとの二項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

8.9.14. 要素ごとの論理演算

入力テンソルを要素ごとに比較し、比較結果として 0(false)または 1(true)の値を持つ "uint8" テンソルを返す。単一オペランドの演算では、その演算の論理 結果を返す。

複数オペランドの演算では、[numpy-broadcasting-rule] に従って演算がブロードキャストされる。入力テンソルは双方向にブロードキャスト可能でなければならない。出力テンソルのランクは、 入力テンソルのランクの最大値となる。 出力テンソルの各次元について、そのサイズは 入力テンソルの対応する次元のサイズの最大値となる。

partial interface MLGraphBuilder {
  MLOperand equal(MLOperand a,
                  MLOperand b,
                  optional MLOperatorOptions options = {});
  MLOperand notEqual(MLOperand a,
                     MLOperand b,
                     optional MLOperatorOptions options = {});
  MLOperand greater(MLOperand a,
                    MLOperand b,
                    optional MLOperatorOptions options = {});
  MLOperand greaterOrEqual(MLOperand a,
                           MLOperand b,
                           optional MLOperatorOptions options = {});
  MLOperand lesser(MLOperand a,
                   MLOperand b,
                   optional MLOperatorOptions options = {});
  MLOperand lesserOrEqual(MLOperand a,
                          MLOperand b,
                          optional MLOperatorOptions options = {});
  MLOperand logicalNot(MLOperand a, optional MLOperatorOptions options = {});
  MLOperand logicalAnd(MLOperand a,
                       MLOperand b,
                       optional MLOperatorOptions options = {});
  MLOperand logicalOr(MLOperand a,
                      MLOperand b,
                      optional MLOperatorOptions options = {});
  MLOperand logicalXor(MLOperand a,
                       MLOperand b,
                       optional MLOperatorOptions options = {});
  MLOperand isNaN(MLOperand a, optional MLOperatorOptions options = {});
  MLOperand isInfinite(MLOperand a, optional MLOperatorOptions options = {});
};

dictionary MLLogicalNotSupportLimits {
  MLTensorLimits a;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLBinarySupportLimits equal;
  MLBinarySupportLimits notEqual;
  MLBinarySupportLimits greater;
  MLBinarySupportLimits greaterOrEqual;
  MLBinarySupportLimits lesser;
  MLBinarySupportLimits lesserOrEqual;
  MLLogicalNotSupportLimits logicalNot;
  MLBinarySupportLimits logicalAnd;
  MLBinarySupportLimits logicalOr;
  MLBinarySupportLimits logicalXor;
  MLLogicalNotSupportLimits isNaN;
  MLLogicalNotSupportLimits isInfinite;
};
引数:

戻り値: MLOperand。 二つの入力テンソルを要素ごとに比較した結果を含む出力テンソル。

equal()/notEqual()/greater()/greaterOrEqual()/lesser()/lesserOrEqual() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
a 任意 "float32", "float16", "int32" N 0 から 5
b 同じ型 a "float32", "float16", "int32" N 0 から 5
出力 "uint8" "uint8" N 0 から 5
logicalNot() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
a "uint8" "uint8" N 0 から 5
出力 "uint8" "uint8" N 0 から 5
logicalAnd()/logicalOr()/logicalXor() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
a "uint8" "uint8" N 0 から 5
b 同じ型 a "uint8" N 0 から 5
出力 "uint8" "uint8" N 0 から 5
isNaN()/isInfinite() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
a "float32", "float16", "bfloat16", "float8e4m3" "float32", "float16" N 0 から 5
出力 "uint8" "uint8" N 0 から 5

注: "float8e4m3" には無限大の表現がないため、 isInfinite() は、このデータ型のオペランドのすべての要素に対してゼロを返す。 isNaN() は、他の浮動小数点データ型と同様に、 "float8e4m3" の NaN 符号化を検出する。

MLLogicalNotSupportLimits には次のメンバーがある:

a, 型は MLTensorLimits

a オペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には要素ごとの論理演算用の次のメンバーがある:

equal, 型は MLBinarySupportLimits

equal() 演算子のサポート制限。

notEqual, 型は MLBinarySupportLimits

notEqual() 演算子のサポート制限。

greater, 型は MLBinarySupportLimits

greater() 演算子のサポート制限。

greaterOrEqual, 型は MLBinarySupportLimits

greaterOrEqual() 演算子のサポート制限。

lesser, 型は MLBinarySupportLimits

lesser() 演算子のサポート制限。

lesserOrEqual, 型は MLBinarySupportLimits

lesserOrEqual() 演算子のサポート制限。

logicalNot, 型は MLLogicalNotSupportLimits

logicalNot() 演算子のサポート制限。

logicalAnd, 型は MLBinarySupportLimits

logicalAnd() 演算子のサポート制限。

logicalOr, 型は MLBinarySupportLimits

logicalOr() 演算子のサポート制限。

logicalXor, 型は MLBinarySupportLimits

logicalXor() 演算子のサポート制限。

isNaN, 型は MLLogicalNotSupportLimits

isNaN() 演算子のサポート制限。

isInfinite, 型は MLLogicalNotSupportLimits

isInfinite() 演算子のサポート制限。

演算の種類:
greaterOrEqual() および lesserOrEqual() の各演算は、logicalNot()、 lesser()、 および greater() の演算を使用して実装できるが(つまり builder.greaterOrEqual(a, b) は builder.logicalNot(builder.lesser(a, b)))、NaN の場合を処理し、 二重の比較を回避して性能を向上させるために、個別に定義されている。
文字列 op、MLOperand a、オプションの MLOperand b、および MLOperatorOptions options を与えて 要素ごとの 論理演算を作成するには、次の手順を実行する:
  1. Assert: op は "equal"、"notEqual"、"greater"、 "greaterOrEqual"、"lesser"、"lesserOrEqual"、"logicalNot"、"logicalAnd"、"logicalOr"、 "logicalXor"、"isNaN"、"isInfinite" のいずれかである。

  2. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  3. オペランドを検証する際に this と a を与えた結果が false の場合、送出するのは TypeError である。

  4. op が "logicalNot"、"logicalAnd"、"logicalOr"、"logicalXor" のいずれかの場合:

    1. a のdataType が "uint8" でない 場合、送出するのは TypeError である。

  5. op が "isNaN"、"isInfinite" のいずれかの場合:

    1. a のdataType が « "float32"、 "float16", "bfloat16", "float8e4m3" » のいずれでもない場合、送出するのは TypeError である。

  6. b が渡された場合:

    1. オペランドを検証する際に this と b を与えた結果が false の場合、送出するのは TypeError である。

    2. a のdataType が b のdataType と等しくない場合、送出するのは TypeError である。

    3. outputShape を、a の形状と b の形状を双方向にブロードキャストした結果とする。それが 失敗を返した場合、送出するのは TypeError である。

  7. そうでない場合:

    1. outputShape を a の形状のクローン とする。

  8. descriptor を、"uint8" と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  9. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と descriptor を与えた結果とする。

    2. operator を、a、(b が渡された場合は)b、 および options を与えた op 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を a と(b が 渡された場合は)b に設定する。

    5. operator の出力を output に設定する。

  10. output を返す。

要素ごとの論理演算アルゴリズムは、次のように要素ごとの論理演算を作成する 手順を呼び出す。
equal(a, b, options) メソッドの手順は次のとおり:
  1. output を、"equal"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

notEqual(a, b, options) メソッドの手順は次のとおり:
  1. output を、"notEqual"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

greater(a, b, options) メソッドの手順は次のとおり:
  1. output を、"greater"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

greaterOrEqual(a, b, options) メソッドの手順は次のとおり:
  1. output を、"greaterOrEqual"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

lesser(a, b, options) メソッドの手順は次のとおり:
  1. output を、"lesser"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

lesserOrEqual(a, b, options) メソッドの手順は次のとおり:
  1. output を、"lesserOrEqual"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

logicalNot(a, options) メソッドの手順は次のとおり:
  1. output を、"logicalNot"、a、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

logicalAnd(a, b, options) メソッドの手順は次のとおり:
  1. output を、"logicalAnd"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

logicalOr(a, b, options) メソッドの手順は次のとおり:
  1. output を、"logicalOr"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

logicalXor(a, b, options) メソッドの手順は次のとおり:
  1. output を、"logicalXor"、a、b、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

isNaN(a, options) メソッドの 手順は次のとおり:
  1. output を、"isNaN"、a、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

isInfinite(a, options) メソッドの手順は次のとおり:
  1. output を、"isInfinite"、a、および options を与えて要素ごとの論理 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

8.9.15. 要素ごとの単項演算

入力テンソルに対して要素ごとの単項演算を計算する。
partial interface MLGraphBuilder {
  MLOperand abs(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand ceil(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand cos(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand erf(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand exp(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand floor(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand identity(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand log(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand neg(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand reciprocal(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand roundEven(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand sin(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand sign(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand sqrt(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand tan(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits abs;
  MLSingleInputSupportLimits ceil;
  MLSingleInputSupportLimits cos;
  MLSingleInputSupportLimits erf;
  MLSingleInputSupportLimits exp;
  MLSingleInputSupportLimits floor;
  MLSingleInputSupportLimits identity;
  MLSingleInputSupportLimits log;
  MLSingleInputSupportLimits neg;
  MLSingleInputSupportLimits reciprocal;
  MLSingleInputSupportLimits roundEven;
  MLSingleInputSupportLimits sin;
  MLSingleInputSupportLimits sign;
  MLSingleInputSupportLimits sqrt;
  MLSingleInputSupportLimits tan;
};
引数:

戻り値: MLOperand。 入力テンソルに対する要素ごとの 単項演算の結果を含む出力テンソル。出力 テンソルの形状は入力テンソルの形状と同じである。

abs()/neg() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16", "int64", "int32", "int8" "float32", "float16", "int32" N 0 から 5
出力 同じ型 input "float32", "float16", "int32" 同じランク input 0 から 5
ceil()/cos()/erf()/exp()/floor()/log()/reciprocal()/roundEven()/sin()/sqrt()/tan() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
出力 同じ型 input "float32", "float16" 同じランク input 0 から 5
identity() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input 任意 "float32", "float16", "int32" N 0 から 5
出力 同じ型 input "float32", "float16", "int32" 同じランク input 0 から 5
sign() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16", "int64", "int32", "int8" "float32", "float16", "int32" N 0 から 5
出力 同じ型 input "float32", "float16", "int32" 同じランク input 0 から 5

MLOpSupportLimits には要素ごとの単項演算用の次のメンバーがある:

abs, 型は MLSingleInputSupportLimits

abs() 演算子のサポート制限。

ceil, 型は MLSingleInputSupportLimits

ceil() 演算子のサポート制限。

cos, 型は MLSingleInputSupportLimits

cos() 演算子のサポート制限。

erf, 型は MLSingleInputSupportLimits

erf() 演算子のサポート制限。

exp, 型は MLSingleInputSupportLimits

exp() 演算子のサポート制限。

floor, 型は MLSingleInputSupportLimits

floor() 演算子のサポート制限。

identity, 型は MLSingleInputSupportLimits

identity() 演算子のサポート制限。

log, 型は MLSingleInputSupportLimits

log() 演算子のサポート制限。

neg, 型は MLSingleInputSupportLimits

neg() 演算子のサポート制限。

reciprocal, 型は MLSingleInputSupportLimits

reciprocal() 演算子のサポート制限。

roundEven, 型は MLSingleInputSupportLimits

roundEven() 演算子のサポート制限。

sin, 型は MLSingleInputSupportLimits

sin() 演算子のサポート制限。

sign, 型は MLSingleInputSupportLimits

sign() 演算子のサポート制限。

sqrt, 型は MLSingleInputSupportLimits

sqrt() 演算子のサポート制限。

tan, 型は MLSingleInputSupportLimits

tan() 演算子のサポート制限。

演算の種類:
文字列 op、MLOperand input、オプションのリスト allowedDataTypes、および options を与えて、次の 手順を実行して要素ごとの 単項演算を作成する:
  1. Assert: op は "abs"、"ceil"、"cos"、"erf"、"exp"、 "floor"、"identity"、"log"、"neg"、"reciprocal"、"roundEven"、"sin"、"sign"、"sqrt"、"tan" のいずれかである。

  2. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  3. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  4. allowedDataTypes が与えられており、input のdataType を含まない 場合、送出するのは TypeError である。

  5. グラフ接続を作成する:

    1. output を、input を与えて MLOperand をコピーした結果とする。

    2. operator を、options を与えた op 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  6. output を返す。

要素ごとの単項演算アルゴリズムは、次のように要素ごとの単項演算を作成する手順を 呼び出す。
abs(input, options) メソッドの 手順は次のとおり:
  1. output を、"abs"、input、« "float32"、 "float16", "bfloat16"、 "int64"、 "int32"、 "int8" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

ceil(input, options) メソッドの 手順は次のとおり:
  1. output を、"ceil"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

cos(input, options) メソッドの 手順は次のとおり:
  1. output を、"cos"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

erf(input, options) メソッドの 手順は次のとおり:
  1. output を、"erf"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

exp(input, options) メソッドの 手順は次のとおり:
  1. output を、"exp"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

floor(input, options) メソッドの 手順は次のとおり:
  1. output を、"floor"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

identity(input, options) メソッドの手順は次のとおり:
  1. output を、"identity"、input、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

log(input, options) メソッドの 手順は次のとおり:
  1. output を、"log"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

neg(input, options) メソッドの 手順は次のとおり:
  1. output を、"neg"、input、« "float32"、 "float16", "bfloat16"、 "int64"、 "int32"、 "int8" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

reciprocal(input, options) メソッドの手順は次のとおり:
  1. output を、"reciprocal"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

roundEven(input, options) メソッドの手順は次のとおり:
  1. output を、"roundEven"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

sin(input, options) メソッドの 手順は次のとおり:
  1. output を、"sin"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

sign(input, options) メソッドの 手順は次のとおり:
  1. output を、"sign"、input、« "float32"、 "float16", "bfloat16"、 "int64"、 "int32"、 "int8" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

sqrt(input, options) メソッドの 手順は次のとおり:
  1. output を、"sqrt"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

tan(input, options) メソッドの 手順は次のとおり:
  1. output を、"tan"、input、« "float32"、 "float16", "bfloat16" »、および options を与えて要素ごとの単項 演算を作成した結果とする。

    1. それがエラーを送出した場合、そのエラーを再度送出する。

  2. output を返す。

sign() 演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、ユーザー エージェントは通常、より効率的な実装を備えています。この分解は説明のための例であり、 参照実装ではありません。アルゴリズムや中間結果の精度を規定するものでは ありません。基盤となるプラットフォームが演算を直接サポートしていない場合、 この分解を実装の指針となるテンプレートとして使用できます。
function sign(builder, input, options) {
  const zero = builder.constant(input.dataType, 0);
  const positiveOne = builder.constant(input.dataType, 1);
  const negativeOne = builder.constant(input.dataType, -1);

  return builder.where(
    builder.greater(input, zero),
    positiveOne,
    builder.where(builder.lesser(input, zero), negativeOne, zero));
}

8.9.16. dequantizeLinear

スケールとゼロポイントバイアスを使用して、量子化された整数または低精度浮動小数点のテンソルを浮動小数点テンソルに逆量子化する。このとき、 output = (input - zeroPoint) * scaleとなる。 scale および zeroPoint テンソルは、 input テンソルより小さくてもよい。これは、これらのテンソルが ブロック単位でブロードキャスト可能であるためである。 input および zeroPoint の値は、減算前にデータ型を変換される。変換先の dataType は scale の型であり、演算もそのデータ型で行われる。
partial interface MLGraphBuilder {
  MLOperand dequantizeLinear(MLOperand input,
                             MLOperand scale,
                             MLOperand zeroPoint,
                             optional MLOperatorOptions options = {});
};

dictionary MLQuantizeDequantizeLinearSupportLimits {
  MLTensorLimits input;
  MLTensorLimits scale;
  MLTensorLimits zeroPoint;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLQuantizeDequantizeLinearSupportLimits dequantizeLinear;
};
引数:

戻り値: MLOperand。 逆量子化された値を含む出力テンソル。

dequantizeLinear() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "uint8", "int8", "uint32", "int32", "float8e4m3" "uint8", "int8" N 0 から 5
scale "float32", "float16", "bfloat16" "float32", "float16" 同じランク input 0 から 5
zeroPoint 同じ型 input "uint8", "int8", "int32" 同じランク input 0 から 5
出力 同じ型 scale "float32", "float16" 同じランク input 0 から 5

MLQuantizeDequantizeLinearSupportLimits には次のメンバーがある:

input, 型は MLTensorLimits

入力オペランドの MLTensorLimits。

scale, 型は MLTensorLimits

スケールオペランドの MLTensorLimits。

zeroPoint, 型は MLTensorLimits

ゼロポイントオペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には dequantizeLinear() 用の次のメンバーがある:

dequantizeLinear, 型は MLQuantizeDequantizeLinearSupportLimits

dequantizeLinear() 演算子のサポート制限。

dequantizeLinear(input, scale, zeroPoint, options) メソッドの手順は次のとおり:
  1. this.[[hasBuilt]] が true の場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、scale、および zeroPoint のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. scale のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  5. zeroPoint のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  6. zeroPoint のdataType が input のdataType と等しくない場合、送出するのは TypeError である。

  7. scale のランクまたは zeroPoint のランクが input のランクと等しくない場合、送出するのは TypeError である。

  8. scale の形状が zeroPoint の形状と等しくない場合、送出するのは TypeError である。

  9. scale の形状と input の形状をブロック単位でブロードキャストした結果が false の場合、送出するのは TypeError である。

  10. zeroPoint の形状と input の形状をブロック単位でブロードキャストした結果が false の場合、送出するのは TypeError である。

  11. outputDescriptor を、scale のdataType と input の形状を与えてMLOperandDescriptor を作成した結果とする。

  12. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と outputDescriptor を与えた結果とする。

    2. operator を、input、scale、zeroPoint、 および options を与えた "dequantizeLinear" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  13. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function dequantizeLinear(builder, input, scale, zeroPoint, options) {
  // output = (input - zeroPoint) * scale
  const floatInput = builder.cast(input, scale.dataType);
  const floatZeroPoint = builder.cast(zeroPoint, scale.dataType);
  const upsampledScale = blockwiseExpand(builder, scale, input.shape);
  const upsampledZeroPoint =
    blockwiseExpand(builder, floatZeroPoint, input.shape);
  return builder.mul(
    builder.sub(floatInput, upsampledZeroPoint), upsampledScale);
}

function blockwiseExpand(builder, input, outputShape) {
  // Given the original input and a desired output shape, this expands each axis
  // by repeating the block the number of times per that axis. Though, backend
  // implementations might have much more efficient upsampling operators that
  // can accept multiple dimensions to upsample all dimensions at once by
  // integer multiples (like tile) using nearest neighbor resampling:
  // output = resample(scale, {sizes: input.shape})

  let output = input;

  for (let axis = 0; axis < input.shape.length; ++axis) {
    const oldShape = output.shape;
    const oldDimensionLength = oldShape[axis];
    const newDimensionLength = outputShape[axis];

    if (newDimensionLength != oldDimensionLength) {
      // Since tile/expand can only accept repetitions of entire dimension
      // slices (not repeating individual elements along an axis), temporarily
      // reshape the tensor to enable them to broadcast the elements up to the
      // full block size, utilizing an inserted dimension of size 1.
      const elementRepeatCount = newDimensionLength / oldDimensionLength;
      const flattenedShape = getFlattenedShapeAroundAxis(oldShape, axis);
      const unexpandedShape =
        [flattenedShape[0], flattenedShape[1], 1, flattenedShape[2]];
      const expandedShape = [
        flattenedShape[0],
        flattenedShape[1],
        elementRepeatCount,
        flattenedShape[2]
      ];
      const reshapedInput = builder.reshape(output, unexpandedShape);
      output = builder.expand(reshapedInput, expandedShape);

      let newShape = [...oldShape];
      newShape[axis] = newDimensionLength;
      output = builder.reshape(output, newShape);
    }
  }

  return output;
}

// Compute the flattened shape before and after the given axis, yielding a
// 3-element list: e.g.
// - inputShape = [2,3,4,5,6] with axis = 2 yields shape [6,4,30].
// - inputShape = [4] with axis = 0 yields shape [1,4,1].
function getFlattenedShapeAroundAxis(inputShape, axis) {
  axis = Math.max(Math.min(axis, inputShape.length - 1), 0);
  const shapeBefore = inputShape.slice(0, axis);
  const shapeAfter = inputShape.slice(axis + 1, inputShape.length);
  const countBefore = shapeBefore.reduce((a, b) => a * b, 1);
  const countAfter = shapeAfter.reduce((a, b) => a * b, 1);
  return [countBefore, inputShape[axis], countAfter];
}

8.9.17. quantizeLinear

スケールとゼロポイントバイアスを使用して、浮動小数点テンソルを整数または低精度浮動小数点のテンソルに量子化する(例えば、"uint8" の場合は output = clamp(roundEven(input / scale) + zeroPoint, 0, 255) となり、クランプの上下限は出力データ型の範囲となる)。 scale と zeroPoint テンソルは、 input テンソルより小さくてもよい。これは、これらのテンソルが ブロック単位でブロードキャストされるためである。 zeroPoint の値は、データ型を変換される。変換先の dataType は input の型であり、演算もそのデータ型で行われる。その後、結果の dataType を zeroPointの型に変換する。

出力データ型が "float8e4m3"などの浮動小数点データ型の場合、スケールを変更した値を整数に丸めたり、クランプしたりしない。代わりに、 output = cast(input / scale + cast(zeroPoint, input.dataType), zeroPoint.dataType)とする。このとき、最も近い表現可能な値への丸めと範囲外の値の飽和処理は、 cast()の動作に従う。

注: "float8e4m3" への量子化は通常は対称であり、その場合、 zeroPoint は、 scaleと同じ形状を持つ、すべての要素がゼロのテンソルとなる。

partial interface MLGraphBuilder {
  MLOperand quantizeLinear(MLOperand input,
                           MLOperand scale,
                           MLOperand zeroPoint,
                           optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLQuantizeDequantizeLinearSupportLimits quantizeLinear;
};
引数:

戻り値: MLOperand。 量子化された値を含む出力テンソル。

quantizeLinear() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
scale 同じ型 input "float32", "float16" 同じランク input 0 から 5
zeroPoint "uint8", "int8", "uint32", "int32", "float8e4m3" "uint8", "int8" 同じランク input 0 から 5
出力 同じ型 zeroPoint "uint8", "int8" 同じランク input 0 から 5

MLOpSupportLimits には quantizeLinear() 用の次のメンバーがある:

quantizeLinear, 型は MLQuantizeDequantizeLinearSupportLimits

quantizeLinear() 演算子のサポート制限。

quantizeLinear(input, scale, zeroPoint, options) メソッドの手順は次のとおり:
  1. this.[[hasBuilt]] が true の場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、scale、および zeroPoint のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. scale のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  5. scale のdataType が input のdataType と等しくない場合、送出するのは TypeError である。

  6. zeroPoint のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  7. scale のランクまたは zeroPoint のランクが input のランクと等しくない場合、送出するのは TypeError である。

  8. scale の形状が zeroPoint の形状と等しくない場合、送出するのは TypeError である。

  9. scale の形状と input の形状をブロック単位でブロードキャストした結果が false の場合、送出するのは TypeError である。

  10. zeroPoint の形状と input の形状をブロック単位でブロードキャストした結果が false の場合、送出するのは TypeError である。

  11. outputDescriptor を、zeroPoint のdataType と input の形状を与えてMLOperandDescriptor を作成した結果とする。

  12. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と outputDescriptor を与えた結果とする。

    2. operator を、input、scale、zeroPoint、 および options を与えた "quantizeLinear" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  13. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function quantizeLinear(builder, input, scale, zeroPoint, options) {
  // For integer output types:
  //   output = clamp(roundEven(input / scale) + zeroPoint, min, max)
  // where [min, max] is the range of the output data type.
  // For floating point output types such as 'float8e4m3':
  //   output = cast(input / scale + cast(zeroPoint, input.dataType),
  //                 zeroPoint.dataType)
  // Note blockwiseExpand is defined in dequantizeLinear.

  const floatZeroPoint = builder.cast(zeroPoint, scale.dataType);
  const upsampledScale = blockwiseExpand(builder, scale, input.shape);
  const upsampledZeroPoint =
    blockwiseExpand(builder, floatZeroPoint, input.shape);
  const scaledInput = builder.div(input, upsampledScale);

  if (zeroPoint.dataType == 'float8e4m3') {
    return builder.cast(
      builder.add(scaledInput, upsampledZeroPoint), zeroPoint.dataType);
  }

  const integerRanges = {
    'int8': [-128, 127],
    'uint8': [0, 255],
    'int32': [-2147483648, 2147483647],
    'uint32': [0, 4294967295]
  };
  const [minValue, maxValue] = integerRanges[zeroPoint.dataType];
  const quantizedInput = builder.roundEven(scaledInput);
  const zeroPointAdjustedInput =
    builder.add(quantizedInput, upsampledZeroPoint);
  const clampedInput = builder.clamp(
    zeroPointAdjustedInput, {'minValue': minValue, 'maxValue': maxValue});
  return builder.cast(clampedInput, zeroPoint.dataType);
}

8.9.18. elu

入力テンソルに対して要素ごとに指数線形ユニット 関数(ELU)を計算する。計算は次の式に従う: max(0, x) + alpha * (exp(min(0, x)) - 1)。
dictionary MLEluOptions : MLOperatorOptions {
  double alpha = 1;
};

partial interface MLGraphBuilder {
  MLOperand elu(MLOperand input, optional MLEluOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits elu;
};

MLEluOptions には次のメンバーがある:

alpha, 型は double、既定値は 1

スカラー乗数。

引数:

戻り値:

elu() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
出力 同じ型 input "float32", "float16" 同じランク input 0 から 5

MLOpSupportLimits には elu() 用の次のメンバーがある:

elu, 型は MLSingleInputSupportLimits

elu() 演算子のサポート制限。

elu(input, options) メソッドの 手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. options.alpha を、options.alpha を input のdataType にキャストした結果に設定する。

  5. グラフ接続を作成する:

    1. output を、input を与えて MLOperand をコピーした結果とする。

    2. operator を、options を与えた "elu" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  6. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function elu(builder, input, options) {
  return builder.add(
    builder.max(builder.constant(input.dataType, 0), input),
    builder.mul(
      builder.constant(input.dataType, options.alpha),
      builder.sub(
        builder.exp(builder.min(builder.constant(input.dataType, 0), input)),
        builder.constant(input.dataType, 1))));
}

8.9.19. expand

入力テンソルのサイズ 1 の任意の次元を、新しい形状に従ってより大きなサイズに拡張する。この拡張は [numpy-broadcasting-rule] に従う。入力テンソルは新しい形状に単方向にブロードキャスト可能でなければならない。各 次元のサイズは 1 であるか、新しい形状に従って対応する出力次元のサイズと 一致しなければならない。
partial interface MLGraphBuilder {
  MLOperand expand(MLOperand input,
                   sequence<[EnforceRange] unsigned long> newShape,
                   optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits expand;
};
引数:

戻り値: MLOperand。 サイズが拡張された形状のテンソル。

expand() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input 任意 "float32", "float16", "int32" N 0 から 5
出力 同じ型 input "float32", "float16", "int32" N 0 から 5

MLOpSupportLimits には expand() 用の次のメンバーがある:

expand, 型は MLSingleInputSupportLimits

expand() 演算子のサポート制限。

expand(input, newShape, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. outputShape を、input の形状と newShape を単方向にブロードキャストした結果とする。

    1. それが失敗を返した場合、送出するのは TypeError である。

  4. outputShape のサイズが 出力テンソルの許可されるランクでない場合(この表による)、送出するのは TypeError である。

  5. outputDescriptor を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  6. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と outputDescriptor を与えた結果とする。

    2. operator を、input、newShape、および options を与えた "expand" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  7. output を返す。

8.9.20. gather

インデックスに従って、指定された軸に沿って入力テンソルの値を収集する。
dictionary MLGatherOptions : MLOperatorOptions {
  [EnforceRange] unsigned long axis = 0;
};

partial interface MLGraphBuilder {
  MLOperand gather(MLOperand input,
                   MLOperand indices,
                   optional MLGatherOptions options = {});
};

dictionary MLGatherSupportLimits {
  MLTensorLimits input;
  MLTensorLimits indices;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLGatherSupportLimits gather;
};

MLGatherOptions には次のメンバーがある:

axis, 型は unsigned long、既定値は 0

値を収集する軸。その値は [0, N-1] の範囲内でなければならず、ここで N は入力テンソルのランクで ある。

引数:

戻り値: MLOperand。 ランクが input のランク + indices のランク - 1 に等しい出力 N 次元テンソル。

indices パラメーターは、gather() のグラフ構築時には許可される範囲にクランプできない。入力値が 実行時まで判明しないためである。実装は、基盤となるプラットフォームが指定されたクランプ動作を提供しない場合、 コンパイル済みグラフに clamp() を導入できる。同様に、基盤となるプラットフォームが負のインデックスをサポートしない場合、実装は コンパイル済みグラフに演算を導入して、次元の末尾から数える負のインデックスを正の インデックスに変換できる。
gather() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input 任意 "float32", "float16", "int32", "int8", "uint8" 1 から N 1 から 5
indices "int32", "uint32", "int64" "int32" N 0 から 5
出力 同じ型 input "float32", "float16", "int32", "int8", "uint8" N 0 から 5

MLGatherSupportLimits には次のメンバーがある:

input, 型は MLTensorLimits

入力オペランドの MLTensorLimits。

indices, 型は MLTensorLimits

インデックスオペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には gather() 用の次のメンバーがある:

gather, 型は MLGatherSupportLimits

gather() 演算子のサポート制限。

gather(input, indices, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input または indices のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. indices のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. inputShape を input の形状、inputRank を input のランクとする。

  5. indicesShape を indices の形状とする。

  6. axis を options.axis とする。

  7. axis が inputRank 以上の場合、送出するのは TypeError である。

  8. dimCount を 0 とする。

  9. outputRank を 0 とする。

  10. outputShape を空のリストとする。

  11. inputShape の各 size について:

    1. dimCount が axis と等しい場合、中断する。

    2. outputShape[dimCount] を size に設定する。

    3. dimCount を 1 増やす。

  12. outputRank を dimCount に設定する。

  13. dimCount を 0 とする。

  14. indicesShape の各 size について:

    1. outputShape[outputRank + dimCount] を size に設定する。

    2. dimCount を 1 増やす。

  15. outputRank を outputRank + dimCount に設定する。

  16. dimCount を 0 とする。

  17. inputShape の各 size について:

    1. dimCount が axis 以下の場合、次の反復に進む。

    2. outputShape[outputRank + dimCount - axis - 1] を size に設定する。

    3. dimCount を 1 増やす。

  18. desc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  19. グラフ接続を作成する:

    1. output を、desc を与えてMLOperand を作成した結果とする。

    2. operator を、input、indices、および options を与えた "gather" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input と indices に設定する。

    5. operator の出力を output に設定する。

  20. output を返す。

さまざまなスライス方式で gather がどのように動作するかを示す例。
// 形状 [4,3] の input:
//   [[ 0,  1,  2],
//    [10, 11, 12],
//    [20, 21, 22],
//    [30, 31, 32]]
const input = builder.constant(
  {dataType: 'float32', shape: [4, 3]},
  new Float32Array([0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32]));

// axis = 0(既定値)
// 形状 [2] の indices:
//   [3,1]
// 形状 [2,3] の output:
//   [[30, 31, 32],
//    [10, 11, 12]]

const indices1 =
  builder.constant({dataType: 'uint32', shape: [2]}, new Uint32Array([3, 1]));

const output1 = builder.gather(input, indices1);

// axis = 1
// 形状 [3] の indices:
//   [2,1,1]
// 形状 [4,3] の output:
//   [[ 2,  1,  1],
//    [12, 11, 11],
//    [22, 21, 21],
//    [32, 31, 31]]

const indices2 = builder.constant(
  {dataType: 'uint32', shape: [3]}, new Uint32Array([2, 1, 1]));

const output2 = builder.gather(input, indices2, {axis: 1});

// axis = 1
// 形状 [2,2] の indices:
//   [[0, 1],
//    [1, 2]]
// 形状 [4,2,2] の output:
//   [[[ 0,  1], [ 1,  2]],
//    [[10, 11], [11, 12]],
//    [[20, 21], [21, 22]],
//    [[30, 31], [31, 32]]]

const indices3 = builder.constant(
  {dataType: 'uint32', shape: [2, 2]}, new Uint32Array([0, 1, 1, 2]));

const output3 = builder.gather(input, indices3, {axis: 1});

8.9.21. gatherElements

インデックスに従って、指定された軸に沿って入力テンソルの値を収集する。
partial interface MLGraphBuilder {
  MLOperand gatherElements(MLOperand input,
                           MLOperand indices,
                           optional MLGatherOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLGatherSupportLimits gatherElements;
};
引数:

戻り値: MLOperand。 ランクが input の ランクと等しい出力 N 次元テンソル。

gatherElements() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input 任意 "float32", "float16", "int32" 1 から N 1 から 5
indices "int32", "uint32", "int64" "int32" 同じランク input 1 から 5
出力 同じ型 input "float32", "float16", "int32" 同じランク input 1 から 5

MLOpSupportLimits には gatherElements() 用の次のメンバーがある:

gatherElements, 型は MLGatherSupportLimits

gatherElements() 演算子のサポート制限。

indices パラメーターは、gatherElements() のグラフ構築時には許可される範囲にクランプできない。入力値が 実行時まで判明しないためである。実装は、基盤となるプラットフォームが指定されたクランプ動作を提供しない場合、 コンパイル済みグラフに clamp() を導入できる。同様に、基盤となるプラットフォームが負のインデックスをサポートしない場合、実装は コンパイル済みグラフに演算を導入して、次元の末尾から数える負のインデックスを正の インデックスに変換できる。
gatherElements(input, indices, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input または indices のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. indices のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. input または indices のいずれかのランクが それぞれの許可されるランクでない場合、送出するのは TypeError である。

  5. axis を options.axis とする。

  6. axis が input のランク以上の場合、送出するのは TypeError である。

  7. indicesShapeExpected を input の形状のコピーとする。

  8. indicesShapeExpected[axis] を indices の形状[axis] に設定する。

  9. indices の形状が indicesShapeExpected と等しくない 場合、送出するのは TypeError である。

  10. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、input、indices、および options を与えた "gatherElements" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input と indices に設定する。

    5. operator の出力を output に設定する。

  11. output を返す。

さまざまなスライス方式で gatherElements がどのように動作するかを示す例。
// 形状 [4,3] の input:
//   [[ 0,  1,  2],
//    [10, 11, 12],
//    [20, 21, 22],
//    [30, 31, 32]]
// 形状 [2,3] の indices:
//   [[3, 1, 1],
//    [2, 0, 3]]
// axis = 0(既定値)
// 形状 [2,3] の output:
//   [[30, 11, 12],
//    [20,  1, 32]]

const input1 = builder.constant(
  {dataType: 'float32', shape: [4, 3]},
  new Float32Array([0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32]));

const indices1 = builder.constant(
  {dataType: 'uint32', shape: [2, 3]},
  new Uint32Array([3, 1, 1, 2, 0, 3]));

const output1 = builder.gatherElements(input1, indices1);

// 形状 [4,3] の input:
//   [[ 0,  1,  2],
//    [10, 11, 12],
//    [20, 21, 22],
//    [30, 31, 32]]
// 形状 [4,1] の indices:
//   [[2],
//    [1],
//    [0],
//    [2]],
// axis = 1
// 形状 [4,1] の output:
//   [[ 2],
//    [11],
//    [20],
//    [32]]

const indices2 = builder.constant(
  {dataType: 'uint32', shape: [4, 1]},
  new Uint32Array([2, 1, 0, 2]));

const output2 = builder.gatherElements(input1, indices2, {axis: 1});

// 形状 [4,2,2] の input:
//   [[[  0,   1],
//     [ 10,  11]],
//    [[100, 101],
//     [110, 111]],
//    [[200, 201],
//     [210, 211]],
//    [[300, 301],
//     [310, 311]],]
// 形状 [1,2,2] の indices:
//   [[[0, 2],
//     [1, 3]]],
// axis = 0
// 形状 [1,2,2] の output:
//   [[[  0, 201],
//     [110, 311]]]

const inputData3 = new Float32Array(
  [0, 1, 10, 11, 100, 101, 110, 111, 200, 201, 210, 211, 300, 301, 310, 311]);

const input3 =
  builder.constant({dataType: 'float32', shape: [4, 2, 2]}, inputData3);

const indices3 = builder.constant(
  {dataType: 'uint32', shape: [1, 2, 2]},
  new Uint32Array([0, 2, 1, 3]));

const output3 = builder.gatherElements(input3, indices3, {axis: 0});

8.9.22. gatherND

インデックスに従って入力テンソルのスライスを収集する。
partial interface MLGraphBuilder {
  MLOperand gatherND(MLOperand input,
                     MLOperand indices,
                     optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLGatherSupportLimits gatherND;
};
引数:

戻り値: MLOperand。 ランクが input の ランク + indices の ランク - indices の 形状[-1] - 1 に等しい出力 N 次元テンソル。

gatherND() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input 任意 "float32", "float16", "int32", "int8", "uint8" 1 から N 1 から 5
indices "int32", "uint32", "int64" "int32" 1 から N 1 から 5
出力 同じ型 input "float32", "float16", "int32", "int8", "uint8" N 0 から 5

MLOpSupportLimits には gatherND() 用の次のメンバーがある:

gatherND, 型は MLGatherSupportLimits

gatherND() 演算子のサポート制限。

indices パラメーターは、gatherND() のグラフ構築時には許可される範囲にクランプできない。入力値が 実行時まで判明しないためである。実装は、基盤となるプラットフォームが指定されたクランプ動作を提供しない場合、 コンパイル済みグラフに clamp() を導入できる。同様に、基盤となるプラットフォームが負のインデックスをサポートしない場合、実装は コンパイル済みグラフに演算を導入して、次元の末尾から数える負のインデックスを正の インデックスに変換できる。
gatherND(input, indices, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input または indices のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. indices のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. input または indices のいずれかのランクが それぞれの許可されるランクでない場合、送出するのは TypeError である。

  5. inputShape を input の形状、inputRank を input のランクとする。

  6. indicesShape を indices の形状、indicesRank を indices のランクとする。

  7. input または indices のいずれかのランクが それぞれの許可されるランクでない場合、送出するのは TypeError である。

  8. indexableSize を indicesRank - 1 とする。

  9. coordinateSize を indicesShape[indexableSize] とする。

  10. coordinateSize が inputRank より大きい場合、送出するのは TypeError である。

  11. outputShape を空のリストとする。

  12. 0 から indexableSize までの範囲(上限を 含まない)の各 index について:

    1. indicesShape[index] を付加する先は outputShape である。

  13. coordinateSize から inputRank までの範囲 (上限を含まない)の各 index について:

    1. inputShape[index] を付加する先は outputShape である。

  14. outputDesc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  15. グラフ接続を作成する:

    1. output を、outputDesc を与えてMLOperand を作成した結果とする。

    2. operator を、input、indices、および options を与えた "gatherND" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input と indices に設定する。

    5. operator の出力を output に設定する。

  16. output を返す。

さまざまなスライス方式で gatherND がどのように動作するかを示す例。
// 形状 [2,2] の input:
//   [[0, 1],
//    [2, 3]]
// 形状 [3,2] の indices:
//   [[0, 0],
//    [1, 1],
//    [1, 0]]
// 形状 [3] の output:
//   [0, 3, 2]

const input1 = builder.constant(
  {dataType: 'float32', shape: [2, 2]},
  new Float32Array([0, 1, 2, 3]));

const indices1 = builder.constant(
  {dataType: 'uint32', shape: [3, 2]},
  new Uint32Array([0, 0, 1, 1, 1, 0]));

const output1 = builder.gatherND(input1, indices1);

// 形状 [2,2] の input:
//   [[0, 1],
//    [2, 3]]
// 形状 [2,1] の indices:
//   [[1],
//    [0]]
// 形状 [2,2] の output:
//   [[2, 3]    <= input の座標 [1, *] から取得した行 [2, 3]
//    [0, 1]]   <= input の座標 [0, *] から取得した行 [0, 1]

const indices2 = builder.constant(
  {dataType: 'uint32', shape: [2, 1]},
  new Uint32Array([1, 0]));

const output2 = builder.gatherND(input1, indices2);

// 形状 [2,2,2] の input:
//   [[[0, 1],
//     [2, 3]],
//    [[4, 5],
//     [6, 7]]]
// 形状 [2,2] の indices:
//   [[0, 1],
//    [1, 0]]
// 形状 [2,2] の output:
//   [[2, 3],   <= input の座標 [0, 1, *] から取得した行 [2, 3]
//    [4, 5]]   <= input の座標 [1, 0, *] から取得した行 [4, 5]

const input2 = builder.constant(
  {dataType: 'float32', shape: [2, 2, 2]},
  new Float32Array([0, 1, 2, 3, 4, 5, 6, 7]));

const indices3 = builder.constant(
  {dataType: 'uint32', shape: [2, 2]},
  new Uint32Array([0, 1, 1, 0]));

const output3 = builder.gatherND(input2, indices3);

// 形状 [2,2,2] の input:
//   [[[0, 1],
//     [2, 3]],
//    [[4, 5],
//     [6, 7]]]
// 形状 [3,1] の indices:
//   [[1],
//    [0],
//    [1]]
// 形状 [3,2,2] の output:
//   [[[4, 5],   <= input の座標 [1, *, *] から取得したブロック [[4, 5], [6, 7]]
//     [6, 7]],
//    [[0, 1],   <= input の座標 [0, *, *] から取得したブロック [[0, 1], [2, 3]]
//     [2, 3]],
//    [[4, 5],   <= input の座標 [1, *, *] から取得したブロック [[4, 5], [6, 7]]
//     [6, 7]]]

const indices4 = builder.constant(
  {dataType: 'uint32', shape: [3, 1]},
  new Uint32Array([1, 0, 1]));

const output4 = builder.gatherND(input2, indices4);

// 形状 [2,2,2] の input:
//   [[[0, 1],
//     [2, 3]],
//    [[4, 5],
//     [6, 7]]]
// 形状 [5,3] の indices:
//   [[0,0,1],
//    [0,1,0],
//    [1,0,0],
//    [1,1,0],
//    [1,1,1]]
// 形状 [5] の output:
//   [1,2,4,6,7]

const indices5 = builder.constant(
  {dataType: 'uint32', shape: [5, 3]},
  new Uint32Array([0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1]));

const output5 = builder.gatherND(input2, indices5);

8.9.23. gelu

入力テンソルのガウス 誤差線形ユニット関数(GELU)を計算する。計算は次の式に従う: 0.5 * x * (1 + erf(x / sqrt(2)))。
partial interface MLGraphBuilder {
  MLOperand gelu(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits gelu;
};
引数:

戻り値:

gelu() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
出力 同じ型 input "float32", "float16" 同じランク input 0 から 5

MLOpSupportLimits には gelu() 用の次のメンバーがある:

gelu, 型は MLSingleInputSupportLimits

gelu() 演算子のサポート制限。

gelu(input, options) メソッドの 手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、options を与えた "gelu" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function gelu(builder, input) {
  return builder.mul(
    builder.mul(input, builder.constant(input.dataType, 0.5)),
    builder.add(
      builder.constant(input.dataType, 1),
      builder.erf(builder.div(
        input, builder.sqrt(builder.constant(input.dataType, 2))))));
}

8.9.24. gemm

基本線形代数サブプログラムの 一般行列乗算を計算する。計算は次の式に従う: alpha * A * B + beta * C。ここで A は形状が [M, K] または [K, M] の二次元テンソル、B は形状が [K, N] または [N, K] の二次元テンソルであり、 C は形状 [M, N] に単方向にブロードキャスト可能である。A と B は計算前に任意で転置できる。
dictionary MLGemmOptions : MLOperatorOptions {
  MLOperand c;
  double alpha = 1.0;
  double beta = 1.0;
  boolean aTranspose = false;
  boolean bTranspose = false;
};

partial interface MLGraphBuilder {
  MLOperand gemm(MLOperand a, MLOperand b, optional MLGemmOptions options = {});
};

dictionary MLGemmSupportLimits {
  MLTensorLimits a;
  MLTensorLimits b;
  MLTensorLimits c;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLGemmSupportLimits gemm;
};

MLGemmOptions には次のメンバーがある:

c, 型は MLOperand

第三の入力テンソル。スカラーであるか、形状 [M, N] に単方向にブロードキャスト可能な形状 である。指定されない場合、c がスカラー 0.0 であるかのように計算する。

alpha, 型は double、既定値は 1.0

最初の入力に対する乗数。

beta, 型は double、既定値は 1.0

第三の入力 c に対する乗数。

aTranspose, 型は boolean、既定値は false

出力の計算前に最初の入力を転置するかどうかを示す。

bTranspose, 型は boolean、既定値は false

出力の計算前に二番目の入力を転置するかどうかを示す。

引数:

戻り値: MLOperand。 すべての入力の計算された積を含む、形状 [M, N] の出力二次元テンソル。

gemm() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
a "float32", "float16", "bfloat16" "float32", "float16" 2 2
b 同じ型 a "float32", "float16" 2 2
c 同じ型 a "float32", "float16" 0 から 2 0 から 2
出力 同じ型 a "float32", "float16" 2 2

MLGemmSupportLimits には次のメンバーがある:

a, 型は MLTensorLimits

a オペランドの MLTensorLimits。

b, 型は MLTensorLimits

b オペランドの MLTensorLimits。

c, 型は MLTensorLimits

c オペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には gemm() 用の次のメンバーがある:

gemm, 型は MLGemmSupportLimits

gemm() 演算子のサポート制限。

gemm(a, b, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と a または b のいずれかを与えた結果が false の場合、 送出するのは TypeError である。

  3. a または b のいずれかのdataType が それぞれの許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

  4. a または b のいずれかのランクが それぞれの許可されるランクでない場合、送出するのは TypeError である。

  5. options.alpha を、options.alpha を a のdataType にキャストした結果に設定する。

  6. options.beta を、options.beta を a のdataType にキャストした結果に設定する。

  7. shapeA を、a の形状のクローンとする。

  8. shapeB を、b の形状のクローンとする。

  9. options.aTranspose が true の場合、shapeA 内の項目の順序を反転する。

  10. options.bTranspose が true の場合、shapeB 内の項目の順序を反転する。

  11. shapeA[1] が shapeB[0] と等しくない場合、送出するのは TypeError である。

  12. options.c が存在する場合:

    1. それが形状 « shapeA[0], shapeB[1] » に単方向にブロードキャスト可能でない 場合、送出するのは TypeError である。

    2. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

  13. desc を、a のdataType と « shapeA[0], shapeB[1] » を与えてMLOperandDescriptor を作成した結果とする。

  14. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、options を与えた "gemm" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を a と b に設定する。

    5. options.c が存在する場合、それを operator の入力に追加する。

    6. operator の出力を output に設定する。

  15. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function gemm(builder, a, b, options) {
  if (options.aTranspose)
    a = builder.transpose(a);

  if (options.bTranspose)
    b = builder.transpose(b);

  let ab = builder.matmul(
    builder.mul(builder.constant(a.dataType, options.alpha), a), b);
  return (
    options.c ?
      builder.add(
        ab,
        builder.mul(builder.constant(a.dataType, options.beta), options.c)) :
      ab);
}

8.9.25. gru

Gated Recurrent Unit [GRU] リカレントネットワークは、update、reset、および new ゲートを使用して、ネットワークの時間シーケンス全体にわたって出力へ 引き継がれる出力状態を計算します。
enum MLGruWeightLayout {
  "zrn",  // update-reset-new ゲートの順序
  "rzn"   // reset-update-new ゲートの順序
};

enum MLRecurrentNetworkActivation {
  "relu",
  "sigmoid",
  "tanh"
};

enum MLRecurrentNetworkDirection {
  "forward",
  "backward",
  "both"
};

dictionary MLGruOptions : MLOperatorOptions {
  MLOperand bias;
  MLOperand recurrentBias;
  MLOperand initialHiddenState;
  boolean resetAfter = true;
  boolean returnSequence = false;
  MLRecurrentNetworkDirection direction = "forward";
  MLGruWeightLayout layout = "zrn";
  sequence<MLRecurrentNetworkActivation> activations;
};

partial interface MLGraphBuilder {
  sequence<MLOperand> gru(MLOperand input,
                          MLOperand weight,
                          MLOperand recurrentWeight,
                          [EnforceRange] unsigned long steps,
                          [EnforceRange] unsigned long hiddenSize,
                          optional MLGruOptions options = {});
};

dictionary MLGruSupportLimits {
  MLTensorLimits input;
  MLTensorLimits weight;
  MLTensorLimits recurrentWeight;
  MLTensorLimits bias;
  MLTensorLimits recurrentBias;
  MLTensorLimits initialHiddenState;
  MLTensorLimits output0;
  MLTensorLimits output1;
};

partial dictionary MLOpSupportLimits {
  MLGruSupportLimits gru;
};

MLGruOptions には次のメンバーがあります。

bias, 型は MLOperand

shape [numDirections, 3 * hiddenSize] の 2-D 入力バイアステンソル。テンソル shape の第 2 次元におけるバイアス ベクトルの順序は layout に従って指定されます。

recurrentBias, 型は MLOperand

shape [numDirections, 3 * hiddenSize] の 2-D リカレントバイアステンソル。テンソル shape の第 2 次元における バイアスベクトルの順序は layout に従って指定されます。

initialHiddenState, 型は MLOperand

shape [numDirections, batchSize, hiddenSize] の 3-D 初期隠れ状態テンソル。 指定されていない場合、実装は 0 で埋められたテンソルを使用しなければなりません。

resetAfter, 型は boolean、デフォルトは true

行列乗算の後または前に reset ゲートを適用するかどうかを示します。

returnSequence, 型は boolean、デフォルトは false

最後の時間ステップの出力に加えて、各時間ステップのすべての出力を含むシーケンス全体も 返すかどうかを示します。

direction, 型は MLRecurrentNetworkDirection、デフォルトは "forward"

入力シーケンスの処理方向。"both" に設定した場合、weight および bias テンソル shape の第 1 次元のサイズは 2 でなければならず、入力は 両方向に処理されます。

layout, 型は MLGruWeightLayout、デフォルトは "zrn"

GRU の内部ゲート、具体的には update (z)、reset (r)、および new (n) ゲートの weight および bias ベクトルの順序であり、weight および bias テンソル shape の 第 2 次元によって示されます。

activations, 型は sequence<MLRecurrentNetworkActivation>

一対の活性化関数を指定します。第 1 関数は update および reset ゲートに使用され、第 2 関数は new ゲートに使用されます。指定されていない場合、デフォルトはそれぞれ "sigmoid" および "tanh" 関数です。

引数:

戻り値: sequence<MLOperand>。 第 1 要素は shape [numDirections, batchSize, hiddenSize] の 3-D テンソルであり、ネットワークの最後の時間ステップからのセル 出力です。さらに、returnSequence が true に設定されている場合、第 2 要素は shape [steps, numDirections, batchSize, hiddenSize] の 4-D 出力テンソルであり、時間 シーケンス内の各時間ステップからのすべてのセル出力を含みます。

gru() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" 3 3
weight 同じ input "float32", "float16" 3 3
recurrentWeight 同じ input "float32", "float16" 3 3
bias 同じ input "float32", "float16" 2 2
recurrentBias 同じ input "float32", "float16" 2 2
initialHiddenState 同じ input "float32", "float16" 3 3
outputs[0] 同じ input "float32", "float16" 3 3
outputs[1] if returnSequence が true の場合 同じ input "float32", "float16" 4 4

MLGruSupportLimits には次のメンバーがあります。

input, 型は MLTensorLimits

input オペランドの MLTensorLimits。

weight, 型は MLTensorLimits

weight オペランドの MLTensorLimits。

recurrentWeight, 型は MLTensorLimits

recurrentWeight オペランドの MLTensorLimits。

bias, 型は MLTensorLimits

bias オペランドの MLTensorLimits。

recurrentBias, 型は MLTensorLimits

recurrentBias オペランドの MLTensorLimits。

initialHiddenState, 型は MLTensorLimits

initialHiddenState オペランドの MLTensorLimits。

output0, 型は MLTensorLimits

すべての出力オペランド[0]の MLTensorLimits。

output1, 型は MLTensorLimits

すべての出力オペランド[1]の MLTensorLimits。

MLOpSupportLimits には gru() 用の次のメンバーがあります。

gru, 型は MLGruSupportLimits

gru() 演算子のサポート制限。

gru(input, weight, recurrentWeight, steps, hiddenSize, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、weight、 recurrentWeight、options.bias (存在する場合)、options.recurrentBias (存在する場合)、および options.initialHiddenState (存在する場合)のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input、weight、または recurrentWeight のいずれかのdataType が それぞれの許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. input、weight、または recurrentWeight のいずれかのランクが それぞれの許可されるランクでない 場合、送出するのは TypeError である。

  5. input の形状[0] が steps と等しくない場合、送出するのは TypeError である。

  6. batchSize を input の形状[1] とする。

  7. inputSize を input の形状[2] とする。

  8. numDirections を、options.direction が "both" の場合は 2、それ以外の場合は 1 とする。

  9. weight の形状が « numDirections, 3 * hiddenSize, inputSize » と等しくない場合、送出するのは TypeError である。

  10. recurrentWeight の形状が « numDirections, 3 * hiddenSize, hiddenSize » と等しくない場合、送出するのは TypeError である。

  11. hiddenSize * 6 が有効な次元でない場合、送出するのは TypeError である。

    なぜ hiddenSize * 6 なのか? 一部の基盤プラットフォームでは、bias と recurrentBias を連結した 単一のバイアステンソルを使用する。そのため、3 * hiddenSize + 3 * hiddenSize も 有効な 次元でなければならない。
  12. options.bias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « numDirections, 3 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  13. options.recurrentBias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « numDirections, 3 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  14. options.initialHiddenState が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « numDirections, batchSize, hiddenSize » と等しくない場合、送出するのは TypeError である。

  15. options.activations が存在する場合:

    1. そのサイズが 2 でない場合、送出するのは TypeError である。

    2. activations を、options.activations のクローン とする。

  16. そうでない場合:

    1. activations を « "sigmoid", "tanh" » とする。

  17. 出力形状を計算する:

    1. desc0 を、input のdataType と « numDirections, batchSize, hiddenSize » を与えてMLOperandDescriptor を作成した結果とする。

    2. desc1 を、input のdataType と « steps, numDirections, batchSize, hiddenSize » を与えてMLOperandDescriptor を作成した結果とする。

      なぜ desc1 を無条件に作成するのか? 一部の基盤プラットフォームでは、returnSequence に関係なく シーケンス全体の出力テンソルを生成するため、desc1 も有効でなければならない。
  18. グラフ接続を作成する:

    1. operator を、weight、recurrentWeight、steps、 hiddenSize および options を与えた "gru" 演算用の演算子とする。

    2. output0 を、MLOperand を 作成する際に this と desc0 を与えた結果とする。

    3. options.returnSequence が true の場合:

      1. output1 を、MLOperand を 作成する際に this と desc1 を与えた結果とする。

      2. output を、リスト « output0, output1 » とする。

      3. output0.[[operator]] と output1.[[operator]] を operator に設定する。

    4. そうでない場合:

      1. output を、リスト « output0 » とする。

      2. output0.[[operator]] を operator に設定する。

    5. operator の入力を input、weight、および recurrentWeight に設定する。

    6. options.bias が存在する場合、それを operator の入力に追加する。

    7. options.recurrentBias が存在する場合、それを operator の入力に追加する。

    8. options.initialHiddenState が存在する場合、それを operator の入力に追加する。

    9. operator の活性化関数を activations のクローンに設定する。

    10. operator の出力を output に設定する。

  19. output を返す。

squeeze() ヘルパーを使用すると、この演算の動作は 以下のように他の演算を使用して一般的にエミュレートできますが、ユーザーエージェントは通常、 より効率的な実装を備えています。この分解は説明のための例であり、 参照実装ではありません。アルゴリズムや中間結果の精度を 規定するものではありません。基盤となるプラットフォームが演算を直接サポートしていない場合、この 分解を実装の指針となるテンプレートとして使用できます。
function gru(
  builder, input, weight, recurrentWeight, steps, hiddenSize, options) {
  const batchSize = input.shape[1];
  const inputSize = input.shape[2];
  const direction = options.direction || 'forward';
  const numDirections = (direction == 'both' ? 2 : 1);
  let hiddenState = options.initialHiddenState;

  if (!hiddenState) {
    const desc = {
      dataType: 'float32',
      shape: [numDirections, batchSize, hiddenSize]
    };
    const totalSize = numDirections * batchSize * hiddenSize;
    hiddenState = builder.constant(desc, new Float32Array(totalSize).fill(0));
  }

  let currentWeight = [];
  let currentRecurrentWeight = [];
  let currentBias = [];
  let currentRecurrentBias = [];
  let forwardSequence = null;
  let backwardSequence = null;
  let outputHidden = null;

  for (let dir = 0; dir < numDirections; ++dir) {
    currentWeight.push(squeeze(
      builder,
      builder.slice(weight, [dir, 0, 0], [1, 3 * hiddenSize, inputSize])));
    currentRecurrentWeight.push(squeeze(
      builder,
      builder.slice(
        recurrentWeight, [dir, 0, 0], [1, 3 * hiddenSize, hiddenSize])));
    currentBias.push(
      options.bias ?
        (squeeze(
          builder,
          builder.slice(options.bias, [dir, 0], [1, 3 * hiddenSize]))) :
        null);
    currentRecurrentBias.push(
      options.recurrentBias ?
        (squeeze(
          builder,
          builder.slice(
            options.recurrentBias, [dir, 0], [1, 3 * hiddenSize]))) :
        null);
    let currentHidden = squeeze(
      builder,
      builder.slice(hiddenState, [dir, 0, 0], [1, batchSize, hiddenSize]), [0]);

    for (let step = 0; step < steps; ++step) {
      const slice =
        (dir == 1 || direction == 'backward' ? steps - step - 1 : step);
      const currentInput = squeeze(
        builder,
        builder.slice(input, [slice, 0, 0], [1, batchSize, inputSize]), [0]);

      currentHidden = builder.gruCell(
        currentInput,
        currentWeight[dir],
        currentRecurrentWeight[dir],
        currentHidden,
        hiddenSize,
        {
          bias: currentBias[dir],
          recurrentBias: currentRecurrentBias[dir],
          resetAfter: options.resetAfter,
          layout: options.layout,
          activations: options.activations
        });

      if (options.returnSequence) {
        // Expand currentHidden of 2D([batchSize, hiddenSize])
        // to 4D([steps, numDirections, batchSize, hiddenSize])
        const expandedHiddenAs4D =
          builder.reshape(currentHidden, [1, 1, batchSize, hiddenSize]);

        if (direction == 'forward' || (dir == 0 && direction == 'both')) {
          forwardSequence = forwardSequence ?
            builder.concat([forwardSequence, expandedHiddenAs4D], 0) :
            expandedHiddenAs4D;
        } else if (
          direction == 'backward' || (dir == 1 && direction == 'both')) {
          backwardSequence = backwardSequence ?
            builder.concat([expandedHiddenAs4D, backwardSequence], 0) :
            expandedHiddenAs4D;
        }
      }
    }

    // Expand currentHidden of 2D([batchSize, hiddenSize])
    // to 3D([numDirections, batchSize, hiddenSize])
    const expandedHiddenAs3D =
      builder.reshape(currentHidden, [1, batchSize, hiddenSize]);
    outputHidden = outputHidden ?
      builder.concat([outputHidden, expandedHiddenAs3D], 0) :
      expandedHiddenAs3D;
  }

  if (options.returnSequence) {
    let outputSequence = null;

    if (direction == 'forward') {
      outputSequence = forwardSequence;
    } else if (direction == 'backward') {
      outputSequence = backwardSequence;
    } else if (direction == 'both') {
      // Concat along axis 1 (numDirections dimension)
      outputSequence = builder.concat([forwardSequence, backwardSequence], 1);
    }

    return [outputHidden, outputSequence];
  } else {
    return [outputHidden];
  }
}

8.9.26. gruCell

ゲート付き回帰ユニット [GRU] の単一タイムステップ。 更新ゲートとリセットゲートを使用して、回帰ネットワークの時間系列に沿って 出力へ引き継がれる隠れ状態を計算する。
dictionary MLGruCellOptions : MLOperatorOptions {
  MLOperand bias;
  MLOperand recurrentBias;
  boolean resetAfter = true;
  MLGruWeightLayout layout = "zrn";
  sequence<MLRecurrentNetworkActivation> activations;
};

partial interface MLGraphBuilder {
  MLOperand gruCell(MLOperand input,
                    MLOperand weight,
                    MLOperand recurrentWeight,
                    MLOperand hiddenState,
                    [EnforceRange] unsigned long hiddenSize,
                    optional MLGruCellOptions options = {});
};

dictionary MLGruCellSupportLimits {
  MLTensorLimits input;
  MLTensorLimits weight;
  MLTensorLimits recurrentWeight;
  MLTensorLimits hiddenState;
  MLTensorLimits bias;
  MLTensorLimits recurrentBias;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLGruCellSupportLimits gruCell;
};

MLGruCellOptions には次のメンバーがある:

bias, 型は MLOperand

形状 [3 * hiddenSize] の一次元入力バイアステンソル。テンソル形状の 第二次元におけるバイアスベクトルの順序は layout に従って指定される。

recurrentBias, 型は MLOperand

形状 [3 * hiddenSize] の一次元回帰バイアステンソル。テンソル形状の 第二次元におけるバイアスベクトルの順序は layout に従って指定される。

resetAfter, 型は boolean、既定値は true

行列乗算の後または前にリセットゲートを適用するかどうかを示す。

layout, 型は MLGruWeightLayout、既定値は "zrn"

GRU の内部ゲートの重みとバイアスベクトルの順序。具体的には update (z)、reset (r)、new (n) ゲートであり、 重みとバイアステンソルの形状の第二次元に示される。

activations, 型は sequence<MLRecurrentNetworkActivation>

二つの活性化関数を指定する。最初の関数は 更新ゲートとリセットゲートに使用され、二番目の関数は新規ゲートに使用される。指定されない場合は "sigmoid" と "tanh" 関数がそれぞれ既定値となる。

引数:

戻り値: MLOperand。 形状 [batchSize, hiddenSize] の二次元テンソルであり、回帰ネットワークの 単一タイムステップにおけるセル出力の隠れ状態を表す。

gruCell() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" 2 2
weight 同じ型 input "float32", "float16" 2 2
recurrentWeight 同じ型 input "float32", "float16" 2 2
hiddenState 同じ型 input "float32", "float16" 2 2
bias 同じ型 input "float32", "float16" 1 1
recurrentBias 同じ型 input "float32", "float16" 1 1
出力 同じ型 input "float32", "float16" 2 2

MLGruCellSupportLimits には次のメンバーがある:

input, 型は MLTensorLimits

入力オペランドの MLTensorLimits。

weight, 型は MLTensorLimits

重みオペランドの MLTensorLimits。

recurrentWeight, 型は MLTensorLimits

回帰重みオペランドの MLTensorLimits。

hiddenState, 型は MLTensorLimits

隠れ状態オペランドの MLTensorLimits。

bias, 型は MLTensorLimits

バイアスオペランドの MLTensorLimits。

recurrentBias, 型は MLTensorLimits

回帰バイアスオペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には gruCell() 用の次のメンバーがある:

gruCell, 型は MLGruCellSupportLimits

gruCell() 演算子のサポート制限。

gruCell(input, weight, recurrentWeight, hiddenState, hiddenSize, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、weight、 recurrentWeight、hiddenState、options.bias (存在する場合)、および options.recurrentBias (存在する場合)のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input、weight、recurrentWeight、または hiddenState のいずれかのdataType が それぞれの許可される データ型のいずれでもない場合(この表による)、送出するのは TypeError である。

  4. input、weight、recurrentWeight、または hiddenState のいずれかのランクが それぞれの許可される ランクでない場合(この表による)、送出するのは TypeError である。

  5. batchSize を input の形状[0] とする。

  6. inputSize を input の形状[1] とする。

  7. weight の形状が « 3 * hiddenSize, inputSize » と等しくない 場合、送出するのは TypeError である。

  8. recurrentWeight の形状が « 3 * hiddenSize, hiddenSize » と等しくない 場合、送出するのは TypeError である。

  9. hiddenState の形状が « batchSize, hiddenSize » と等しくない場合、 送出するのは TypeError である。

  10. hiddenSize * 6 が有効な次元でない場合、送出するのは TypeError である。

    なぜ hiddenSize * 6 なのか? 一部の基盤プラットフォームでは、bias と recurrentBias を連結した 単一のバイアステンソルを使用する。そのため、3 * hiddenSize + 3 * hiddenSize も 有効な 次元でなければならない。
  11. options.bias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « 3 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  12. options.recurrentBias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « 3 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  13. options.activations が存在する場合:

    1. そのサイズが 2 でない場合、送出するのは TypeError である。

    2. activations を、options.activations のクローン とする。

  14. そうでない場合:

    1. activations を « "sigmoid", "tanh" » とする。

  15. desc を、input のdataType と « batchSize, hiddenSize » を与えてMLOperandDescriptor を作成した結果とする。

  16. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、weight、recurrentWeight、hiddenState、 hiddenSize および options を与えた "gruCell" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input、weight、 recurrentWeight、および hiddenState に設定する。

    5. options.bias が存在する場合、それを operator の入力に追加する。

    6. options.recurrentBias が存在する場合、それを operator の入力に追加する。

    7. operator の活性化関数を activations のクローンに設定する。

    8. operator の出力を output に設定する。

  17. output を返す。

重みレイアウトがデフォルトの "zrn" レイアウトであり、更新/リセットゲートと新規ゲートの 活性化関数がそれぞれ sigmoid() および tanh() である場合、この演算の動作は以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例であり、アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function gruCell(
  builder, input, weight, recurrentWeight, hiddenState, hiddenSize, options) {
  const one = builder.constant(input.dataType, 1);
  const zero = builder.constant(input.dataType, 0);

  const inputSize = input.shape[1];

  // update gate (z)
  let z = builder.sigmoid(builder.add(
    builder.add(
      (options.bias ? builder.slice(options.bias, [0], [hiddenSize]) : zero),
      (options.recurrentBias ?
         builder.slice(options.recurrentBias, [0], [hiddenSize]) :
         zero)),
    builder.add(
      builder.matmul(
        input,
        builder.transpose(
          builder.slice(weight, [0, 0], [hiddenSize, inputSize]))),
      builder.matmul(
        hiddenState,
        builder.transpose(
          builder.slice(recurrentWeight, [0, 0], [hiddenSize, hiddenSize]))))));

  // reset gate (r)
  let r = builder.sigmoid(builder.add(
    builder.add(
      (options.bias ? builder.slice(options.bias, [hiddenSize], [hiddenSize]) :
                      zero),
      (options.recurrentBias ?
         builder.slice(options.recurrentBias, [hiddenSize], [hiddenSize]) :
         zero)),
    builder.add(
      builder.matmul(
        input,
        builder.transpose(
          builder.slice(weight, [hiddenSize, 0], [hiddenSize, inputSize]))),
      builder.matmul(
        hiddenState,
        builder.transpose(builder.slice(
          recurrentWeight, [hiddenSize, 0], [hiddenSize, hiddenSize]))))));

  // new gate (n)
  let n;
  if (options.resetAfter) {
    n = builder.tanh(builder.add(
      (options.bias ?
         builder.slice(options.bias, [2 * hiddenSize], [hiddenSize]) :
         zero),
      builder.add(
        builder.matmul(
          input,
          builder.transpose(builder.slice(
            weight, [2 * hiddenSize, 0], [hiddenSize, inputSize]))),
        builder.mul(
          r,
          builder.add(
            (options.recurrentBias ?
               builder.slice(
                 options.recurrentBias, [2 * hiddenSize], [hiddenSize]) :
               zero),
            builder.matmul(
              hiddenState,
              builder.transpose(builder.slice(
                recurrentWeight,
                [2 * hiddenSize, 0],
                [hiddenSize, hiddenSize]))))))));
  } else {
    n = builder.tanh(builder.add(
      builder.add(
        (options.bias ?
           builder.slice(options.bias, [2 * hiddenSize], [hiddenSize]) :
           zero),
        (options.recurrentBias ?
           builder.slice(
             options.recurrentBias, [2 * hiddenSize], [hiddenSize]) :
           zero)),
      builder.add(
        builder.matmul(
          input,
          builder.transpose(builder.slice(
            weight, [2 * hiddenSize, 0], [hiddenSize, inputSize]))),
        builder.matmul(
          builder.mul(r, hiddenState),
          builder.transpose(builder.slice(
            recurrentWeight,
            [2 * hiddenSize, 0],
            [hiddenSize, hiddenSize]))))));
  }

  // compute the new hidden state
  return builder.add(
    builder.mul(z, hiddenState), builder.mul(n, builder.sub(one, z)));
}

8.9.27. hardSigmoid

入力テンソルに対して、滑らかでないハードシグモイド関数を計算する。 計算を高速化するためにシグモイド関数の代わりに使用される。
dictionary MLHardSigmoidOptions : MLOperatorOptions {
  double alpha = 0.2;
  double beta = 0.5;
};

partial interface MLGraphBuilder {
  MLOperand hardSigmoid(MLOperand input, optional MLHardSigmoidOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits hardSigmoid;
};

MLHardSigmoidOptions には次のメンバーがある:

alpha, 型は double、既定値は 0.2

スカラー乗数。

beta, 型は double、既定値は 0.5

スカラー加算値。

引数:

戻り値:

hardSigmoid() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
出力 同じ型 input "float32", "float16" 同じランク input 0 から 5

MLOpSupportLimits には hardSigmoid() 用の次のメンバーがある:

hardSigmoid, 型は MLSingleInputSupportLimits

hardSigmoid() 演算子のサポート制限。

hardSigmoid(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. options.alpha を、options.alpha を input のdataType にキャストした結果に設定する。

  5. options.beta を、options.beta を input のdataType にキャストした結果に設定する。

  6. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、options を与えた "hardSigmoid" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  7. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function hardSigmoid(builder, input, options) {
  return builder.max(
    builder.min(
      builder.add(
        builder.mul(builder.constant(input.dataType, options.alpha), input),
        builder.constant(input.dataType, options.beta)),
      builder.constant(input.dataType, 1)),
    builder.constant(input.dataType, 0));
}

8.9.28. hardSwish

[MobileNetV3] で導入された 非線形関数 y = x * max(0, min(6, (x + 3))) / 6 を入力テンソルに対して 要素ごとに計算する。
partial interface MLGraphBuilder {
  MLOperand hardSwish(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits hardSwish;
};
引数:

戻り値:

hardSwish() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
出力 同じ型 input "float32", "float16" 同じランク input 0 から 5

MLOpSupportLimits には hardSwish() 用の次のメンバーがある:

hardSwish, 型は MLSingleInputSupportLimits

hardSwish() 演算子のサポート制限。

hardSwish(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、options を与えた "hardSwish" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function hardSwish(builder, input, options) {
  return builder.div(
    builder.mul(
      input,
      builder.max(
        builder.constant(input.dataType, 0),
        builder.min(
          builder.constant(input.dataType, 6),
          builder.add(input, builder.constant(input.dataType, 3))))),
    builder.constant(input.dataType, 6));
}

8.9.29. instanceNormalization

[Instance-Normalization] を使用して入力を正規化する。 batchNormalization() では、正規化に使用する平均値と分散値をモデルの学習中にバッチ次元の 全サンプルにわたって計算するのに対し、インスタンス正規化に使用する平均値と分散値は、 バッチ内の個々のサンプルの各入力特徴量について、その場で計算される。
dictionary MLInstanceNormalizationOptions : MLOperatorOptions {
  MLOperand scale;
  MLOperand bias;
  double epsilon = 1e-5;
  MLInputOperandLayout layout = "nchw";
};

partial interface MLGraphBuilder {
  MLOperand instanceNormalization(
    MLOperand input,
    optional MLInstanceNormalizationOptions options = {});
};

dictionary MLNormalizationSupportLimits {
  MLTensorLimits input;
  MLTensorLimits scale;
  MLTensorLimits bias;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLNormalizationSupportLimits instanceNormalization;
};

MLInstanceNormalizationOptions には次のメンバーがある:

scale, 型は MLOperand

サイズがチャネル数、 すなわち入力の特徴次元のサイズと等しい、スケーリング値の一次元テンソル。例えば、 input テンソルが "nchw" レイアウトの場合、サイズは input の 形状[1] と等しい。

bias, 型は MLOperand

サイズが入力の 特徴次元のサイズと等しい、バイアス値の一次元テンソル。例えば、input テンソルが "nchw" レイアウトの場合、サイズは input の 形状[1] と等しい。

epsilon, 型は double、既定値は 1e-5

ゼロ除算による計算エラーを防ぐための小さな値。

layout, 型は MLInputOperandLayout、既定値は "nchw"

入力のレイアウト形式。

引数:

戻り値: MLOperand。 input と同じ形状のインスタンス正規化された四次元テンソル。

instanceNormalization() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" 4 4
scale 同じ型 input "float32", "float16" 1 1
bias 同じ型 input "float32", "float16" 1 1
出力 同じ型 input "float32", "float16" 4 4

MLNormalizationSupportLimits には次のメンバーがある:

input, 型は MLTensorLimits

入力オペランドの MLTensorLimits。

scale, 型は MLTensorLimits

スケールオペランドの MLTensorLimits。

bias, 型は MLTensorLimits

バイアスオペランドの MLTensorLimits。

output, 型は MLTensorLimits

出力オペランドの MLTensorLimits。

MLOpSupportLimits には instanceNormalization() 用の次のメンバーがある:

instanceNormalization, 型は MLNormalizationSupportLimits

instanceNormalization() 演算子のサポート制限。

instanceNormalization(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、options.scale (存在する場合)、および options.bias (存在する場合)のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. input のランクが許可されるランクでない場合、送出するのは TypeError である。

  5. options.epsilon を、options.epsilon を input のdataType にキャストした結果に設定する。

  6. axis を、options.layout が "nchw" の場合は 1、それ以外の場合は 3 とする。

  7. options.scale が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « input の形状[axis] » と等しくない場合、送出するのは TypeError である。

  8. options.bias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « input の形状[axis] » と等しくない場合、送出するのは TypeError である。

  9. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、options を与えた "instanceNormalization" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. options.scale が存在する場合、それを operator の入力に追加する。

    6. options.bias が存在する場合、それを operator の入力に追加する。

    7. operator の出力を output に設定する。

  10. output を返す。

入力テンソルが "nchw" レイアウトの 4-D である場合のこの演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、ユーザー エージェントは通常、より効率的な実装を備えています。この分解は説明のための例であり、 参照実装ではありません。アルゴリズムや中間結果の精度を規定するものでは ありません。基盤となるプラットフォームが演算を直接サポートしていない場合、 この分解を実装の指針となるテンプレートとして使用できます。
function instanceNormalization(builder, input, options) {
  // The reduction of the mean and variance values happens over the spatial
  // dimensions of the input e.g. axis 2 and 3 of the input tensor.
  const reduceOptions = {axes: [2, 3], keepDimensions: true};
  const mean = builder.reduceMean(input, reduceOptions);
  const variance = builder.reduceMean(
    builder.pow(builder.sub(input, mean), builder.constant(input.dataType, 2)),
    reduceOptions);

  // The scale and bias values are applied per input feature
  // e.g. axis 1 of the input tensor.
  const shape = [1, input.shape[1], 1, 1];
  return builder.add(
    builder.mul(
      builder.reshape(options.scale, shape),
      builder.div(
        builder.sub(input, mean),
        builder.sqrt(builder.add(variance, options.epsilon)))),
    builder.reshape(options.bias, shape));
}

8.9.30. layerNormalization

[Layer-Normalization] を使用して入力を正規化する。batchNormalization() では、モデルの学習中にバッチ次元のすべてのサンプルにわたって平均値と分散値を 計算し、instanceNormalization() では、バッチ内の個々のサンプルの各入力特徴量について平均値と分散値をその場で 計算するのに対し、層正規化の平均値と分散値は、バッチ内の各サンプルの すべての入力特徴量にわたってその場で計算される。
dictionary MLLayerNormalizationOptions : MLOperatorOptions {
  MLOperand scale;
  MLOperand bias;
  sequence<[EnforceRange] unsigned long> axes;
  double epsilon = 1e-5;
};

partial interface MLGraphBuilder {
  MLOperand layerNormalization(MLOperand input,
                               optional MLLayerNormalizationOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLNormalizationSupportLimits layerNormalization;
};

MLLayerNormalizationOptions には次のメンバーがある:

scale, 型は MLOperand

スケーリング値の N 次元テンソルであり、その形状は axes メンバーによって決定される。axes の各値は、スケーリング値を持つ入力テンソルの次元を示す。例えば axes の値が [1,2,3] の場合、このテンソルの形状は入力テンソルの 次元 1、2、3 の対応するサイズのリストとなる。このメンバーがない場合、スケーリング値は 1 とみなされる。

bias, 型は MLOperand

バイアス値の N 次元テンソルであり、その形状は axes メンバーによって決定される。axes の各値は、バイアス値を持つ入力テンソルの次元を示す。例えば axes の値が [1,2,3] の場合、このテンソルの形状は入力テンソルの 次元 1、2、3 の対応するサイズのリストとなる。このメンバーがない場合、バイアス値は 0 とみなされる。

axes, 型は sequence<[EnforceRange] unsigned long>

縮約する入力次元のインデックス。このメンバーがない場合、 最初以外のすべての次元が指定されたものとして扱う(例えば四次元入力テンソルでは、axes = [1,2,3])。つまり、平均値と分散値の縮約は、各独立したバッチの すべての入力特徴量にわたって計算される。空の場合、どの次元も縮約されない。

epsilon, 型は double、既定値は 1e-5

ゼロ除算による計算エラーを防ぐための小さな値。

引数:

戻り値: MLOperand。 input と同じ形状の層正規化された N 次元テンソル。

layerNormalization() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
scale 同じ型 input "float32", "float16" N 0 から 5
bias 同じ型 input "float32", "float16" N 0 から 5
出力 同じ型 input "float32", "float16" 同じランク input 0 から 5

MLOpSupportLimits には layerNormalization() 用の次のメンバーがある:

layerNormalization, 型は MLNormalizationSupportLimits

layerNormalization() 演算子のサポート制限。

layerNormalization(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、options.scale (存在する場合)、および options.bias (存在する場合)のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. options.axes が存在しない場合、options.axes を新しいリストに設定する。それは input のランクが 1 より大きい場合は 1 から input のランクまで(上限を含まない)の範囲、 それ以外の場合は空のリストとする。

  5. そうでなく、options.axes に重複する値が含まれるか、その項目のいずれかが 0 から input のランクまで(上限を含まない)の範囲内にない場合、送出するのは TypeError である。

  6. options.epsilon を、options.epsilon を input のdataType にキャストした結果に設定する。

  7. options.scale が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. そのランクが options.axes の サイズと等しくない場合、送出するのは TypeError である。

  8. options.bias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. そのランクが options.axes の サイズと等しくない場合、送出するのは TypeError である。

  9. 0 から options.axes の サイズまで(上限を含まない)の範囲の各 index について:

    1. axis を options.axes[index] とする。

    2. axis が input のランク以上の場合、送出するのは TypeError である。

    3. size を input の形状[axis] とする。

    4. options.scale が存在する場合:

      1. その形状[index] が size と等しくない場合、送出するのは TypeError である。

    5. options.bias が存在する場合:

      1. その形状[index] が size と等しくない場合、送出するのは TypeError である。

  10. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、options を与えた "layerNormalization" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. options.scale が存在する場合、それを operator の入力に追加する。

    6. options.bias が存在する場合、それを operator の入力に追加する。

    7. operator の出力を output に設定する。

  11. output を返す。

axes パラメーターが [1,2,3] に設定されている場合のこの演算の動作は、一般的に 以下のように他の演算を使用してエミュレートできますが、ユーザーエージェントは通常、より効率的な 実装を備えています。この分解は参照実装ではなく説明のための 例です。アルゴリズムや中間結果の精度を規定するものではありません。 基盤となるプラットフォームが演算を直接サポートしていない場合、この分解を 実装の指針となるテンプレートとして使用できます。
function layerNormalization(builder, input, options) {
  // The reduction of the mean and variance values happens over the spatial
  // dimensions across all the input features (i.e. all channels) of the input
  // tensor.
  const reduceOptions = {axes: [1, 2, 3], keepDimensions: true};
  const mean = builder.reduceMean(input, reduceOptions);
  const variance = builder.reduceMean(
    builder.pow(builder.sub(input, mean), builder.constant(input.dataType, 2)),
    reduceOptions);

  // The scale and bias tensors are of the shape of the input
  // specified by the values in the axes parameter (i.e. [1,2,3]).
  return builder.add(
    builder.mul(
      options.scale,
      builder.div(
        builder.sub(input, mean),
        builder.sqrt(builder.add(variance, options.epsilon)))),
    options.bias);
}

8.9.31. leakyRelu

入力テンソルに対して漏れのある 正規化線形関数を要素ごとに計算する。計算は次の式に従う: max(0, x) + alpha * min(0, x)。
dictionary MLLeakyReluOptions : MLOperatorOptions {
  double alpha = 0.01;
};

partial interface MLGraphBuilder {
  MLOperand leakyRelu(MLOperand input, optional MLLeakyReluOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits leakyRelu;
};

MLLeakyReluOptions には次のメンバーがある:

alpha, 型は double、既定値は 0.01

スカラー乗数。

引数:

戻り値:

leakyRelu() のテンソル制限
オペランド 許可される データ型 必須の データ型 許可されるランク 必須のランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
出力 同じ型 input "float32", "float16" 同じランク input 0 から 5

MLOpSupportLimits には leakyRelu() 用の次のメンバーがある:

leakyRelu, 型は MLSingleInputSupportLimits

leakyRelu() 演算子のサポート制限。

leakyRelu(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. options.alpha を、options.alpha を input のdataType にキャストした結果に設定する。

  5. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、options を与えた "leakyRelu" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  6. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function leakyRelu(builder, input, options) {
  return builder.add(
    builder.max(builder.constant(input.dataType, 0), input),
    builder.mul(
      builder.constant(input.dataType, options.alpha),
      builder.min(builder.constant(input.dataType, 0), input)));
}

8.9.32. linear

入力テンソルに対して線形関数 y = alpha * x + beta を計算します。
dictionary MLLinearOptions : MLOperatorOptions {
  double alpha = 1;
  double beta = 0;
};

partial interface MLGraphBuilder {
  MLOperand linear(MLOperand input, optional MLLinearOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits linear;
};

MLLinearOptions には次のメンバーがあります。

alpha, 型は double、デフォルトは 1

スカラー乗数。

beta, 型は double、デフォルトは 0

スカラー加算値。

引数:

戻り値:

linear() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" 同じ input 0 から 5

MLOpSupportLimits には linear() 用の次のメンバーがあります。

linear, 型は MLSingleInputSupportLimits

linear() 演算子のサポート制限。

linear(input, options) の メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. options.alpha を options.alpha を input のdataType にキャストした結果に設定する。

  5. options.beta を options.beta を input のdataType にキャストした結果に設定する。

  6. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、options を与えた "linear" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  7. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function linear(builder, input, options) {
  return builder.add(
    builder.mul(input, builder.constant(input.dataType, options.alpha)),
    builder.constant(input.dataType, options.beta));
}

8.9.33. lstm

Long Short-Term Memory [LSTM] リカレントネットワークは、input、output、forget、および cell ゲートを使用して、ネットワークの 時間シーケンス全体にわたって出力へ引き継がれる出力状態を計算します。
enum MLLstmWeightLayout {
  "iofg", // input-output-forget-cell ゲートの順序
  "ifgo"  // input-forget-cell-output ゲートの順序
};

dictionary MLLstmOptions : MLOperatorOptions {
  MLOperand bias;
  MLOperand recurrentBias;
  MLOperand peepholeWeight;
  MLOperand initialHiddenState;
  MLOperand initialCellState;
  boolean returnSequence = false;
  MLRecurrentNetworkDirection direction = "forward";
  MLLstmWeightLayout layout = "iofg";
  sequence<MLRecurrentNetworkActivation> activations;
};

partial interface MLGraphBuilder {
  sequence<MLOperand> lstm(MLOperand input,
                           MLOperand weight,
                           MLOperand recurrentWeight,
                           [EnforceRange] unsigned long steps,
                           [EnforceRange] unsigned long hiddenSize,
                           optional MLLstmOptions options = {});
};

dictionary MLLstmSupportLimits {
  MLTensorLimits input;
  MLTensorLimits weight;
  MLTensorLimits recurrentWeight;
  MLTensorLimits bias;
  MLTensorLimits recurrentBias;
  MLTensorLimits peepholeWeight;
  MLTensorLimits initialHiddenState;
  MLTensorLimits initialCellState;
  MLTensorLimits output0;
  MLTensorLimits output1;
  MLTensorLimits output2;
};

partial dictionary MLOpSupportLimits {
  MLLstmSupportLimits lstm;
};

MLLstmOptions には次のメンバーがあります。

bias, 型は MLOperand

shape [numDirections, 4 * hiddenSize] の 2-D 入力 bias テンソル。テンソル shape の第 2 次元における bias ベクトルの順序は layout に従って指定されます。

recurrentBias, 型は MLOperand

shape [numDirections, 4 * hiddenSize] の 2-D リカレント bias テンソル。テンソル shape の第 1 次元における bias ベクトルの順序は layout に従って指定されます。

peepholeWeight, 型は MLOperand

shape [numDirections, 3 * hiddenSize] の peephole 用 2-D weight テンソル。weight ベクトルのパック 順序は、それぞれ input (i)、output (o)、および forget (f) ゲートです。

initialHiddenState, 型は MLOperand

shape [numDirections, batchSize, hiddenSize] の 3-D 初期隠れ状態テンソル。指定 されていない場合、実装は 0 で埋められたテンソルを使用しなければなりません。

initialCellState, 型は MLOperand

shape [numDirections, batchSize, hiddenSize] の 3-D 初期隠れ状態テンソル。指定 されていない場合、実装は 0 で埋められたテンソルを使用しなければなりません。

returnSequence, 型は boolean、デフォルトは false

最後の時間ステップの出力に加えて、各時間ステップのすべての出力を含むシーケンス全体も 返すかどうかを示します。

direction, 型は MLRecurrentNetworkDirection、デフォルトは "forward"

入力シーケンスの処理方向。"both" に設定した場合、weight および bias テンソル shape の第 1 次元のサイズは 2 でなければならず、入力は 両方向に処理されます。

layout, 型は MLLstmWeightLayout、デフォルトは "iofg"

LSTM の内部ゲート、具体的には input (i)、output (o)、forget (f)、および cell (g) ゲートの weight および bias ベクトルの順序であり、weight および bias テンソル shape の第 1 次元によって示されます。

activations, 型は sequence<MLRecurrentNetworkActivation>

3 つの活性化関数のリストで、第 1 の関数は input (i)、forget (f)、および output (o) ゲートに使用され、第 2 の関数は cell (g) ゲートに使用され、最後の関数は出力 cell state をフィルタリングして output ゲートの結果と結合し、出力 hidden state を形成するために使用されます。指定されていない場合、 デフォルトは "sigmoid"、 "tanh"、 および "tanh" 関数のシーケンスです。

引数:

戻り値: sequence<MLOperand>。 第 1 要素は shape [numDirections, batchSize, hiddenSize] の 3-D テンソルであり、ネットワークの最後の時間ステップからの出力 hidden state です。第 2 要素は shape [numDirections, batchSize, hiddenSize] の 3-D テンソルであり、ネットワークの最後の時間ステップからの出力 cell state です。 さらに、returnSequence が true に設定されている場合、第 3 要素は shape [steps, numDirections, batchSize, hiddenSize] の 4-D 出力テンソルであり、時間シーケンス内の各時間ステップからのすべての出力を含みます。

lstm() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" 3 3
weight 同じ input "float32", "float16" 3 3
recurrentWeight 同じ input "float32", "float16" 3 3
bias 同じ input "float32", "float16" 2 2
recurrentBias 同じ input "float32", "float16" 2 2
peepholeWeight 同じ input "float32", "float16" 2 2
initialHiddenState 同じ input "float32", "float16" 3 3
initialCellState 同じ input "float32", "float16" 3 3
outputs[0] 同じ input "float32", "float16" 3 3
outputs[1] 同じ input "float32", "float16" 3 3
outputs[2] if returnSequence が true の場合 同じ input "float32", "float16" 4 4

MLLstmSupportLimits には次のメンバーがあります。

input, 型は MLTensorLimits

input オペランドの MLTensorLimits。

weight, 型は MLTensorLimits

weight オペランドの MLTensorLimits。

recurrentWeight, 型は MLTensorLimits

recurrentWeight オペランドの MLTensorLimits。

bias, 型は MLTensorLimits

bias オペランドの MLTensorLimits。

recurrentBias, 型は MLTensorLimits

recurrentBias オペランドの MLTensorLimits。

peepholeWeight, 型は MLTensorLimits

peepholeWeight オペランドの MLTensorLimits。

initialHiddenState, 型は MLTensorLimits

initialHiddenState オペランドの MLTensorLimits。

initialCellState, 型は MLTensorLimits

initialCellState オペランドの MLTensorLimits。

output0, 型は MLTensorLimits

すべての出力オペランド[0]の MLTensorLimits。

output1, 型は MLTensorLimits

すべての出力オペランド[1]の MLTensorLimits。

output2, 型は MLTensorLimits

すべての出力オペランド[2]の MLTensorLimits。

MLOpSupportLimits には lstm() 用の次のメンバーがあります。

lstm, 型は MLLstmSupportLimits

lstm() 演算子のサポート制限。

lstm(input, weight, recurrentWeight, steps, hiddenSize, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、weight、 recurrentWeight、options.bias (存在する場合)、options.recurrentBias (存在する場合)、options.peepholeWeight (存在する場合)、options.initialHiddenState (存在する場合)、および options.initialCellState (存在する場合)のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. numDirections を、options.direction が "both" の場合は 2、それ以外の場合は 1 とする。

  4. input、weight または recurrentWeight のいずれかのdataType が それぞれの許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  5. input、weight または recurrentWeight のいずれかのランクが それぞれの許可されるランクでない 場合、送出するのは TypeError である。

  6. steps が 0 の場合、送出するのは TypeError である。

  7. input の形状[0] が steps と等しくない場合、送出するのは TypeError である。

  8. batchSize を input の形状[1] とする。

  9. inputSize を input の形状[2] とする。

  10. weight の形状が « numDirections, 4 * hiddenSize, inputSize » と等しくない場合、送出するのは TypeError である。

  11. recurrentWeight の形状が « numDirections, 4 * hiddenSize, hiddenSize » と等しくない場合、送出するのは TypeError である。

  12. hiddenSize * 8 が有効な次元でない場合、送出するのは TypeError である。

    なぜ hiddenSize * 8 なのか? 一部の基盤プラットフォームでは、bias と recurrentBias を連結した単一のバイアステンソルを使用する。 したがって、4 * hiddenSize + 4 * hiddenSize も有効な 次元でなければならない。
  13. options.bias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « numDirections, 4 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  14. options.recurrentBias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « numDirections, 4 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  15. options.peepholeWeight が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « numDirections, 3 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  16. options.initialHiddenState が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « numDirections, batchSize, hiddenSize » と等しくない場合、送出するのは TypeError である。

  17. options.initialCellState が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « numDirections, batchSize, hiddenSize » と等しくない場合、送出するのは TypeError である。

  18. options.activations が存在する場合:

    1. そのサイズが 3 でない場合、送出するのは TypeError である。

    2. activations を、options.activations のクローン とする。

  19. そうでない場合:

    1. activations を « "sigmoid", "tanh", "tanh" » とする。

  20. 出力形状を計算する:

    1. desc を、MLOperandDescriptor を作成する際に input のdataType と « numDirections, batchSize, hiddenSize » を与えた結果とする。

    2. desc2 を、MLOperandDescriptor を作成する際に input のdataType と « steps, numDirections, batchSize, hiddenSize » を与えた結果とする。

      なぜ desc2 を無条件に作成するのか? 一部の基盤プラットフォームでは、returnSequence に関係なくシーケンス全体の出力テンソルを生成する。 したがって、desc2 も有効でなければならない。
  21. グラフ接続を作成する:

    1. operator を、weight、recurrentWeight、steps、 hiddenSize および options を与えた "lstm" 演算用の演算子とする。

    2. output0 を、MLOperand を 作成する際に this と desc を与えた結果とする。

    3. output1 を、MLOperand を 作成する際に this と desc を与えた結果とする。

    4. options.returnSequence が true の場合:

      1. output2 を、MLOperand を 作成する際に this と desc2 を与えた結果とする。

      2. output をリスト « output0, output1, output2 » とする。

      3. output0.[[operator]]、 output1.[[operator]] および output2.[[operator]] を operator に設定する。

    5. そうでない場合:

      1. output をリスト « output0, output1 » とする。

      2. output0.[[operator]] および output1.[[operator]] を operator に設定する。

    6. operator の入力を input、weight、および recurrentWeight に設定する。

    7. options.bias が存在する場合、それを operator の入力に追加する。

    8. options.recurrentBias が存在する場合、それを operator の入力に追加する。

    9. options.peepholeWeight が存在する場合、それを operator の入力に追加する。

    10. options.initialHiddenState が存在する場合、それを operator の入力に追加する。

    11. options.initialCellState が存在する場合、それを operator の入力に追加する。

    12. operator の活性化関数を activations のクローンに設定する。

    13. operator の出力を output に設定する。

  22. output を返す。

squeeze() ヘルパーを使用すると、この演算の動作は 以下のように他の演算を使用して一般的にエミュレートできますが、ユーザーエージェントは通常、 より効率的な実装を備えています。この分解は説明のための例であり、 参照実装ではありません。アルゴリズムや中間結果の精度を 規定するものではありません。基盤となるプラットフォームが演算を直接サポートしていない場合、この 分解を実装の指針となるテンプレートとして使用できます。
function lstm(
  builder, input, weight, recurrentWeight, steps, hiddenSize, options) {
  const batchSize = input.shape[1];
  const inputSize = input.shape[2];
  const direction = options.direction || 'forward';
  const numDirections = (direction == 'both' ? 2 : 1);
  let hiddenState = options.initialHiddenState;
  let cellState = options.initialCellState;

  if (!hiddenState) {
    const desc = {
      dataType: 'float32',
      shape: [numDirections, batchSize, hiddenSize]
    };
    const totalSize = numDirections * batchSize * hiddenSize;
    hiddenState = builder.constant(desc, new Float32Array(totalSize).fill(0));
  }

  if (!cellState) {
    const desc = {
      dataType: 'float32',
      shape: [numDirections, batchSize, hiddenSize]
    };
    const totalSize = numDirections * batchSize * hiddenSize;
    cellState = builder.constant(desc, new Float32Array(totalSize).fill(0));
  }

  let currentWeight = [];
  let currentRecurrentWeight = [];
  let currentBias = [];
  let currentRecurrentBias = [];
  let currentPeepholeWeight = [];
  let forwardSequence = null;
  let backwardSequence = null;
  let outputHidden = null;
  let outputCell = null;

  for (let dir = 0; dir < numDirections; ++dir) {
    currentWeight.push(squeeze(
      builder,
      builder.slice(weight, [dir, 0, 0], [1, 4 * hiddenSize, inputSize])));
    currentRecurrentWeight.push(squeeze(
      builder,
      builder.slice(
        recurrentWeight, [dir, 0, 0], [1, 4 * hiddenSize, hiddenSize])));
    currentBias.push(
      options.bias ?
        (squeeze(
          builder,
          builder.slice(options.bias, [dir, 0], [1, 4 * hiddenSize]))) :
        null);
    currentRecurrentBias.push(
      options.recurrentBias ?
        (squeeze(
          builder,
          builder.slice(
            options.recurrentBias, [dir, 0], [1, 4 * hiddenSize]))) :
        null);
    currentPeepholeWeight.push(
      options.peepholeWeight ?
        (squeeze(
          builder,
          builder.slice(
            options.peepholeWeight, [dir, 0], [1, 3 * hiddenSize]))) :
        null);

    let currentHidden = squeeze(
      builder,
      builder.slice(hiddenState, [dir, 0, 0], [1, batchSize, hiddenSize]), [0]);
    let currentCell = squeeze(
      builder,
      builder.slice(cellState, [dir, 0, 0], [1, batchSize, hiddenSize]), [0]);

    for (let step = 0; step < steps; ++step) {
      const slice =
        (dir == 1 || direction == 'backward' ? steps - step - 1 : step);
      const currentInput = squeeze(
        builder,
        builder.slice(input, [slice, 0, 0], [1, batchSize, inputSize]), [0]);

      [currentHidden, currentCell] = builder.lstmCell(
        currentInput,
        currentWeight[dir],
        currentRecurrentWeight[dir],
        currentHidden,
        currentCell,
        hiddenSize,
        {
          bias: currentBias[dir],
          recurrentBias: currentRecurrentBias[dir],
          peepholeWeight: currentPeepholeWeight[dir],
          layout: options.layout,
          activations: options.activations
        });

      if (options.returnSequence) {
        // 2D([batchSize, hiddenSize]) の currentHidden を拡張する
        // 4D([steps, numDirections, batchSize, hiddenSize]) へ
        const expandedHiddenAs4D =
          builder.reshape(currentHidden, [1, 1, batchSize, hiddenSize]);

        if (direction == 'forward' || (dir == 0 && direction == 'both')) {
          forwardSequence = forwardSequence ?
            builder.concat([forwardSequence, expandedHiddenAs4D], 0) :
            expandedHiddenAs4D;
        } else if (
          direction == 'backward' || (dir == 1 && direction == 'both')) {
          backwardSequence = backwardSequence ?
            builder.concat([expandedHiddenAs4D, backwardSequence], 0) :
            expandedHiddenAs4D;
        }
      }
    }

    // 2D([batchSize, hiddenSize]) の currentHidden を拡張する
    // 3D([numDirections, batchSize, hiddenSize]) へ
    const expandedHiddenAs3D =
      builder.reshape(currentHidden, [1, batchSize, hiddenSize]);
    outputHidden = outputHidden ?
      builder.concat([outputHidden, expandedHiddenAs3D], 0) :
      expandedHiddenAs3D;

    // 2D([batchSize, hiddenSize]) の currentCell を拡張する
    // 3D([numDirections, batchSize, hiddenSize]) へ
    const expandedCellAs3D =
      builder.reshape(currentCell, [1, batchSize, hiddenSize]);
    outputCell = outputCell ?
      builder.concat([outputCell, expandedCellAs3D], 0) :
      expandedCellAs3D;
  }

  if (options.returnSequence) {
    let outputSequence = null;

    if (direction == 'forward') {
      outputSequence = forwardSequence;
    } else if (direction == 'backward') {
      outputSequence = backwardSequence;
    } else if (direction == 'both') {
      // axis 1(numDirections 次元)に沿って連結する
      outputSequence = builder.concat([forwardSequence, backwardSequence], 1);
    }

    return [outputHidden, outputCell, outputSequence];
  } else {
    return [outputHidden, outputCell];
  }
}

8.9.34. lstmCell

セル状態、入力、出力、および forget ゲートを使用する Long Short-Term Memory [LSTM] リカレントネットワークの単一時間ステップであり、ネットワークの 時系列全体にわたって出力へ引き継がれる次の時間ステップのセル状態と隠れ状態を 計算します。
dictionary MLLstmCellOptions : MLOperatorOptions {
  MLOperand bias;
  MLOperand recurrentBias;
  MLOperand peepholeWeight;
  MLLstmWeightLayout layout = "iofg";
  sequence<MLRecurrentNetworkActivation> activations;
};

partial interface MLGraphBuilder {
  sequence<MLOperand> lstmCell(MLOperand input,
                               MLOperand weight,
                               MLOperand recurrentWeight,
                               MLOperand hiddenState,
                               MLOperand cellState,
                               [EnforceRange] unsigned long hiddenSize,
                               optional MLLstmCellOptions options = {});
};

dictionary MLLstmCellSupportLimits {
  MLTensorLimits input;
  MLTensorLimits weight;
  MLTensorLimits recurrentWeight;
  MLTensorLimits hiddenState;
  MLTensorLimits cellState;
  MLTensorLimits bias;
  MLTensorLimits recurrentBias;
  MLTensorLimits peepholeWeight;
  MLTensorLimits output0;
  MLTensorLimits output1;
};

partial dictionary MLOpSupportLimits {
  MLLstmCellSupportLimits lstmCell;
};

MLLstmCellOptions には次のメンバーがあります:

bias, 型は MLOperand

shape [4 * hiddenSize] の 1-D 入力バイアステンソル。テンソル shape の 第 1 次元におけるバイアスベクトルの順序は layout に従って指定されます。

recurrentBias, 型は MLOperand

shape [4 * hiddenSize] の 1-D リカレントバイアステンソル。テンソル shape の 第 1 次元におけるバイアスベクトルの順序は layout に従って指定されます。

peepholeWeight, 型は MLOperand

shape [3 * hiddenSize] の peephole 用 1-D weight テンソル。weight ベクトルのパック順序は、 それぞれ input (i)、output (o)、および forget (f) ゲートです。

layout, 型は MLLstmWeightLayout、デフォルトは "iofg"

LSTM の内部ゲート、具体的には input (i)、output (o)、forget (f)、および cell (g) ゲートの weight および bias ベクトルの順序であり、weight および bias テンソル shape の第 1 次元によって示されます。

activations, 型は sequence<MLRecurrentNetworkActivation>

3 つの活性化関数のリスト。第 1 の関数は input (i)、forget (f)、および output (o) ゲートに使用され、第 2 の関数は cell (g) ゲートに使用され、最後の関数は出力セル状態をフィルタリングして output ゲートの結果と結合し、出力隠れ状態を形成するために使用されます。指定されていない場合、 デフォルトは "sigmoid"、 "tanh"、 および "tanh" 関数のシーケンスです。

引数:

戻り値: sequence<MLOperand>。 第 1 要素はリカレントネットワークの現在の時間ステップの出力隠れ状態です。 次の要素は出力セル状態です。両方の要素は shape [batchSize, hiddenSize] の 2-D テンソルです。

lstmCell() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" 2 2
weight 同じ input "float32", "float16" 2 2
recurrentWeight 同じ input "float32", "float16" 2 2
hiddenState 同じ input "float32", "float16" 2 2
cellState 同じ input "float32", "float16" 2 2
bias 同じ input "float32", "float16" 1 1
recurrentBias 同じ input "float32", "float16" 1 1
peepholeWeight 同じ input "float32", "float16" 1 1
outputs[0] 同じ input "float32", "float16" 2 2
outputs[1] 同じ input "float32", "float16" 2 2

MLLstmCellSupportLimits には次のメンバーがあります:

input, 型は MLTensorLimits

MLTensorLimits は input オペランド用です。

weight, 型は MLTensorLimits

MLTensorLimits は weight オペランド用です。

recurrentWeight, 型は MLTensorLimits

MLTensorLimits は recurrentWeight オペランド用です。

hiddenState, 型は MLTensorLimits

MLTensorLimits は hiddenState オペランド用です。

cellState, 型は MLTensorLimits

MLTensorLimits は cellState オペランド用です。

bias, 型は MLTensorLimits

MLTensorLimits は bias オペランド用です。

recurrentBias, 型は MLTensorLimits

MLTensorLimits は recurrentBias オペランド用です。

peepholeWeight, 型は MLTensorLimits

MLTensorLimits は peepholeWeight オペランド用です。

output0, 型は MLTensorLimits

MLTensorLimits はすべての出力オペランド[0]用です。

output1, 型は MLTensorLimits

MLTensorLimits はすべての出力オペランド[1]用です。

MLOpSupportLimits には lstmCell() 用の次のメンバーがあります:

lstmCell, 型は MLLstmCellSupportLimits

演算子 lstmCell() のサポート制限。

lstmCell(input, weight, recurrentWeight, hiddenState, cellState, hiddenSize, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、weight、 recurrentWeight、hiddenState、cellState、 options.bias (存在する場合)、options.recurrentBias (存在する場合)、および options.peepholeWeight (存在する場合)のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input、weight、recurrentWeight、hiddenState または cellState のいずれかのdataType が それぞれの許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

  4. input、weight、recurrentWeight、hiddenState または cellState のいずれかのランクが それぞれの許可されるランクでない場合、送出するのは TypeError である。

  5. batchSize を input の形状[0] とする。

  6. inputSize を input の形状[1] とする。

  7. weight の形状が « 4 * hiddenSize, inputSize » と等しくない 場合、送出するのは TypeError である。

  8. recurrentWeight の形状が « 4 * hiddenSize, hiddenSize » と等しくない 場合、送出するのは TypeError である。

  9. hiddenState の形状が « batchSize, hiddenSize » と等しくない場合、 送出するのは TypeError である。

  10. cellState の形状が « batchSize, hiddenSize » と等しくない場合、 送出するのは TypeError である。

  11. hiddenSize * 8 が有効な次元でない場合、送出するのは TypeError である。

    なぜ hiddenSize * 8 なのか? 一部の基盤プラットフォームでは、bias と recurrentBias を連結した単一のバイアステンソルを使用する。 したがって、4 * hiddenSize + 4 * hiddenSize も有効な 次元でなければならない。
  12. options.bias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « 4 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  13. options.recurrentBias が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « 4 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  14. options.peepholeWeight が存在する場合:

    1. そのdataType が許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

    2. その形状が « 3 * hiddenSize » と等しくない場合、送出するのは TypeError である。

  15. options.activations が存在する場合:

    1. そのサイズが 3 でない場合、送出するのは TypeError である。

    2. activations を、options.activations のクローン とする。

  16. そうでない場合:

    1. activations を « "sigmoid", "tanh", "tanh" » とする。

  17. desc を新しい MLOperandDescriptor とする。

  18. desc.shape をリスト « batchSize, hiddenSize » に設定する。

  19. desc.dataType を input のdataType に設定する。

  20. グラフ接続を作成する:

    1. output0 を、MLOperand を作成 する際に this と desc を与えた結果とする。

    2. output1 を、MLOperand を作成 する際に this と desc を与えた結果とする。

    3. output をリスト « output0, output1 » とする。

    4. operator を、weight、recurrentWeight、hiddenState、 cellState、hiddenSize および options を与えた "lstmCell" 演算用の演算子とする。

    5. output0.[[operator]] と output1.[[operator]] を operator に設定する。

    6. operator の入力を input、weight、 recurrentWeight、hiddenState、および cellState に設定する。

    7. options.bias が存在する場合、それを operator の入力に追加する。

    8. options.recurrentBias が存在する場合、それを operator の入力に追加する。

    9. options.peepholeWeight が存在する場合、それを operator の入力に追加する。

    10. operator の活性化関数を activations のクローンに設定する。

    11. operator の出力を output に設定する。

  21. output を返す。

重みレイアウトがデフォルトの "iofg" レイアウトであり、入力/忘却/出力ゲートの 活性化関数と、 セルゲート/出力隠れ状態に対するセル状態のフィルターの活性化関数が、それぞれ sigmoid() および tanh() である場合、この演算の動作は以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例であり、アルゴリズムや中間結果の精度を 規定するものではありません。基盤となるプラットフォームが演算を直接サポートしていない 場合、この分解を実装の指針となるテンプレートとして使用できます。
function lstmCell(
  builder,
  input,
  weight,
  recurrentWeight,
  hiddenState,
  cellState,
  hiddenSize,
  options) {
  const zero = builder.constant(input.dataType, 0);

  const inputSize = input.shape[1];

  // input ゲート (i)
  let i = builder.sigmoid(builder.add(
    builder.mul(
      cellState,
      (options.peepholeWeight ?
         builder.slice(options.peepholeWeight, [0], [hiddenSize]) :
         zero)),
    builder.add(
      builder.add(
        (options.bias ? builder.slice(options.bias, [0], [hiddenSize]) : zero),
        (options.recurrentBias ?
           builder.slice(options.recurrentBias, [0], [hiddenSize]) :
           zero)),
      builder.add(
        builder.matmul(
          input,
          builder.transpose(
            builder.slice(weight, [0, 0], [hiddenSize, inputSize]))),
        builder.matmul(
          hiddenState,
          builder.transpose(builder.slice(
            recurrentWeight, [0, 0], [hiddenSize, hiddenSize])))))));

  // forget ゲート (f)
  let f = builder.sigmoid(builder.add(
    builder.mul(
      cellState,
      (options.peepholeWeight ?
         builder.slice(options.peepholeWeight, [2 * hiddenSize], [hiddenSize]) :
         zero)),
    builder.add(
      builder.add(
        (options.bias ?
           builder.slice(options.bias, [2 * hiddenSize], [hiddenSize]) :
           zero),
        (options.recurrentBias ?
           builder.slice(
             options.recurrentBias, [2 * hiddenSize], [hiddenSize]) :
           zero)),
      builder.add(
        builder.matmul(
          input,
          builder.transpose(builder.slice(
            weight, [2 * hiddenSize, 0], [hiddenSize, inputSize]))),
        builder.matmul(
          hiddenState,
          builder.transpose(builder.slice(
            recurrentWeight,
            [2 * hiddenSize, 0],
            [hiddenSize, hiddenSize])))))));

  // cell ゲート (g)
  let g = builder.tanh(builder.add(
    builder.add(
      (options.bias ?
         builder.slice(options.bias, [3 * hiddenSize], [hiddenSize]) :
         zero),
      (options.recurrentBias ?
         builder.slice(options.recurrentBias, [3 * hiddenSize], [hiddenSize]) :
         zero)),
    builder.add(
      builder.matmul(
        input,
        builder.transpose(
          builder.slice(weight, [3 * hiddenSize, 0], [hiddenSize, inputSize]))),
      builder.matmul(
        hiddenState,
        builder.transpose(builder.slice(
          recurrentWeight, [3 * hiddenSize, 0], [hiddenSize, hiddenSize]))))));

  // output ゲート (o)
  let o = builder.sigmoid(builder.add(
    builder.mul(
      cellState,
      (options.peepholeWeight ?
         builder.slice(options.peepholeWeight, [hiddenSize], [hiddenSize]) :
         zero)),
    builder.add(
      builder.add(
        (options.bias ?
           builder.slice(options.bias, [hiddenSize], [hiddenSize]) :
           zero),
        (options.recurrentBias ?
           builder.slice(options.recurrentBias, [hiddenSize], [hiddenSize]) :
           zero)),
      builder.add(
        builder.matmul(
          input,
          builder.transpose(
            builder.slice(weight, [hiddenSize, 0], [hiddenSize, inputSize]))),
        builder.matmul(
          hiddenState,
          builder.transpose(builder.slice(
            recurrentWeight, [hiddenSize, 0], [hiddenSize, hiddenSize])))))));

  // 出力セル状態 (ct)
  let ct = builder.add(builder.mul(f, cellState), builder.mul(i, g));

  // 出力隠れ状態 (ht)
  let ht = builder.mul(o, builder.tanh(ct));

  return [ht, ct];
}

8.9.35. matmul

2 つの入力テンソルの行列積を計算します。
partial interface MLGraphBuilder {
  MLOperand matmul(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLBinarySupportLimits matmul;
};
引数:

戻り値: MLOperand。 2 つの入力テンソルの行列 積を含む出力テンソル。

2 つの入力テンソルの行列積を次のように計算します:
matmul() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
a "float32", "float16", "bfloat16" "float32", "float16" 2 から N 2 から 5
b 同じ a "float32", "float16" 2 から N 2 から 5
output 同じ a "float32", "float16" 2 から N 2 から 5

MLOpSupportLimits には matmul() 用の次のメンバーがあります:

matmul, 型は MLBinarySupportLimits

演算子 matmul() のサポート制限。

matmul(a, b, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と a または b のいずれかを与えた結果が false の場合、 送出するのは TypeError である。

  3. a または b のいずれかのdataType が それぞれの許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

  4. 出力形状を計算する:

    1. shapeA を、a の形状のクローン とする。

    2. rankA を a のランクとする。

    3. shapeB を、b の形状のクローン とする。

    4. rankB を b のランクとする。

    5. rankA または rankB のいずれかが 2 未満の場合、送出するのは TypeError である。

    6. colsA を shapeA[rankA - 1] とする。

    7. rowsA を shapeA[rankA - 2] とする。

    8. colsB を shapeB[rankB - 1] とする。

    9. rowsB を shapeB[rankB - 2] とする。

    10. colsA が rowsB と等しくない場合、送出するのは TypeError である。

    11. batchShapeA を、shapeA のクローンから 空間次元(最後の 2 項目)を削除したものとする。

    12. batchShapeB を、shapeB のクローンから 空間次元(最後の 2 項目)を削除したものとする。

    13. outputShape を、batchShapeA と batchShapeB を双方向にブロードキャストした結果とする。 その結果が失敗の場合、送出するのは TypeError である。

    14. « rowsA, colsB » を付加する先は outputShape である。

    15. desc を、a のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  5. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、options を与えた "matmul" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を a と b に設定する。

    5. operator の出力を output に設定する。

  6. output を返す。

8.9.36. pad

テンソルの端を定数値または鏡像値で拡張します。
enum MLPaddingMode {
  "constant",
  "edge",
  "reflection"
};

dictionary MLPadOptions : MLOperatorOptions {
  MLPaddingMode mode = "constant";
  MLNumber value = 0;
};

partial interface MLGraphBuilder {
  MLOperand pad(MLOperand input,
                sequence<[EnforceRange] unsigned long> beginningPadding,
                sequence<[EnforceRange] unsigned long> endingPadding,
                optional MLPadOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits pad;
};

MLPadOptions には次のメンバーがあります:

mode, 型は MLPaddingMode、デフォルトは "constant"

テンソルをパディングするさまざまな方法。

value, 型は MLNumber、デフォルトは 0

mode が "constant" に設定されている場合のパディング値。

引数:

戻り値: MLOperand。 パディングされた出力テンソル。出力テンソルの各次元は次のように計算できます:

output size = beginning padding + input size + ending padding

pad() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" 同じ input 0 から 5

MLOpSupportLimits には pad() 用の次のメンバーがあります:

pad, 型は MLSingleInputSupportLimits

演算子 pad() のサポート制限。

pad(input, beginningPadding, endingPadding, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. beginningPadding のサイズと endingPadding のサイズの 少なくとも一方が input のランクと等しくない場合、送出するのは TypeError である。

  4. outputShape を、input の形状のクローン とする。

  5. 各 index について、範囲 0 から outputShape のランクまで (上限を含まない):

    1. options.mode に応じて分岐する:

      "constant"

      何もしない。

      "edge"

      何もしない。

      "reflection"
      1. beginningPadding[index] が outputShape[index] 以上の場合、送出するのは TypeError である。

      2. endingPadding[index] が outputShape[index] 以上の場合、送出するのは TypeError である。

    2. outputShape[index] に beginningPadding[index] の値を加算する。

    3. outputShape[index] に endingPadding[index] の値を加算する。

  6. outputShape 内の項目のいずれかが有効な次元でない場合、送出するのは TypeError である。

  7. options.value を、options.value を input のdataType にキャストした結果に設定する。

  8. desc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  9. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、beginningPadding、endingPadding および options を与えた "padding" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  10. output を返す。

constant、edge、および reflection パディングの例:
// input: [[1,2,3], [4,5,6]]
const input = builder.constant(
  {dataType: 'float32', shape: [2, 3]}, new Float32Array([1, 2, 3, 4, 5, 6]));

const beginningPadding = [1, 2];
const endingPadding = [1, 2];

// "constant" パディング:
//    [[0,0,0,0,0,0,0],
//     [0,0,1,2,3,0,0],
//     [0,0,4,5,6,0,0],
//     [0,0,0,0,0,0,0]]
builder.pad(input, beginningPadding, endingPadding);

// "edge" パディング:
//    [[1,1,1,2,3,3,3],
//     [1,1,1,2,3,3,3],
//     [4,4,4,5,6,6,6],
//     [4,4,4,5,6,6,6]]
builder.pad(input, beginningPadding, endingPadding, {mode: 'edge'});

// "reflection" パディング:
//    [[6,5,4,5,6,5,4],
//     [3,2,1,2,3,2,1],
//     [6,5,4,5,6,5,4],
//     [3,2,1,2,3,2,1]]
builder.pad(input, beginningPadding, endingPadding, {mode: 'reflection'});

8.9.37. プーリング演算

入力テンソル上を移動するウィンドウ内のすべての要素にわたってプーリング演算を計算します。
enum MLRoundingType {
  "floor",
  "ceil"
};

dictionary MLPool2dOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> windowDimensions;
  sequence<[EnforceRange] unsigned long> padding;
  sequence<[EnforceRange] unsigned long> strides;
  sequence<[EnforceRange] unsigned long> dilations;
  MLInputOperandLayout layout = "nchw";
  MLRoundingType outputShapeRounding = "floor";
  sequence<[EnforceRange] unsigned long> outputSizes;
};

partial interface MLGraphBuilder {
  MLOperand averagePool2d(MLOperand input, optional MLPool2dOptions options = {});
  MLOperand l2Pool2d(MLOperand input, optional MLPool2dOptions options = {});
  MLOperand maxPool2d(MLOperand input, optional MLPool2dOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits averagePool2d;
  MLSingleInputSupportLimits l2Pool2d;
  MLSingleInputSupportLimits maxPool2d;
};

MLPool2dOptions には次のメンバーがあります:

windowDimensions, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト: [windowHeight, windowWidth]。 スライディングウィンドウの次元を指定します。 ウィンドウ次元のデフォルト値は入力 shape の高さと幅の次元です。

padding, 型は sequence<[EnforceRange] unsigned long>

長さ 4 のリスト: [beginningHeight, endingHeight, beginningWidth, endingWidth]。 畳み込み入力の各空間 次元の先頭と末尾に追加される行と列を指定します。 デフォルト値は [0,0,0,0] です。

strides, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト: [strideHeight, strideWidth]。 畳み込み入力の各空間次元に対するスライディングウィンドウのストライドを指定します。 デフォルト値は [1,1] です。

dilations, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト: [dilationHeight, dilationWidth]。畳み込みフィルター(kernel)に適用される各 空間次元の dilation 係数を指定します。 デフォルト値は [1,1] です。

layout, 型は MLInputOperandLayout、デフォルトは "nchw"

入力および出力テンソルの layout 形式を次のように指定します:

  • "nchw"

    • 入力テンソル: [batches, inputChannels, height, width]

    • 出力テンソル: [batches, outputChannels, height, width]

  • "nhwc":

    • 入力テンソル: [batches, height, width, inputChannels]

    • 出力テンソル: [batches, height, width, outputChannels]

outputShapeRounding, 型は MLRoundingType、デフォルトは "floor"

完全なウィンドウ結果または部分的なウィンドウ結果のどちらが必要かに応じて、出力 shape の計算に使用される 丸め関数。

outputSizes, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト: [outputHeight, outputWidth] 出力テンソルの 2 つの空間次元のサイズを指定します。 出力サイズが明示的に指定されている場合、outputShapeRounding は無視されます。 指定されていない場合、出力サイズは自動的に計算されます。

引数:

戻り値: MLOperand。 リダクションの 結果を含む出力 4-D テンソル。論理 shape は layout の値に従って解釈されます。 より具体的には、outputShapeRounding が "floor" の場合、出力テンソルの単一次元の空間次元は次のように計算できます:

output size = floor(1 + (input size - filter size + beginning padding + ending padding) / stride)

または outputShapeRounding が "ceil" の場合:

output size = ceil(1 + (input size - filter size + beginning padding + ending padding) / stride)

averagePool2d()/l2Pool2d() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" 4 4
output 同じ input "float32", "float16" 4 4
maxPool2d() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16" 4 4
output 同じ input "float32", "float16" 4 4

MLOpSupportLimits にはプーリング演算用の次のメンバーがあります:

averagePool2d, 型は MLSingleInputSupportLimits

演算子 averagePool2d() のサポート制限。

l2Pool2d, 型は MLSingleInputSupportLimits

演算子 l2Pool2d() のサポート制限。

maxPool2d, 型は MLSingleInputSupportLimits

演算子 maxPool2d() のサポート制限。

max pooling 演算のようなグローバルプーリング演算は、 ウィンドウ次元が入力 shape の空間次元(最後の 2 次元)であるプーリングの変種です。次のようになります。
// 'global' max pooling
builder.maxPool2d(input);
文字列 op、MLOperand input、MLPool2dOptions options、およびオプションのリスト allowedDataTypes を与えて プーリング演算を作成するには、次の手順を実行する:
  1. 表明: op は "averagePool2d"、"l2Pool2d"、 "maxPool2d" のいずれかである。

  2. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  3. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  4. allowedDataTypes が与えられ、それが input のdataType を含まない 場合、送出するのは TypeError である。

  5. input のランクが 4 でない場合、送出するのは TypeError である。

  6. options.layout に応じて分岐する:

    "nchw"

    « batches, channels, inputHeight, inputWidth » を input の形状とする。

    "nhwc"

    « batches, inputHeight, inputWidth, channels » を input の形状とする。

  7. options.windowDimensions が存在しない場合、options.windowDimensions を « inputHeight, inputWidth » に設定する。

  8. options.windowDimensions の サイズが 2 でない場合、送出するのは TypeError である。

  9. options.windowDimensions 内の項目のいずれかが 0 に等しい場合、送出するのは TypeError である。

  10. options.outputSizes が存在する場合、または options.padding が存在しない場合、options.padding をリスト « 0, 0, 0, 0 » に設定する。

  11. options.padding の サイズが 4 でない場合、送出するのは TypeError である。

  12. options.strides が存在しない場合、options.strides をリスト « 1, 1 » に設定する。

  13. options.strides の サイズが 2 でない場合、送出するのは TypeError である。

  14. options.strides 内の項目のいずれかが 0 の場合、送出するのは TypeError である。

  15. options.outputSizes が存在する場合:

    1. そのサイズが 2 でない場合、送出するのは TypeError である。

    2. その項目が options.strides の 同じ次元(インデックス)にある項目 より小さくない場合、送出するのは TypeError である。

  16. options.dilations が存在しない場合、options.dilations をリスト « 1, 1 » に設定する。

  17. options.dilations の サイズが 2 でない場合、送出するのは TypeError である。

  18. options.dilations 内の項目のいずれかが 0 の場合、送出するのは TypeError である。

  19. 出力形状を計算する:

    1. « windowHeight, windowWidth » を options.windowDimensions とする。

    2. « calculatedOutputHeight, calculatedOutputWidth » を inputHeight、inputWidth、windowHeight、 windowWidth、options.padding、 options.strides、 および options.dilations を与えて conv2d の出力 サイズを計算した結果とする。

    3. options.outputSizes が存在する場合:

      1. « outputHeight, outputWidth » を options.outputSizes とする。

      2. outputHeight が floor( calculatedOutputHeight ) と等しく、かつ outputWidth が floor( calculatedOutputWidth ) と等しい場合でも、outputHeight が ceil( calculatedOutputHeight ) と等しく、かつ outputWidth が ceil( calculatedOutputWidth ) と等しい場合でもないとき、送出するのは TypeError である。

    4. そうでない場合:

      1. « outputHeight, outputWidth » を « calculatedOutputHeight, calculatedOutputWidth » とする。

      2. options.outputShapeRounding に応じて分岐する:

        "floor"
        1. outputWidth を floor(outputWidth) に設定する。

        2. outputHeight を floor(outputHeight) に設定する。

        "ceil"
        1. outputWidth を ceiling(outputWidth) に設定する。

        2. outputHeight を ceiling(outputHeight) に設定する。

    5. outputHeight または outputWidth のいずれかが有効な 次元でない場合、送出するのは TypeError である。

    6. options.layout に応じて分岐する:

      "nchw"

      outputShape を « batches, channels, outputHeight, outputWidth » とする。

      "nhwc"

      outputShape を « batches, outputHeight, outputWidth, channels » とする。

    7. desc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  20. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、options を与えた op 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  21. output を返す。

次のプーリングアルゴリズムがサポートされる。
averagePool2d(input, options) メソッドの手順は次のとおり:
  1. output を、"averagePool2d"、input、options、および « "float32", "float16", "bfloat16" » を与えてプーリング演算を 作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

l2Pool2d(input, options) メソッドの手順は次のとおり:
  1. output を、"l2Pool2d"、input、options、および « "float32", "float16", "bfloat16" » を与えてプーリング演算を 作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

maxPool2d(input, options) メソッドの手順は次のとおり:
  1. output を、"maxPool2d"、input および options を与えてプーリング演算を 作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

8.9.37.1. averagePool2d
feature map のパッチの平均値を計算し、それを使用してプールされた feature map を作成します。詳細については § 8.9.37 プーリング演算を参照してください。
8.9.37.2. l2Pool2d
入力 feature map の領域に L2 ノルム関数を適用します。L2 ノルムは、 その要素の二乗和の平方根です。詳細については § 8.9.37 プーリング演算を 参照してください。
8.9.37.3. maxPool2d
feature map のパッチの最大値を計算し、それを使用してプールされた feature map を作成します。詳細については § 8.9.37 プーリング演算を参照してください。

8.9.38. prelu

入力テンソルに対して要素単位でrectified linear 関数の パラメトリック版(Parametric ReLU)を計算します。Parametric ReLU は leaky ReLU の一種であり、0.01 のようなスカラーの傾きを持つ代わりに、傾き( leakage の係数)をこの演算のモデル学習フェーズ中に学習されるパラメーターにします。計算は 式 max(0, x) + slope * min(0, x) に従います。

この演算はブロードキャスト されます、[numpy-broadcasting-rule] に従って。入力テンソルは双方向にブロードキャスト可能でなければなりません。出力テンソルのランク は入力テンソルの最大ランクです。 出力テンソルの各次元について、そのサイズは入力テンソルのその次元に沿った最大サイズです。

partial interface MLGraphBuilder {
  MLOperand prelu(MLOperand input,
                  MLOperand slope,
                  optional MLOperatorOptions options = {});
};

dictionary MLPreluSupportLimits {
  MLTensorLimits input;
  MLTensorLimits slope;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLPreluSupportLimits prelu;
};
引数:

戻り値:

prelu() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16", "int64", "int32", "int8" "float32", "float16" N 0 から 5
slope 同じ input "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" N 0 から 5

MLPreluSupportLimits には次のメンバーがあります:

input, 型は MLTensorLimits

MLTensorLimits は input オペランド用です。

slope, 型は MLTensorLimits

MLTensorLimits は slope オペランド用です。

output, 型は MLTensorLimits

MLTensorLimits は output オペランド用です。

MLOpSupportLimits には prelu() 用の次のメンバーがあります:

prelu, 型は MLPreluSupportLimits

演算子 prelu() のサポート制限。

prelu(input, slope, options) の メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input または slope のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. input または slope のいずれかのdataType が それぞれの許可されるデータ型のいずれでもない場合(この表による)、送出するのは TypeError である。

  4. outputShape を、slope の形状と input の形状を双方向にブロードキャストした結果とする。

    1. その結果が失敗の場合、送出するのは TypeError である。

  5. descriptor を、input のdataType と outputShape を与えてMLOperandDescriptor を 作成した結果とする。

  6. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と descriptor を与えた結果とする。

    2. operator を、slope と options を与えた "prelu" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input と slope に設定する。

    5. operator の出力を output に設定する。

  7. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function prelu(builder, input, slope) {
  return builder.add(
    builder.max(builder.constant(input.dataType, 0), input),
    builder.mul(
      slope, builder.min(builder.constant(input.dataType, 0), input)));
}

8.9.39. リダクション演算

入力テンソルをすべての次元に沿って、または axes 配列パラメーターで指定された軸に沿ってリダクションします。指定された各軸について、そのインデックスを持つ次元がリダクションされます。つまり、結果のテンソルには keepDimensions が指定されていない限り、その次元は含まれません。結果のテンソルの値は、リダクションされた次元全体のすべての入力値を パラメーターとして受け取る、指定されたリダクション関数を使用して計算されます。
dictionary MLReduceOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> axes;
  boolean keepDimensions = false;
};

partial interface MLGraphBuilder {
  MLOperand reduceL1(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceL2(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceLogSum(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceLogSumExp(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceMax(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceMean(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceMin(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceProduct(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceSum(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceSumSquare(MLOperand input, optional MLReduceOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits reduceL1;
  MLSingleInputSupportLimits reduceL2;
  MLSingleInputSupportLimits reduceLogSum;
  MLSingleInputSupportLimits reduceLogSumExp;
  MLSingleInputSupportLimits reduceMax;
  MLSingleInputSupportLimits reduceMean;
  MLSingleInputSupportLimits reduceMin;
  MLSingleInputSupportLimits reduceProduct;
  MLSingleInputSupportLimits reduceSum;
  MLSingleInputSupportLimits reduceSumSquare;
};

MLReduceOptions には次のメンバーがあります:

axes, 型は sequence<[EnforceRange] unsigned long>

リダクションする次元。これは、入力テンソル内のどの値を リダクション関数で使用するかも指定します。リスト内の軸は [0, N-1] の範囲内でなければならず、N は入力テンソルのランクです。

存在しない場合、すべての次元がリダクションされます。リダクション関数への入力値は 入力テンソル内のすべての値です。

存在し、空でない場合、リダクション関数への入力値は 入力テンソルの指定された次元に対するすべての値です。

存在し、空の場合、どの次元もリダクションされず、出力テンソルの形状は 入力テンソルの形状と同じです。リダクション関数はテンソル内の各値に 個別に適用されます。

keepDimensions, 型は boolean、デフォルトは false

true の場合、出力は入力と同じランクを持ち、リダクションされたすべての次元のサイズを 1 に設定します。

引数:

戻り値: MLOperand。 出力 N-D テンソルのランクは 0 から input の ランクまでの範囲(両端を含む)であり、 axes と keepDimensions に依存します。 入力オペランドがスカラーの場合、リダクション関数はスカラー値に適用され、出力も スカラーです。

reduceL1()/reduceSum()/reduceSumSquare() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16", "int32", "uint32", "int64", "uint64" "float32", "float16", "int32" N 0 から 5
output 同じ input "float32", "float16", "int32" N 0 から 5
reduceL2()/reduceLogSum()/reduceLogSumExp()/reduceMean() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" N 0 から 5
reduceMax()/reduceMin() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32" N 0 から 5
output 同じ input "float32", "float16", "int32" N 0 から 5
reduceProduct() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16", "int32", "uint32", "int64", "uint64" "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" N 0 から 5

MLOpSupportLimits にはリダクション演算用の次のメンバーがあります:

reduceL1, 型は MLSingleInputSupportLimits

演算子 reduceL1() のサポート制限。

reduceL2, 型は MLSingleInputSupportLimits

演算子 reduceL2() のサポート制限。

reduceLogSum, 型は MLSingleInputSupportLimits

演算子 reduceLogSum() のサポート制限。

reduceLogSumExp, 型は MLSingleInputSupportLimits

演算子 reduceLogSumExp() のサポート制限。

reduceMax, 型は MLSingleInputSupportLimits

演算子 reduceMax() のサポート制限。

reduceMean, 型は MLSingleInputSupportLimits

演算子 reduceMean() のサポート制限。

reduceMin, 型は MLSingleInputSupportLimits

演算子 reduceMin() のサポート制限。

reduceProduct, 型は MLSingleInputSupportLimits

演算子 reduceProduct() のサポート制限。

reduceSum, 型は MLSingleInputSupportLimits

演算子 reduceSum() のサポート制限。

reduceSumSquare, 型は MLSingleInputSupportLimits

演算子 reduceSumSquare() のサポート制限。

リダクションの種類:
符号なし整数のリスト inputShape、オプションの符号なし整数のリスト axes、および真偽値 keepDimensions を与えて 縮約の出力サイズを計算するには、次の手順を実行する。 符号なし整数の新しいリスト、 または失敗を返す。
  1. inputRank を inputShape のサイズとする。

  2. axes が与えられていない場合、axes を 0 から inputRank まで(上限を含まない)の範囲とする。

  3. そうでなく、axes に重複する値が含まれるか、その項目のいずれかが 0 から inputRank まで(上限を含まない)の範囲内にない場合、 失敗を返す。

  4. keepDimensions が true の場合:

    1. outputShape を inputShape のクローン とする。

    2. axes の各 axis について:

      1. outputShape[axis] を 1 に設定する。

  5. そうでない場合:

    1. outputShape を空のリストとする。

    2. 0 から inputRank まで(上限を含まない)の範囲内の 各 index について:

      1. axes が index を含まない場合、inputShape[index] を outputShape に付加する。

  6. outputShape を返す。

文字列 op、MLOperand input、MLReduceOptions options、およびオプションのリスト allowedDataTypes を与えて 縮約演算を作成するには、次の手順を実行する:
  1. 表明: op は "reduceL1"、"reduceL2"、 "reduceLogSum"、"reduceLogSumExp"、"reduceMax"、"reduceMean"、"reduceMin"、"reduceProduct"、 "reduceSum"、"reduceSumSquare" のいずれかである。

  2. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  3. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  4. allowedDataTypes が与えられ、それが input のdataType を含まない 場合、送出するのは TypeError である。

  5. outputShape を、input の形状、options.axes (存在する場合)、および options.keepDimensions を与えて 縮約の出力 サイズを計算した結果とする。失敗が返された場合、送出するのは TypeError である。

  6. desc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  7. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、options を与えた op 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  8. output を返す。

次の縮約アルゴリズムがサポートされる。
reduceL1(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceL1"、input、options、および « "float32", "float16", "bfloat16", "int32", "uint32", "int64", "uint64" » を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceL2(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceL2"、input、options、および « "float32", "float16", "bfloat16" » を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceLogSum(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceLogSum"、input、options、および « "float32", "float16", "bfloat16" » を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceLogSumExp(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceLogSumExp"、input、options、および « "float32", "float16", "bfloat16" » を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceMax(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceMax"、input および options を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceMean(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceMean"、input、options、および « "float32", "float16", "bfloat16" » を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceMin(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceMin"、input および options を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceProduct(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceProduct"、input、options、および « "float32", "float16", "bfloat16", "int32", "uint32", "int64", "uint64" » を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceSum(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceSum"、input、options、および « "float32", "float16", "bfloat16", "int32", "uint32", "int64", "uint64" » を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

reduceSumSquare(input, options) メソッドの手順は次のとおり:
  1. output を、"reduceSumSquare"、input、options、および « "float32", "float16", "bfloat16", "int32", "uint32", "int64", "uint64" » を与えて縮約演算を作成した結果とする。

    1. その処理がエラーを送出する場合、そのエラーを再度送出する。

  2. output を返す。

いくつかのリダクション演算の動作は、以下のように他の演算を使用して一般的に エミュレートできますが、ユーザーエージェントは通常、より効率的な実装を備えています。この 分解は参照実装ではなく説明のための例であり、 アルゴリズムや中間結果の精度を規定するものではありません。基盤となる プラットフォームが演算を直接サポートしていない場合、この分解を 実装の指針となるテンプレートとして使用できます。
function reduceLogSum(builder, input, options) {
  return builder.log(builder.reduceSum(input, options));
}

function reduceLogSumExp(builder, input, options) {
  // これは直接分解するよりも数値的に安定している
  // log(reduceSum(exp(input))): 最大値を減算することで
  // 指数値を範囲内に保ち、最後に最大値を加え戻す。
  const maxX =
    builder.reduceMax(input, {axes: options.axes, keepDimensions: true});
  const sumExpX =
    builder.reduceSum(builder.exp(builder.sub(input, maxX)), options);
  return builder.add(
    builder.log(sumExpX), builder.reshape(maxX, sumExpX.shape));
}

function reduceSumSquare(builder, input, options) {
  return builder.reduceSum(builder.pow(input, 2), options);
}
一部の基盤プラットフォームは keepDimensions のようなオプションを直接サポートしていません。これは基盤となるテンソルデータには影響せず、形状のみに影響します。たとえば、入力形状が [2, 3, 4]、軸が 1、かつ keepDimensions が true の場合、期待される出力形状は [2, 1 ,4] です。基盤プラットフォームがリダクションされた 次元を保持しない場合、出力形状は [2, 4] になります。実装は no-op の reshape を [2, 1, 4] に導入できます。同様に、keepDimensions が false であっても、基盤プラットフォームが常にリダクションされた次元を保持する場合、同様の no-op reshape を導入できます。

8.9.40. relu

入力テンソルの整流線形関数を 計算します。
partial interface MLGraphBuilder {
  MLOperand relu(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits relu;
};
引数:

戻り値:

relu() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16", "int64", "int32", "int8" "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" 同じ input 0 から 5

MLOpSupportLimits には relu() 用の次のメンバーがあります:

relu, 型は MLSingleInputSupportLimits

演算子 relu() のサポート制限。

relu(input, options) メソッドの 手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、演算子とする。"relu" 演算用であり、 options を与える。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function relu(builder, input) {
  return builder.max(builder.constant(input.dataType, 0), input);
}

8.9.41. resample2d

軸とスケーリング係数に従って、テンソル値をソース次元からデスティネーション次元へリサンプリング します。
enum MLInterpolationMode {
  "nearest-neighbor",
  "linear"
};

dictionary MLResample2dOptions : MLOperatorOptions {
  MLInterpolationMode mode = "nearest-neighbor";
  sequence<float> scales;
  sequence<[EnforceRange] unsigned long> sizes;
  sequence<[EnforceRange] unsigned long> axes;
};

partial interface MLGraphBuilder {
  MLOperand resample2d(MLOperand input, optional MLResample2dOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits resample2d;
};
引数:

戻り値: MLOperand。 出力 4-D テンソル。

MLResample2dOptions には次のメンバーがあります:

mode, 型は MLInterpolationMode、デフォルトは "nearest-neighbor"

出力テンソルの値を埋めるために使用される補間アルゴリズム。

両方のアルゴリズムは、各空間軸について計算された次の入力から開始します(axes に基づく)。 ここで inputSize は input テンソルの形状によって与えられ、 outputSize は sizes または scales によって与えられ、 outputCoordinate は計算される出力テンソル内の要素を識別します。

scale = outputSize / inputSize
unclampedCoordinate = (outputCoordinate + 0.5) / scale - 0.5
inputCoordinate = clamp(unclampedCoordinate, 0, inputSize - 1)
出力テンソル内の指定された outputCoordinate.x および outputCoordinate.y の位置について、 上記の式は有理数の inputCoordinate.x および inputCoordinate.y を与えます。
nearest-neighbor

上で計算された inputCoordinate.x および inputCoordinate.y は、 次のように出力テンソル値を計算するため、nearest-neighbor サンプリングアルゴリズムへの入力として 使用されます:

x = ceil(inputCoordinate.x - 0.5)
y = ceil(inputCoordinate.y - 0.5)
output tensor value = input tensor value at (x, y)
linear

上で計算された inputCoordinate.x および inputCoordinate.y は、 次のように出力テンソル値を計算するため、双線形サンプリングアルゴリズムへの入力として使用されます:

x0 = floor(inputCoordinate.x)
x1 = ceil(inputCoordinate.x)
y0 = floor(inputCoordinate.y)
y1 = ceil(inputCoordinate.y)
vx0y0 = input tensor value at (x0, y0)
vx1y0 = input tensor value at (x1, y0)
vx0y1 = input tensor value at (x0, y1)
vx1y1 = input tensor value at (x1, y1)
tx = inputCoordinate.x - x0
ty = inputCoordinate.y - y0

vy0 = vx0y0 * (1 - tx) + vx1y0 * tx
vy1 = vx0y1 * (1 - tx) + vx1y1 * tx
output tensor value = vy0 * (1 - ty) + vy1 * ty
scales, 型は sequence<float>

長さ 2 のリスト。 axes の各入力次元に対するスケーリング係数を指定します: [scaleForFirstAxis, scaleForSecondAxis]。 デフォルト値は [1.0, 1.0] です。

sizes, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト。 axes の各入力次元に対するターゲットサイズを指定します: [sizeForFirstAxis, sizeForSecondAxis]。sizes が指定されている場合、scales は無視されます。これは、スケーリング係数の値が入力のターゲットサイズから導出されるためです。

axes, 型は sequence<[EnforceRange] unsigned long>

長さ 2 のリスト。 補間アルゴリズムを適用する入力テンソルの 2 つの次元を指定します。 デフォルト値は [2, 3] です。

resample2d() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16", "uint8", "int8" "float32", "float16" 4 4
output 同じ input "float32", "float16" 4 4

MLOpSupportLimits には resample2d() 用の次のメンバーがあります:

resample2d, 型は MLSingleInputSupportLimits

演算子 resample2d() のサポート制限。

resample2d(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. input のランクが許可されるランクでない場合、送出するのは TypeError である。

  5. options.scales が存在しない場合、それをリスト « 1.0, 1.0 » に設定する。

  6. そうでなく、その項目のいずれかが 0 以下であるか、そのサイズが 2 でない場合、送出するのは TypeError である。

  7. options.sizes が存在する場合、そのサイズが 2 でないか、 またはその項目のいずれかが 0 の場合、送出するのは TypeError である。

  8. options.axes が存在しない場合、それをリスト « 2, 3 » に設定する。

  9. そうでなく、options.axes に重複する値が含まれるか、その項目のいずれかが 0 から input のランクまで(上限を含まない)の範囲内にない場合、送出するのは TypeError である。

  10. 出力形状を計算する:

    1. inputDescriptor を input.[[descriptor]] とする。

    2. outputShape を inputDescriptor.shape のクローン とする。

    3. 各 index について、範囲 0 から options.axes の サイズまで(上限を含まない):

      1. options.sizes が存在する場合、size を options.sizes[index] とする。

      2. そうでない場合、size を floor(input の形状[options.axes[index]] * options.scales[index]) とする。

      3. size が有効な次元でない場合、送出するのは TypeError である。

      4. outputShape[options.axes[index]] を size に設定する。

    4. desc を、inputDescriptor.dataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  11. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、options を与えた "resample2d" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  12. output を返す。

具体的なサンプリングアルゴリズムは、既存の機械学習フレームワークで広く使用されているものに基づいています。たとえば、 次の [4, 4] 入力テンソル(空間次元のみを考慮)から linear リサンプリングを実行する場合:
[   0   1   2   3  ]
[   0   1   2   3  ]
[  12  13  14  15  ]
[  12  13  14  15  ]

[8, 8] 出力テンソルの場合、期待される値は次のとおりです:

[   0   0.25   0.75   1.25   1.75   2.25   2.75   3  ]
[   0   0.25   0.75   1.25   1.75   2.25   2.75   3  ]
[   0   0.25   0.75   1.25   1.75   2.25   2.75   3  ]
[   3   3.25   3.75   4.25   4.75   5.25   5.75   6  ]
[   9   9.25   9.75  10.25  10.75  11.25  11.75  12  ]
[  12  12.25  12.75  13.25  13.75  14.25  14.75  15  ]
[  12  12.25  12.75  13.25  13.75  14.25  14.75  15  ]
[  12  12.25  12.75  13.25  13.75  14.25  14.75  15  ]

これには、サンプリングが均等に分布し、対称であり、画像の ミラーリングに対して堅牢で、隅の値が整列するという便利な特性があります。

8.9.42. reshape

テンソルの形状を新しい形状に変更します。Reshape はテンソルの内容をコピーまたは変更しません。単に 後続の演算に対するテンソルの論理形状を変更します。
partial interface MLGraphBuilder {
  MLOperand reshape(MLOperand input,
                    sequence<[EnforceRange] unsigned long> newShape,
                    optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits reshape;
};
引数:

戻り値: MLOperand。 出力テンソル。出力 テンソルの値は入力テンソルの値と同じです。出力 テンソルの形状は newShape によって指定されます。

reshape() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32", "int8", "uint8" N 0 から 5
output 同じ input "float32", "float16", "int32", "int8", "uint8" N 0 から 5

MLOpSupportLimits には reshape() 用の次のメンバーがあります:

reshape, 型は MLSingleInputSupportLimits

演算子 reshape() のサポート制限。

reshape(input, newShape, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. newShape のサイズが出力テンソルの許可されるランクでない場合(この表による)、送出するのは TypeError である。

  4. outputShape を unsigned long の空の配列とする。

  5. newShape のサイズが 0 の場合、outputShape をスカラー用の空のリスト に設定する。

  6. newShape 内の項目のいずれかが有効な次元でない場合、送出するのは TypeError である。

  7. inputElementCount を、input の形状内のすべての項目の積とする。 次元が空の場合、inputElementCount は 1 となる。

  8. newShape 内のすべての値の積が inputElementCount と等しくない場合、 送出するのは TypeError である。

  9. desc を、input のdataType と newShape を与えてMLOperandDescriptor を 作成した結果とする。

  10. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に this と desc を与えた結果とする。

    2. operator を、options を与えた "reshape" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  11. output を返す。

8.9.43. reverse

指定された軸に沿ってテンソルを反転します。
dictionary MLReverseOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> axes;
};

partial interface MLGraphBuilder {
  MLOperand reverse(MLOperand input, optional MLReverseOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits reverse;
};

MLReverseOptions には次のメンバーがあります:

axes, 型は sequence<[EnforceRange] unsigned long>

反転する入力次元のインデックス。このメンバーが存在しない場合、 すべての次元が反転されるものとして扱われます。明示的に空として渡された場合、どの次元も反転されません。

引数:

戻り値:

reverse() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32" N 0 から 5
output 同じ input "float32", "float16", "int32" 同じ input 0 から 5

MLOpSupportLimits には reverse() 用の次のメンバーがあります:

reverse, 型は MLSingleInputSupportLimits

演算子 reverse() のサポート制限。

reverse(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. inputRank を input のランクとする。

  5. axes が与えられていない場合、axes を 0 から inputRank まで(上限を含まない)の範囲とする。

  6. そうでなく、axes に重複する値が含まれるか、その要素のいずれかが範囲 0 から inputRank まで(上限を含まない)にない場合、 失敗を返す。

  7. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、演算子とする。"reverse" 演算および options 用である。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  8. output を返す。

8.9.44. scatterElements

indices に従って、updates テンソルの値を入力テンソルのコピー上へ軸に沿って scatter します。
dictionary MLScatterOptions : MLOperatorOptions {
  [EnforceRange] unsigned long axis = 0;
};

partial interface MLGraphBuilder {
  MLOperand scatterElements(MLOperand input,
                            MLOperand indices,
                            MLOperand updates,
                            optional MLScatterOptions options = {});
};

dictionary MLScatterSupportLimits {
  MLTensorLimits input;
  MLTensorLimits indices;
  MLTensorLimits updates;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLScatterSupportLimits scatterElements;
};

MLScatterOptions には次のメンバーがあります:

axis, 型は unsigned long、デフォルトは 0

scatter された値を取得する軸。その値は [0, N-1] の範囲内でなければならず、 N は入力テンソルのランクです。

引数:

戻り値: MLOperand。 出力 N-D テンソルのランクは input の ランクに等しいです。

scatterElements() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32" 1 から N 1 から 5
indices "int32", "uint32", "int64" "int32" 同じ input 1 から 5
updates 同じ input "float32", "float16", "int32" 同じ input 1 から 5
output 同じ input "float32", "float16", "int32" 同じ input 1 から 5

MLScatterSupportLimits には次のメンバーがあります:

input, 型は MLTensorLimits

MLTensorLimits は input オペランド用です。

indices, 型は MLTensorLimits

MLTensorLimits は indices オペランド用です。

updates, 型は MLTensorLimits

MLTensorLimits は updates オペランド用です。

output, 型は MLTensorLimits

MLTensorLimits は output オペランド用です。

MLOpSupportLimits には scatterElements() 用の次のメンバーがあります:

scatterElements, 型は MLScatterSupportLimits

演算子 scatterElements() のサポート制限。

indices パラメーターを scatterElements() に渡す場合、入力は実行時まで不明であるため、グラフのビルド時に許可範囲へクランプすることはできません。 指定されたクランプ動作が基盤プラットフォームによって提供されない場合、実装は clamp() をコンパイル済みグラフに導入できます。同様に、基盤プラットフォームが負のインデックスをサポートしない場合、実装は 次元の末尾からの負のインデックスを正の インデックスに変換する演算をコンパイル済みグラフに導入できます。
scatterElements(input, indices, updates, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、indices、および updates のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. indices のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. updates のdataType が input のdataType と等しくない場合、送出するのは TypeError である。

  5. input、indices、または updates のいずれかのランクが それぞれの許可されるランクでない 場合、送出するのは TypeError である。

  6. axis を options.axis とする。

  7. axis が input のランク以上の場合、送出するのは TypeError である。

  8. indicesShapeExpected を input の形状のコピーとする。

  9. indicesShapeExpected[axis] を indices の形状[axis] に設定する。

  10. indices の形状が indicesShapeExpected と等しくない場合、送出するのは TypeError である。

  11. updates の形状が indices の形状と等しくない場合、送出するのは TypeError である。

  12. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、input、indices、updates、および options を与えた 演算子とする。"scatterElements" 演算用である。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input、indices、 および updates に設定する。

    5. operator の出力を output に設定する。

  13. output を返す。

異なるスライス方式で scatterElements がどのように動作するかの例。
// shape [4,3] の input:
//   [[ 0,  1,  2],
//    [10, 11, 12],
//    [20, 21, 22],
//    [30, 31, 32]]
// shape [2,3] の indices:
//   [[3, 1, 1],
//    [2, 0, 3]]
// shape [2,3] の updates:
//   [[-1, -2, -3],
//    [-4, -5, -6]]
// axis = 0 (デフォルト)
// shape [4,3] の output:
//   [[ 0, -5,  2],
//    [10, -2, -3],
//    [-4, 21, 22],
//    [-1, 31, -6]]

const input1 = builder.constant(
  {dataType: 'float32', shape: [4, 3]},
  new Float32Array([0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32]));

const indices1 = builder.constant(
  {dataType: 'uint32', shape: [2, 3]}, new Uint32Array([3, 1, 1, 2, 0, 3]));

const updates1 = builder.constant(
  {dataType: 'float32', shape: [2, 3]},
  new Uint32Array([-1, -2, -3, -4, -5, -6]));

const output1 = builder.scatterElements(input1, indices1, updates1);

// shape [4,3] の input:
//   [[ 0,  1,  2],
//    [10, 11, 12],
//    [20, 21, 22],
//    [30, 31, 32]]
// shape [4,1] の indices:
//   [[2],
//    [1],
//    [0],
//    [2]],
// shape [4,1] の updates:
//   [[-1],
//    [-2],
//    [-3],
//    [-4]],
// axis = 1
// shape [4,3] の output:
//   [[ 0,  1, -1],
//    [10, -2, 12],
//    [-3, 21, 22],
//    [30, 31, -4]]

const indices2 = builder.constant(
  {dataType: 'uint32', shape: [4, 1]}, new Uint32Array([2, 1, 0, 2]));

const updates2 = builder.constant(
  {dataType: 'float32', shape: [4, 1]}, new Uint32Array([-1, -2, -3, -4]));

const output2 = builder.scatterElements(input1, indices2, updates2, {axis: 1});

// shape [4,2,2] の input:
//   [[[  0,   1],
//     [ 10,  11]],
//    [[100, 101],
//     [110, 111]],
//    [[200, 201],
//     [210, 211]],
//    [[300, 301],
//     [310, 311]],]
// shape [1,2,2] の indices:
//   [[[0, 2],
//     [1, 3]]],
// shape [1,2,2] の updates:
//   [[[-1, -2],
//     [-3, -4]]],
// axis = 0
// shape [4,2,2] の output:
//   [[[ -1,   1],
//     [ 10,  11]],
//    [[100, 101],
//     [ -3, 111]],
//    [[200,  -2],
//     [210, 211]],
//    [[300, 301],
//     [310,  -4]],]

const inputData3 = new Float32Array(
  [0, 1, 10, 11, 100, 101, 110, 111, 200, 201, 210, 211, 300, 301, 310, 311]);

const input3 =
  builder.constant({dataType: 'float32', shape: [4, 2, 2]}, inputData3);

const indices3 = builder.constant(
  {dataType: 'uint32', shape: [1, 2, 2]}, new Uint32Array([0, 2, 1, 3]));

const updates3 = builder.constant(
  {dataType: 'float32', shape: [1, 2, 2]}, new Uint32Array([-1, -2, -3, -4]));

const output3 = builder.scatterElements(input3, indices3, updates3, {axis: 0});

8.9.45. scatterND

indices に従って、updates テンソルの値のスライスを入力テンソルのコピー上に scatter します。
partial interface MLGraphBuilder {
  MLOperand scatterND(MLOperand input,
                      MLOperand indices,
                      MLOperand updates,
                      optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLScatterSupportLimits scatterND;
};
引数:

戻り値: MLOperand。 出力 N-D テンソルのランクは input の ランク + indices の ランク - indices の shape[-1] - 1 に等しいです。

scatterND() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32" 1 から N 1 から 5
indices "int32", "uint32", "int64" "int32" 1 から N 1 から 5
updates 同じ input "float32", "float16", "int32" N 0 から 5
output 同じ input "float32", "float16", "int32" 1 から N 1 から 5

MLOpSupportLimits には scatterND() 用の次のメンバーがあります:

scatterND, 型は MLScatterSupportLimits

演算子 scatterND() のサポート制限。

indices パラメーターを scatterND() に渡す場合、入力は実行時まで不明であるため、グラフのビルド時に許可範囲へクランプすることはできません。 指定されたクランプ動作が基盤プラットフォームによって提供されない場合、実装は clamp() をコンパイル済みグラフに導入できます。 同様に、基盤プラットフォームが負のインデックスをサポートしない場合、実装は 次元の末尾からの負のインデックスを正の インデックスに変換する演算をコンパイル済みグラフに導入できます。
scatterND(input, indices, updates, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input、indices、および updates のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. indices のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. updates のdataType が input のdataType と等しくない場合、送出するのは TypeError である。

  5. input、indices、または updates のいずれかのランクが それぞれの許可されるランクでない 場合、送出するのは TypeError である。

  6. inputShape を input の形状とし、inputRank を input のランクとする。

  7. indicesShape を indices の形状とし、indicesRank を indices のランクとする。

  8. indexableSize を indicesRank - 1 とする。

  9. coordinateSize を indicesShape[indexableSize] とする。

  10. coordinateSize が inputRank より大きい場合、送出するのは TypeError である。

  11. expectedUpdatesShape を空のリストとする。

  12. 各 index について、範囲 0 から indexableSize まで(上限を含まない):

    1. 付加するのは indicesShape[index] で、 付加先は expectedUpdatesShape である。

  13. 各 index について、範囲 coordinateSize から inputRank まで(上限を含まない):

    1. 付加するのは inputShape[index] で、 付加先は expectedUpdatesShape である。

  14. updates の形状が expectedUpdatesShape と等しくない場合、送出するのは TypeError である。

  15. outputShape を input の形状のコピーとする。

  16. outputDesc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  17. グラフ接続を作成する:

    1. output を、MLOperand を 作成する際に outputDesc を与えた結果とする。

    2. operator を、input、indices、updates、および options を与えた 演算子とする。"scatterND" 演算用である。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input、indices、 および updates に設定する。

    5. operator の出力を output に設定する。

  18. output を返す。

異なるスライス方式で scatterND がどのように動作するかの例。
// shape [8] の input:
//   [0, 1, 2, 3, 4, 5, 6, 7]
// shape [4, 1] の indices:
//   [[4],
//    [3],
//    [1],
//    [7]]
// shape [4] の updates:
//   [-1, -2, -3, -4]
// shape [8] の output:
//   [0, -3, 2, -2, -1, 5, 6, -4]

const input1 = builder.constant(
  {dataType: 'float32', shape: [8]},
  new Float32Array([0, 1, 2, 3, 4, 5, 6, 7]));

const indices1 = builder.constant(
  {dataType: 'uint32', shape: [4, 1]}, new Uint32Array([4, 3, 1, 7]));

const updates1 = builder.constant(
  {dataType: 'uint32', shape: [4]}, new Uint32Array([-1, -2, -3, -4]));

const output1 = builder.scatterND(input1, indices1, updates1);

// shape [2,2] の input:
//   [[0, 1],
//    [2, 3]]
// shape [2,2] の indices:
//   [[0, 0],
//    [1, 1]]
// shape [2] の updates:
//   [-1, -2]
// shape [2,2] の output:
//   [[-1,  1],   <= -1 を出力座標 [0, 0] に書き込む
//    [ 2, -2]]   <= -2 を出力座標 [1, 1] に書き込む

const input2 = builder.constant(
  {dataType: 'float32', shape: [2, 2]}, new Float32Array([0, 1, 2, 3]));

const indices2 = builder.constant(
  {dataType: 'uint32', shape: [2, 2]}, new Uint32Array([0, 0, 1, 1]));

const updates2 =
  builder.constant({dataType: 'uint32', shape: [2]}, new Uint32Array([-1, -2]));

const output2 = builder.scatterND(input2, indices2, updates2);

// shape [3,2] の input:
//   [[0, 1],
//    [2, 3],
//    [4, 5]]
// shape [2,1] の indices:
//   [[2],
//    [0]]
// shape [2,2] の updates:
//   [[-1, -2],
//    [-3, -4]]
// shape [3,2] の output:
//   [[-3 ,-4],    <= [-3, -4] を出力座標 [0, *] に書き込む
//    [ 2,  3],
//    [-1, -2]]    <= [-1, -2] を出力座標 [2, *] に書き込む

const input3 = builder.constant(
  {dataType: 'float32', shape: [3, 2]}, new Float32Array([0, 1, 2, 3, 4, 5]));

const indices3 = builder.constant(
  {dataType: 'uint32', shape: [2, 1]}, new Uint32Array([1, 0]));

const updates3 = builder.constant(
  {dataType: 'uint32', shape: [2, 2]}, new Uint32Array([-1, -2, -3, 4]));

const output3 = builder.scatterND(input3, indices3, updates3);

// shape [2,2,2] の input:
//   [[[0, 1],
//     [2, 3]],
//    [[4, 5],
//     [6, 7]]]
// shape [2,2] の indices:
//   [[0, 1],
//    [1, 0]]
// shape [2,2] の updates:
//   [[-1, -2],
//    [-3, -4]]
// shape [2,2,2] の output:
//   [[[ 0,  1],
//     [-1, -2]],   <= [-1, -2] を出力座標 [0, 1, *] に書き込む
//    [[-3, -4],    <= [-3, -4] を出力座標 [1, 0, *] に書き込む
//     [ 6,  7]]]

const input4 = builder.constant(
  {dataType: 'float32', shape: [2, 2, 2]},
  new Float32Array([0, 1, 2, 3, 4, 5, 6, 7]));

const indices4 = builder.constant(
  {dataType: 'uint32', shape: [2, 2]}, new Uint32Array([0, 1, 1, 0]));

const updates4 = builder.constant(
  {dataType: 'uint32', shape: [2, 2]}, new Uint32Array([-1, -2, -3, 4]));

const output4 = builder.scatterND(input4, indices4, updates4);

8.9.46. sigmoid

入力テンソルのシグモイド関数を計算します。 計算は式 1 / (exp(-x) + 1) に従います。
partial interface MLGraphBuilder {
  MLOperand sigmoid(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits sigmoid;
};
引数:

戻り値:

sigmoid() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" 同じ input 0 から 5

MLOpSupportLimits には sigmoid() 用の次のメンバーがあります:

sigmoid, 型は MLSingleInputSupportLimits

演算子 sigmoid() のサポート制限。

sigmoid(input, options) メソッドの 手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、演算子とする。"sigmoid" 演算用であり、 options を与える。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function sigmoid(builder, input) {
  return builder.div(
    builder.constant(input.dataType, 1),
    builder.add(
      builder.exp(builder.neg(input)), builder.constant(input.dataType, 1)));
}

8.9.47. slice

入力テンソルのスライスを生成します。
dictionary MLSliceOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> strides;
};

partial interface MLGraphBuilder {
  MLOperand slice(MLOperand input,
                  sequence<[EnforceRange] unsigned long> starts,
                  sequence<[EnforceRange] unsigned long> sizes,
                  optional MLSliceOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits slice;
};

MLSliceOptions には次のメンバーがあります:

strides, 型は sequence<[EnforceRange] unsigned long>

各軸に沿って各入力をステップするためのストライド。 strides 配列の長さは入力テンソルのランクと等しくなければなりません。 デフォルトは、すべて 1 からなる長さランクの配列です。 たとえば 3-D テンソルでは [1,1,1] です。 ストライドは 0 より大きくなければなりません。

引数:

戻り値: MLOperand。 入力テンソルと同じランクを持ち、各次元の指定された 開始インデックスと終了インデックスに従ってテンソル値を切り出した出力テンソル。

slice() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32", "int8", "uint8" N 0 から 5
output 同じ input "float32", "float16", "int32", "int8", "uint8" 同じ input 0 から 5

MLOpSupportLimits には slice() 用の次のメンバーがあります:

slice, 型は MLSingleInputSupportLimits

演算子 slice() のサポート制限。

slice(input, starts, sizes, options) の メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. sizes の項目のいずれかが 0 の 場合、送出するのは TypeError である。

  4. starts のサイズと sizes のサイズの 少なくとも一方が input のランクと等しくない場合、送出するのは TypeError である。

  5. strides を新しいリストとする。

  6. options.strides が存在する場合:

    1. strides を options.strides に設定する。

    2. strides のサイズが input のランクと等しくない場合、送出するのは TypeError である。

  7. inputShape を input の形状とし、inputRank を input のランクとする。

  8. outputShape を新しいリストとする。

  9. 各 index について、範囲 0 から inputRank まで(上限を含まない):

    1. inputSize を inputShape[index] とする。

    2. inputSliceSize を sizes[index] とする。

    3. stride を、strides[index] が空でなければその値、そうでなければ 1 とする:

    4. inputSliceSize が 0 の場合、送出するのは TypeError である。

      サイズ 0 の次元が許可される場合、これらの手順を修正する。[Issue #391]

    5. stride が 1 未満の場合、送出するのは TypeError である。

    6. starts[index] が inputSize より大きい場合、送出するのは TypeError である。

    7. starts[index] + inputSliceSize が inputSize より大きい場合、送出するのは TypeError である。

    8. outputSizeRoundingExcess を、inputSliceSize % stride != 0 の場合は 1、それ以外の場合は 0 とする。

    9. outputSize を floor(inputSliceSize / stride) + outputSizeRoundingExcess とする:

    10. 付加するのは outputSize で、 付加先は outputShape である。

  10. outputDesc を、input のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  11. グラフ接続を作成する:

    1. output を、outputDesc を与えてMLOperand を 作成した結果とする。

    2. operator を、starts、sizes、および options を与えた演算子とする。"slice" 演算用である。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  12. output を返す。

8.9.48. softmax

指定された軸に沿って N-D 入力テンソルのsoftmax 値を 計算します。
partial interface MLGraphBuilder {
  MLOperand softmax(MLOperand input,
                    [EnforceRange] unsigned long axis,
                    optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits softmax;
};
引数:

戻り値:

softmax() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" 1 から N 1 から 5
output 同じ input "float32", "float16" 同じ input 1 から 5

MLOpSupportLimits には softmax() 用の次のメンバーがあります:

softmax, 型は MLSingleInputSupportLimits

演算子 softmax() のサポート制限。

softmax(input, axis, options) の メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType が許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. axis が input のランク以上の場合、送出するのは TypeError である。

  5. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、"softmax" 演算用の演算子とし、これには axis と options を与える。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  6. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function softmax(builder, input, axis) {
  // このサンプルでは、数値的安定性を高めるため、入力値自体の指数ではなく、
  // 最大値までの距離の指数を計算する、よく知られた実装上の工夫 [1] を
  // 使用します。
  // 結果の数値的安定性を向上させます。
  // [1]: https://cs231n.github.io/linear-classify/#softmax
  const maxX = builder.reduceMax(input, {axes: [axis], keepDimensions: true});
  const expX = builder.exp(builder.sub(input, maxX));
  return builder.div(
    expX, builder.reduceSum(expX, {axes: [axis], keepDimensions: true}));
}

8.9.49. softplus

入力テンソルのsoftplus 関数 を計算します。計算は式 ln(1 + exp(x)) に従います。
partial interface MLGraphBuilder {
  MLOperand softplus(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits softplus;
};
引数:

戻り値:

softplus() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" 同じ input 0 から 5

MLOpSupportLimits には softplus() 用の次のメンバーがあります:

softplus, 型は MLSingleInputSupportLimits

演算子 softplus() のサポート制限。

softplus(input, options) の メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType がその許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、演算子とする。"softplus" 演算および options 用である。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function softplus(builder, input) {
  const zero = builder.constant(input.dataType, 0);
  const one = builder.constant(input.dataType, 1);
  return builder.add(
    builder.max(zero, input),
    builder.log(
      builder.add(one, builder.exp(builder.neg(builder.abs(input))))));
}

8.9.50. softsign

入力テンソルのsoftsign 関数を 計算します。計算は式 x / (1 + |x|) に従います。
partial interface MLGraphBuilder {
  MLOperand softsign(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits softsign;
};
この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function softsign(builder, input) {
  return builder.div(
    input,
    builder.add(builder.constant(input.dataType, 1), builder.abs(input)));
}
引数:

戻り値:

softsign() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" 同じ input 0 から 5

MLOpSupportLimits には softsign() 用の次のメンバーがあります:

softsign, 型は MLSingleInputSupportLimits

演算子 softsign() のサポート制限。

softsign(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType がその許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、演算子とする。"softsign" 演算および options 用である。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

8.9.51. split

指定された軸に沿って入力テンソルを複数のサブテンソルに分割します。
dictionary MLSplitOptions : MLOperatorOptions {
  [EnforceRange] unsigned long axis = 0;
};

partial interface MLGraphBuilder {
  sequence<MLOperand> split(
      MLOperand input,
      ([EnforceRange] unsigned long or sequence<[EnforceRange] unsigned long>) splits,
      optional MLSplitOptions options = {});
};

dictionary MLSplitSupportLimits {
  MLTensorLimits input;
  MLTensorLimits outputs;
};

partial dictionary MLOpSupportLimits {
  MLSplitSupportLimits split;
};
引数:

戻り値: sequence<MLOperand>。 分割された出力テンソル。splits が unsigned long の場合、 出力のサイズは splits と等しくなります。 各出力テンソルの形状は input と同じですが、 axis の次元サイズは input の axis に沿った次元サイズを splits で割った商と等しくなります。 splits が sequence<unsigned long> の場合、 出力のサイズは splits のサイズと等しくなります。 i 番目の出力テンソルの形状は input と同じですが、 axis に沿っては 次元サイズが splits[i] です。

MLSplitOptions には次のメンバーがあります:

axis, 型は unsigned long、デフォルトは 0

分割する次元。その値は [0, N-1] の範囲内でなければならず、N は入力 テンソルのランクです。

split() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32" 1 から N 1 から 5
outputs 同じ input "float32", "float16", "int32" 同じ input 1 から 5

MLSplitSupportLimits には次のメンバーがあります:

input, 型は MLTensorLimits

MLTensorLimits は input オペランド用です。

outputs, 型は MLTensorLimits

MLTensorLimits はすべての出力オペランド用です。

MLOpSupportLimits には split() 用の次のメンバーがあります:

split, 型は MLSplitSupportLimits

演算子 split() のサポート制限。

split(input, splits, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. axis を options.axis とする。

  4. axis が input のランク以上の場合、送出するのは TypeError である。

  5. splits が unsigned long の場合、 次を実行する:

    1. splits が有効なテンソル数でない場合、送出するのは TypeError である。

    2. input の形状[axis] % splits が 0 でない場合、送出するのは TypeError である。

    3. そうでない場合、splitCount を splits とする。

  6. splits がsequence<unsigned long> の場合、 次を実行する:

    1. splits のサイズが 有効なテンソル数でない場合、送出するのは TypeError である。

    2. その項目のいずれかが 0 に等しい場合、送出するのは TypeError である。

      サイズが 0 の次元が許可される場合、上記の手順を修正する。[Issue #391]

    3. その項目の合計が input の形状[axis] と等しくない場合、送出するのは TypeError である。

    4. そうでない場合、splitCount を splits のサイズとする。

  7. グラフ接続を作成する:

    1. operator を、"split" 演算用の演算子とし、これには splits と options を与える。

    2. outputs を新しいリストとする。

    3. 各 index について、範囲 0 から splitCount まで(上限を含まない):

      1. operand を、input を与えてMLOperand を コピーした結果とする。

      2. splits が unsigned long の場合、 newDimension を operand の形状[axis] / splits とする。

      3. そうでない場合、newDimension を splits[index] とする。

      4. operand の形状[axis] を newDimension に設定する。

      5. operand.[[operator]] を operator に設定する。

      6. 付加するのは operand で、 付加先は outputs である。

    4. operator の入力を input に設定する。

    5. operator の出力を outputs に設定する。

  8. outputs を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function split(builder, input, splits, options) {
  // このサンプルでは、splits パラメーターが配列である場合を示します。
  const outputs = [];
  const inputShape = input.shape;
  const inputRank = inputShape.length;
  let starts = Array(inputRank).fill(0);
  let sizes = inputShape;
  let start = 0;
  for (const size of splits) {
    starts[options.axis] = start;
    sizes[options.axis] = size;
    outputs.push(builder.slice(input, starts, sizes));
    start += size;
  }
  return outputs;
}

8.9.52. tanh

入力テンソルの双曲線正接関数を 計算します。計算は式 (exp(2 * x) - 1) / (exp(2 * x) + 1) に従います。
partial interface MLGraphBuilder {
  MLOperand tanh(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits tanh;
};
引数:

戻り値:

tanh() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input "float32", "float16", "bfloat16" "float32", "float16" N 0 から 5
output 同じ input "float32", "float16" 同じ input 0 から 5

MLOpSupportLimits には tanh() 用の次のメンバーがあります:

tanh, 型は MLSingleInputSupportLimits

演算子 tanh() のサポート制限。

tanh(input, options) メソッドの 手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のdataType がその許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、演算子とする。"tanh" 演算用であり、 options を与える。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function tanh(builder, input) {
  const one = builder.constant(input.dataType, 1);
  const expNeg2AbsX = builder.exp(
    builder.mul(builder.constant(input.dataType, -2), builder.abs(input)));
  return builder.mul(
    builder.sign(input),
    builder.div(builder.sub(one, expNeg2AbsX), builder.add(one, expNeg2AbsX)));
}

8.9.53. tile

各次元に沿って、指定された回数だけテンソルを繰り返します。
partial interface MLGraphBuilder {
  MLOperand tile(MLOperand input,
                 sequence<unsigned long> repetitions,
                 optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits tile;
};
引数:

戻り値: MLOperand。 反転された N-D テンソル。

tile() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32" N 0 から 5
output 同じ input "float32", "float16", "int32" 同じ input 0 から 5

MLOpSupportLimits には tile() 用の次のメンバーがあります:

tile, 型は MLSingleInputSupportLimits

演算子 tile() のサポート制限。

tile(input, repetitions, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. repetitions のサイズが input のランクと等しくない場合、送出するのは TypeError である。

  4. repetitions の値に 0 が含まれる場合、送出するのは TypeError である。

    サイズが 0 の 次元が許可される場合、これらの手順を修正する。[Issue #391]

  5. outputShape を input の形状のコピーとする。

  6. 各 index について、範囲 0 から outputShape のサイズまで(上限を含まない):

    1. outputShape[index] を outputShape[index] * repetitions[index] に設定する。

  7. outputDescriptor を、input のdataType と outputShape を与えてMLOperandDescriptor を 作成した結果とする。

  8. グラフ接続を作成する:

    1. output を、outputDescriptor を与えてMLOperand を 作成した結果とする。

    2. operator を、演算子とする。"tile" 演算用であり、 options を与える。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  9. output を返す。

8.9.54. transpose

permutation に従って入力テンソルの次元を並べ替えます。
dictionary MLTransposeOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> permutation;
};

partial interface MLGraphBuilder {
  MLOperand transpose(MLOperand input, optional MLTransposeOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits transpose;
};

MLTransposeOptions には次のメンバーがあります:

permutation, 型は sequence<[EnforceRange] unsigned long>

出力形状の並べ替えに使用される値。 デフォルトは [N-1, ..., 0] です。ここで N は入力テンソルのランクで、たとえば 3-D テンソルでは [2,1,0] です。 これらのデフォルト値により、出力は入力を転置したテンソルになります。指定する場合、 値の数は入力テンソルのランクと同じでなければならず、値は重複なく 0 から N-1 の範囲内でなければなりません。

引数:

戻り値: MLOperand。 並べ替えまたは転置された N-D テンソル。

transpose() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16", "int32" N 0 から 5
output 同じ input "float32", "float16", "int32" 同じ input 0 から 5

MLOpSupportLimits には transpose() 用の次のメンバーがあります:

transpose, 型は MLSingleInputSupportLimits

演算子 transpose() のサポート制限。

transpose(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. options.permutation が存在しない場合、options.permutation を input の形状のすべてのインデックスを逆順にしたシーケンスとする。

  4. そうでなく、options.permutation が存在する場合:

    1. そのサイズが input のランクと等しくない 場合、送出するのは TypeError である。

    2. その項目が範囲 0 から input のランクまで(上限を含まない)にない場合、送出するのは TypeError である。

    3. 重複する値が含まれる場合、送出するのは TypeError である。

  5. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、"transpose" 演算用の演算子とし、これには options を与える。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  6. output を返す。

8.9.55. triangular

2-D テンソル(行列)が与えられた場合、入力テンソルの上三角部分または下三角部分のいずれかを含む 2-D テンソルを返します。入力テンソルが 2 より多い次元を持つ場合、それは行列のバッチとして扱われ、 結果は同じ形状を持ちます。
dictionary MLTriangularOptions : MLOperatorOptions {
  boolean upper = true;
  [EnforceRange] long diagonal = 0;
};

partial interface MLGraphBuilder {
  MLOperand triangular(MLOperand input, optional MLTriangularOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits triangular;
};

MLTriangularOptions には次のメンバーがあります:

upper, 型は boolean、デフォルトは true

入力行列の上部または下部のどちらを出力に保持するかを示します。true は上部を保持することを示します。

diagonal, 型は long、デフォルトは 0

入力行列の主対角線より上または下の対角線を何本保持または 除外するかを指定します。値 0 は、主対角線以外の対角線には影響しないことを意味します。

引数:

戻り値: MLOperand。 三角行列、または入力と同じ形状を持つ行列のバッチを表す 出力テンソル。

triangular() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
input 任意 "float32", "float16" 2 から N 2 から 5
output 同じ input "float32", "float16" 同じ input 2 から 5

MLOpSupportLimits には triangular() 用の次のメンバーがあります:

triangular, 型は MLSingleInputSupportLimits

演算子 triangular() のサポート制限。

triangular(input, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と input を与えた結果が false の場合、送出するのは TypeError である。

  3. input のランクがその許可されるランクのいずれでもない場合(この表による)、送出するのは TypeError である。

  4. グラフ接続を作成する:

    1. output を、input を与えてMLOperand をコピーした結果とする。

    2. operator を、"triangular" 演算用の演算子とし、これには options を与える。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を input に設定する。

    5. operator の出力を output に設定する。

  5. output を返す。

異なる diagonal 設定で triangular がどのように動作するかの例。
// input:
//   [[7, 1, 2],
//    [9, 4, 8],
//    [2, 6, 3]]
const input = builder.constant(
  {dataType: 'float32', shape: [3, 3]},
  new Float32Array([7, 1, 2, 9, 4, 8, 2, 6, 3]));

// 上三角行列:
//   [[7, 1, 2],
//    [0, 4, 8],
//    [0, 0, 3]]
const upper = builder.triangular(input);

// 追加の 1 組の対角線を除外した上三角行列:
//   [[0, 1, 2],
//    [0, 0, 8],
//    [0, 0, 0]]
const upperPositive = builder.triangular(input, {diagonal: 1});

// 追加の 1 組の対角線を保持した上三角行列:
//   [[7, 1, 2],
//    [9, 4, 8],
//    [0, 6, 3]]
const upperNegative = builder.triangular(input, {diagonal: -1});

// 下三角行列:
//   [[7, 0, 0],
//    [9, 4, 0],
//    [2, 6, 3]]
const lower = builder.triangular(input, {upper: false});

// 追加の 1 組の対角線を保持した下三角行列:
//   [[7, 1, 0],
//    [9, 4, 8],
//    [2, 6, 3]]
const lowerPositive = builder.triangular(input, {upper: false, diagonal: 1});

// 追加の 1 組の対角線を除外した下三角行列:
//   [[0, 0, 0],
//    [9, 0, 0],
//    [2, 6, 0]]
const lowerNegative = builder.triangular(input, {upper: false, diagonal: -1})

// 2 つのバッチを持つ下三角行列:
//   [[[7, 0, 0],
//     [9, 4, 0],
//     [2, 6, 3]],
//    [[1, 0, 0],
//     [4, 5, 0],
//     [7, 8, 9]]]
const lowerWithBatches = builder.triangular(input, {upper: false});

8.9.56. where

trueValue または falseValue テンソルから、condition テンソルの対応する値に応じて値を選択します。ここで非ゼロは true、ゼロは false です。condition テンソルは多くの場合、要素単位の論理演算のいずれかの出力です。

この演算は、[numpy-broadcasting-rule] に従ってブロードキャスト されます。入力テンソルは双方向にブロードキャスト可能でなければなりません。出力テンソルのランク は入力テンソルの最大ランクです。 出力テンソルの各次元について、そのサイズは入力テンソルのその次元に沿った最大サイズです。

partial interface MLGraphBuilder {
  MLOperand where(MLOperand condition,
                  MLOperand trueValue,
                  MLOperand falseValue,
                  optional MLOperatorOptions options = {});
};

dictionary MLWhereSupportLimits {
  MLTensorLimits condition;
  MLTensorLimits trueValue;
  MLTensorLimits falseValue;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLWhereSupportLimits where;
};
引数:

戻り値: MLOperand。 trueValue または falseValue テンソルのいずれかから要素単位で選択された値を含む出力テンソル。

where() のテンソル制限
オペランド 許可される データ型 必須 データ型 許可されるランク 必須ランク
condition "uint8" "uint8" N 0 から 5
trueValue 任意 "float32", "float16", "int32" N 0 から 5
falseValue 同じ trueValue "float32", "float16", "int32" N 0 から 5
output 同じ trueValue "float32", "float16", "int32" N 0 から 5

MLWhereSupportLimits には次のメンバーがあります:

condition, 型は MLTensorLimits

MLTensorLimits は condition オペランド用です。

trueValue, 型は MLTensorLimits

MLTensorLimits は trueValue オペランド用です。

falseValue, 型は MLTensorLimits

MLTensorLimits は falseValue オペランド用です。

output, 型は MLTensorLimits

MLTensorLimits は output オペランド用です。

MLOpSupportLimits には where() 用の次のメンバーがあります:

where, 型は MLWhereSupportLimits

演算子 where() のサポート制限。

where(condition, trueValue, falseValue, options) メソッドの手順は次のとおり:
  1. this がビルドできない場合、送出するのは "InvalidStateError" DOMException である。

  2. オペランドを検証する際に this と condition、trueValue、および falseValue のいずれかを与えた結果が false の場合、送出するのは TypeError である。

  3. condition、trueValue、または falseValue のいずれかのdataType が、それぞれの許可されるデータ型のいずれでもない 場合(この表による)、送出するのは TypeError である。

  4. outputShape を、trueValue の形状と falseValue の形状を双方向にブロードキャストした結果とする。

    1. その結果が失敗の場合、送出するのは TypeError である。

  5. outputShape を、condition の形状と outputShape を双方向にブロードキャストした結果に設定する。

    1. その結果が失敗の場合、送出するのは TypeError である。

  6. descriptor を、trueValue のdataType と outputShape を与えてMLOperandDescriptor を作成した結果とする。

  7. グラフ接続を作成する:

    1. output を、MLOperand を作成する際に this と descriptor を与えた結果とする。

    2. operator を、condition、trueValue、falseValue、および options を与えた "where" 演算用の演算子とする。

    3. output.[[operator]] を operator に設定する。

    4. operator の入力を condition、 trueValue および falseValue に設定する。

    5. operator の出力を output に設定する。

  8. output を返す。

この演算の動作は、以下のように他の演算を使用して一般的にエミュレートできますが、 ユーザーエージェントは通常、より効率的な実装を備えています。この分解は 参照実装ではなく説明のための例です。アルゴリズムや 中間結果の精度を規定するものではありません。基盤となるプラットフォームが演算を直接 サポートしていない場合、この分解を実装の指針となるテンプレートとして使用できます。
function where(builder, condition, trueValue, falseValue) {
  const c = builder.clamp(condition, {'minValue': 0, 'maxValue': 1});
  builder.add(
    builder.mul(trueValue, builder.cast(c, trueValue.dataType)),
    builder.mul(
      falseValue, builder.cast(builder.logicalNot(c), falseValue.dataType)));
}

9. アルゴリズム

9.1. ブロードキャスト

ブロードキャストは、 WebNN がグラフ構築および計算中に異なる形状のテンソルをどのように扱うかを説明します。これは [NumPy] の影響を強く受け、[numpy-broadcasting-rule] に従います。大まかに言えば、より小さいテンソルに対する 演算をより大きいテンソルの形状全体に「ブロードキャスト」できるようにし、同じ データをコピーせずに繰り返し適用できるようにします。

最も単純な例は、add() や mul() のような要素単位の 二項演算を使用して、スカラー定数を N 次元テンソルに適用することです。 スカラー定数の複数のコピーを含む一致する N 次元テンソルを割り当てて値を設定する必要はなく、 これらの要素単位演算ではスカラー定数を直接使用し、 N 次元テンソル全体にスカラー値をブロードキャストできます。以下の考慮事項により、同じ ロジックが他の次元のテンソルにも適用されます。

入力テンソルの形状は互換でなければなりません。あるテンソルは、最初のテンソルを 最後(最右)の次元から開始して、サイズ 1 の軸に沿って繰り返すか、新しい次元にわたって繰り返すことで「引き伸ばせる」場合、別のテンソルへ単方向に ブロードキャスト可能です。 たとえば、[4] テンソルは 5 回繰り返すことで [5, 4] テンソルへブロードキャストできます。 [1] テンソルは、最後の次元で 4 回、前の次元で 5 回繰り返すことで [5,4] テンソルへ ブロードキャストできます。単方向ブロードキャストは、expand() のようにターゲットテンソルの形状が明示的に与えられる演算で重要です。

2 つのテンソルは、最後の次元から開始してさまざまな次元にわたり相互に 「引き伸ばす」(繰り返す)ことができる場合、双方向にブロードキャスト可能です。たとえば、 [5,1] テンソルは、最初のテンソルを最後の次元で 6 回、2 番目のテンソルを前の次元で 5 回 繰り返すことにより、[1,6] テンソルと双方向にブロードキャストできます。演算結果は [5,6] テンソルになります。双方向ブロードキャストは要素単位の 演算に便利です。

テンソルは、すべての次元を整数倍でターゲットテンソルの形状までアップサンプリングできる場合、ブロック単位でブロードキャスト可能です。たとえば、[4,5] テンソルは、 正確な倍数(16 % 4 = 0、10 % 5 = 0)であるため、第 1 次元の各要素を 4 回、最後の次元の各要素を 2 回繰り返すことで [16,10] テンソルまでブロック単位でブロードキャストできます(たとえば、最後の次元の値 [1,2,3,4,5] は [1,1,2,2,3,3,4,4,5,5] に繰り返されます)。しかし、 [4,5] テンソルは、両方の次元で余りが 0 でないため(9 % 4 = 1、3 % 5 = 3)、 [9,3] テンソルとは互換ではありません。ブロック単位ブロードキャストは、 メモリを節約するために大きなブロック内で共通値を共有するのに役立ちます。両方のテンソルは同じランクを持つことが期待され、 出力形状は単に、小さい方がアップサンプリングされるターゲットテンソルの形状です。

一部の演算では、特別な意味を持つブロードキャストが許可されます。たとえば、matmul() は入力テンソルの最後の 2 次元を行列の行と列として扱い、第 1 行列の列数は 第 2 行列の行数と等しくなければなりません。行列 乗算は追加の次元にわたって双方向にブロードキャストされ、入力テンソルを 乗算する行列のスタックとして扱います。

形状を単方向にブロードキャストするには、shapeFrom および shapeTo について次の手順を実行します。shapeFrom と shapeTo は、 テンソルの次元を表す正の整数のリストであり、 この手順は正の整数の新しいリスト、 または failure を返します。
  1. sizeFrom を shapeFrom のサイズとします。

  2. sizeTo を shapeTo のサイズとします。

  3. sizeFrom > sizeTo の場合、failure を返します。

  4. paddedShapeFrom を shapeFrom の複製とします。

  5. paddedShapeFrom のサイズが sizeTo 未満である間、1 を paddedShapeFrom に先頭追加します。

  6. outputShape を新しいリストとします。

  7. 各 index について 範囲 0 から sizeTo まで(上限を含まない)を反復します:

    1. dimFrom を paddedShapeFrom[index] とします。

    2. dimTo を shapeTo[index] とします。

    3. dimTo が dimFrom と等しくなく、かつ dimFrom が 1 と等しくない場合、failure を返します。

    4. 追加します dimTo を outputShape に。

  8. outputShape を返します。

shapeFrom は shapeTo に単方向にブロードキャスト可能です。これは、shapeFrom と shapeTo を単方向にブロードキャストする処理が failure にならない場合です。

形状を双方向にブロードキャストするには、shapeA および shapeB について次の手順を実行します。shapeA と shapeB は、 テンソルの次元を表す正の整数のリストであり、 この手順は正の整数の新しいリスト、 または failure を返します。
  1. sizeA を shapeA のサイズとします。

  2. sizeB を shapeB のサイズとします。

  3. outputSize を sizeA と sizeB の最大値とします。

  4. paddedA を shapeA の複製とします。

  5. paddedA のサイズが outputSize 未満である間、1 を paddedA に先頭追加します。

  6. paddedB を shapeB の複製とします。

  7. paddedB のサイズが outputSize 未満である間、1 を paddedB に先頭追加します。

  8. outputShape を新しいリストとします。

  9. 各 index について 範囲 0 から outputSize まで(上限を含まない)を反復します:

    1. dimA を paddedA[index] とします。

    2. dimB を paddedB[index] とします。

    3. dimA が dimB と等しくなく、かつ dimA が 1 と等しくなく、かつ dimB が 1 と等しくない場合、failure を返します。

    4. 追加します dimA と dimB の最大値を outputShape に。

  10. outputShape を返します。

shapeA は shapeB に双方向にブロードキャスト可能です。これは、shapeA と shapeB を双方向にブロードキャストする処理が failure にならない場合です。

形状をブロック単位でブロードキャストするには、shapeFrom および shapeTo について次の手順を実行します。shapeFrom と shapeTo は、 テンソルの次元を表す正の整数のリストであり、 この手順は true または false を返します。
  1. shapeFrom のサイズが shapeTo のサイズと等しくない場合、false を返します。

  2. 各 index について 範囲 0 から shapeTo のサイズまで(上限を含まない)を反復します:

    1. shapeTo[index] が shapeFrom[index] で正確に割り切れない場合、false を返します。

  3. true を返します。

shapeFrom は shapeTo にブロック単位でブロードキャスト可能です。これは、shapeFrom と shapeTo をブロック単位で ブロードキャストする処理が true を返す場合です。

9.2. キャスト

明示的な数値キャストは、MLNumber または double として渡されたパラメーターを、入力または出力 MLOperandDataType の MLOperand に一致するよう変換する必要があるアルゴリズムで使用されます。

数値 x を指定された MLOperandDataType dataType にキャストするには、 次の手順を実行します。これらは数値を返します。
  1. dataType に応じて分岐します:

    "float32"

    ConvertToFloat(x, "float32") を返します。

    "float16"

    ConvertToFloat(x, "float16") を返します。

    "bfloat16"

    ConvertToFloat(x, "bfloat16") を返します。

    "float8e4m3"

    ConvertToFloat(x, "float8e4m3") を返します。

    "int64"

    ConvertToInt(x, 64, "signed") を返します。

    "uint64"

    ConvertToInt(x, 64, "unsigned") を返します。

    "int32"

    ConvertToInt(x, 32, "signed") を返します。

    "uint32"

    ConvertToInt(x, 32, "signed") を返します。

    "int8"

    ConvertToInt(x, 8, "signed") を返します。

    "uint8"

    ConvertToInt(x, 8, "unsigned") を返します。

注: キャストへの入力は、Infinity、-Infinity、NaN という特殊値を含む、 範囲と精度に制限のない抽象数です。出力も抽象数ですが、 指定された型で正確に表現可能です。

ConvertToFloat(x, dataType) の手順は次のとおりです:
  1. x が NaN の場合、NaN を返します。

  2. dataType に応じて分岐します:

    "float32"
    1. upperBound を 2128 とします。

    2. lowerBound を -2128 とします。

    3. S を、 [IEEE-754-2019] の有限な binary32 浮動小数点値から -0 を除いた集合とし、特殊値 upperBound および lowerBound を追加します。

    "float16"
    1. upperBound を 216 とします。

    2. lowerBound を -216 とします。

    3. S を、 [IEEE-754-2019] の有限な binary16 浮動小数点値から -0 を除いた集合とし、特殊値 upperBound および lowerBound を追加します。

    "bfloat16"
    1. upperBound を 2128とします。

    2. lowerBound を -2128とします。

    3. S を、 [IEEE-754-2019] の有限な binary32 浮動小数点値のうち、符号化の下位 16 ビットがゼロであるもの(すなわち、 "bfloat16"で表現可能な有限値)から -0 を除いた集合とし、特殊値 upperBound および lowerBound を追加します。

    "float8e4m3"
    1. upperBound を 480 とします。

    2. lowerBound を -480 とします。

    3. S を、 [OCP-OFP8] の E4M3 形式の有限な浮動小数点値から -0 を除いた集合とし、特殊値 upperBound および lowerBound を追加します。

  3. y を S 内で x に最も近い数とし、2 つの等距離の値がある場合は、 仮数部が偶数の数を選択します。この目的では、2 つの特殊値 lowerBound および upperBound は偶数の仮数部を持つものとみなします。

  4. y が upperBoundの場合:

    1. dataType が "float8e4m3"の場合、448 を返します。

    2. +Infinity を返します。

  5. y が lowerBoundの場合:

    1. dataType が "float8e4m3"の場合、-448 を返します。

    2. -Infinity を返します。

  6. y が +0 で、x が負の場合、-0 を返します。

  7. y を返します。

注: これは [WEBIDL]の定義に基づきますが、16 ビットおよび 8 ビット浮動小数点値を対象に含めるよう拡張されています。特殊値 upperBound および lowerBound は、符号化を継続したと仮定した場合に、絶対値が最大の有限値の次に現れる値です。 "float8e4m3" 形式には無限大がないため、これらの値は表現できません。そのため、このアルゴリズムは [OCP-OFP8]の飽和変換を実行します。範囲外の値と無限大は、絶対値が最大の有限値である 448 に変換され、NaN は保持されます。

ConvertToInt(x, bitLength, signedness) の手順は次のとおりです:
  1. signedness が "unsigned" の場合:

    1. lowerBound を 0 とします。

    2. upperBound を 2bitLength - 1 とします。

  2. それ以外の場合:

    1. lowerBound を -(2bitLength - 1) とします。

    2. upperBound を 2bitLength - 1 - 1 とします。

  3. x が -0 の場合、x を +0 に設定します。

  4. x が NaN の場合、+0 を返します。

  5. x を min(max(x, lowerBound), upperBound) に設定します。

  6. x を最も近い整数に丸め、2 つの整数のちょうど中間にある場合は偶数の整数を選び、 -0 ではなく +0 を選びます。

  7. x を返します。

注: これは [WEBIDL] の定義に基づきますが、次の 相違点があります: 64-bit 整数を特別扱いせず、入力 x は抽象 数であり、クランプは常に実行されます。

9.3. その他

リスト A は、A のサイズが B の サイズと等しく、 A 内の各項目が B 内の同じインデックスにある項目と等しい場合、リスト B と等しいです。

[INFRA] に定義が 利用可能になったら、これを削除します。[whatwg/infra Issue #664]

10. 例

次のビルドグラフが与えられた場合:
constant1 ---+
             +--- Add ---> intermediateOutput1 ---+
input1    ---+                                    |
                                                  +--- Mul---> output
constant2 ---+                                    |
             +--- Add ---> intermediateOutput2 ---+
input2    ---+
次のコードはこのグラフを実装します:
// 4 次元のテンソルを使用します。
const TENSOR_SHAPE = [1, 2, 2, 2];
const TENSOR_SIZE = 8;

const context = await navigator.ml.createContext();
const builder = new MLGraphBuilder(context);

// MLOperandDescriptor オブジェクトを作成します。
const desc = {
  dataType: 'float32',
  shape: TENSOR_SHAPE
};

// constant1 は値 0.5 を持つ定数 MLOperand です。
const constantBuffer1 = new Float32Array(TENSOR_SIZE).fill(0.5);
const constant1 = builder.constant(desc, constantBuffer1);

// input1 は入力 MLOperand の 1 つです。その値は
// 実行前に設定されます。
const input1 = builder.input('input1', desc);

// constant2 は値 0.5 を持つ別の定数 MLOperand です。
const constantBuffer2 = new Float32Array(TENSOR_SIZE).fill(0.5);
const constant2 = builder.constant(desc, constantBuffer2);

// input2 は別の入力 MLOperand です。その値は実行前に設定されます。
const input2 = builder.input('input2', desc);

// intermediateOutput1 は最初の Add 演算の出力です。
const intermediateOutput1 = builder.add(constant1, input1);

// intermediateOutput2 は 2 番目の Add 演算の出力です。
const intermediateOutput2 = builder.add(constant2, input2);

// output は Mul 演算の出力 MLOperand です。
const output = builder.mul(intermediateOutput1, intermediateOutput2);

11. 演算子のエミュレーション

このセクションは非規範的です。

他のニューラルネットワーク推論 API に存在する演算は、多くの場合、WebNN に存在する演算を使用して エミュレートできます。

11.1. squeeze

squeeze 演算は、 入力の指定されたサイズ 1 のすべての次元を削除したテンソルを返します。これは reshape() 演算を使用して次のように一般的に実装できます:
function squeeze(builder, input, axes) {
  if (!axes)
    axes = [];
  if (!axes.length)
    input.shape.forEach((item, i) => {
      axes.push(i);
    });
  const shape = Array.from(input.shape);
  for (let axis of axes.sort().reverse())
    if (axis < shape.length && shape[axis] == 1)
      shape.splice(axis, 1);
  return builder.reshape(input, shape);
}

11.2. unsqueeze

unsqueeze 演算は、 指定された位置にサイズ 1 の次元を挿入した新しいテンソルを返します。これは reshape() 演算を使用して次のように一般的に実装できます:
function unsqueeze(builder, input, axes) {
  const shape = Array.from(input.shape);
  for (let axis of axes.sort())
    shape.splice(axis, 0, 1);
  return builder.reshape(input, shape);
}

11.3. flatten

flatten 演算は、 入力を 1 次元テンソルに reshape します。これは reshape() 演算を使用して次のように一般的に実装できます:
function flatten(builder, input, axis) {
  if (axis > input.shape.length)
    return input;
  const before = axis.slice(0, axis).reduce((a, b) => a * b, 1);
  const after = axis.slice(axis, input.shape.length).reduce((a, b) => a * b, 1);
  return builder.reshape(input, [before, after]);
}

12. 付録

12.1. MLOperandDataType と ArrayBufferView の互換性

MLOperandDataType ArrayBufferView
float32 Float32Array
float16 Float16Array
int64 BigInt64Array
uint64 BigUint64Array
int32 Int32Array
uint32 Uint32Array
int8 Int8Array
uint8 Uint8Array
bfloat16 Uint16Array
float8e4m3 Uint8Array

Float16Array は現在、 [ECMASCRIPT]の一部となっている。利用可能になる前は、この API の実装では、 "float16" の値の生のビット列を Uint16Array を介して渡すことでエミュレートしていた([Issue webnn#373])。この表によると、 Uint16Array は "float16"用としては受け付けられず、 Float16Array も "bfloat16"用としては受け付けられない。

ArrayBufferView 型には、 "bfloat16" と "float8e4m3"専用の型はない。 Uint16Array の各要素は、1 個の "bfloat16" 値の 16 ビット符号化を、プラットフォームのネイティブバイト順のビットパターンとして保持する。これは、 Float16Array が "float16" の値に使用する規約と同じである。また、 Uint8Array の各要素は、1 個の "float8e4m3" 値の 8 ビット符号化を保持する。符号化には、 § 8.5 MLOperandDescriptor 辞書で説明するものを使用する。この表とは別に、 Uint8Array は、どの MLOperandDataTypeに対しても汎用のビューとして受け付けられる。 記述子によるバッファの検証を参照。

13. 謝辞

この仕様は Android Neural Networks API C API の概念に従っています。

ユースケースについて、Tomoyuki Shimizu、Ningxin Hu、Zhiqiang Yu、Belem Zhang に 感謝します。

API 仕様への貢献について、Nikhil Thorat、Daniel Smilkov、Ganesan Ramalingam、Rafael Cintron、 Benjamin Poulain に感謝します。

この仕様について、Web アーキテクチャへの適合性、設計の一貫性、開発者の使いやすさの観点からレビューしていただいた Sangwhan Moon および W3C Technical Architecture Group に感謝します。

アルゴリズムを追加し、この仕様を快適にナビゲートできるようにしてくださった Zoltan Kis に感謝します。 仕様を現代的な編集慣行に合わせてくださった Joshua Bell に感謝します。丁寧なレビューとコメントをしてくださった Ningxin Hu、Lisha Guo、Shiyi Zou、Mingming Xu、Junwei Fu、Bruce Dai、Bin Miao に感謝します。

プライバシーおよびセキュリティのレビューとフィードバックについて W3C Privacy Interest Group に感謝します。

セキュリティレビューと質問について Alex Gough および Chrome Security チームに感謝します。

ONNX から得た実践的なガイドラインと知見を共有してくださった Michal Karzynski に感謝します。

フィードバックとプライバシー上の考慮事項について Kaustubha Govind および Chrome のプライバシーレビュアーに感謝します。

Chromium 実装のレビューとフィードバックについて Jiewei Qian に感謝します。

transformer サポートを調査し、推奨事項を提供する作業を行った Dwayne Robinson、Joshua Lochner、Wanming Lin に感謝します。 演算子の適合性と web-platform-tests 実装のレビューを提供してくださった Dwayne と Wanming にも 改めて感謝します。

web-platform-tests を仕様と並行して進化させ続ける継続的な貢献について Feng Dai に感謝します。

レビューと提案について Fuqiao Xue および W3C Internationalization Activity に感謝します。

14. 変更

このセクションは非規範的です。

このセクションでは、前回の主要公開以降にこの仕様へ加えられた変更を変更のクラスの観点から記録します。

候補勧告スナップショット 2024 年 4 月 11 日 と 2026 年 1 月 22 日 の間の詳細な変更

新機能(class 4)

新機能を追加しないその他の変更(class 3)

文書の解釈に機能的な影響を与えない変更(class 2)

横断的(class 2 および class 3)

編集上の変更(class 2)

適合性

文書の 表記規則

適合性要件は、 説明的な表明と RFC 2119 の用語の組み合わせで表現されます。 キーワード “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、 “MAY”、および “OPTIONAL” は、 この文書の規範的な部分において、 RFC 2119 に記載されているとおりに解釈されるものとします。 ただし、可読性のため、 この仕様ではこれらの語が常にすべて大文字で表記されるわけではありません。

この仕様のすべてのテキストは、非規範的であると明示的に示されたセクション、例、および注記を除き、 規範的です。[RFC2119]

この仕様の例は、“for example” という語で導入されるか、 規範的なテキストから class="example" によって区別されます。 次のようになります:

これは参考例の一例です。

参考注記は “Note” という語で始まり、 規範的なテキストから class="note" によって区別されます。 次のようになります:

注: これは参考注記です。

適合 アルゴリズム

アルゴリズムの一部として命令形で表現された要件 ("先頭の空白文字をすべて除去する" または "false を返してこれらの手順を中止する" など)は、 アルゴリズムを導入する際に使用されたキーワード ("must"、"should"、"may" など)の意味で解釈されるものとします。

アルゴリズムまたは具体的な手順として表現された適合性要件は、 最終結果が同等である限り、 どのような方法でも実装できます。 特に、この仕様で定義されるアルゴリズムは 理解しやすいことを意図しており、 高性能であることを意図していません。 実装者には最適化が推奨されます。

索引

この仕様で定義される 用語

参照先で定義される 用語

参考文献

規範的参考文献

[ECMASCRIPT]
ECMAScript 言語仕様。URL: https://tc39.es/ecma262/multipage/
[HTML]
Anne van Kesteren、ほか。HTML 標準。 現行標準。URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren、Domenic Denicola。Infra 標準。現行標準。URL: https://infra.spec.whatwg.org/
[NUMPY-BROADCASTING-RULE]
SciPy コミュニティ。NumPy の一般的な ブロードキャスト規則。2019 年 7 月。URL: https://numpy.org/doc/stable/user/basics.broadcasting.html#general-broadcasting-rules
[PERMISSIONS-POLICY-1]
Ian Clelland、Ari Chivukula。権限 ポリシー。2026 年 9 月 22 日。作業草案。URL: https://www.w3.org/TR/permissions-policy-1/
[RFC2119]
S. Bradner。要件レベルを 示すために RFC で使用するキーワード。1997 年 3 月。現行のベストプラクティス。URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBGPU]
Kai Ninomiya、Brandon Jones、Jim Blandy。WebGPU。15 2026 年 9 月。勧告候補草案。URL: https://www.w3.org/TR/webgpu/
[WEBIDL]
Edgar Chen、Timothy Gu。Web IDL 標準。現行 標準。URL: https://webidl.spec.whatwg.org/

非規範的参考文献

[Batch-Normalization]
Sergey Ioffe、Christian Szegedy。バッチ正規化: 内部共変量シフトの低減による深層ネットワークの学習の高速化。2015 年 3 月。URL: https://arxiv.org/abs/1502.03167
[ContextualLoss]
Roey Mechrez、Itamar Talmi、Lihi Zelnik-Manor。位置合わせされていない データを用いた画像変換のためのコンテキスト損失。2018 年 7 月。URL: https://arxiv.org/abs/1803.02077
[DeepLabv3+]
Liang-Chieh Chen、ほか。セマンティック画像セグメンテーションのための Atrous 分離可能畳み込みを用いたエンコーダー・デコーダー。2018 年 8 月。URL: https://arxiv.org/abs/1802.02611
[DeepMoji]
Bjarke Felbo、ほか。数百万件の絵文字の使用例を用いて 感情極性、感情、皮肉を検出するためのドメイン非依存の表現を学習する。2017 年 10 月。 URL: https://arxiv.org/abs/1708.00524
[ELU]
Djork-Arné Clevert、Thomas Unterthiner、Sepp Hochreiter。指数線形ユニットによる高速かつ高精度な 深層ネットワークの学習(ELU)。2016 年 2 月。URL: https://arxiv.org/abs/1511.07289
[Error-Function]
Larry C. Andrews。技術者のための数学の特殊 関数。1998 年。URL: https://books.google.com/books?id=2CAqsF-RebgC&pg=PA110
[FaceForensics++]
Andreas Rössler、ほか。FaceForensics++。 2019 年 1 月。URL: https://github.com/ondyari/FaceForensics
[FaceNet]
Florian Schroff、Dmitry Kalenichenko、James Philbin。FaceNet: 顔認識と クラスタリングのための統一的な埋め込み。2015 年 6 月。URL: https://arxiv.org/abs/1503.03832
[FAN]
Adrian Bulat、Georgios Tzimiropoulos。2D および 3D の顔位置合わせ問題の 解決まであとどれほどか?(および 230,000 個の 3D 顔 ランドマークのデータセット)。2017 年 9 月。URL: https://arxiv.org/abs/1703.07332
[GNMT]
Minh-Thang Luong、Eugene Brevdo、Rui Zhao。ニューラル機械 翻訳(seq2seq)チュートリアル。2017 年 5 月。URL: https://github.com/tensorflow/nmt
[GPT2]
Alec Radford、ほか。言語 モデルは教師なしマルチタスク学習器である。2019 年 2 月。URL: https://d4mucfpksywv.cloudfront.net/better-language-models/language-models.pdf
[GRU]
Kyunghyun Cho、ほか。統計的機械翻訳のための RNN エンコーダー・デコーダーを用いた句表現の学習。2014 年 9 月。URL: https://arxiv.org/pdf/1406.1078.pdf
[HR-TIME-3]
Yoav Weiss。高精度時刻。2026 年 9 月 1 日。 作業草案。URL: https://www.w3.org/TR/hr-time-3/
[IEEE-754-2019]
浮動小数点 演算の IEEE 標準。2019 年 7 月 22 日。URL: https://ieeexplore.ieee.org/document/8766229
[IM2TXT]
Oriol Vinyals、ほか。Show and Tell: 2015 年の MSCOCO 画像キャプション生成チャレンジから得られた教訓。2016 年 9 月。URL: https://arxiv.org/abs/1609.06647
[Instance-Normalization]
Dmitry Ulyanov、Andrea Vedaldi、Victor Lempitsky。インスタンス 正規化: 高速なスタイル変換に欠けていた要素。2016 年 7 月。URL: https://arxiv.org/abs/1607.08022
[Layer-Normalization]
Jimmy Lei Ba、Jamie Ryan Kiros、Geoffrey E. Hinton。レイヤー 正規化。2016 年 7 月。URL: https://arxiv.org/abs/1607.06450
[LDM]
Robin Rombach、ほか。潜在拡散モデルによる 高解像度画像合成。2022 年 4 月。URL: https://arxiv.org/abs/2112.10752
[LeakyReLU]
Andrew L. Maas、Awni Y. Hannun、Andrew Y. Ng。整流器の 非線形性によるニューラルネットワーク音響モデルの改善。2013 年 6 月。URL: https://pdfs.semanticscholar.org/367f/2c63a6f6a10b3b64b8729d601e69337ee3cc.pdf
[LLAMA-2-7B]
Hugo Touvron、ほか。Llama 2: オープンな基盤モデルと ファインチューニングされたチャットモデル。2023 年 7 月。URL: https://arxiv.org/abs/2307.09288
[LSTM]
Sepp Hochreiter、Jürgen Schmidhuber。長期・ 短期記憶。1997 年 11 月。URL: https://doi.org/10.1162/neco.1997.9.8.1735
[m2m100_418M]
Angela Fan、ほか。英語中心主義を超えた多言語 機械翻訳。2020 年 10 月。URL: https://arxiv.org/abs/2010.11125
[MaskR-CNN]
Kaiming He、ほか。Mask R-CNN。2018 年 1 月。 URL: https://arxiv.org/abs/1703.06870
[MobileNetV3]
Andrew Howard、ほか。MobileNetV3 の探索。 2019 年 11 月。URL: https://arxiv.org/pdf/1905.02244
[MODELS]
Web 向け機械学習コミュニティグループ。第 1 波のモデル。2020 年。URL: https://github.com/webmachinelearning/webnn/blob/master/op_compatibility/first_wave_models.md
[NumPy]
SciPy コミュニティ。NumPy。2019 年 7 月。URL: https://numpy.org/doc/stable/
[OCP-OFP8]
Stuart Oberman ほか。 OCP 8 ビット浮動小数点仕様(OFP8)、改訂 1.1。2026年1月。URL: https://www.opencompute.org/documents/ocp-8-bit-floating-point-specification-ofp8-revision-1-1-final-pdf
[OpenNMT]
Guillaume Klein、ほか。OpenNMT: ニューラル機械翻訳のための オープンソースツールキット。2017 年 3 月。URL: https://arxiv.org/abs/1701.02810
[PairedCycleGAN]
Huiwen Chang、ほか。PairedCycleGAN: メイクの適用と除去のための非対称スタイル転送。2018 年 6 月。URL: http://openaccess.thecvf.com/content_cvpr_2018/html/Chang_PairedCycleGAN_Asymmetric_Style_CVPR_2018_paper.html
[PoseNet]
Dan Oved。ブラウザーでのリアルタイム TensorFlow.js を用いた人体姿勢推定。2018 年 5 月。URL: https://medium.com/tensorflow/real-time-human-pose-estimation-in-the-browser-with-tensorflow-js-7dd0bc881cd5
[POWERFUL-FEATURES]
Mike West。セキュアコンテキスト。2023 年 11 月 10 日。 勧告候補草案。URL: https://www.w3.org/TR/secure-contexts/
[Prefix-sum]
Wikipedia コミュニティ。累積和。 2025 年 1 月。URL: https://en.wikipedia.org/wiki/Prefix_sum
[RNNoise]
Jean-Marc Valin。音声ノイズ低減のための再帰型ニューラルネットワーク 。2017 年 9 月。URL: https://github.com/xiph/rnnoise
[SECURITY-PRIVACY-QUESTIONNAIRE]
Theresa O'Connor、Peter Snyder、Simone Onofri。自己レビュー質問票: セキュリティ とプライバシー。2025 年 4 月 18 日。注記。URL: https://www.w3.org/TR/security-privacy-questionnaire/
[SegAny]
Alexander Kirillov、ほか。あらゆるものをセグメント化する。 2023 年 4 月。URL: https://arxiv.org/abs/2304.02643
[SRGAN]
Christian Ledig、ほか。生成的敵対ネットワークを用いた写実的な単一画像 超解像。2017 年 5 月。URL: https://arxiv.org/abs/1609.04802
[SSD]
Wei Liu、ほか。SSD: シングルショット MultiBox 検出器。2016 年 12 月。URL: https://arxiv.org/abs/1512.02325
[T5-SMALL]
Colin Raffel、ほか。統一されたテキスト間 Transformer による 転移学習の限界の探究。2020 年 6 月。URL: https://jmlr.org/papers/volume21/20-074/20-074.pdf
[UTR36]
Mark Davis、Michel Suignard。Unicode の セキュリティに関する考慮事項。2014 年 9 月 19 日。Unicode 技術報告書 #36。URL: https://www.unicode.org/reports/tr36/tr36-15.html
[UTS55]
Robin Leroy、Mark Davis。Unicode ソース コードの取り扱い。2024 年 1 月 29 日。Unicode 技術標準 #55。URL: https://www.unicode.org/reports/tr55/tr55-5.html
[Video-Summarization-with-LSTM]
Ke Zhang、ほか。長・短期記憶を用いた動画要約 。2016 年 10 月。URL: http://www-scf.usc.edu/~zhan355/ke_eccv2016.pdf
[WASM-JS-API-2]
. Ms2ger、Ryan Hunt。WebAssembly JavaScript インターフェース。2026年10月13日。CRD。URL: https://www.w3.org/TR/wasm-js-api-2/
[WCAG]
Michael Cooper、ほか。ウェブコンテンツアクセシビリティガイドライン (WCAG)2.2。2024 年 12 月 12 日。勧告。URL: https://www.w3.org/TR/WCAG22/
[WEBMACHINELEARNING-ETHICS]
Anssi Kostiainen。ウェブ機械学習のための倫理原則 。2024 年 1 月 8 日。草案注記。URL: https://www.w3.org/TR/webmachinelearning-ethics/
[Whisper]
Alec Radford、ほか。大規模な弱教師あり学習による頑健な音声認識 。2022 年 12 月。URL: https://arxiv.org/abs/2212.04356
[YOLO]
Joseph Redmon、ほか。You Only Look Once: 統一された リアルタイム物体検出。2016 年 5 月。URL: https://arxiv.org/abs/1506.02640

IDL 索引

interface mixin NavigatorML {
  [SecureContext, SameObject] readonly attribute ML ml;
};
Navigator includes NavigatorML;
WorkerNavigator includes NavigatorML;

enum MLPowerPreference {
  "default",
  "high-performance",
  "low-power"
};

dictionary MLContextOptions {
  MLPowerPreference powerPreference = "default";
  boolean accelerated = true;
};

[SecureContext, Exposed=(Window, Worker)]
interface ML {
  Promise<MLContext> createContext(optional MLContextOptions options = {});
  Promise<MLContext> createContext(GPUDevice gpuDevice);
};

typedef record<USVString, MLTensor> MLNamedTensors;

dictionary MLContextLostInfo {
  DOMString message;
};

[SecureContext, Exposed=(Window, Worker)]
interface MLContext {
  undefined dispatch(MLGraph graph, MLNamedTensors inputs, MLNamedTensors outputs);

  Promise<MLTensor> createTensor(MLTensorDescriptor descriptor);
  Promise<MLTensor> createExportableTensor(
    MLTensorDescriptor descriptor, GPUDevice gpuDevice);
  Promise<MLTensor> createConstantTensor(
    MLOperandDescriptor descriptor, AllowSharedBufferSource inputData);

  Promise<ArrayBuffer> readTensor(MLTensor tensor);
  Promise<undefined> readTensor(MLTensor tensor, AllowSharedBufferSource outputData);

  undefined writeTensor(MLTensor tensor, AllowSharedBufferSource inputData);

  GPUBuffer exportToGPU(MLTensor tensor);

  MLOpSupportLimits opSupportLimits();

  undefined destroy();

  readonly attribute boolean accelerated;
  readonly attribute Promise<MLContextLostInfo> lost;
};

dictionary MLOpSupportLimits {
  MLInputOperandLayout preferredInputLayout;
  [EnforceRange] unsigned long long maxTensorByteLength;
  MLTensorLimits input;
  MLTensorLimits constant;
  MLTensorLimits output;
};

dictionary MLRankRange {
  unsigned long min;
  unsigned long max;
};

typedef sequence<MLOperandDataType> MLDataTypeList;

dictionary MLTensorLimits {
  MLDataTypeList dataTypes;
  MLRankRange rankRange;
};

dictionary MLBinarySupportLimits {
  MLTensorLimits a;
  MLTensorLimits b;
  MLTensorLimits output;
};

dictionary MLSingleInputSupportLimits {
  MLTensorLimits input;
  MLTensorLimits output;
};

[SecureContext, Exposed=(Window, Worker)]
interface MLGraph {
  undefined destroy();
};

enum MLInputOperandLayout {
  "nchw",
  "nhwc"
};

enum MLOperandDataType {
  "float32",
  "float16",
  "int32",
  "uint32",
  "int64",
  "uint64",
  "int8",
  "uint8",
  "bfloat16",
  "float8e4m3"
};

dictionary MLOperandDescriptor {
  required MLOperandDataType dataType;
  required sequence<[EnforceRange] unsigned long> shape;
};

[SecureContext, Exposed=(Window, Worker)]
interface MLOperand {
  readonly attribute MLOperandDataType dataType;
  readonly attribute FrozenArray<unsigned long> shape;
};

dictionary MLOperatorOptions {
  USVString label = "";
};

typedef (bigint or unrestricted double) MLNumber;

dictionary MLTensorDescriptor : MLOperandDescriptor {
  boolean readable = false;
  boolean writable = false;
};

[SecureContext, Exposed=(Window, Worker)]
interface MLTensor {
  readonly attribute MLOperandDataType dataType;
  readonly attribute FrozenArray<unsigned long> shape;
  readonly attribute boolean readable;
  readonly attribute boolean writable;
  readonly attribute boolean constant;

  undefined destroy();
};

typedef record<USVString, MLOperand> MLNamedOperands;

[SecureContext, Exposed=(Window, Worker)]
interface MLGraphBuilder {
  // Construct the graph builder from the context.
  constructor(MLContext context);

  // Create an operand for a graph input.
  MLOperand input(USVString name, MLOperandDescriptor descriptor);

  // Create an operand for a graph constant.
  MLOperand constant(MLOperandDescriptor descriptor,
                     AllowSharedBufferSource buffer);

  // Create a scalar operand from the specified number of the specified type.
  MLOperand constant(MLOperandDataType dataType, MLNumber value);

  // Create an operand from a specified constant tensor.
  MLOperand constant(MLTensor tensor);

  // Compile the graph up to the specified output operands asynchronously.
  Promise<MLGraph> build(MLNamedOperands outputs);
};

dictionary MLArgMinMaxOptions : MLOperatorOptions {
  boolean keepDimensions = false;
  MLOperandDataType outputDataType = "int32";
};

partial interface MLGraphBuilder {
  MLOperand argMin(MLOperand input, [EnforceRange] unsigned long axis,
                   optional MLArgMinMaxOptions options = {});
  MLOperand argMax(MLOperand input, [EnforceRange] unsigned long axis,
                   optional MLArgMinMaxOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits argMin;
  MLSingleInputSupportLimits argMax;
};

dictionary MLBatchNormalizationOptions : MLOperatorOptions {
  MLOperand scale;
  MLOperand bias;
  [EnforceRange] unsigned long axis = 1;
  double epsilon = 1e-5;
};

partial interface MLGraphBuilder {
  MLOperand batchNormalization(MLOperand input, MLOperand mean, MLOperand variance,
                               optional MLBatchNormalizationOptions options = {});
};

dictionary MLBatchNormalizationSupportLimits {
  MLTensorLimits input;
  MLTensorLimits mean;
  MLTensorLimits variance;
  MLTensorLimits scale;
  MLTensorLimits bias;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLBatchNormalizationSupportLimits batchNormalization;
};

partial interface MLGraphBuilder {
  MLOperand cast(MLOperand input,
                 MLOperandDataType dataType,
                 optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits cast;
};

dictionary MLClampOptions : MLOperatorOptions {
  MLNumber minValue;
  MLNumber maxValue;
};

partial interface MLGraphBuilder {
  MLOperand clamp(MLOperand input, optional MLClampOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits clamp;
};

partial interface MLGraphBuilder {
  MLOperand concat(sequence<MLOperand> inputs,
                   [EnforceRange] unsigned long axis,
                   optional MLOperatorOptions options = {});
};

dictionary MLConcatSupportLimits {
  MLTensorLimits inputs;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLConcatSupportLimits concat;
};

enum MLConv2dFilterOperandLayout {
  "oihw",
  "hwio",
  "ohwi",
  "ihwo"
};

dictionary MLConv2dOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> padding;
  sequence<[EnforceRange] unsigned long> strides;
  sequence<[EnforceRange] unsigned long> dilations;
  [EnforceRange] unsigned long groups = 1;
  MLInputOperandLayout inputLayout = "nchw";
  MLConv2dFilterOperandLayout filterLayout = "oihw";
  MLOperand bias;
};

partial interface MLGraphBuilder {
  MLOperand conv2d(MLOperand input,
                   MLOperand filter,
                   optional MLConv2dOptions options = {});
};

dictionary MLConv2dSupportLimits {
  MLTensorLimits input;
  MLTensorLimits filter;
  MLTensorLimits bias;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLConv2dSupportLimits conv2d;
};

enum MLConvTranspose2dFilterOperandLayout {
  "iohw",
  "hwoi",
  "ohwi"
};

dictionary MLConvTranspose2dOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> padding;
  sequence<[EnforceRange] unsigned long> strides;
  sequence<[EnforceRange] unsigned long> dilations;
  sequence<[EnforceRange] unsigned long> outputPadding;
  sequence<[EnforceRange] unsigned long> outputSizes;
  [EnforceRange] unsigned long groups = 1;
  MLInputOperandLayout inputLayout = "nchw";
  MLConvTranspose2dFilterOperandLayout filterLayout = "iohw";
  MLOperand bias;
};

partial interface MLGraphBuilder {
  MLOperand convTranspose2d(MLOperand input, MLOperand filter,
                            optional MLConvTranspose2dOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLConv2dSupportLimits convTranspose2d;
};

dictionary MLCumulativeSumOptions : MLOperatorOptions {
  boolean exclusive = false;
  boolean reversed = false;
};

partial interface MLGraphBuilder {
  MLOperand cumulativeSum(MLOperand input,
                          unsigned long axis,
                          optional MLCumulativeSumOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits cumulativeSum;
};

partial interface MLGraphBuilder {
  MLOperand add(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand sub(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand mul(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand div(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand max(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand min(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
  MLOperand pow(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLBinarySupportLimits add;
  MLBinarySupportLimits sub;
  MLBinarySupportLimits mul;
  MLBinarySupportLimits div;
  MLBinarySupportLimits max;
  MLBinarySupportLimits min;
  MLBinarySupportLimits pow;
};

partial interface MLGraphBuilder {
  MLOperand equal(MLOperand a,
                  MLOperand b,
                  optional MLOperatorOptions options = {});
  MLOperand notEqual(MLOperand a,
                     MLOperand b,
                     optional MLOperatorOptions options = {});
  MLOperand greater(MLOperand a,
                    MLOperand b,
                    optional MLOperatorOptions options = {});
  MLOperand greaterOrEqual(MLOperand a,
                           MLOperand b,
                           optional MLOperatorOptions options = {});
  MLOperand lesser(MLOperand a,
                   MLOperand b,
                   optional MLOperatorOptions options = {});
  MLOperand lesserOrEqual(MLOperand a,
                          MLOperand b,
                          optional MLOperatorOptions options = {});
  MLOperand logicalNot(MLOperand a, optional MLOperatorOptions options = {});
  MLOperand logicalAnd(MLOperand a,
                       MLOperand b,
                       optional MLOperatorOptions options = {});
  MLOperand logicalOr(MLOperand a,
                      MLOperand b,
                      optional MLOperatorOptions options = {});
  MLOperand logicalXor(MLOperand a,
                       MLOperand b,
                       optional MLOperatorOptions options = {});
  MLOperand isNaN(MLOperand a, optional MLOperatorOptions options = {});
  MLOperand isInfinite(MLOperand a, optional MLOperatorOptions options = {});
};

dictionary MLLogicalNotSupportLimits {
  MLTensorLimits a;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLBinarySupportLimits equal;
  MLBinarySupportLimits notEqual;
  MLBinarySupportLimits greater;
  MLBinarySupportLimits greaterOrEqual;
  MLBinarySupportLimits lesser;
  MLBinarySupportLimits lesserOrEqual;
  MLLogicalNotSupportLimits logicalNot;
  MLBinarySupportLimits logicalAnd;
  MLBinarySupportLimits logicalOr;
  MLBinarySupportLimits logicalXor;
  MLLogicalNotSupportLimits isNaN;
  MLLogicalNotSupportLimits isInfinite;
};

partial interface MLGraphBuilder {
  MLOperand abs(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand ceil(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand cos(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand erf(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand exp(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand floor(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand identity(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand log(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand neg(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand reciprocal(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand roundEven(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand sin(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand sign(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand sqrt(MLOperand input, optional MLOperatorOptions options = {});
  MLOperand tan(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits abs;
  MLSingleInputSupportLimits ceil;
  MLSingleInputSupportLimits cos;
  MLSingleInputSupportLimits erf;
  MLSingleInputSupportLimits exp;
  MLSingleInputSupportLimits floor;
  MLSingleInputSupportLimits identity;
  MLSingleInputSupportLimits log;
  MLSingleInputSupportLimits neg;
  MLSingleInputSupportLimits reciprocal;
  MLSingleInputSupportLimits roundEven;
  MLSingleInputSupportLimits sin;
  MLSingleInputSupportLimits sign;
  MLSingleInputSupportLimits sqrt;
  MLSingleInputSupportLimits tan;
};

partial interface MLGraphBuilder {
  MLOperand dequantizeLinear(MLOperand input,
                             MLOperand scale,
                             MLOperand zeroPoint,
                             optional MLOperatorOptions options = {});
};

dictionary MLQuantizeDequantizeLinearSupportLimits {
  MLTensorLimits input;
  MLTensorLimits scale;
  MLTensorLimits zeroPoint;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLQuantizeDequantizeLinearSupportLimits dequantizeLinear;
};

partial interface MLGraphBuilder {
  MLOperand quantizeLinear(MLOperand input,
                           MLOperand scale,
                           MLOperand zeroPoint,
                           optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLQuantizeDequantizeLinearSupportLimits quantizeLinear;
};

dictionary MLEluOptions : MLOperatorOptions {
  double alpha = 1;
};

partial interface MLGraphBuilder {
  MLOperand elu(MLOperand input, optional MLEluOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits elu;
};

partial interface MLGraphBuilder {
  MLOperand expand(MLOperand input,
                   sequence<[EnforceRange] unsigned long> newShape,
                   optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits expand;
};

dictionary MLGatherOptions : MLOperatorOptions {
  [EnforceRange] unsigned long axis = 0;
};

partial interface MLGraphBuilder {
  MLOperand gather(MLOperand input,
                   MLOperand indices,
                   optional MLGatherOptions options = {});
};

dictionary MLGatherSupportLimits {
  MLTensorLimits input;
  MLTensorLimits indices;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLGatherSupportLimits gather;
};

partial interface MLGraphBuilder {
  MLOperand gatherElements(MLOperand input,
                           MLOperand indices,
                           optional MLGatherOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLGatherSupportLimits gatherElements;
};

partial interface MLGraphBuilder {
  MLOperand gatherND(MLOperand input,
                     MLOperand indices,
                     optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLGatherSupportLimits gatherND;
};

partial interface MLGraphBuilder {
  MLOperand gelu(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits gelu;
};

dictionary MLGemmOptions : MLOperatorOptions {
  MLOperand c;
  double alpha = 1.0;
  double beta = 1.0;
  boolean aTranspose = false;
  boolean bTranspose = false;
};

partial interface MLGraphBuilder {
  MLOperand gemm(MLOperand a, MLOperand b, optional MLGemmOptions options = {});
};

dictionary MLGemmSupportLimits {
  MLTensorLimits a;
  MLTensorLimits b;
  MLTensorLimits c;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLGemmSupportLimits gemm;
};

enum MLGruWeightLayout {
  "zrn",  // update-reset-new gate ordering
  "rzn"   // reset-update-new gate ordering
};

enum MLRecurrentNetworkActivation {
  "relu",
  "sigmoid",
  "tanh"
};

enum MLRecurrentNetworkDirection {
  "forward",
  "backward",
  "both"
};

dictionary MLGruOptions : MLOperatorOptions {
  MLOperand bias;
  MLOperand recurrentBias;
  MLOperand initialHiddenState;
  boolean resetAfter = true;
  boolean returnSequence = false;
  MLRecurrentNetworkDirection direction = "forward";
  MLGruWeightLayout layout = "zrn";
  sequence<MLRecurrentNetworkActivation> activations;
};

partial interface MLGraphBuilder {
  sequence<MLOperand> gru(MLOperand input,
                          MLOperand weight,
                          MLOperand recurrentWeight,
                          [EnforceRange] unsigned long steps,
                          [EnforceRange] unsigned long hiddenSize,
                          optional MLGruOptions options = {});
};

dictionary MLGruSupportLimits {
  MLTensorLimits input;
  MLTensorLimits weight;
  MLTensorLimits recurrentWeight;
  MLTensorLimits bias;
  MLTensorLimits recurrentBias;
  MLTensorLimits initialHiddenState;
  MLTensorLimits output0;
  MLTensorLimits output1;
};

partial dictionary MLOpSupportLimits {
  MLGruSupportLimits gru;
};

dictionary MLGruCellOptions : MLOperatorOptions {
  MLOperand bias;
  MLOperand recurrentBias;
  boolean resetAfter = true;
  MLGruWeightLayout layout = "zrn";
  sequence<MLRecurrentNetworkActivation> activations;
};

partial interface MLGraphBuilder {
  MLOperand gruCell(MLOperand input,
                    MLOperand weight,
                    MLOperand recurrentWeight,
                    MLOperand hiddenState,
                    [EnforceRange] unsigned long hiddenSize,
                    optional MLGruCellOptions options = {});
};

dictionary MLGruCellSupportLimits {
  MLTensorLimits input;
  MLTensorLimits weight;
  MLTensorLimits recurrentWeight;
  MLTensorLimits hiddenState;
  MLTensorLimits bias;
  MLTensorLimits recurrentBias;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLGruCellSupportLimits gruCell;
};

dictionary MLHardSigmoidOptions : MLOperatorOptions {
  double alpha = 0.2;
  double beta = 0.5;
};

partial interface MLGraphBuilder {
  MLOperand hardSigmoid(MLOperand input, optional MLHardSigmoidOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits hardSigmoid;
};

partial interface MLGraphBuilder {
  MLOperand hardSwish(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits hardSwish;
};

dictionary MLInstanceNormalizationOptions : MLOperatorOptions {
  MLOperand scale;
  MLOperand bias;
  double epsilon = 1e-5;
  MLInputOperandLayout layout = "nchw";
};

partial interface MLGraphBuilder {
  MLOperand instanceNormalization(
    MLOperand input,
    optional MLInstanceNormalizationOptions options = {});
};

dictionary MLNormalizationSupportLimits {
  MLTensorLimits input;
  MLTensorLimits scale;
  MLTensorLimits bias;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLNormalizationSupportLimits instanceNormalization;
};

dictionary MLLayerNormalizationOptions : MLOperatorOptions {
  MLOperand scale;
  MLOperand bias;
  sequence<[EnforceRange] unsigned long> axes;
  double epsilon = 1e-5;
};

partial interface MLGraphBuilder {
  MLOperand layerNormalization(MLOperand input,
                               optional MLLayerNormalizationOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLNormalizationSupportLimits layerNormalization;
};

dictionary MLLeakyReluOptions : MLOperatorOptions {
  double alpha = 0.01;
};

partial interface MLGraphBuilder {
  MLOperand leakyRelu(MLOperand input, optional MLLeakyReluOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits leakyRelu;
};

dictionary MLLinearOptions : MLOperatorOptions {
  double alpha = 1;
  double beta = 0;
};

partial interface MLGraphBuilder {
  MLOperand linear(MLOperand input, optional MLLinearOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits linear;
};

enum MLLstmWeightLayout {
  "iofg", // input-output-forget-cell gate ordering
  "ifgo"  // input-forget-cell-output gate ordering
};

dictionary MLLstmOptions : MLOperatorOptions {
  MLOperand bias;
  MLOperand recurrentBias;
  MLOperand peepholeWeight;
  MLOperand initialHiddenState;
  MLOperand initialCellState;
  boolean returnSequence = false;
  MLRecurrentNetworkDirection direction = "forward";
  MLLstmWeightLayout layout = "iofg";
  sequence<MLRecurrentNetworkActivation> activations;
};

partial interface MLGraphBuilder {
  sequence<MLOperand> lstm(MLOperand input,
                           MLOperand weight,
                           MLOperand recurrentWeight,
                           [EnforceRange] unsigned long steps,
                           [EnforceRange] unsigned long hiddenSize,
                           optional MLLstmOptions options = {});
};

dictionary MLLstmSupportLimits {
  MLTensorLimits input;
  MLTensorLimits weight;
  MLTensorLimits recurrentWeight;
  MLTensorLimits bias;
  MLTensorLimits recurrentBias;
  MLTensorLimits peepholeWeight;
  MLTensorLimits initialHiddenState;
  MLTensorLimits initialCellState;
  MLTensorLimits output0;
  MLTensorLimits output1;
  MLTensorLimits output2;
};

partial dictionary MLOpSupportLimits {
  MLLstmSupportLimits lstm;
};


dictionary MLLstmCellOptions : MLOperatorOptions {
  MLOperand bias;
  MLOperand recurrentBias;
  MLOperand peepholeWeight;
  MLLstmWeightLayout layout = "iofg";
  sequence<MLRecurrentNetworkActivation> activations;
};

partial interface MLGraphBuilder {
  sequence<MLOperand> lstmCell(MLOperand input,
                               MLOperand weight,
                               MLOperand recurrentWeight,
                               MLOperand hiddenState,
                               MLOperand cellState,
                               [EnforceRange] unsigned long hiddenSize,
                               optional MLLstmCellOptions options = {});
};

dictionary MLLstmCellSupportLimits {
  MLTensorLimits input;
  MLTensorLimits weight;
  MLTensorLimits recurrentWeight;
  MLTensorLimits hiddenState;
  MLTensorLimits cellState;
  MLTensorLimits bias;
  MLTensorLimits recurrentBias;
  MLTensorLimits peepholeWeight;
  MLTensorLimits output0;
  MLTensorLimits output1;
};

partial dictionary MLOpSupportLimits {
  MLLstmCellSupportLimits lstmCell;
};

partial interface MLGraphBuilder {
  MLOperand matmul(MLOperand a, MLOperand b, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLBinarySupportLimits matmul;
};

enum MLPaddingMode {
  "constant",
  "edge",
  "reflection"
};

dictionary MLPadOptions : MLOperatorOptions {
  MLPaddingMode mode = "constant";
  MLNumber value = 0;
};

partial interface MLGraphBuilder {
  MLOperand pad(MLOperand input,
                sequence<[EnforceRange] unsigned long> beginningPadding,
                sequence<[EnforceRange] unsigned long> endingPadding,
                optional MLPadOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits pad;
};

enum MLRoundingType {
  "floor",
  "ceil"
};

dictionary MLPool2dOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> windowDimensions;
  sequence<[EnforceRange] unsigned long> padding;
  sequence<[EnforceRange] unsigned long> strides;
  sequence<[EnforceRange] unsigned long> dilations;
  MLInputOperandLayout layout = "nchw";
  MLRoundingType outputShapeRounding = "floor";
  sequence<[EnforceRange] unsigned long> outputSizes;
};

partial interface MLGraphBuilder {
  MLOperand averagePool2d(MLOperand input, optional MLPool2dOptions options = {});
  MLOperand l2Pool2d(MLOperand input, optional MLPool2dOptions options = {});
  MLOperand maxPool2d(MLOperand input, optional MLPool2dOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits averagePool2d;
  MLSingleInputSupportLimits l2Pool2d;
  MLSingleInputSupportLimits maxPool2d;
};

partial interface MLGraphBuilder {
  MLOperand prelu(MLOperand input,
                  MLOperand slope,
                  optional MLOperatorOptions options = {});
};

dictionary MLPreluSupportLimits {
  MLTensorLimits input;
  MLTensorLimits slope;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLPreluSupportLimits prelu;
};

dictionary MLReduceOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> axes;
  boolean keepDimensions = false;
};

partial interface MLGraphBuilder {
  MLOperand reduceL1(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceL2(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceLogSum(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceLogSumExp(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceMax(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceMean(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceMin(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceProduct(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceSum(MLOperand input, optional MLReduceOptions options = {});
  MLOperand reduceSumSquare(MLOperand input, optional MLReduceOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits reduceL1;
  MLSingleInputSupportLimits reduceL2;
  MLSingleInputSupportLimits reduceLogSum;
  MLSingleInputSupportLimits reduceLogSumExp;
  MLSingleInputSupportLimits reduceMax;
  MLSingleInputSupportLimits reduceMean;
  MLSingleInputSupportLimits reduceMin;
  MLSingleInputSupportLimits reduceProduct;
  MLSingleInputSupportLimits reduceSum;
  MLSingleInputSupportLimits reduceSumSquare;
};

partial interface MLGraphBuilder {
  MLOperand relu(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits relu;
};

enum MLInterpolationMode {
  "nearest-neighbor",
  "linear"
};

dictionary MLResample2dOptions : MLOperatorOptions {
  MLInterpolationMode mode = "nearest-neighbor";
  sequence<float> scales;
  sequence<[EnforceRange] unsigned long> sizes;
  sequence<[EnforceRange] unsigned long> axes;
};

partial interface MLGraphBuilder {
  MLOperand resample2d(MLOperand input, optional MLResample2dOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits resample2d;
};

partial interface MLGraphBuilder {
  MLOperand reshape(MLOperand input,
                    sequence<[EnforceRange] unsigned long> newShape,
                    optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits reshape;
};

dictionary MLReverseOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> axes;
};

partial interface MLGraphBuilder {
  MLOperand reverse(MLOperand input, optional MLReverseOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits reverse;
};

dictionary MLScatterOptions : MLOperatorOptions {
  [EnforceRange] unsigned long axis = 0;
};

partial interface MLGraphBuilder {
  MLOperand scatterElements(MLOperand input,
                            MLOperand indices,
                            MLOperand updates,
                            optional MLScatterOptions options = {});
};

dictionary MLScatterSupportLimits {
  MLTensorLimits input;
  MLTensorLimits indices;
  MLTensorLimits updates;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLScatterSupportLimits scatterElements;
};

partial interface MLGraphBuilder {
  MLOperand scatterND(MLOperand input,
                      MLOperand indices,
                      MLOperand updates,
                      optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLScatterSupportLimits scatterND;
};

partial interface MLGraphBuilder {
  MLOperand sigmoid(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits sigmoid;
};

dictionary MLSliceOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> strides;
};

partial interface MLGraphBuilder {
  MLOperand slice(MLOperand input,
                  sequence<[EnforceRange] unsigned long> starts,
                  sequence<[EnforceRange] unsigned long> sizes,
                  optional MLSliceOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits slice;
};

partial interface MLGraphBuilder {
  MLOperand softmax(MLOperand input,
                    [EnforceRange] unsigned long axis,
                    optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits softmax;
};

partial interface MLGraphBuilder {
  MLOperand softplus(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits softplus;
};

partial interface MLGraphBuilder {
  MLOperand softsign(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits softsign;
};

dictionary MLSplitOptions : MLOperatorOptions {
  [EnforceRange] unsigned long axis = 0;
};

partial interface MLGraphBuilder {
  sequence<MLOperand> split(
      MLOperand input,
      ([EnforceRange] unsigned long or sequence<[EnforceRange] unsigned long>) splits,
      optional MLSplitOptions options = {});
};

dictionary MLSplitSupportLimits {
  MLTensorLimits input;
  MLTensorLimits outputs;
};

partial dictionary MLOpSupportLimits {
  MLSplitSupportLimits split;
};

partial interface MLGraphBuilder {
  MLOperand tanh(MLOperand input, optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits tanh;
};

partial interface MLGraphBuilder {
  MLOperand tile(MLOperand input,
                 sequence<unsigned long> repetitions,
                 optional MLOperatorOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits tile;
};

dictionary MLTransposeOptions : MLOperatorOptions {
  sequence<[EnforceRange] unsigned long> permutation;
};

partial interface MLGraphBuilder {
  MLOperand transpose(MLOperand input, optional MLTransposeOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits transpose;
};

dictionary MLTriangularOptions : MLOperatorOptions {
  boolean upper = true;
  [EnforceRange] long diagonal = 0;
};

partial interface MLGraphBuilder {
  MLOperand triangular(MLOperand input, optional MLTriangularOptions options = {});
};

partial dictionary MLOpSupportLimits {
  MLSingleInputSupportLimits triangular;
};

partial interface MLGraphBuilder {
  MLOperand where(MLOperand condition,
                  MLOperand trueValue,
                  MLOperand falseValue,
                  optional MLOperatorOptions options = {});
};

dictionary MLWhereSupportLimits {
  MLTensorLimits condition;
  MLTensorLimits trueValue;
  MLTensorLimits falseValue;
  MLTensorLimits output;
};

partial dictionary MLOpSupportLimits {
  MLWhereSupportLimits where;
};

課題索引

実装者への指針として、範囲外アクセスの影響を受ける可能性がある演算を文書化する。 ↵
レンダラーを実行するプロセス間で CPU が共有されている現在の状況を考慮し、 サイドチャネル攻撃の実現可能性を調査する。 ↵
ヒント付与によって懸念は部分的に軽減される。追加の緩和策を調査する。 ↵
グラフが完全に構築およびコンパイルされた後に、実行用として実際に選択されたデバイスを公開するため、 MLGraph.devices API 拡張が提案されている。この API 拡張のプライバシーへの影響は調査中である。 [Issue #836] ↵
dispatch() 中のエラーを報告する仕組みの追加を検討する。 [Issue #778] ↵
このタイムラインをより厳密に定義する。 [Issue #529] ↵
グラフ実行中のエラーを報告する仕組みを追加する。 [Issue #778] ↵
テンソルへの書き込み中のエラーを報告する仕組みを追加する。 [Issue #778] ↵
サイズ 0 の次元をサポートすべきか? [Issue #391] ↵
オペランドの次元数の最大値は定義されていないが、ネイティブ ML API には通常、 サポートされる最大数がある。 [Issue #456] ↵
bigint と 数値型の union のサポートは [WEBIDL] で新たに導入されたものであり、 実装でのサポートも限定的である。プロトタイプ実装には、この アプローチについてフィードバックを提供することが推奨される。 [whatwg/webidl Issue #1388] ↵
サイズ 0 の次元が許可される場合、これらの手順を改訂する。 [Issue #391] ↵
サイズ 0 の次元が許可される場合、上記の手順を改訂する。 [Issue #391] ↵
サイズ 0 の次元が許可される場合、これらの手順を改訂する。 [Issue #391] ↵
[INFRA] に定義が 利用可能になったら、これを削除する。 [whatwg/infra Issue #664] ↵