Browse Source

Add node to connectivity between two layers.

tags/v0.8.0
Oceania2018 6 years ago
parent
commit
d94c685dba
11 changed files with 141 additions and 19 deletions
  1. +4
    -2
      src/TensorFlowNET.Core/APIs/keras.layers.cs
  2. +6
    -0
      src/TensorFlowNET.Core/Keras/Engine/Sequential.cs
  3. +11
    -2
      src/TensorFlowNET.Core/Keras/Layers/Embedding.cs
  4. +12
    -1
      src/TensorFlowNET.Core/Keras/Layers/InputLayer.cs
  5. +23
    -9
      src/TensorFlowNET.Core/Keras/Layers/Layer.cs
  6. +71
    -0
      src/TensorFlowNET.Core/Keras/Layers/Node.cs
  7. +10
    -1
      src/TensorFlowNET.Core/Keras/Utils/base_layer_utils.cs
  8. +1
    -1
      src/TensorFlowNET.Core/Layers/Layer.cs
  9. +1
    -1
      src/TensorFlowNET.Core/TensorFlowNET.Core.csproj
  10. +1
    -1
      test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj
  11. +1
    -1
      test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj

+ 4
- 2
src/TensorFlowNET.Core/APIs/keras.layers.cs View File

@@ -18,7 +18,7 @@ namespace Tensorflow
embeddings_initializer, embeddings_initializer,
mask_zero); mask_zero);


public static InputLayer Input(int[] batch_shape = null,
public static Tensor[] Input(int[] batch_shape = null,
TF_DataType dtype = TF_DataType.DtInvalid, TF_DataType dtype = TF_DataType.DtInvalid,
string name = null, string name = null,
bool sparse = false, bool sparse = false,
@@ -35,7 +35,9 @@ namespace Tensorflow
sparse: sparse, sparse: sparse,
input_tensor: tensor); input_tensor: tensor);


throw new NotImplementedException("");
var outputs = input_layer.inbound_nodes[0].output_tensors;

return outputs;
} }
} }
} }


+ 6
- 0
src/TensorFlowNET.Core/Keras/Engine/Sequential.cs View File

@@ -33,6 +33,12 @@ namespace Tensorflow.Keras.Engine
batch_shape: batch_shape, batch_shape: batch_shape,
dtype: dtype, dtype: dtype,
name: layer._name + "_input"); name: layer._name + "_input");

// This will build the current layer
// and create the node connecting the current layer
// to the input layer we just created.
layer.__call__(x);
set_inputs = true;
} }
} }
} }


+ 11
- 2
src/TensorFlowNET.Core/Keras/Layers/Embedding.cs View File

@@ -9,6 +9,8 @@ namespace Tensorflow.Keras.Layers
private int input_dim; private int input_dim;
private int output_dim; private int output_dim;
private bool mask_zero; private bool mask_zero;
public RefVariable embeddings;
public IInitializer embeddings_initializer;


public Embedding(int input_dim, int output_dim, public Embedding(int input_dim, int output_dim,
IInitializer embeddings_initializer = null, IInitializer embeddings_initializer = null,
@@ -18,10 +20,17 @@ namespace Tensorflow.Keras.Layers
{ {
this.input_dim = input_dim; this.input_dim = input_dim;
this.output_dim = output_dim; this.output_dim = output_dim;
if (embeddings_initializer == null)
embeddings_initializer = tf.uniform_initializer;
this.embeddings_initializer = embeddings_initializer == null ? tf.uniform_initializer : embeddings_initializer;
this.mask_zero = mask_zero; this.mask_zero = mask_zero;
supports_masking = mask_zero; supports_masking = mask_zero;
} }

protected override void build(TensorShape input_shape)
{
embeddings = add_weight(shape: new int[] { input_dim, output_dim },
initializer: embeddings_initializer,
name: "embeddings");
built = true;
}
} }
} }

+ 12
- 1
src/TensorFlowNET.Core/Keras/Layers/InputLayer.cs View File

@@ -11,6 +11,7 @@ namespace Tensorflow.Keras.Layers
{ {
public bool sparse; public bool sparse;
public int? batch_size; public int? batch_size;
public bool is_placeholder;


public InputLayer(int[] input_shape = null, public InputLayer(int[] input_shape = null,
int? batch_size = null, int? batch_size = null,
@@ -24,7 +25,7 @@ namespace Tensorflow.Keras.Layers
this.batch_size = batch_size; this.batch_size = batch_size;
this.supports_masking = true; this.supports_masking = true;


if(input_tensor == null)
if (input_tensor == null)
{ {
var batch_input_shape = new int[] { batch_size.HasValue ? batch_size.Value : -1, -1 }; var batch_input_shape = new int[] { batch_size.HasValue ? batch_size.Value : -1, -1 };


@@ -39,7 +40,17 @@ namespace Tensorflow.Keras.Layers
dtype: dtype, dtype: dtype,
name: name); name: name);
} }

is_placeholder = true;
_batch_input_shape = batch_input_shape;
} }

