Это один из возможных подходов:
import tensorflow as tf
x = tf.placeholder(tf.float32, [20, 50])
# Break X into its parts
x_parts = tf.unstack(x)
# Recompose
x = tf.stack(x_parts)
# Compute Y however
y = tf.reduce_sum(x, axis=1)
# Break Y into parts
y_parts = tf.unstack(y)
# Compute gradient part-wise
g_parts = [tf.gradients(y_part, x_part)[0] for x_part, y_part in zip(x_parts, y_parts)]
# Recompose gradient
g = tf.stack(g_parts)
print(g)
# Tensor("stack_1:0", shape=(20, 50), dtype=float32)
Однако здесь есть как минимум две проблемы:
- Требуется использовать фиксированный размер для
n
(но не для m
).
- Это создаст
O(n)
узлов на графике, что может быть проблемой, если вы намеревались использовать очень большой n
.
Теоретически можно использовать цикл TensorFlow while, но что-то в тензорных массивах или циклах не распространяет градиенты по мере необходимости.
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, None])
n = tf.shape(x)[0]
element_shape = x.shape[1:]
x_parts = tf.TensorArray(x.dtype, size=n, dynamic_size=False,
element_shape=element_shape, clear_after_read=False)
_, x_parts, _ = tf.while_loop(lambda i, x_parts, x: i < n,
lambda i, x_parts, x: (i + 1, x_parts.write(i, x[i]), x),
[tf.constant(0, n.dtype), x_parts, x])
x = x_parts.stack()
y = tf.reduce_sum(x, axis=1)
g_parts = tf.TensorArray(y.dtype, size=n, dynamic_size=False,
element_shape=element_shape, clear_after_read=True)
_, g_parts, _ = tf.while_loop(lambda i, g_parts, x_parts, y: i < n,
lambda i, g_parts, x_parts, y:
(i + 1, g_parts.write(i, tf.gradients(y[i], x_parts.read(i))[0]), x_parts, y),
[tf.constant(0, n.dtype), g_parts, x_parts, y])
# Fails due to None gradients
g = g_parts.stack()
print(g)