Функция потери квадратов с квадратом
Я видел несколько различных среднеквадратичных функций потери ошибок в разных сообщениях для моделей регрессии в 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)
В чем разница между ними?
Ответы
Ответ 1
Я бы сказал, что третье уравнение отличается, а 1 и 2 формально одинаковы, но ведут себя по-разному из-за численных проблем.
Я думаю, что 3-е уравнение (используя l2_loss
) просто возвращает 1/2 квадратичной евклидовой нормы, т.е. сумму квадрата элемента в входе, который равен x=prediction-Y
. Вы не делите на количество образцов в любом месте. Таким образом, если у вас очень большое количество выборок, вычисление может переполняться (возвращая Inf).
Остальные два формально совпадают, вычисляя среднее значение квадратичного квадратичного тензора x
. Однако, хотя документация не указывает его явно, очень вероятно, что reduce_mean
использует алгоритм, который позволяет избежать переполнения с очень большим количеством выборок. Другими словами, он, вероятно, не пытается сначала суммировать все, а затем делить на N, но использовать какое-то среднее значение, которое может адаптироваться к произвольному количеству выборок, не обязательно вызывая переполнение.
Ответ 2
Первая и вторая функции потерь вычисляют одно и то же, но несколько иначе. Третья функция вычисляет нечто совершенно другое. Вы можете увидеть это, выполнив этот код:
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]
Теперь вы можете проверить, что 1-й и 2-й вычисления вычисляет одно и то же (теоретически), замечая, что tf.pow(a - b, 2)
совпадает с tf.squared_difference(a - b, 2)
. Также 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]
.
Что касается вашей последней функции, в документации указано, что:
Вычисляет половину нормы L2 тензора без sqrt: output = sum (t ** 2)/2
Итак, если вы хотите, чтобы он вычислял одно и то же (теоретически), как первое, вам нужно соответствующим образом масштабировать его:
loss3 = tf.nn.l2_loss(Y1 - Y2) * 2 / (reduce(lambda x, y: x*y, shape_obj))