StridedSlice#

バージョン名: StridedSlice-1

カテゴリー: データ移動

簡単な説明: StridedSlice は、テンソルのストライドスライスを抽出します。

詳細な説明: StridedSlice 操作は、入力から計算されたインデックス (各次元の begin (指定されたインデックスの要素を含む)、end (指定されたインデックスの要素を含まない)、および stride) に基づいて、指定されたテンソルからスライスを抽出します。

この操作では、次のプロパティーを持つ入力を受け取ります:

  • \(input\) スライスする N 次元のテンソル。

  • \(begin, end, stride\) - 同じ長さ M の整数の 1D リスト。ストライド入力にはゼロを含めることはできません。

  • \(begin\_mask, end\_mask, new\_axis\_mask, shrink\_axis\_mask, ellipsis\_mask\) - ビットマスク、整数 (0 または 1) の 1 次元リスト。\(ellipsis\_mask\) には、値 1 が 1 回出現することがあります。各マスクの長さはそれぞれ異なります。マスクの長さは、入力形状のランクによって異なる場合があります。

  • \(new\_axis\_mask, shrink\_axis\_mask, ellipsis\_mask\) は、データの出力次元を変更します未使用の場合は、\(N == M\) です。それ以外では、N は必ずしも M と等しくなるわけではありません。

開始と終了の負の値 (負の値の調整)

\(begin\) または \(end\) に存在する負の値は、後方から始まるインデックスを表します。つまり、値 -1 は入力次元の最後の要素を表します。実際には、負の値は次元のサイズに応じて自動的に増加します。例えば、i に対して \(data = [0, 1, 2, 3]\)\(size(data) = 4\)\(begin(i) = -1\) である場合、この値は \(begin(i) = -1 + 4 = 3\) に変更されます。I に対して \(begin(i) = -5\) の場合、この値は次のように調整されることに注意してください: \(begin(i) -5 + 4 = -1\) となり、値のクランプがトリガーされます。

基本スライス操作では、出力要素が次のように蓄積されます:

  • この操作は、begin、end、stride の値を反復処理します。各ステップで、操作は begin、end、stride の i 番目の要素を使用して、対応する次元でスライスを実行します。

  • \(slicing\_index = begin[i]\) とします。この値は、スライスを開始する最初のインデックスを決定します。スライスされた要素は出力に追加されます。

  • \(begin[i] == end[i]\) の場合、対応する次元の 1 つの要素のみが出力に追加されます。対応する出力次元は 1 になります (つまり、次元は保持されます)。

  • 各ステップで、\(slicing\_index\)\(stride[i]\) の値だけ増加します。\(slicing\_index < end[i]\) である限り、\(slicing\_index\) に対応する要素が出力に追加されます。

  • \(slicing\_index >= end[i]\) の場合は、スライスは停止し、対応する要素は出力に追加されません。

基本スライス操作では、マスクが使用されないため、\(N == M\) (つまり、i 番目のスライスステップが i 番目の次元に対応する) が想定されることに注意してください。

この仕様では、\(dim\) は i 番目のスライスステップに対応する次元であると仮定します。

逆方向のインデックス作成 (逆方向のスライス)

\(stride[i] < 0\) の場合、インデックスは逆順に付加されます。各ステップで、\(stride[i]\) の値が \(slicing\_index\) から減算されます。\(slicing\_index < end[i]\) である限り、対応する要素が出力に追加されます。\(slicing\_index <= end[i]\) の場合、スライスは停止します。

範囲外の値 (サイレントクランプ)

開始または終了の値が対応する次元の範囲外である場合、その値は暗黙的にクランプされます。次のようになります:

  • \(begin[i] >= size(dim)\) の場合、\(begin[i] = size(dim)\) となります。\(begin[i] < 0\) の場合 (負の値の調整後)、\(begin[i] = 0\) になります。

  • \(end[i] >= size(dim)\) の場合、\(end[i] = size(dim)\) となります。\(end[i] < 0\) の場合 (負の値の調整後)、\(end[i] = 0\) になります。

逆方向にスライスする場合、クランプ動作は次のようになります:

  • \(begin[i] >= size(dim)\) の場合、\(begin[i] = size(dim) - 1\) となります。\(begin[i] < 0\) の場合 (負の値の調整後)、\(begin[i] = 0\) になります。

  • \(end[i] >= size(dim)\) の場合、\(end[i] = size(dim)\) となります。\(end[i] < 0\) の場合 (負の値の調整後)、\(end[i] = -1\) になります。

