From 5b429c797696b0f2815315b83319c52ea9825aca Mon Sep 17 00:00:00 2001 From: Meinrad Recheis Date: Sun, 7 Apr 2019 16:43:04 +0200 Subject: [PATCH 1/3] downgrade to .net core 2.1 --- .../TensorFlowNET.Visualization.csproj | 2 +- test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj | 2 +- test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/TensorFlowNET.Visualization/TensorFlowNET.Visualization.csproj b/src/TensorFlowNET.Visualization/TensorFlowNET.Visualization.csproj index 827932d7..81860dad 100644 --- a/src/TensorFlowNET.Visualization/TensorFlowNET.Visualization.csproj +++ b/src/TensorFlowNET.Visualization/TensorFlowNET.Visualization.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp2.1 InProcess diff --git a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj index 0259fc4e..ba342e5f 100644 --- a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj +++ b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp2.1 false diff --git a/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj b/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj index 04aebf0d..a3dd23ec 100644 --- a/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj +++ b/test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp2.1 false From b6a9cd634f6f4a117872bdf30831272bc5c9ed5c Mon Sep 17 00:00:00 2001 From: Meinrad Recheis Date: Sun, 7 Apr 2019 21:14:07 +0200 Subject: [PATCH 2/3] Added documentation comments from tf source --- .../Graphs/Graph.Control.cs | 7 +++++++ .../Operations/Operation.cs | 21 ++++++++++++++++++- .../Train/GradientDescentOptimizer.cs | 19 ++++++++++++++++- src/TensorFlowNET.Core/ops.py.cs | 21 ++++++++++++++++--- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/TensorFlowNET.Core/Graphs/Graph.Control.cs b/src/TensorFlowNET.Core/Graphs/Graph.Control.cs index a1977968..d6fda591 100644 --- a/src/TensorFlowNET.Core/Graphs/Graph.Control.cs +++ b/src/TensorFlowNET.Core/Graphs/Graph.Control.cs @@ -54,6 +54,13 @@ namespace Tensorflow return ret; } + /// + /// Returns a context manager that specifies control dependencies. + /// + /// Use with the `with` keyword to specify that all operations constructed + /// within the context should have control dependencies on + /// `control_inputs`. + /// public _ControlDependenciesController control_dependencies(ITensorOrOperation[] control_inputs) { if (control_inputs == null) diff --git a/src/TensorFlowNET.Core/Operations/Operation.cs b/src/TensorFlowNET.Core/Operations/Operation.cs index b6952540..de030b70 100644 --- a/src/TensorFlowNET.Core/Operations/Operation.cs +++ b/src/TensorFlowNET.Core/Operations/Operation.cs @@ -7,7 +7,26 @@ using System.Runtime.InteropServices; using System.Text; namespace Tensorflow -{ +{ + + /// + /// Represents a graph node that performs computation on tensors. + /// + /// An `Operation` is a node in a TensorFlow `Graph` that takes zero or + /// more `Tensor` objects as input, and produces zero or more `Tensor` + /// objects as output. Objects of type `Operation` are created by + /// calling an op constructor(such as `tf.matmul`) + /// or `tf.Graph.create_op`. + /// + /// For example `c = tf.matmul(a, b)` creates an `Operation` of type + /// "MatMul" that takes tensors `a` and `b` as input, and produces `c` + /// as output. + /// + /// After the graph has been launched in a session, an `Operation` can + /// be executed by passing it to + /// `tf.Session.run`. + /// `op.run()` is a shortcut for calling `tf.get_default_session().run(op)`. + /// public partial class Operation : ITensorOrOperation { private readonly IntPtr _handle; // _c_op in python diff --git a/src/TensorFlowNET.Core/Train/GradientDescentOptimizer.cs b/src/TensorFlowNET.Core/Train/GradientDescentOptimizer.cs index ecdb22f6..f545d859 100644 --- a/src/TensorFlowNET.Core/Train/GradientDescentOptimizer.cs +++ b/src/TensorFlowNET.Core/Train/GradientDescentOptimizer.cs @@ -4,8 +4,25 @@ using System.Text; namespace Tensorflow.Train { + /// + /// Optimizer that implements the gradient descent algorithm. + /// public class GradientDescentOptimizer : Optimizer - { + { + /// + /// Construct a new gradient descent optimizer. + /// + /// A Tensor or a floating point value. The learning + /// rate to use. + /// If true use locks for update operations. + /// Optional name prefix for the operations created when applying + /// gradients.Defaults to "GradientDescent". + /// + /// When eager execution is enabled, `learning_rate` can be a callable that + /// takes no arguments and returns the actual value to use.This can be useful + /// for changing these values across different invocations of optimizer + /// functions. + /// public GradientDescentOptimizer(float learning_rate, bool use_locking = false, string name = "GradientDescent") : base(learning_rate, use_locking, name) { diff --git a/src/TensorFlowNET.Core/ops.py.cs b/src/TensorFlowNET.Core/ops.py.cs index 43a3c9ba..514530f3 100644 --- a/src/TensorFlowNET.Core/ops.py.cs +++ b/src/TensorFlowNET.Core/ops.py.cs @@ -98,12 +98,27 @@ namespace Tensorflow public static Tensor internal_convert_to_tensor_or_composite(Tensor value, TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool as_ref = false) { return internal_convert_to_tensor(value, dtype: dtype, name: name, as_ref: as_ref); - } - + } + /// /// Wrapper for `Graph.control_dependencies()` using the default graph. + /// + /// See `tf.Graph.control_dependencies` for more details. + + /// When eager execution is enabled, any callable object in the `control_inputs` + /// list will be called. /// - /// + /// + /// A list of `Operation` or `Tensor` objects which + /// must be executed or computed before running the operations + /// defined in the context.Can also be `None` to clear the control + /// dependencies.If eager execution is enabled, any callable object in the + /// `control_inputs` list will be called. + /// + /// + /// A context manager that specifies control dependencies for all + /// operations constructed within the context. + /// public static _ControlDependenciesController control_dependencies(Operation[] control_inputs) { return get_default_graph().control_dependencies(control_inputs); From f079605032397adfdb7cffa0b3e30f2cdafd46fd Mon Sep 17 00:00:00 2001 From: Meinrad Recheis Date: Sun, 7 Apr 2019 21:24:29 +0200 Subject: [PATCH 3/3] Operation: implemented support for Tensors in Operation constructor + Test --- .../Operations/Operation.cs | 7 ++++ .../ControlDependenciesTest.cs | 38 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 test/TensorFlowNET.UnitTest/ControlDependenciesTest.cs diff --git a/src/TensorFlowNET.Core/Operations/Operation.cs b/src/TensorFlowNET.Core/Operations/Operation.cs index de030b70..e4bccea1 100644 --- a/src/TensorFlowNET.Core/Operations/Operation.cs +++ b/src/TensorFlowNET.Core/Operations/Operation.cs @@ -117,6 +117,13 @@ namespace Tensorflow case Operation c1: control_input_ops.Add(c1); break; + case Tensor tensor: + control_input_ops.Add(tensor.op); + break; + // TODO: IndexedSlices don't yet exist, but once they do, this needs to be uncommented + //case IndexedSlices islices: + // control_input_ops.Add(islices.op); + // break; default: throw new NotImplementedException($"Control input must be an Operation, a Tensor, or IndexedSlices: {c}"); } diff --git a/test/TensorFlowNET.UnitTest/ControlDependenciesTest.cs b/test/TensorFlowNET.UnitTest/ControlDependenciesTest.cs new file mode 100644 index 00000000..c2c40337 --- /dev/null +++ b/test/TensorFlowNET.UnitTest/ControlDependenciesTest.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Tensorflow; + +namespace TensorFlowNET.UnitTest +{ + /// + /// tensorflow/python/framework/ops_test.py + /// + [TestClass] + public class ControlDependenciesTest : Python + { + [TestMethod] + public void TestBasic() + { + var graph = tf.Graph().as_default(); + Tensor a=null, b = null, c = null, d = null, e = null; + with(graph, g => + { + a = constant_op.constant(1.0); + b = constant_op.constant(1.0); + with(g.control_dependencies(new ITensorOrOperation[] {a}), x => + { + c = constant_op.constant(1.0); + d = array_ops.identity(b); + e = array_ops.identity(c); + }); + }); + Assert.IsTrue(Enumerable.SequenceEqual(c.op.control_inputs, new[] {a.op})); + Assert.IsTrue(Enumerable.SequenceEqual(d.op.control_inputs, new[] {a.op})); + // e should be dominated by c. + Assert.AreEqual(0, e.op.control_inputs.Length); + } + } +}