Я думаю, что вы можете достичь того, что вы хотите с tf.nn.pool
:
import tensorflow as tf
with tf.Graph().as_default(), tf.Session() as sess:
data = tf.constant([
[
[ 1, 12, 13],
[ 2, 11, 14],
[ 3, 10, 15],
[ 4, 9, 16],
[ 5, 8, 17],
[ 6, 7, 18],
],
[
[19, 30, 31],
[20, 29, 32],
[21, 28, 33],
[22, 27, 34],
[23, 26, 35],
[24, 25, 36],
]], dtype=tf.int32)
segments = tf.constant([0, 0, 1, 1, 2, 2], dtype=tf.int32)
pool = tf.nn.pool(data, [2], 'MAX', 'VALID', strides=[2])
print(sess.run(pool))
Вывод:
[[[ 2 12 14]
[ 4 10 16]
[ 6 8 18]]
[[20 30 32]
[22 28 34]
[24 26 36]]]
Если вы действительно хотите к нам tf.unsorted_segment_max
, вы можете сделать это, как вы предлагаете в свой ответ .Вот эквивалентная формулировка, которая избегает транспонирования и включает окончательное изменение формы:
import tensorflow as tf
with tf.Graph().as_default(), tf.Session() as sess:
data = ...
segments = ...
shape = tf.shape(data)
n, k = shape[0], shape[2]
m = tf.reduce_max(segments) + 1
grid = tf.meshgrid(tf.range(n) * m * k,
segments * k,
tf.range(k), indexing='ij')
segment_nd = tf.add_n(grid)
segmented = tf.unsorted_segment_max(data, segment_nd, n * m * k)
result = tf.reshape(segmented, [n, m, k])
print(sess.run(result))
# Same output
Оба метода должны нормально работать в нейронной сети с точки зрения обратного распространения.
РЕДАКТИРОВАТЬ: С точки зренияпроизводительность, пул кажется более масштабируемой, чем сегментированная сумма (как и следовало ожидать):
import tensorflow as tf
import numpy as np
def method_pool(data, window):
return tf.nn.pool(data, [window], 'MAX', 'VALID', strides=[window])
def method_segment(data, window):
shape = tf.shape(data)
n, s, k = shape[0], shape[1], shape[2]
segments = tf.range(s) // window
m = tf.reduce_max(segments) + 1
grid = tf.meshgrid(tf.range(n) * m * k,
segments * k,
tf.range(k), indexing='ij')
segment_nd = tf.add_n(grid)
segmented = tf.unsorted_segment_max(data, segment_nd, n * m * k)
return tf.reshape(segmented, [n, m, k])
np.random.seed(100)
rand_data = np.random.rand(300, 500, 100)
window = 10
with tf.Graph().as_default(), tf.Session() as sess:
data = tf.constant(rand_data, dtype=tf.float32)
res_pool = method_pool(data, n)
res_segment = method_segment(data, n)
print(np.allclose(*sess.run([res_pool, res_segment])))
# True
%timeit sess.run(res_pool)
# 2.56 ms ± 80.8 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit sess.run(res_segment)
# 514 ms ± 6.29 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)