diff --git a/docs/source/Constant.md b/docs/source/Constant.md index f6ebf461..655a4b08 100644 --- a/docs/source/Constant.md +++ b/docs/source/Constant.md @@ -47,4 +47,14 @@ var tensor = tf.constant(nd); Now let's explore how constant works. -现在让我探究一下`tf.constant`是怎么工作的。 \ No newline at end of file +现在让我探究一下`tf.constant`是怎么工作的。 + + + +##### Other functions to create a Constant + +* tf.zeros +* tf.zeros_like +* tf.ones +* tf.ones_like +* tf.fill \ No newline at end of file diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs index 9c283bbf..8fd922d3 100644 --- a/src/TensorFlowNET.Core/APIs/tf.math.cs +++ b/src/TensorFlowNET.Core/APIs/tf.math.cs @@ -36,13 +36,13 @@ namespace Tensorflow { Tensor rank; string name; - using (var namescop = new ops.name_scope("", "Rank", new List { input })) + using (var namescop = new ops.name_scope("", "Rank", new List { input })) { name = namescop; rank = gen_array_ops.rank(input, namescop); } - using (var namescope = new ops.name_scope("range", "Range", new List { 0D, input, 1D })) + using (var namescope = new ops.name_scope("range", "Range", new List { 0D, input, 1D })) { name = namescope; var start = ops.convert_to_tensor(0D); diff --git a/src/TensorFlowNET.Core/Gradients/gradients_impl.py.cs b/src/TensorFlowNET.Core/Gradients/gradients_impl.py.cs index cd639427..45cea9ed 100644 --- a/src/TensorFlowNET.Core/Gradients/gradients_impl.py.cs +++ b/src/TensorFlowNET.Core/Gradients/gradients_impl.py.cs @@ -50,7 +50,7 @@ namespace Tensorflow all.AddRange(grad_ys1); string grad_scope = ""; - using (var namescope = new ops.name_scope(name, "gradients", values: all)) + using (var namescope = new ops.name_scope(name, "gradients", values: all)) { grad_scope = namescope; // Get a uid for this call to gradients that can be used to help diff --git a/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs b/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs index f4b5b08f..642cbb13 100644 --- a/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs +++ b/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs @@ -41,7 +41,7 @@ namespace Tensorflow var input_types = new List(); string scope = ""; - using (var namescope = new ops.name_scope(name)) + using (var namescope = new ops.name_scope(name)) { scope = namescope; diff --git a/src/TensorFlowNET.Core/Operations/array_ops.py.cs b/src/TensorFlowNET.Core/Operations/array_ops.py.cs new file mode 100644 index 00000000..7f0b0e92 --- /dev/null +++ b/src/TensorFlowNET.Core/Operations/array_ops.py.cs @@ -0,0 +1,56 @@ +using NumSharp.Core; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tensorflow +{ + public class array_ops + { + public static Tensor zeros(Shape shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = "") + { + Tensor output = null; + + dtype = dtype.as_base_dtype(); + Python.with(new ops.name_scope(name, "zeros", shape), self => + { + name = self as ops.name_scope; + switch (dtype) + { + case TF_DataType.TF_BOOL: + output = _constant_if_small(false, shape, dtype, name); + break; + case TF_DataType.TF_DOUBLE: + output = _constant_if_small(0.0D, shape, dtype, name); + break; + case TF_DataType.TF_FLOAT: + output = _constant_if_small(0.0F, shape, dtype, name); + break; + case TF_DataType.TF_INT32: + output = _constant_if_small(0, shape, dtype, name); + break; + default: + break; + } + }); + + return output; + } + + private static Tensor _constant_if_small(T value, Shape shape, TF_DataType dtype, string name) + { + Tensor tShape = null; + var nd = np.zeros(shape); + if (shape.Size < 1000) + { + return constant_op.Constant(nd, name); + } + else + { + tShape = constant_op._tensor_shape_tensor_conversion_function(shape.as_shape(), dtype, name); + var c = constant_op.Constant(nd, name); + return gen_array_ops.fill(shape, value, name); + } + } + } +} diff --git a/src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs b/src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs index 6146e54d..6b784239 100644 --- a/src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs +++ b/src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs @@ -9,7 +9,7 @@ namespace Tensorflow { public static Operation group(List inputs, string name = "") { - using(var namescope = new ops.name_scope(name, "group_deps", inputs)) + using(var namescope = new ops.name_scope(name, "group_deps", inputs)) { name = namescope; diff --git a/src/TensorFlowNET.Core/Operations/gen_array_ops.cs b/src/TensorFlowNET.Core/Operations/gen_array_ops.cs index f9896275..0ff134cc 100644 --- a/src/TensorFlowNET.Core/Operations/gen_array_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_array_ops.cs @@ -55,5 +55,24 @@ namespace Tensorflow return _op.outputs[0]; } + + /// + /// Creates a tensor filled with a scalar value. + /// + /// + /// + /// + /// + /// + public static Tensor fill(int[] dims, T value, string name = "") + { + var keywords = new Dictionary(); + keywords.Add("dims", dims); + keywords.Add("value", value); + + var _op = _op_def_lib._apply_op_helper("Fill", name); + + return _op.outputs[0]; + } } } diff --git a/src/TensorFlowNET.Core/Python.cs b/src/TensorFlowNET.Core/Python.cs index 9059be1e..78ba4786 100644 --- a/src/TensorFlowNET.Core/Python.cs +++ b/src/TensorFlowNET.Core/Python.cs @@ -14,12 +14,12 @@ namespace Tensorflow Console.WriteLine(obj.ToString()); } - public static void with(IPython py, Action action) + public static void with(IPython py, Action action) { try { py.__enter__(); - action(); + action(py); } catch (Exception ex) { diff --git a/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj b/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj index 2efeb120..182b457a 100644 --- a/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj +++ b/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj @@ -37,7 +37,7 @@ TensorFlow 1.13 RC. - + diff --git a/src/TensorFlowNET.Core/Tensors/constant_op.cs b/src/TensorFlowNET.Core/Tensors/constant_op.cs index 9d364b3c..b98150ae 100644 --- a/src/TensorFlowNET.Core/Tensors/constant_op.cs +++ b/src/TensorFlowNET.Core/Tensors/constant_op.cs @@ -46,5 +46,37 @@ namespace Tensorflow return op.outputs[0]; } + + /// + /// Function to convert TensorShape to Tensor. + /// + /// + /// + /// + /// + /// + public static Tensor _tensor_shape_tensor_conversion_function(TensorShape s, TF_DataType dtype = TF_DataType.DtInvalid, string name = "", bool as_ref = false) + { + var s_list = s.Dimensions; + var int64_value = 0; + foreach(var dim in s_list) + { + if (dim > Math.Pow(2, 31)) + { + int64_value = dim; + break; + } + } + + if(int64_value > 0) + { + dtype = TF_DataType.TF_INT32; + } + + if (string.IsNullOrEmpty(name)) + name = "shape_as_tensor"; + + return constant_op.Constant(s_list, name); + } } } diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs index fc625c44..a923240b 100644 --- a/src/TensorFlowNET.Core/Tensors/dtypes.cs +++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs @@ -70,5 +70,12 @@ namespace Tensorflow (TF_DataType)Enum.Parse(typeof(TF_DataType), ((int)type - 100).ToString()) : type; } + + public static DataType as_base_dtype(this DataType type) + { + return (int)type > 100 ? + (DataType)Enum.Parse(typeof(DataType), ((int)type - 100).ToString()) : + type; + } } } diff --git a/src/TensorFlowNET.Core/Tensors/tensor_util.cs b/src/TensorFlowNET.Core/Tensors/tensor_util.cs index 76e77986..59aa3639 100644 --- a/src/TensorFlowNET.Core/Tensors/tensor_util.cs +++ b/src/TensorFlowNET.Core/Tensors/tensor_util.cs @@ -18,7 +18,7 @@ namespace Tensorflow var tensor_proto = new tensor_pb2.TensorProto { Dtype = numpy_dtype.as_datatype_enum(), - TensorShape = shape.as_shape(nd.shape).as_proto() + TensorShape = shape.reshape(nd.shape).as_proto() }; switch (nd.dtype.Name) @@ -94,7 +94,12 @@ namespace Tensorflow return new TensorShape(dims.Select(x => (int)x).ToArray()); } - public static TensorShape as_shape(this IShape shape, int[] dims) + public static TensorShape as_shape(this IShape shape) + { + return new TensorShape(shape.Dimensions); + } + + public static TensorShape reshape(this IShape shape, int[] dims) { return new TensorShape(dims); } diff --git a/src/TensorFlowNET.Core/APIs/tf.constant.cs b/src/TensorFlowNET.Core/Tensors/tf.constant.cs similarity index 65% rename from src/TensorFlowNET.Core/APIs/tf.constant.cs rename to src/TensorFlowNET.Core/Tensors/tf.constant.cs index 7d1e2a8e..e2a7bedd 100644 --- a/src/TensorFlowNET.Core/APIs/tf.constant.cs +++ b/src/TensorFlowNET.Core/Tensors/tf.constant.cs @@ -11,5 +11,10 @@ namespace Tensorflow { return constant_op.Constant(nd, name, verify_shape); } + + public static Tensor zeros(Shape shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = "") + { + return array_ops.zeros(shape, dtype, name); + } } } diff --git a/src/TensorFlowNET.Core/Variables/RefVariable.cs b/src/TensorFlowNET.Core/Variables/RefVariable.cs index 5736dd23..69a1f55b 100644 --- a/src/TensorFlowNET.Core/Variables/RefVariable.cs +++ b/src/TensorFlowNET.Core/Variables/RefVariable.cs @@ -65,7 +65,7 @@ namespace Tensorflow ops.init_scope(); var values = init_from_fn ? new List() : new List { initial_value }; - using (var namescope = new ops.name_scope(name, "Variable", values)) + using (var namescope = new ops.name_scope(name, "Variable", values)) { name = namescope; diff --git a/src/TensorFlowNET.Core/ops.name_scope.cs b/src/TensorFlowNET.Core/ops.name_scope.cs index 403d8897..c0e60b52 100644 --- a/src/TensorFlowNET.Core/ops.name_scope.cs +++ b/src/TensorFlowNET.Core/ops.name_scope.cs @@ -7,7 +7,7 @@ namespace Tensorflow { public partial class ops { - public class name_scope : IDisposable + public class name_scope : IPython { public string _name; public string _default_name; @@ -16,7 +16,7 @@ namespace Tensorflow public string _name_scope; private object _g_manager; - public name_scope(string name, string default_name = "", List values = null) + public name_scope(string name, string default_name = "", object values = null) { _name = name; _default_name = default_name; @@ -24,7 +24,7 @@ namespace Tensorflow // _ctx = new Context(); } - public string __enter__() + public void __enter__() { if (String.IsNullOrEmpty(_name)) { @@ -39,8 +39,6 @@ namespace Tensorflow g = get_default_graph(); _name_scope = g.name_scope(_name); - - return _name_scope; } public void Dispose() @@ -51,16 +49,17 @@ namespace Tensorflow g.old_stack = ""; } + public void __exit__() + { + } + /// /// __enter__() /// /// - public static implicit operator string(name_scope ns) + public static implicit operator string(name_scope ns) { - if (string.IsNullOrEmpty(ns._name_scope)) - return ns.__enter__(); - else - return ns._name_scope; + return ns._name_scope; } } } diff --git a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj index db80b4bd..b7436a2e 100644 --- a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj +++ b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj @@ -6,7 +6,7 @@ - + diff --git a/test/TensorFlowNET.UnitTest/ConstantTest.cs b/test/TensorFlowNET.UnitTest/ConstantTest.cs index 76348a77..caba1f59 100644 --- a/test/TensorFlowNET.UnitTest/ConstantTest.cs +++ b/test/TensorFlowNET.UnitTest/ConstantTest.cs @@ -2,6 +2,7 @@ using NumSharp.Core; using System; using System.Collections.Generic; +using System.Linq; using System.Text; using Tensorflow; @@ -26,6 +27,17 @@ namespace TensorFlowNET.UnitTest tensor = tf.constant("Elephant"); } + [TestMethod] + public void ZerosConst() + { + tensor = tf.zeros(new Shape(3, 2), TF_DataType.TF_INT32, "x"); + Assert.AreEqual(tensor.shape[0], 3); + Assert.AreEqual(tensor.shape[0], 2); + Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 0, 0, 0, 0 }, tensor.Data())); + + tensor = tf.zeros(new Shape(200, 300), TF_DataType.TF_INT32, "x"); + } + [TestMethod] public void NDimConst() { diff --git a/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj b/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj index 43dfb82d..5c2e39bd 100644 --- a/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj +++ b/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj @@ -19,7 +19,7 @@ - +