【问题标题】:Find the maximum number of consecutive ones in Tensorflow找到Tensorflow中连续的最大数量
【发布时间】:2019-11-27 01:10:34
【问题描述】:

我在

中找到了解决方案

Matlab:https://uk.mathworks.com/matlabcentral/answers/85143-find-maximum-number-of-consecutive-negative-values

Numpy:Find consecutive ones in numpy array

但不是在 TensorFlow 中。我发现的最接近的问题是: Reduce sum with condition in tensorflow

但是,这仅计算第一组,而不是找到最大的组。基本上,如果有一个相当于 Matlab 的 RCUMSUMC 的 Tensorflow,这个问题就很容易解决了

https://uk.mathworks.com/matlabcentral/fileexchange/28685-rcumsumc

我的输入是一个形状为 NxHxW 的二进制张量,输出预计是 NxW,其中每一列代表连续的最大数量:

Input = [[1,1,0,0,1,0,1,1,1,1,0,0,1],
         [1,0,0,1,1,1,1,1,1,0,0,1,0],
         [0,0,0,1,1,1,0,0,1,0,1,1,0]]

Output = [4,6,3]

【问题讨论】:

  • 你能提供一个简单的例子来说明你的输入和预期的输出吗?
  • 用示例输入和输出编辑

标签: python tensorflow


【解决方案1】:

编辑:以下是对 3 维张量执行相同操作的方法,在第二维中搜索一组张量:

import tensorflow as tf

inp = tf.random.stateless_uniform((3, 4, 5), [0, 0], 0, 2, tf.int32)
tf.print(inp)
# [[[0 1 0 0 0]
#   [0 0 0 1 1]
#   [0 1 1 0 0]
#   [0 0 0 0 0]]
# 
#  [[1 1 0 0 0]
#   [0 1 1 0 0]
#   [0 1 0 1 0]
#   [0 0 0 0 0]]
# 
#  [[1 1 1 0 0]
#   [0 0 1 1 1]
#   [0 1 1 0 1]
#   [0 1 0 0 0]]]
# Pad with ones to avoid all-zeros
inp = tf.pad(inp, [(0, 1), (0, 0), (0, 0)], constant_values=1)
s = tf.shape(inp)
# Transpose and reshape
inp_t = tf.reshape(tf.transpose(inp, [0, 2, 1]), [-1, s[1]])
# Surround with zeros
inp_t = tf.pad(inp_t, [(0, 0), (1, 1)])
# Find bounds of groups of ones
groups = tf.reshape(tf.where(tf.not_equal(inp_t[:, 1:], inp_t[:, :-1])), [-1, 2, 2])
# Compute group sizes
group_sizes = groups[:, 1, 1] - groups[:, 0, 1]
# Find maximum group sizes
max_ones_group = tf.math.segment_max(group_sizes, groups[:, 0, 0], name=None)
# Reshape back
out = tf.reshape(max_ones_group, [s[0], s[2]])[:-1]
tf.print(out)
# [[0 1 1 1 1]
#  [1 3 1 1 0]
#  [1 2 3 1 2]]

假设输入是二进制张量(只有零和一),这是一种方法:

import tensorflow as tf

inp = tf.constant([[1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1],
                   [1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0],
                   [0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0]])
# Surround with zeros
inp = tf.pad(inp, [(0, 0), (1, 1)])
# Find bounds of groups of ones
groups = tf.reshape(tf.where(tf.not_equal(inp[:, 1:], inp[:, :-1])), [-1, 2, 2])
# Compute group sizes
group_sizes = groups[:, 1, 1] - groups[:, 0, 1]
# Find maximum group sizes
max_ones_group = tf.math.segment_max(group_sizes, groups[:, 0, 0], name=None)
tf.print(max_ones_group)
# [4 6 3]

【讨论】:

  • 它适用于 N=1,但如果我们有很多样本怎么办?对于形状为 NxHxW 的输入,输出需要为 NxW。
  • @metalruka 我添加了另一个带有 3D 张量的示例。
  • 只是一个旁注,如果输入数组中没有,则此操作失败。用单行填充输入是一种简单的解决方法。
  • @metalruka 你是对的,感谢您的反馈。是的,我认为填充是最简单的解决方案,我更新了答案。
【解决方案2】:

好吧,这有点令人费解。但是想出这个很有趣。 (在 TF 2.0 和 TF 1.15 上测试过)

# Let's assume a simpler example for demonstration [0, 1, 1, 1, 0, 1]
tf_a = tf.constant([[1,1,0,0,1,0,1,1,1,1,0,0,1],
         [1,0,0,1,1,1,1,1,1,0,0,1,0],
         [0,0,0,1,1,1,0,0,1,0,1,1,0]])

# You get the cumsum [0, 1, 2, 3, 3, 4]
tf_a_sum = tf.cumsum(tf_a, axis=1)
# You get the range  [0, 1, 2, 3, 4, 5]
tf_range = tf.range(tf_a.shape[1])

# You get the difference [0, 0, 0, 0, 1, 1]
tf_diff = tf_range - tf_a_sum
# To make sure it's starting with 0
tf_diff = tf_diff - tf.reduce_min(tf_diff, axis=1, keepdims=True)

# Now comes the tricky bit. We are using segment_sum
# I would have liked to achieve this with tf.map_fn but segment_sum didn't play nicely with map_fn
# So we are first unstacking the arrays on rows
# Applying segment_sum to individual rows
# And restacking them

tf_list_diff = tf.unstack(tf_diff)
tf_list_a = tf.unstack(tf_a)

# [0, 1, 1, 1, 0, 1] => summing segment-wise with [0, 0, 0, 0, 1, 1]
# Gives [3,1]
# And you get max of that which is 3
tf_res = tf.stack([tf.reduce_max(tf.math.segment_sum(a, diff)) for a, diff in zip(tf_list_a, tf_list_diff)])

警告:只要您对包含 0 和 1 的数组中的 1 的数量感兴趣,这将起作用。如果数组中有其他数字,这将不起作用。所以这种解决方式对你要解决的问题非常具体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-31
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 2021-08-07
    相关资源
    最近更新 更多