From c6169e8758d4ed6e3fb9b72e0be0a737f3b0f949 Mon Sep 17 00:00:00 2001 From: haiping008 Date: Fri, 1 Feb 2019 14:48:30 -0600 Subject: [PATCH] change Python.zip to use yield return. --- .../Gradients/gradients_impl.py.cs | 45 +++++++++---------- src/TensorFlowNET.Core/Python.cs | 10 +++-- .../LinearRegression.cs | 3 +- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/TensorFlowNET.Core/Gradients/gradients_impl.py.cs b/src/TensorFlowNET.Core/Gradients/gradients_impl.py.cs index a5eb97ac..aec61d1c 100644 --- a/src/TensorFlowNET.Core/Gradients/gradients_impl.py.cs +++ b/src/TensorFlowNET.Core/Gradients/gradients_impl.py.cs @@ -46,7 +46,15 @@ namespace Tensorflow all.AddRange(stop_gradients); all.AddRange(grad_ys); - var grads = new Dictionary(); + // Iterate over the collected ops. + /** + * grads: op => list of gradients received on each output endpoint of the + * op. The gradients for each endpoint are initially collected as a list. + * When it is time to call the op's gradient function, for each endpoint we + * aggregate the list of received gradients into a Add() Operation if there + * is more than one. + **/ + var grads = new Dictionary(); Python.with(new ops.name_scope(name, "gradients", values: all), scope => { @@ -71,21 +79,9 @@ namespace Tensorflow var from_ops = xs.Select(x => x.op).ToList(); var stop_gradient_ops = stop_gradients.Select(x => x.op).ToList(); (var reachable_to_ops, var pending_count, var loop_state) = _PendingCount(to_ops, from_ops, colocate_gradients_with_ops, new List(), xs); - - // Iterate over the collected ops. - /** - * grads: op => list of gradients received on each output endpoint of the - * op. The gradients for each endpoint are initially collected as a list. - * When it is time to call the op's gradient function, for each endpoint we - * aggregate the list of received gradients into a Add() Operation if there - * is more than one. - **/ - for(int i = 0; i < ys.Count(); i++) - { - (var y, var grad_y) = Python.zip(ys, grad_ys, i); + foreach(var (y, grad_y) in Python.zip(ys, grad_ys)) _SetGrad(grads, y, grad_y); - } // Initialize queue with to_ops. var queue = new Queue(); @@ -141,10 +137,9 @@ namespace Tensorflow } } - for(int i =0; i< in_grads.Length; i++) + var inputs = (List)_NonEagerInputs(op, xs); + foreach (var (t_in, in_grad) in Python.zip(inputs, in_grads)) { - var inputs = (List)_NonEagerInputs(op, xs); - var (t_in, in_grad) = Python.zip(inputs, in_grads, i); if(in_grad != null) { in_grad.shape = t_in.shape; @@ -188,9 +183,9 @@ namespace Tensorflow return op.OpType == "PartitionedCall" || op.OpType == "StatefulPartitionedCall"; } - private static Tensor[] _AggregatedGrads(Dictionary grads, Operation op, string gradient_uid, object loop_state, int aggregation_method = 0) + private static Tensor[] _AggregatedGrads(Dictionary grads, Operation op, string gradient_uid, object loop_state, int aggregation_method = 0) { - var out_grads = _GetGrads(grads, op) as object[]; + var out_grads = _GetGrads(grads, op); for(int i = 0; i < out_grads.Length; i++) { var out_grad = out_grads[i]; @@ -255,12 +250,12 @@ namespace Tensorflow return t_grad[0]; } - private static object _GetGrads(Dictionary grads, Operation op) + private static Tensor[][] _GetGrads(Dictionary grads, Operation op) { if (grads.ContainsKey(op.Name)) return grads[op.Name]; else - return op.outputs.Select(x => new object[0]).ToArray(); + return op.outputs.Select(x => new Tensor[0]).ToArray(); } /// @@ -269,16 +264,16 @@ namespace Tensorflow /// /// /// - private static void _SetGrad(Dictionary grads, Tensor t, Tensor grad) + private static void _SetGrad(Dictionary grads, Tensor t, Tensor grad) { var op = t.op; - object op_grads = null; + Tensor[][] op_grads = null; if (!grads.ContainsKey(op.Name)) { - op_grads = op.outputs.Select(x => new object[1]).ToList(); + op_grads = op.outputs.Select(x => new Tensor[1]).ToArray(); grads[op.Name] = op_grads; } - var t_grads = (op_grads as object[])[t.value_index]; + var t_grads = op_grads[t.value_index]; // t_grads[0] = grad; } diff --git a/src/TensorFlowNET.Core/Python.cs b/src/TensorFlowNET.Core/Python.cs index b4358e58..54dd4b10 100644 --- a/src/TensorFlowNET.Core/Python.cs +++ b/src/TensorFlowNET.Core/Python.cs @@ -53,14 +53,16 @@ namespace Tensorflow } } - public static (T, T) zip(IList t1, IList t2, int index = 0) + public static IEnumerable<(T, T)> zip(NDArray t1, NDArray t2) { - return (t1[index], t2[index]); + int index = 0; + yield return(t1.Data(index), t2.Data(index)); } - public static (T, T) zip(NDArray t1, NDArray t2, int index = 0) + public static IEnumerable<(T, T)> zip(IList t1, IList t2) { - return (t1.Data(index), t2.Data(index)); + int index = 0; + yield return (t1[index], t2[index]); } } diff --git a/test/TensorFlowNET.Examples/LinearRegression.cs b/test/TensorFlowNET.Examples/LinearRegression.cs index b724234b..6e9a2c0a 100644 --- a/test/TensorFlowNET.Examples/LinearRegression.cs +++ b/test/TensorFlowNET.Examples/LinearRegression.cs @@ -63,9 +63,8 @@ namespace TensorFlowNET.Examples // Fit all training data for (int i = 0; i < training_epochs; i++) { - for(int index = 0; index < train_X.size; index++) + foreach((double x, double y) in Python.zip(train_X, train_Y)) { - (double x, double y) = Python.zip(train_X, train_Y, index); var feed_dict = new Dictionary(); //sess.run(optimizer, feed_dict);