给定二维张量t
,计算张量t'
的最快方法是什么
t'[i, :] = tf.histogram_fixed_width(t[i, :], vals, nbins)
即。每行调用tf.histogram_fixed_width
?
似乎tf.histogram_fixed_width
缺少axis
参数,其效果类似于tf.reduce_sum
的{{1}}参数。
答案 0 :(得分:3)
tf.histogram_fixed_width
确实适用于整个张量。您必须显式循环遍历行以计算每行直方图。以下是使用TensorFlow tf.while_loop
构造的完整工作示例:
import tensorflow as tf
t = tf.random_uniform([2, 2])
i = 0
hist = tf.constant(0, shape=[0, 5], dtype=tf.int32)
def loop_body(i, hist):
h = tf.histogram_fixed_width(t[i, :], [0.0, 1.0], nbins=5)
return i+1, tf.concat_v2([hist, tf.expand_dims(h, 0)], axis=0)
i, hist = tf.while_loop(
lambda i, _: i < 2, loop_body, [i, hist],
shape_invariants=[tf.TensorShape([]), tf.TensorShape([None, 5])])
sess = tf.InteractiveSession()
print(hist.eval())
答案 1 :(得分:1)
受到keveman的回答的启发,并且因为,
的行数固定且相当小,我选择使用t
的组合来拆分行和tf.gather
加入行。它看起来简单而有效,会看它是否有效......
tf.pack
答案 2 :(得分:0)
我想提出另一个实施方案。 此实现还可以处理多轴和未知尺寸(批处理)。
def histogram(tensor, nbins=10, axis=None):
value_range = [tf.reduce_min(tensor), tf.reduce_max(tensor)]
if axis is None:
return tf.histogram_fixed_width(tensor, value_range, nbins=nbins)
else:
if not hasattr(axis, "__len__"):
axis = [axis]
other_axis = [x for x in range(0, len(tensor.shape)) if x not in axis]
swap = tf.transpose(tensor, [*other_axis, *axis])
flat = tf.reshape(swap, [-1, *np.take(tensor.shape.as_list(), axis)])
count = tf.map_fn(lambda x: tf.histogram_fixed_width(x, value_range, nbins=nbins), flat, dtype=(tf.int32))
return tf.reshape(count, [*np.take([-1 if a is None else a for a in tensor.shape.as_list()], other_axis), nbins])
这里唯一慢的部分是tf.map_fn
,但它仍然比提到的其他解决方案快。
如果有人知道更快的实现方式,请发表评论,因为此操作仍然非常昂贵。
答案 3 :(得分:0)
答案在GPU中运行仍然很慢。在这里,我给出了另一个选择,它更快(至少在我运行的环境中),但是它限制为0〜1(您可以先将值标准化)。可以预先定义一次train_equal_mask_nbin
def histogram_v3_nomask(tensor, nbins, row_num, col_num):
#init mask
equal_mask_list = []
for i in range(nbins):
equal_mask_list.append(tf.ones([row_num, col_num], dtype=tf.int32) * i)
#[nbins, row, col]
#[0, row, col] is tensor of shape [row, col] with all value 0
#[1, row, col] is tensor of shape [row, col] with all value 1
#....
train_equal_mask_nbin = tf.stack(equal_mask_list, axis=0)
#[inst, doc_len] float to int(equaly seg float in bins)
int_input = tf.cast(tensor * (nbins), dtype=tf.int32)
#input [row,col] -> copy N times, [nbins, row_num, col_num]
int_input_nbin_copy = tf.reshape(tf.tile(int_input, [nbins, 1]), [nbins, row_num, col_num])
#calculate histogram
histogram = tf.transpose(tf.count_nonzero(tf.equal(train_equal_mask_nbin, int_input_nbin_copy), axis=2))
return histogram