我正在尝试实施一个判别性损失函数,例如基于本文的图像分割:https://arxiv.org/pdf/1708.02551.pdf(此链接仅供读者参考;我不希望任何人都可以阅读它来帮助我!)
我的问题:一旦我从一个简单的丢失函数转移到一个更复杂的函数(就像你在附带的代码片段中看到的那样),丢失函数在第一个纪元之后就会清零。我检查了重量,几乎所有的重量似乎都在-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
问题:我知道如果没有阅读论文,很难理解代码的作用,但我有几个问题:
定义的损失函数是否存在明显的错误 以上?
任何人都知道为什么损失函数在第一个纪元后可以归零?
非常感谢您的时间和帮助!
答案 0 :(得分:1)
我认为你的问题受到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)
答案 1 :(得分:0)
在Ldist
计算中,您使用tf.tile
和tf.reshape
以下列方式查找不同群集方式之间的距离(假设我们有三个群集):
mu_1 - mu_1
mu_2 - mu_1
mu_3 - mu_1
mu_1 - mu_2
mu_2 - mu_2
mu_3 - mu_2
mu_1 - mu_3
mu_2 - mu_3
mu_3 - mu_3
问题是您的距离向量包含零向量,之后您执行标准操作。 tf.norm
数值不稳定,因为它在向量的长度上执行除法。结果是渐变得到zero
或inf
。请参阅此github issue。
解决方案是以类似Stackoverflow question的方式删除那些零向量。