From da542513bca4166a22fe4d2181502bae8c5cfa94 Mon Sep 17 00:00:00 2001 From: Oceania2018 Date: Sun, 15 Mar 2020 06:12:59 -0500 Subject: [PATCH] add float and double Equal. --- TensorFlow.NET.sln | 4 +- src/TensorFlowNET.Core/Eager/EagerTensor.cs | 8 ++++ .../TensorFlow.Binding.csproj | 2 +- .../Tensors/Tensor.Creation.cs | 14 +++---- .../Tensors/Tensor.Value.cs | 2 + .../Tensors/c_api.tensor.cs | 8 ++-- src/TensorFlowNET.Core/Tensors/constant_op.cs | 2 + test/TensorFlowNET.UnitTest/TFNetApiTest.cs | 37 +++++++++++++++++++ .../math_test/MathOperationTest.cs | 8 ++-- .../nn_test/ActivationFunctionTest.cs | 12 +++--- 10 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 test/TensorFlowNET.UnitTest/TFNetApiTest.cs diff --git a/TensorFlow.NET.sln b/TensorFlow.NET.sln index 61f5cf6b..ae290b70 100644 --- a/TensorFlow.NET.sln +++ b/TensorFlow.NET.sln @@ -27,8 +27,8 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {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|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.Build.0 = Debug|Any CPU {FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug-Minimal|x64.ActiveCfg = Debug|Any CPU diff --git a/src/TensorFlowNET.Core/Eager/EagerTensor.cs b/src/TensorFlowNET.Core/Eager/EagerTensor.cs index 6c61eb28..5f822c95 100644 --- a/src/TensorFlowNET.Core/Eager/EagerTensor.cs +++ b/src/TensorFlowNET.Core/Eager/EagerTensor.cs @@ -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) { } diff --git a/src/TensorFlowNET.Core/TensorFlow.Binding.csproj b/src/TensorFlowNET.Core/TensorFlow.Binding.csproj index 09159483..3aac7f92 100644 --- a/src/TensorFlowNET.Core/TensorFlow.Binding.csproj +++ b/src/TensorFlowNET.Core/TensorFlow.Binding.csproj @@ -37,7 +37,7 @@ https://tensorflownet.readthedocs.io true TRACE;DEBUG;SERIALIZABLE_ - AnyCPU + x64 diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs index 243fe9f3..4ef5b113 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs @@ -83,7 +83,7 @@ namespace Tensorflow { 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; } } @@ -99,7 +99,7 @@ namespace Tensorflow /// Size of the tensor in memory 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; } @@ -372,9 +372,9 @@ namespace Tensorflow /// /// Create a 1d Tensor from the given linear array and shape /// - 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)); } /// @@ -526,7 +526,7 @@ namespace Tensorflow dims: nd.shape.Select(i => (long) i).ToArray(), num_dims: nd.ndim, 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_TensorData(handle).ToPointer() == arraySlice.Address) @@ -647,9 +647,9 @@ namespace Tensorflow //call NewTensor IntPtr handle; 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 - 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. if (c_api.TF_TensorData(handle) == pinnedAddr) diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Value.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Value.cs index 72c660bb..2491eb30 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.Value.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.Value.cs @@ -165,6 +165,8 @@ namespace Tensorflow return ToArray(); case TF_DataType.TF_FLOAT: return ToArray(); + case TF_DataType.TF_DOUBLE: + return ToArray(); default: return BufferToArray(); } diff --git a/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs b/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs index be5f3932..c56d50ae 100644 --- a/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs +++ b/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs @@ -90,7 +90,7 @@ namespace Tensorflow /// /// [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); /// /// Return a new tensor that holds the bytes data[0,len-1] @@ -103,9 +103,9 @@ namespace Tensorflow /// /// [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); } /// /// Return a new tensor that holds the bytes data[0,len-1] @@ -118,7 +118,7 @@ namespace Tensorflow /// /// [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); } diff --git a/src/TensorFlowNET.Core/Tensors/constant_op.cs b/src/TensorFlowNET.Core/Tensors/constant_op.cs index 204baaae..7b2d9d21 100644 --- a/src/TensorFlowNET.Core/Tensors/constant_op.cs +++ b/src/TensorFlowNET.Core/Tensors/constant_op.cs @@ -93,6 +93,8 @@ namespace Tensorflow return new EagerTensor(int32, ctx.device_name); case float[] float32s: return new EagerTensor(float32s, ctx.device_name); + case double[] double64s: + return new EagerTensor(double64s, ctx.device_name); default: throw new NotImplementedException($"convert_to_eager_tensor {value.GetType()}"); } diff --git a/test/TensorFlowNET.UnitTest/TFNetApiTest.cs b/test/TensorFlowNET.UnitTest/TFNetApiTest.cs new file mode 100644 index 00000000..12d37c43 --- /dev/null +++ b/test/TensorFlowNET.UnitTest/TFNetApiTest.cs @@ -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; + } + } +} diff --git a/test/TensorFlowNET.UnitTest/math_test/MathOperationTest.cs b/test/TensorFlowNET.UnitTest/math_test/MathOperationTest.cs index 0840b318..ccc9c2d9 100644 --- a/test/TensorFlowNET.UnitTest/math_test/MathOperationTest.cs +++ b/test/TensorFlowNET.UnitTest/math_test/MathOperationTest.cs @@ -9,7 +9,7 @@ using static Tensorflow.Binding; namespace TensorFlowNET.UnitTest.math_test { [TestClass] - public class MathOperationTest + public class MathOperationTest : TFNetApiTest { // A constant vector of size 6 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() { 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(); - Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + Assert.IsTrue(Equal(expected, actual)); } [TestMethod] @@ -29,7 +29,7 @@ namespace TensorFlowNET.UnitTest.math_test var b = tf.tan(a, name: "Tan"); var expected = new float[] { 1.5574077f, -0.5463025f, 0.264317f, 1.709847f, 0f, -0.2202772f }; var actual = b.ToArray(); - Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + Assert.IsTrue(Equal(expected, actual)); } } } diff --git a/test/TensorFlowNET.UnitTest/nn_test/ActivationFunctionTest.cs b/test/TensorFlowNET.UnitTest/nn_test/ActivationFunctionTest.cs index 63163bfb..474fd344 100644 --- a/test/TensorFlowNET.UnitTest/nn_test/ActivationFunctionTest.cs +++ b/test/TensorFlowNET.UnitTest/nn_test/ActivationFunctionTest.cs @@ -9,7 +9,7 @@ using static Tensorflow.Binding; namespace TensorFlowNET.UnitTest.nn_test { [TestClass] - public class ActivationFunctionTest + public class ActivationFunctionTest : TFNetApiTest { // A constant vector of size 6 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() { 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(); - Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + Assert.IsTrue(Equal(expected, actual)); } [TestMethod] @@ -31,7 +29,7 @@ namespace TensorFlowNET.UnitTest.nn_test var b = tf.nn.relu(a, name: "ReLU"); var expected = new float[] { 1f, 0f, 3.4f, 0f, 0f, 0f }; var actual = b.ToArray(); - Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + Assert.IsTrue(Equal(expected, actual)); } [TestMethod] @@ -40,7 +38,7 @@ namespace TensorFlowNET.UnitTest.nn_test var b = tf.nn.tanh(a, name: "TanH"); var expected = new float[] { 0.7615942f, -0.46211717f, 0.9977749f , -0.970452f, 0f, -0.99999547f }; var actual = b.ToArray(); - Assert.IsTrue(Enumerable.SequenceEqual(expected, actual)); + Assert.IsTrue(Equal(expected, actual)); } } }