我正在尝试在tensorflow中创建2D直方图以在tensorflow中的自定义损失函数中使用。更普遍地说,我认为人们可以从神经元的共激活中受益,这需要类似的结构。

具体来说,这就是我想要做的事情:

给定一个Nx2张量,其中N是一些样本,我想创建一个共激活的(合并的)直方图。例如,在input = [[[0,0.01],[0,0.99],[0.5,0.5]]的简单情况下,总共有10000个bin,我想生成一个100x100张量,除了3以外都为0 (0,0.01),(0,0.99)和(0.5,0.5)处的条目,其中值将为1/3(缩放很容易,所以我可以用1代替)。

我可以使用标准的numpy或数组操作轻松完成此操作

neuron1 = data[:, 1]
neuron2 = data[:, 2]

hist_2d = np.zeros((100, 100))

for neuron1_output in neuron1:
    for neuron2_output in neuron2:
        hist_2d[int(100 * neuron1_output), int(100 * neuron2_output)] += 1


但是,如果我想在tensorflow中使用hist_2d作为损失函数的一部分,则看起来我无法进行这种迭代。

有谁知道生成我正在寻找的2d直方图的好方法?我很高兴找到tf.histogram_fixed_width(),但这只会生成1d直方图。我已经开始研究tf.while_loop()和tf.map_fn()了,但是我对Tensorflow还是很陌生,所以我不确定哪种途径最有前途。

最佳答案

我发现发布了一个“答案”,更像是一种解决方法。

我想要创建2D直方图的全部原因是我想计算两个神经元激活的联合分布的熵。我已经将激活值离散化为bin,所以可以将分布改组,因为这样不会修改熵值,所以可以。

鉴于此,这就是我要做的事情:我创建了一个带有平方箱数的一维直方图,并简单地滑动值,以便数字的前半部分对应于神经元1的激活,而后半部分对应于神经元2的激活。在python中:

# Calculate the entropy of a 1D tensor, fuzzing the edges with epsilon to keep numbers
# clean.
def calculate_entropy(y, epsilon):
    clipped = tf.clip_by_value(y, epsilon, 1 - epsilon)
    return -tf.cast(tf.reduce_sum(clipped * tf.log(clipped)), dtype=tf.float32)


# Sandbox for developing calculating the entropies of y
def tf_entropies(y, epsilon, nbins):
    # Create histograms for the activations in the batch.
    value_range = [0.0, 1.0]
    # For prototype, only consider first two features.
    neuron1 = y[:, 0]
    neuron2 = y[:, 1]
    hist1 = tf.histogram_fixed_width(neuron1, value_range, nbins=nbins)
    hist2 = tf.histogram_fixed_width(neuron2, value_range, nbins=nbins)
    # Normalize
    count = tf.cast(tf.count_nonzero(hist1), tf.int32)
    dist1 = tf.divide(hist1, count)
    dist2 = tf.divide(hist2, count)
    neuron1_entropy = calculate_entropy(dist1, epsilon)
    neuron2_entropy = calculate_entropy(dist2, epsilon)

    # Calculate the joint distribution and then get the entropy
    recast_n1 = tf.cast(tf.divide(tf.cast(nbins * neuron1, tf.int32), nbins), tf.float32)
    meshed = recast_n1 + tf.divide(neuron2, nbins)  # Shift over the numbers for neuron2
    joint_hist = tf.histogram_fixed_width(meshed, value_range, nbins=nbins * nbins)
    joint_dist = tf.divide(joint_hist, count)
    joint_entropy = calculate_entropy(joint_dist, epsilon)

    return neuron1_entropy, neuron2_entropy, joint_entropy, joint_dist


一旦获得了关节直方图,就可以使用常规程序获得关节熵。我通过使用常规的numpy操作实现相同的逻辑来验证是否获得了正确的结果。熵计算匹配。

我希望这对其他遇到类似问题的人有所帮助。

关于python - Tensorflow 2d直方图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52992805/

10-16 06:46