我在Tensorflow中的回归模型的各个帖子中看到了一些不同的均方误差丢失函数:
loss = tf.reduce_sum(tf.pow(prediction - Y,2))/(n_instances)
loss = tf.reduce_mean(tf.squared_difference(prediction, Y))
loss = tf.nn.l2_loss(prediction - Y)
这些之间有什么区别?
答案 0 :(得分:14)
我会说第三个等式是不同的,而第一个和第二个等式正式相同但由于数值问题而表现不同。
我认为第3个等式(使用- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
NSRect bounds= [self bounds];
[[NSColor whiteColor] set];
[NSBezierPath fillRect:bounds];
}
)只返回平方欧几里德范数的1/2,即输入的元素平方和的总和,即{{1} }。您没有在任何地方除以样本数量。因此,如果您有大量样本,计算可能会溢出(返回Inf)。
另外两个正式相同,计算元素方形l2_loss
张量的平均值。但是,虽然文档没有明确指定,但x=prediction-Y
很可能使用适合于避免溢出大量样本的算法。换句话说,它可能不会先尝试对所有内容求和,而然后除以N,但使用某种滚动均值可以适应任意数量的样本而不必导致溢出。
答案 1 :(得分:10)
第一个和第二个损失函数计算相同的东西,但方式略有不同。第三个函数计算完全不同的东西。您可以通过执行以下代码来查看:
import tensorflow as tf
shape_obj = (5, 5)
shape_obj = (100, 6, 12)
Y1 = tf.random_normal(shape=shape_obj)
Y2 = tf.random_normal(shape=shape_obj)
loss1 = tf.reduce_sum(tf.pow(Y1 - Y2, 2)) / (reduce(lambda x, y: x*y, shape_obj))
loss2 = tf.reduce_mean(tf.squared_difference(Y1, Y2))
loss3 = tf.nn.l2_loss(Y1 - Y2)
with tf.Session() as sess:
print sess.run([loss1, loss2, loss3])
# when I run it I got: [2.0291963, 2.0291963, 7305.1069]
现在,您可以通过注意tf.pow(a - b, 2)
与tf.squared_difference(a - b, 2)
相同来验证1-st和2-nd计算相同的内容(理论上)。 reduce_mean
也与reduce_sum / number_of_element
相同。问题是计算机无法准确计算所有内容。要查看数值不稳定性对计算的影响,请看一下:
import tensorflow as tf
shape_obj = (5000, 5000, 10)
Y1 = tf.zeros(shape=shape_obj)
Y2 = tf.ones(shape=shape_obj)
loss1 = tf.reduce_sum(tf.pow(Y1 - Y2, 2)) / (reduce(lambda x, y: x*y, shape_obj))
loss2 = tf.reduce_mean(tf.squared_difference(Y1, Y2))
with tf.Session() as sess:
print sess.run([loss1, loss2])
很容易看出答案应该是1,但你会得到这样的结果:[1.0, 0.26843545]
。
关于你的上一个功能,文档说:
在没有sqrt:output = sum(t ** 2)/ 2
因此,如果您希望它(在理论上)计算与第一个相同的东西,您需要适当地缩放它:
loss3 = tf.nn.l2_loss(Y1 - Y2) * 2 / (reduce(lambda x, y: x*y, shape_obj))