diff --git a/src/TensorFlowNET.Core/Binding.Util.cs b/src/TensorFlowNET.Core/Binding.Util.cs index 9f51ce2d..3340e512 100644 --- a/src/TensorFlowNET.Core/Binding.Util.cs +++ b/src/TensorFlowNET.Core/Binding.Util.cs @@ -111,7 +111,7 @@ namespace Tensorflow return Enumerable.Range(start, end - start); } - public static T New() where T : IObjectLife, new() + public static T New() where T : ITensorFlowObject, new() { var instance = new T(); instance.__init__(); @@ -120,7 +120,7 @@ namespace Tensorflow [DebuggerStepThrough] [DebuggerNonUserCode()] // with "Just My Code" enabled this lets the debugger break at the origin of the exception - public static void tf_with(IObjectLife py, Action action) + public static void tf_with(ITensorFlowObject py, Action action) { try { @@ -136,7 +136,7 @@ namespace Tensorflow [DebuggerStepThrough] [DebuggerNonUserCode()] // with "Just My Code" enabled this lets the debugger break at the origin of the exception - public static void tf_with(T py, Action action) where T : IObjectLife + public static void tf_with(T py, Action action) where T : ITensorFlowObject { try { @@ -152,7 +152,7 @@ namespace Tensorflow [DebuggerStepThrough] [DebuggerNonUserCode()] // with "Just My Code" enabled this lets the debugger break at the origin of the exception - public static TOut tf_with(TIn py, Func action) where TIn : IObjectLife + public static TOut tf_with(TIn py, Func action) where TIn : ITensorFlowObject { try { diff --git a/src/TensorFlowNET.Core/Eager/Context.cs b/src/TensorFlowNET.Core/Eager/Context.cs index 700e1236..b2909327 100644 --- a/src/TensorFlowNET.Core/Eager/Context.cs +++ b/src/TensorFlowNET.Core/Eager/Context.cs @@ -8,6 +8,7 @@ namespace Tensorflow.Eager public const int EAGER_MODE = 1; public int default_execution_mode; + public string device_name = ""; public Context(ContextOptions opts, Status status) { @@ -22,7 +23,7 @@ namespace Tensorflow.Eager => c_api.TFE_DeleteContext(_handle); - public bool executing_eagerly() => false; + public bool executing_eagerly() => true; public static implicit operator IntPtr(Context ctx) => ctx._handle; diff --git a/src/TensorFlowNET.Core/Eager/EagerTensor.cs b/src/TensorFlowNET.Core/Eager/EagerTensor.cs new file mode 100644 index 00000000..636e9520 --- /dev/null +++ b/src/TensorFlowNET.Core/Eager/EagerTensor.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tensorflow.Eager +{ + public class EagerTensor : Tensor + { + public EagerTensor(IntPtr handle) : base(handle) + { + } + + public EagerTensor(string value, string device_name) : base(value) + { + } + + public override string ToString() + { + switch (rank) + { + case -1: + return $"tf.Tensor: shape=, dtype={dtype.as_numpy_name()}, numpy={GetFormattedString()}"; + case 0: + return $"tf.Tensor: shape=(), dtype={dtype.as_numpy_name()}, numpy={GetFormattedString()}"; + default: + return $"tf.Tensor: shape=({string.Join(",", shape)}), dtype={dtype.as_numpy_name()}, numpy={GetFormattedString()}"; + } + } + + private string GetFormattedString() + { + var nd = numpy(); + switch (dtype) + { + case TF_DataType.TF_STRING: + return $"b'{(string)nd}'"; + default: + return nd.ToString(); + } + } + } +} diff --git a/src/TensorFlowNET.Core/Graphs/_ControlDependenciesController.cs b/src/TensorFlowNET.Core/Graphs/_ControlDependenciesController.cs index 3472db29..e3deb7f8 100644 --- a/src/TensorFlowNET.Core/Graphs/_ControlDependenciesController.cs +++ b/src/TensorFlowNET.Core/Graphs/_ControlDependenciesController.cs @@ -23,7 +23,7 @@ namespace Tensorflow /// /// Context manager for `control_dependencies()` /// - public class _ControlDependenciesController : IObjectLife + public class _ControlDependenciesController : ITensorFlowObject { private Graph _graph; private List _control_inputs_val; diff --git a/src/TensorFlowNET.Core/Interfaces/IObjectLife.cs b/src/TensorFlowNET.Core/Interfaces/ITensorFlowObject.cs similarity index 95% rename from src/TensorFlowNET.Core/Interfaces/IObjectLife.cs rename to src/TensorFlowNET.Core/Interfaces/ITensorFlowObject.cs index a3978cc2..3b4a87ec 100644 --- a/src/TensorFlowNET.Core/Interfaces/IObjectLife.cs +++ b/src/TensorFlowNET.Core/Interfaces/ITensorFlowObject.cs @@ -18,7 +18,7 @@ using System; namespace Tensorflow { - public interface IObjectLife : IDisposable + public interface ITensorFlowObject : IDisposable { /// /// Called when the instance is created. diff --git a/src/TensorFlowNET.Core/Keras/Engine/Sequential.cs b/src/TensorFlowNET.Core/Keras/Engine/Sequential.cs index 9aa6d619..819c62e7 100644 --- a/src/TensorFlowNET.Core/Keras/Engine/Sequential.cs +++ b/src/TensorFlowNET.Core/Keras/Engine/Sequential.cs @@ -18,7 +18,7 @@ using Tensorflow.Keras.Layers; namespace Tensorflow.Keras.Engine { - public class Sequential : Model, IObjectLife + public class Sequential : Model, ITensorFlowObject { bool _is_graph_network; Tensor[] outputs; diff --git a/src/TensorFlowNET.Core/Operations/ControlFlows/ControlFlowContext.cs b/src/TensorFlowNET.Core/Operations/ControlFlows/ControlFlowContext.cs index 0d2665e1..1ea1b801 100644 --- a/src/TensorFlowNET.Core/Operations/ControlFlows/ControlFlowContext.cs +++ b/src/TensorFlowNET.Core/Operations/ControlFlows/ControlFlowContext.cs @@ -41,7 +41,7 @@ namespace Tensorflow.Operations /// 4. A ControlFlowContext has _context_stack. /// Pushed and popped by ctxt.Enter() and ctxt.Exit() /// - public abstract class ControlFlowContext : IObjectLife + public abstract class ControlFlowContext : ITensorFlowObject { /// /// The predicate tensor in this branch diff --git a/src/TensorFlowNET.Core/Sessions/Session.cs b/src/TensorFlowNET.Core/Sessions/Session.cs index c60a49c1..c18df439 100644 --- a/src/TensorFlowNET.Core/Sessions/Session.cs +++ b/src/TensorFlowNET.Core/Sessions/Session.cs @@ -22,7 +22,7 @@ using static Tensorflow.Binding; namespace Tensorflow { - public class Session : BaseSession, IObjectLife + public class Session : BaseSession, ITensorFlowObject { public Session(string target = "", Graph g = null) : base(target, g, null) { } diff --git a/src/TensorFlowNET.Core/TensorFlow.Binding.csproj b/src/TensorFlowNET.Core/TensorFlow.Binding.csproj index 97fd03de..1518bccb 100644 --- a/src/TensorFlowNET.Core/TensorFlow.Binding.csproj +++ b/src/TensorFlowNET.Core/TensorFlow.Binding.csproj @@ -6,6 +6,7 @@ Tensorflow 1.14.1 0.20.0 + 8.0 Haiping Chen, Meinrad Recheis, Eli Belash SciSharp STACK true @@ -25,7 +26,6 @@ https://tensorflownet.readthedocs.io 3: Import Protobuf.Text 4: Support YOLOv3 object detection 5: Add implicitation for Operation to RefVariable - 7.3 0.20.0.0 LICENSE true diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs index 39c272b4..243fe9f3 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs @@ -455,14 +455,14 @@ namespace Tensorflow { var status = new Status(); var buffer = Encoding.UTF8.GetBytes(str); - var size = c_api.TF_StringEncodedSize((UIntPtr) buffer.Length); - var handle = TF_AllocateTensor(TF_DataType.TF_STRING, IntPtr.Zero, 0, (UIntPtr) ((ulong) size + 8)); + var size = c_api.TF_StringEncodedSize((UIntPtr)buffer.Length); + var handle = TF_AllocateTensor(TF_DataType.TF_STRING, IntPtr.Zero, 0, (UIntPtr)((ulong)size + 8)); AllocationType = AllocationType.Tensorflow; IntPtr tensor = c_api.TF_TensorData(handle); Marshal.WriteInt64(tensor, 0); fixed (byte* src = buffer) - c_api.TF_StringEncode(src, (UIntPtr) buffer.Length, (sbyte*) (tensor + sizeof(Int64)), size, status); + c_api.TF_StringEncode(src, (UIntPtr)buffer.Length, (sbyte*)(tensor + sizeof(long)), size, status); _handle = handle; status.Check(true); } diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.cs b/src/TensorFlowNET.Core/Tensors/Tensor.cs index 2ec02232..3a681499 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.cs @@ -79,7 +79,7 @@ namespace Tensorflow /// /// The string name of this tensor. /// - public string name => $"{(op == null ? "" : $"{op.name}:{_value_index}")}"; + public string name => $"{(op == null ? "" : $"{op.name}:{_value_index}")}"; /// /// The index of this tensor in the outputs of its Operation. @@ -381,13 +381,21 @@ namespace Tensorflow } /// - /// Copies the memory of current buffer onto newly allocated array. + /// Copy of the contents of this Tensor into a NumPy array or scalar. /// - /// - [Obsolete("Please use set_shape(TensorShape shape) instead.", false)] - public byte[] Data() + /// + /// A NumPy array of the same shape and dtype or a NumPy scalar, if this + /// Tensor has rank 0. + /// + public NDArray numpy() { - return BufferToArray(); + switch (dtype) + { + case TF_DataType.TF_STRING: + return StringData()[0]; + default: + return BufferToArray(); + } } /// @@ -399,7 +407,7 @@ namespace Tensorflow unsafe { // ReSharper disable once LocalVariableHidesMember - var bytesize = (long) this.bytesize; + var bytesize = (long)this.bytesize; var data = new byte[bytesize]; fixed (byte* dst = data) System.Buffer.MemoryCopy(buffer.ToPointer(), dst, bytesize, bytesize); @@ -427,7 +435,7 @@ namespace Tensorflow var buffer = new byte[size][]; var src = c_api.TF_TensorData(_handle); - var srcLen = (IntPtr) (src.ToInt64() + (long) bytesize); + var srcLen = (IntPtr)(src.ToInt64() + (long)bytesize); src += (int) (size * 8); for (int i = 0; i < buffer.Length; i++) { @@ -435,7 +443,7 @@ namespace Tensorflow { IntPtr dst = IntPtr.Zero; UIntPtr dstLen = UIntPtr.Zero; - var read = c_api.TF_StringDecode((byte*) src, (UIntPtr) (srcLen.ToInt64() - src.ToInt64()), (byte**) &dst, &dstLen, status); + var read = c_api.TF_StringDecode((byte*)src, (UIntPtr)(srcLen.ToInt64() - src.ToInt64()), (byte**)&dst, &dstLen, status); status.Check(true); buffer[i] = new byte[(int) dstLen]; Marshal.Copy(dst, buffer[i], 0, buffer[i].Length); diff --git a/src/TensorFlowNET.Core/Tensors/constant_op.cs b/src/TensorFlowNET.Core/Tensors/constant_op.cs index 92eda9ba..961b36ac 100644 --- a/src/TensorFlowNET.Core/Tensors/constant_op.cs +++ b/src/TensorFlowNET.Core/Tensors/constant_op.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using Tensorflow.Eager; using static Tensorflow.Binding; namespace Tensorflow @@ -39,11 +40,18 @@ namespace Tensorflow return _constant_impl(value, dtype, shape, name, verify_shape: false, allow_broadcast: true); } - public static Tensor _constant_impl(object value, TF_DataType dtype, int[] shape, string name, bool verify_shape, bool allow_broadcast) + public static Tensor _constant_impl(object value, + TF_DataType dtype, + int[] shape, + string name, + bool verify_shape, + bool allow_broadcast) { if (tf.context.executing_eagerly()) { - + var t = convert_to_eager_tensor(value, tf.context, dtype: dtype); + if (shape == null) + return t; } Graph g = ops.get_default_graph(); @@ -72,6 +80,17 @@ namespace Tensorflow return op.outputs[0]; } + private static EagerTensor convert_to_eager_tensor(object value, Context ctx, TF_DataType dtype = TF_DataType.DtInvalid) + { + switch (value) + { + case string str: + return new EagerTensor(str, ctx.device_name); + default: + throw new NotImplementedException($"convert_to_eager_tensor {value.GetType()}"); + } + } + /// /// Function to convert TensorShape to Tensor. /// diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs index a54d0448..65c8fb70 100644 --- a/src/TensorFlowNET.Core/Tensors/dtypes.cs +++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs @@ -197,6 +197,13 @@ namespace Tensorflow return (int)type; } + public static string as_numpy_name(this TF_DataType type) + => type switch + { + TF_DataType.TF_STRING => "string", + _ => type.ToString() + }; + public static Type as_numpy_dtype(this DataType type) { return type.as_tf_dtype().as_numpy_dtype(); diff --git a/src/TensorFlowNET.Core/Tensors/tf.constant.cs b/src/TensorFlowNET.Core/Tensors/tf.constant.cs index a6516740..8ee1a531 100644 --- a/src/TensorFlowNET.Core/Tensors/tf.constant.cs +++ b/src/TensorFlowNET.Core/Tensors/tf.constant.cs @@ -20,35 +20,44 @@ namespace Tensorflow { public partial class tensorflow { - // public static Tensor constant(NDArray nd, string name = "Const") => constant_op.constant(nd, name: name); - + /// + /// + /// + /// + /// + /// + /// + /// public Tensor constant(object value, TF_DataType dtype = TF_DataType.DtInvalid, - int[] shape = null, - string name = "Const", - bool verify_shape = false) => constant_op._constant_impl(value, - dtype, - shape, - name, - verify_shape: verify_shape, - allow_broadcast: false); - - public Tensor constant(string value, - string name = "Const") => constant_op._constant_impl(value, - @string, - new int[] { 1 }, - name, - verify_shape: false, - allow_broadcast: false); - - public Tensor constant(float value, - int shape, - string name = "Const") => constant_op._constant_impl(value, - float32, - new int[] { shape }, - name, - verify_shape: false, - allow_broadcast: false); + TensorShape shape = null, + string name = "Const") + { + switch (value) + { + case string str: + return constant_op._constant_impl(str, + @string, + null, + name, + verify_shape: false, + allow_broadcast: true); + case float val: + return constant_op._constant_impl(value, + float32, + new int[] { (int)shape }, + name, + verify_shape: false, + allow_broadcast: true); + default: + return constant_op._constant_impl(value, + dtype, + shape, + name, + verify_shape: false, + allow_broadcast: true); + } + } public Tensor zeros(TensorShape shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = null) => array_ops.zeros(shape, dtype, name); diff --git a/src/TensorFlowNET.Core/Variables/PureVariableScope.cs b/src/TensorFlowNET.Core/Variables/PureVariableScope.cs index 2326d9e3..dd09d8a7 100644 --- a/src/TensorFlowNET.Core/Variables/PureVariableScope.cs +++ b/src/TensorFlowNET.Core/Variables/PureVariableScope.cs @@ -19,7 +19,7 @@ using System.Linq; namespace Tensorflow { - public class PureVariableScope : IObjectLife + public class PureVariableScope : ITensorFlowObject { private string _name; private VariableScope _scope; diff --git a/src/TensorFlowNET.Core/Variables/variable_scope.py.cs b/src/TensorFlowNET.Core/Variables/variable_scope.py.cs index 41e8e429..2c46ef38 100644 --- a/src/TensorFlowNET.Core/Variables/variable_scope.py.cs +++ b/src/TensorFlowNET.Core/Variables/variable_scope.py.cs @@ -23,7 +23,7 @@ namespace Tensorflow /// /// A context manager for defining ops that creates variables (layers). /// - public class variable_scope : IObjectLife + public class variable_scope : ITensorFlowObject { public static string _VARSTORE_KEY = "__variable_store"; public static string _VARSCOPESTORE_KEY = "__varscope"; diff --git a/src/TensorFlowNET.Core/ops._DefaultStack.cs b/src/TensorFlowNET.Core/ops._DefaultStack.cs index 3a6932a4..a9250d2b 100644 --- a/src/TensorFlowNET.Core/ops._DefaultStack.cs +++ b/src/TensorFlowNET.Core/ops._DefaultStack.cs @@ -23,7 +23,7 @@ namespace Tensorflow { _DefaultStack _default_session_stack = new _DefaultStack(); - public class _DefaultStack : IObjectLife + public class _DefaultStack : ITensorFlowObject { Stack stack; bool _enforce_nesting = true; diff --git a/src/TensorFlowNET.Core/ops.cs b/src/TensorFlowNET.Core/ops.cs index 633a9bf7..9ac0a042 100644 --- a/src/TensorFlowNET.Core/ops.cs +++ b/src/TensorFlowNET.Core/ops.cs @@ -254,7 +254,7 @@ namespace Tensorflow }); } - public static IObjectLife init_scope2() + public static ITensorFlowObject init_scope2() { // Retrieve the active name scope: entering an `init_scope` preserves // the name scope of the current context. diff --git a/src/TensorFlowNET.Core/ops.name_scope.cs b/src/TensorFlowNET.Core/ops.name_scope.cs index 55e9cf61..32befbcd 100644 --- a/src/TensorFlowNET.Core/ops.name_scope.cs +++ b/src/TensorFlowNET.Core/ops.name_scope.cs @@ -27,7 +27,7 @@ namespace Tensorflow /// /// Returns a context manager that creates hierarchical names for operations. /// - public class NameScope : IObjectLife + public class NameScope : ITensorFlowObject { public string _name; public string _default_name; diff --git a/src/TensorFlowNET.Core/tensorflow.cs b/src/TensorFlowNET.Core/tensorflow.cs index a42297b2..7f0d30fd 100644 --- a/src/TensorFlowNET.Core/tensorflow.cs +++ b/src/TensorFlowNET.Core/tensorflow.cs @@ -19,7 +19,7 @@ using Tensorflow.Eager; namespace Tensorflow { - public partial class tensorflow : IObjectLife + public partial class tensorflow : ITensorFlowObject { public TF_DataType @byte = TF_DataType.TF_UINT8; public TF_DataType @sbyte = TF_DataType.TF_INT8; diff --git a/src/TensorFlowNET.Core/tensorflow.threading.cs b/src/TensorFlowNET.Core/tensorflow.threading.cs index 33e925fd..71f93008 100644 --- a/src/TensorFlowNET.Core/tensorflow.threading.cs +++ b/src/TensorFlowNET.Core/tensorflow.threading.cs @@ -19,7 +19,7 @@ using System.Threading; namespace Tensorflow { - public partial class tensorflow : IObjectLife + public partial class tensorflow : ITensorFlowObject { protected ThreadLocal _defaultSessionFactory; diff --git a/test/TensorFlowNET.UnitTest/PythonTest.cs b/test/TensorFlowNET.UnitTest/PythonTest.cs index 7db2eeaa..cf908fa2 100644 --- a/test/TensorFlowNET.UnitTest/PythonTest.cs +++ b/test/TensorFlowNET.UnitTest/PythonTest.cs @@ -259,7 +259,7 @@ namespace TensorFlowNET.UnitTest return s.as_default(); } - private IObjectLife _constrain_devices_and_set_default(Session sess, bool useGpu, bool forceGpu) + private ITensorFlowObject _constrain_devices_and_set_default(Session sess, bool useGpu, bool forceGpu) { //def _constrain_devices_and_set_default(self, sess, use_gpu, force_gpu): //"""Set the session and its graph to global default and constrain devices.""" diff --git a/test/TensorFlowNET.UnitTest/VersionTest.cs b/test/TensorFlowNET.UnitTest/VersionTest.cs index cabcdd25..66ed31eb 100644 --- a/test/TensorFlowNET.UnitTest/VersionTest.cs +++ b/test/TensorFlowNET.UnitTest/VersionTest.cs @@ -11,7 +11,7 @@ namespace TensorFlowNET.UnitTest public void GetVersion() { var ver = tf.VERSION; - Assert.IsTrue(ver.StartsWith("1.14.")); + Assert.IsTrue(ver.StartsWith("1.15.")); } } }