| @@ -36,7 +36,7 @@ namespace Tensorflow.Gradients | |||
| return new Tensor[] { gen_ops.mul(grad, gen_math_ops.sign(x)) }; | |||
| } | |||
| [RegisterGradient("Add")] | |||
| [RegisterGradient("AddV2")] | |||
| public static Tensor[] _AddGrad(Operation op, Tensor[] grads) | |||
| { | |||
| var x = op.inputs[0]; | |||
| @@ -107,7 +107,9 @@ namespace Tensorflow.Gradients | |||
| var y = op.outputs[0]; // y = e^x | |||
| return tf_with(ops.control_dependencies(new Operation[] { grad }), dp => { | |||
| y = math_ops.conj(y); | |||
| return new Tensor[] { math_ops.mul_no_nan(y, grad) }; | |||
| // forward_compatible(2019, 9, 14) | |||
| // return new Tensor[] { math_ops.mul_no_nan(y, grad) }; | |||
| return new Tensor[] { grad * y }; | |||
| }); | |||
| } | |||
| @@ -167,8 +169,7 @@ namespace Tensorflow.Gradients | |||
| new TF_DataType[] { tf.int32, tf.float32 }.Contains(grad.dtype)) | |||
| return new Tensor[] { gen_math_ops.mul(grad, y), gen_math_ops.mul(grad, x) }; | |||
| var sx = array_ops.shape(x); | |||
| var sy = array_ops.shape(y); | |||
| var (sx, sy) = SmartBroadcastGradientArgs(x, y); | |||
| var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | |||
| x = math_ops.conj(x); | |||
| @@ -355,8 +356,8 @@ namespace Tensorflow.Gradients | |||
| : gen_math_ops.less_equal(x, y); | |||
| var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | |||
| var xgrad = array_ops.where(xmask, grad, zeros); | |||
| var ygrad = array_ops.where(xmask, zeros, grad); | |||
| var gx = array_ops.reshape(math_ops.reduce_sum(xgrad, rx), sx); | |||
| var ygrad = array_ops.where(xmask, zeros, grad); | |||
| var gy = array_ops.reshape(math_ops.reduce_sum(ygrad, ry), sy); | |||
| return new Tensor[] { gx, gy }; | |||
| } | |||
| @@ -397,14 +398,13 @@ namespace Tensorflow.Gradients | |||
| _ShapesFullySpecifiedAndEqual(x, y, grad)) | |||
| return new Tensor[] { grad, -grad }; | |||
| var sx = array_ops.shape(x); | |||
| var sy = array_ops.shape(y); | |||
| var (sx, sy) = SmartBroadcastGradientArgs(x, y); | |||
| var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | |||
| var r1 = gen_array_ops.reshape(math_ops.reduce_sum(grad, rx), sx); | |||
| var r2 = gen_array_ops.reshape(-math_ops.reduce_sum(grad, ry), sy); | |||
| var gx = array_ops.reshape(math_ops.reduce_sum(grad, rx), sx); | |||
| var gy = array_ops.reshape(math_ops.reduce_sum(-grad, ry), sy); | |||
| return new Tensor[] { r1, r2 }; | |||
| return new Tensor[] { gx, gy }; | |||
| } | |||
| public static bool _ShapesFullySpecifiedAndEqual(Tensor x, Tensor y, Tensor grad) | |||
| @@ -468,15 +468,16 @@ namespace Tensorflow.Gradients | |||
| x = math_ops.conj(x); | |||
| y = math_ops.conj(y); | |||
| var realdiv1 = gen_math_ops.real_div(-x, y); | |||
| var realdiv2 = gen_math_ops.real_div(realdiv1, y); | |||
| var reduce_sum1 = math_ops.reduce_sum(grad * realdiv2, ry); | |||
| var reshape1 = gen_array_ops.reshape(reduce_sum1, sy); | |||
| var realdiv3 = gen_math_ops.real_div(grad, y); | |||
| var reduce_sum2 = math_ops.reduce_sum(realdiv3, rx); | |||
| var reshape2 = gen_array_ops.reshape(reduce_sum2, sx); | |||
| var reshape1 = array_ops.reshape( | |||
| math_ops.reduce_sum( | |||
| math_ops.realdiv(grad, y), rx), | |||
| sx); | |||
| var reshape2 = array_ops.reshape( | |||
| math_ops.reduce_sum( | |||
| grad * math_ops.realdiv(math_ops.realdiv(-x, y), y), ry), | |||
| sy); | |||
| return new Tensor[] { reshape2, reshape1 }; | |||
| return new Tensor[] { reshape1, reshape2 }; | |||
| } | |||
| [RegisterGradient("Sigmoid")] | |||
| @@ -602,14 +603,12 @@ namespace Tensorflow.Gradients | |||
| var y = op.inputs[1]; | |||
| var z = op.outputs[0]; | |||
| var sx = array_ops.shape(x); | |||
| var sy = array_ops.shape(y); | |||
| var (sx, sy) = SmartBroadcastGradientArgs(x, y); | |||
| var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | |||
| x = math_ops.conj(x); | |||
| y = math_ops.conj(y); | |||
| z = math_ops.conj(z); | |||
| var pow = gen_math_ops.pow(x, y - 1.0f); | |||
| var mul = grad * y * pow; | |||
| var mul = grad * y * math_ops.pow(x, y - 1.0f); | |||
| var reduce_sum = math_ops.reduce_sum(mul, rx); | |||
| var gx = gen_array_ops.reshape(reduce_sum, sx); | |||
| @@ -630,5 +629,29 @@ namespace Tensorflow.Gradients | |||
| return new Tensor[] { gx, gy }; | |||
| } | |||
| /// <summary> | |||
| /// Optimized version of `broadcast_gradient_args` that caches results. | |||
| /// </summary> | |||
| /// <param name="x"></param> | |||
| /// <param name="y"></param> | |||
| /// <returns></returns> | |||
| private static (Tensor, Tensor) SmartBroadcastGradientArgs(Tensor x, Tensor y) | |||
| { | |||
| Tensor sx, sy; | |||
| if (x.TensorShape.is_fully_defined() && | |||
| y.TensorShape.is_fully_defined()) | |||
| { | |||
| sx = array_ops.shape(x); | |||
| sy = array_ops.shape(y); | |||
| } | |||
| else | |||
| { | |||
| sx = array_ops.shape_internal(x, optimize: false); | |||
| sy = array_ops.shape_internal(y, optimize: false); | |||
| } | |||
| return (sx, sy); | |||
| } | |||
| } | |||
| } | |||