簡體   English   中英

Tensorflow 二維直方圖

[英]Tensorflow 2d Histogram

我正在嘗試在 tensorflow 中創建一個 2D 直方圖,以便在 tensorflow 中的自定義損失函數中使用。 更一般地說,我認為人們可以從使用神經元的共同激活中受益,這需要類似的結構。

這是我正在嘗試做的具體事情:

給定一個 Nx2 張量,其中 N 是一定數量的樣本,我想創建一個共激活的(分箱)直方圖。 例如,在 input=[[0, 0.01], [0, 0.99], [0.5, 0.5]] 的簡單情況下,總共有 10000 個 bin,我想生成一個 100x100 張量,除了 3 (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 作為損失函數的一部分,看起來我無法進行這種迭代。

有誰知道生成我正在尋找的二維直方圖的好方法嗎? 我很高興找到 tf.histogram_fixed_width(),但它只生成一維直方圖。 我已經開始研究 tf.while_loop() 和 tf.map_fn(),但我對 Tensorflow 還很陌生,所以我不確定什么途徑最有前途。

發布我想出的“答案”,更像是一種解決方法。

我想創建 2D 直方圖的全部原因是我想計算兩個神經元激活的聯合分布的熵。 我已經將激活值離散化到 bin 中,所以如果我對分布進行混洗也沒關系,因為這不會修改熵值。

鑒於此,這就是我所做的:我創建了一個具有平方數量的 bin 的一維直方圖,並簡單地滑動這些值,以便數字的前半部分對應於神經元 1 的激活,而后半部分對應於神經元 2 的激活。 在蟒蛇中:

# 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 操作實現相同的邏輯來驗證我得到了正確的結果。 熵計算匹配。

我希望這可以幫助其他人,如果他們遇到類似的問題。

也許這個剪輯會幫助你。

import tensorflow as tf
@tf.function
def get2dHistogram(x, y,
                   value_range,
                   nbins=100,
                   dtype=tf.dtypes.int32):
    """
    Bins x, y coordinates of points onto simple square 2d histogram
    
    Given the tensor x and y:
    x: x coordinates of points
    y: y coordinates of points
    this operation returns a rank 2 `Tensor` 
    representing the indices of a histogram into which each element
    of `values` would be binned. The bins are equal width and
    determined by the arguments `value_range` and `nbins`.
    
    
  Args:
    x:  Numeric `Tensor`.
    y: Numeric `Tensor`.
    value_range[0] lims for x
    value_range[1] lims for y
    
    nbins:  Scalar `int32 Tensor`.  Number of histogram bins.
    dtype:  dtype for returned histogram.
  
    
    
    """
    x_range = value_range[0]
    y_range = value_range[1]

    histy_bins = tf.histogram_fixed_width_bins(y, y_range, nbins=nbins, dtype=dtype)
    
    H = tf.map_fn(lambda i: tf.histogram_fixed_width(x[histy_bins == i], x_range, nbins=nbins),
              tf.range(nbins))
    return H # Matrix!

用 tensorflow 2.0 編寫,但您肯定可以管理它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM