| @@ -1,5 +1,6 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| @@ -19,14 +20,51 @@ namespace Tensorflow | |||
| public static void _GradientsHelper(object ys, | |||
| object xs, | |||
| List<Tensor> grad_ys = null, | |||
| object grad_ys = null, | |||
| string name = "gradients", | |||
| bool colocate_gradients_with_ops = false, | |||
| bool gate_gradients = false, | |||
| object stop_gradients = null, | |||
| Graph src_graph = null) | |||
| { | |||
| if (src_graph == null) | |||
| src_graph = ops.get_default_graph(); | |||
| var ys1 = _AsList(ys); | |||
| var xs1 = _AsList(xs); | |||
| List<Tensor> grad_ys1 = null; | |||
| List<Tensor> stop_gradients1 = stop_gradients == null ? new List<Tensor>() : _AsList(stop_gradients); | |||
| if (grad_ys == null) | |||
| grad_ys1 = ys1.Select(x => new Tensor(IntPtr.Zero)).ToList(); | |||
| else | |||
| grad_ys = _AsList(grad_ys); | |||
| var all = new List<Tensor>(); | |||
| all.AddRange(ys1); | |||
| all.AddRange(xs1); | |||
| all.AddRange(stop_gradients1); | |||
| all.AddRange(grad_ys1); | |||
| string grad_scope = ""; | |||
| using (var namescope = new ops.name_scope<Tensor>(name, "gradients", values: all)) | |||
| grad_scope = namescope; | |||
| } | |||
| private static List<Tensor> _AsList(object ys) | |||
| { | |||
| List<Tensor> ret = null; | |||
| switch (ys) | |||
| { | |||
| case Tensor value: | |||
| ret = new List<Tensor> { value }; | |||
| break; | |||
| case List<Tensor> value: | |||
| ret = value; | |||
| break; | |||
| } | |||
| return ret; | |||
| } | |||
| } | |||
| } | |||
| @@ -23,7 +23,8 @@ namespace Tensorflow | |||
| private int _next_id_counter; | |||
| private List<String> _unfetchable_ops = new List<string>(); | |||
| private string _name_stack; | |||
| public string _name_stack = ""; | |||
| public string old_stack = ""; | |||
| public string _graph_key; | |||
| public Status Status { get; } | |||
| @@ -168,23 +169,22 @@ namespace Tensorflow | |||
| public string name_scope(string name) | |||
| { | |||
| old_stack = _name_stack; | |||
| string new_stack = ""; | |||
| if (name.EndsWith("/")) | |||
| { | |||
| new_stack = ops._name_from_scope_name(name); | |||
| } | |||
| else | |||
| { | |||
| new_stack = unique_name(name); | |||
| } | |||
| _name_stack = new_stack; | |||
| return String.IsNullOrEmpty(new_stack) ? "" : new_stack + "/"; | |||
| } | |||
| public string unique_name(string name) | |||
| public string unique_name(string name, bool mark_as_used = true) | |||
| { | |||
| if (!String.IsNullOrEmpty(_name_stack)) | |||
| { | |||
| @@ -192,17 +192,45 @@ namespace Tensorflow | |||
| } | |||
| var name_key = name.ToLower(); | |||
| int i = 0; | |||
| if (_names_in_use.ContainsKey(name_key)) | |||
| { | |||
| _names_in_use[name_key]++; | |||
| foreach (var item in _names_in_use) | |||
| { | |||
| if (item.Key == name_key) | |||
| { | |||
| i = _names_in_use[name_key]; | |||
| break; | |||
| } | |||
| i++; | |||
| } | |||
| } | |||
| else | |||
| if (mark_as_used) | |||
| if (_names_in_use.ContainsKey(name_key)) | |||
| _names_in_use[name_key]++; | |||
| else | |||
| _names_in_use[name_key] = i + 1; | |||
| if (i > 0) | |||
| { | |||
| _names_in_use[name_key] = 1; | |||
| return name; | |||
| var base_name_key = name_key; | |||
| // Make sure the composed name key is not already used. | |||
| if (_names_in_use.ContainsKey(name_key)) | |||
| { | |||
| name_key = $"{base_name_key}_{i}"; | |||
| i += 1; | |||
| } | |||
| if (mark_as_used) | |||
| _names_in_use[name_key] = 1; | |||
| name = $"{name}_{i - 1}"; | |||
| } | |||
| return $"{name}_{_names_in_use[name_key]}"; | |||
| return name; | |||
| } | |||
| public TF_Output[] ReturnOutputs(IntPtr results) | |||
| @@ -20,7 +20,9 @@ namespace Tensorflow | |||
| name = op_type_name; | |||
| } | |||
| string scope = new ops.name_scope(name); | |||
| string scope = ""; | |||
| using (var namescope = new ops.name_scope<object>(name)) | |||
| scope = namescope; | |||
| var default_type_attr_map = new Dictionary<string, object>(); | |||
| foreach (var attr_def in op_def.Attr) | |||
| @@ -51,31 +51,36 @@ namespace Tensorflow | |||
| collections.Add(ops.GraphKeys.TRAINABLE_VARIABLES); | |||
| ops.init_scope(); | |||
| name = new ops.name_scope(name, "Variable", init_from_fn ? new List<object>() : new List<object> { initial_value }); | |||
| if (init_from_fn) | |||
| var values = init_from_fn ? new List<object>() : new List<object> { initial_value }; | |||
| using (var namescope = new ops.name_scope<object>(name, "Variable", values)) | |||
| { | |||
| name = namescope; | |||
| } | |||
| else | |||
| { | |||
| _initial_value = ops.convert_to_tensor(initial_value, name: "initial_value"); | |||
| } | |||
| if (init_from_fn) | |||
| { | |||
| var shape = _initial_value.shape; | |||
| dtype = _initial_value.dtype; | |||
| _variable = gen_state_ops.variable_v2(shape, dtype, name); | |||
| } | |||
| else | |||
| { | |||
| _initial_value = ops.convert_to_tensor(initial_value, name: "initial_value"); | |||
| } | |||
| // Manually overrides the variable's shape with the initial value's. | |||
| if (validate_shape) | |||
| { | |||
| var initial_value_shape = _initial_value.shape; | |||
| } | |||
| var shape = _initial_value.shape; | |||
| dtype = _initial_value.dtype; | |||
| _variable = gen_state_ops.variable_v2(shape, dtype, name); | |||
| // Manually overrides the variable's shape with the initial value's. | |||
| if (validate_shape) | |||
| { | |||
| var initial_value_shape = _initial_value.shape; | |||
| } | |||
| // If 'initial_value' makes use of other variables, make sure we don't | |||
| // have an issue if these other variables aren't initialized first by | |||
| // using their initialized_value() method. | |||
| // If 'initial_value' makes use of other variables, make sure we don't | |||
| // have an issue if these other variables aren't initialized first by | |||
| // using their initialized_value() method. | |||
| ops.add_to_collections(collections, this); | |||
| ops.add_to_collections(collections, this); | |||
| } | |||
| } | |||
| public Tensor _ref() | |||
| @@ -6,15 +6,16 @@ namespace Tensorflow | |||
| { | |||
| public partial class ops | |||
| { | |||
| public class name_scope | |||
| public class name_scope<T> : IDisposable | |||
| { | |||
| public string _name; | |||
| public string _default_name; | |||
| public object _values; | |||
| public Context _ctx; | |||
| public string _name_scope; | |||
| private object _g_manager; | |||
| public name_scope(string name, string default_name = "", List<object> values = null) | |||
| public name_scope(string name, string default_name = "", List<T> values = null) | |||
| { | |||
| _name = name; | |||
| _default_name = default_name; | |||
| @@ -31,11 +32,23 @@ namespace Tensorflow | |||
| _name = _default_name; | |||
| } | |||
| Graph g = null; | |||
| if (_values is List<Tensor> values) | |||
| g = _get_graph_from_inputs(values); | |||
| if (g == null) | |||
| g = get_default_graph(); | |||
| return g.name_scope(_name); ; | |||
| } | |||
| public void Dispose() | |||
| { | |||
| var g = get_default_graph(); | |||
| return g.name_scope(_name); | |||
| g._name_stack = g.old_stack; | |||
| } | |||
| public static implicit operator string(name_scope ns) | |||
| public static implicit operator string(name_scope<T> ns) | |||
| { | |||
| return ns._name_scope; | |||
| } | |||
| @@ -34,6 +34,17 @@ namespace Tensorflow | |||
| return tf.Graph(); | |||
| } | |||
| public static Graph _get_graph_from_inputs(List<Tensor> op_input_list, Graph graph = null) | |||
| { | |||
| foreach(var op_input in op_input_list) | |||
| { | |||
| // Determine if this is a valid graph_element. | |||
| var graph_element = op_input; | |||
| } | |||
| return get_default_graph(); | |||
| } | |||
| public static Tensor convert_to_tensor(object value, string name = "") | |||
| { | |||
| var nd = tensor_util.convert_to_numpy_ndarray(value); | |||