この操作では、整数配列の形式で複数のビットマスクを受け入れ、上記の動作を変更します。ビットマスクの長さが対応する入力より短い場合、ビットマスクはゼロで拡張 (末尾にゼロを埋め込む) されているとみなされます。ビットマスクが必要以上に長い場合、残りの値は無視されます。

各マスクの使用例については、ドキュメントの最後に記載されている例を参照してください。

i 番目のスライスステップ中:

  • \(begin\_mask[i]\) が 1 に設定されていると、\(begin[i]\) の値は \(0`\) (逆方向にスライスする場合は \(size(dim) - 1\)) に設定されます。Python のスライス演算 \(array[0:10]\)) の左側を \(array[:10]\) と置き換えるのと同じです (先頭からスライスします)。

  • \(end\_mask[i]\) が 1 に設定されている場合、\(end[i]\) の値は \(size(dim)\) に設定されます (逆方向にスライスする場合は \(0\)) - この場合、最初の値を含むスライスは許可されないことに注意してください)。Python のスライス演算 \(array[0:10]\) の右側部分 (\(len(array) = 10\) と仮定) を \(array[0:]\) と入れ替えるのと同等です(最後までスライスします)。

  • \(new\_axis\_mask[i]\) が 1 に設定されている場合、\(begin[i]\)\(end[i]\)、および \(stride[i]\) の値は無視され、サイズ 1 の新しい次元が出力に表示されます。このステップではスライスは行われません。numpy \(array[..., np.newaxis, ...]\) を使用して行列に新しい次元を挿入するのと同じです: \(shape(array) = [..., 1, ...]\)

  • \(shrink\_axis\_mask[i]\) が 1 に設定されている場合、\(begin[i]\) の値は \(end[i]\)等しくなければなりません (通常、これはサイズ 1 の次元になることに注意してください)。また、\(stride[i]\) の値は無視されます。対応する次元が削除され、その次元の要素が 1 つだけ残ります。次元を保持せずに特定の要素のみを選択するのと同等です (NumPy では keepdims=False に相当) \(array[..., 0, ...]-> array[..., ...]\)(次元が 1 つ減ります)。

  • \(ellipsis\_mask[i]\) が 1 に設定されている場合、\(begin[i], end[i],\) および \(stride[i]\) の値は無視され、いくつかの次元がスキップされます。元の入力でスキップされる次元の正確な数は、\(rank(input) - (M - sum(new\_axis\_mask) - 1)\) です。対応する次元は省略記号 (’…’) として扱われます。言い換えると、スライス操作の残りの部分と一致する複数の連続したスライス次元として扱われ、スライス次元の影響を受けません。これにより、簡潔かつ柔軟な方法でスライス操作を実行できるようになり、省略記号でマークされた次元のスライス・パラメーターが 1 つのスライス表記に効果的に凝縮されます。例えば、10-D 入力が与えられ、1 番目と最後の次元から最初の要素を選択するタスクが与えられた場合、通常は \([0, :, :, :, :, :, :, :, :, :, 0]\) と記述する必要がありますが、省略記号を使用すると \([0, ..., 0]\) と記述するだけで済みます。numpy で ‘…’ (省略記号) 演算を使用するのと同等な \(array[0, ..., 0] (rank(array) = 10)\) は、\(array[0, :, :, :, :, :, :, :, :, 0]\) と記述することと同じです。

I 番目のスライスステップと次元の変更

i 番目のスライスステップは、必ずしも i 番目の次元の変更に対応するわけではありません。i をスライスステップのインデックスとし、j を対応する処理済み次元のインデックスとします。非自明な場合:

  • すべてのマスクが設定されていないと (0 に設定されている)、j は 1 ずつ増加します。

  • \(begin\_mask[i]\) または \(end\_mask[i]\) が 1 に設定されるたびに、j は 1 ずつ増加します。

  • \(shrink\_axis\_mask[i]\) が 1 に設定されるたびに、j は 1 ずつ増加します。

ただし:

  • \(new\_axis\_mask[i]\) が 1 に設定されるたびに、j は 1 ずつ増加します。

  • \(ellipsis\_mask[i]\) に値 1 が現れると、j は \(rank(input) - (M - sum(new\_axis\_mask) - 1)\) だけ増加します。

属性

  • begin_mask

    • 説明: begin_mask はビットマスクです。begin_mask[i]1 に等しい場合は、begin 入力の対応する次元が無視され、テンソルの ‘実際’ の始まりが対応する次元に沿って使用されることを意味します。

    • 値の範囲: 01 のリスト

    • タイプ: int[]

    • デフォルト値: なし

    • 必須: はい

  • end_mask

    • 説明: end_mask はビットマスクです。end_mask[i]1 の場合、end 入力の対応する次元は無視され、テンソルの実際の ‘終了’ が対応する次元に沿って使用されます。

    • 値の範囲: 01 のリスト

    • タイプ: int[]

    • デフォルト値: なし

    • 必須: はい

  • new_axis_mask

    • 説明: new_axis_mask はビットマスクです。If new_axis_mask[i]1 の場合、長さ 1 次元が入力テンソルの i 番目の位置に挿入されます。

    • 値の範囲: 01 のリスト

    • タイプ: int[]

    • デフォルト値: [0]

    • 必須: いいえ

  • shrink_axis_mask

    • 説明: shrink_axis_mask はビットマスクです。shrink_axis_mask[i]1 の場合、i 番目の位置の次元が削除されます。

    • 値の範囲: 01 のリスト

    • タイプ: int[]

    • デフォルト値: [0]

    • 必須: いいえ

  • ellipsis_mask

    • 説明: ellipsis_mask はビットマスクです。欠落している次元をゼロ以外のビットの位置に挿入します。

    • 値の範囲: 01 のリスト。ゼロ以外のビットは 1 つだけ許可されます。

    • タイプ: int[]

    • デフォルト値: [0]

    • 必須: いいえ

入力:

  • 1: data - スライスされるタイプ T および任意の形状の入力テンソル。必須。

  • 2: begin - 入力テンソルスライスの開始インデックスを持つ T_IND タイプの 1D テンソル。範囲外の値は黙ってクランプされます。begin_mask[i]1 の場合、begin[i] の値は無視され、適切な次元の範囲は 0 から始まります。負の値は、インデックス作成が最後から開始されることを意味します。必須。

  • 3: end - 入力テンソルスライスの終了インデックスを持つ T_IND タイプの 1D テンソル。範囲外の値は警告なしにクランプされます。end_mask[i]1 の場合、end[i] の値は無視され、代わりに適切な次元の全範囲が使用されます。負の値は、インデックス作成が最後から開始されることを意味します。必須。

  • 4: stride - ストライドを持つ T_IND タイプの 1D テンソル。入力が提供されないと、値は 1 に等しいとみなされます。オプション。

出力:

  • 1: 上記の規則に従ってスライス操作によって値が選択された T タイプのテンソル。

タイプ

  • T: サポートされるタイプ。

  • T_IND: サポートされている整数タイプ。

異なるストライド、標準スライス、逆スライスを使用した基本的な例。6-D 配列に対して \(array[0:4, 1:4, 0:4:2, 1:4:2, 3:0:-1, 3:0:-2]\) を実行するのと同じです。

 <layer ... type="StridedSlice" ...> 
    <data/> 
    <input> 
        <port id="0"> 
            <dim>4</dim> 
            <dim>4</dim> 
            <dim>4</dim> 
            <dim>4</dim> 
            <dim>4</dim> 
            <dim>4</dim> 
        </port> 
        <port id="1"> 
            <dim>6</dim> <!-- begin: [0, 1, 0, 1, 3, 3] --> 
        </port> 
        <port id="2"> 
            <dim>6</dim> <!-- end: [4, 4, 4, 4, 0, 0] --> 
        </port> 
        <port id="3"> 
            <dim>6</dim> <!-- stride: [1, 1, 2, 2, -1, -2] --> 
        </port> 
    </input> 
    <output> 
        <port id="4"> 
            <dim>4</dim> <!-- element ids: [0, 1, 2, 3] --> 
            <dim>3</dim> <!-- element ids: [1, 2, 3] --> 
            <dim>2</dim> <!-- element ids: [0, 2] --> 
            <dim>2</dim> <!-- element ids: [1, 3] --> 
            <dim>4</dim> <!-- element ids: [3, 2, 1, 0] --> 
            <dim>2</dim> <!-- element ids: [3, 1] --> 
        </port> 
    </output> 
</layer>

標準スライスと逆スライスのクランプの例。2-D 配列に対して \(array[2:3, 2:1:-1]\) を実行するのと同じです。

 <layer ... type="StridedSlice" ...> 
    <data/> 
    <input> 
        <port id="0"> 
            <dim>2</dim> 
            <dim>2</dim> 
        </port> 
        <port id="1"> 
            <dim>2</dim> <!-- begin: [1234, 2] --> 
        </port> 
        <port id="2"> 
            <dim>2</dim> <!-- end: [1234, 4321] --> 
        </port> <port id="3"> 
            <dim>2</dim> <!-- stride: [1, -1] - 2 番目のスライスは逆になります--> 
        </port> 
    </input> 
    <output> 
        <port id="4"> 
            <dim>1</dim> <!-- 開始は 2 に固定、終了は 3 に固定、要素 ID: [2] --> 
            <dim>1</dim> <!-- 開始は 2 に固定、終了は 1 に固定、要素 ID: [2] --> 
        </port> 
    </output> 
</layer>

ネガティブスライスの例。3-D 配列に対して array[0:2, 0:2, 0:-1] を実行するのと同じです。

 <layer ... type="StridedSlice" ...> 
    <data/> 
    <input> 
        <port id="0"> 
            <dim>2</dim> 
            <dim>3</dim> 
            <dim>4</dim> 
        </port> 
        <port id="1"> 
            <dim>3</dim> <!-- begin: [0, 0, 0] --> 
        </port> 
        <port id="2"> 
            <dim>3</dim> <!-- end: [2, 2, -1] - -1 は 4 - 1 = 3 に置き換えられます --> 
        </port> 
        <port id="3"> 
            <dim>3</dim> <!-- stride: [1, 1, 1] --> 
        </port> 
    </input> 
    <output> 
        <port id="4"> 
            <dim>2</dim> <!-- element ids: [0, 1] --> 
            <dim>2</dim> <!-- element ids: [0, 1] --> 
            <dim>3</dim> <!-- element ids: [0, 1, 2] --> 
        </port> 
    </output> 
</layer>

begin_mask & end_mask の使用例。3-D 配列に対して \(array[1:, :, ::-1]\) を実行するのと同じです。

 <layer ... type="StridedSlice" ...> 
    <data begin_mask="0,1,1" end_mask="1,1,1" new_axis_mask="0,0,0,0,0" shrink_axis_mask="0,0" ellipsis_mask="0" /> 
    <input> 
        <port id="0"> 
            <dim>2</dim> 
            <dim>3</dim> 
            <dim>4</dim> 
        </port> 
        <port id="1"> 
            <dim>3</dim> <!-- begin: [1, 1, 123] begin_mask は指定された値を無視します --> 
        </port> 
        <port id="2"> 
            <dim>3</dim> <!-- end: [0, 0, 2] end_mask は指定された値を無視します --> 
        </port> 
        <port id="3"> 
            <dim>3</dim> <!-- stride: [1, 1, -1] - 最後のスライスは逆で、マスクの動作が変わります --> 
        </port> 
    </input> 
    <output> 
        <port id="4"> 
            <dim>1</dim> <!-- begin = 1, end = 2 (end_mask), element ids: [1] --> 
            <dim>3</dim> <!-- begin = 0 (begin_mask), end = 3 (end_mask), element ids: [0, 1, 2] --> 
            <dim>3</dim> <!-- begin = 3 (begin_mask), end = 0 (end_mask), element ids: [3, 2, 1] --> 
        </port> 
    </output> 
</layer>

new_axis_mask の使用例。2-D 配列に対して \(array[np.newaxis, 0:2, np.newaxis, 0:4]\) を実行するのと同じです。

 <layer ... type="StridedSlice" ...> 
    <data begin_mask="0,0,0,0" end_mask="0,0,0,0" new_axis_mask="1,0,1,0" shrink_axis_mask="0,0,0,0" ellipsis_mask="0,0,0,0"/> 
    <input> 
        <port id="0"> 
            <dim>2</dim> 
            <dim>4</dim> 
        </port> 
        <port id="1"> 
            <dim>4</dim> <!-- begin: [1234, 0, -1, 0] - new_axis_mask は値をスキップします --> 
        </port> 
        <port id="2"> 
            <dim>4</dim> <!-- end: [1234, 2, 9876, 4] - new_axis_mask は値をスキップします --> 
            </port> 
            <port id="3"> 
                <dim>4</dim> <!-- stride: [132, 1, 241, 1] - new_axis_mask は値をスキップします --> 
        </port> 
    </input> 
    <output> 
        <port id="4"> 
            <dim>1</dim> <!-- 新しい次元 --> 
            <dim>2</dim> <!-- 入力の最初の次元から作成された 2 番目の次元 --> 
            <dim>1</dim> <!-- 新しい次元 --> 
            <dim>4</dim> <!-- 入力の 2 番目の次元から作成された 4 番目の次元 --> 
        </port> 
    </output> 
</layer>

shrink_axis_mask の使用例。5-D 配列に対して \(array[0:1, 0, 0:384, 0:640, 0:8]\) を実行するのと同じです。

 <layer ... type="StridedSlice" ...> 
    <data begin_mask="0,0,0,0,0" end_mask="0,0,0,0,0" new_axis_mask="0,0,0,0,0" shrink_axis_mask="0,1,0,0,0" ellipsis_mask="0,0,0,0,0"/> 
    <input> 
        <port id="0"> 
            <dim>1</dim> <!-- 最初の dim --> 
            <dim>2</dim> <!-- 2 番目の dim --> 
            <dim>384</dim> 
            <dim>640</dim> 
            <dim>8</dim> 
        </port> 
        <port id="1"> 
            <dim>5</dim> <!-- begin: [0, 0, 0, 0, 0] --> 
        </port> 
        <port id="2"> 
            <dim>5</dim> <!-- end: [1, 0, 384, 640, 8] --> 
        </port> 
        <port id="3"> 
            <dim>5</dim> <!-- stride: [1, 1, 1, 1, 1] --> 
        </port> 
    </input> 
    <output> 
        <port id="4"> 
            <dim>1</dim> <!-- shrink_axis_mask が 0 なので、最初の dim は保持されます --> 
            <dim>384</dim> <!-- shrink_axis_mask が 1 なので、2 番目の dim は欠落します --> 
            <dim>640</dim> 
            <dim>8</dim> 
        </port> 
    </output> 
</layer>

ellipsis_mask の使用例。10-D 配列に対して \(array[0:4, ..., 0:5]\) を実行するのと同じです。

 <layer ... type="StridedSlice" ...> 
    <data begin_mask="0,0,0" end_mask="0,0,0" new_axis_mask="0,0,0" shrink_axis_mask="0,0,0" ellipsis_mask="0,1,0"/> 
    <input> 
        <port id="0"> 
            <dim>10</dim> <!-- first dim --> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> <!-- last dim --> 
        </port> 
        <port id="1"> 
            <dim>3</dim> <!-- begin: [0, 0, 0] - 2 番目の次元は省略記号でマーク --> 
        </port> 
        <port id="2"> 
            <dim>3</dim> <!-- end: [4, 0, 5] --> 
        </port> 
        <port id="3"> 
            <dim>3</dim> <!-- stride: [1, -1, 1] --> 
        </port> 
    </input> 
    <output> 
        <port id="4"> 
            <dim>4</dim> <!-- 最初に変更された dim --> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> <!-- パターンに一致するように省略記号が 8 つの次元をスキップ --> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>5</dim> <!-- 最後に変更された dim --> 
        </port> 
    </output> 
</layer>

長さが異なる他のマスクを使用した ellipsis_mask の使用例。10-D 配列に対して \(array[2:, ..., np.newaxis, :10]\) を実行するのと同じです。

 <layer ... type="StridedSlice" ...> 
    <data begin_mask="0,0,1,1" end_mask="1,1,0,0" new_axis_mask="0,0,1" shrink_axis_mask="0" ellipsis_mask="0,1"/> 
    <input> 
        <port id="0"> 
            <dim>10</dim> <!-- first dim --> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> <!-- last dim --> 
        </port> 
        <port id="1"> 
            <dim>3</dim> <!-- begin: [2, 1, 10, 10] - 2 番目の次元は省略記号としてマークされています。3 番目の次元は新しい軸としてマークされています --> 
        </port> 
        <port id="2"> 
            <dim>3</dim> <!-- end: [123, 1, 10, 5] --> 
        </port> 
        <port id="3"> 
            <dim>3</dim> <!-- stride: [1, -1, 1, 1] --> 
        </port> 
    </input> 
    <output> 
        <port id="4"> 
            <dim>8</dim> <!-- 最初に変更された dim, begin = 2, end = 10 --> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>10</dim> <!-- 省略記号は 8 つの次元をスキップ --> 
            <dim>10</dim> <!-- 8 = 10 - (4 - 1 - 1) --> 
            <dim>10</dim> <!-- 10 - rank(input), 4 - rank(begin), 1 - new_axis_mask --> 
            <dim>10</dim> 
            <dim>10</dim> 
            <dim>1</dim> <!-- new_axis_mask からの新しい次元。最後から 2 番目のスライス引数を '消費’ します。 --> 
            <dim>5</dim> <!-- 最後に変更された dim, begin = 0, end = 5 --> 
        </port> 
    </output> 
</layer>