diff --git a/src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs b/src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs index a6b94b3b..d5b0f152 100644 --- a/src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs +++ b/src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs @@ -14,16 +14,42 @@ namespace Tensorflow.Eager Resolve(); } + #region scalar eager tensor + public EagerTensor(bool value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(byte value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(sbyte value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(short value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(int value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(uint value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(long value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(ulong value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(float value) : base(value) + => NewEagerTensorHandle(_handle); + public EagerTensor(double value) : base(value) + => NewEagerTensorHandle(_handle); + #endregion + public EagerTensor(object value,string device_name, TF_DataType dtype = TF_DataType.TF_UINT8) : base((float[])value) { throw new NotImplementedException(""); } - public EagerTensor(object value, Shape shape = null, string device_name = null, TF_DataType dtype = TF_DataType.TF_UINT8) : base((float[])value) + public EagerTensor(object value, Shape? shape = null, string device_name = null, TF_DataType dtype = TF_DataType.TF_UINT8) : base((float[])value) { NewEagerTensorHandle(_handle); } + public EagerTensor(Shape shape, TF_DataType dtype) : base(shape, dtype) + => NewEagerTensorHandle(_handle); + internal unsafe EagerTensor(string value) : base(value) => NewEagerTensorHandle(_handle); diff --git a/src/TensorFlowNET.Core/Numpy/NDArray.Creation.cs b/src/TensorFlowNET.Core/Numpy/NDArray.Creation.cs index 1ac9fbba..ea9d9d69 100644 --- a/src/TensorFlowNET.Core/Numpy/NDArray.Creation.cs +++ b/src/TensorFlowNET.Core/Numpy/NDArray.Creation.cs @@ -1,15 +1,55 @@ using System; using System.Collections.Generic; using System.Text; +using Tensorflow.Eager; using static Tensorflow.Binding; namespace Tensorflow.NumPy { public partial class NDArray { + public NDArray(bool value) => _tensor = new EagerTensor(value); + public NDArray(byte value) => _tensor = new EagerTensor(value); + public NDArray(short value) => _tensor = new EagerTensor(value); + public NDArray(int value) => _tensor = new EagerTensor(value); + public NDArray(long value) => _tensor = new EagerTensor(value); + public NDArray(float value) => _tensor = new EagerTensor(value); + public NDArray(double value) => _tensor = new EagerTensor(value); + + public NDArray(Array value, Shape? shape = null) => _tensor = new EagerTensor(value, shape); + + public NDArray(Shape shape, NumpyDType dtype = NumpyDType.Float) + { + Initialize(shape, dtype: dtype); + } + + public NDArray(Tensor value, Shape? shape = null) + { + if (shape is not null) + _tensor = tf.reshape(value, shape); + else + _tensor = value; + + if (_tensor.TensorDataPointer == IntPtr.Zero) + _tensor = tf.get_default_session().eval(_tensor); + } + + public static NDArray Scalar(T value) where T : unmanaged + { + return value switch + { + bool val => new NDArray(val), + int val => new NDArray(val), + float val => new NDArray(val), + double val => new NDArray(val), + _ => throw new NotImplementedException("") + }; + } + void Initialize(Shape shape, NumpyDType dtype = NumpyDType.Float) { - _tensor = tf.zeros(shape, dtype: dtype.as_tf_dtype()); + // _tensor = tf.zeros(shape, dtype: dtype.as_tf_dtype()); + _tensor = new EagerTensor(shape, dtype: dtype.as_tf_dtype()); } } } diff --git a/src/TensorFlowNET.Core/Numpy/NDArray.cs b/src/TensorFlowNET.Core/Numpy/NDArray.cs index 0a0d53fb..72ab9475 100644 --- a/src/TensorFlowNET.Core/Numpy/NDArray.cs +++ b/src/TensorFlowNET.Core/Numpy/NDArray.cs @@ -17,63 +17,6 @@ namespace Tensorflow.NumPy public Shape shape => _tensor.shape; public IntPtr data => _tensor.TensorDataPointer; - public NDArray(bool value) - { - _tensor = ops.convert_to_tensor(value); - } - - public NDArray(byte value) - { - _tensor = ops.convert_to_tensor(value); - } - - public NDArray(int value) - { - _tensor = ops.convert_to_tensor(value); - } - - public NDArray(float value) - { - _tensor = ops.convert_to_tensor(value); - } - - public NDArray(double value) - { - _tensor = ops.convert_to_tensor(value); - } - - public NDArray(Array value, Shape shape = null) - { - _tensor = ops.convert_to_tensor(value); - } - - public NDArray(Type dtype, Shape shape) - { - - } - - public NDArray(Shape shape, NumpyDType dtype = NumpyDType.Float) - { - Initialize(shape, dtype: dtype); - } - - public NDArray(Tensor value, Shape? shape = null) - { - if (shape is not null) - _tensor = tf.reshape(value, shape); - else - _tensor = value; - } - - public static NDArray Scalar(T value) where T : unmanaged - { - return value switch - { - bool b => new NDArray(b), - _ => throw new NotImplementedException("") - }; - } - public T GetValue(int index) where T : unmanaged => _tensor.ToArray()[index]; public T GetAtIndex(int index) where T : unmanaged diff --git a/src/TensorFlowNET.Core/Sessions/BaseSession.cs b/src/TensorFlowNET.Core/Sessions/BaseSession.cs index b7403c56..d6bc9ae4 100644 --- a/src/TensorFlowNET.Core/Sessions/BaseSession.cs +++ b/src/TensorFlowNET.Core/Sessions/BaseSession.cs @@ -245,6 +245,31 @@ namespace Tensorflow return result; } + public unsafe Tensor eval(Tensor tensor) + { + var status = tf.Status; + + var output_values = new IntPtr[1]; + var fetch_list = new[] { tensor._as_tf_output() }; + + c_api.TF_SessionRun(_handle, + run_options: null, + inputs: new TF_Output[0], + input_values: new IntPtr[0], + ninputs: 0, + outputs: fetch_list, + output_values: output_values, + noutputs: 1, + target_opers: new IntPtr[0], + ntargets: 0, + run_metadata: IntPtr.Zero, + status: status.Handle); + + status.Check(true); + + return new Tensor(output_values[0]); + } + private static unsafe NDArray fetchValue(IntPtr output) { var tensor = new Tensor(output); diff --git a/src/TensorFlowNET.Core/Sessions/_FetchHandler.cs b/src/TensorFlowNET.Core/Sessions/_FetchHandler.cs index 0be6b395..93656cf7 100644 --- a/src/TensorFlowNET.Core/Sessions/_FetchHandler.cs +++ b/src/TensorFlowNET.Core/Sessions/_FetchHandler.cs @@ -78,10 +78,7 @@ namespace Tensorflow { var value = tensor_values[j]; j += 1; - if (value.ndim == 0) - full_values.Add(value); - else - full_values.Add(value[np.arange(0, (int)value.dims[0])]); + full_values.Add(value); } i += 1; } diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs index dda4a291..2459ae1a 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs @@ -64,6 +64,9 @@ namespace Tensorflow #endif } + unsafe internal Tensor(Shape shape, TF_DataType dtype) + => _handle = TF_NewTensor(shape, dtype, null); + internal Tensor(Array array, Shape? shape = null) => InitTensor(array, shape); @@ -71,41 +74,40 @@ namespace Tensorflow { shape = shape ?? array.GetShape(); var dtype = array.GetType().GetElementType().as_tf_dtype(); - var length = (ulong)(array.Length * dtype.get_datatype_size()); switch (array) { case bool[] val: fixed (void* addr = &val[0]) - _handle = TF_NewTensor(shape, dtype, addr, length); + _handle = TF_NewTensor(shape, dtype, addr); break; case int[] val: fixed (void* addr = &val[0]) - _handle = TF_NewTensor(shape, dtype, addr, length); + _handle = TF_NewTensor(shape, dtype, addr); break; case int[,] val: fixed (void* addr = &val[0, 0]) - _handle = TF_NewTensor(shape, dtype, addr, length); + _handle = TF_NewTensor(shape, dtype, addr); break; case long[] val: fixed (void* addr = &val[0]) - _handle = TF_NewTensor(shape, dtype, addr, length); + _handle = TF_NewTensor(shape, dtype, addr); break; case float[] val: fixed (void* addr = &val[0]) - _handle = TF_NewTensor(shape, dtype, addr, length); + _handle = TF_NewTensor(shape, dtype, addr); break; case float[,] val: fixed (void* addr = &val[0, 0]) - _handle = TF_NewTensor(shape, dtype, addr, length); + _handle = TF_NewTensor(shape, dtype, addr); break; case double[] val: fixed (void* addr = &val[0]) - _handle = TF_NewTensor(shape, dtype, addr, length); + _handle = TF_NewTensor(shape, dtype, addr); break; case double[,] val: fixed (void* addr = &val[0, 0]) - _handle = TF_NewTensor(shape, dtype, addr, length); + _handle = TF_NewTensor(shape, dtype, addr); break; default: throw new NotImplementedException(""); @@ -131,7 +133,7 @@ namespace Tensorflow } public unsafe Tensor(NDArray nd) - => _handle = TF_NewTensor(nd.shape, nd.dtype.as_tf_dtype(), nd.data.ToPointer(), nd.size * nd.dtypesize); + => _handle = TF_NewTensor(nd.shape, nd.dtype.as_tf_dtype(), nd.data.ToPointer()); #region scala public Tensor(bool value) => _handle = TF_NewTensor(value); diff --git a/src/TensorFlowNET.Core/Tensors/TensorShape.Convert.cs b/src/TensorFlowNET.Core/Tensors/TensorShape.Convert.cs index 45627b0e..ecb273a0 100644 --- a/src/TensorFlowNET.Core/Tensors/TensorShape.Convert.cs +++ b/src/TensorFlowNET.Core/Tensors/TensorShape.Convert.cs @@ -11,7 +11,7 @@ namespace Tensorflow } public static implicit operator TensorShape(Shape shape) => new TensorShape((long[])shape.dims.Clone()); - public static implicit operator Shape(TensorShape shape) => new Shape((long[])shape.dims.Clone()); + public static implicit operator Shape(TensorShape shape) => shape == null ? null : new Shape((long[])shape.dims.Clone()); public static implicit operator int[](TensorShape shape) => shape == null ? null : (int[])shape.dims.Clone(); //we clone to avoid any changes public static implicit operator TensorShape(int[] dims) => dims == null ? null : new TensorShape(dims); diff --git a/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs b/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs index 4347ace2..b0390f5b 100644 --- a/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs +++ b/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs @@ -104,8 +104,9 @@ namespace Tensorflow return c_api.TF_NewTensor(dataType, dims, num_dims, data, len, EmptyDeallocator, DeallocatorArgs.Empty); } - public static unsafe IntPtr TF_NewTensor(Shape shape, TF_DataType dtype, void* data, ulong length) + public static unsafe IntPtr TF_NewTensor(Shape shape, TF_DataType dtype, void* data) { + var length = shape.size * (ulong)dtype.get_datatype_size(); var handle = TF_AllocateTensor(dtype, shape.dims, shape.ndim, length); var tensor = TF_TensorData(handle); System.Buffer.MemoryCopy(data, tensor.ToPointer(), length, length); diff --git a/src/TensorFlowNET.Core/Tensors/constant_op.cs b/src/TensorFlowNET.Core/Tensors/constant_op.cs index e7fdabf0..f934de22 100644 --- a/src/TensorFlowNET.Core/Tensors/constant_op.cs +++ b/src/TensorFlowNET.Core/Tensors/constant_op.cs @@ -98,6 +98,7 @@ namespace Tensorflow attrs: attrs, name: name); + var o = op.outputs; return op.outputs[0]; } diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs index 1037eff2..b811ba7f 100644 --- a/src/TensorFlowNET.Core/Tensors/dtypes.cs +++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs @@ -182,6 +182,58 @@ namespace Tensorflow return dtype.Value; } + public static TF_DataType tf_dtype_from_name(string name) + { + TF_DataType dtype = TF_DataType.DtInvalid; + switch (name.ToLower()) + { + case "char": + dtype = TF_DataType.TF_UINT8; + break; + case "boolean": + dtype = TF_DataType.TF_BOOL; + break; + case "sbyte": + dtype = TF_DataType.TF_INT8; + break; + case "byte": + dtype = TF_DataType.TF_UINT8; + break; + case "int16": + dtype = TF_DataType.TF_INT16; + break; + case "uint16": + dtype = TF_DataType.TF_UINT16; + break; + case "int32": + dtype = TF_DataType.TF_INT32; + break; + case "uint32": + dtype = TF_DataType.TF_UINT32; + break; + case "int64": + dtype = TF_DataType.TF_INT64; + break; + case "uint64": + dtype = TF_DataType.TF_UINT64; + break; + case "single": + dtype = TF_DataType.TF_FLOAT; + break; + case "double": + dtype = TF_DataType.TF_DOUBLE; + break; + case "complex": + dtype = TF_DataType.TF_COMPLEX128; + break; + case "string": + dtype = TF_DataType.TF_STRING; + break; + } + + return dtype; + } + public static DataType as_datatype_enum(this TF_DataType type) { return (DataType)type; diff --git a/src/TensorFlowNET.Core/Tensors/tensor_util.cs b/src/TensorFlowNET.Core/Tensors/tensor_util.cs index 453606f4..525509a4 100644 --- a/src/TensorFlowNET.Core/Tensors/tensor_util.cs +++ b/src/TensorFlowNET.Core/Tensors/tensor_util.cs @@ -101,7 +101,7 @@ namespace Tensorflow /// /// /// - public static TensorProto make_tensor_proto(object values, TF_DataType dtype = TF_DataType.DtInvalid, int[]? shape = null, bool verify_shape = false, bool allow_broadcast = false) + public static TensorProto make_tensor_proto(object values, TF_DataType dtype = TF_DataType.DtInvalid, Shape? shape = null, bool verify_shape = false, bool allow_broadcast = false) { if (allow_broadcast && verify_shape) throw new ValueError("allow_broadcast and verify_shape are not both allowed."); @@ -109,10 +109,11 @@ namespace Tensorflow return tp; dtype = values.GetType().as_tf_dtype(); + shape = shape ?? values.GetShape(); var tensor_proto = new TensorProto { Dtype = dtype.as_datatype_enum(), - TensorShape = values.GetShape().as_shape_proto() + TensorShape = shape.as_shape_proto() }; // scalar @@ -141,8 +142,6 @@ namespace Tensorflow default: throw new Exception("make_tensor_proto Not Implemented"); } - - return tensor_proto; } else if (dtype == TF_DataType.TF_STRING && !(values is NDArray)) { @@ -154,15 +153,14 @@ namespace Tensorflow tensor_proto.StringVal.AddRange(str_values.Select(x => Google.Protobuf.ByteString.CopyFromUtf8(x))); else if (values is byte[] byte_values) tensor_proto.TensorContent = Google.Protobuf.ByteString.CopyFrom(byte_values); - - return tensor_proto; } else if(values is Array array) { // array - /*byte[] bytes = array.ToByteArray(); - tensor_proto.TensorContent = Google.Protobuf.ByteString.CopyFrom(bytes.ToArray()); - return tensor_proto;*/ + var len = dtype.get_datatype_size() * (int)shape.size; + byte[] bytes = new byte[len]; + System.Buffer.BlockCopy(array, 0, bytes, 0, len); + tensor_proto.TensorContent = Google.Protobuf.ByteString.CopyFrom(bytes); } return tensor_proto; diff --git a/src/TensorFlowNET.Keras/Sequence.cs b/src/TensorFlowNET.Keras/Sequence.cs index 4f10abfa..b9036a93 100644 --- a/src/TensorFlowNET.Keras/Sequence.cs +++ b/src/TensorFlowNET.Keras/Sequence.cs @@ -54,8 +54,8 @@ namespace Tensorflow.Keras if (value == null) value = 0f; - var type = getNPType(dtype); - var nd = new NDArray(type, new Shape(length.Count(), maxlen.Value)); + var type = dtypes.tf_dtype_from_name(dtype); + var nd = new NDArray((length.Count(), maxlen.Value), dtype: type.as_numpy_typecode()); for (int i = 0; i < nd.dims[0]; i++) { @@ -71,10 +71,5 @@ namespace Tensorflow.Keras return nd; } - - private Type getNPType(string typeName) - { - return System.Type.GetType("NumSharp.np,NumSharp").GetField(typeName).GetValue(null) as Type; - } } }