TensorFlow.org で表示 | Google Colab で実行 | GitHub でソースを表示 | ノートブックをダウンロード |
オブジェクト検出や NLP などの機械学習アプリケーションでは、テンソルのサブセクション(スライス)を使用する必要がある場合があります。たとえば、モデルアーキテクチャにルーティングが含まれている場合、1 つのレイヤーが次のレイヤーにルーティングされるトレーニングサンプルを制御することがあります。この場合、テンソルスライス演算を使用して、テンソルを分割し、正しい順序に戻すことができます。
NLP アプリケーションでは、トレーニング時にテンソルスライスを使用してワードマスキングを実行できます。たとえば、各文でマスクする単語インデックスを選択し、その単語をラベルとして取り出し、選択した単語をマスクトークンに置き換えることで、文のリストからトレーニングデータを生成できます。
このガイドでは、TensorFlow API を使用して次を実行する方法を学習します。
- テンソルからスライスを抽出する
- テンソルの特定のインデックスにデータを挿入する
このガイドは、テンソルのインデキシングに精通していることを前提としています。このガイドを開始する前に、テンソル、および TensorFlow NumPy ガイドのインデキシングセクションをお読みください。
セットアップ
import tensorflow as tf
import numpy as np
2022-12-14 22:54:42.642753: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory 2022-12-14 22:54:42.642872: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory 2022-12-14 22:54:42.642881: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.
テンソルスライスを抽出する
tf.slice
を使用して、NumPy のようなテンソルスライスを実行します。
t1 = tf.constant([0, 1, 2, 3, 4, 5, 6, 7])
print(tf.slice(t1,
begin=[1],
size=[3]))
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
または、Python 構文を使用することもできます。テンソルスライスは、開始から終了までの範囲で等間隔に配置されていることに注意してください。
print(t1[1:4])
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
print(t1[-3:])
tf.Tensor([5 6 7], shape=(3,), dtype=int32)
2 次元テンソルの場合、次を使用できます。
t2 = tf.constant([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
print(t2[:-1, 1:3])
tf.Tensor( [[ 1 2] [ 6 7] [11 12]], shape=(3, 2), dtype=int32)
高次元テンソルでも tf.slice
を使用できます。
t3 = tf.constant([[[1, 3, 5, 7],
[9, 11, 13, 15]],
[[17, 19, 21, 23],
[25, 27, 29, 31]]
])
print(tf.slice(t3,
begin=[1, 1, 0],
size=[1, 1, 2]))
tf.Tensor([[[25 27]]], shape=(1, 1, 2), dtype=int32)
また、tf.strided_slice
を使用して、テンソルの次元をストライドすることでテンソルのスライスを抽出することもできます。
tf.gather
を使用して、テンソルの 1 つの軸から特定のインデックスを抽出します。
print(tf.gather(t1,
indices=[0, 3, 6]))
# This is similar to doing
t1[::3]
tf.Tensor([0 3 6], shape=(3,), dtype=int32) <tf.Tensor: shape=(3,), dtype=int32, numpy=array([0, 3, 6], dtype=int32)>
tf.gather
では、インデックスが等間隔である必要はありません。
alphabet = tf.constant(list('abcdefghijklmnopqrstuvwxyz'))
print(tf.gather(alphabet,
indices=[2, 0, 19, 18]))
tf.Tensor([b'c' b'a' b't' b's'], shape=(4,), dtype=string)
テンソルの複数の軸からスライスを抽出するには、tf.gather_nd
を使用します。これは、行または列だけではなく、行列の要素を収集する場合に役立ちます。
t4 = tf.constant([[0, 5],
[1, 6],
[2, 7],
[3, 8],
[4, 9]])
print(tf.gather_nd(t4,
indices=[[2], [3], [0]]))
tf.Tensor( [[2 7] [3 8] [0 5]], shape=(3, 2), dtype=int32)
t5 = np.reshape(np.arange(18), [2, 3, 3])
print(tf.gather_nd(t5,
indices=[[0, 0, 0], [1, 2, 1]]))
tf.Tensor([ 0 16], shape=(2,), dtype=int64)
# Return a list of two matrices
print(tf.gather_nd(t5,
indices=[[[0, 0], [0, 2]], [[1, 0], [1, 2]]]))
tf.Tensor( [[[ 0 1 2] [ 6 7 8]] [[ 9 10 11] [15 16 17]]], shape=(2, 2, 3), dtype=int64)
# Return one matrix
print(tf.gather_nd(t5,
indices=[[0, 0], [0, 2], [1, 0], [1, 2]]))
tf.Tensor( [[ 0 1 2] [ 6 7 8] [ 9 10 11] [15 16 17]], shape=(4, 3), dtype=int64)
データをテンソルに挿入する
tf.scatter_nd
を使用して、テンソルの特定のスライス/インデックスにデータを挿入します。値を挿入するテンソルはゼロで初期化されることに注意してください。
t6 = tf.constant([10])
indices = tf.constant([[1], [3], [5], [7], [9]])
data = tf.constant([2, 4, 6, 8, 10])
print(tf.scatter_nd(indices=indices,
updates=data,
shape=t6))
tf.Tensor([ 0 2 0 4 0 6 0 8 0 10], shape=(10,), dtype=int32)
ゼロで初期化されたテンソルを必要とする tf.scatter_nd
のようなメソッドは、スパーステンソルのイニシャライザに似ています。tf.gather_nd
と tf.scatter_nd
を使用して、スパーステンソル演算の動作を模倣できます。
これら 2 つのメソッドを組み合わせて使用してスパーステンソルを構築する例を考えてみましょう。
# Gather values from one tensor by specifying indices
new_indices = tf.constant([[0, 2], [2, 1], [3, 3]])
t7 = tf.gather_nd(t2, indices=new_indices)
# Add these values into a new tensor
t8 = tf.scatter_nd(indices=new_indices, updates=t7, shape=tf.constant([4, 5]))
print(t8)
tf.Tensor( [[ 0 0 2 0 0] [ 0 0 0 0 0] [ 0 11 0 0 0] [ 0 0 0 18 0]], shape=(4, 5), dtype=int32)
これは次と同様です。
t9 = tf.SparseTensor(indices=[[0, 2], [2, 1], [3, 3]],
values=[2, 11, 18],
dense_shape=[4, 5])
print(t9)
SparseTensor(indices=tf.Tensor( [[0 2] [2 1] [3 3]], shape=(3, 2), dtype=int64), values=tf.Tensor([ 2 11 18], shape=(3,), dtype=int32), dense_shape=tf.Tensor([4 5], shape=(2,), dtype=int64))
# Convert the sparse tensor into a dense tensor
t10 = tf.sparse.to_dense(t9)
print(t10)
tf.Tensor( [[ 0 0 2 0 0] [ 0 0 0 0 0] [ 0 11 0 0 0] [ 0 0 0 18 0]], shape=(4, 5), dtype=int32)
既存の値を持つテンソルにデータを挿入するには、tf.tensor_scatter_nd_add
を使用します。
t11 = tf.constant([[2, 7, 0],
[9, 0, 1],
[0, 3, 8]])
# Convert the tensor into a magic square by inserting numbers at appropriate indices
t12 = tf.tensor_scatter_nd_add(t11,
indices=[[0, 2], [1, 1], [2, 0]],
updates=[6, 5, 4])
print(t12)
tf.Tensor( [[2 7 6] [9 5 1] [4 3 8]], shape=(3, 3), dtype=int32)
同様に、tf.tensor_scatter_nd_sub
を使用して、既存の値を持つテンソルから値を減算します。
# Convert the tensor into an identity matrix
t13 = tf.tensor_scatter_nd_sub(t11,
indices=[[0, 0], [0, 1], [1, 0], [1, 1], [1, 2], [2, 1], [2, 2]],
updates=[1, 7, 9, -1, 1, 3, 7])
print(t13)
tf.Tensor( [[1 0 0] [0 1 0] [0 0 1]], shape=(3, 3), dtype=int32)
tf.tensor_scatter_nd_min
を使用して、要素ごとの最小値をあるテンソルから別のテンソルにコピーします。
t14 = tf.constant([[-2, -7, 0],
[-9, 0, 1],
[0, -3, -8]])
t15 = tf.tensor_scatter_nd_min(t14,
indices=[[0, 2], [1, 1], [2, 0]],
updates=[-6, -5, -4])
print(t15)
tf.Tensor( [[-2 -7 -6] [-9 -5 1] [-4 -3 -8]], shape=(3, 3), dtype=int32)
同様に、tf.tensor_scatter_nd_max
を使用して、要素ごとの最大値をあるテンソルから別のテンソルにコピーします。
t16 = tf.tensor_scatter_nd_max(t14,
indices=[[0, 2], [1, 1], [2, 0]],
updates=[6, 5, 4])
print(t16)
tf.Tensor( [[-2 -7 6] [-9 5 1] [ 4 -3 -8]], shape=(3, 3), dtype=int32)
その他の資料とリソース
このガイドでは、TensorFlow で利用可能なテンソルスライス演算を使用して、テンソル内の要素をより詳細に制御する方法を学びました。
tf.experimental.numpy.take_along_axis
やtf.experimental.numpy.take
など、TensorFlow NumPy で利用可能なスライス演算を確認してください。