RandomUniform

バージョン名: RandomUniform-8

カテゴリー: 生成

簡単な説明: RandomUniform 操作は、一様分布からランダムな値のシーケンスを生成します。

詳細な説明:

RandomUniform 操作は、範囲 [minval, maxval) の一様分布から乱数を生成します。生成アルゴリズムは、Philox アルゴリズムを使用する基礎となるランダム整数ジェネレーターに基づいています。Philox アルゴリズムは、uint32 値を生成するカウンターベースの擬似乱数ジェネレーターです。Philox アルゴリズムを 1 回呼び出すと、指定されたキーカウンターの値に応じて 4 つのランダムな結果値が返されます。キーカウンターはそれぞれ global_seed 属性と op_seed 属性で初期化されます。

両方のシード値がゼロに等しい場合、RandomUniform は非決定論的なシーケンスを生成します。

\[\begin{split}key = global_seed\\ counter = op_seed\end{split}\]

元の論文 Parallel Random Numbers: As Easy as 1, 2, 3 へのリンク。

Philox の結果は、固定数のキーカウンターの更新、いわゆる “ラウンド” を適用することによって計算されます。この実装では、Philox アルゴリズムの 4x32_10 バージョン (ラウンド数 = 10) が使用されます。

ランダムシーケンスの n 番目の 4 要素を決定する n があるとします。各ラウンドキーでは、countern が uint32 値のペアに分割されます。

\[\begin{split}R = cast\_to\_uint32(value)\\ L = cast\_to\_uint32(value >> 32),\end{split}\]

ここで、cast_to_uint32 - uint32 への静的キャスト、value - uint64 入力値、LR - uint32 結果の値 >>- ビット単位の右シフト。

次に、ncounter が次の式で更新されます。

\[\begin{split}L'= mullo(R, M)\\ R' = mulhi(R, M) {\oplus} k {\oplus} L \\ mulhi(a, b) = floor((a {\times} b) / 2^{32}) \\ mullo(a, b) = (a {\times} b) \mod 2^{32}\end{split}\]

ここで、\({\oplus}\) - ビットごとの xor、k = \(R_{key}\) - カウンター更新、k = \(L_{key}\) - n 更新、M = 0xD2511F53 - n 更新、M = 0xCD9E8D57 - カウンター更新。

各ラウンドの後、別の const 値のペアと合計することによってキーが生成されます。

\[\begin{split}L += 0x9E3779B9 \\ R += 0xBB67AE85\end{split}\]

\(L'_{n}, R'_{n}, L'_{counter}, R'_{counter}\) の結果は、4 つの乱数になります。

[0..1) 間の浮動小数点値は、次の規則に従って 32 ビット整数から取得されます。

Float16 は、符号 (1 ビット) 指数 (5 ビット) 仮数 (10 ビット) のようにフォーマットされます。値は次の式を使用して解釈されます。

\[(-1)^{sign} * 1, mantissa * 2 ^{exponent - 15}\]

したがって、float16 値を取得するには、符号指数仮数は次のように設定されます。

sign = 0
exponent = 15 - representation of a zero exponent.
mantissa = 10 right bits from generated uint32 random value.

したがって、結果の float16 値は次のようになります。

x_uint16 = x // Truncate the upper 16 bits.
val = ((exponent << 10) | x_uint16 & 0x3ffu) - 1.0,

ここで、x は uint32 で生成されたランダム値です。

Float32 は、符号 (1 ビット) 指数 (8 ビット) 仮数 (23 ビット) のようにフォーマットされます。値は次の式で解釈されます。

\[(-1)^{sign} * 1, mantissa * 2 ^{exponent - 127}\]

したがって、float 値を取得するには、符号指数仮数は次のように設定されます。

sign = 0
exponent = 127 - representation of a zero exponent.
mantissa = 23 right bits from generated uint32 random value.

したがって、結果の float 値は次のようになります。

val = ((exponent << 23) | x & 0x7fffffu) - 1.0,

ここで、x は uint32 で生成されたランダム値です。

Double は次のようにフォーマットされます: 符号 (1 ビット) 指数 (11 ビット) 仮数 (52 ビット)。値は次の式で解釈されます。

\[(-1)^{sign} * 1, mantissa * 2 ^{exponent - 1023}\]

したがって、double 値を取得するには、符号指数仮数は次のように設定されます。

sign = 0
exponent = 1023 - representation of a zero exponent.
mantissa = 52 right bits from two concatinated uint32 values from random integer generator.

したがって、結果の double は次のように取得されます。

mantissa_h = x0 & 0xfffffu;  // upper 20 bits of mantissa
mantissa_l = x1;             // lower 32 bits of mantissa
mantissa = (mantissa_h << 32) | mantissa_l;
val = ((exponent << 52) | mantissa) - 1.0,

ここで、x0、x1 は uint32 で生成されたランダム値です。

指定された範囲の値を取得するには、各値が次の式で処理されます。

float 値の場合:

\[result = x * (maxval - minval) + minval,\]

ここで、x は [0..1) 間のランダムな float または double 値です。

整数値の場合:

\[result = x \mod (maxval - minval) + minval,\]

ここで、x は uint32 のランダム値です。

例 1 - global_seed = 150、op_seed = 10、output_type = f32 の RandomUniform 出力:

 input_shape    = [ 3, 3 ]
 output  = [[0.7011236  0.30539632 0.93931055]
         [0.9456035   0.11694777 0.50770056]
         [0.5197197   0.22727466 0.991374  ]]

例 2 - global_seed = 80、op_seed = 100、output_type double の RandomUniform 出力:

input_shape    = [ 2, 2 ]

minval = 2

maxval = 10

output  = [[5.65927959 4.23122376]
      [2.67008206 2.36423758]]

例 3 - global_seed = 80、op_seed = 100、output_type = i32 の RandomUniform 出力:

input_shape    = [ 2, 3 ]

minval = 50

maxval = 100

output  = [[65 70 56]
      [59 82 92]]

属性:

  • output_type

    • 説明: 出力のタイプ生成アルゴリズムを決定し、結果の値に影響します。output_type の異なる値に対して生成される出力番号は、等しくない場合があります。

    • 値の範囲: “i32”、“i64”、“f16”、“bf16”、“f32”、“f64”。

    • タイプ: 文字列

    • 必須: はい

  • global_seed

    • 説明: グローバルシード値。

    • 値の範囲: 正の整数

    • タイプ: int

    • デフォルト値: 0

    • 必須: はい

  • op_seed

    • 説明: 運用シード値。

    • 値の範囲: 正の整数

    • タイプ: int

    • デフォルト値: 0

    • 必須: はい

入力:

  • 1: shape - 出力形状を記述する T_SHAPE タイプの 1D テンソル。必須。

  • 2: minval - 属性 output_type で指定されたタイプを持つ 1 つの要素を持つスカラーまたは 1D テンソルは、生成するランダム値の範囲の下限を定義します (両端を含む)。必須。

  • 3: maxval - 属性 output_type で指定されたタイプを持つ 1 つの要素を持つスカラーまたは 1D テンソルは、生成するランダム値の範囲の上限を定義します (排他的)。必須。

出力:

  • 1: 属性 output_type で指定されたタイプと、shape 入力テンソルで定義された形状を持つテンソル。

タイプ:

  • T_SHAPE: int32 または int64

例 1: IR の例。

 <layer ... name="RandomUniform" type="RandomUniform">
     <data output_type="f32" global_seed="234" op_seed="148"/>
     <input>
         <port id="0" precision="I32">  <!-- shape value: [2, 3, 10] -->
             <dim>3</dim>
         </port>
         <port id="1" precision="FP32"/> <!-- min value -->
         <port id="2" precision="FP32"/> <!-- max value -->
     </input>
     <output>
         <port id="3" precision="FP32" names="RandomUniform:0">
             <dim>2</dim>
             <dim>3</dim>
             <dim>10</dim>
         </port>
     </output>
 </layer>