サーチ…


前書き

Tensorflowがどのようにテンソルにインデックスを付けることができるかを示すさまざまな例は、可能であればnumpyのようなインデックス付けとの違いと類似点を強調しています。

テンソルからスライスを抽出する

詳細については、 tf.slice(input, begin, size)マニュアルを参照してください。

引数:

  • input :Tensor
  • begininput各次元の開始位置
  • sizeinput各次元の要素数。 -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.stacknp.asarrayと等価であり、この場合、最後の次元(この場合は1番目)に沿って2つのインデックスベクトルを積み重ねて次のように生成します。

[[1 2]
 [3 2]]

tf.gather_ndの使い方

tf.gather_ndはテンソルの第1次元にアクセスするだけでなく、潜在的にすべてのテンソルにアクセスできるという意味でtf.gatherの拡張です。

引数:

  • params :索引付けしたいテンソルを表すrank Pのテンソル
  • indices :アクセスしたいparamsへのインデックスを表すランクQテンソル

関数の出力は、 indicesの形状に依存しindicesindicesの最も内側の次元の長さが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]]


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow