| @@ -47,4 +47,14 @@ var tensor = tf.constant(nd); | |||||
| Now let's explore how constant works. | Now let's explore how constant works. | ||||
| 现在让我探究一下`tf.constant`是怎么工作的。 | |||||
| 现在让我探究一下`tf.constant`是怎么工作的。 | |||||
| ##### Other functions to create a Constant | |||||
| * tf.zeros | |||||
| * tf.zeros_like | |||||
| * tf.ones | |||||
| * tf.ones_like | |||||
| * tf.fill | |||||
| @@ -36,13 +36,13 @@ namespace Tensorflow | |||||
| { | { | ||||
| Tensor rank; | Tensor rank; | ||||
| string name; | string name; | ||||
| using (var namescop = new ops.name_scope<Tensor>("", "Rank", new List<Tensor> { input })) | |||||
| using (var namescop = new ops.name_scope("", "Rank", new List<Tensor> { input })) | |||||
| { | { | ||||
| name = namescop; | name = namescop; | ||||
| rank = gen_array_ops.rank(input, namescop); | rank = gen_array_ops.rank(input, namescop); | ||||
| } | } | ||||
| using (var namescope = new ops.name_scope<Tensor>("range", "Range", new List<Tensor> { 0D, input, 1D })) | |||||
| using (var namescope = new ops.name_scope("range", "Range", new List<Tensor> { 0D, input, 1D })) | |||||
| { | { | ||||
| name = namescope; | name = namescope; | ||||
| var start = ops.convert_to_tensor(0D); | var start = ops.convert_to_tensor(0D); | ||||
| @@ -50,7 +50,7 @@ namespace Tensorflow | |||||
| all.AddRange(grad_ys1); | all.AddRange(grad_ys1); | ||||
| string grad_scope = ""; | string grad_scope = ""; | ||||
| using (var namescope = new ops.name_scope<Tensor>(name, "gradients", values: all)) | |||||
| using (var namescope = new ops.name_scope(name, "gradients", values: all)) | |||||
| { | { | ||||
| grad_scope = namescope; | grad_scope = namescope; | ||||
| // Get a uid for this call to gradients that can be used to help | // Get a uid for this call to gradients that can be used to help | ||||
| @@ -41,7 +41,7 @@ namespace Tensorflow | |||||
| var input_types = new List<TF_DataType>(); | var input_types = new List<TF_DataType>(); | ||||
| string scope = ""; | string scope = ""; | ||||
| using (var namescope = new ops.name_scope<object>(name)) | |||||
| using (var namescope = new ops.name_scope(name)) | |||||
| { | { | ||||
| scope = namescope; | scope = namescope; | ||||
| @@ -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>(T value, Shape shape, TF_DataType dtype, string name) | |||||
| { | |||||
| Tensor tShape = null; | |||||
| var nd = np.zeros<T>(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<T>(shape, value, name); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -9,7 +9,7 @@ namespace Tensorflow | |||||
| { | { | ||||
| public static Operation group(List<Operation> inputs, string name = "") | public static Operation group(List<Operation> inputs, string name = "") | ||||
| { | { | ||||
| using(var namescope = new ops.name_scope<Operation>(name, "group_deps", inputs)) | |||||
| using(var namescope = new ops.name_scope(name, "group_deps", inputs)) | |||||
| { | { | ||||
| name = namescope; | name = namescope; | ||||
| @@ -55,5 +55,24 @@ namespace Tensorflow | |||||
| return _op.outputs[0]; | return _op.outputs[0]; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Creates a tensor filled with a scalar value. | |||||
| /// </summary> | |||||
| /// <typeparam name="T"></typeparam> | |||||
| /// <param name="dims"></param> | |||||
| /// <param name="value"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor fill<T>(int[] dims, T value, string name = "") | |||||
| { | |||||
| var keywords = new Dictionary<string, object>(); | |||||
| keywords.Add("dims", dims); | |||||
| keywords.Add("value", value); | |||||
| var _op = _op_def_lib._apply_op_helper("Fill", name); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -14,12 +14,12 @@ namespace Tensorflow | |||||
| Console.WriteLine(obj.ToString()); | Console.WriteLine(obj.ToString()); | ||||
| } | } | ||||
| public static void with(IPython py, Action action) | |||||
| public static void with(IPython py, Action<IPython> action) | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| py.__enter__(); | py.__enter__(); | ||||
| action(); | |||||
| action(py); | |||||
| } | } | ||||
| catch (Exception ex) | catch (Exception ex) | ||||
| { | { | ||||
| @@ -37,7 +37,7 @@ TensorFlow 1.13 RC.</PackageReleaseNotes> | |||||
| <ItemGroup> | <ItemGroup> | ||||
| <PackageReference Include="Google.Protobuf" Version="3.6.1" /> | <PackageReference Include="Google.Protobuf" Version="3.6.1" /> | ||||
| <PackageReference Include="NumSharp" Version="0.6.6" /> | |||||
| <PackageReference Include="NumSharp" Version="0.7.0" /> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| @@ -46,5 +46,37 @@ namespace Tensorflow | |||||
| return op.outputs[0]; | return op.outputs[0]; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Function to convert TensorShape to Tensor. | |||||
| /// </summary> | |||||
| /// <param name="s"></param> | |||||
| /// <param name="dtype"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <param name="as_ref"></param> | |||||
| /// <returns></returns> | |||||
| 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); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -70,5 +70,12 @@ namespace Tensorflow | |||||
| (TF_DataType)Enum.Parse(typeof(TF_DataType), ((int)type - 100).ToString()) : | (TF_DataType)Enum.Parse(typeof(TF_DataType), ((int)type - 100).ToString()) : | ||||
| type; | type; | ||||
| } | } | ||||
| public static DataType as_base_dtype(this DataType type) | |||||
| { | |||||
| return (int)type > 100 ? | |||||
| (DataType)Enum.Parse(typeof(DataType), ((int)type - 100).ToString()) : | |||||
| type; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -18,7 +18,7 @@ namespace Tensorflow | |||||
| var tensor_proto = new tensor_pb2.TensorProto | var tensor_proto = new tensor_pb2.TensorProto | ||||
| { | { | ||||
| Dtype = numpy_dtype.as_datatype_enum(), | 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) | switch (nd.dtype.Name) | ||||
| @@ -94,7 +94,12 @@ namespace Tensorflow | |||||
| return new TensorShape(dims.Select(x => (int)x).ToArray()); | 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); | return new TensorShape(dims); | ||||
| } | } | ||||
| @@ -11,5 +11,10 @@ namespace Tensorflow | |||||
| { | { | ||||
| return constant_op.Constant(nd, name, verify_shape); | 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); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -65,7 +65,7 @@ namespace Tensorflow | |||||
| ops.init_scope(); | ops.init_scope(); | ||||
| var values = init_from_fn ? new List<object>() : new List<object> { initial_value }; | var values = init_from_fn ? new List<object>() : new List<object> { initial_value }; | ||||
| using (var namescope = new ops.name_scope<object>(name, "Variable", values)) | |||||
| using (var namescope = new ops.name_scope(name, "Variable", values)) | |||||
| { | { | ||||
| name = namescope; | name = namescope; | ||||
| @@ -7,7 +7,7 @@ namespace Tensorflow | |||||
| { | { | ||||
| public partial class ops | public partial class ops | ||||
| { | { | ||||
| public class name_scope<T> : IDisposable | |||||
| public class name_scope : IPython | |||||
| { | { | ||||
| public string _name; | public string _name; | ||||
| public string _default_name; | public string _default_name; | ||||
| @@ -16,7 +16,7 @@ namespace Tensorflow | |||||
| public string _name_scope; | public string _name_scope; | ||||
| private object _g_manager; | private object _g_manager; | ||||
| public name_scope(string name, string default_name = "", List<T> values = null) | |||||
| public name_scope(string name, string default_name = "", object values = null) | |||||
| { | { | ||||
| _name = name; | _name = name; | ||||
| _default_name = default_name; | _default_name = default_name; | ||||
| @@ -24,7 +24,7 @@ namespace Tensorflow | |||||
| // _ctx = new Context(); | // _ctx = new Context(); | ||||
| } | } | ||||
| public string __enter__() | |||||
| public void __enter__() | |||||
| { | { | ||||
| if (String.IsNullOrEmpty(_name)) | if (String.IsNullOrEmpty(_name)) | ||||
| { | { | ||||
| @@ -39,8 +39,6 @@ namespace Tensorflow | |||||
| g = get_default_graph(); | g = get_default_graph(); | ||||
| _name_scope = g.name_scope(_name); | _name_scope = g.name_scope(_name); | ||||
| return _name_scope; | |||||
| } | } | ||||
| public void Dispose() | public void Dispose() | ||||
| @@ -51,16 +49,17 @@ namespace Tensorflow | |||||
| g.old_stack = ""; | g.old_stack = ""; | ||||
| } | } | ||||
| public void __exit__() | |||||
| { | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// __enter__() | /// __enter__() | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="ns"></param> | /// <param name="ns"></param> | ||||
| public static implicit operator string(name_scope<T> 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; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -6,7 +6,7 @@ | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <PackageReference Include="NumSharp" Version="0.6.6" /> | |||||
| <PackageReference Include="NumSharp" Version="0.7.0" /> | |||||
| <PackageReference Include="TensorFlow.NET" Version="0.1.0" /> | <PackageReference Include="TensorFlow.NET" Version="0.1.0" /> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| @@ -2,6 +2,7 @@ | |||||
| using NumSharp.Core; | using NumSharp.Core; | ||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | |||||
| using System.Text; | using System.Text; | ||||
| using Tensorflow; | using Tensorflow; | ||||
| @@ -26,6 +27,17 @@ namespace TensorFlowNET.UnitTest | |||||
| tensor = tf.constant("Elephant"); | 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<int>())); | |||||
| tensor = tf.zeros(new Shape(200, 300), TF_DataType.TF_INT32, "x"); | |||||
| } | |||||
| [TestMethod] | [TestMethod] | ||||
| public void NDimConst() | public void NDimConst() | ||||
| { | { | ||||
| @@ -19,7 +19,7 @@ | |||||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> | ||||
| <PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> | <PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> | ||||
| <PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> | <PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> | ||||
| <PackageReference Include="NumSharp" Version="0.6.6" /> | |||||
| <PackageReference Include="NumSharp" Version="0.7.0" /> | |||||
| <PackageReference Include="TensorFlow.NET" Version="0.1.0" /> | <PackageReference Include="TensorFlow.NET" Version="0.1.0" /> | ||||
| </ItemGroup> | </ItemGroup> | ||||