| @@ -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); | |||
| @@ -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>(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()); | |||
| } | |||
| } | |||
| } | |||
| @@ -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>(T value) where T : unmanaged | |||
| { | |||
| return value switch | |||
| { | |||
| bool b => new NDArray(b), | |||
| _ => throw new NotImplementedException("") | |||
| }; | |||
| } | |||
| public T GetValue<T>(int index) where T : unmanaged | |||
| => _tensor.ToArray<T>()[index]; | |||
| public T GetAtIndex<T>(int index) where T : unmanaged | |||
| @@ -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); | |||
| @@ -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; | |||
| } | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -98,6 +98,7 @@ namespace Tensorflow | |||
| attrs: attrs, | |||
| name: name); | |||
| var o = op.outputs; | |||
| return op.outputs[0]; | |||
| } | |||
| @@ -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; | |||
| @@ -101,7 +101,7 @@ namespace Tensorflow | |||
| /// <param name="verify_shape"></param> | |||
| /// <param name="allow_broadcast"></param> | |||
| /// <returns></returns> | |||
| 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; | |||
| @@ -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; | |||
| } | |||
| } | |||
| } | |||