TensorIterator¶
バージョン名: TensorIterator-1
カテゴリー: インフラストラクチャー
簡単な説明: TensorIterator レイヤーは、body
で記述されているネットワークの反復実行し、データを反復処理します。
TensorIterator 属性:
-
Body:
body
は反復的に実行されるネットワークです。ネットワークは、典型的な IR ネットワークとしてレイヤーごとに記述されます。-
Body 属性:
利用可能な属性はありません。
-
-
ポートマップ:
port_map は、
TensorIterator
レイヤーの入力または出力データテンソルをbody
データテンソルにマッピングするルールのセットです。port_map
エントリーはinput
とoutput
が可能です。各エントリーは、対応するマッピングルールを説明します。-
ポートマップ属性:
-
external_port_id
説明: external_port_id は
TensorIterator
レイヤーのポート ID です。値の範囲: TensorIterator 出力のインデックス
タイプ:
int
デフォルト値: なし
必須: はい
-
internal_layer_id
説明: internal_layer_id は、マッピング先の
body
ネットワーク内のパラメーターまたは結果レイヤー ID です。値の範囲: TensorIterator レイヤー内のパラメーター・レイヤーの ID
タイプ:
int
デフォルト値: なし
必須: はい
-
axis
説明: axis は反復処理の対象となる軸です。このテンソルのスライス化をトリガーします。指定された場合にのみ、対応する
input
またはoutput
が分割され、開始、終了、およびストライド属性でスライス化の方法が定義されます。値の範囲: 整数。
タイプ:
int
デフォルト値: なし
必須: いいえ
-
start
説明: start は、反復が開始されるインデックスです。負の値はインデックスを最後からカウントすることを意味します。
axis
属性が指定されている場合にのみ適用されます。値の範囲: 整数。
タイプ:
int
デフォルト値: 0
必須: いいえ
-
end
説明: end は反復が終了するインデックスです。負の値はインデックスを最後からカウントすることを意味します。
axis
属性が指定されている場合にのみ適用されます。値の範囲: 整数。
タイプ:
int
デフォルト値: -1
必須: いいえ
-
stride
説明: stride は反復のステップです。負の値は後方からの反復を意味します。
axis
属性が指定されている場合にのみ適用されます。値の範囲: 整数。
タイプ:
int
デフォルト値: 1
必須: いいえ
-
-
-
バックエッジ:
back_edges は、ある反復での
body
出力から次の反復へのbody
パラメーターにテンソル値を転送するルールのセットです。バックエッジは、body
内の一部の結果レイヤーを同じbody
内のパラメーター・レイヤーに接続します。-
バックエッジ属性:
-
from-layer
説明: from-layer は、
body
ネットワーク内の結果レイヤー ID です。値の範囲: TensorIterator 内の結果レイヤーの ID
タイプ:
int
デフォルト値: なし
必須: はい
-
to-layer
説明: to-layer は、マッピングを終了する
body
ネットワーク内のパラメーター・レイヤー ID です。値の範囲: TensorIterator 内のパラメーター・レイヤーの ID
タイプ:
int
デフォルト値: なし
必須: はい
-
-
入力:
複数の入力: あらゆるタイプおよび形状のテンソルがサポートされるタイプ。
出力:
複数の出力:
body
の実行結果。あらゆるタイプと形状のテンソル。
詳細な説明:
他のレイヤーと同様に、TensorIterator には input
と output
の通常セクションがあります。これにより、TensorIterator を残りの IR に接続できるようになります。TensorIterator にもいくつかの特別なセクションがあります: body
、port_map
、back_edges
。これら動作原理を以下に説明します。
body
がどのように反復されるか:
最初の反復時: TensorIterator は、指定された軸で入力テンソルをスライスし、指定された順序ですべてを反復処理します。body
セクションで IR ネットワークで指定された任意のネットワークで入力テンソルを処理します。バックエッジが存在しないため、IR が実行されます。port map
のエッジは、TensorIterator の入力ポートをボディー内の Parameters
に接続するのに使用されます。
[inputs
] - Port map
エッジ -> [Parameters:body:Results
]
Parameter
および Result
レイヤーは body
の一部です。Parameters
は、body
内の安定したエントリーポイントです。body
の実行結果は、安定した Result
レイヤーとして表示されます。安定状態はノードを融合できないことを意味します。
次の反復: バックエッジは、TensorIterator body
の IR 反復間に、どのデータが Results
レイヤーから Parameters
レイヤーにコピーされるか定義します。つまり、データをソースレイヤーからターゲットレイヤーに渡します。バックエッジのターゲットである各レイヤーには、入力として受信 port map
エッジもあります。バックエッジからの値が、port map
の対応するエッジの代わりに使用されます。ネットワークの各反復の後、すべてのバックエッジが実行されます。反復は静的にアンロールされたシーケンスと考えることができます: つまり、2 つの隣接する反復間を流れるすべてのエッジはバックエッジです。したがって、アンロールされたループでは、各バックエッジが通常のエッジに変換されます。
… -> [Parameters:body:Results
] - back-edges -> [Parameters:body:Results
] - back-edges -> [Parameters:body:Results
] - back-edges -> …
結果の計算:
Port map
の output
エントリーにパーティション化 (axis, begin, end, strides
) 属性がない場合、TensorIterator の output
の最終値は、最後の反復からの Result
ノードの値になります。それ以外の場合、TensorIterator の output
の最終値は、すべての body
反復の Result
ノード内のテンソルの連結になります。連結順序は stride
属性で指定します。
最後の反復:
[Parameters:body:Results
] - Port map
エッジ -> [outputs
] (パーティション化属性が設定されない場合)。
パーティション化属性がある場合、出力テンソルはすべてのボディー反復からのテンソルの連結になります。stride > 0
の場合:
output = Concat(S[0], S[1], ..., S[N-1])
ここで、Si
は、この出力ポートに対応するテンソル反復子ボディーの i 回目の反復における Result
操作の値です。stride < 0
の場合、出力は逆の順序で連結されます。
output = Concat(S[N-1], S[N-2], ..., S[0])
例:
例 1: 典型的な TensorIterator 構造
<layer type="TensorIterator" ... >
<input> ... </input>
<output> ... </output>
<port_map>
<input external_port_id="0" internal_layer_id="0" axis="1" start="-1" end="0" stride="-1"/>
<input external_port_id="1" internal_layer_id="1"/>
...
<output external_port_id="3" internal_layer_id="2" axis="1" start="-1" end="0" stride="-1"/>
...
</port_map>
<back_edges>
<edge from-layer="1" to-layer="1"/>
...
</back_edges>
<body>
<layers> ... </layers>
<edges> ... </edges>
</body>
</layer>
例 2: 完全な TensorIterator レイヤー
<layer type="TensorIterator" ...>
<input>
<port id="0">
<dim>1</dim>
<dim>25</dim>
<dim>512</dim>
</port>
<port id="1">
<dim>1</dim>
<dim>256</dim>
</port>
<port id="2">
<dim>1</dim>
<dim>256</dim>
</port>
</input>
<output>
<port id="3" precision="FP32">
<dim>1</dim>
<dim>25</dim>
<dim>256</dim>
</port>
</output>
<port_map>
<input axis="1" external_port_id="0" internal_layer_id="0" start="0"/>
<input external_port_id="1" internal_layer_id="3"/>
<input external_port_id="2" internal_layer_id="4"/>
<output axis="1" external_port_id="3" internal_layer_id="12"/>
</port_map>
<back_edges>
<edge from-layer="8" to-layer="4"/>
<edge from-layer="9" to-layer="3"/>
</back_edges>
<body>
<layers>
<layer id="0" type="Parameter" ...>
<output>
<port id="0" precision="FP32">
<dim>1</dim>
<dim>1</dim>
<dim>512</dim>
</port>
</output>
</layer>
<layer id="1" type="Const" ...>
<data offset="0" size="16"/>
<output>
<port id="1" precision="I64">
<dim>2</dim>
</port>
</output>
</layer>
<layer id="2" type="Reshape" ...>
<input>
<port id="0">
<dim>1</dim>
<dim>1</dim>
<dim>512</dim>
</port>
<port id="1">
<dim>2</dim>
</port>
</input>
<output>
<port id="2" precision="FP32">
<dim>1</dim>
<dim>512</dim>
</port>
</output>
</layer>
<layer id="3" type="Parameter" ...>
<output>
<port id="0" precision="FP32">
<dim>1</dim>
<dim>256</dim>
</port>
</output>
</layer>
<layer id="4" type="Parameter" ...>
<output>
<port id="0" precision="FP32">
<dim>1</dim>
<dim>256</dim>
</port>
</output>
</layer>
<layer id="5" type="Const" ...>
<data offset="16" size="3145728"/>
<output>
<port id="1" precision="FP32">
<dim>1024</dim>
<dim>768</dim>
</port>
</output>
</layer>
<layer id="6" type="Const" ...>
<data offset="3145744" size="4096"/>
<output>
<port id="1" precision="FP32">
<dim>1024</dim>
</port>
</output>
</layer>
<layer id="7" type="LSTMCell" ...>
<data hidden_size="256"/>
<input>
<port id="0">
<dim>1</dim>
<dim>512</dim>
</port>
<port id="1">
<dim>1</dim>
<dim>256</dim>
</port>
<port id="2">
<dim>1</dim>
<dim>256</dim>
</port>
<port id="3">
<dim>1024</dim>
<dim>768</dim>
</port>
<port id="4">
<dim>1024</dim>
</port>
</input>
<output>
<port id="5" precision="FP32">
<dim>1</dim>
<dim>256</dim>
</port>
<port id="6" precision="FP32">
<dim>1</dim>
<dim>256</dim>
</port>
</output>
</layer>
<layer id="8" type="Result" ...>
<input>
<port id="0">
<dim>1</dim>
<dim>256</dim>
</port>
</input>
</layer>
<layer id="9" type="Result" ...>
<input>
<port id="0">
<dim>1</dim>
<dim>256</dim>
</port>
</input>
</layer>
<layer id="10" type="Const" ...>
<data offset="3149840" size="24"/>
<output>
<port id="1" precision="I64">
<dim>3</dim>
</port>
</output>
</layer>
<layer id="11" type="Reshape" ...>
<input>
<port id="0">
<dim>1</dim>
<dim>256</dim>
</port>
<port id="1">
<dim>3</dim>
</port>
</input>
<output>
<port id="2" precision="FP32">
<dim>1</dim>
<dim>1</dim>
<dim>256</dim>
</port>
</output>
</layer>
<layer id="12" type="Result" ...>
<input>
<port id="0">
<dim>1</dim>
<dim>1</dim>
<dim>256</dim>
</port>
</input>
</layer>
</layers>
<edges>
<edge from-layer="0" from-port="0" to-layer="2" to-port="0"/>
<edge from-layer="1" from-port="1" to-layer="2" to-port="1"/>
<edge from-layer="2" from-port="2" to-layer="7" to-port="0"/>
<edge from-layer="3" from-port="0" to-layer="7" to-port="1"/>
<edge from-layer="4" from-port="0" to-layer="7" to-port="2"/>
<edge from-layer="5" from-port="1" to-layer="7" to-port="3"/>
<edge from-layer="6" from-port="1" to-layer="7" to-port="4"/>
<edge from-layer="7" from-port="6" to-layer="8" to-port="0"/>
<edge from-layer="7" from-port="5" to-layer="9" to-port="0"/>
<edge from-layer="7" from-port="5" to-layer="11" to-port="0"/>
<edge from-layer="10" from-port="1" to-layer="11" to-port="1"/>
<edge from-layer="11" from-port="2" to-layer="12" to-port="0"/>
</edges>
</body>
</layer>