| @@ -54,19 +54,19 @@ namespace Tensorflow | |||
| status.Check(true); | |||
| } | |||
| public virtual NDArray run(object fetches, params FeedItem[] feed_dict) | |||
| public virtual NDArray[] run(object fetches, params FeedItem[] feed_dict) | |||
| { | |||
| return _run(fetches, feed_dict); | |||
| } | |||
| public virtual NDArray run(object fetches, Hashtable feed_dict = null) | |||
| public virtual NDArray[] run(object fetches, Hashtable feed_dict = null) | |||
| { | |||
| var feed_items = feed_dict == null ? new FeedItem[0] : | |||
| feed_dict.Keys.OfType<object>().Select(key => new FeedItem(key, feed_dict[key])).ToArray(); | |||
| return _run(fetches, feed_items); | |||
| } | |||
| private NDArray _run(object fetches, FeedItem[] feed_dict = null) | |||
| private NDArray[] _run(object fetches, FeedItem[] feed_dict = null) | |||
| { | |||
| var feed_dict_tensor = new Dictionary<object, object>(); | |||
| var feed_map = new Dictionary<object, object>(); | |||
| @@ -17,6 +17,7 @@ | |||
| using NumSharp; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Numerics; | |||
| namespace Tensorflow | |||
| { | |||
| @@ -45,9 +46,9 @@ namespace Tensorflow | |||
| /// </summary> | |||
| /// <param name="values"></param> | |||
| /// <returns></returns> | |||
| public override NDArray build_results(List<NDArray> values) | |||
| public override NDArray[] build_results(List<NDArray> values) | |||
| { | |||
| NDArray result = null; | |||
| NDArray[] result = null; | |||
| if (values.Count > 0) | |||
| { | |||
| @@ -55,26 +56,53 @@ namespace Tensorflow | |||
| switch (ret) | |||
| { | |||
| case NDArray value: | |||
| result = value; | |||
| result = new[] { value }; | |||
| break; | |||
| #if _REGEN | |||
| %types=["sbyte", "bool", "byte", "short", "ushort", "int", "uint", "long", "ulong", "float", "double", "Complex"] | |||
| %foreach types% | |||
| case #1 value: | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| % | |||
| #else | |||
| case sbyte value: | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case bool value: | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case byte value: | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case short value: | |||
| result = value; | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case ushort value: | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case int value: | |||
| result = value; | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case uint value: | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case long value: | |||
| result = value; | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case ulong value: | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case float value: | |||
| result = value; | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case double value: | |||
| result = value; | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| case string value: | |||
| result = value; | |||
| case Complex value: | |||
| result = new[] { NDArray.Scalar(value) }; | |||
| break; | |||
| #endif | |||
| default: | |||
| break; | |||
| } | |||
| @@ -57,7 +57,7 @@ namespace Tensorflow | |||
| _final_fetches = _fetches; | |||
| } | |||
| public NDArray build_results(BaseSession session, NDArray[] tensor_values) | |||
| public NDArray[] build_results(BaseSession session, NDArray[] tensor_values) | |||
| { | |||
| var full_values = new List<NDArray>(); | |||
| if (_final_fetches.Count != tensor_values.Length) | |||
| @@ -123,8 +123,7 @@ namespace Tensorflow | |||
| } | |||
| else | |||
| { | |||
| //full_values.Add(value.GetNDArrays()); | |||
| full_values.Add(value); | |||
| full_values.Add(value[np.arange(0, value.shape[0])]); | |||
| } | |||
| } | |||
| i += 1; | |||
| @@ -37,23 +37,9 @@ namespace Tensorflow | |||
| return new _ElementFetchMapper(fetches, (List<NDArray> fetched_vals) => fetched_vals[0]); | |||
| } | |||
| public virtual NDArray build_results(List<NDArray> values) | |||
| public virtual NDArray[] build_results(List<NDArray> values) | |||
| { | |||
| // if they're all scalar value | |||
| bool isAllScalars = values.Count(x => x.ndim == 0) == values.Count; | |||
| if (isAllScalars) | |||
| { | |||
| var type = values[0].dtype; | |||
| switch(Type.GetTypeCode(type)) | |||
| { | |||
| case TypeCode.Single: | |||
| return np.array(values.Select(x => (float)x).ToArray()); | |||
| default: | |||
| throw new NotImplementedException("build_results"); | |||
| } | |||
| } | |||
| return np.stack(values.ToArray()); | |||
| return values.ToArray(); | |||
| } | |||
| public virtual List<ITensorOrOperation> unique_fetches() | |||
| @@ -37,7 +37,7 @@ Docs: https://tensorflownet.readthedocs.io</Description> | |||
| 15. Fix Tensor memory leak. | |||
| 16. Rename with to tf_with that is only used to build graph purpose. | |||
| 17. Graph inherit from DisposableObject.</PackageReleaseNotes> | |||
| <LangVersion>7.2</LangVersion> | |||
| <LangVersion>7.3</LangVersion> | |||
| <FileVersion>0.10.11.0</FileVersion> | |||
| <PackageLicenseFile>LICENSE</PackageLicenseFile> | |||
| <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||
| @@ -531,8 +531,8 @@ namespace Tensorflow | |||
| var handle = TF_NewTensor(dtype, dims: nd.shape.Select(i=>(long)i).ToArray(), num_dims: nd.ndim, data: ptr, len: (UIntPtr)num_bytes, deallocator: _nothingDeallocator, ref _deallocatorArgs); | |||
| IsMemoryOwner = false; | |||
| return handle; | |||
| } | |||
| } | |||
| public unsafe Tensor(byte[][] buffer, long[] shape) | |||
| { | |||
| int size = 0; | |||
| @@ -394,9 +394,8 @@ namespace Tensorflow | |||
| protected override void DisposeManagedState() | |||
| { | |||
| if (gcHandle.IsAllocated) | |||
| gcHandle.Free(); | |||
| } | |||
| protected override void DisposeUnManagedState(IntPtr handle) | |||
| { | |||
| if(handle != IntPtr.Zero) | |||
| @@ -71,12 +71,12 @@ namespace Tensorflow | |||
| return new TensorShape(); | |||
| else | |||
| { | |||
| var concatenate_dims = new int[NDim + other.NDim]; | |||
| for (int i = 0; i < NDim; i++) | |||
| var concatenate_dims = new int[ndim + other.ndim]; | |||
| for (int i = 0; i < ndim; i++) | |||
| concatenate_dims[i] = dims[i]; | |||
| for (int i = 0; i < other.NDim; i++) | |||
| concatenate_dims[NDim + i] = other.dims[i]; | |||
| for (int i = 0; i < other.ndim; i++) | |||
| concatenate_dims[ndim + i] = other.dims[i]; | |||
| return new TensorShape(concatenate_dims); | |||
| } | |||
| @@ -212,7 +212,7 @@ namespace Tensorflow | |||
| if (values.GetType().IsArray) | |||
| nparray = np.array((string[])values, np_dt); | |||
| else | |||
| nparray = Convert.ToString(values); | |||
| nparray = NDArray.FromString(Convert.ToString(values)); | |||
| break; | |||
| case "Boolean": | |||
| if (values.GetType().IsArray) | |||
| @@ -267,7 +267,10 @@ namespace Tensorflow | |||
| if (numpy_dtype == TF_DataType.TF_STRING && !(values is NDArray)) | |||
| { | |||
| if (values is string str) | |||
| { | |||
| tensor_proto.StringVal.Add(Google.Protobuf.ByteString.CopyFromUtf8(str)); | |||
| tensor_proto.TensorShape = tensor_util.as_shape(new int[0]); | |||
| } | |||
| else if (values is string[] str_values) | |||
| tensor_proto.StringVal.AddRange(str_values.Select(x => Google.Protobuf.ByteString.CopyFromUtf8(x))); | |||
| else if(values is byte[] byte_values) | |||
| @@ -377,7 +377,7 @@ namespace Tensorflow | |||
| "`eval(session=sess)`."); | |||
| } | |||
| return session.run(tensor, feed_dict); | |||
| return session.run(tensor, feed_dict)[0]; | |||
| } | |||
| /// <summary> | |||
| @@ -91,16 +91,16 @@ namespace TensorFlowNET.Examples | |||
| { | |||
| var c = sess.run(cost, | |||
| new FeedItem(X, train_X), | |||
| new FeedItem(Y, train_Y)); | |||
| Console.WriteLine($"Epoch: {epoch + 1} cost={c} " + $"W={sess.run(W)} b={sess.run(b)}"); | |||
| new FeedItem(Y, train_Y))[0]; | |||
| Console.WriteLine($"Epoch: {epoch + 1} cost={c} " + $"W={sess.run(W)[0]} b={sess.run(b)[0]}"); | |||
| } | |||
| } | |||
| Console.WriteLine("Optimization Finished!"); | |||
| var training_cost = sess.run(cost, | |||
| new FeedItem(X, train_X), | |||
| new FeedItem(Y, train_Y)); | |||
| Console.WriteLine($"Training cost={training_cost} W={sess.run(W)} b={sess.run(b)}"); | |||
| new FeedItem(Y, train_Y))[0]; | |||
| Console.WriteLine($"Training cost={training_cost} W={sess.run(W)[0]} b={sess.run(b)[0]}"); | |||
| // Testing example | |||
| var test_X = np.array(6.83f, 4.668f, 8.9f, 7.91f, 5.7f, 8.7f, 3.1f, 2.1f); | |||
| @@ -108,7 +108,7 @@ namespace TensorFlowNET.Examples | |||
| Console.WriteLine("Testing... (Mean square loss Comparison)"); | |||
| var testing_cost = sess.run(tf.reduce_sum(tf.pow(pred - Y, 2.0f)) / (2.0f * test_X.shape[0]), | |||
| new FeedItem(X, test_X), | |||
| new FeedItem(Y, test_Y)); | |||
| new FeedItem(Y, test_Y))[0]; | |||
| Console.WriteLine($"Testing cost={testing_cost}"); | |||
| var diff = Math.Abs((float)training_cost - (float)testing_cost); | |||
| Console.WriteLine($"Absolute mean square loss difference: {diff}"); | |||
| @@ -162,7 +162,7 @@ namespace TensorFlowNET.Examples | |||
| var (batch_xs, batch_ys) = mnist.Train.GetNextBatch(10); | |||
| var results = sess.run(output, new FeedItem(input, batch_xs[np.arange(1)])); | |||
| if (results.argmax() == (batch_ys[0] as NDArray).argmax()) | |||
| if (results[0].argmax() == (batch_ys[0] as NDArray).argmax()) | |||
| print("predicted OK!"); | |||
| else | |||
| throw new ValueError("predict error, should be 90% accuracy"); | |||
| @@ -64,7 +64,7 @@ namespace TensorFlowNET.Examples | |||
| foreach(int i in range(Xte.shape[0])) | |||
| { | |||
| // Get nearest neighbor | |||
| long nn_index = sess.run(pred, new FeedItem(xtr, Xtr), new FeedItem(xte, Xte[i])); | |||
| long nn_index = sess.run(pred, new FeedItem(xtr, Xtr), new FeedItem(xte, Xte[i]))[0]; | |||
| // Get nearest neighbor class label and compare it to its true label | |||
| int index = (int)nn_index; | |||
| @@ -51,7 +51,7 @@ namespace TensorFlowNET.Examples | |||
| { | |||
| sw.Restart(); | |||
| var results = sess.run(output_operation.outputs[0], new FeedItem(input_operation.outputs[0], nd)); | |||
| var results = sess.run(output_operation.outputs[0], new FeedItem(input_operation.outputs[0], nd))[0]; | |||
| results = np.squeeze(results); | |||
| int idx = np.argmax(results); | |||
| @@ -78,9 +78,7 @@ namespace TensorFlowNET.Examples | |||
| var results = sess.run(outTensorArr, new FeedItem(imgTensor, imgArr)); | |||
| NDArray[] resultArr = results.GetNDArrays(); | |||
| buildOutputImage(resultArr); | |||
| buildOutputImage(results); | |||
| } | |||
| public void PrepareData() | |||
| @@ -110,7 +108,7 @@ namespace TensorFlowNET.Examples | |||
| var dims_expander = tf.expand_dims(casted, 0); | |||
| using (var sess = tf.Session(graph)) | |||
| return sess.run(dims_expander); | |||
| return sess.run(dims_expander)[0]; | |||
| } | |||
| private void buildOutputImage(NDArray[] resultArr) | |||
| @@ -122,12 +120,13 @@ namespace TensorFlowNET.Examples | |||
| Bitmap bitmap = new Bitmap(Path.Join(imageDir, "input.jpg")); | |||
| var scores = resultArr[2].AsIterator<float>(); | |||
| var boxes = resultArr[1].GetData<float>(); | |||
| var id = np.squeeze(resultArr[3]).GetData<float>(); | |||
| for (int i=0; i< scores.size; i++) | |||
| { | |||
| float score = scores.MoveNext(); | |||
| if (score > MIN_SCORE) | |||
| { | |||
| float[] boxes = resultArr[1].GetData<float>().ToArray(); | |||
| float top = boxes[i * 4] * bitmap.Height; | |||
| float left = boxes[i * 4 + 1] * bitmap.Width; | |||
| float bottom = boxes[i * 4 + 2] * bitmap.Height; | |||
| @@ -141,8 +140,7 @@ namespace TensorFlowNET.Examples | |||
| Height = (int)(bottom - top) | |||
| }; | |||
| var id = (int)resultArr[3].GetValue(i); | |||
| string name = pbTxtItems.items.Where(w => w.id == id).Select(s=>s.display_name).FirstOrDefault(); | |||
| string name = pbTxtItems.items.Where(w => w.id == id[i]).Select(s=>s.display_name).FirstOrDefault(); | |||
| drawObjectOnBitmap(bitmap, rect, score, name); | |||
| } | |||
| @@ -455,7 +455,7 @@ namespace TensorFlowNET.Examples | |||
| // First decode the JPEG image, resize it, and rescale the pixel values. | |||
| var resized_input_values = sess.run(decoded_image_tensor, new FeedItem(image_data_tensor, new Tensor(image_data, TF_DataType.TF_STRING))); | |||
| // Then run it through the recognition network. | |||
| var bottleneck_values = sess.run(bottleneck_tensor, new FeedItem(resized_input_tensor, resized_input_values)); | |||
| var bottleneck_values = sess.run(bottleneck_tensor, new FeedItem(resized_input_tensor, resized_input_values))[0]; | |||
| bottleneck_values = np.squeeze(bottleneck_values); | |||
| return bottleneck_values; | |||
| } | |||
| @@ -244,7 +244,7 @@ namespace TensorFlowNET.Examples | |||
| [is_training] = false | |||
| }; | |||
| var result1 = sess.run(accuracy, valid_feed_dict); | |||
| float accuracy_value = result1; | |||
| float accuracy_value = result1[0]; | |||
| sum_accuracy += accuracy_value; | |||
| cnt += 1; | |||
| } | |||
| @@ -98,9 +98,9 @@ namespace TensorFlowNET.UnitTest | |||
| { | |||
| var result = sess.run(tensor); | |||
| Assert.AreEqual(result.shape[0], 3); | |||
| Assert.AreEqual(result.shape[1], 2); | |||
| Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 0, 0, 0, 0 }, result.Data<int>())); | |||
| Assert.AreEqual(result[0].shape[0], 3); | |||
| Assert.AreEqual(result[0].shape[1], 2); | |||
| Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 0, 0, 0, 0 }, result[0].Data<int>())); | |||
| } | |||
| // big size | |||
| @@ -109,13 +109,13 @@ namespace TensorFlowNET.UnitTest | |||
| { | |||
| var result = sess.run(tensor); | |||
| Assert.AreEqual(result.shape[0], 200); | |||
| Assert.AreEqual(result.shape[1], 100); | |||
| Assert.AreEqual(result[0].shape[0], 200); | |||
| Assert.AreEqual(result[0].shape[1], 100); | |||
| var data = result.Data<int>(); | |||
| var data = result[0].Data<int>(); | |||
| Assert.AreEqual(0, data[0]); | |||
| Assert.AreEqual(0, data[500]); | |||
| Assert.AreEqual(0, data[result.size - 1]); | |||
| Assert.AreEqual(0, data[result[0].size - 1]); | |||
| } | |||
| } | |||
| @@ -127,9 +127,9 @@ namespace TensorFlowNET.UnitTest | |||
| { | |||
| var result = sess.run(ones); | |||
| Assert.AreEqual(result.shape[0], 3); | |||
| Assert.AreEqual(result.shape[1], 2); | |||
| Assert.IsTrue(new[] { 1, 1, 1, 1, 1, 1 }.SequenceEqual(result.Data<int>())); | |||
| Assert.AreEqual(result[0].shape[0], 3); | |||
| Assert.AreEqual(result[0].shape[1], 2); | |||
| Assert.IsTrue(new[] { 1, 1, 1, 1, 1, 1 }.SequenceEqual(result[0].Data<int>())); | |||
| } | |||
| } | |||
| @@ -142,9 +142,9 @@ namespace TensorFlowNET.UnitTest | |||
| { | |||
| var result = sess.run(halfes); | |||
| Assert.AreEqual(result.shape[0], 3); | |||
| Assert.AreEqual(result.shape[1], 2); | |||
| Assert.IsTrue(new[] { .5, .5, .5, .5, .5, .5 }.SequenceEqual(result.Data<double>())); | |||
| Assert.AreEqual(result[0].shape[0], 3); | |||
| Assert.AreEqual(result[0].shape[1], 2); | |||
| Assert.IsTrue(new[] { .5, .5, .5, .5, .5, .5 }.SequenceEqual(result[0].Data<double>())); | |||
| } | |||
| } | |||
| @@ -161,10 +161,10 @@ namespace TensorFlowNET.UnitTest | |||
| using (var sess = tf.Session()) | |||
| { | |||
| var result = sess.run(tensor); | |||
| var data = result.Data<int>(); | |||
| var data = result[0].Data<int>(); | |||
| Assert.AreEqual(result.shape[0], 2); | |||
| Assert.AreEqual(result.shape[1], 3); | |||
| Assert.AreEqual(result[0].shape[0], 2); | |||
| Assert.AreEqual(result[0].shape[1], 3); | |||
| Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 3, 1, 1, 2, 1, 3 }, data)); | |||
| } | |||
| } | |||
| @@ -177,7 +177,7 @@ namespace TensorFlowNET.UnitTest | |||
| var c = a * b; | |||
| var sess = tf.Session(); | |||
| double result = sess.run(c); | |||
| double result = sess.run(c)[0]; | |||
| sess.close(); | |||
| Assert.AreEqual(6.0, result); | |||
| @@ -41,7 +41,7 @@ namespace TensorFlowNET.UnitTest | |||
| var grad = tf.gradients(y, x); | |||
| Assert.AreEqual(grad[0].name, "gradients/AddN:0"); | |||
| float r = sess.run(grad[0]); | |||
| float r = sess.run(grad[0])[0]; | |||
| Assert.AreEqual(r, 1.4f); | |||
| } | |||
| } | |||
| @@ -57,7 +57,7 @@ namespace TensorFlowNET.UnitTest | |||
| var grad = tf.gradients(y, x); | |||
| Assert.AreEqual(grad[0].name, "gradients/AddN:0"); | |||
| float r = sess.run(grad[0]); | |||
| float r = sess.run(grad[0])[0]; | |||
| Assert.AreEqual(r, 14.700001f); | |||
| }); | |||
| } | |||
| @@ -94,7 +94,7 @@ namespace TensorFlowNET.UnitTest | |||
| using (var sess = tf.Session(graph)) | |||
| { | |||
| var r = sess.run(slice); | |||
| var r = sess.run(slice)[0]; | |||
| Assert.IsTrue(Enumerable.SequenceEqual(r.shape, new[] { 2, 1, 2 })); | |||
| Assert.IsTrue(Enumerable.SequenceEqual(r[0].GetData<int>(), new[] { 11, 13 })); | |||
| @@ -17,7 +17,7 @@ namespace TensorFlowNET.UnitTest | |||
| { | |||
| var result = sess.run(y, | |||
| new FeedItem(x, 2)); | |||
| Assert.AreEqual((int)result, 6); | |||
| Assert.AreEqual((int)result[0], 6); | |||
| } | |||
| } | |||
| } | |||
| @@ -16,7 +16,7 @@ namespace TensorFlowNET.UnitTest | |||
| { | |||
| session.run(x.initializer); | |||
| var result = session.run(x); | |||
| Assert.AreEqual(10, (int)result); | |||
| Assert.AreEqual(10, (int)result[0]); | |||
| } | |||
| } | |||
| @@ -81,7 +81,7 @@ namespace TensorFlowNET.UnitTest | |||
| using (var session = tf.Session()) | |||
| { | |||
| session.run(model); | |||
| int result = session.run(y); | |||
| int result = session.run(y)[0]; | |||
| Assert.AreEqual(result, 4); | |||
| } | |||
| } | |||
| @@ -98,11 +98,11 @@ namespace TensorFlowNET.UnitTest | |||
| sess.run(init); | |||
| var result = sess.run(variable); | |||
| Assert.IsTrue((int)result == 31); | |||
| Assert.IsTrue((int)result[0] == 31); | |||
| var assign = variable.assign(12); | |||
| result = sess.run(assign); | |||
| Assert.IsTrue((int)result == 12); | |||
| Assert.IsTrue((int)result[0] == 12); | |||
| } | |||
| [TestMethod] | |||
| @@ -139,7 +139,7 @@ namespace TensorFlowNET.UnitTest | |||
| for(int i = 0; i < 5; i++) | |||
| { | |||
| x = x + 1; | |||
| result = session.run(x); | |||
| result = session.run(x)[0]; | |||
| print(result); | |||
| } | |||
| } | |||