new Node(this,
inbound_layers: new Layer[0],
node_indices: new int[0],
tensor_indices: new int[0],
input_tensors: new Tensor[] { input_tensor },
output_tensors: new Tensor[] { input_tensor });
} }
} }
} }

+ 23
- 9
src/TensorFlowNET.Core/Keras/Layers/Layer.cs View File

@@ -39,6 +39,12 @@ namespace Tensorflow.Keras.Layers
protected List<Operation> _updates; protected List<Operation> _updates;
public int[] _batch_input_shape; public int[] _batch_input_shape;


private List<Node> _inbound_nodes;
public List<Node> inbound_nodes => _inbound_nodes;

private List<Node> _outbound_nodes;
public List<Node> outbound_nodes => _outbound_nodes;

public Layer(bool trainable = true, public Layer(bool trainable = true,
string name = null, string name = null,
TF_DataType dtype = TF_DataType.DtInvalid, TF_DataType dtype = TF_DataType.DtInvalid,
@@ -59,13 +65,15 @@ namespace Tensorflow.Keras.Layers
_batch_input_shape = new int[] { -1, -1 }; _batch_input_shape = new int[] { -1, -1 };


_dtype = dtype; _dtype = dtype;

_inbound_nodes = new List<Node>();
} }


public Tensor __call__(Tensor inputs,
public Tensor __call__(Tensor[] inputs,
Tensor training = null, Tensor training = null,
VariableScope scope = null) VariableScope scope = null)
{ {
var input_list = new Tensor[] { inputs };
var input_list = inputs;
Tensor outputs = null; Tensor outputs = null;


// We will attempt to build a TF graph if & only if all inputs are symbolic. // We will attempt to build a TF graph if & only if all inputs are symbolic.
@@ -88,9 +96,9 @@ namespace Tensorflow.Keras.Layers
// Symbolic execution on symbolic tensors. We will attempt to build // Symbolic execution on symbolic tensors. We will attempt to build
// the corresponding TF subgraph inside `backend.get_graph()` // the corresponding TF subgraph inside `backend.get_graph()`
var graph = backend.get_graph(); var graph = backend.get_graph();
outputs = call(inputs, training: training);
_handle_activity_regularization(inputs, outputs);
_set_mask_metadata(inputs, outputs, null);
outputs = call(inputs[0], training: training);
_handle_activity_regularization(inputs[0], outputs);
_set_mask_metadata(inputs[0], outputs, null);
} }
}); });


@@ -125,10 +133,10 @@ namespace Tensorflow.Keras.Layers
return null; return null;
} }


protected void _maybe_build(Tensor inputs)
protected void _maybe_build(Tensor[] inputs)
{ {
var input_list = new Tensor[] { inputs };
build(inputs.getShape());
var input_list = inputs;
build(input_list[0].getShape());
} }


