如何实现0.5*||euclidean_norm||^2?

How to implement the 0.5*||euclidean_norm||^2?

我想使用欧氏范数作为损失函数 0.5 ||Correlation||^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. t_multim1[ 的逐元素乘积=37=]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. 然而,当你走正方形时,情况就变了。由于您要对 轴上的元素总和进行平方 ,它们之间会有相互作用,因此您不仅会得到平方项,还会得到每对的叉积。这将在正方形上添加一堆线性项,当你求导时,你不仅会得到 δx2x = 2x 但还有很多其他术语与元素之间的相互作用。

  4. 真正的问题是在这一行:# Euclidiean Norm: 1/2 ||t_corr||^2 = df/im0 = im1因为Euclidean norm的真正公式是√Σxi2。但这也不会产生干净的 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.]]]]
=========================
grad/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.]]]]