簡體   English   中英

Tensorflow 中的微分輪 function?

[英]Differentiable round function in Tensorflow?

所以 my.network 的 output 是一個概率列表,然后我使用 tf.round() 將其舍入為 0 或 1,這對這個項目至關重要。 然后我發現 tf.round 是不可微分的,所以我有點迷路了……:/

類似於 x - sin(2pi x)/(2pi) 的東西?

我確信有一種方法可以將斜坡壓得更陡一些。

在此處輸入圖片說明

您可以使用 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)

四舍五入是一個基本上不可微的函數,所以你在那里不走運。 這種情況的正常程序是找到一種方法來使用概率,例如通過使用它們來計算期望值,或者通過獲取輸出的最大概率並選擇該概率作為網絡的預測。 但是,如果您不使用輸出來計算損失函數,則可以繼續將其應用於結果,並且它是否可微無關緊要。 現在,如果您想要一個用於訓練網絡的信息損失函數,也許您應該考慮將輸出保持為概率格式是否實際上對您有利(這可能會使您的訓練過程更順暢)-那樣您可以在訓練后將概率轉換為網絡外部的實際估計值。

這對我有用:

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

基於先前的答案,獲得任意好的近似值的一種方法是使用有限傅立葉近似值來近似round()並根據需要使用盡可能多的項。 從根本上說,你能想到的round(x)添加一個反向(即降序)鋸齒波x 所以,使用鋸齒波的傅立葉展開我們得到

round(x) ≈ x + 1/π ∑_n^N (-1)^n sin(2π n x)/n

N = 5 時,我們得到了一個非常好的近似值: 近似圓形圖()

在 0 1 范圍內,平移和縮放 sigmoid 可以是一個解決方案:

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

一個老問題,但我剛剛為 TensorFlow 2.0 解決了這個問題。 我在我的音頻自動編碼器項目中使用以下輪函數。 我基本上想創建一個在時間上被壓縮的聲音的離散表示。 我使用 round 函數將編碼器的輸出限制為整數值。 到目前為止,它對我來說效果很好。

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

在 tensorflow 2.10 中,有一個名為soft_round的 function 正是實現了這一點。

幸運的是,對於那些使用較低版本的人來說,源代碼非常簡單,所以我只是復制粘貼了這些行,它就像一個魅力:

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設置 function 的軟度。 更大的值導致 function 輪的更好近似,但隨后變得更難擬合,因為梯度消失:

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. 看起來是個不錯的選擇。

不同 alpha 值的軟輪函數

暫無
暫無

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

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