Как рассчитать среднее значение в маске для каждой строки 2D-тензора? - PullRequest
1 голос
/ 05 июня 2019

У меня есть 2D-тензор, подобный этому:

[[1. 0. 0. 2. 1. 0. 1.]
 [0. 0. 0. 1. 0. 0. 0.]
 [2. 0. 2. 1. 1. 3. 0.]]

Я хотел бы вычислить среднее значение каждого ненулевого элемента в каждой строке, поэтому результат будет:

[1.25 1.   1.8 ]

Как я могу сделать это с TensorFlow?

Ответы [ 2 ]

2 голосов
/ 05 июня 2019

Один из способов вычисления масок для каждой строки - это использование tf.math.unsorted_segment_mean. По сути, вы можете иметь один идентификатор сегмента на строку, а затем заменить идентификатор сегмента для маскируемых элементов на дополнительный.

import tensorflow as tf

with tf.Graph().as_default(), tf.Session() as sess:
    x = tf.constant([[1., 0., 0., 2., 1., 0., 1.],
                     [0., 0., 0., 1., 0., 0., 0.],
                     [2., 0., 2., 1., 1., 3., 0.]], tf.float32)
    s = tf.shape(x)
    num_rows = s[0]
    num_cols = s[1]
    # Mask for selected elements
    mask = tf.not_equal(x, 0)
    # Make per-row ids
    row_id = tf.tile(tf.expand_dims(tf.range(num_rows), 1), [1, num_cols])
    # Id is replaced for masked elements
    seg_id = tf.where(mask, row_id, num_rows * tf.ones_like(row_id))
    # Take segmented mean discarding last value (mean of masked elements)
    out = tf.math.unsorted_segment_mean(tf.reshape(x, [-1]), tf.reshape(seg_id, [-1]),
                                        num_rows + 1)[:-1]
    print(sess.run(out))
    # [1.25 1.   1.8 ]

Однако, поскольку в этом случае маска предназначена именно для ненулевых элементов, вы также можете просто использовать tf.math.count_nonzero:

import tensorflow as tf

with tf.Graph().as_default(), tf.Session() as sess:
    x = tf.constant([[1., 0., 0., 2., 1., 0., 1.],
                     [0., 0., 0., 1., 0., 0., 0.],
                     [2., 0., 2., 1., 1., 3., 0.]], tf.float32)
    x_sum = tf.reduce_sum(x, axis=1)
    x_count = tf.cast(tf.count_nonzero(x, axis=1), x.dtype)
    # Using maximum avoids problems when all elements are zero
    out = x_sum / tf.maximum(x_count, 1)
    print(sess.run(out))
    # [1.25 1.   1.8 ]
1 голос
/ 06 июня 2019

Мы могли бы использовать tf.map_fn для достижения этого:

x = tf.constant([[1., 0., 0., 2., 1., 0., 1.],
                 [0., 0., 0., 1., 0., 0., 0.],
                 [2., 0., 2., 1., 1., 3., 0.]], tf.float32)
def mean(row):
  mask = tf.not_equal(row, 0.0)
  filtered = tf.boolean_mask(row, mask)
  return tf.reduce_mean(filtered)

out = tf.map_fn(mean, x)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...