我正在使用 tensorflow 训练自动编码器,入门代码提供了一种计算均方误差作为损失函数的方法。
self.mse_loss = tf.reduce_mean(tf.square(self.x - self.x_))
请注意,self.x 是包含输入数据(MNIST,具有 784 个特征)的张量,self.x_ 是算法另一端解码器的结果。
我想使用 MSE 来找到一些输入参数的最佳值(即在我正在处理的这个无监督问题中找到的集群数量),但是 MSE 在不同的运行之间没有足够的区别来尝试肘部方法。相反,我认为我可以尝试不同的指标,例如均方对数误差。可以在此处找到该指标的公式。
最初我尝试了以下代码;
self.msle_loss = tf.reduce_mean(tf.square(tf.log(1 + self.x) - tf.log(1 + self.x_ )))
但是,每当我运行它时,它都会返回 nan。我认为这与 tf.log() 无法处理零有关。
所以我尝试过一些产生价值的解决方案(我只是不确定哪个是最好的);
- 使用 tf.clip_by_value()
self.msle_loss = tf.reduce_mean(tf.square(tf.math.log(tf.clip_by_value(1 + self.x,1e-10,1e10)) - tf.math.log(tf.clip_by_value(1 + self.x_,1e-10,1e10))))
这将运行并返回值,但我认为这是不正确的,因为它们非常大,大约。240
- 添加一个小常数
self.msle_loss = tf.reduce_mean(tf.square(tf.log(1 + (self.x + 1e-4)) - tf.log(1 + (self.x_ + 1e-4))))
这会产生有效值,小于解决方案 1),ca。12(所以小了一个数量级)。这让我担心这两种方法不能互换,这就引出了一个问题,这里的正确方法是什么?当我最初遇到添加一个小常数的建议时,建议是添加一个小得多的常数(1e-10),但我一直得到 nan 直到我将常数变得足够大,如 1e-4。
- 使用 tf.where() 我找到了一个旨在捕捉零的解决方案。
self.msle_loss = tf.reduce_mean(tf.square(tf.log(1. + tf.where(tf.equal(self.x, 0.), tf.ones_like(self.x), self.x)) - tf.log(1.0 + tf.where(tf.equal(self.x_, 0.), tf.ones_like(self.x_), self.x_))))
但是我认为我没有正确实施它,因为我仍然使用这种方法得到 nan 。
如果有人能够在不影响我得到的价值观的情况下提出最好的方法,我将不胜感激。谢谢。