@@ -191,7 +191,7 @@ namespace Tensorflow.Keras.Engine | |||
tf.Context.eager_mode(isFunc: tf.Context.is_build_function()); | |||
} | |||
build(inputs); | |||
build(inputs.shape); | |||
if (need_restore_mode) | |||
tf.Context.restore_mode(); | |||
@@ -199,7 +199,7 @@ namespace Tensorflow.Keras.Engine | |||
built = true; | |||
} | |||
protected virtual void build(Tensors inputs) | |||
public virtual void build(Shape input_shape) | |||
{ | |||
built = true; | |||
} | |||
@@ -6,30 +6,38 @@ using Tensorflow.Keras.Engine; | |||
using static Tensorflow.Binding; | |||
namespace Tensorflow.Keras.Layers { | |||
/// <summary> | |||
/// ELU Layer: | |||
/// x = 0 when x > 0, x = alpha( e^x-1 ) elsewhere | |||
/// </summary> | |||
public class ELU : Layer { | |||
ELUArgs args; | |||
float alpha => args.Alpha; | |||
public ELU ( ELUArgs args ) : base(args) { | |||
this.args = args; | |||
} | |||
protected override void build ( Tensors inputs ) { | |||
if ( alpha < 0f ) { | |||
throw new ValueError("Alpha must be a number greater than 0."); | |||
} | |||
built = true; | |||
} | |||
protected override Tensors Call ( Tensors inputs, Tensor state = null, bool? training = null ) { | |||
Tensor output = inputs; | |||
output = tf.where(output > 0f, output, | |||
tf.multiply(alpha, tf.sub(tf.exp(output), 1f))); | |||
return output; | |||
} | |||
public override Shape ComputeOutputShape ( Shape input_shape ) { | |||
return input_shape; | |||
/// <summary> | |||
/// ELU Layer: | |||
/// x = 0 when x > 0, x = alpha( e^x-1 ) elsewhere | |||
/// </summary> | |||
public class ELU : Layer | |||
{ | |||
ELUArgs args; | |||
float alpha => args.Alpha; | |||
public ELU(ELUArgs args) : base(args) | |||
{ | |||
this.args = args; | |||
} | |||
public override void build(Shape input_shape) | |||
{ | |||
if (alpha < 0f) | |||
{ | |||
throw new ValueError("Alpha must be a number greater than 0."); | |||
} | |||
} | |||
built = true; | |||
} | |||
protected override Tensors Call(Tensors inputs, Tensor state = null, bool? training = null) | |||
{ | |||
Tensor output = inputs; | |||
output = tf.where(output > 0f, output, | |||
tf.multiply(alpha, tf.sub(tf.exp(output), 1f))); | |||
return output; | |||
} | |||
public override Shape ComputeOutputShape(Shape input_shape) | |||
{ | |||
return input_shape; | |||
} | |||
} | |||
} |
@@ -6,19 +6,24 @@ using Tensorflow.Keras.Engine; | |||
using static Tensorflow.Binding; | |||
namespace Tensorflow.Keras.Layers { | |||
public class Exponential : Layer { | |||
public Exponential ( LayerArgs args ) : base(args) { | |||
// Exponential has no args | |||
} | |||
protected override void build ( Tensors inputs ) { | |||
built = true; | |||
} | |||
protected override Tensors Call ( Tensors inputs, Tensor state = null, bool? training = null ) { | |||
Tensor output = inputs; | |||
return tf.exp(output); | |||
} | |||
public override Shape ComputeOutputShape ( Shape input_shape ) { | |||
return input_shape; | |||
} | |||
} | |||
public class Exponential : Layer | |||
{ | |||
public Exponential(LayerArgs args) : base(args) | |||
{ | |||
// Exponential has no args | |||
} | |||
public override void build(Shape input_shape) | |||
{ | |||
built = true; | |||
} | |||
protected override Tensors Call(Tensors inputs, Tensor state = null, bool? training = null) | |||
{ | |||
Tensor output = inputs; | |||
return tf.exp(output); | |||
} | |||
public override Shape ComputeOutputShape(Shape input_shape) | |||
{ | |||
return input_shape; | |||
} | |||
} | |||
} |
@@ -15,7 +15,7 @@ namespace Tensorflow.Keras.Layers { | |||
public SELU ( LayerArgs args ) : base(args) { | |||
// SELU has no arguments | |||
} | |||
protected override void build ( Tensors inputs ) { | |||
public override void build(Shape input_shape) { | |||
if ( alpha < 0f ) { | |||
throw new ValueError("Alpha must be a number greater than 0."); | |||
} | |||
@@ -90,9 +90,10 @@ namespace Tensorflow.Keras.Layers | |||
}.Contains(this.score_mode)) | |||
throw new ValueError("Received: score_mode={score_mode}. Acceptable values are: [\"dot\", \"concat\"]"); | |||
} | |||
// Creates variable when `use_scale` is True or `score_mode` is `concat`. | |||
protected override void build(Tensors inputs) { | |||
public override void build(Shape input_shape) | |||
{ | |||
if (this.use_scale) | |||
this.scale = this.add_weight(name: "scale", | |||
shape: 1, | |||
@@ -110,7 +111,7 @@ namespace Tensorflow.Keras.Layers | |||
trainable: true); | |||
else | |||
this.concat_score_weight = null; | |||
base.build(inputs); | |||
base.build(input_shape); | |||
} | |||
/// <summary> | |||
@@ -29,9 +29,8 @@ namespace Tensorflow.Keras.Layers | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
var input_shape = inputs.shape; | |||
if (len(input_shape) != 4) | |||
throw new ValueError($"Inputs should have rank 4. Received input shape: {input_shape}"); | |||
@@ -43,14 +42,12 @@ namespace Tensorflow.Keras.Layers | |||
shape: kernel_shape, | |||
initializer: kernel_initializer, | |||
regularizer: kernel_regularizer, | |||
trainable: true, | |||
dtype: inputs.dtype); | |||
trainable: true); | |||
if (use_bias) | |||
bias = add_weight(name: "bias", | |||
shape: filters, | |||
initializer: bias_initializer, | |||
trainable: true, | |||
dtype: inputs.dtype); | |||
trainable: true); | |||
built = true; | |||
} | |||
@@ -57,9 +57,8 @@ namespace Tensorflow.Keras.Layers | |||
_tf_data_format = conv_utils.convert_data_format(data_format, rank + 2); | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
Shape input_shape = inputs.shape; | |||
int channel_axis = data_format == "channels_first" ? 1 : -1; | |||
var input_channel = channel_axis < 0 ? | |||
input_shape.dims[input_shape.ndim + channel_axis] : | |||
@@ -41,9 +41,8 @@ namespace Tensorflow.Keras.Layers | |||
this.inputSpec = new InputSpec(min_ndim: 2); | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
Shape input_shape = inputs.shape; | |||
var last_dim = input_shape.dims.Last(); | |||
var axes = new Dictionary<int, int>(); | |||
axes[-1] = (int)last_dim; | |||
@@ -119,9 +119,8 @@ namespace Tensorflow.Keras.Layers | |||
this.bias_constraint = args.BiasConstraint; | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
var input_shape = inputs.shape; | |||
var shape_data = _analyze_einsum_string(this.equation, this.bias_axes, input_shape, this.partial_output_shape); | |||
var kernel_shape = shape_data.Item1; | |||
var bias_shape = shape_data.Item2; | |||
@@ -141,7 +140,7 @@ namespace Tensorflow.Keras.Layers | |||
trainable: true); | |||
else | |||
this.bias = null; | |||
base.build(inputs); | |||
base.build(input_shape); | |||
} | |||
public override Shape ComputeOutputShape(Shape input_shape) | |||
@@ -54,7 +54,7 @@ namespace Tensorflow.Keras.Layers | |||
SupportsMasking = mask_zero; | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
tf.Context.eager_mode(); | |||
embeddings = add_weight(shape: (input_dim, output_dim), | |||
@@ -2,49 +2,61 @@ | |||
using Tensorflow.Keras.Engine; | |||
namespace Tensorflow.Keras.Layers { | |||
public class Cropping1D : Layer { | |||
CroppingArgs args; | |||
public Cropping1D ( CroppingArgs args ) : base(args) { | |||
this.args = args; | |||
} | |||
public class Cropping1D : Layer | |||
{ | |||
CroppingArgs args; | |||
public Cropping1D(CroppingArgs args) : base(args) | |||
{ | |||
this.args = args; | |||
} | |||
protected override void build ( Tensors inputs ) { | |||
if ( args.cropping.rank != 1 ) { | |||
// throw an ValueError exception | |||
throw new ValueError(""); | |||
} | |||
else if ( args.cropping.shape[0] > 2 || args.cropping.shape[0] < 1 ) { | |||
throw new ValueError("The `cropping` argument must be a tuple of 2 integers."); | |||
} | |||
built = true; | |||
public override void build(Shape input_shape) | |||
{ | |||
if (args.cropping.rank != 1) | |||
{ | |||
// throw an ValueError exception | |||
throw new ValueError(""); | |||
} | |||
else if (args.cropping.shape[0] > 2 || args.cropping.shape[0] < 1) | |||
{ | |||
throw new ValueError("The `cropping` argument must be a tuple of 2 integers."); | |||
} | |||
built = true; | |||
} | |||
protected override Tensors Call ( Tensors inputs, Tensor state = null, bool? training = null ) { | |||
Tensor output = inputs; | |||
if ( output.rank != 3 ) { | |||
// throw an ValueError exception | |||
throw new ValueError("Expected dim=3, found dim=" + output.rank); | |||
} | |||
if ( args.cropping.shape[0] == 1 ) { | |||
int crop_start = args.cropping[0]; | |||
output = output[new Slice(), new Slice(crop_start, ( int ) output.shape[1] - crop_start), new Slice()]; | |||
} | |||
else { | |||
int crop_start = args.cropping[0], crop_end = args.cropping[1]; | |||
output = output[new Slice(), new Slice(crop_start, ( int ) (output.shape[1]) - crop_end), new Slice()]; | |||
} | |||
return output; | |||
protected override Tensors Call(Tensors inputs, Tensor state = null, bool? training = null) | |||
{ | |||
Tensor output = inputs; | |||
if (output.rank != 3) | |||
{ | |||
// throw an ValueError exception | |||
throw new ValueError("Expected dim=3, found dim=" + output.rank); | |||
} | |||
if (args.cropping.shape[0] == 1) | |||
{ | |||
int crop_start = args.cropping[0]; | |||
output = output[new Slice(), new Slice(crop_start, (int)output.shape[1] - crop_start), new Slice()]; | |||
} | |||
else | |||
{ | |||
int crop_start = args.cropping[0], crop_end = args.cropping[1]; | |||
output = output[new Slice(), new Slice(crop_start, (int)(output.shape[1]) - crop_end), new Slice()]; | |||
} | |||
return output; | |||
} | |||
public override Shape ComputeOutputShape ( Shape input_shape ) { | |||
if ( args.cropping.shape[0] == 1 ) { | |||
int crop = args.cropping[0]; | |||
return new Shape(( int ) (input_shape[0]), ( int ) (input_shape[1] - crop * 2), ( int ) (input_shape[2])); | |||
} | |||
else { | |||
int crop_start = args.cropping[0], crop_end = args.cropping[1]; | |||
return new Shape(( int ) (input_shape[0]), ( int ) (input_shape[1] - crop_start - crop_end), ( int ) (input_shape[2])); | |||
} | |||
public override Shape ComputeOutputShape(Shape input_shape) | |||
{ | |||
if (args.cropping.shape[0] == 1) | |||
{ | |||
int crop = args.cropping[0]; | |||
return new Shape((int)(input_shape[0]), (int)(input_shape[1] - crop * 2), (int)(input_shape[2])); | |||
} | |||
else | |||
{ | |||
int crop_start = args.cropping[0], crop_end = args.cropping[1]; | |||
return new Shape((int)(input_shape[0]), (int)(input_shape[1] - crop_start - crop_end), (int)(input_shape[2])); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -12,7 +12,7 @@ namespace Tensorflow.Keras.Layers { | |||
public Cropping2D ( Cropping2DArgs args ) : base(args) { | |||
this.args = args; | |||
} | |||
protected override void build ( Tensors inputs ) { | |||
public override void build(Shape input_shape) { | |||
built = true; | |||
} | |||
protected override Tensors Call ( Tensors inputs, Tensor state = null, bool? training = null ) { | |||
@@ -11,7 +11,7 @@ namespace Tensorflow.Keras.Layers { | |||
this.args = args; | |||
} | |||
protected override void build ( Tensors inputs ) { | |||
public override void build(Shape input_shape) { | |||
built = true; | |||
} | |||
@@ -23,7 +23,7 @@ namespace Tensorflow.Keras.Layers | |||
this.args = args; | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
/*var shape_set = new HashSet<Shape>(); | |||
var reduced_inputs_shapes = inputs.Select(x => x.shape).ToArray(); | |||
@@ -14,7 +14,7 @@ namespace Tensorflow.Keras.Layers | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
// output_shape = input_shape.dims[1^]; | |||
} | |||
@@ -53,9 +53,8 @@ namespace Tensorflow.Keras.Layers | |||
axis = args.Axis.dims.Select(x => (int)x).ToArray(); | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
Shape input_shape = inputs.shape; | |||
var ndims = input_shape.ndim; | |||
foreach (var (idx, x) in enumerate(axis)) | |||
if (x < 0) | |||
@@ -49,9 +49,8 @@ namespace Tensorflow.Keras.Layers | |||
axis = args.Axis.axis; | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
Shape input_shape = inputs.shape; | |||
var ndims = input_shape.ndim; | |||
foreach (var (idx, x) in enumerate(axis)) | |||
if (x < 0) | |||
@@ -35,14 +35,14 @@ namespace Tensorflow.Keras.Layers | |||
var shape = data.output_shapes[0]; | |||
if (shape.ndim == 1) | |||
data = data.map(tensor => array_ops.expand_dims(tensor, -1)); | |||
build(data.variant_tensor); | |||
build(data.variant_tensor.shape); | |||
var preprocessed_inputs = data.map(_preprocess); | |||
_index_lookup_layer.adapt(preprocessed_inputs); | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
base.build(inputs); | |||
base.build(input_shape); | |||
} | |||
Tensors _preprocess(Tensors inputs) | |||
@@ -7,32 +7,39 @@ using static Tensorflow.Binding; | |||
using Tensorflow.Keras.ArgsDefinition; | |||
namespace Tensorflow.Keras.Layers { | |||
public class Permute : Layer { | |||
int[] dims, permute; | |||
public Permute ( PermuteArgs args ) : base(args) { | |||
this.dims = args.dims; | |||
public class Permute : Layer | |||
{ | |||
int[] dims, permute; | |||
public Permute(PermuteArgs args) : base(args) | |||
{ | |||
this.dims = args.dims; | |||
} | |||
public override void build(Shape input_shape) | |||
{ | |||
var rank = input_shape.rank; | |||
if (dims.Length != rank - 1) | |||
{ | |||
throw new ValueError("Dimensions must match."); | |||
} | |||
protected override void build ( Tensors inputs ) { | |||
var rank = inputs.rank; | |||
if ( dims.Length != rank - 1 ) { | |||
throw new ValueError("Dimensions must match."); | |||
} | |||
permute = new int[inputs.rank]; | |||
dims.CopyTo(permute, 1); | |||
built = true; | |||
permute = new int[input_shape.rank]; | |||
dims.CopyTo(permute, 1); | |||
built = true; | |||
} | |||
protected override Tensors Call(Tensors inputs, Tensor state = null, bool? training = null) | |||
{ | |||
Tensor outputs = inputs; | |||
return tf.transpose(outputs, new Axis(permute)); | |||
} | |||
public override Shape ComputeOutputShape(Shape input_shape) | |||
{ | |||
Shape output_shape = new Shape(input_shape.dims); | |||
for (int i = 0; i < dims.Length; i += 1) | |||
{ | |||
var d = dims[i]; | |||
var target_dim = input_shape[d]; | |||
output_shape[i + 1] = target_dim; | |||
} | |||
protected override Tensors Call ( Tensors inputs, Tensor state = null, bool? training = null ) { | |||
Tensor outputs = inputs; | |||
return tf.transpose(outputs, new Axis(permute)); | |||
} | |||
public override Shape ComputeOutputShape ( Shape input_shape ) { | |||
Shape output_shape = new Shape(input_shape.dims); | |||
for ( int i = 0; i < dims.Length; i += 1 ) { | |||
var d = dims[i]; | |||
var target_dim = input_shape[d]; | |||
output_shape[i + 1] = target_dim; | |||
} | |||
return output_shape; | |||
} | |||
} | |||
return output_shape; | |||
} | |||
} | |||
} |
@@ -15,9 +15,8 @@ namespace Tensorflow.Keras.Layers.Rnn | |||
this.args = args; | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
var input_shape = inputs.shape; | |||
var input_dim = input_shape[-1]; | |||
kernel = add_weight("kernel", (input_shape[-1], args.Units), | |||
@@ -13,7 +13,7 @@ namespace Tensorflow.Keras.Layers.Rnn | |||
} | |||
protected override void build(Tensors inputs) | |||
public override void build(Shape input_shape) | |||
{ | |||
} | |||