tensorflow
テンソルインデックス作成
サーチ…
前書き
Tensorflowがどのようにテンソルにインデックスを付けることができるかを示すさまざまな例は、可能であればnumpyのようなインデックス付けとの違いと類似点を強調しています。
テンソルからスライスを抽出する
詳細については、 tf.slice(input, begin, size)
マニュアルを参照してください。
引数:
-
input
:Tensor -
begin
:input
各次元の開始位置 -
size
:input
各次元の要素数。-1
を使用すると残りの要素がすべて含まれます。
ナンパのようなスライス:
# x has shape [2, 3, 2]
x = tf.constant([[[1., 2.], [3., 4. ], [5. , 6. ]],
[[7., 8.], [9., 10.], [11., 12.]]])
# Extracts x[0, 1:2, :] == [[[ 3., 4.]]]
res = tf.slice(x, [0, 1, 0], [1, 1, -1])
負のインデックス付けを使用して、3番目の次元の最後の要素を取得します。
# Extracts x[0, :, -1:] == [[[2.], [4.], [6.]]]
last_indice = x.get_shape().as_list()[2] - 1
res = tf.slice(x, [0, 1, last_indice], [1, -1, -1])
テンソルの最初の次元から非連続スライスを抽出する
一般に、 tf.gather
は、テンソルの最初の次元(例えば、2次元テンソルの行1,3、および7)の要素にアクセスします。最初のもの以外のディメンションにアクセスする必要がある場合、またはスライス全体が必要ではない場合(たとえば1行目、3行目、7行目の5番目のエントリのみ)、 tf.gather_nd
を使用する方がよいでしょうこれの例)。
tf.gather
引数:
-
params
:値を抽出するテンソルです。 -
indices
:テンソルに指すインデックスを特定params
詳細については、 tf.gather(params、indices)のドキュメントを参照してください。
私たちは、2次元のテンソルで1行目と4行目を抽出したいと考えています。
# data is [[0, 1, 2, 3, 4, 5],
# [6, 7, 8, 9, 10, 11],
# ...
# [24, 25, 26, 27, 28, 29]]
data = np.reshape(np.arange(30), [5, 6])
params = tf.constant(data)
indices = tf.constant([0, 3])
selected = tf.gather(params, indices)
selected
形状は[2, 6]
あり、その値を印刷すると
[[ 0 1 2 3 4 5]
[18 19 20 21 22 23]]
indices
はスカラーだけでもかまいません(しかし、負のインデックスを含むことはできません)。例えば上記の例では:
tf.gather(params, tf.constant(3))
印刷する
[18 19 20 21 22 23]
indices
は任意の形状を持つことができますが、 indices
格納される要素は常にparams
最初の次元のみを参照します。たとえば、1行目と 3行目と 2行目と4行目を同時に取得する場合は、次のようにします。
indices = tf.constant([[0, 2], [1, 3]])
selected = tf.gather(params, indices)
今selected
された形状は[2, 2, 6]
2、2、6 [2, 2, 6]
あり、その内容は次のようになります。
[[[ 0 1 2 3 4 5]
[12 13 14 15 16 17]]
[[ 6 7 8 9 10 11]
[18 19 20 21 22 23]]]
tf.gather
を使って順列を計算することができます。たとえば、次のようにparams
すべての行を反転させます。
indices = tf.constant(list(range(4, -1, -1)))
selected = tf.gather(params, indices)
selected
[[24 25 26 27 28 29]
[18 19 20 21 22 23]
[12 13 14 15 16 17]
[ 6 7 8 9 10 11]
[ 0 1 2 3 4 5]]
最初のディメンション以外にアクセスする必要がある場合は、 tf.transpose
を使用してtf.transpose
することができます。たとえば、この例では行の代わりに列を集めるために、これを行うことができます。
indices = tf.constant([0, 2])
selected = tf.gather(tf.transpose(params, [1, 0]), indices)
selected_t = tf.transpose(selected, [1, 0])
selected_t
は形状[5, 2]
5、2 [5, 2]
あり、次のようになります。
[[ 0 2]
[ 6 8]
[12 14]
[18 20]
[24 26]]
しかし、 tf.transpose
はかなり高価なので、このユースケースではtf.gather_nd
を使用するほうが良いかもしれません。
テンソルを使ったナンシー様索引
この例はこの記事に基づいています: TensorFlow - テンソルインデックスのようなnumpyのようなもの 。
Numpyでは、配列を使用して配列にインデックスを付けることができます。たとえば、 (1, 2)
と(3, 2)
(1, 2)
の要素を2次元配列で選択するには、次のようにします。
# data is [[0, 1, 2, 3, 4, 5],
# [6, 7, 8, 9, 10, 11],
# [12 13 14 15 16 17],
# [18 19 20 21 22 23],
# [24, 25, 26, 27, 28, 29]]
data = np.reshape(np.arange(30), [5, 6])
a = [1, 3]
b = [2, 2]
selected = data[a, b]
print(selected)
これは印刷されます:
[ 8 20]
tf.gather_nd
で同じ動作をするには、 tf.gather_nd
を使用しtf.gather_nd
。これはtf.gather
拡張です。上記の例は次のように書くことができます:
x = tf.constant(data)
idx1 = tf.constant(a)
idx2 = tf.constant(b)
result = tf.gather_nd(x, tf.stack((idx1, idx2), -1))
with tf.Session() as sess:
print(sess.run(result))
これは印刷されます:
[ 8 20]
tf.stack
はnp.asarray
と等価であり、この場合、最後の次元(この場合は1番目)に沿って2つのインデックスベクトルを積み重ねて次のように生成します。
[[1 2]
[3 2]]
tf.gather_ndの使い方
tf.gather_nd
はテンソルの第1次元にアクセスするだけでなく、潜在的にすべてのテンソルにアクセスできるという意味でtf.gather
の拡張です。
引数:
-
params
:索引付けしたいテンソルを表すrankP
のテンソル -
indices
:アクセスしたいparams
へのインデックスを表すランクQ
テンソル
関数の出力は、 indices
の形状に依存しindices
。 indices
の最も内側の次元の長さがP
なら、 params
から単一の要素を集めています。 P
より小さい場合は、 tf.gather
と同様にスライスを収集しますが、1次元にしかアクセスできないという制限はありません。
ランク2のテンソルから要素を集める
行列の中の(1, 2)
の要素にアクセスするには、次のものを使用できます。
# data is [[0, 1, 2, 3, 4, 5],
# [6, 7, 8, 9, 10, 11],
# [12 13 14 15 16 17],
# [18 19 20 21 22 23],
# [24, 25, 26, 27, 28, 29]]
data = np.reshape(np.arange(30), [5, 6])
x = tf.constant(data)
result = tf.gather_nd(x, [1, 2])
result
は期待どおり8
なります。これは異なる方法注tf.gather
:渡された同じインデックスがするtf.gather(x, [1, 2])
から2番目と3番目の列として与えられたであろうdata
。
同時に複数の要素を取得する場合は、インデックスペアのリストを渡すだけです。
result = tf.gather_nd(x, [[1, 2], [4, 3], [2, 5]])
それは[ 8 27 17]
ランク2のテンソルから行を収集する
上記の例で要素の代わりに行(つまりスライス)を収集する場合は、次のようにindices
パラメータを調整します。
data = np.reshape(np.arange(30), [5, 6])
x = tf.constant(data)
result = tf.gather_nd(x, [[1], [3]])
これにより、2行目と4行目のdata
が得られます。
[[ 6 7 8 9 10 11]
[18 19 20 21 22 23]]
ランク3のテンソルから要素を集める
階数2のテンソルにアクセスする方法の概念は、より高い次元のテンソルに直接変換されます。したがって、ランク3のテンソルの要素にアクセスするには、 indices
の最内の次元は長さ3でなければなりません。
# data is [[[ 0 1]
# [ 2 3]
# [ 4 5]]
#
# [[ 6 7]
# [ 8 9]
# [10 11]]]
data = np.reshape(np.arange(12), [2, 3, 2])
x = tf.constant(data)
result = tf.gather_nd(x, [[0, 0, 0], [1, 2, 1]])
result
は次のようになります: [ 0 11]
ランク3のテンソルからバッチ処理された行を収集する
rank-3テンソルを行列のバッチ(batch_size, m, n)
として考えてみましょう。バッチ内のすべての要素の1行目と2行目を収集する場合は、次のようにします。
# data is [[[ 0 1]
# [ 2 3]
# [ 4 5]]
#
# [[ 6 7]
# [ 8 9]
# [10 11]]]
data = np.reshape(np.arange(12), [2, 3, 2])
x = tf.constant(data)
result = tf.gather_nd(x, [[[0, 0], [0, 1]], [[1, 0], [1, 1]]])
これは次のようになります:
[[[0 1]
[2 3]]
[[6 7]
[8 9]]]
indices
の形状が出力テンソルの形状にどのように影響するかに注意してください。 indices
引数にrank-2テンソルを使用したとすると、次のようになります。
result = tf.gather_nd(x, [[0, 0], [0, 1], [1, 0], [1, 1]])
出力は
[[0 1]
[2 3]
[6 7]
[8 9]]