Как получить количество элементов в Тензоре
Я хочу получить количество элемента в Тензоре, например, t=[1,2,0,0,0,0] (t-тензор), я могу получить сумму, 4, '0', вызвав t.count (0) в python, но в tensorflow я не могу найти никаких функций для этого. Как я могу получить счет "0"? Кто-нибудь может мне помочь?
4 ответов
в тензорном потоке сейчас нет встроенного метода подсчета. Но вы можете сделать это, используя существующие инструменты в таком методе:
def tf_count(t, val):
elements_equal_to_value = tf.equal(t, val)
as_ints = tf.cast(elements_equal_to_value, tf.int32)
count = tf.reduce_sum(as_ints)
return count
чтобы подсчитать только определенный элемент, вы можете создать логическую маску, преобразовать ее в int
и подводя итог:
import tensorflow as tf
X = tf.constant([6, 3, 3, 3, 0, 1, 3, 6, 7])
res = tf.reduce_sum(tf.cast(tf.equal(X, 3), tf.int32))
with tf.Session() as sess:
print sess.run(res)
также вы можете подсчитать каждый элемент в списке / Тензоре, используя tf.unique_with_counts;
import tensorflow as tf
X = tf.constant([6, 3, 3, 3, 0, 1, 3, 6, 7])
y, idx, cnts = tf.unique_with_counts(X)
with tf.Session() as sess:
a, _, b = sess.run([y, idx, cnts])
print a
print b
дополнение к ответу Слейтера выше. Если вы хотите получить счет все элементы, вы можете использовать one_hot
и reduce_sum
чтобы избежать любого цикла в python. Например, приведенный ниже фрагмент кода возвращает vocab, упорядоченный по вхождениям в word_tensor.
def build_vocab(word_tensor, vocab_size):
unique, idx = tf.unique(word_tensor)
counts_one_hot = tf.one_hot(
idx,
tf.shape(unique)[0],
dtype=tf.int32
)
counts = tf.reduce_sum(counts_one_hot, 0)
_, indices = tf.nn.top_k(counts, k=vocab_size)
return tf.gather(unique, indices)
EDIT: после небольшого эксперимента я обнаружил, что это довольно легко для one_hot
тензор для взрыва за пределами максимального размера тензора TF. Это, вероятно, более эффективно (если немного менее элегантно) чтобы заменить counts
вызов с чем-то вроде этого:
counts = tf.foldl(
lambda counts, item: counts + tf.one_hot(
item, tf.shape(unique)[0], dtype=tf.int32),
idx,
initializer=tf.zeros_like(unique, dtype=tf.int32),
back_prop=False
)
если вы хотите получить количество всех целых чисел до n
в тензор t
, вы можете использовать tf.unsorted_segment_sum такой:
count_all = tf.unsorted_segment_sum(tf.ones_like(t), t, n)
count_all
теперь будет похоже на гистограмму.
например count_all[0]
скажет вам, сколько раз число 0 появляется в Тензоре t
:
t = tf.placeholder(tf.int32)
count_all = tf.unsorted_segment_sum(tf.ones_like(t), t, 3)
sess.run(count_all[0], {t: [1,2,0,0,0,0]})
# returns 4
sess.run(count_all, {t: [1,2,0,0,0,0]})
# returns array([4, 1, 1], dtype=int32)
к сожалению, это работает только при условии, что нет измерения партии. И, как Илай Биксби указал,, более быстрый способ с назначением one_hot может занять слишком много памяти. Мое личное предпочтение обойти это, чтобы использовать tf.map_fn такой:
def count_all_fnc(e):
return tf.unsorted_segment_sum(tf.ones_like(e), e, n)
count_all = tf.map_fn(count_all_fnc, t)
например
n = 3
t = tf.placeholder(tf.int32)
def count_all_fnc(e):
return tf.unsorted_segment_sum(tf.ones_like(e), e, n)
count_all = tf.map_fn(count_all_fnc, t)
sess.run(count_all, {t:[[1, 0, 0, 2], [1, 2, 0, 0], [0, 0, 0, 0], [1, 1, 1, 2]]})
возвращает
array([[2, 1, 1],
[2, 1, 1],
[4, 0, 0],
[0, 3, 1]], dtype=int32)
если у вас есть доступная память, гораздо быстрее (около 10x) индексировать поиск векторов с одним горячим, представляющих каждый индекс, и суммировать их вместе, потому что это очень параллелизируемо. Но пространство растет как n*|t|
так что это быстро становится невозможным.
one_hot_t = tf.one_hot(t, n)
count_all = tf.reduce_sum(one_hot_t, axis=1)