| @@ -32,8 +32,19 @@ namespace Tensorflow | |||||
| { | { | ||||
| public static T2 get<T1, T2>(this Dictionary<T1, T2> dict, T1 key) | public static T2 get<T1, T2>(this Dictionary<T1, T2> dict, T1 key) | ||||
| => key == null ? | => key == null ? | ||||
| default(T2) : | |||||
| (dict.ContainsKey(key) ? dict[key] : default(T2)); | |||||
| default : | |||||
| (dict.ContainsKey(key) ? dict[key] : default); | |||||
| public static void Update<T>(this IList<T> list, T element) | |||||
| { | |||||
| var index = list.IndexOf(element); | |||||
| if (index < 0) | |||||
| list.Add(element); | |||||
| else | |||||
| { | |||||
| list[index] = element; | |||||
| } | |||||
| } | |||||
| public static void add<T>(this IList<T> list, T element) | public static void add<T>(this IList<T> list, T element) | ||||
| => list.Add(element); | => list.Add(element); | ||||
| @@ -155,6 +155,16 @@ namespace Tensorflow.Keras | |||||
| return array_ops.pad(x, pattern); | return array_ops.pad(x, pattern); | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Method to evaluate a tensor in eager or in a tf.function. | |||||
| /// </summary> | |||||
| /// <param name="outputs"></param> | |||||
| /// <returns></returns> | |||||
| public Tensor eval_in_eager_or_function(Tensor outputs) | |||||
| { | |||||
| throw new NotImplementedException(""); | |||||
| } | |||||
| public class _DummyEagerGraph | public class _DummyEagerGraph | ||||
| { } | { } | ||||
| } | } | ||||
| @@ -1,7 +1,6 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Security.Cryptography.X509Certificates; | |||||
| using System.Text; | using System.Text; | ||||
| using Tensorflow.Keras.ArgsDefinition; | using Tensorflow.Keras.ArgsDefinition; | ||||
| using Tensorflow.Keras.Utils; | using Tensorflow.Keras.Utils; | ||||
| @@ -69,6 +68,11 @@ namespace Tensorflow.Keras.Engine | |||||
| _input_coordinates.append(new KerasHistory(layer, node_index, tensor_index, x)); | _input_coordinates.append(new KerasHistory(layer, node_index, tensor_index, x)); | ||||
| } | } | ||||
| } | } | ||||
| protected override Tensors call(Tensors inputs, Tensor state = null, bool is_training = false) | |||||
| { | |||||
| return base.call(inputs, state, is_training); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -20,8 +20,6 @@ namespace Tensorflow.Keras.Engine | |||||
| this.node_index = node_index; | this.node_index = node_index; | ||||
| this.tensor_index = tensor_index; | this.tensor_index = tensor_index; | ||||
| this.tensor = tensor; | this.tensor = tensor; | ||||
| Layer.KerasHistories.Add(this); | |||||
| Console.WriteLine(tensor.name); | |||||
| } | } | ||||
| public void Deconstruct(out Layer layer, out int node_index, out int tensor_index) | public void Deconstruct(out Layer layer, out int node_index, out int tensor_index) | ||||
| @@ -89,7 +89,6 @@ namespace Tensorflow.Keras.Engine | |||||
| ThreadLocal<CallContext> callContext; | ThreadLocal<CallContext> callContext; | ||||
| public CallContext CallContext => callContext.Value; | public CallContext CallContext => callContext.Value; | ||||
| public static List<KerasHistory> KerasHistories = new List<KerasHistory>(); | |||||
| public Layer(LayerArgs args) | public Layer(LayerArgs args) | ||||
| { | { | ||||
| @@ -125,29 +124,16 @@ namespace Tensorflow.Keras.Engine | |||||
| } | } | ||||
| public void SetConnectivityMetadata(Tensors inputs, Tensors outputs) | public void SetConnectivityMetadata(Tensors inputs, Tensors outputs) | ||||
| { | |||||
| } | |||||
| => _set_connectivity_metadata_(inputs, outputs); | |||||
| private Tensors _set_connectivity_metadata_(Tensors inputs, Tensors outputs) | private Tensors _set_connectivity_metadata_(Tensors inputs, Tensors outputs) | ||||
| { | { | ||||
| /*var returnOutputs = new List<Tensor>(); | |||||
| foreach(var x in outputs) | |||||
| { | |||||
| if (inputs.Contains(x)) | |||||
| { | |||||
| } | |||||
| returnOutputs.Add(x); | |||||
| }*/ | |||||
| new Node(this, new NodeArgs | new Node(this, new NodeArgs | ||||
| { | { | ||||
| InputTensors = inputs, | InputTensors = inputs, | ||||
| Outputs = outputs | Outputs = outputs | ||||
| }); | }); | ||||
| //_add_inbound_node(input_tensors: inputs, output_tensors: outputs); | |||||
| return outputs; | return outputs; | ||||
| } | } | ||||
| @@ -52,6 +52,8 @@ namespace Tensorflow.Keras.Engine | |||||
| layer.InboundNodes.Add(this); | layer.InboundNodes.Add(this); | ||||
| foreach (var kt in kerasInputs) | foreach (var kt in kerasInputs) | ||||
| { | { | ||||
| if (kt.KerasHistory == null) | |||||
| continue; | |||||
| var inbound_layer = kt.KerasHistory.layer; | var inbound_layer = kt.KerasHistory.layer; | ||||
| if (inbound_layer != null) | if (inbound_layer != null) | ||||
| inbound_layer.OutboundNodes.Add(this); | inbound_layer.OutboundNodes.Add(this); | ||||
| @@ -8,12 +8,12 @@ namespace Tensorflow.Keras.Engine | |||||
| public class TensorFlowOpLayer : Layer | public class TensorFlowOpLayer : Layer | ||||
| { | { | ||||
| TensorFlowOpLayerArgs args; | TensorFlowOpLayerArgs args; | ||||
| string _TF_OP_LAYER_NAME_PREFIX = ""; | |||||
| static string TF_OP_LAYER_NAME_PREFIX = "tf_op_layer_"; | |||||
| public TensorFlowOpLayer(TensorFlowOpLayerArgs args) | public TensorFlowOpLayer(TensorFlowOpLayerArgs args) | ||||
| : base(new LayerArgs | : base(new LayerArgs | ||||
| { | { | ||||
| Name = "tf_op_layer_" + args.Name, | |||||
| Name = TF_OP_LAYER_NAME_PREFIX + args.Name, | |||||
| Trainable = args.Trainable, | Trainable = args.Trainable, | ||||
| DType = args.DType, | DType = args.DType, | ||||
| Autocast = false | Autocast = false | ||||
| @@ -8,6 +8,7 @@ using Tensorflow.Keras.Datasets; | |||||
| using Tensorflow.Keras.Engine; | using Tensorflow.Keras.Engine; | ||||
| using Tensorflow.Keras.Layers; | using Tensorflow.Keras.Layers; | ||||
| using Tensorflow.Keras.Losses; | using Tensorflow.Keras.Losses; | ||||
| using Tensorflow.Keras.Optimizers; | |||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| namespace Tensorflow | namespace Tensorflow | ||||
| @@ -22,6 +23,7 @@ namespace Tensorflow | |||||
| public Activations activations { get; } = new Activations(); | public Activations activations { get; } = new Activations(); | ||||
| public Preprocessing preprocessing { get; } = new Preprocessing(); | public Preprocessing preprocessing { get; } = new Preprocessing(); | ||||
| public BackendImpl backend { get; } = new BackendImpl(); | public BackendImpl backend { get; } = new BackendImpl(); | ||||
| public OptimizerApi optimizers { get; } = new OptimizerApi(); | |||||
| public Sequential Sequential(List<Layer> layers = null, | public Sequential Sequential(List<Layer> layers = null, | ||||
| string name = null) | string name = null) | ||||
| @@ -0,0 +1,33 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace Tensorflow.Keras.Optimizers | |||||
| { | |||||
| public class OptimizerApi | |||||
| { | |||||
| /// <summary> | |||||
| /// Adam optimization is a stochastic gradient descent method that is based on | |||||
| /// adaptive estimation of first-order and second-order moments. | |||||
| /// </summary> | |||||
| /// <param name="learning_rate"></param> | |||||
| /// <param name="beta_1"></param> | |||||
| /// <param name="beta_2"></param> | |||||
| /// <param name="epsilon"></param> | |||||
| /// <param name="amsgrad"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public OptimizerV2 Adam(float learning_rate = 0.001f, | |||||
| float beta_1 = 0.9f, | |||||
| float beta_2 = 0.999f, | |||||
| float epsilon = 1e-7f, | |||||
| bool amsgrad = false, | |||||
| string name = "Adam") | |||||
| => new Adam(learning_rate: learning_rate, | |||||
| beta_1: beta_1, | |||||
| beta_2: beta_2, | |||||
| epsilon: epsilon, | |||||
| amsgrad: amsgrad, | |||||
| name: name); | |||||
| } | |||||
| } | |||||
| @@ -142,26 +142,39 @@ namespace Tensorflow.Keras.Utils | |||||
| layer_inputs.Add(op_input); | layer_inputs.Add(op_input); | ||||
| else | else | ||||
| { | { | ||||
| tf_with(ops.init_scope(), delegate | |||||
| { | |||||
| } | |||||
| // recursively | |||||
| CreateKerasHistoryHelper(layer_inputs, processed_ops, created_layers); | |||||
| var op_layer = new TensorFlowOpLayer(new TensorFlowOpLayerArgs | |||||
| { | |||||
| NodeDef = op.node_def, | |||||
| Name = op.name | |||||
| }); | |||||
| created_layers.Add(op_layer); | |||||
| op_layer.SetConnectivityMetadata(layer_inputs, op.outputs); | |||||
| }); | |||||
| } | |||||
| } | } | ||||
| // recursively | |||||
| CreateKerasHistoryHelper(layer_inputs, processed_ops, created_layers); | |||||
| var op_layer = new TensorFlowOpLayer(new TensorFlowOpLayerArgs | |||||
| { | |||||
| NodeDef = op.node_def, | |||||
| Name = op.name | |||||
| }); | |||||
| created_layers.Add(op_layer); | |||||
| op_layer.SetConnectivityMetadata(layer_inputs, op.outputs); | |||||
| processed_ops.Add(op); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| // recusive | |||||
| static bool uses_keras_history(Tensor op_input) | static bool uses_keras_history(Tensor op_input) | ||||
| { | { | ||||
| return Layer.KerasHistories.Any(x => x.tensor.name == op_input.name); | |||||
| if (op_input.KerasHistory != null) | |||||
| return true; | |||||
| foreach (var input in op_input.op.inputs._inputs) | |||||
| if (uses_keras_history(input)) | |||||
| return true; | |||||
| return false; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -29,7 +29,7 @@ https://tensorflownet.readthedocs.io</Description> | |||||
| <FileVersion>0.21.0.0</FileVersion> | <FileVersion>0.21.0.0</FileVersion> | ||||
| <PackageLicenseFile>LICENSE</PackageLicenseFile> | <PackageLicenseFile>LICENSE</PackageLicenseFile> | ||||
| <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | ||||
| <SignAssembly>false</SignAssembly> | |||||
| <SignAssembly>true</SignAssembly> | |||||
| <AssemblyOriginatorKeyFile>Open.snk</AssemblyOriginatorKeyFile> | <AssemblyOriginatorKeyFile>Open.snk</AssemblyOriginatorKeyFile> | ||||
| <Platforms>AnyCPU;x64</Platforms> | <Platforms>AnyCPU;x64</Platforms> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||