Browse Source

fix internal_convert_to_tensor shape exception for scalar value.

tags/v0.8.0
Oceania2018 6 years ago
parent
commit
0c6f8cd9e4
4 changed files with 54 additions and 20 deletions
  1. +17
    -0
      docs/source/Variable.md
  2. +18
    -16
      src/TensorFlowNET.Core/Operations/OpDefLibrary.cs
  3. +14
    -3
      src/TensorFlowNET.Core/Operations/math_ops.py.cs
  4. +5
    -1
      src/TensorFlowNET.Core/ops.py.cs

+ 17
- 0
docs/source/Variable.md View File

@@ -1,2 +1,19 @@
# Chapter. Variable # 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提供了一系列操作符来初始化张量,初始值是常量或是随机值。

+ 18
- 16
src/TensorFlowNET.Core/Operations/OpDefLibrary.cs View File

@@ -44,14 +44,13 @@ namespace Tensorflow
var input_types = new List<TF_DataType>(); var input_types = new List<TF_DataType>();
var base_types = new List<TF_DataType>(); var base_types = new List<TF_DataType>();


Operation op = null;
Python.with<ops.name_scope>(new ops.name_scope(name), scope =>
return Python.with<ops.name_scope, Operation>(new ops.name_scope(name), scope =>
{ {
// Perform input type inference // Perform input type inference
foreach (var input_arg in op_def.InputArg) 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: // Goals:
// * Convert values to Tensors if it contains constants. // * Convert values to Tensors if it contains constants.
// * Verify that values is a list if that matches the input_arg's // * 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 // * If the input_arg has an explicit type, make sure the input
// conforms. // conforms.


DataType dtype = DataType.DtInvalid;
DataType default_dtype = DataType.DtInvalid;

if (_IsListParameter(input_arg)) if (_IsListParameter(input_arg))
{ {
DataType dtype = DataType.DtInvalid;
DataType default_dtype = DataType.DtInvalid;

if (!_IsListValue(values)) 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) if(input_arg.Type != DataType.DtInvalid)
{ {
dtype = input_arg.Type; dtype = input_arg.Type;
@@ -87,19 +86,22 @@ namespace Tensorflow
} }
else 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 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)) 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[]); inputs.AddRange(values as Tensor[]);
@@ -122,7 +124,7 @@ namespace Tensorflow
{ {
var key = attr_def.Name; var key = attr_def.Name;
if (!attrs.ContainsKey(key)) 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 value = attrs[key];
var attr_value = new AttrValue(); var attr_value = new AttrValue();


@@ -165,14 +167,14 @@ namespace Tensorflow
} }


// Add Op to graph // 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, name: scope,
input_types: input_types.ToArray(), input_types: input_types.ToArray(),
attrs: attr_protos, attrs: attr_protos,
op_def: op_def); op_def: op_def);
});


return op;
return op;
});
} }


public DataType _MakeType(TF_DataType v, AttrDef attr_def) public DataType _MakeType(TF_DataType v, AttrDef attr_def)


+ 14
- 3
src/TensorFlowNET.Core/Operations/math_ops.py.cs View File

@@ -20,8 +20,10 @@ namespace Tensorflow
var input_rank = array_ops.size(input_shape); var input_rank = array_ops.size(input_shape);
axes = (axes + input_rank) % input_rank; axes = (axes + input_rank) % input_rank;
var axes_shape = array_ops.shape(axes); 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); 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<ops.name_scope, Tensor>(new ops.name_scope(name, "Range", new object[] { start, limit, delta }), scope => return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "Range", new object[] { start, limit, delta }), scope =>
{ {
name = scope; name = scope;


+ 5
- 1
src/TensorFlowNET.Core/ops.py.cs View File

@@ -333,8 +333,12 @@ namespace Tensorflow
{ {
case "Tensor": case "Tensor":
return value as 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: default:
return constant_op.constant(np.array(value), name);
throw new NotImplementedException($"internal_convert_to_tensor: Can't convert {typeof(T).Name} to Tensor");
} }
} }
} }


Loading…
Cancel
Save