| @@ -27,8 +27,8 @@ Global | |||||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.Build.0 = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x64.ActiveCfg = Debug|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x64.Build.0 = Debug|Any CPU | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x64.ActiveCfg = Debug|x64 | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|x64.Build.0 = Debug|x64 | |||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|Any CPU.Build.0 = Debug|Any CPU | ||||
| {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|x64.ActiveCfg = Debug|Any CPU | {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|x64.ActiveCfg = Debug|Any CPU | ||||
| @@ -19,6 +19,14 @@ namespace Tensorflow.Eager | |||||
| { | { | ||||
| } | } | ||||
| public EagerTensor(float[] value, string device_name) : base(value) | |||||
| { | |||||
| } | |||||
| public EagerTensor(double[] value, string device_name) : base(value) | |||||
| { | |||||
| } | |||||
| public EagerTensor(NDArray value, string device_name) : base(value) | public EagerTensor(NDArray value, string device_name) : base(value) | ||||
| { | { | ||||
| } | } | ||||
| @@ -37,7 +37,7 @@ https://tensorflownet.readthedocs.io</Description> | |||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | ||||
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||||
| <DefineConstants>TRACE;DEBUG;SERIALIZABLE_</DefineConstants> | <DefineConstants>TRACE;DEBUG;SERIALIZABLE_</DefineConstants> | ||||
| <PlatformTarget>AnyCPU</PlatformTarget> | |||||
| <PlatformTarget>x64</PlatformTarget> | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||
| @@ -83,7 +83,7 @@ namespace Tensorflow | |||||
| { | { | ||||
| unsafe | unsafe | ||||
| { | { | ||||
| _handle = TF_NewTensor(dType, dims: shape, num_dims: shape.Length, data: data_ptr, len: (UIntPtr) num_bytes); | |||||
| _handle = TF_NewTensor(dType, dims: shape, num_dims: shape.Length, data: data_ptr, len: (ulong)num_bytes); | |||||
| AllocationType = TF_TensorData(_handle) == data_ptr ? AllocationType.FromPointer : AllocationType.Tensorflow; | AllocationType = TF_TensorData(_handle) == data_ptr ? AllocationType.FromPointer : AllocationType.Tensorflow; | ||||
| } | } | ||||
| } | } | ||||
| @@ -99,7 +99,7 @@ namespace Tensorflow | |||||
| /// <param name="num_bytes">Size of the tensor in memory</param> | /// <param name="num_bytes">Size of the tensor in memory</param> | ||||
| public unsafe Tensor(void* data_ptr, long[] shape, TF_DataType dType, int num_bytes) | public unsafe Tensor(void* data_ptr, long[] shape, TF_DataType dType, int num_bytes) | ||||
| { | { | ||||
| _handle = TF_NewTensor(dType, dims: shape, num_dims: shape.Length, data: data_ptr, len: (UIntPtr) num_bytes); | |||||
| _handle = TF_NewTensor(dType, dims: shape, num_dims: shape.Length, data: data_ptr, len: (ulong) num_bytes); | |||||
| AllocationType = TF_TensorData(_handle).ToPointer() == data_ptr ? AllocationType.FromPointer : AllocationType.Tensorflow; | AllocationType = TF_TensorData(_handle).ToPointer() == data_ptr ? AllocationType.FromPointer : AllocationType.Tensorflow; | ||||
| } | } | ||||
| @@ -372,9 +372,9 @@ namespace Tensorflow | |||||
| /// <summary> | /// <summary> | ||||
| /// Create a 1d Tensor from the given linear array and shape | /// Create a 1d Tensor from the given linear array and shape | ||||
| /// </summary> | /// </summary> | ||||
| public Tensor(float[] data, TF_DataType? dType = null) | |||||
| public Tensor(float[] data) | |||||
| { | { | ||||
| _handle = CreateTensorFromArray(dType ?? dtypes.as_dtype(typeof(float)), new long[] {data.Length}, data, sizeof(float)); | |||||
| _handle = CreateTensorFromArray(TF_DataType.TF_FLOAT, new long[] { data.Length }, data, sizeof(float)); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -526,7 +526,7 @@ namespace Tensorflow | |||||
| dims: nd.shape.Select(i => (long) i).ToArray(), | dims: nd.shape.Select(i => (long) i).ToArray(), | ||||
| num_dims: nd.ndim, | num_dims: nd.ndim, | ||||
| data: arraySlice.Address, | data: arraySlice.Address, | ||||
| len: (UIntPtr) (nd.size * nd.dtypesize)); | |||||
| len: (ulong) (nd.size * nd.dtypesize)); | |||||
| //if TF decided not to perform copy, hold reference for given NDArray. | //if TF decided not to perform copy, hold reference for given NDArray. | ||||
| if (TF_TensorData(handle).ToPointer() == arraySlice.Address) | if (TF_TensorData(handle).ToPointer() == arraySlice.Address) | ||||
| @@ -647,9 +647,9 @@ namespace Tensorflow | |||||
| //call NewTensor | //call NewTensor | ||||
| IntPtr handle; | IntPtr handle; | ||||
| if (shape == null || shape.Length == 0) | if (shape == null || shape.Length == 0) | ||||
| handle = TF_NewTensor(dt, new long[0], 0, pinnedAddr + start * element_size, (UIntPtr) (count * element_size)); | |||||
| handle = TF_NewTensor(dt, new long[0], 0, pinnedAddr + start * element_size, (ulong) (count * element_size)); | |||||
| else | else | ||||
| handle = TF_NewTensor(dt, shape, shape.Length, pinnedAddr + start * element_size, (UIntPtr) (count * element_size)); | |||||
| handle = TF_NewTensor(dt, shape, shape.Length, pinnedAddr + start * element_size, (ulong) (count * element_size)); | |||||
| //Figure if TF decided to clone or not. | //Figure if TF decided to clone or not. | ||||
| if (c_api.TF_TensorData(handle) == pinnedAddr) | if (c_api.TF_TensorData(handle) == pinnedAddr) | ||||
| @@ -165,6 +165,8 @@ namespace Tensorflow | |||||
| return ToArray<int>(); | return ToArray<int>(); | ||||
| case TF_DataType.TF_FLOAT: | case TF_DataType.TF_FLOAT: | ||||
| return ToArray<float>(); | return ToArray<float>(); | ||||
| case TF_DataType.TF_DOUBLE: | |||||
| return ToArray<double>(); | |||||
| default: | default: | ||||
| return BufferToArray(); | return BufferToArray(); | ||||
| } | } | ||||
| @@ -90,7 +90,7 @@ namespace Tensorflow | |||||
| /// <param name="deallocator_arg"></param> | /// <param name="deallocator_arg"></param> | ||||
| /// <returns></returns> | /// <returns></returns> | ||||
| [DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
| public static extern IntPtr TF_NewTensor(TF_DataType dataType, long[] dims, int num_dims, IntPtr data, UIntPtr len, Deallocator deallocator, IntPtr deallocator_arg); | |||||
| public static extern IntPtr TF_NewTensor(TF_DataType dataType, long[] dims, int num_dims, IntPtr data, ulong len, Deallocator deallocator, IntPtr deallocator_arg); | |||||
| /// <summary> | /// <summary> | ||||
| /// Return a new tensor that holds the bytes data[0,len-1] | /// Return a new tensor that holds the bytes data[0,len-1] | ||||
| @@ -103,9 +103,9 @@ namespace Tensorflow | |||||
| /// <param name="deallocator"></param> | /// <param name="deallocator"></param> | ||||
| /// <param name="deallocator_arg"></param> | /// <param name="deallocator_arg"></param> | ||||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||
| public static unsafe IntPtr TF_NewTensor(TF_DataType dataType, long[] dims, int num_dims, IntPtr data, UIntPtr len) | |||||
| public static unsafe IntPtr TF_NewTensor(TF_DataType dataType, long[] dims, int num_dims, IntPtr data, ulong len) | |||||
| { | { | ||||
| return TF_NewTensor(dataType, dims, num_dims, data, len, EmptyDeallocator, DeallocatorArgs.Empty); | |||||
| return c_api.TF_NewTensor(dataType, dims, num_dims, data, len, EmptyDeallocator, DeallocatorArgs.Empty); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Return a new tensor that holds the bytes data[0,len-1] | /// Return a new tensor that holds the bytes data[0,len-1] | ||||
| @@ -118,7 +118,7 @@ namespace Tensorflow | |||||
| /// <param name="deallocator"></param> | /// <param name="deallocator"></param> | ||||
| /// <param name="deallocator_arg"></param> | /// <param name="deallocator_arg"></param> | ||||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||
| public static unsafe IntPtr TF_NewTensor(TF_DataType dataType, long[] dims, int num_dims, void* data, UIntPtr len) | |||||
| public static unsafe IntPtr TF_NewTensor(TF_DataType dataType, long[] dims, int num_dims, void* data, ulong len) | |||||
| { | { | ||||
| return TF_NewTensor(dataType, dims, num_dims, new IntPtr(data), len); | return TF_NewTensor(dataType, dims, num_dims, new IntPtr(data), len); | ||||
| } | } | ||||
| @@ -93,6 +93,8 @@ namespace Tensorflow | |||||
| return new EagerTensor(int32, ctx.device_name); | return new EagerTensor(int32, ctx.device_name); | ||||
| case float[] float32s: | case float[] float32s: | ||||
| return new EagerTensor(float32s, ctx.device_name); | return new EagerTensor(float32s, ctx.device_name); | ||||
| case double[] double64s: | |||||
| return new EagerTensor(double64s, ctx.device_name); | |||||
| default: | default: | ||||
| throw new NotImplementedException($"convert_to_eager_tensor {value.GetType()}"); | throw new NotImplementedException($"convert_to_eager_tensor {value.GetType()}"); | ||||
| } | } | ||||
| @@ -0,0 +1,37 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace TensorFlowNET.UnitTest | |||||
| { | |||||
| public class TFNetApiTest | |||||
| { | |||||
| public bool Equal(float[] f1, float[] f2) | |||||
| { | |||||
| bool ret = false; | |||||
| var tolerance = .000001f; | |||||
| for (var i = 0; i < f1.Length; i++) | |||||
| { | |||||
| ret = Math.Abs(f1[i] - f2[i]) <= tolerance; | |||||
| if (!ret) | |||||
| break; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| public bool Equal(double[] d1, double[] d2) | |||||
| { | |||||
| bool ret = false; | |||||
| var tolerance = .000000000000001f; | |||||
| for (var i = 0; i < d1.Length; i++) | |||||
| { | |||||
| ret = Math.Abs(d1[i] - d2[i]) <= tolerance; | |||||
| if (!ret) | |||||
| break; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -9,7 +9,7 @@ using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.UnitTest.math_test | namespace TensorFlowNET.UnitTest.math_test | ||||
| { | { | ||||
| [TestClass] | [TestClass] | ||||
| public class MathOperationTest | |||||
| public class MathOperationTest : TFNetApiTest | |||||
| { | { | ||||
| // A constant vector of size 6 | // A constant vector of size 6 | ||||
| Tensor a = tf.constant(new float[] { 1.0f, -0.5f, 3.4f, -2.1f, 0.0f, -6.5f }); | Tensor a = tf.constant(new float[] { 1.0f, -0.5f, 3.4f, -2.1f, 0.0f, -6.5f }); | ||||
| @@ -18,9 +18,9 @@ namespace TensorFlowNET.UnitTest.math_test | |||||
| public void Sin() | public void Sin() | ||||
| { | { | ||||
| var b = tf.sin(a, name: "Sin"); | var b = tf.sin(a, name: "Sin"); | ||||
| var expected = new float[] { 0.84147096f, -0.47942555f, -0.2555412f, -0.8632094f /*python output -0.86320937*/, 0f, -0.21511999f }; | |||||
| var expected = new float[] { 0.84147096f, -0.47942555f, -0.2555412f, -0.86320937f, 0f, -0.21511999f }; | |||||
| var actual = b.ToArray<float>(); | var actual = b.ToArray<float>(); | ||||
| Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); | |||||
| Assert.IsTrue(Equal(expected, actual)); | |||||
| } | } | ||||
| [TestMethod] | [TestMethod] | ||||
| @@ -29,7 +29,7 @@ namespace TensorFlowNET.UnitTest.math_test | |||||
| var b = tf.tan(a, name: "Tan"); | var b = tf.tan(a, name: "Tan"); | ||||
| var expected = new float[] { 1.5574077f, -0.5463025f, 0.264317f, 1.709847f, 0f, -0.2202772f }; | var expected = new float[] { 1.5574077f, -0.5463025f, 0.264317f, 1.709847f, 0f, -0.2202772f }; | ||||
| var actual = b.ToArray<float>(); | var actual = b.ToArray<float>(); | ||||
| Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); | |||||
| Assert.IsTrue(Equal(expected, actual)); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -9,7 +9,7 @@ using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.UnitTest.nn_test | namespace TensorFlowNET.UnitTest.nn_test | ||||
| { | { | ||||
| [TestClass] | [TestClass] | ||||
| public class ActivationFunctionTest | |||||
| public class ActivationFunctionTest : TFNetApiTest | |||||
| { | { | ||||
| // A constant vector of size 6 | // A constant vector of size 6 | ||||
| Tensor a = tf.constant(new float[] { 1.0f, -0.5f, 3.4f, -2.1f, 0.0f, -6.5f }); | Tensor a = tf.constant(new float[] { 1.0f, -0.5f, 3.4f, -2.1f, 0.0f, -6.5f }); | ||||
| @@ -18,11 +18,9 @@ namespace TensorFlowNET.UnitTest.nn_test | |||||
| public void Sigmoid() | public void Sigmoid() | ||||
| { | { | ||||
| var b = tf.nn.sigmoid(a, name: "sigmoid"); | var b = tf.nn.sigmoid(a, name: "sigmoid"); | ||||
| // from python | |||||
| // [0.7310586f, 0.37754068f, 0.9677046f, 0.10909683f, 0.5f, 0.00150118f] | |||||
| var expected = new float[] { 0.7310586f, 0.377540678f, 0.9677046f, 0.109096833f, 0.5f, 0.00150118221f }; | |||||
| var expected = new float[] { 0.7310586f, 0.37754068f, 0.9677046f, 0.10909683f, 0.5f, 0.00150118f }; | |||||
| var actual = b.ToArray<float>(); | var actual = b.ToArray<float>(); | ||||
| Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); | |||||
| Assert.IsTrue(Equal(expected, actual)); | |||||
| } | } | ||||
| [TestMethod] | [TestMethod] | ||||
| @@ -31,7 +29,7 @@ namespace TensorFlowNET.UnitTest.nn_test | |||||
| var b = tf.nn.relu(a, name: "ReLU"); | var b = tf.nn.relu(a, name: "ReLU"); | ||||
| var expected = new float[] { 1f, 0f, 3.4f, 0f, 0f, 0f }; | var expected = new float[] { 1f, 0f, 3.4f, 0f, 0f, 0f }; | ||||
| var actual = b.ToArray<float>(); | var actual = b.ToArray<float>(); | ||||
| Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); | |||||
| Assert.IsTrue(Equal(expected, actual)); | |||||
| } | } | ||||
| [TestMethod] | [TestMethod] | ||||
| @@ -40,7 +38,7 @@ namespace TensorFlowNET.UnitTest.nn_test | |||||
| var b = tf.nn.tanh(a, name: "TanH"); | var b = tf.nn.tanh(a, name: "TanH"); | ||||
| var expected = new float[] { 0.7615942f, -0.46211717f, 0.9977749f , -0.970452f, 0f, -0.99999547f }; | var expected = new float[] { 0.7615942f, -0.46211717f, 0.9977749f , -0.970452f, 0f, -0.99999547f }; | ||||
| var actual = b.ToArray<float>(); | var actual = b.ToArray<float>(); | ||||
| Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); | |||||
| Assert.IsTrue(Equal(expected, actual)); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||