Skip to content

Commit b95601f

Browse files
committed
add math_ops.reciprocal
1 parent 7d0d271 commit b95601f

File tree

5 files changed

+64
-8
lines changed

5 files changed

+64
-8
lines changed

src/TensorFlowNET.Core/Gradients/math_grad.py.cs renamed to src/TensorFlowNET.Core/Gradients/math_grad.cs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Tensorflow.Gradients
88
/// <summary>
99
/// Gradients for operators defined in math_ops.py.
1010
/// </summary>
11-
public class math_grad
11+
public class math_grad : Python
1212
{
1313
public static Tensor[] _AddGrad(Operation op, Tensor[] grads)
1414
{
@@ -33,6 +33,16 @@ public static Tensor[] _IdGrad(Operation op, Tensor[] grads)
3333
return new Tensor[] { grads[0] };
3434
}
3535

36+
public static Tensor[] _LogGrad(Operation op, Tensor[] grads)
37+
{
38+
var grad = grads[0];
39+
var x = op.inputs[0];
40+
return with(ops.control_dependencies(new Operation[] { grad }), dp => {
41+
x = math_ops.conj(x);
42+
return new Tensor[] { grad * math_ops.reciprocal(x) };
43+
});
44+
}
45+
3646
public static Tensor[] _MulGrad(Operation op, Tensor[] grads)
3747
{
3848
var x = op.inputs[0];
@@ -106,6 +116,11 @@ public static Tensor[] _MeanGrad(Operation op, Tensor[] grads)
106116
return new Tensor[] { math_ops.truediv(sum_grad, math_ops.cast(factor, sum_grad.dtype)), null };
107117
}
108118

119+
public static Tensor[] _NegGrad(Operation op, Tensor[] grads)
120+
{
121+
return new Tensor[] { -grads[0] };
122+
}
123+
109124
private static Tensor _safe_shape_div(Tensor x, Tensor y)
110125
{
111126
return math_ops.floordiv(x, gen_math_ops.maximum(y, 1));
@@ -145,13 +160,16 @@ public static Tensor[] _SumGrad(Operation op, Tensor[] grads)
145160
var axes = tensor_util.constant_value(op.inputs[1]);
146161
if(!(axes is null))
147162
{
148-
var rank = axes.shape.Rank;
149-
grad = array_ops.reshape(grad, new int[] { 1 });
150-
if (!input_0_shape.Contains(-1))
151-
input_shape = constant_op.constant(input_0_shape);
152-
else
153-
input_shape = array_ops.shape(op.inputs[0]);
154-
return new Tensor[] { gen_array_ops.tile(grad, input_shape), null };
163+
var rank = input_0_shape.Length;
164+
if (Enumerable.SequenceEqual(Enumerable.Range(0, rank), axes.Data<int>()))
165+
{
166+
grad = array_ops.reshape(grad, new int[] { 1 });
167+
if (!input_0_shape.Contains(-1))
168+
input_shape = constant_op.constant(input_0_shape);
169+
else
170+
input_shape = array_ops.shape(op.inputs[0]);
171+
return new Tensor[] { gen_array_ops.tile(grad, input_shape), null };
172+
}
155173
}
156174
}
157175

src/TensorFlowNET.Core/Gradients/nn_grad.py.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ public static Tensor[] _ReluGrad(Operation op, Tensor[] grads)
2727
return new Tensor[] { gen_nn_ops.relu_grad(grads[0], op.outputs[0]) };
2828
}
2929

30+
/// <summary>
31+
/// The derivative of the softmax nonlinearity.
32+
/// </summary>
33+
/// <param name="op"></param>
34+
/// <param name="grads"></param>
35+
/// <returns></returns>
36+
public static Tensor[] _SoftmaxGrad(Operation op, Tensor[] grads)
37+
{
38+
var grad_softmax = grads[0];
39+
40+
var softmax = op.outputs[0];
41+
var sum_channels = math_ops.reduce_sum(grad_softmax * softmax, -1, keepdims: true);
42+
return new Tensor[] { (grad_softmax - sum_channels) * softmax };
43+
}
44+
3045
/// <summary>
3146
/// Gradient function for SoftmaxCrossEntropyWithLogits.
3247
/// </summary>

src/TensorFlowNET.Core/Gradients/ops.gradient_function_mapping.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public static Func<Operation, Tensor[], Tensor[]> get_gradient_function(Operatio
2424
return nn_grad._BiasAddGrad(oper, out_grads);
2525
case "Identity":
2626
return math_grad._IdGrad(oper, out_grads);
27+
case "Log":
28+
return math_grad._LogGrad(oper, out_grads);
2729
case "MatMul":
2830
return math_grad._MatMulGrad(oper, out_grads);
2931
case "Merge":
@@ -32,6 +34,8 @@ public static Func<Operation, Tensor[], Tensor[]> get_gradient_function(Operatio
3234
return math_grad._MulGrad(oper, out_grads);
3335
case "Mean":
3436
return math_grad._MeanGrad(oper, out_grads);
37+
case "Neg":
38+
return math_grad._NegGrad(oper, out_grads);
3539
case "Sum":
3640
return math_grad._SumGrad(oper, out_grads);
3741
case "Sub":
@@ -46,6 +50,8 @@ public static Func<Operation, Tensor[], Tensor[]> get_gradient_function(Operatio
4650
return nn_grad._ReluGrad(oper, out_grads);
4751
case "Squeeze":
4852
return array_grad._SqueezeGrad(oper, out_grads);
53+
case "Softmax":
54+
return nn_grad._SoftmaxGrad(oper, out_grads);
4955
case "SoftmaxCrossEntropyWithLogits":
5056
return nn_grad._SoftmaxCrossEntropyWithLogitsGrad(oper, out_grads);
5157
case "Transpose":

src/TensorFlowNET.Core/Operations/gen_math_ops.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,13 @@ public static Tensor real_div(Tensor x, Tensor y, string name = null)
142142
return _op.outputs[0];
143143
}
144144

145+
public static Tensor reciprocal(Tensor x, string name = null)
146+
{
147+
var _op = _op_def_lib._apply_op_helper("Reciprocal", name, args: new { x });
148+
149+
return _op.outputs[0];
150+
}
151+
145152
public static Tensor floor_mod(Tensor x, Tensor y, string name = null)
146153
{
147154
var _op = _op_def_lib._apply_op_helper("FloorMod", name, args: new { x, y });

src/TensorFlowNET.Core/Operations/math_ops.py.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ public static Tensor reduced_shape(Tensor input_shape, Tensor axes)
126126
return gen_data_flow_ops.dynamic_stitch(a1, a2);
127127
}
128128

129+
/// <summary>
130+
/// Computes the reciprocal of x element-wise.
131+
/// </summary>
132+
/// <param name="x"></param>
133+
/// <param name="name"></param>
134+
/// <returns></returns>
135+
public static Tensor reciprocal(Tensor x, string name = null)
136+
=> gen_math_ops.reciprocal(x, name: name);
137+
138+
129139
/// <summary>
130140
/// Computes log(sum(exp(elements across dimensions of a tensor))).
131141
/// Reduces `input_tensor` along the dimensions given in `axis`.

0 commit comments

Comments
 (0)