Функция потери квадратов с квадратом

Я видел несколько различных среднеквадратичных функций потери ошибок в разных сообщениях для моделей регрессии в 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))