diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs index 6ee90749..bbf240e3 100644 --- a/src/TensorFlowNET.Core/APIs/tf.math.cs +++ b/src/TensorFlowNET.Core/APIs/tf.math.cs @@ -54,6 +54,24 @@ namespace Tensorflow public static Tensor ceil(Tensor x, string name = null) => gen_math_ops.ceil(x, name); + /// + /// Computes sin of x element-wise. + /// + /// + /// + /// + public static Tensor sin(Tensor x, string name = null) + => gen_math_ops.sin(x, name); + + /// + /// Computes hyperbolic sine of x element-wise. + /// + /// + /// + /// + public static Tensor sinh(Tensor x, string name = null) + => gen_math_ops.sinh(x, name); + /// /// Computes cos of x element-wise. /// @@ -72,6 +90,12 @@ namespace Tensorflow public static Tensor cosh(Tensor x, string name = null) => gen_math_ops.cosh(x, name); + public static Tensor tan(Tensor x, string name = null) + => gen_math_ops.tan(x, name); + + public static Tensor tanh(Tensor x, string name = null) + => gen_math_ops.tanh(x, name); + /// /// Returns element-wise largest integer not greater than x. /// @@ -257,6 +281,9 @@ namespace Tensorflow return math_ops.reduce_sum(input, axis); } + public static Tensor sum(Tensor input, int axis, bool keep_dims = false, string name = null) + => gen_math_ops._sum(input, axis, keep_dims: keep_dims, name: name); + public static Tensor reduce_mean(Tensor input_tensor, int[] axis = null, bool keepdims = false, string name = null, int? reduction_indices = null) => math_ops.reduce_mean(input_tensor, axis: axis, keepdims: keepdims, name: name, reduction_indices: reduction_indices); diff --git a/src/TensorFlowNET.Core/Clustering/_InitializeClustersOpFactory.cs b/src/TensorFlowNET.Core/Clustering/_InitializeClustersOpFactory.cs index 14393708..54edf83b 100644 --- a/src/TensorFlowNET.Core/Clustering/_InitializeClustersOpFactory.cs +++ b/src/TensorFlowNET.Core/Clustering/_InitializeClustersOpFactory.cs @@ -52,13 +52,6 @@ namespace Tensorflow.Clustering _num_data = math_ops.add_n(_inputs.Select(i => array_ops.shape(i)[0]).ToArray()); } - public Tensor[] op() - { - return control_flow_ops.cond(gen_math_ops.equal(_num_remaining, 0), - () => new Operation[] { check_ops.assert_equal(_cluster_centers_initialized, true) }, - _initialize); - } - private Operation[] _initialize() { with(ops.control_dependencies(new Operation[] @@ -72,6 +65,17 @@ namespace Tensorflow.Clustering throw new NotImplementedException("_InitializeClustersOpFactory _initialize"); } + public Tensor[] op() + { + return control_flow_ops.cond(gen_math_ops.equal(_num_remaining, 0), + () => + { + var op = check_ops.assert_equal(_cluster_centers_initialized, true); + return new Operation[] { op }; + }, + _initialize); + } + /*private int _add_new_centers() { var new_centers = _choose_initial_centers(); diff --git a/src/TensorFlowNET.Core/Operations/Operation.Control.cs b/src/TensorFlowNET.Core/Operations/Operation.Control.cs index 39a011a8..812ca9fb 100644 --- a/src/TensorFlowNET.Core/Operations/Operation.Control.cs +++ b/src/TensorFlowNET.Core/Operations/Operation.Control.cs @@ -25,7 +25,7 @@ namespace Tensorflow public void _add_control_input(Operation op) { - c_api.TF_AddControlInput(_handle, op); + c_api.TF_AddControlInput(_operDesc, op); } public void _add_control_inputs(Operation[] ops) diff --git a/src/TensorFlowNET.Core/Operations/Operation.cs b/src/TensorFlowNET.Core/Operations/Operation.cs index 0979c150..b6952540 100644 --- a/src/TensorFlowNET.Core/Operations/Operation.cs +++ b/src/TensorFlowNET.Core/Operations/Operation.cs @@ -11,6 +11,7 @@ namespace Tensorflow public partial class Operation : ITensorOrOperation { private readonly IntPtr _handle; // _c_op in python + private readonly IntPtr _operDesc; private Graph _graph; //[JsonIgnore] @@ -58,9 +59,9 @@ namespace Tensorflow { _graph = g; - var desc = c_api.TF_NewOperation(g, opType, oper_name); - c_api.TF_SetAttrType(desc, "dtype", TF_DataType.TF_INT32); - c_api.TF_FinishOperation(desc, status); + _operDesc = c_api.TF_NewOperation(g, opType, oper_name); + c_api.TF_SetAttrType(_operDesc, "dtype", TF_DataType.TF_INT32); + _handle = c_api.TF_FinishOperation(_operDesc, status); } /// @@ -112,7 +113,7 @@ namespace Tensorflow op_def = g.GetOpDef(node_def.Op); var grouped_inputs = _reconstruct_sequence_inputs(op_def, inputs, node_def.Attr); - _handle = ops._create_c_op(g, node_def, grouped_inputs, control_input_ops.ToArray()); + (_handle, _operDesc) = ops._create_c_op(g, node_def, grouped_inputs, control_input_ops.ToArray()); // Initialize self._outputs. output_types = new TF_DataType[NumOutputs]; diff --git a/src/TensorFlowNET.Core/Operations/check_ops.cs b/src/TensorFlowNET.Core/Operations/check_ops.cs index 169cb333..8f395223 100644 --- a/src/TensorFlowNET.Core/Operations/check_ops.cs +++ b/src/TensorFlowNET.Core/Operations/check_ops.cs @@ -12,12 +12,29 @@ namespace Tensorflow /// /// /// - public static Operation assert_equal(object t1, object t2, object[] data = null, string name = null) + public static Operation assert_equal(object t1, object t2, object[] data = null, string message = null, string name = null) { + if (message == null) + message = ""; + return with(ops.name_scope(name, "assert_equal", new { t1, t2, data }), delegate { var x = ops.convert_to_tensor(t1, name: "x"); var y = ops.convert_to_tensor(t2, name: "y"); + + if (data == null) + { + data = new object[] + { + message, + "Condition x == y did not hold element-wise:", + $"x (%s) = {x.name}", + x, + $"y (%s) = {y.name}", + y + }; + } + var condition = math_ops.reduce_all(gen_math_ops.equal(x, y)); var x_static = tensor_util.constant_value(x); var y_static = tensor_util.constant_value(y); diff --git a/src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs b/src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs index 79416930..8ed7c17e 100644 --- a/src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs +++ b/src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs @@ -16,14 +16,16 @@ namespace Tensorflow name = scope; var xs = ops.convert_n_to_tensor(data); condition = ops.convert_to_tensor(condition, name: "Condition"); - Func true_assert = () => new Operation[] + Func true_assert = () => { - gen_logging_ops._assert(condition, data, summarize, name: "Assert") + var assert = gen_logging_ops._assert(condition, data, summarize, name: "Assert"); + return new Operation[] { assert }; }; - Func false_assert = () => new Operation[] + Func false_assert = () => { - gen_control_flow_ops.no_op() + var op = gen_control_flow_ops.no_op(); + return new Operation[] { op }; }; var guarded_assert = cond(condition, false_assert, true_assert, name: "AssertGuard"); diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs index 25ae46ed..c562586a 100644 --- a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs @@ -101,6 +101,20 @@ namespace Tensorflow return _op.outputs[0]; } + public static Tensor sin(Tensor x, string name = null) + { + var _op = _op_def_lib._apply_op_helper("Sin", name, args: new { x }); + + return _op.outputs[0]; + } + + public static Tensor sinh(Tensor x, string name = null) + { + var _op = _op_def_lib._apply_op_helper("Sinh", name, args: new { x }); + + return _op.outputs[0]; + } + public static Tensor cos(Tensor x, string name = null) { var _op = _op_def_lib._apply_op_helper("Cos", name, args: new { x }); @@ -115,6 +129,20 @@ namespace Tensorflow return _op.outputs[0]; } + public static Tensor tan(Tensor x, string name = null) + { + var _op = _op_def_lib._apply_op_helper("Tan", name, args: new { x }); + + return _op.outputs[0]; + } + + public static Tensor tanh(Tensor x, string name = null) + { + var _op = _op_def_lib._apply_op_helper("Tanh", name, args: new { x }); + + return _op.outputs[0]; + } + public static Tensor floor(Tensor x, string name = null) { var _op = _op_def_lib._apply_op_helper("Floor", name, args: new { x }); diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs index f14affbc..34d6a8f7 100644 --- a/src/TensorFlowNET.Core/Tensors/dtypes.cs +++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs @@ -10,6 +10,8 @@ namespace Tensorflow { switch (type) { + case TF_DataType.TF_BOOL: + return typeof(bool); case TF_DataType.TF_INT32: return typeof(int); case TF_DataType.TF_INT16: diff --git a/src/TensorFlowNET.Core/Tensors/tensor_util.cs b/src/TensorFlowNET.Core/Tensors/tensor_util.cs index 870db57b..a2830fc1 100644 --- a/src/TensorFlowNET.Core/Tensors/tensor_util.cs +++ b/src/TensorFlowNET.Core/Tensors/tensor_util.cs @@ -47,16 +47,23 @@ namespace Tensorflow var tensor_dtype = tensor.Dtype.as_numpy_dtype(); if (tensor.TensorContent.Length > 0) - return np.frombuffer(tensor.TensorContent.ToByteArray(), tensor_dtype) - .reshape(shape); + { + return np.frombuffer(tensor.TensorContent.ToByteArray(), tensor_dtype).reshape(shape); + } else if (tensor.Dtype == DataType.DtHalf || tensor.Dtype == DataType.DtBfloat16) ; else if (tensor.Dtype == DataType.DtFloat) ; else if (new DataType[] { DataType.DtInt32, DataType.DtUint8 }.Contains(tensor.Dtype)) + { if (tensor.IntVal.Count == 1) - return np.repeat(np.array(tensor.IntVal[0]), Convert.ToInt32(num_elements)) - .reshape(shape); + return np.repeat(np.array(tensor.IntVal[0]), num_elements).reshape(shape); + } + else if (tensor.Dtype == DataType.DtBool) + { + if (tensor.BoolVal.Count == 1) + return np.repeat(np.array(tensor.BoolVal[0]), num_elements).reshape(shape); + } throw new NotImplementedException("MakeNdarray"); } diff --git a/src/TensorFlowNET.Core/Variables/RefVariable.cs b/src/TensorFlowNET.Core/Variables/RefVariable.cs index e7ee3043..8d20f34d 100644 --- a/src/TensorFlowNET.Core/Variables/RefVariable.cs +++ b/src/TensorFlowNET.Core/Variables/RefVariable.cs @@ -265,7 +265,7 @@ namespace Tensorflow public override string ToString() { - return $"tf.Variable '{name}' shape={shape} dtype={dtype}"; + return $"tf.RefVariable '{name}' shape={shape} dtype={dtype}"; } public VariableDef to_proto(string export_scope) diff --git a/src/TensorFlowNET.Core/ops.py.cs b/src/TensorFlowNET.Core/ops.py.cs index 2c672d42..43a3c9ba 100644 --- a/src/TensorFlowNET.Core/ops.py.cs +++ b/src/TensorFlowNET.Core/ops.py.cs @@ -122,7 +122,7 @@ namespace Tensorflow /// /// A list of `Operation`s to set as control dependencies. /// A wrapped TF_Operation*. - public static IntPtr _create_c_op(Graph graph, NodeDef node_def, T[] inputs, Operation[] control_inputs) + public static (IntPtr, IntPtr) _create_c_op(Graph graph, NodeDef node_def, T[] inputs, Operation[] control_inputs) { var op_desc = graph.NewOperation(node_def.Op, node_def.Name); @@ -164,7 +164,7 @@ namespace Tensorflow status.Check(true); - return c_op; + return (c_op, op_desc); } public static OpDef _get_op_def(Graph graph, string type) diff --git a/test/TensorFlowNET.Examples/KMeansClustering.cs b/test/TensorFlowNET.Examples/KMeansClustering.cs index ece7623d..93fae200 100644 --- a/test/TensorFlowNET.Examples/KMeansClustering.cs +++ b/test/TensorFlowNET.Examples/KMeansClustering.cs @@ -16,7 +16,7 @@ namespace TensorFlowNET.Examples public class KMeansClustering : Python, IExample { public int Priority => 8; - public bool Enabled => false; + public bool Enabled => true; public string Name => "K-means Clustering"; Datasets mnist;