@@ -11,7 +11,7 @@ namespace Tensorflow.Eager | |||
Tensor[] inputs, | |||
object[] attrs, | |||
Tensor[] results, | |||
Func<BackwardFunction> getBackwardFunction = null) | |||
BackwardFunction backwardFunction = null) | |||
{ | |||
bool should_record = ShouldRecord(inputs); | |||
@@ -28,9 +28,9 @@ namespace Tensorflow.Eager | |||
} | |||
if (!should_record) return should_record; | |||
tf.Logger.Debug($"RecordGradient: op_name={op_name}"); | |||
// tf.Logger.Debug($"RecordGradient: op_name={op_name}"); | |||
Tensor[] op_outputs; | |||
/*Tensor[] op_outputs = null; | |||
var unused_output_indices = gradient_exclustions.OpGradientUnusedOutputIndices(op_name); | |||
if (unused_output_indices != null) | |||
{ | |||
@@ -44,7 +44,7 @@ namespace Tensorflow.Eager | |||
else | |||
op_outputs = results; | |||
Tensor[] op_inputs; | |||
Tensor[] op_inputs = null; | |||
var unused_input_indices = gradient_exclustions.OpGradientUnusedInputIndices(op_name); | |||
if (unused_input_indices != null) | |||
{ | |||
@@ -56,22 +56,14 @@ namespace Tensorflow.Eager | |||
} | |||
} | |||
else | |||
op_inputs = inputs; | |||
op_inputs = inputs;*/ | |||
TapeSetRecordOperation(op_name, inputs, results, | |||
getBackwardFunction ?? GetBackwradFunction(op_name, inputs, attrs, results)); | |||
backwardFunction = backwardFunction ?? GetGradientFunction(op_name, inputs, attrs, results); | |||
TapeSetRecordOperation(op_name, inputs, results, backwardFunction); | |||
return true; | |||
} | |||
Func<BackwardFunction> GetBackwradFunction(string op_name, | |||
Tensor[] op_inputs, | |||
object[] attrs, | |||
Tensor[] op_outputs) | |||
{ | |||
return () => GetGradientFunction(op_name, op_inputs, attrs, op_outputs); | |||
} | |||
BackwardFunction GetGradientFunction(string op_name, | |||
Tensor[] op_inputs, | |||
object[] attrs, | |||
@@ -1,7 +1,6 @@ | |||
using System; | |||
using Tensorflow.Gradients; | |||
using static Tensorflow.Binding; | |||
using static Tensorflow.tensorflow; | |||
namespace Tensorflow.Eager | |||
{ | |||
@@ -10,7 +9,7 @@ namespace Tensorflow.Eager | |||
void TapeSetRecordBackprop(string op_type, | |||
Tensor[] input_tensors, | |||
TapeTensor[] output_tensors, | |||
Func<BackwardFunction> backward_function_getter) | |||
BackwardFunction backward_function) | |||
{ | |||
if (!CouldBackprop()) | |||
{ | |||
@@ -19,8 +18,7 @@ namespace Tensorflow.Eager | |||
foreach (var tape in tf.GetTapeSet()) | |||
{ | |||
tape.RecordOperation(op_type, input_tensors, output_tensors, | |||
backward_function_getter); | |||
tape.RecordOperation(op_type, input_tensors, output_tensors, backward_function); | |||
} | |||
} | |||
} | |||
@@ -9,7 +9,7 @@ namespace Tensorflow.Eager | |||
bool TapeSetRecordForwardprop(string op_type, | |||
Tensor[] input_tensors, | |||
TapeTensor[] output_tensors, | |||
Func<BackwardFunction> backward_function_getter) | |||
BackwardFunction backward_function_getter) | |||
{ | |||
if (!CouldForwardprop()) | |||
{ | |||
@@ -10,16 +10,16 @@ namespace Tensorflow.Eager | |||
public bool TapeSetRecordOperation(string op_type, | |||
Tensor[] input_tensors, | |||
Tensor[] output_tensors, | |||
Func<BackwardFunction> backward_function_getter) | |||
BackwardFunction backward_function) | |||
{ | |||
var output_info = output_tensors.Select(x => new TapeTensor(x)).ToArray(); | |||
if (!TapeSetRecordForwardprop(op_type, input_tensors, output_info, | |||
backward_function_getter)) | |||
backward_function)) | |||
return false; | |||
TapeSetRecordBackprop(op_type, input_tensors, output_info, | |||
backward_function_getter); | |||
backward_function); | |||
return true; | |||
} | |||
@@ -9,7 +9,8 @@ namespace Tensorflow.Eager | |||
{ | |||
Tensor[] Execute(Context ctx, string op_name, | |||
int num_outputs, | |||
Tensor[] inputs, object[] attrs, | |||
Tensor[] inputs, | |||
object[] attrs, | |||
string name = null); | |||
(TF_DataType, Tensor[]) ArgsToMatchingEager(Context ctx, | |||
@@ -34,7 +35,7 @@ namespace Tensorflow.Eager | |||
Tensor[] inputs, | |||
object[] attrs, | |||
Tensor[] results, | |||
Func<BackwardFunction> getBackwardFunction = null); | |||
BackwardFunction getBackwardFunction = null); | |||
bool MustRecordGradient(); | |||
@@ -47,7 +47,7 @@ namespace Tensorflow.Functions | |||
{ | |||
var (backward_function, to_record) = _wrap_backward_function(_forward_graph, _backward, flat_outputs); | |||
tf.Runner.RecordGradient(_forward.Name, inference_args, new object[0], to_record, | |||
getBackwardFunction: () => backward_function); | |||
getBackwardFunction: backward_function); | |||
} | |||
/// <summary> | |||
@@ -5,7 +5,7 @@ namespace Tensorflow.Gradients | |||
{ | |||
public class BackpropInitialState | |||
{ | |||
public OpTape<BackwardFunction, TapeTensor> op_tape { get; set; } | |||
public OpTape op_tape { get; set; } | |||
/// <summary> | |||
/// Map from tensor to how many references still exist for this tensor in | |||
/// the tape. | |||
@@ -19,7 +19,7 @@ namespace Tensorflow.Gradients | |||
public BackpropInitialState() | |||
{ | |||
op_tape = new OpTape<BackwardFunction, TapeTensor>(); | |||
op_tape = new OpTape(); | |||
tensor_usage_counts = new UnorderedMap<Tensor, long>(); | |||
op_missing_tensor = new UnorderedMap<Tensor, long>(); | |||
} | |||
@@ -13,7 +13,7 @@ namespace Tensorflow.Gradients | |||
void RecordOperation(string op_type, | |||
Tensor[] input_tensors, | |||
TapeTensor[] output_tensors, | |||
Func<BackwardFunction> backward_function_getter); | |||
BackwardFunction backward_function); | |||
void VariableAccessed(ResourceVariable variable); | |||
@@ -5,10 +5,7 @@ namespace Tensorflow.Gradients | |||
/// <summary> | |||
/// Map from operation-id to tape entry. | |||
/// </summary> | |||
/// <typeparam name="BackwardFunction"></typeparam> | |||
/// <typeparam name="TapeTensor"></typeparam> | |||
public class OpTape<BackwardFunction, TapeTensor> : | |||
UnorderedMap<Tensor, OpTapeEntry<BackwardFunction, TapeTensor>> | |||
public class OpTape : UnorderedMap<Tensor, OpTapeEntry> | |||
{ | |||
} | |||
@@ -5,9 +5,7 @@ namespace Tensorflow.Gradients | |||
/// <summary> | |||
/// Represents an entry in the tape. | |||
/// </summary> | |||
/// <typeparam name="BackwardFunction"></typeparam> | |||
/// <typeparam name="TapeTensor"></typeparam> | |||
public class OpTapeEntry<BackwardFunction, TapeTensor> | |||
public class OpTapeEntry | |||
{ | |||
public string op_type { get; set; } | |||
public TapeTensor[] output_tensor_info { get; set; } | |||
@@ -1,5 +1,4 @@ | |||
using System.Collections.Generic; | |||
using static Tensorflow.tensorflow; | |||
namespace Tensorflow.Gradients | |||
{ | |||
@@ -9,7 +8,7 @@ namespace Tensorflow.Gradients | |||
List<long> unneeded_gradients, | |||
List<Tensor> output_gradients) | |||
{ | |||
var grads = new Tensor[output_gradients.Count]; | |||
// var grads = new Tensor[output_gradients.Count]; | |||
var result = backward_function(output_gradients.ToArray(), | |||
unneeded_gradients.ToArray()); | |||
@@ -2,24 +2,22 @@ | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using Tensorflow.Util; | |||
using static Tensorflow.tensorflow; | |||
namespace Tensorflow.Gradients | |||
{ | |||
public partial class Tape | |||
{ | |||
int kMinAggregateCount = 4; | |||
int kMinAggregateBytes = 128 * 1024 * 1024; | |||
// int kMinAggregateCount = 4; | |||
// int kMinAggregateBytes = 128 * 1024 * 1024; | |||
public Tensor[] ComputeGradient(Tensor[] target_tensor_ids, | |||
Tensor[] source_tensor_ids, | |||
UnorderedMap<Tensor, TapeTensor> sources_that_are_targets, | |||
Tensor[] output_gradients) | |||
{ | |||
var result = new List<Tensor>(source_tensor_ids.Length); | |||
var sources_set = new UnorderedSet<Tensor>(source_tensor_ids); | |||
var gradients_size = new UnorderedMap<Tensor, long>(); | |||
// var gradients_size = new UnorderedMap<Tensor, long>(); | |||
var functionsAcceptingNoneForIndicesMap = FunctionsAcceptingNoneForIndicesMap(); | |||
var state = PrepareBackprop( | |||
target_tensor_ids, tensor_tape_, op_tape_, sources_set, _persistent); | |||
var op_stack = InitialStack(state.op_tape, state.op_missing_tensor); | |||
@@ -54,7 +52,7 @@ namespace Tensorflow.Gradients | |||
var id = trace.output_tensor_info[i].GetTensor(); | |||
if (!gradients.find(id, out var grad_it)) | |||
{ | |||
if (FunctionsAcceptingNoneForIndicesMap().find(trace.op_type, out var func_name_it) && | |||
if (functionsAcceptingNoneForIndicesMap.find(trace.op_type, out var func_name_it) && | |||
func_name_it.find(i)) | |||
{ | |||
out_gradients.Add(null); | |||
@@ -76,8 +74,8 @@ namespace Tensorflow.Gradients | |||
gradients.Remove(id); | |||
else | |||
{ | |||
grad_it.Clear(); | |||
grad_it.Add(new_gradients); | |||
// grad_it.Clear(); | |||
// grad_it.Add(new_gradients); | |||
// vspace.MarkAsResult(new_gradients); | |||
} | |||
out_gradients.Add(new_gradients); | |||
@@ -87,18 +85,17 @@ namespace Tensorflow.Gradients | |||
Tensor[] in_gradients; | |||
if (any_gradient_nonzero) | |||
{ | |||
foreach (var i in zero_indices) | |||
out_gradients[i] = trace.output_tensor_info[i].ZerosLike(); | |||
// foreach (var i in zero_indices) | |||
// out_gradients[i] = trace.output_tensor_info[i].ZerosLike(); | |||
in_gradients = CallBackwardFunction(trace.backward_function, | |||
unneeded_gradients, | |||
out_gradients); | |||
in_gradients = trace.backward_function(out_gradients.ToArray(), unneeded_gradients.ToArray()); | |||
if (in_gradients.Count() != trace.input_tensor_id.Count()) | |||
throw new RuntimeError($"Recorded operation '{trace.op_type}' returned too few gradients. Expected {trace.input_tensor_id.Length} but received {in_gradients.Count()}"); | |||
if (!_persistent) | |||
{ | |||
// trace.backward_function_deleter(trace.backward_function); | |||
trace.backward_function = null; | |||
} | |||
} | |||
else | |||
@@ -113,7 +110,7 @@ namespace Tensorflow.Gradients | |||
{ | |||
var unaggregated_grads = gradients[id]; | |||
unaggregated_grads.Add(in_gradients[i]); | |||
if (unaggregated_grads.Count > kMinAggregateCount) | |||
/*if (unaggregated_grads.Count > kMinAggregateCount) | |||
{ | |||
if (!gradients_size.find(id, out var size)) | |||
{ | |||
@@ -125,7 +122,7 @@ namespace Tensorflow.Gradients | |||
{ | |||
throw new NotImplementedException(""); | |||
} | |||
} | |||
}*/ | |||
} | |||
if (!state.tensor_usage_counts.find(id)) | |||
@@ -162,36 +159,21 @@ namespace Tensorflow.Gradients | |||
if (state.op_tape.Count > 0) | |||
throw new RuntimeError("Invalid tape state."); | |||
var used_gradient_ids = new List<Tensor>(source_tensor_ids.Length); | |||
var result = new Tensor[source_tensor_ids.Length]; | |||
var j = 0; | |||
foreach (var id in source_tensor_ids) | |||
{ | |||
if (!gradients.find(id, out var grad_it)) | |||
result.Add(null); | |||
else | |||
if (gradients.find(id, out var grad_it)) | |||
{ | |||
if (grad_it.Count > 1) | |||
{ | |||
var grad = gen_math_ops.add_n(grad_it.ToArray()); | |||
grad_it.Clear(); | |||
grad_it.Add(grad); | |||
} | |||
result.Add(grad_it[0]); | |||
used_gradient_ids.Add(id); | |||
result[j] = gen_math_ops.add_n(grad_it.ToArray()); | |||
else | |||
result[j] = grad_it[0]; | |||
} | |||
j++; | |||
} | |||
/*foreach(var grad_pair in gradients) | |||
{ | |||
if(!used_gradient_ids.Contains(grad_pair.Key)) | |||
{ | |||
foreach(var g in grad_pair.Value) | |||
{ | |||
vspace.DeleteGradient(g); | |||
} | |||
} | |||
}*/ | |||
return result.ToArray(); | |||
return result; | |||
} | |||
UnorderedMap<string, UnorderedSet<int>> FunctionsAcceptingNoneForIndicesMap() | |||
@@ -207,7 +189,7 @@ namespace Tensorflow.Gradients | |||
UnorderedMap<Tensor, TapeTensor> sources_that_are_targets, | |||
Tensor[] output_gradients, | |||
TensorTape tensor_tape, | |||
OpTape<BackwardFunction, TapeTensor> op_tape) | |||
OpTape op_tape) | |||
{ | |||
var result = new UnorderedMapEnumerable<Tensor, List<Tensor>>(); | |||
for (int i = 0; i < target_tensor_ids.Length; ++i) | |||
@@ -253,7 +235,7 @@ namespace Tensorflow.Gradients | |||
return result; | |||
} | |||
Queue<Tensor> InitialStack(OpTape<BackwardFunction, TapeTensor> op_tape, | |||
Queue<Tensor> InitialStack(OpTape op_tape, | |||
UnorderedMap<Tensor, long> op_missing_tensor) | |||
{ | |||
var result = new Queue<Tensor>(); | |||
@@ -8,7 +8,7 @@ namespace Tensorflow.Gradients | |||
{ | |||
public BackpropInitialState PrepareBackprop(Tensor[] target, | |||
TensorTape tensor_tape, | |||
OpTape<BackwardFunction, TapeTensor> op_tape, | |||
OpTape op_tape, | |||
UnorderedSet<Tensor> sources_set, | |||
bool persistent_tape) | |||
{ | |||
@@ -16,7 +16,7 @@ namespace Tensorflow.Gradients | |||
public void RecordOperation(string op_type, | |||
Tensor[] input_tensors, | |||
TapeTensor[] output_tensors, | |||
Func<BackwardFunction> backward_function_getter) | |||
BackwardFunction backward_function) | |||
{ | |||
if (!ShouldRecord(input_tensors)) | |||
return; | |||
@@ -32,12 +32,12 @@ namespace Tensorflow.Gradients | |||
tensor_usage_[o.GetTensor()] = 1; | |||
} | |||
op_tape_[op_id] = new OpTapeEntry<BackwardFunction, TapeTensor> | |||
op_tape_[op_id] = new OpTapeEntry | |||
{ | |||
op_type = op_type, | |||
output_tensor_info = output_tensors, | |||
input_tensor_id = input_tensors, | |||
backward_function = backward_function_getter() | |||
backward_function = backward_function | |||
}; | |||
} | |||
} | |||
@@ -15,7 +15,7 @@ namespace Tensorflow.Gradients | |||
bool _recording; | |||
bool _created_eagerly; | |||
TensorTape tensor_tape_; | |||
OpTape<BackwardFunction, TapeTensor> op_tape_; | |||
OpTape op_tape_; | |||
/// <summary> | |||
/// A deque-backed stack, whose element references are not invalidated by | |||
@@ -28,7 +28,7 @@ namespace Tensorflow.Gradients | |||
_persistent = persistent; | |||
_created_eagerly = tf.Context.executing_eagerly(); | |||
tensor_tape_ = new TensorTape(); | |||
op_tape_ = new OpTape<BackwardFunction, TapeTensor>(); | |||
op_tape_ = new OpTape(); | |||
tensor_usage_ = new UnorderedMap<Tensor, long>(); | |||
if(_created_eagerly) | |||
tf.Context.start_step(); | |||
@@ -161,7 +161,7 @@ namespace Tensorflow.Graphs | |||
tf.Runner.RecordGradient("captured_value", | |||
new[] { graph_const }, null, | |||
new[] { tensor }, | |||
getBackwardFunction: () => _backward_function_wrapper | |||
getBackwardFunction: _backward_function_wrapper | |||
/*getForwardFunction: forward_function*/); | |||
return graph_const; | |||
@@ -191,7 +191,7 @@ namespace Tensorflow.Graphs | |||
tf.Runner.RecordGradient("captured_value", | |||
new[] { placeholder }, null, | |||
new[] { tensor }, | |||
getBackwardFunction: () => _backward_function_wrapper | |||
getBackwardFunction: _backward_function_wrapper | |||
/*getForwardFunction: forward_function*/); | |||
return placeholder; | |||
@@ -15,6 +15,8 @@ | |||
******************************************************************************/ | |||
using System; | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using Tensorflow.Contexts; | |||
using static Tensorflow.Binding; | |||
@@ -215,7 +215,7 @@ namespace Tensorflow | |||
/// Evaluates this tensor in a `Session`. | |||
/// </summary> | |||
/// <param name="feed_dict">A dictionary that maps `Tensor` objects to feed values.</param> | |||
/// <returns>A <see cref="NumSharp"/> array corresponding to the value of this tensor.</returns> | |||
/// <returns>A <see cref="NumPy"/> array corresponding to the value of this tensor.</returns> | |||
public NDArray eval(params FeedItem[] feed_dict) | |||
{ | |||
return ops._eval_using_default_session(this, feed_dict, graph); | |||
@@ -226,7 +226,7 @@ namespace Tensorflow | |||
/// </summary> | |||
/// <param name="feed_dict">A dictionary that maps `Tensor` objects to feed values.</param> | |||
/// <param name="session">The `Session` to be used to evaluate this tensor.</param> | |||
/// <returns>A <see cref="NumSharp"/> array corresponding to the value of this tensor.</returns> | |||
/// <returns>A <see cref="NumPy"/> array corresponding to the value of this tensor.</returns> | |||
public NDArray eval(Session session, params FeedItem[] feed_dict) | |||
{ | |||
return ops._eval_using_default_session(this, feed_dict, graph, session); | |||
@@ -14,7 +14,6 @@ | |||
limitations under the License. | |||
******************************************************************************/ | |||
using System.Collections.Generic; | |||
using Serilog; | |||
using Serilog.Core; | |||
using Tensorflow.Contexts; | |||