Tensorflow?中的可微圆函数

5jvtdoz2  于 2022-11-25  发布在  其他
关注(0)|答案(8)|浏览(114)

所以我的网络的输出是一个概率列表,然后我用tf.round()把它舍入为0或1,这对这个项目来说是至关重要的。然后我发现tf.round是不可微的,所以我有点迷失在那里..:/

h9a6wy2h

h9a6wy2h1#

沿着于x-sin(2 pi x)/(2 pi)的东西?
我肯定有办法把斜坡压得更陡一点。

sqxo8psd

sqxo8psd2#

您可以利用tf.maximum()和tf.minimum()是可微的这一事实,并且输入是从0到1的概率

# round numbers less than 0.5 to zero;
# by making them negative and taking the maximum with 0
differentiable_round = tf.maximum(x-0.499,0)
# scale the remaining numbers (0 to 0.5) to greater than 1
# the other half (zeros) is not affected by multiplication
differentiable_round = differentiable_round * 10000
# take the minimum with 1
differentiable_round = tf.minimum(differentiable_round, 1)

示例:

[0.1,       0.5,     0.7]
[-0.0989, 0.001, 0.20099] # x - 0.499
[0,       0.001, 0.20099] # max(x-0.499, 0)
[0,          10,  2009.9] # max(x-0.499, 0) * 10000
[0,         1.0,     1.0] # min(max(x-0.499, 0) * 10000, 1)
a6b3iqyw

a6b3iqyw3#

这对我很有效:

x_rounded_NOT_differentiable = tf.round(x)
x_rounded_differentiable = x - tf.stop_gradient(x - x_rounded_NOT_differentiable)
mcdcgff0

mcdcgff04#

四舍五入是一个基本上不可微的函数,所以你在这方面运气不好。这种情况下的正常程序是找到一种方法来使用概率,比如用它们来计算期望值,或者取输出的最大概率,并选择它作为网络的预测值。如果你没有使用输出来计算损失函数,你可以直接把它应用到结果中,它是否可微并不重要,现在,如果你想要一个信息损失函数来训练网络,也许你应该考虑是否保持输出的概率格式可能实际上是你的优势(这可能会使您的训练过程更加顺畅)--这样,您就可以在训练后将概率转换为网络外部的实际估计值。

vptzau2j

vptzau2j5#

在前面的答案的基础上,一种获得任意好的近似的方法是使用有限傅里叶近似来近似round(),并使用你需要的任意多的项。基本上,你可以认为round(x)x加上一个反向(即下降)锯齿波。因此,使用锯齿波的傅里叶展开,我们得到

N = 5时,我们得到一个非常好的近似值:

baubqpgj

baubqpgj6#

这是一个老问题,但我刚刚为TensorFlow 2.0解决了这个问题。我在音频自动编码器项目中使用了下面的round函数。我基本上想创建声音的离散表示,并在时间上进行压缩。我使用round函数将编码器的输出钳制为整数值。到目前为止,它对我来说效果很好。

@tf.custom_gradient
def round_with_gradients(x):
    def grad(dy):
        return dy
    return tf.round(x), grad
wooyq4lh

wooyq4lh7#

在范围0 1中,平移和缩放S形可以是一种解决方案:

slope = 1000
  center = 0.5
  e = tf.exp(slope*(x-center))
  round_diff = e/(e+1)
f0ofjuux

f0ofjuux8#

在tensorflow 2.10中,有一个名为soft_round的函数可以实现这一点。
幸运的是,对于那些使用较低版本的人来说,源代码非常简单,所以我只是复制粘贴了这些行,它就像一个魅力:

def soft_round(x, alpha, eps=1e-3):
    """Differentiable approximation to `round`.

    Larger alphas correspond to closer approximations of the round function.
    If alpha is close to zero, this function reduces to the identity.

    This is described in Sec. 4.1. in the paper
    > "Universally Quantized Neural Compression"<br />
    > Eirikur Agustsson & Lucas Theis<br />
    > https://arxiv.org/abs/2006.09952

    Args:
    x: `tf.Tensor`. Inputs to the rounding function.
    alpha: Float or `tf.Tensor`. Controls smoothness of the approximation.
    eps: Float. Threshold below which `soft_round` will return identity.

    Returns:
    `tf.Tensor`
    """
    # This guards the gradient of tf.where below against NaNs, while maintaining
    # correctness, as for alpha < eps the result is ignored.
    alpha_bounded = tf.maximum(alpha, eps)

    m = tf.floor(x) + .5
    r = x - m
    z = tf.tanh(alpha_bounded / 2.) * 2.
    y = m + tf.tanh(alpha_bounded * r) / z

    # For very low alphas, soft_round behaves like identity
    return tf.where(alpha < eps, x, y, name="soft_round")

alpha设置函数的柔和程度。值越大,舍入函数的近似程度越高,但由于渐变消失,拟合变得越困难:

x = tf.convert_to_tensor(np.arange(-2,2,.1).astype(np.float32))

for alpha in [ 3., 7., 15.]:

    y = soft_round(x, alpha)
    plt.plot(x.numpy(), y.numpy(), label=f'alpha={alpha}')

plt.legend()
plt.title('Soft round function for different alphas')
plt.grid()

在我的例子中,我尝试了不同的alpha值,3.看起来是个不错的选择。

相关问题