この記事は、https://www.oneapi.io/spec/ で 2023年9月14日に公開された『oneAPI 1.3 Provisional Specification Rev. 1』 (HTML、PDF) をベースにしています。原文は2000 ページ近くあり、翻訳の時間とリソースも限られるため、全文翻訳ではなく、記事形式で区切った仕様とその解説を提供することにしました。
この回では、『oneAPI 1.3 Provisional Specification Rev. 1』の「oneDNN」の「Batch Normalization」と「Binary」の節を取り上げています。
バッチ正規化
バッチ正規化プリミティブは、次元数が 2 以上のテンソルに対して順方向または逆方法のバッチ正規化操作を実行します。変数名は標準の規則 (英語) に従います。
バッチ正規化操作は、次の式で定義されます。高次元と低次元のケースで一般化が容易な 2D 空間データの式のみを示します。
プリミティブのさまざまな振る舞いは、dnnl::batch_normalization_forward::primitive_desc
などの操作記述子の初期化関数に渡される flags
パラメーターで制御できます。複数のフラグはビットごとの OR 演算子 (|
) を使用して組み合わせることができます。
順方向 (前方)
説明:
γ(c)
とβ(c)
は、チャネルのオプションのスケールとシフトです (use_scale
とuse_shift
フラグで制御されます)。μ(c)
とσ2(c)
は、チャンルの平均と分散 (use_global_stats
フラグで設定) です。ε
は数値の安定性を向上させる定数です。
平均と分散は実行時に計算されるか、ユーザーによって提供されます。平均と分散を実行時に計算する場合、次の式が使用されます
γ(c)
と β(c)
テンソルは学習可能であると見なされます。
訓練モードでは、プリミティブはオプションであり、結果にゼロの負の勾配が適用された ReLU 活性化との融合もサポートされます (fuse_norm_relu
フラグ (英語) を参照)。
注: バッチ正規化プリミティブは、一般に移動平均と分散の計算に使用されるサンプルやバイアスがないバージョンではなく、母平均と分散を計算します。
*バッチ正規化プリミティブによって計算される平均と分散を使用して、移動平均 と分散 (i
は反復回数) は、次のように計算できます。
順方向訓練と順方向推論の違い
平均と分散が実行時に計算される場合 (つまり
use_global_stats
が設定されていない場合)、それらは伝播種別forward_training
の出力となり (逆伝播で必要となります)、伝播種別forward_inference
には提供されません。バッチ正規化が ReLU 融合で作成される場合 (
fuse_norm_relu
が設定される場合)、伝播種別がforward_training
であると、プリミティブは追加出力としてworkspace
メモリーを生成します。このメモリーは逆伝播を計算する際に必要です。プリミティブが伝播種別forward_inference
で実行されると、ワークスペースは生成されません。この動作は、post-op として ReLU を使用したバッチ正規化プリミティブを作成するのと同様です (以下のセクションを参照)。
逆方向 (後方)
逆方向伝播では、diff_dst(n, c, h, w)
、src(n, c, h, w)
、μ(c)
、σ2(c)
、γ(c)*
、および β(c)*
に基づいて、diff_src(n, c, h, w)
、diff_γ(c)*
、および diff_β(c)*
を計算します。
アスタリスク付きのテンソルは、プリミティブが γ(c)
と β(c)
を使用するように構成されている (use_scale
と use_shift
が設定される) 場合にのみ使用されます。
実行引数
フラグと伝播の種別に応じて、バッチ正規化プリミティブには異なる入力 (In) と出力 (Out) が必要です。以下に要約します。
すべての引数の詳細についてはこちらの表 (英語) をご覧ください。
実行時に入力と出力は、次の表で示す実行引数インデックスにマップする必要があります。
プリミティブの入力/出力 | 実行引数インデックス |
---|---|
src | DNNL_ARG_SRC |
γ | DNNL_ARG_SCALE |
β | DNNL_ARG_SHIFT |
mean (μ) | DNNL_ARG_MEAN |
variance (σ) | DNNL_ARG_VARIANCE |
dst | DNNL_ARG_DST |
workspace | DNNL_ARG_WORKSPACE |
diff_dst | DNNL_ARG_DIFF_DST |
diff_src | DNNL_ARG_DIFF_SRC |
diff_γ | DNNL_ARG_DIFF_SCALE |
diff_β | DNNL_ARG_DIFF_SHIFT |
操作の詳細
順伝播の場合、平均と分散は実行時に計算されるか (プリミティブの出力)、ユーザーによって提供されます (入力)。後者の場合、
use_global_stats
フラグを設定する必要があります。逆伝播の場合、平均と分散は常に入力パラメーターとなります。src
とdst
のメモリー形式とデータタイプは同一であると想定され、API ではdata
として参照されます (dnnl::batch_normalization_forward::desc::desc()
(英語) のdata_desc
を参照)。diff_src
とdiff_dst
にも同じことが当てはまります。対応するメモリー記述子はdiff_data_desc
と呼ばれます。順方向と逆方向の両方でインプレース操作がサポートされ、
src
は順方向伝播の入力および出力として使用でき、diff_dst
は逆伝播の入力および出力として使用できます。インプレースの場合、元のデータは上書きされます。ただし、逆伝播では元のsrc
が必要であるため、対応する順伝播をインプレースで実行してはなりません。前述のように、バッチ正規化プリミティブは、訓練モードでも ReLU 活性化と融合できます。この場合、順方向伝播では、プリミティブに 1 つの追加出力
workspace
があり、逆方向伝播に渡される必要があります。
サポートされるデータタイプ
操作は次のデータタイプの組み合わせをサポートします。
注: この節では、可読性のためデータタイプの名称を省略しています。例えば、dnnl::memory::data_type::f32
は f32
に省略されます。
伝播 | ソース/デスティネーション | 平均/分散/スケール/シフト |
---|---|---|
順方向/逆方向 | f32 , bf16 |
f32 |
順方向 | f16 |
f32 |
順方向 | s8 |
f32 |
データ表現
ソース、デスティネーション、およびそれらの勾配
ほかの CNN プリミティブと同様に、バッチ正規化プリミティブはデータが N×C×SPn×⋯× SP0
テンソルであることを期待します。
バッチ正規化プリミティブは次のメモリー形式に最適化されています。
空間 | 論理テンソル | メモリー形式向けに最適化された実装 |
---|---|---|
0D | NC | nc (ab ) |
1D | NCW | ncw (abc ), nwc (acb ), optimized |
2D | NCHW | nchw (abcd ), nhwc (acdb ), optimized |
3D | NCDHW | ncdhw (abcde ), ndhwc (acdeb ), optimized |
ここでいう optimized (最適化) とは、前述の計算集約型プリミティブによって選択された形式を意味します。
統計テンソル
平均 (μ) と分散 (σ2) は、異なるサイズ C
の 1D テンソルです。
対応するメモリー・オブジェクトの形式は x
(a
) である必要があります。
使用する場合、スケール (γ) とシフト (β) は、形状 2×C
の単一 2D テンソルに結合されます。
対応するメモリー・オブジェクトの形式は nc
(ab
) である必要があります。
post-ops と属性
伝播 | タイプ | 操作 | 説明 |
---|---|---|---|
順方向 | post-op | eltwise | eltwise (要素ごとの) 操作を出力に適用します。 |
注: post-op として ReLU を使用しても、逆伝播を正しく計算するために必要な出力は workspace
に生成されません。そのため、訓練には fuse_norm_relu
フラグを使用する必要があります。
API
API については、こちら (英語) をご覧ください。
バイナリー
バイナリー・プリミティブは、テンソル src0
と src1
間のバイナリー要素ごとの演算結果を計算します。
ここで、 と op
は加算、乗算、最大、最小などの演算子です。変数名は標準規則 (英語) に従います。
順方向と逆方向
バイナリー・プリミティブには、順方向と逆方向の伝播の概念がありません。
実行引数
実行時に入力と出力は、次の表で示す実行引数インデックスにマップする必要があります。
プリミティブの入力/出力 | 実行引数インデックス |
---|---|
src0 | DNNL_ARG_src_0 |
src1 | DNNL_ARG_src_1 |
dst |
DNNL_ARG_DST |
操作の詳細
バイナリー・プリミティブでは、すべてのソースとデスティネーション・テンソルの次元は同一でなければなりません。
バイナリー・プリミティブは、
src1
の暗黙のブロードキャストをサポートします。これは、特定の次元の値が 1 である場合、この値を使用して次元のsrc0
のそれぞれのポイントで計算操作を行うことを意味します。dst
メモリー形式は、明示的に指定することも、dnnl::memory::format_tag::any
(推奨) を使用して指定することもできます。この場合、プリミティブはsrc0
テンソルの形式をベースに最も適切なメモリー形式を取得できます。デスティネーション・メモリー記述子は、
src0
メモリー記述子と完全に一致する必要があります。バイナリー・プリミティブはインプレース操作をサポートし、
src0
テンソルをデスティネーションとして使用できます。この場合、データは上書きされます。
post-ops と属性
次の属性をサポートする必要があります。
タイプ | 操作 | 説明 | 制限事項 |
---|---|---|---|
Attribute | scales |
対応するテンソルのスケールを設定します。 | |
post-op | eltwise |
結果に要素ごとの操作を適用します。 | |
post-op | binary |
結果にバイナリー操作を適用します。 | |
post-op | sum |
演算結果を上書きせずに、デスティネーション・テンソルに加算します。 |
サポートされるデータタイプ
ソースとデスティネーション・テンソルには、dnnl::memory::data_type::f32
、dnnl::memory::data_type::bf16
、dnnl::memory::data_type::s8
または dnnl::memory::data_type::u8
データタイプがあります。
データ表現
バイナリー・プリミティブは任意のデータテンソルで機能します。テンソルの次元については特別な意味はありません。
API
API については、こちら (英語) をご覧ください。
法務上の注意書き
The content of this oneAPI Specification is licensed under the Creative Commons Attribution 4.0 International License (英語). Unless stated otherwise, the sample code examples in this document are released to you under the MIT license (英語).
This specification is a continuation of Intel’s decades-long history of working with standards groups and industry/academia initiatives such as The Khronos Group*, to create and define specifications in an open and fair process to achieve interoperability and interchangeability. oneAPI is intended to be an open specification and we encourage you to help us make it better. Your feedback is optional, but to enable Intel to incorporate any feedback you may provide to this specification, and to further upstream your feedback to other standards bodies, including The Khronos Group SYCL* specification, please submit your feedback under the terms and conditions below. Any contribution of your feedback to the oneAPI Specification does not prohibit you from also contributing your feedback directly to other standard bodies, including The Khronos Group under their respective submission policies.
By opening an issue, providing feedback, or otherwise contributing to the specification, you agree that Intel will be free to use, disclose, reproduce, modify, license, or otherwise distribute your feedback at its sole discretion without any obligations or restrictions of any kind, including without limitation, intellectual property rights or licensing obligations.
This document contains information on products, services and/or processes in development. All information provided here is subject to change without notice.
© Intel Corporation. Intel、インテル、Intel ロゴ、その他のインテルの名称やロゴは、Intel Corporation またはその子会社の商標です。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。