From 2ee6513c986afde9b5c5e9de2eae88d2bc87188b Mon Sep 17 00:00:00 2001 From: haiping008 Date: Fri, 15 Mar 2019 15:09:24 -0500 Subject: [PATCH] fix shape issue for array_ops.size_internal --- .../Gradients/nn_grad.py.cs | 19 +++++-- .../Operations/array_ops.py.cs | 54 ++++++++++++------- .../Operations/math_ops.py.cs | 3 +- src/TensorFlowNET.Core/Tensors/dtypes.cs | 5 +- src/TensorFlowNET.Core/Tensors/tensor_util.cs | 6 +++ src/TensorFlowNET.Core/ops.py.cs | 18 +------ 6 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/TensorFlowNET.Core/Gradients/nn_grad.py.cs b/src/TensorFlowNET.Core/Gradients/nn_grad.py.cs index 60255687..9f5e2391 100644 --- a/src/TensorFlowNET.Core/Gradients/nn_grad.py.cs +++ b/src/TensorFlowNET.Core/Gradients/nn_grad.py.cs @@ -83,11 +83,24 @@ namespace Tensorflow.Gradients var ind_shape = array_ops.shape(op.outputs[1]); // int32 is not supported on GPU hence up-casting - var ind_lastdim = array_ops.gather(math_ops.cast( - ind_shape, TF_DataType.TF_INT64), array_ops.size(ind_shape) - 1); + var cast = math_ops.cast(ind_shape, TF_DataType.TF_INT64); + var size = array_ops.size(ind_shape) - 1; + var ind_lastdim = array_ops.gather(cast, size); // Flatten indices to 2D. - var ind_2d = array_ops.reshape(op.outputs[1], array_ops.stack(new object[] { -1, ind_lastdim })); + var stack = array_ops.stack(new object[] { -1L, ind_lastdim }); + var ind_2d = array_ops.reshape(op.outputs[1], stack); + + var in_lastdim = array_ops.gather(math_ops.cast(in_shape, TF_DataType.TF_INT64), + array_ops.size(in_shape) - 1); + var outerdim = array_ops.shape(ind_2d); + + // Compute linear indices(flattened to 1D). + var cast1 = math_ops.cast(outerdim, TF_DataType.TF_INT64); + var range2 = math_ops.range(0L, cast1 * in_lastdim, in_lastdim); + var dim2 = array_ops.expand_dims(range2, -1); + var cast2 = math_ops.cast(dim2, TF_DataType.TF_INT32); + var ind = array_ops.reshape(ind_2d + cast2, new int[] { -1 }); throw new NotImplementedException("nn_grad._TopKGrad"); } diff --git a/src/TensorFlowNET.Core/Operations/array_ops.py.cs b/src/TensorFlowNET.Core/Operations/array_ops.py.cs index 100732b1..39df4c37 100644 --- a/src/TensorFlowNET.Core/Operations/array_ops.py.cs +++ b/src/TensorFlowNET.Core/Operations/array_ops.py.cs @@ -46,6 +46,35 @@ namespace Tensorflow } } + public static Tensor _autopacking_conversion_function(object[] v, TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool as_ref = false) + { + var inferred_dtype = _get_dtype_from_nested_lists(v); + if (dtype == TF_DataType.DtInvalid) + dtype = inferred_dtype; + + return _autopacking_helper(v, dtype, name == null ? "packed" : name); + } + + private static TF_DataType _get_dtype_from_nested_lists(object[] list_or_tuple) + { + TF_DataType dtype = TF_DataType.DtInvalid; + + foreach(var obj in list_or_tuple) + { + switch (obj) + { + case Tensor t: + dtype = t.dtype.as_base_dtype(); + break; + } + + if (dtype != TF_DataType.DtInvalid) + break; + } + + return dtype; + } + public static Tensor _autopacking_helper(object[] list_or_tuple, TF_DataType dtype, string name) { var must_pack = false; @@ -242,32 +271,21 @@ namespace Tensorflow private static Tensor size_internal(Tensor input, string name = null, bool optimize = true, TF_DataType out_type = TF_DataType.TF_INT32) { - return with(ops.name_scope(name, "Size", new Tensor[] { input }), scope => + return with(ops.name_scope(name, "Size", new { input }), scope => { name = scope; - if (!tf.context.executing_eagerly()) + var input_tensor = ops.convert_to_tensor(input); + var input_shape = tensor_util.to_shape(input_tensor.shape); + if (optimize) { - var input_tensor = ops.convert_to_tensor(input); - var input_shape = tensor_util.to_shape(input_tensor.shape); - if (optimize) + if (input_shape.is_fully_defined()) { - if (input_shape.is_fully_defined()) - { - var nd = np.array(input_tensor.shape, out_type.as_numpy_datatype()); - return constant_op.constant(nd, name: name); - } + return constant_op.constant(input_shape.Size, dtype: out_type, name: name); } - - return gen_array_ops.size(input, name: name, out_type: out_type); - } - else - { - // result = gen_array_ops.shape(); - throw new NotImplementedException("array_ops.size_internal"); } - return null; + return gen_array_ops.size(input, name: name, out_type: out_type); }); } diff --git a/src/TensorFlowNET.Core/Operations/math_ops.py.cs b/src/TensorFlowNET.Core/Operations/math_ops.py.cs index f73164d8..4741214e 100644 --- a/src/TensorFlowNET.Core/Operations/math_ops.py.cs +++ b/src/TensorFlowNET.Core/Operations/math_ops.py.cs @@ -18,6 +18,7 @@ namespace Tensorflow return with(ops.name_scope(name, "Cast", new { x }), scope => { + name = scope; x = ops.convert_to_tensor(x, name: "x"); if (x.dtype.as_base_dtype() != base_type) x = gen_math_ops.cast(x, base_type, name: name); @@ -263,7 +264,7 @@ namespace Tensorflow if (delta == null) delta = 1; - return with(ops.name_scope(name, "Range", new object[] { start, limit, delta }), scope => + return with(ops.name_scope(name, "Range", new { start, limit, delta }), scope => { name = scope; var start1 = ops.convert_to_tensor(start, name: "start"); diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs index 005b5df9..ebce4e21 100644 --- a/src/TensorFlowNET.Core/Tensors/dtypes.cs +++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs @@ -34,6 +34,9 @@ namespace Tensorflow case "Int32": dtype = TF_DataType.TF_INT32; break; + case "Int64": + dtype = TF_DataType.TF_INT64; + break; case "Single": dtype = TF_DataType.TF_FLOAT; break; @@ -47,7 +50,7 @@ namespace Tensorflow dtype = TF_DataType.TF_STRING; break; default: - throw new Exception("Not Implemented"); + throw new Exception($"{type.Name} Not Implemented in as_dtype"); } return dtype; diff --git a/src/TensorFlowNET.Core/Tensors/tensor_util.cs b/src/TensorFlowNET.Core/Tensors/tensor_util.cs index a3eabfaa..bdfaddf7 100644 --- a/src/TensorFlowNET.Core/Tensors/tensor_util.cs +++ b/src/TensorFlowNET.Core/Tensors/tensor_util.cs @@ -111,6 +111,9 @@ namespace Tensorflow case int intVal: nparray = intVal; break; + case long intVal: + nparray = intVal; + break; case int[] intVals: nparray = np.array(intVals); break; @@ -231,6 +234,9 @@ namespace Tensorflow case "Int32": tensor_proto.IntVal.AddRange(proto_values.Data()); break; + case "Int64": + tensor_proto.Int64Val.AddRange(proto_values.Data()); + break; case "Single": tensor_proto.FloatVal.AddRange(proto_values.Data()); break; diff --git a/src/TensorFlowNET.Core/ops.py.cs b/src/TensorFlowNET.Core/ops.py.cs index 3708c540..9118926f 100644 --- a/src/TensorFlowNET.Core/ops.py.cs +++ b/src/TensorFlowNET.Core/ops.py.cs @@ -410,26 +410,12 @@ namespace Tensorflow return tensor; case Tensor[] tensors: return array_ops._autopacking_helper(tensors, dtype, name); - case string str: - return constant_op.constant(str, dtype: dtype, name: name); - case string[] strArray: - return constant_op.constant(strArray, dtype: dtype, name: name); - case int intVal: - return constant_op.constant(intVal, dtype: dtype, name: name); - case int[] intArray: - return constant_op.constant(intArray, dtype: dtype, name: name); - case float floatVal: - return constant_op.constant(floatVal, dtype: dtype, name: name); - case float[] floatArray: - return constant_op.constant(floatArray, dtype: dtype, name: name); - case double doubleVal: - return constant_op.constant(doubleVal, dtype: dtype, name: name); case RefVariable varVal: return varVal._TensorConversionFunction(as_ref: as_ref); case object[] objects: - return array_ops._autopacking_helper(objects, dtype: dtype, name: name); + return array_ops._autopacking_conversion_function(objects, dtype: dtype, name: name); default: - throw new NotImplementedException($"internal_convert_to_tensor: Can't convert {value.GetType().Name} to Tensor"); + return constant_op.constant(value, dtype: dtype, name: name); } }