diff --git a/TensorFlow.NET.sln b/TensorFlow.NET.sln index 3ac50b23..019bad25 100644 --- a/TensorFlow.NET.sln +++ b/TensorFlow.NET.sln @@ -9,8 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Core", "src\T EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Examples", "test\TensorFlowNET.Examples\TensorFlowNET.Examples.csproj", "{1FE60088-157C-4140-91AB-E96B915E4BAE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NumSharp.Core", "..\NumSharp\src\NumSharp.Core\NumSharp.Core.csproj", "{EC622ADF-8DAE-474B-B18E-9598A4F91BA2}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,10 +27,6 @@ Global {1FE60088-157C-4140-91AB-E96B915E4BAE}.Debug|Any CPU.Build.0 = Debug|Any CPU {1FE60088-157C-4140-91AB-E96B915E4BAE}.Release|Any CPU.ActiveCfg = Release|Any CPU {1FE60088-157C-4140-91AB-E96B915E4BAE}.Release|Any CPU.Build.0 = Release|Any CPU - {EC622ADF-8DAE-474B-B18E-9598A4F91BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC622ADF-8DAE-474B-B18E-9598A4F91BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC622ADF-8DAE-474B-B18E-9598A4F91BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EC622ADF-8DAE-474B-B18E-9598A4F91BA2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs index 08aa39bb..5f019bb4 100644 --- a/src/TensorFlowNET.Core/APIs/tf.math.cs +++ b/src/TensorFlowNET.Core/APIs/tf.math.cs @@ -15,5 +15,10 @@ namespace Tensorflow { return gen_math_ops.mul(x, y); } + + public static unsafe Tensor multiply(Tensor x, RefVariable y) + { + return gen_math_ops.mul(x, y); + } } } diff --git a/src/TensorFlowNET.Core/Graphs/Graph.cs b/src/TensorFlowNET.Core/Graphs/Graph.cs index 9cae49fc..fcc335fc 100644 --- a/src/TensorFlowNET.Core/Graphs/Graph.cs +++ b/src/TensorFlowNET.Core/Graphs/Graph.cs @@ -24,6 +24,7 @@ namespace Tensorflow private List _unfetchable_ops = new List(); private string _name_stack; + public string _graph_key; public Status Status { get; } public Graph() diff --git a/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs b/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs index 66fa8089..8e19be1c 100644 --- a/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs +++ b/src/TensorFlowNET.Core/Operations/OpDefLibrary.cs @@ -36,24 +36,50 @@ namespace Tensorflow foreach (var input_arg in op_def.InputArg) { var input_name = input_arg.Name; - if (keywords.ContainsKey(input_name)) + switch (keywords[input_name]) { - inputs.Add(keywords[input_name] as Tensor); - } - - if (!String.IsNullOrEmpty(input_arg.TypeAttr)) - { - attrs[input_arg.TypeAttr] = (keywords[input_name] as Tensor).dtype; + case Tensor value: + if (keywords.ContainsKey(input_name)) + { + inputs.Add(value); + } + + if (!String.IsNullOrEmpty(input_arg.TypeAttr)) + { + attrs[input_arg.TypeAttr] = value.dtype; + } + + if (input_arg.IsRef) + { + + } + else + { + input_types.Add(value.dtype); + } + break; + case RefVariable value: + if (keywords.ContainsKey(input_name)) + { + inputs.Add(value._initial_value); + } + + if (!String.IsNullOrEmpty(input_arg.TypeAttr)) + { + attrs[input_arg.TypeAttr] = value._initial_value.dtype; + } + + if (input_arg.IsRef) + { + + } + else + { + input_types.Add(value._initial_value.dtype); + } + break; } - if (input_arg.IsRef) - { - - } - else - { - input_types.Add((keywords[input_name] as Tensor).dtype); - } } // Process remaining attrs diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs index 25aa2d8a..27e555bc 100644 --- a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs @@ -31,6 +31,17 @@ namespace Tensorflow return new Tensor(_op, 0, _op.OutputType(0)); } + public static Tensor mul(Tensor x, RefVariable y) + { + var keywords = new Dictionary(); + keywords.Add("x", x); + keywords.Add("y", y); + + var _op = _op_def_lib._apply_op_helper("Mul", name: "mul", keywords: keywords); + + return new Tensor(_op, 0, _op.OutputType(0)); + } + public static Tensor mat_mul(Tensor a, Tensor b, bool transpose_a = false, bool transpose_b = false) { var keywords = new Dictionary(); diff --git a/src/TensorFlowNET.Core/Sessions/BaseSession.cs b/src/TensorFlowNET.Core/Sessions/BaseSession.cs index 2a49d1a6..f74e3498 100644 --- a/src/TensorFlowNET.Core/Sessions/BaseSession.cs +++ b/src/TensorFlowNET.Core/Sessions/BaseSession.cs @@ -124,25 +124,25 @@ namespace Tensorflow // wired, don't know why we have to start from offset 9. var bytes = tensor.Data(); var output = UTF8Encoding.Default.GetString(bytes, 9, bytes.Length - 9); - result[i] = tensor.NDims == 0 ? output : np.array(output).reshape(ndims); + result[i] = fetchValue(tensor, ndims, output); } break; case TF_DataType.TF_FLOAT: { var output = *(float*)c_api.TF_TensorData(output_values[i]); - result[i] = tensor.NDims == 0 ? output : np.array(output).reshape(ndims); + result[i] = fetchValue(tensor, ndims, output); } break; case TF_DataType.TF_INT16: { var output = *(short*)c_api.TF_TensorData(output_values[i]); - result[i] = tensor.NDims == 0 ? output : np.array(output).reshape(ndims); + result[i] = fetchValue(tensor, ndims, output); } break; case TF_DataType.TF_INT32: { var output = *(int*)c_api.TF_TensorData(output_values[i]); - result[i] = tensor.NDims == 0 ? output : np.array(output).reshape(ndims); + result[i] = fetchValue(tensor, ndims, output); } break; default: @@ -153,6 +153,18 @@ namespace Tensorflow return result; } + private object fetchValue(Tensor tensor, int[] ndims, T output) + { + if (tensor.NDims == 0) + { + return output; + } + else + { + return np.array(output).reshape(ndims); + } + } + /// /// If a tensor handle that is fed to a device incompatible placeholder, /// we move the tensor to the right device, generate a new tensor handle, diff --git a/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj b/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj index bbc7011b..c826bceb 100644 --- a/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj +++ b/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj @@ -36,15 +36,11 @@ Docs: https://tensorflownet.readthedocs.io - + - - - - diff --git a/src/TensorFlowNET.Core/Tensors/RefVariable.cs b/src/TensorFlowNET.Core/Tensors/RefVariable.cs index 083a978d..f65b8e9a 100644 --- a/src/TensorFlowNET.Core/Tensors/RefVariable.cs +++ b/src/TensorFlowNET.Core/Tensors/RefVariable.cs @@ -10,17 +10,19 @@ namespace Tensorflow public Tensor _initial_value; public RefVariable(object initial_value, - TF_DataType trainable, + string name = "", + TF_DataType trainable = TF_DataType.DtInvalid, bool validate_shape = true) : - base(initial_value, trainable, validate_shape) + base(initial_value, name, trainable, validate_shape) { - _init_from_args(initial_value, trainable); + _init_from_args(initial_value, name, trainable); } private void _init_from_args(object initial_value, - TF_DataType trainable) + string name = "", + TF_DataType trainable = TF_DataType.DtInvalid) { - var name = ops.name_scope("", "Variable", initial_value); + name = ops.name_scope("", "Variable", initial_value); _initial_value = ops.convert_to_tensor(initial_value, name: "initial_value"); } } diff --git a/src/TensorFlowNET.Core/Tensors/Variable.cs b/src/TensorFlowNET.Core/Tensors/Variable.cs index 19253ce1..b8031490 100644 --- a/src/TensorFlowNET.Core/Tensors/Variable.cs +++ b/src/TensorFlowNET.Core/Tensors/Variable.cs @@ -16,7 +16,7 @@ namespace Tensorflow /// public class Variable { - public Variable(object initial_value, TF_DataType trainable, bool validate_shape = true) + public Variable(object initial_value, string name = "", TF_DataType trainable = TF_DataType.DtInvalid, bool validate_shape = true) { } diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs index e03f5732..ace8b66c 100644 --- a/src/TensorFlowNET.Core/Tensors/dtypes.cs +++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs @@ -12,6 +12,14 @@ namespace Tensorflow { case TF_DataType.TF_INT32: return typeof(int); + case TF_DataType.TF_INT16: + return typeof(short); + case TF_DataType.TF_FLOAT: + return typeof(float); + case TF_DataType.TF_DOUBLE: + return typeof(double); + case TF_DataType.TF_STRING: + return typeof(string); default: throw new NotImplementedException("as_numpy_datatype failed"); } diff --git a/src/TensorFlowNET.Core/tf.cs b/src/TensorFlowNET.Core/tf.cs index fbdaf470..2ed1e223 100644 --- a/src/TensorFlowNET.Core/tf.cs +++ b/src/TensorFlowNET.Core/tf.cs @@ -11,16 +11,18 @@ namespace Tensorflow public static partial class tf { public static TF_DataType int16 = TF_DataType.TF_INT16; + public static TF_DataType float16 = TF_DataType.TF_HALF; public static TF_DataType float32 = TF_DataType.TF_FLOAT; + public static TF_DataType float64 = TF_DataType.TF_DOUBLE; public static TF_DataType chars = TF_DataType.TF_STRING; public static Context context = new Context(); public static Graph g = new Graph(c_api.TF_NewGraph()); - public static object Variable(T data, TF_DataType dtype = TF_DataType.DtInvalid) + public static RefVariable Variable(T data, string name = "", TF_DataType dtype = TF_DataType.DtInvalid) { - return new RefVariable(data, dtype); + return new RefVariable(data, name, dtype); } public static unsafe Tensor placeholder(TF_DataType dtype, TensorShape shape = null) diff --git a/test/TensorFlowNET.Examples/BasicEagerApi.cs b/test/TensorFlowNET.Examples/BasicEagerApi.cs new file mode 100644 index 00000000..2e164bc4 --- /dev/null +++ b/test/TensorFlowNET.Examples/BasicEagerApi.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Tensorflow; + +namespace TensorFlowNET.Examples +{ + /// + /// Basic introduction to TensorFlow's Eager API. + /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/1_Introduction/basic_eager_api.py + /// + public class BasicEagerApi : IExample + { + private Tensor a, b, c, d; + public void Run() + { + // Set Eager API + Console.WriteLine("Setting Eager mode..."); + tf.enable_eager_execution(); + + // Define constant tensors + Console.WriteLine("Define constant tensors"); + a = tf.constant(2); + Console.WriteLine($"a = {a}"); + b = tf.constant(3); + Console.WriteLine($"b = {b}"); + + // Run the operation without the need for tf.Session + Console.WriteLine("Running operations, without tf.Session"); + c = a + b; + Console.WriteLine($"a + b = {c}"); + d = a * b; + Console.WriteLine($"a * b = {d}"); + + // Full compatibility with Numpy + } + } +} diff --git a/test/TensorFlowNET.Examples/BasicOperations.cs b/test/TensorFlowNET.Examples/BasicOperations.cs index 2b782fc9..8d41b2d4 100644 --- a/test/TensorFlowNET.Examples/BasicOperations.cs +++ b/test/TensorFlowNET.Examples/BasicOperations.cs @@ -19,7 +19,7 @@ namespace TensorFlowNET.Examples // Basic constant operations // The value returned by the constructor represents the output // of the Constant op. - /*var a = tf.constant(2); + var a = tf.constant(2); var b = tf.constant(3); // Launch the default graph. @@ -50,7 +50,7 @@ namespace TensorFlowNET.Examples // Run every operation with variable input Console.WriteLine($"Addition with variables: {sess.run(add, feed_dict)}"); Console.WriteLine($"Multiplication with variables: {sess.run(mul, feed_dict)}"); - }*/ + } // ---------------- // More in details: diff --git a/test/TensorFlowNET.Examples/LinearRegression.cs b/test/TensorFlowNET.Examples/LinearRegression.cs new file mode 100644 index 00000000..7ecf02d1 --- /dev/null +++ b/test/TensorFlowNET.Examples/LinearRegression.cs @@ -0,0 +1,42 @@ +using NumSharp.Core; +using System; +using System.Collections.Generic; +using System.Text; +using Tensorflow; + +namespace TensorFlowNET.Examples +{ + /// + /// A linear regression learning algorithm example using TensorFlow library. + /// https://github.com/aymericdamien/TensorFlow-Examples/blob/master/examples/2_BasicModels/linear_regression.py + /// + public class LinearRegression : IExample + { + private NumPyRandom rng = np.random; + + public void Run() + { + // Parameters + double learning_rate = 0.01; + int training_epochs = 1000; + int display_step = 50; + + // Training Data + var train_X = np.array(3.3, 4.4, 5.5, 6.71, 6.93, 4.168, 9.779, 6.182, 7.59, 2.167, + 7.042, 10.791, 5.313, 7.997, 5.654, 9.27, 3.1); + var train_Y = np.array(1.7, 2.76, 2.09, 3.19, 1.694, 1.573, 3.366, 2.596, 2.53, 1.221, + 2.827, 3.465, 1.65, 2.904, 2.42, 2.94, 1.3); + var n_samples = train_X.shape[0]; + + // tf Graph Input + var X = tf.placeholder(tf.float64); + var Y = tf.placeholder(tf.float64); + + // Set model weights + var W = tf.Variable(rng.randn(), name: "weight"); + var b = tf.Variable(rng.randn(), name: "bias"); + + var aa = tf.multiply(X, W); + } + } +} diff --git a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj index de4a6985..51307a5a 100644 --- a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj +++ b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj @@ -6,11 +6,10 @@ - + - diff --git a/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj b/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj index f227365e..2a864bd5 100644 --- a/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj +++ b/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj @@ -19,11 +19,10 @@ - + - diff --git a/test/TensorFlowNET.UnitTest/VariableTest.cs b/test/TensorFlowNET.UnitTest/VariableTest.cs index 2dbe3816..7b8f1ded 100644 --- a/test/TensorFlowNET.UnitTest/VariableTest.cs +++ b/test/TensorFlowNET.UnitTest/VariableTest.cs @@ -12,7 +12,7 @@ namespace TensorFlowNET.UnitTest [TestMethod] public void StringVar() { - var mammal1 = tf.Variable("Elephant", tf.chars); + var mammal1 = tf.Variable("Elephant", "var1", tf.chars); var mammal2 = tf.Variable("Tiger"); }