Tensorflow 中的高效池化操作:自定义池化层
Efficient pooling operation in Tensorflow : Custom pooling layer
我希望创建一个可以在 GPU 上高效工作的自定义池化层。
例如,我有以下输入张量
in = <tf.Tensor: shape=(4, 5), dtype=float32, numpy=
array([[0., 1., 2., 3., 4.],
[5., 1., 7., 3., 2.],
[9., 9., 2., 3., 5.],
[2., 6., 2., 8., 4.]], dtype=float32)>
我希望提供我希望对其执行池化的列号列表,例如,我希望对以下列索引执行最大池化
pool_cols =
[<tf.Tensor: shape=(2,), dtype=int32, numpy=array([0, 1], dtype=int32)>,
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([2, 3, 4], dtype=int32)>]
最终的合并输出看起来像
pooled_out = <tf.Tensor: shape=(4, 2), dtype=float32, numpy=
array([[1., 4.],
[5., 7.],
[9., 5.],
[6., 8.]], dtype=float32)>
最有效的方法是什么?
IIUC,您可以仅使用 tf
操作来尝试类似的操作,但我不确定它在 GPU 上的效率如何:
import tensorflow as tf
tensor = tf.constant([[0., 1., 2., 3., 4.],
[5., 1., 7., 3., 2.],
[9., 9., 2., 3., 5.],
[2., 6., 2., 8., 4.]])
pool_cols = [tf.constant([0, 1]), tf.constant([2, 3, 4])]
def column_max_pooling(tensor, pool_cols):
results = []
tensor_shape = tf.shape(tensor)
for col in pool_cols:
col_shape = tf.shape(col)
t = tf.gather_nd(tensor, tf.transpose(tf.stack([tf.tile(tf.range(tensor_shape[0]), [col_shape[0]]), tf.repeat(col, [tensor_shape[0]])])))
t = tf.reduce_max(tf.transpose(tf.reshape(t, (col_shape[0], tensor_shape[0]))), axis=-1, keepdims=True)
results.append(t)
return tf.concat(results, axis=-1)
print(column_max_pooling(tensor, pool_cols))
tf.Tensor(
[[1. 4.]
[5. 7.]
[9. 5.]
[6. 8.]], shape=(4, 2), dtype=float32)
如果你能保证pool_cols
的顺序,你也可以尝试使用tf.math.unsorted_segment_max
:
import tensorflow as tf
tensor = tf.constant([[0., 1., 2., 3., 4.],
[5., 1., 7., 3., 2.],
[9., 9., 2., 3., 5.],
[2., 6., 2., 8., 4.]])
pool_cols = [tf.constant([0, 1]), tf.constant([2, 3, 4])]
result = tf.transpose(tf.math.unsorted_segment_max(tf.transpose(tensor), tf.concat([tf.repeat(idx, tf.shape(col)[0])for idx, col in enumerate(pool_cols)], axis=0), num_segments=len(pool_cols)))
print(result)
tf.Tensor(
[[1. 4.]
[5. 7.]
[9. 5.]
[6. 8.]], shape=(4, 2), dtype=float32)
我希望创建一个可以在 GPU 上高效工作的自定义池化层。
例如,我有以下输入张量
in = <tf.Tensor: shape=(4, 5), dtype=float32, numpy=
array([[0., 1., 2., 3., 4.],
[5., 1., 7., 3., 2.],
[9., 9., 2., 3., 5.],
[2., 6., 2., 8., 4.]], dtype=float32)>
我希望提供我希望对其执行池化的列号列表,例如,我希望对以下列索引执行最大池化
pool_cols =
[<tf.Tensor: shape=(2,), dtype=int32, numpy=array([0, 1], dtype=int32)>,
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([2, 3, 4], dtype=int32)>]
最终的合并输出看起来像
pooled_out = <tf.Tensor: shape=(4, 2), dtype=float32, numpy=
array([[1., 4.],
[5., 7.],
[9., 5.],
[6., 8.]], dtype=float32)>
最有效的方法是什么?
IIUC,您可以仅使用 tf
操作来尝试类似的操作,但我不确定它在 GPU 上的效率如何:
import tensorflow as tf
tensor = tf.constant([[0., 1., 2., 3., 4.],
[5., 1., 7., 3., 2.],
[9., 9., 2., 3., 5.],
[2., 6., 2., 8., 4.]])
pool_cols = [tf.constant([0, 1]), tf.constant([2, 3, 4])]
def column_max_pooling(tensor, pool_cols):
results = []
tensor_shape = tf.shape(tensor)
for col in pool_cols:
col_shape = tf.shape(col)
t = tf.gather_nd(tensor, tf.transpose(tf.stack([tf.tile(tf.range(tensor_shape[0]), [col_shape[0]]), tf.repeat(col, [tensor_shape[0]])])))
t = tf.reduce_max(tf.transpose(tf.reshape(t, (col_shape[0], tensor_shape[0]))), axis=-1, keepdims=True)
results.append(t)
return tf.concat(results, axis=-1)
print(column_max_pooling(tensor, pool_cols))
tf.Tensor(
[[1. 4.]
[5. 7.]
[9. 5.]
[6. 8.]], shape=(4, 2), dtype=float32)
如果你能保证pool_cols
的顺序,你也可以尝试使用tf.math.unsorted_segment_max
:
import tensorflow as tf
tensor = tf.constant([[0., 1., 2., 3., 4.],
[5., 1., 7., 3., 2.],
[9., 9., 2., 3., 5.],
[2., 6., 2., 8., 4.]])
pool_cols = [tf.constant([0, 1]), tf.constant([2, 3, 4])]
result = tf.transpose(tf.math.unsorted_segment_max(tf.transpose(tensor), tf.concat([tf.repeat(idx, tf.shape(col)[0])for idx, col in enumerate(pool_cols)], axis=0), num_segments=len(pool_cols)))
print(result)
tf.Tensor(
[[1. 4.]
[5. 7.]
[9. 5.]
[6. 8.]], shape=(4, 2), dtype=float32)