| @@ -22,8 +22,10 @@ namespace Tensorflow.Gradients | |||||
| var sy = array_ops.shape(y); | var sy = array_ops.shape(y); | ||||
| var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | var (rx, ry) = gen_array_ops.broadcast_gradient_args(sx, sy); | ||||
| var r1 = gen_array_ops.reshape(math_ops.reduce_sum(grad, rx), sx); | |||||
| var r2 = gen_array_ops.reshape(math_ops.reduce_sum(grad, ry), sy); | |||||
| var sum1 = math_ops.reduce_sum(grad, rx); | |||||
| var r1 = gen_array_ops.reshape(sum1, sx); | |||||
| var sum2 = math_ops.reduce_sum(grad, ry); | |||||
| var r2 = gen_array_ops.reshape(sum2, sy); | |||||
| return new Tensor[] { r1, r2 }; | return new Tensor[] { r1, r2 }; | ||||
| } | } | ||||
| @@ -48,7 +50,8 @@ namespace Tensorflow.Gradients | |||||
| var x = op.inputs[0]; | var x = op.inputs[0]; | ||||
| var y = op.inputs[1]; | var y = op.inputs[1]; | ||||
| var grad = grads[0]; | var grad = grads[0]; | ||||
| if (grad is Tensor && _ShapesFullySpecifiedAndEqual(x, y, grad) && | |||||
| if (grad is Tensor && | |||||
| _ShapesFullySpecifiedAndEqual(x, y, grad) && | |||||
| new TF_DataType[] { tf.int32, tf.float32 }.Contains(grad.dtype)) | new TF_DataType[] { tf.int32, tf.float32 }.Contains(grad.dtype)) | ||||
| return new Tensor[] { gen_math_ops.mul(grad, y), gen_math_ops.mul(grad, x) }; | return new Tensor[] { gen_math_ops.mul(grad, y), gen_math_ops.mul(grad, x) }; | ||||
| @@ -60,10 +63,11 @@ namespace Tensorflow.Gradients | |||||
| y = math_ops.conj(y); | y = math_ops.conj(y); | ||||
| var mul1 = gen_math_ops.mul(grad, y); | var mul1 = gen_math_ops.mul(grad, y); | ||||
| var mul2 = gen_math_ops.mul(x, grad); | |||||
| var reduce_sum1 = math_ops.reduce_sum(mul1, rx); | var reduce_sum1 = math_ops.reduce_sum(mul1, rx); | ||||
| var reduce_sum2 = math_ops.reduce_sum(mul2, ry); | |||||
| var reshape1 = gen_array_ops.reshape(reduce_sum1, sx); | var reshape1 = gen_array_ops.reshape(reduce_sum1, sx); | ||||
| var mul2 = gen_math_ops.mul(x, grad); | |||||
| var reduce_sum2 = math_ops.reduce_sum(mul2, ry); | |||||
| var reshape2 = gen_array_ops.reshape(reduce_sum2, sy); | var reshape2 = gen_array_ops.reshape(reduce_sum2, sy); | ||||
| return new Tensor[] { reshape1, reshape2 }; | return new Tensor[] { reshape1, reshape2 }; | ||||
| @@ -146,7 +150,13 @@ namespace Tensorflow.Gradients | |||||
| public static bool _ShapesFullySpecifiedAndEqual(Tensor x, Tensor y, Tensor grad) | public static bool _ShapesFullySpecifiedAndEqual(Tensor x, Tensor y, Tensor grad) | ||||
| { | { | ||||
| return x.NDims == y.NDims && y.NDims == grad.NDims && x.NDims > -1; | |||||
| var x_shape = x._shape_tuple(); | |||||
| var y_shape = y._shape_tuple(); | |||||
| var grad_shape = grad._shape_tuple(); | |||||
| return Enumerable.SequenceEqual(x_shape, y_shape) && | |||||
| Enumerable.SequenceEqual(y_shape, grad_shape) && | |||||
| x.NDims != -1 && | |||||
| !x_shape.Contains(-1); | |||||
| } | } | ||||
| public static Tensor[] _SumGrad(Operation op, Tensor[] grads) | public static Tensor[] _SumGrad(Operation op, Tensor[] grads) | ||||
| @@ -2,6 +2,7 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.ComponentModel; | using System.ComponentModel; | ||||
| using System.Linq; | |||||
| using System.Text; | using System.Text; | ||||
| namespace Tensorflow | namespace Tensorflow | ||||
| @@ -16,6 +17,11 @@ namespace Tensorflow | |||||
| Console.WriteLine(obj.ToString()); | Console.WriteLine(obj.ToString()); | ||||
| } | } | ||||
| protected IEnumerable<int> range(int end) | |||||
| { | |||||
| return Enumerable.Range(0, end); | |||||
| } | |||||
| public static T New<T>(object args) where T : IPyClass | public static T New<T>(object args) where T : IPyClass | ||||
| { | { | ||||
| var instance = Activator.CreateInstance<T>(); | var instance = Activator.CreateInstance<T>(); | ||||
| @@ -43,6 +43,8 @@ namespace Tensorflow | |||||
| public IntPtr buffer => _handle == IntPtr.Zero ? IntPtr.Zero : c_api.TF_TensorData(_handle); | public IntPtr buffer => _handle == IntPtr.Zero ? IntPtr.Zero : c_api.TF_TensorData(_handle); | ||||
| public int num_consumers(TF_Output oper_out) => _handle == IntPtr.Zero ? 0 : c_api.TF_OperationOutputNumConsumers(oper_out); | public int num_consumers(TF_Output oper_out) => _handle == IntPtr.Zero ? 0 : c_api.TF_OperationOutputNumConsumers(oper_out); | ||||
| private TF_Output? _tf_output; | |||||
| public long[] shape | public long[] shape | ||||
| { | { | ||||
| get | get | ||||
| @@ -123,7 +125,10 @@ namespace Tensorflow | |||||
| public TF_Output _as_tf_output() | public TF_Output _as_tf_output() | ||||
| { | { | ||||
| return new TF_Output(op, value_index); | |||||
| if(!_tf_output.HasValue) | |||||
| _tf_output = new TF_Output(op, value_index); | |||||
| return _tf_output.Value; | |||||
| } | } | ||||
| public T[] Data<T>() | public T[] Data<T>() | ||||
| @@ -1,6 +1,8 @@ | |||||
| using NumSharp.Core; | |||||
| using Newtonsoft.Json; | |||||
| using NumSharp.Core; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | |||||
| using System.Text; | using System.Text; | ||||
| using Tensorflow; | using Tensorflow; | ||||
| using TensorFlowNET.Examples.Utility; | using TensorFlowNET.Examples.Utility; | ||||
| @@ -26,8 +28,6 @@ namespace TensorFlowNET.Examples | |||||
| private void PrepareData() | private void PrepareData() | ||||
| { | { | ||||
| //var mnist = MnistDataSet.read_data_sets("logistic_regression", one_hot: true); | |||||
| // tf Graph Input | // tf Graph Input | ||||
| var x = tf.placeholder(tf.float32, new TensorShape(-1, 784)); // mnist data image of shape 28*28=784 | var x = tf.placeholder(tf.float32, new TensorShape(-1, 784)); // mnist data image of shape 28*28=784 | ||||
| var y = tf.placeholder(tf.float32, new TensorShape(-1, 10)); // 0-9 digits recognition => 10 classes | var y = tf.placeholder(tf.float32, new TensorShape(-1, 10)); // 0-9 digits recognition => 10 classes | ||||
| @@ -49,13 +49,37 @@ namespace TensorFlowNET.Examples | |||||
| // Gradient Descent | // Gradient Descent | ||||
| var optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost); | var optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost); | ||||
| //var new_saver = tf.train.import_meta_graph("logistic_regression.meta.bin"); | |||||
| /*var text = JsonConvert.SerializeObject(tf.get_default_graph(), new JsonSerializerSettings | |||||
| { | |||||
| Formatting = Formatting.Indented | |||||
| });*/ | |||||
| // Initialize the variables (i.e. assign their default value) | // Initialize the variables (i.e. assign their default value) | ||||
| var init = tf.global_variables_initializer(); | var init = tf.global_variables_initializer(); | ||||
| with(tf.Session(), sess => | with(tf.Session(), sess => | ||||
| { | { | ||||
| var mnist = MnistDataSet.read_data_sets("logistic_regression", one_hot: true); | |||||
| // Run the initializer | // Run the initializer | ||||
| sess.run(init); | sess.run(init); | ||||
| // Training cycle | |||||
| foreach(var epoch in range(training_epochs)) | |||||
| { | |||||
| var avg_cost = 0.0f; | |||||
| var total_batch = (int)(mnist.train.num_examples / batch_size); | |||||
| // Loop over all batches | |||||
| foreach (var i in range(total_batch)) | |||||
| { | |||||
| var (batch_xs, batch_ys) = mnist.train.next_batch(batch_size); | |||||
| // Run optimization op (backprop) and cost op (to get loss value) | |||||
| /*sess.run(optimizer, | |||||
| new FeedItem(x, batch_xs), | |||||
| new FeedItem(y, batch_ys));*/ | |||||
| } | |||||
| } | |||||
| }); | }); | ||||
| } | } | ||||
| } | } | ||||
| @@ -9,10 +9,15 @@ namespace TensorFlowNET.Examples.Utility | |||||
| public class DataSet | public class DataSet | ||||
| { | { | ||||
| private int _num_examples; | private int _num_examples; | ||||
| public int num_examples => _num_examples; | |||||
| private int _epochs_completed; | private int _epochs_completed; | ||||
| public int epochs_completed => _epochs_completed; | |||||
| private int _index_in_epoch; | private int _index_in_epoch; | ||||
| public int index_in_epoch => _index_in_epoch; | |||||
| private NDArray _images; | private NDArray _images; | ||||
| public NDArray images => _images; | |||||
| private NDArray _labels; | private NDArray _labels; | ||||
| public NDArray labels => _labels; | |||||
| public DataSet(NDArray images, NDArray labels, TF_DataType dtype, bool reshape) | public DataSet(NDArray images, NDArray labels, TF_DataType dtype, bool reshape) | ||||
| { | { | ||||
| @@ -26,5 +31,33 @@ namespace TensorFlowNET.Examples.Utility | |||||
| _epochs_completed = 0; | _epochs_completed = 0; | ||||
| _index_in_epoch = 0; | _index_in_epoch = 0; | ||||
| } | } | ||||
| public (int, int) next_batch(int batch_size, bool fake_data = false, bool shuffle = true) | |||||
| { | |||||
| var start = _index_in_epoch; | |||||
| // Shuffle for the first epoch | |||||
| if(_epochs_completed == 0 && start == 0 && shuffle) | |||||
| { | |||||
| var perm0 = np.arange(_num_examples); | |||||
| np.random.shuffle(perm0); | |||||
| _images = images[perm0]; | |||||
| _labels = labels[perm0]; | |||||
| } | |||||
| // Go to the next epoch | |||||
| if (start + batch_size > _num_examples) | |||||
| { | |||||
| // Finished epoch | |||||
| _epochs_completed += 1; | |||||
| throw new NotImplementedException("next_batch"); | |||||
| } | |||||
| else | |||||
| { | |||||
| _index_in_epoch += batch_size; | |||||
| var end = _index_in_epoch; | |||||
| return (_images[np.arange(start, end)], _labels[np.arange(start, end)]); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||