Как реализовать 0.5 * || euclidean_norm || ^ 2? - PullRequest
0 голосов
/ 15 мая 2018

Я хочу использовать евклидову норму в качестве функции потерь 0,5 || Корреляция || ^ 2.Но, если я это осуществлю, появится не правильный результат.Должно появиться снова левое или правое входное изображение.

Я реализовал два градиента.grad выплевывает левое или правое изображение, в то время как grad_norm (евклидово расстояние) выплевывает очень большие числа ...

import tensorflow as tf

im1 = np.ascontiguousarray(np.arange(36).reshape((1,3,3,4))).astype(np.float32)
im2 = np.ascontiguousarray(np.arange(36,72).reshape((1,3,3,4))).astype(np.float32)
t_mult = tf.multiply(t_im1, t_im2)
t_corr = tf.reduce_sum(t_mult, axis=[1])
grad = tf.gradients(ys=t_corr, xs=[t_im1, t_im2])

# Euclidiean Norm:  1/2 ||t_corr||^2 = df/im0 = im1
loss1 = tf.multiply(tf.square(t_corr), 0.5)
grad_norm = tf.gradients(ys=loss1, xs=[t_im1, t_im2], stop_gradients=[t_im1, t_im2])
loss1 = tf.multiply(tf.square(t_corr), 0.5)


sess = tf.InteractiveSession()
# print t_mult.eval()
# print t_corr.eval()
# print grad0[0].eval() # returns right image
# print grad0[1].eval() # returns left image

grad_norm[0].eval() # ought to return left image

1 Ответ

0 голосов
/ 15 мая 2018

Нет, код ведет себя правильно, у вас есть теоретическая проблема.

  1. t_mult - поэлементное произведение im1 и im2 .Ясно, что δ (im1 * im2) / δ im2 действительно даст im1 , поэтому tf.gradiens( t_mult, t_im2 ) даст im1.

  2. Когда вы примените tf.reduce_sum(), то есть, в основном, вы сложите все элементы вдоль оси, это не изменится, потому что tf.gradiens() принимает частную производную , и полная сумма изменяется только с каждым элементом im1.Поэтому grad = tf.gradients( t_corr, t_im2 ) также дает im1.

  3. Однако, когда вы берете квадрат, ситуация меняется.Поскольку вы возводите в квадрат сумму элементов вдоль оси , между ними будет взаимодействие, вы будете получать не только квадратные члены, но и перекрестные произведения каждой пары.Это добавит кучу линейных членов вдоль квадрата, и когда вы возьмете производную, вы получите не только δ x 2 / δ x = 2 x , но множество других терминов, связанных с взаимодействиями между элементами.

  4. Истинная проблема в этой строке: # Euclidiean Norm: 1/2 ||t_corr||^2 = df/im0 = im1, потому что реальная формула для евклидовой нормы - это √Σ x i 2 .Но это также не даст чистого im0, потому что если вы возьмете квадратный корень, у вас снова будут взаимодействия.Если вы хотите получить обратно im0, вам нужно вычислить loss1 = tf.reduce_sum( 0.5 * tf.square( t_mult ), axis = 1 ), и как только вы возьмете производную, вы должны разделить на квадрат другого изображения.Не уверен, что вы пытаетесь достичь, но этот код (проверено):

from __future__ import print_function
import tensorflow as tf
import numpy as np

im1 = np.ascontiguousarray(np.arange(36).reshape((1,3,3,4))).astype(np.float32)
t_im1 = tf.constant( im1 )
im2 = np.ascontiguousarray(np.arange(36,72).reshape((1,3,3,4))).astype(np.float32)
t_im2 = tf.constant( im2 )
t_mult = tf.multiply( t_im1, t_im2 )
t_corr = tf.reduce_sum(t_mult, axis=[1])
grad = tf.gradients( ys=t_corr, xs= t_im2, name = "grad" )

# Euclidiean Norm:  0.5 * sqrt( sum( ||t_mult||^2 ) ) = d f/d im1 = im2
loss1 = tf.reduce_sum( 0.5 * tf.square( t_mult ), axis = 1 )
grad_norm = tf.gradients( ys = loss1, xs = t_im1, name = "grad_norm" ) / t_im2 ** 2

with tf.Session() as sess:
    fetch = [ t_im1, grad[ 0 ], grad_norm[ 0 ] ]
    res = sess.run( fetch )
    for idx, v in enumerate( res ):
        print( " =========================")
        print( fetch[ idx ].name )
        print()
        print( v )

выведет:

=========================
Const: 0

[[[[0. 1. 2. 3.]
[4. 5. 6. 7.]
[8. 9. 10. 11.]]

[[12.13. 14. 15.]
[16.17. 18. 19.]
[20.21. 22. 23.]]

[[24.25. 26. 27.]
[28.29. 30. 31.]
[32.33. 34. 35.]]]]
================================
град / Mul_grad / Mul_1: 0

[[[[0. 1. 2. 3.]
[4. 5. 6. 7.]
[8. 9. 10. 11.]]

[[12.13. 14. 15.]
[16.17. 18. 19.]
[20.21. 22. 23.]]

[[24.25. 26. 27.]
[28.29. 30. 31.]
[32.33. 34. 35.]]]]
================================
strided_slice: 0

[[[[0. 1. 2. 3.]
[4. 5. 6. 7.]
[8. 9. 10. 11.]]

[[12.13. 14. 15.]
[16.17. 18. 19.]
[20.21. 22. 23.]]

[[24.25. 26. 27.]
[28.29. 30. 31.]
[32.33. 34. 35.]]]]

...