J'ai vu différentes fonctions de perte d'erreur moyenne au carré dans différents articles pour les modèles de régression dans 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)
Quelles sont les différences entre ceux-ci?
Je dirais que la troisième équation est différente, alors que les 1ère et 2ème sont formellement identiques mais se comportent différemment pour des raisons numériques.
Je pense que la 3ème équation (en utilisant l2_loss
) ne renvoie que la moitié de la norme euclidienne au carré, c'est-à-dire la somme du carré élément par élément de l'entrée, qui est x=prediction-Y
. Vous ne divisez pas par le nombre d'échantillons n'importe où. Ainsi, si vous avez un très grand nombre d'échantillons, le calcul peut déborder (renvoyer Inf).
Les deux autres sont formellement les mêmes, calculant la moyenne du tenseur élémentaire x
. Cependant, bien que la documentation ne le spécifie pas explicitement, il est très probable que reduce_mean
utilise un algorithme adapté pour éviter les débordements avec un très grand nombre d'échantillons. En d’autres termes, il ne tente probablement pas de tout additionner en premier et puis diviser par N, mais utiliser une sorte de moyen glissant qui peut s’adapter à une situation arbitraire. nombre d'échantillons sans provoquer nécessairement un débordement.
Les première et deuxième fonctions de perte calculent la même chose, mais d'une manière légèrement différente. La troisième fonction calcule quelque chose de complètement différent. Vous pouvez le voir en exécutant ce code:
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]
Maintenant, vous pouvez vérifier que 1-st et 2-nd calculent la même chose (en théorie) en remarquant que tf.pow(a - b, 2)
est identique à tf.squared_difference(a - b, 2)
. De plus, reduce_mean
Est identique à reduce_sum / number_of_element
. Le fait est que les ordinateurs ne peuvent pas tout calculer exactement. Pour voir ce que les instabilités numériques peuvent faire pour vos calculs, jetez un oeil à ceci:
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])
Il est facile de voir que la réponse devrait être 1, mais vous obtiendrez quelque chose comme ceci: [1.0, 0.26843545]
.
En ce qui concerne votre dernière fonction, la documentation indique que:
Calcule la moitié de la norme L2 d'un tenseur sans le carré: output = sum (t ** 2)/2
Donc, si vous voulez qu'il calcule la même chose (en théorie) que le premier, vous devez l’adapter de manière appropriée:
loss3 = tf.nn.l2_loss(Y1 - Y2) * 2 / (reduce(lambda x, y: x*y, shape_obj))