protected virtual void build(TensorShape input_shape) protected virtual void build(TensorShape input_shape)
@@ -143,10 +151,16 @@ namespace Tensorflow.Keras.Layers
bool? trainable = null, bool? trainable = null,
Func<string, int[], TF_DataType, IInitializer, bool, RefVariable> getter = null) Func<string, int[], TF_DataType, IInitializer, bool, RefVariable> getter = null)
{ {
if (dtype == TF_DataType.DtInvalid)
dtype = TF_DataType.TF_FLOAT;

if (trainable == null)
trainable = true;

var variable = _add_variable_with_custom_getter(name, var variable = _add_variable_with_custom_getter(name,
shape, shape,
dtype: dtype, dtype: dtype,
getter: getter,
getter: getter == null ? base_layer_utils.make_variable : getter,
overwrite: true, overwrite: true,
initializer: initializer, initializer: initializer,
trainable: trainable.Value); trainable: trainable.Value);


+ 71
- 0
src/TensorFlowNET.Core/Keras/Layers/Node.cs View File

@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tensorflow.Keras.Layers
{
/// <summary>
/// A `Node` describes the connectivity between two layers.
/// </summary>
public class Node
{
public InputLayer outbound_layer;
public Layer[] inbound_layers;
public int[] node_indices;
public int[] tensor_indices;
public Tensor[] input_tensors;
public Tensor[] output_tensors;
public int[][] input_shapes;
public int[][] output_shapes;

/// <summary>
///
/// </summary>
/// <param name="outbound_layer">
/// the layer that takes
/// `input_tensors` and turns them into `output_tensors`
/// (the node gets created when the `call`
/// method of the layer was called).
/// </param>
/// <param name="inbound_layers">
/// a list of layers, the same length as `input_tensors`,
/// the layers from where `input_tensors` originate.
/// </param>
/// <param name="node_indices">
/// a list of integers, the same length as `inbound_layers`.
/// `node_indices[i]` is the origin node of `input_tensors[i]`
/// (necessary since each inbound layer might have several nodes,
/// e.g. if the layer is being shared with a different data stream).
/// </param>
/// <param name="tensor_indices"></param>
/// <param name="input_tensors">list of input tensors.</param>
/// <param name="output_tensors">list of output tensors.</param>
public Node(InputLayer outbound_layer,
Layer[] inbound_layers,
int[] node_indices,
int[] tensor_indices,
Tensor[] input_tensors,
Tensor[] output_tensors)
{
this.outbound_layer = outbound_layer;
this.inbound_layers = inbound_layers;
this.node_indices = node_indices;
this.tensor_indices = tensor_indices;
this.input_tensors = input_tensors;
this.output_tensors = output_tensors;

input_shapes = input_tensors.Select(x => x._shape_tuple()).ToArray();
output_shapes = output_tensors.Select(x => x._shape_tuple()).ToArray();

// Add nodes to all layers involved.
foreach (var layer in inbound_layers)
{
if (layer != null)
layer.outbound_nodes.Add(this);
}

outbound_layer.inbound_nodes.Add(this);
}
}
}

src/TensorFlowNET.Core/Keras/Engine/base_layer_utils.cs → src/TensorFlowNET.Core/Keras/Utils/base_layer_utils.cs View File

@@ -2,10 +2,19 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;


namespace Tensorflow.Keras.Engine
namespace Tensorflow.Keras.Utils
{ {
public class base_layer_utils public class base_layer_utils
{ {
public static RefVariable make_variable(string name,
int[] shape,
TF_DataType dtype = TF_DataType.TF_FLOAT,
IInitializer initializer = null,
bool trainable = false)
{
throw new NotImplementedException("");
}

/// <summary> /// <summary>
/// Makes a layer name (or arbitrary string) unique within a TensorFlow graph. /// Makes a layer name (or arbitrary string) unique within a TensorFlow graph.
/// </summary> /// </summary>

+ 1
- 1
src/TensorFlowNET.Core/Layers/Layer.cs View File

@@ -52,7 +52,7 @@ namespace Tensorflow.Layers


Python.with(scope_context_manager, scope2 => _current_scope = scope2); Python.with(scope_context_manager, scope2 => _current_scope = scope2);
// Actually call layer // Actually call layer
var outputs = base.__call__(inputs, training: training);
var outputs = base.__call__(new Tensor[] { inputs }, training: training);


// Update global default collections. // Update global default collections.
_add_elements_to_collection(_updates.ToArray(), new string[] { ops.GraphKeys.UPDATE_OPS }); _add_elements_to_collection(_updates.ToArray(), new string[] { ops.GraphKeys.UPDATE_OPS });


+ 1
- 1
src/TensorFlowNET.Core/TensorFlowNET.Core.csproj View File

@@ -43,7 +43,7 @@ Docs: https://tensorflownet.readthedocs.io</Description>


<ItemGroup> <ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.7.0" /> <PackageReference Include="Google.Protobuf" Version="3.7.0" />
<PackageReference Include="NumSharp" Version="0.7.4" />
<PackageReference Include="NumSharp" Version="0.8.0" />
</ItemGroup> </ItemGroup>


<ItemGroup> <ItemGroup>


+ 1
- 1
test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj View File

@@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>


<ItemGroup> <ItemGroup>
<PackageReference Include="NumSharp" Version="0.7.4" />
<PackageReference Include="NumSharp" Version="0.8.0" />
<PackageReference Include="SharpZipLib" Version="1.1.0" /> <PackageReference Include="SharpZipLib" Version="1.1.0" />
<PackageReference Include="TensorFlow.NET" Version="0.4.2" /> <PackageReference Include="TensorFlow.NET" Version="0.4.2" />
</ItemGroup> </ItemGroup>


+ 1
- 1
test/TensorFlowNET.UnitTest/TensorFlowNET.UnitTest.csproj View File

@@ -19,7 +19,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
<PackageReference Include="NumSharp" Version="0.7.4" />
<PackageReference Include="NumSharp" Version="0.8.0" />
<PackageReference Include="TensorFlow.NET" Version="0.4.2" /> <PackageReference Include="TensorFlow.NET" Version="0.4.2" />
</ItemGroup> </ItemGroup>




Loading…
Cancel
Save