| @@ -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) | |||
| { | |||
| } | |||