在计算每行张量值的连续熵时获取 inf

getting inf while calculating continuous entropy over each row of the tensor values

我试图在张量上计算 continuous entropy 大多数时候我收到 -inf 因为张量中我的数字太小:

tf.Tensor([-inf -inf -inf -inf -inf -inf -inf], shape=(7,), dtype=float32)

这是我拥有的张量子样本:

tf_ent = tf.constant([  [0.096,    -0.00065,  0.99,    0.01   ],
                        [0.097,      0.033,     0.025,     0.005   ],
                        [0.009,     0.0001,    0.0009,    0.0033],
                        [0.00060,   0.001,    0.03,     0.0005 ],
                        [0.0049,   -0.08,    -0.05,    -0.00036],
                        [0.09  ,   -0.45,     0.087,    0.0023 ],
                        [0.3,      -0.23,     0.82,    -0.28   ]])

这就是我在这个张量的 each 样本上计算连续熵的方法:

import  tensorflow as tf
import math
tf.enable_eager_execution()

def score(X):
    def entropy(data):
        if data is not None:
            data = tf.reshape(data, shape=[1, -1])
            num_samples = data.shape[0]
            if len(data.shape) == 1:
                num_dimensions = 1
            else:
                num_dimensions = data.shape[1]
            detCov = tf.linalg.det(tf.cast(tf.matmul(data, tf.transpose(data)),tf.int32)/tf.cast(num_samples,tf.int32))
            normalization = tf.math.pow(tf.cast((tf.math.multiply(2, tf.math.multiply(np.pi, tf.math.exp(1.0)))),tf.int32), num_dimensions)
            if detCov == 0:
                return -np.inf
            else:
                return 0.5 * tf.math.log(tf.math.multiply(tf.cast(normalization,tf.float32),tf.cast(detCov, tf.float32)))
    rev = tf.map_fn(entropy, X, dtype=tf.float32)
    return rev

ent_p = score(tf_ent)

所以我的问题是,如果我通过说 10000 将张量中的所有元素相乘是否可以,这样我的大部分行都会得到每行的分数? 或者它在概念上可能没有意义?

我相信您意识到您看到了这种行为,因为您将一个非常小的数字传递给了日志函数。如果我们试图除以一个非常小的数字,也会发生同样的事情。在考虑了 float32(或任何 dtype)的数值精度限制之后,我们最终除以零。

避免此问题的最常见方法(用于大多数甚至所有 'out of the box' 损失函数)是添加一个非常小的常量值(通常称为 epsilon)我们取一个日志或划分。原则是 epsilon 小到可以忽略不计它改变损失值的程度,但又大到永远不必实际除以零。

所以也许改成这样:

def score(X):
    def entropy(data):
        epsilon = tf.constant(0.000001)
        if data is not None:
            data = tf.reshape(data, shape=[1, -1])
            num_samples = data.shape[0]
            if len(data.shape) == 1:
                num_dimensions = 1
            else:
                num_dimensions = data.shape[1]
            detCov = tf.linalg.det(tf.cast(tf.matmul(data, tf.transpose(data)),tf.int32)/tf.cast(num_samples,tf.int32))
            normalization = tf.math.pow(tf.cast((tf.math.multiply(2, tf.math.multiply(np.pi, tf.math.exp(1.0)))),tf.int32), num_dimensions)
            if detCov == 0:
                return -np.inf
            else:
                return 0.5 * tf.math.log(epsilon + tf.math.multiply(tf.cast(normalization,tf.float32),tf.cast(detCov, tf.float32)))
    rev = tf.map_fn(entropy, X, dtype=tf.float32)
    return rev

ent_p = score(tf_ent)