From 0c6f8cd9e4ecbdb7d6dd2fda162e2d032f0133e4 Mon Sep 17 00:00:00 2001 From: Oceania2018 Date: Wed, 6 Feb 2019 05:02:49 -0600 Subject: [PATCH] fix internal_convert_to_tensor shape exception for scalar value. --- docs/source/Variable.md | 17 ++++++++++ .../Operations/OpDefLibrary.cs | 34 ++++++++++--------- .../Operations/math_ops.py.cs | 17 ++++++++-- src/TensorFlowNET.Core/ops.py.cs | 6 +++- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/docs/source/Variable.md b/docs/source/Variable.md index f98fbaf7..48eaa9ae 100644 --- a/docs/source/Variable.md +++ b/docs/source/Variable.md @@ -1,2 +1,19 @@ # Chapter. Variable +The variables in TensorFlow are mainly used to represent variable parameter values in the machine learning model. Variables can be initialized by the `tf.Variable` function. During the graph computation the variables are modified by other operations. Variables exist in the session, as long as they are in the same session, other computing nodes on the network can access the same variable value. Variables use lazy loading and will only request memory space when they are used. + +TensorFlow中变量主要用来表示机器学习模型中的可变参数值,变量通过可以通过`tf.Variable` 类进行初始化。在图运行过程中,通过各种操作对变量进行修改。变量存在于会话当中,只要是在同一个会话里,网络上的其它计算结节都可以访问到相同的变量值。变量采用延迟加载的方式,只有使用的时候才会申请内存空间。 + +```csharp +var x = tf.Variable(10, name: "x"); +using (var session = tf.Session()) +{ + session.run(x.initializer); + var result = session.run(x); + Console.Write(result); // should be 10 +} +``` + +The above code first creates a variable operation, initializes the variable, then runs the session, and finally gets the result. This code is very simple, but it shows the complete process how TensorFlow operates on variables. When creating a variable, you pass a `tensor` as the initial value to the function `Variable()`. TensorFlow provides a series of operators to initialize the tensor, the initial value is a constant or a random value. + +以上代码先创建变量操作,初始化变量,再运行会话,最后得到结果。这段代码非常简单,但是它体现了整个TensorFlow对变量操作的完整流程。当创建一个变量时,你将一个`张量`作为初始值传入函数`Variable()`。TensorFlow提供了一系列操作符来初始化张量,初始值是常量或是随机值。 \ No newline at end of file diff --git a/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs b/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs index e11a0e5f..60d0319a 100644 --- a/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs +++ b/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs @@ -44,14 +44,13 @@ namespace Tensorflow var input_types = new List(); var base_types = new List(); - Operation op = null; - Python.with(new ops.name_scope(name), scope => + return Python.with(new ops.name_scope(name), scope => { // Perform input type inference foreach (var input_arg in op_def.InputArg) { - var input_name = input_arg.Name; - var values = keywords[input_name]; + var input_arg_name = input_arg.Name; + var values = keywords[input_arg_name]; // Goals: // * Convert values to Tensors if it contains constants. // * Verify that values is a list if that matches the input_arg's @@ -64,13 +63,13 @@ namespace Tensorflow // * If the input_arg has an explicit type, make sure the input // conforms. + DataType dtype = DataType.DtInvalid; + DataType default_dtype = DataType.DtInvalid; + if (_IsListParameter(input_arg)) { - DataType dtype = DataType.DtInvalid; - DataType default_dtype = DataType.DtInvalid; - if (!_IsListValue(values)) - throw new TypeError($"Expected list for '{input_name}' argument to '{op_type_name}' Op, not {values}."); + throw new TypeError($"Expected list for '{input_arg_name}' argument to '{op_type_name}' Op, not {values}."); if(input_arg.Type != DataType.DtInvalid) { dtype = input_arg.Type; @@ -87,19 +86,22 @@ namespace Tensorflow } else { - if (keywords[input_name] is Tensor) + if (default_type_attr_map.ContainsKey(input_arg.TypeAttr)) + default_dtype = (DataType)default_type_attr_map[input_arg.TypeAttr]; + + if (keywords[input_arg_name] is Tensor) { } else { - keywords[input_name] = ops.internal_convert_to_tensor(values, name: input_name); + keywords[input_arg_name] = ops.internal_convert_to_tensor(values, name: input_arg_name); } if (!String.IsNullOrEmpty(input_arg.TypeAttr)) { - attrs[input_arg.TypeAttr] = (keywords[input_name] as Tensor).dtype; + attrs[input_arg.TypeAttr] = (keywords[input_arg_name] as Tensor).dtype; } - values = new Tensor[] { keywords[input_name] as Tensor }; + values = new Tensor[] { keywords[input_arg_name] as Tensor }; } inputs.AddRange(values as Tensor[]); @@ -122,7 +124,7 @@ namespace Tensorflow { var key = attr_def.Name; if (!attrs.ContainsKey(key)) - Console.WriteLine($"{key} not found in attr_def."); + Console.WriteLine($"_apply_op_helper: key '{key}' is not found in '{op_def.Name}' operation's attr_def."); var value = attrs[key]; var attr_value = new AttrValue(); @@ -165,14 +167,14 @@ namespace Tensorflow } // Add Op to graph - op = g.create_op(op_type_name, inputs, output_types.ToArray(), + var op = g.create_op(op_type_name, inputs, output_types.ToArray(), name: scope, input_types: input_types.ToArray(), attrs: attr_protos, op_def: op_def); - }); - return op; + return op; + }); } public DataType _MakeType(TF_DataType v, AttrDef attr_def) diff --git a/src/TensorFlowNET.Core/Operations/math_ops.py.cs b/src/TensorFlowNET.Core/Operations/math_ops.py.cs index 143a3dc8..8818fa57 100644 --- a/src/TensorFlowNET.Core/Operations/math_ops.py.cs +++ b/src/TensorFlowNET.Core/Operations/math_ops.py.cs @@ -20,8 +20,10 @@ namespace Tensorflow var input_rank = array_ops.size(input_shape); axes = (axes + input_rank) % input_rank; var axes_shape = array_ops.shape(axes); - var a1 = new Tensor[] { input_rank, axes }; - var a2 = new Tensor[] { input_shape, gen_array_ops.fill(axes_shape, 1) }; + var rng = math_ops.range(input_rank); + var a1 = new Tensor[] { rng, axes }; + var fill = gen_array_ops.fill(axes_shape, 1); + var a2 = new Tensor[] { input_shape, fill }; return gen_data_flow_ops.dynamic_stitch(a1, a2); } @@ -80,8 +82,17 @@ namespace Tensorflow } } - public static Tensor range(object start, Tensor limit = null, object delta = null, TF_DataType dtype = TF_DataType.DtInvalid, string name = "range" ) + public static Tensor range(object start, object limit = null, object delta = null, TF_DataType dtype = TF_DataType.DtInvalid, string name = "range" ) { + if(limit == null) + { + limit = start; + start = 0; + } + + if (delta == null) + delta = 1; + return Python.with(new ops.name_scope(name, "Range", new object[] { start, limit, delta }), scope => { name = scope; diff --git a/src/TensorFlowNET.Core/ops.py.cs b/src/TensorFlowNET.Core/ops.py.cs index f72eb3bc..22651f75 100644 --- a/src/TensorFlowNET.Core/ops.py.cs +++ b/src/TensorFlowNET.Core/ops.py.cs @@ -333,8 +333,12 @@ namespace Tensorflow { case "Tensor": return value as Tensor; + case "Int32": + return constant_op.constant(Convert.ToInt32(value), name); + case "Double": + return constant_op.constant(Convert.ToDouble(value), name); default: - return constant_op.constant(np.array(value), name); + throw new NotImplementedException($"internal_convert_to_tensor: Can't convert {typeof(T).Name} to Tensor"); } } }