diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs index dec4c470..a28ec9d3 100644 --- a/src/TensorFlowNET.Core/APIs/tf.math.cs +++ b/src/TensorFlowNET.Core/APIs/tf.math.cs @@ -364,8 +364,8 @@ namespace Tensorflow public Tensor divide(Tensor x, T[] y, string name = null) where T : struct => x / ops.convert_to_tensor(y, dtype: x.dtype.as_base_dtype(), name: "y"); - public Tensor pow(T1 x, T2 y) - => gen_math_ops.pow(x, y); + public Tensor pow(T1 x, T2 y, string name = "pow") + => gen_math_ops.pow(x, y, name: name); /// /// Divides `x / y` elementwise, rounding toward the most negative integer. diff --git a/src/TensorFlowNET.Core/Gradients/math_grad.cs b/src/TensorFlowNET.Core/Gradients/math_grad.cs index 94e434cb..d8ca512a 100644 --- a/src/TensorFlowNET.Core/Gradients/math_grad.cs +++ b/src/TensorFlowNET.Core/Gradients/math_grad.cs @@ -33,10 +33,14 @@ namespace Tensorflow.Gradients var x = op.inputs[0]; var grad = grads[0]; - return new Tensor[] { gen_ops.mul(grad, gen_math_ops.sign(x)) }; + return new Tensor[] { grad * math_ops.sign(x) }; } [RegisterGradient("AddV2")] + public static Tensor[] _AddV2Grad(Operation op, Tensor[] grads) + => _AddGrad(op, grads); + + [RegisterGradient("Add")] public static Tensor[] _AddGrad(Operation op, Tensor[] grads) { var x = op.inputs[0]; diff --git a/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs b/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs index e842fcb4..5700ccdd 100644 --- a/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs +++ b/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs @@ -65,10 +65,6 @@ namespace Tensorflow var base_types = new List(); var types = new List(); -#if DEBUG - if (op_type_name == "FusedBatchNormGradV3") - ; -#endif // Perform input type inference foreach (var input_arg in op_def.InputArg) { diff --git a/src/TensorFlowNET.Core/Operations/Operation.Input.cs b/src/TensorFlowNET.Core/Operations/Operation.Input.cs index bbd11b0e..5c4106ae 100644 --- a/src/TensorFlowNET.Core/Operations/Operation.Input.cs +++ b/src/TensorFlowNET.Core/Operations/Operation.Input.cs @@ -40,13 +40,11 @@ namespace Tensorflow } return num; } -#if SERIALIZABLE - [JsonIgnore] -#endif public int NumInputs => c_api.TF_OperationNumInputs(_handle); private TF_DataType[] _input_types => _inputs_val._inputs.Select(x => x.dtype).ToArray(); private InputList _inputs_val; + public InputList inputs { get @@ -69,8 +67,10 @@ namespace Tensorflow } } - public int NumControlInputs => c_api.TF_OperationNumControlInputs(_handle); + public int NumControlInputs + => _handle == IntPtr.Zero ? 0 : c_api.TF_OperationNumControlInputs(_handle); + Operation[] _control_inputs; /// /// The `Operation` objects on which this op has a control dependency. /// @@ -87,7 +87,9 @@ namespace Tensorflow { get { - return GetControlInputs(); + if (_control_inputs == null || _control_inputs.Length == 0) + _control_inputs = GetControlInputs(); + return _control_inputs; } } diff --git a/src/TensorFlowNET.Core/Operations/Operation.Output.cs b/src/TensorFlowNET.Core/Operations/Operation.Output.cs index 3a70c107..bbf0b13f 100644 --- a/src/TensorFlowNET.Core/Operations/Operation.Output.cs +++ b/src/TensorFlowNET.Core/Operations/Operation.Output.cs @@ -26,9 +26,6 @@ namespace Tensorflow { public partial class Operation { -#if SERIALIZABLE - [JsonIgnore] -#endif public int NumOutputs => c_api.TF_OperationNumOutputs(_handle); public TF_DataType OutputType(int index) => c_api.TF_OperationOutputType(_tf_output(index)); diff --git a/src/TensorFlowNET.Core/Operations/Operation.cs b/src/TensorFlowNET.Core/Operations/Operation.cs index a0acf4bb..029f8d69 100644 --- a/src/TensorFlowNET.Core/Operations/Operation.cs +++ b/src/TensorFlowNET.Core/Operations/Operation.cs @@ -154,11 +154,6 @@ namespace Tensorflow public Operation(NodeDef node_def, Graph g, Tensor[] inputs = null, TF_DataType[] output_types = null, ITensorOrOperation[] control_inputs = null, TF_DataType[] input_types = null, string original_op = "", OpDef op_def = null) { _graph = g; - -#if DEBUG - if (node_def.Name == "define_second_stage_train/gradients/define_loss/conv_lobj_branch/batch_normalization/cond/FusedBatchNormV3_1_grad/FusedBatchNormGradV3") - ; -#endif // Build the list of control inputs. var control_input_ops = new List(); if (control_inputs != null) diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs index 7621d1b2..02bc1ada 100644 --- a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs @@ -140,6 +140,14 @@ namespace Tensorflow } public static Tensor add(Tx x, Ty y, string name = null) + { + // forward_compatible(2019, 6, 25): + var _op = _op_def_lib._apply_op_helper("Add", name, args: new { x, y }); + + return _op.output; + } + + public static Tensor add_v2(Tx x, Ty y, string name = null) { // forward_compatible(2019, 6, 25): var _op = _op_def_lib._apply_op_helper("AddV2", name, args: new { x, y }); @@ -213,7 +221,7 @@ namespace Tensorflow return op.outputs[0]; } - public static Tensor sign(Tensor x, string name = "Sign") + public static Tensor sign(T x, string name = "Sign") { var op = _op_def_lib._apply_op_helper("Sign", name: name, args: new {x}); @@ -448,7 +456,7 @@ namespace Tensorflow return _op.outputs[0]; } - public static Tensor cast(Tensor x, TF_DataType DstT, bool Truncate= false, string name= "") + public static Tensor cast(Tensor x, TF_DataType DstT, bool Truncate= false, string name= null) { var _op = _op_def_lib._apply_op_helper("Cast", name, args: new { x, DstT, Truncate }); diff --git a/src/TensorFlowNET.Core/Operations/math_ops.cs b/src/TensorFlowNET.Core/Operations/math_ops.cs index bc904028..34ab587f 100644 --- a/src/TensorFlowNET.Core/Operations/math_ops.cs +++ b/src/TensorFlowNET.Core/Operations/math_ops.cs @@ -35,14 +35,17 @@ namespace Tensorflow x = ops.convert_to_tensor(x, name: "x"); if (x.dtype.is_complex()) throw new NotImplementedException("math_ops.abs for dtype.is_complex"); - //return gen_math_ops.complex_abs(x, Tout: x.dtype.real_dtype, name: name); + //return gen_math_ops.complex_abs(x, Tout: x.dtype.real_dtype, name: name); return gen_math_ops._abs(x, name: name); }); } - public static Tensor add(Tx x, Ty y, string name = null) + public static Tensor add(Tx x, Ty y, string name = null) => gen_math_ops.add(x, y, name); + public static Tensor add_v2(Tx x, Ty y, string name = null) + => gen_math_ops.add_v2(x, y, name); + /// /// Adds all input tensors element-wise. /// @@ -53,21 +56,38 @@ namespace Tensorflow { inputs = ops.convert_n_to_tensor_or_indexed_slices(inputs); - if(inputs.Length == 1) + if (inputs.Length == 1) { var values = inputs[0]; if (name != null) return array_ops.identity(values, name: name); return values; } - + return gen_math_ops.add_n(inputs, name: name); } + public static Tensor cast(RefVariable x, TF_DataType dtype = TF_DataType.DtInvalid, string name = null) + { + var base_type = dtype.as_base_dtype(); + if (base_type == x.dtype) + return x; + + return tf_with(ops.name_scope(name, "Cast", new { x }), scope => + { + name = scope; + var t_x = ops.convert_to_tensor(x, name: "x"); + if (t_x.dtype.as_base_dtype() != base_type) + t_x = gen_math_ops.cast(t_x, base_type, name: name); + + return x; + }); + } + public static Tensor cast(Tensor x, TF_DataType dtype = TF_DataType.DtInvalid, string name = null) { var base_type = dtype.as_base_dtype(); - if(base_type == x.dtype) + if (base_type == x.dtype) return x; return tf_with(ops.name_scope(name, "Cast", new { x }), scope => @@ -98,13 +118,13 @@ namespace Tensorflow public static Tensor cumsum(Tensor x, T axis = default, bool exclusive = false, bool reverse = false, string name = null) { - return tf_with(ops.name_scope(name, "Cumsum", new {x}), scope => - { - name = scope; - x = ops.convert_to_tensor(x, name: "x"); + return tf_with(ops.name_scope(name, "Cumsum", new { x }), scope => + { + name = scope; + x = ops.convert_to_tensor(x, name: "x"); - return gen_math_ops.cumsum(x, axis: axis, exclusive: exclusive, reverse: reverse, name: name); - }); + return gen_math_ops.cumsum(x, axis: axis, exclusive: exclusive, reverse: reverse, name: name); + }); } /// @@ -221,7 +241,7 @@ namespace Tensorflow public static Tensor reduce_mean(Tensor[] input_tensors, int? axis = null, bool keepdims = false, string name = null) { - if(axis == null) + if (axis == null) { var r = _ReductionDims(input_tensors, axis); var m = gen_math_ops.mean(input_tensors, r, keepdims, name); @@ -263,14 +283,8 @@ namespace Tensorflow return gen_math_ops.sigmoid(x_tensor, name: name); } - public static Tensor sign(Tensor x, string name = null) - { - return tf_with(ops.name_scope(name, "Sign", new {x}), scope => - { - x = ops.convert_to_tensor(x, name: "x"); - return gen_math_ops.sign(x); - }); - } + public static Tensor sign(T x, string name = null) + => gen_math_ops.sign(x, name: name); /// /// Returns (x - y)(x - y) element-wise. diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Operators.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Operators.cs index b205674d..616a375f 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.Operators.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.Operators.cs @@ -328,7 +328,7 @@ namespace Tensorflow switch (name.ToLowerInvariant()) { case "add": - result = math_ops.add(x1, y1, name: scope); + result = math_ops.add_v2(x1, y1, name: scope); break; case "div": result = math_ops.div(x1, y1, name: scope);