You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

TensorTest.cs 13 kB

Performance optimization, refactoring and revamping. (#362) * Refactored DisposableObject * Added different build directory for TensorflowNET.Examples.GPU * _FetchHandler: Switched to NPTypeCode * gfile.cs, Walk(...): Handle case when directory top doesn't exist. * Tensor.Creation: Perf-opted when creating tensor from NDArray of string * Graph.cs: refactor and added docs * Tensor.Creation.cs: perf-ops * Tensor.Explicit.cs: perf-ops * Copied globals.regen from NumSharp - Added supported_numericals_TF_DataType * Tensor perf-ops and cleanup, Revamped dtypes.cs, some renames. - Cleanup and docs to all Tensor.cs files - Changed all uses of System.Convert to NumSharp.Utilities.Converts - Added all missing types in dtypes.cs - Renamed tensor.Data<T> to tensor.ToArray<T>, added obsolete message - Renamed tensor.Data() to tensor.BufferToArray(), added obsolete message - Made GraphKeys to use const string instead allocating strings at every use of GraphKeys. * Tensor: Added guards for explicit casts. * Tensor: Added explicit cast to string * Tensor.ToArray<T>(): Added support for cases when tensor is scalar. * Tensor.BufferToArray(): Fixed to use long instead of int. * TensorShape: Revamped and documented. * BaseSession: Added Session.run(ITensorOrOperation fetche, params FeedItem[] feed_dict) * Tensor: renamed _dtype to _override_dtype - Fixed all locations _dtype is used incorrectly. * Fixed unit tests * Tensor.Operations: Reverted commit * DisposableObject: sorted internal_dispose to properly handle Dispose() calls * Tensor.DisposeUnmanagedResources: Nullify _handle after delete. * TensorShape.this[...]: fixed guard check. * DisposableObject #362
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. using Microsoft.VisualStudio.TestTools.UnitTesting;
  2. using NumSharp;
  3. using System;
  4. using System.Linq;
  5. using System.Runtime.InteropServices;
  6. using System.Threading;
  7. using FluentAssertions;
  8. using Tensorflow;
  9. using static Tensorflow.Binding;
  10. using Tensorflow.Framework;
  11. namespace TensorFlowNET.UnitTest.NativeAPI
  12. {
  13. [TestClass]
  14. public class TensorTest : CApiTest
  15. {
  16. [TestMethod]
  17. public unsafe void TensorFromFixed()
  18. {
  19. var array = new float[1000];
  20. var span = new Span<float>(array, 100, 500);
  21. fixed (float* ptr = &MemoryMarshal.GetReference(span))
  22. {
  23. using (var t = new Tensor((IntPtr) ptr, new long[] {span.Length}, tf.float32, 4 * span.Length))
  24. {
  25. Assert.IsFalse(t.IsDisposed);
  26. Assert.AreEqual(2000, (int) t.bytesize);
  27. }
  28. }
  29. fixed (float* ptr = &array[0])
  30. {
  31. using (var t = new Tensor((IntPtr) ptr, new long[] {array.Length}, tf.float32, 4 * array.Length))
  32. {
  33. Assert.IsFalse(t.IsDisposed);
  34. Assert.AreEqual(4000, (int) t.bytesize);
  35. }
  36. }
  37. }
  38. [TestMethod]
  39. public unsafe void TensorFromArray()
  40. {
  41. var array = new float[1000];
  42. using (var t = new Tensor(array, new long[] {array.Length}, tf.float32))
  43. {
  44. Assert.IsFalse(t.IsDisposed);
  45. Assert.AreEqual(1000 * sizeof(float), (int) t.bytesize);
  46. }
  47. using (var t = new Tensor(new float[] {1}, new long[] {1}, tf.float32))
  48. {
  49. Assert.IsFalse(t.IsDisposed);
  50. Assert.AreEqual(1 * sizeof(float), (int) t.bytesize);
  51. }
  52. using (var t = new Tensor(new float[] {1}, null, tf.float32))
  53. {
  54. Assert.IsFalse(t.IsDisposed);
  55. Assert.AreEqual(1 * sizeof(float), (int) t.bytesize);
  56. t.shape.Should().BeEmpty();
  57. }
  58. }
  59. [TestMethod]
  60. public void AllocateTensor()
  61. {
  62. ulong num_bytes = 6 * sizeof(float);
  63. long[] dims = {2, 3};
  64. Tensor t = c_api.TF_AllocateTensor(TF_DataType.TF_FLOAT, dims, 2, num_bytes);
  65. EXPECT_EQ(TF_DataType.TF_FLOAT, t.dtype);
  66. EXPECT_EQ(2, t.NDims);
  67. EXPECT_EQ((int) dims[0], t.shape[0]);
  68. EXPECT_EQ(num_bytes, t.bytesize);
  69. t.Dispose();
  70. }
  71. /// <summary>
  72. /// Port from c_api_test.cc
  73. /// `TEST(CAPI, MaybeMove)`
  74. /// </summary>
  75. [TestMethod, Ignore]
  76. public void MaybeMove()
  77. {
  78. NDArray nd = np.array(2, 3);
  79. Tensor t = new Tensor(nd);
  80. Tensor o = t.MaybeMove();
  81. ASSERT_TRUE(o == IntPtr.Zero); // It is unsafe to move memory TF might not own.
  82. t.Dispose();
  83. }
  84. /// <summary>
  85. /// Port from c_api_test.cc
  86. /// `TEST(CAPI, Tensor)`
  87. /// </summary>
  88. [TestMethod]
  89. public void Tensor()
  90. {
  91. var nd = np.array(1f, 2f, 3f, 4f, 5f, 6f).reshape(2, 3);
  92. var tensor = new Tensor(nd);
  93. var array = tensor.ToArray<float>();
  94. EXPECT_EQ(tensor.dtype, TF_DataType.TF_FLOAT);
  95. EXPECT_EQ(tensor.rank, nd.ndim);
  96. EXPECT_EQ((int) tensor.shape[0], nd.shape[0]);
  97. EXPECT_EQ((int) tensor.shape[1], nd.shape[1]);
  98. EXPECT_EQ(tensor.bytesize, (ulong) nd.size * sizeof(float));
  99. Assert.IsTrue(Enumerable.SequenceEqual(nd.Data<float>(), new float[] {1, 2, 3, 4, 5, 6}));
  100. }
  101. /// <summary>
  102. /// Port from tensorflow\c\c_api_test.cc
  103. /// `TEST(CAPI, SetShape)`
  104. /// </summary>
  105. [TestMethod]
  106. public void SetShape()
  107. {
  108. var s = new Status();
  109. var graph = new Graph().as_default();
  110. var feed = c_test_util.Placeholder(graph, s);
  111. var feed_out_0 = new TF_Output(feed, 0);
  112. // Fetch the shape, it should be completely unknown.
  113. int num_dims = c_api.TF_GraphGetTensorNumDims(graph, feed_out_0, s.Handle);
  114. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  115. EXPECT_EQ(-1, num_dims);
  116. // Set the shape to be unknown, expect no change.
  117. c_api.TF_GraphSetTensorShape(graph, feed_out_0, null, -1, s.Handle);
  118. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  119. num_dims = c_api.TF_GraphGetTensorNumDims(graph, feed_out_0, s.Handle);
  120. EXPECT_EQ(-1, num_dims);
  121. // Set the shape to be 2 x Unknown
  122. long[] dims = {2, -1};
  123. c_api.TF_GraphSetTensorShape(graph, feed_out_0, dims, dims.Length, s.Handle);
  124. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  125. num_dims = c_api.TF_GraphGetTensorNumDims(graph, feed_out_0, s.Handle);
  126. EXPECT_EQ(2, num_dims);
  127. // Get the dimension vector appropriately.
  128. var returned_dims = new long[dims.Length];
  129. c_api.TF_GraphGetTensorShape(graph, feed_out_0, returned_dims, num_dims, s.Handle);
  130. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  131. Assert.IsTrue(Enumerable.SequenceEqual(dims, returned_dims));
  132. // Set to a new valid shape: [2, 3]
  133. dims[1] = 3;
  134. c_api.TF_GraphSetTensorShape(graph, feed_out_0, dims, dims.Length, s.Handle);
  135. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  136. // Fetch and see that the new value is returned.
  137. c_api.TF_GraphGetTensorShape(graph, feed_out_0, returned_dims, num_dims, s.Handle);
  138. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  139. Assert.IsTrue(Enumerable.SequenceEqual(dims, returned_dims));
  140. // Try to set 'unknown' with unknown rank on the shape and see that
  141. // it doesn't change.
  142. c_api.TF_GraphSetTensorShape(graph, feed_out_0, null, -1, s.Handle);
  143. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  144. c_api.TF_GraphGetTensorShape(graph, feed_out_0, returned_dims, num_dims, s.Handle);
  145. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  146. EXPECT_EQ(2, num_dims);
  147. EXPECT_EQ(2, (int) returned_dims[0]);
  148. EXPECT_EQ(3, (int) returned_dims[1]);
  149. // Try to set 'unknown' with same rank on the shape and see that
  150. // it doesn't change.
  151. dims[0] = -1;
  152. dims[1] = -1;
  153. c_api.TF_GraphSetTensorShape(graph, feed_out_0, dims, 2, s.Handle);
  154. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  155. c_api.TF_GraphGetTensorShape(graph, feed_out_0, returned_dims, num_dims, s.Handle);
  156. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  157. EXPECT_EQ(2, num_dims);
  158. EXPECT_EQ(2, (int) returned_dims[0]);
  159. EXPECT_EQ(3, (int) returned_dims[1]);
  160. // Try to fetch a shape with the wrong num_dims
  161. c_api.TF_GraphGetTensorShape(graph, feed_out_0, returned_dims, 5, s.Handle);
  162. Assert.IsTrue(s.Code == TF_Code.TF_INVALID_ARGUMENT);
  163. // Try to set an invalid shape (cannot change 2x3 to a 2x5).
  164. dims[1] = 5;
  165. c_api.TF_GraphSetTensorShape(graph, feed_out_0, dims, 2, s.Handle);
  166. Assert.IsTrue(s.Code == TF_Code.TF_INVALID_ARGUMENT);
  167. // Test for a scalar.
  168. var three = c_test_util.ScalarConst(3, graph, s);
  169. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  170. var three_out_0 = new TF_Output(three, 0);
  171. num_dims = c_api.TF_GraphGetTensorNumDims(graph, three_out_0, s.Handle);
  172. Assert.IsTrue(s.Code == TF_Code.TF_OK);
  173. EXPECT_EQ(0, num_dims);
  174. c_api.TF_GraphGetTensorShape(graph, feed_out_0, null, num_dims, s.Handle);
  175. //Assert.IsTrue(s.Code == TF_Code.TF_OK);
  176. // graph.Dispose();
  177. s.Dispose();
  178. }
  179. [TestMethod]
  180. public void sparse_to_dense()
  181. {
  182. var indices = tf.reshape(tf.range(0, 5), new int[] { 5, 1 });
  183. var labels = tf.expand_dims(tf.constant(new[] { 0, 1, 2, 3, 4 }),1);
  184. var st = tf.concat(values: new[] { indices, labels }, axis: 1);
  185. var onehot = tf.sparse_to_dense(st, (5, 5), 1);
  186. using (var sess = tf.Session())
  187. {
  188. var result = sess.run(onehot);
  189. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 1, 0, 0, 0, 0 }, result[0].ToArray<int>()));
  190. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 1, 0, 0, 0 }, result[1].ToArray<int>()));
  191. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 1, 0, 0 }, result[2].ToArray<int>()));
  192. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 0, 1, 0 }, result[3].ToArray<int>()));
  193. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 0, 0, 1 }, result[4].ToArray<int>()));
  194. };
  195. }
  196. [TestMethod]
  197. public void sparse_tensor_to_dense()
  198. {
  199. var decoded_list = tf.SparseTensor(new[,]
  200. {
  201. { 0L, 0L },
  202. { 1L, 2L }
  203. },
  204. new int[] { 1, 2 },
  205. new[] { 3L, 4L });
  206. var onehot = tf.sparse_tensor_to_dense(decoded_list);
  207. using (var sess = tf.Session())
  208. {
  209. var result = sess.run(onehot);
  210. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 1, 0, 0, 0 }, result[0].ToArray<int>()));
  211. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 2, 0 }, result[1].ToArray<int>()));
  212. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 0, 0 }, result[2].ToArray<int>()));
  213. }
  214. }
  215. [TestMethod]
  216. public void batch_to_space_nd()
  217. {
  218. var inputs = np.arange(24).reshape(4, 2, 3);
  219. var block_shape = new[] { 2, 2 };
  220. int[,] crops = { { 0, 0 }, { 0, 0 } };
  221. var tensor = tf.batch_to_space_nd(inputs, block_shape, crops);
  222. using (var sess = tf.Session())
  223. {
  224. var result = sess.run(tensor);
  225. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 6, 1, 7, 2, 8 }, result[0, 0].ToArray<int>()));
  226. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 12, 18, 13, 19, 14, 20 }, result[0, 1].ToArray<int>()));
  227. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 3, 9, 4, 10, 5, 11 }, result[0, 2].ToArray<int>()));
  228. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 15, 21, 16, 22, 17, 23 }, result[0, 3].ToArray<int>()));
  229. }
  230. }
  231. [TestMethod, Ignore]
  232. public void boolean_mask()
  233. {
  234. var tensor = new[] { 0, 1, 2, 3 };
  235. var mask = np.array(new[] { true, false, true, false });
  236. var masked = tf.boolean_mask(tensor, mask);
  237. using (var sess = tf.Session())
  238. {
  239. var result = sess.run(masked);
  240. Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 2 }, masked.ToArray<int>()));
  241. }
  242. }
  243. /// <summary>
  244. /// Creates a tensor from an image of 256x256x3 and resizes it to 100x100x3
  245. /// </summary>
  246. [TestMethod]
  247. public unsafe void tensor_resize()
  248. {
  249. var imageArray = new float[256 * 256 * 3];
  250. using var newSize = tf.convert_to_tensor(new int[] { 100, 100 });
  251. using (var t = new Tensor(imageArray, new long[] { 1, 256, 256, 3 }, tf.float32))
  252. {
  253. Assert.IsFalse(t.IsDisposed);
  254. Assert.AreEqual(256 * 256 * 3 * sizeof(float), (int)t.bytesize);
  255. using var resized = tf.image.resize_bilinear(t, newSize);
  256. EXPECT_EQ((int)resized.shape[0], 1);
  257. EXPECT_EQ((int)resized.shape[1], 100);
  258. EXPECT_EQ((int)resized.shape[2], 100);
  259. EXPECT_EQ((int)resized.shape[3], 3);
  260. }
  261. fixed (float* ptr = &imageArray[0])
  262. {
  263. using (var t = new Tensor((IntPtr)ptr, new long[] { imageArray.Length }, tf.float32, 4 * imageArray.Length))
  264. {
  265. Assert.IsFalse(t.IsDisposed);
  266. Assert.AreEqual(256 * 256 * 3 * sizeof(float), (int)t.bytesize);
  267. using var resized = tf.image.resize_bilinear(t, newSize);
  268. EXPECT_EQ((int)resized.shape[0], 1);
  269. EXPECT_EQ((int)resized.shape[1], 100);
  270. EXPECT_EQ((int)resized.shape[2], 100);
  271. EXPECT_EQ((int)resized.shape[3], 3);
  272. }
  273. }
  274. }
  275. }
  276. }