Tensorflow에서 인덱스로 축 대치
Sep 02 2020
3D 텐서 입력 [batch, n_classes - k, 5]과 2D 텐서 인덱스가 [batch, n_classes - k]있습니다. k에있을 수 있습니다 [0, n_classes)예를 들어, 가지고 n_classes=3, k=1:
X = tf.constant([
[[0.36636186, 0.45606998, 0.785176 , 0.19967379, 0. ],
[0.2799339 , 0.9548653 , 0.7378969 , 0.5543541 , 1. ]],
[[0.07455064, 0.9868869 , 0.77224475, 0.19871569, 0. ],
[0.19579114, 0.0693613 , 0.100778 , 0.01822183, 1. ]],
[[0.684233 , 0.4401525 , 0.12203824, 0.4951769 , 0. ],
[0.47417384, 0.09783416, 0.49161586, 0.47347176, 0. ]]
])
idcs = tf.constant([
[0, 2],
[0, 1],
[1, 2]
])
의 요소 idcs는 클래스 값 (인덱스)입니다. 0의 벡터로 설정 X하여 범위에서 누락 된 인덱스에 대해 축 1을 따라 대치하려고합니다 (0, n_classes). 즉,
tf.constant([
[[0.36636186, 0.45606998, 0.785176 , 0.19967379, 0. ],
[0. , 0. , 0. , 0. , 0. ], # missing 1 in `idcs`
[0.2799339 , 0.9548653 , 0.7378969 , 0.5543541 , 1. ]],
[[0.07455064, 0.9868869 , 0.77224475, 0.19871569, 0. ],
[0.19579114, 0.0693613 , 0.100778 , 0.01822183, 1. ],
[0. , 0. , 0. , 0. , 0. ]], # missing 2 in `idcs`
[[0. , 0. , 0. , 0. , 0. ], # missing 0 in `idcs`
[0.684233 , 0.4401525 , 0.12203824, 0.4951769 , 0. ],
[0.47417384, 0.09783416, 0.49161586, 0.47347176, 0. ]]
])
나는 이것을 tensorflow로 표현하는 방법을 잘 모르겠습니다. 0의 텐서를 만들고 축 1 [batch, n_classes, 5]을 X따라 현재 인덱스를 할당 하는 것을 고려 했지만 텐서에서는 할당이 허용되지 않습니다. tensorflow에서 이것을 수행하는 쉬운 방법이 있습니까?
예를 들어, 이것을 Numpy로 표현하려면 다음과 같이 시도 할 수 있습니다.
X = np.array([
[[0.36636186, 0.45606998, 0.785176 , 0.19967379, 0. ],
[0.2799339 , 0.9548653 , 0.7378969 , 0.5543541 , 1. ]],
[[0.07455064, 0.9868869 , 0.77224475, 0.19871569, 0. ],
[0.19579114, 0.0693613 , 0.100778 , 0.01822183, 1. ]],
[[0.684233 , 0.4401525 , 0.12203824, 0.4951769 , 0. ],
[0.47417384, 0.09783416, 0.49161586, 0.47347176, 0. ]]
])
idcs = np.array([
[0, 2],
[0, 1],
[1, 2]
])
n_classes = 3
batch_size = 3
# selectors
x = np.repeat(np.arange(idcs.shape[0]), 2) # [0, 0, 1, 1, 2, 2]
y = idcs.ravel() # [0, 2, 0, 1, 1, 2]
z = np.zeros((batch_size, n_classes, 5))
z[x, y] = np.reshape(X, [x.shape[0], 5])
z
# array([[[0.36636186, 0.45606998, 0.785176 , 0.19967379, 0. ],
# [0. , 0. , 0. , 0. , 0. ],
# [0.2799339 , 0.9548653 , 0.7378969 , 0.5543541 , 1. ]],
#
# [[0.07455064, 0.9868869 , 0.77224475, 0.19871569, 0. ],
# [0.19579114, 0.0693613 , 0.100778 , 0.01822183, 1. ],
# [0. , 0. , 0. , 0. , 0. ]],
#
# [[0. , 0. , 0. , 0. , 0. ],
# [0.684233 , 0.4401525 , 0.12203824, 0.4951769 , 0. ],
# [0.47417384, 0.09783416, 0.49161586, 0.47347176, 0. ]]])
답변
2 Tgsmith61591 Sep 02 2020 at 03:45
나는 텐서를 희소로 변환하여 약간의 해킹으로 이것을 해결 한 다음 즉시 밀도로 돌아갑니다.
batch_size, n_inputs, _ = X.shape.as_list()
n_classes = 3
sparse_indices = tf.concat([
tf.reshape(tf.repeat(tf.range(batch_size, dtype=tf.int64), n_inputs * 5), [-1, 1]),
tf.reshape(tf.repeat(idcs, 5), [-1, 1]),
tf.reshape(tf.tile(tf.range(5, dtype=tf.int64), [n_inputs * batch_size]), [-1, 1]),
],
axis=1
)
# ravel X to 1d, create a sparse tensor for non-zero indices and then
# expand back to dense as a hack for filling in the zeros
X_ravel = tf.reshape(X, shape=[-1])
tf.sparse.to_dense(
tf.sparse.SparseTensor(
sparse_indices,
X_ravel,
dense_shape=[batch_size, n_classes, 5],
),
)
예상대로 결과는 다음과 같습니다.
<tf.Tensor: shape=(3, 3, 5), dtype=float32, numpy=
array([[[0.36636186, 0.45606998, 0.785176 , 0.19967379, 0. ],
[0. , 0. , 0. , 0. , 0. ],
[0.2799339 , 0.9548653 , 0.7378969 , 0.5543541 , 1. ]],
[[0.07455064, 0.9868869 , 0.77224475, 0.19871569, 0. ],
[0.19579114, 0.0693613 , 0.100778 , 0.01822183, 1. ],
[0. , 0. , 0. , 0. , 0. ]],
[[0. , 0. , 0. , 0. , 0. ],
[0.47417384, 0.09783416, 0.49161586, 0.47347176, 0. ],
[0.684233 , 0.4401525 , 0.12203824, 0.4951769 , 0. ]]],
dtype=float32)>