TensorFlow 损失函数在第一个 epoch 后归零

Posted

技术标签:

【中文标题】TensorFlow 损失函数在第一个 epoch 后归零【英文标题】:TensorFlow loss function zeroes out after first epoch 【发布时间】:2018-03-03 17:00:35 【问题描述】:

我正在尝试根据这篇论文实现一个判别损失函数,用于图像的实例分割:https://arxiv.org/pdf/1708.02551.pdf(此链接仅供读者参考;我不希望任何人阅读它来提供帮助我出去!

我的问题:一旦我从一个简单的损失函数转移到一个更复杂的损失函数(就像你在附加的代码 sn-p 中看到的那样),损失函数在第一个 epoch 之后归零。我检查了重量,几乎所有重量似乎都在 -300 附近徘徊。它们并不完全相同,但彼此非常接近(仅在小数位上有所不同)。

实现判别损失函数的相关代码

def regDLF(y_true, y_pred):
    global alpha
    global beta
    global gamma
    global delta_v
    global delta_d
    global image_height
    global image_width
    global nDim

    y_true = tf.reshape(y_true, [image_height*image_width])

    X = tf.reshape(y_pred, [image_height*image_width, nDim])
    uniqueLabels, uniqueInd = tf.unique(y_true)

    numUnique = tf.size(uniqueLabels)

    Sigma = tf.unsorted_segment_sum(X, uniqueInd, numUnique)
    ones_Sigma = tf.ones((tf.shape(X)[0], 1))
    ones_Sigma = tf.unsorted_segment_sum(ones_Sigma,uniqueInd, numUnique)
    mu = tf.divide(Sigma, ones_Sigma)

    Lreg = tf.reduce_mean(tf.norm(mu, axis = 1))

    T = tf.norm(tf.subtract(tf.gather(mu, uniqueInd), X), axis = 1)
    T = tf.divide(T, Lreg)
    T = tf.subtract(T, delta_v)
    T = tf.clip_by_value(T, 0, T)
    T = tf.square(T)

    ones_Sigma = tf.ones_like(uniqueInd, dtype = tf.float32)
    ones_Sigma = tf.unsorted_segment_sum(ones_Sigma,uniqueInd, numUnique)
    clusterSigma = tf.unsorted_segment_sum(T, uniqueInd, numUnique)
    clusterSigma = tf.divide(clusterSigma, ones_Sigma)

    Lvar = tf.reduce_mean(clusterSigma, axis = 0)

    mu_interleaved_rep = tf.tile(mu, [numUnique, 1])
    mu_band_rep = tf.tile(mu, [1, numUnique])
    mu_band_rep = tf.reshape(mu_band_rep, (numUnique*numUnique, nDim))

    mu_diff = tf.subtract(mu_band_rep, mu_interleaved_rep)
    mu_diff = tf.norm(mu_diff, axis = 1)
    mu_diff = tf.divide(mu_diff, Lreg)

    mu_diff = tf.subtract(2*delta_d, mu_diff)
    mu_diff = tf.clip_by_value(mu_diff, 0, mu_diff)
    mu_diff = tf.square(mu_diff)

    numUniqueF = tf.cast(numUnique, tf.float32)
    Ldist = tf.reduce_mean(mu_diff)        

    L = alpha * Lvar + beta * Ldist + gamma * Lreg

    return L

问题:我知道不阅读论文很难理解代码的作用,但我有几个问题:

    定义的损失函数是否存在明显错误 上面?

    任何人都知道为什么损失函数会在第一个 epoch 之后归零?

非常感谢您的宝贵时间和帮助!

【问题讨论】:

您的损失似乎由三个项组成。为什么不改变三个词的权重,看看哪一个有问题? 【参考方案1】:

在您的Ldist 计算中,您使用tf.tiletf.reshape 按以下方式查找不同聚类均值之间的距离(假设我们有三个聚类):

mu_1 - mu_1 mu_2 - mu_1 mu_3 - mu_1 mu_1 - mu_2mu_2 - mu_2 mu_3 - mu_2 mu_1 - mu_3 mu_2 - mu_3mu_3 - mu_3

问题在于您的距离向量包含零向量,然后您执行了范数运算。 tf.norm 得到数值不稳定,因为它在向量的长度上执行除法。结果是渐变得到zeroinf。看到这个github issue。

解决方案是像*** question 这样的方式删除那些零向量。

【讨论】:

【参考方案2】:

我认为您的问题来自不安全的 tf.norm(导致向量中某处为零,因此其梯度中为 nan)。 用这个自定义函数替换 tf.norm 会更好:

def tf_norm(inputs, axis=1, epsilon=1e-7,  name='safe_norm'):
    squared_norm    = tf.reduce_sum(tf.square(inputs), axis=axis, keep_dims=True)
    safe_norm       = tf.sqrt(squared_norm+epsilon)
    return tf.identity(safe_norm, name=name)

【讨论】:

以上是关于TensorFlow 损失函数在第一个 epoch 后归零的主要内容,如果未能解决你的问题,请参考以下文章

在执行第一个 epoch 后,Tensorflow 无法将批次附加在一起

为啥 Keras 的 train_on_batch 在第二个 epoch 产生零损失和准确率?

tensorflow学习笔记--深度学习中的epochs,batch_size,iterations详解

tensorflow学习笔记--深度学习中的epochs,batch_size,iterations详解

报告训练数据集中特定样本的训练损失,而不是训练过程中的平均损失 (TensorFlow)

第一个 epoch 后的神经网络生成 NaN 值作为输出,损失