| @@ -1,4 +1,5 @@ | |||
| using System; | |||
| using Tensorflow.Framework.Models; | |||
| using Tensorflow.NumPy; | |||
| using static Google.Protobuf.Reflection.FieldDescriptorProto.Types; | |||
| @@ -133,11 +134,16 @@ namespace Tensorflow.Keras.Layers | |||
| public ILayer GlobalMaxPooling1D(string data_format = "channels_last"); | |||
| public ILayer GlobalMaxPooling2D(string data_format = "channels_last"); | |||
| public Tensors Input(Shape shape, | |||
| public Tensors Input(Shape shape = null, | |||
| int batch_size = -1, | |||
| string name = null, | |||
| TF_DataType dtype = TF_DataType.DtInvalid, | |||
| bool sparse = false, | |||
| bool ragged = false); | |||
| Tensor tensor = null, | |||
| bool ragged = false, | |||
| TypeSpec type_spec = null, | |||
| Shape batch_input_shape = null, | |||
| Shape batch_shape = null); | |||
| public ILayer InputLayer(Shape input_shape, | |||
| string name = null, | |||
| bool sparse = false, | |||
| @@ -12,6 +12,7 @@ using Tensorflow.Keras.Models; | |||
| using Tensorflow.Keras.Optimizers; | |||
| using Tensorflow.Keras.Utils; | |||
| using System.Threading; | |||
| using Tensorflow.Framework.Models; | |||
| namespace Tensorflow.Keras | |||
| { | |||
| @@ -66,33 +67,16 @@ namespace Tensorflow.Keras | |||
| /// If set, the layer will not create a placeholder tensor. | |||
| /// </param> | |||
| /// <returns></returns> | |||
| public Tensor Input(Shape shape = null, | |||
| int batch_size = -1, | |||
| Shape batch_input_shape = null, | |||
| TF_DataType dtype = TF_DataType.DtInvalid, | |||
| string name = null, | |||
| bool sparse = false, | |||
| bool ragged = false, | |||
| Tensor tensor = null) | |||
| { | |||
| if (batch_input_shape != null) | |||
| shape = batch_input_shape.dims.Skip(1).ToArray(); | |||
| var args = new InputLayerArgs | |||
| { | |||
| Name = name, | |||
| InputShape = shape, | |||
| BatchInputShape = batch_input_shape, | |||
| BatchSize = batch_size, | |||
| DType = dtype, | |||
| Sparse = sparse, | |||
| Ragged = ragged, | |||
| InputTensor = tensor | |||
| }; | |||
| var layer = new InputLayer(args); | |||
| return layer.InboundNodes[0].Outputs; | |||
| } | |||
| public Tensors Input(Shape shape = null, | |||
| int batch_size = -1, | |||
| string name = null, | |||
| TF_DataType dtype = TF_DataType.DtInvalid, | |||
| bool sparse = false, | |||
| Tensor tensor = null, | |||
| bool ragged = false, | |||
| TypeSpec type_spec = null, | |||
| Shape batch_input_shape = null, | |||
| Shape batch_shape = null) => keras.layers.Input(shape, batch_size, name, | |||
| dtype, sparse, tensor, ragged, type_spec, batch_input_shape, batch_shape); | |||
| } | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| using System; | |||
| using Tensorflow.Framework.Models; | |||
| using Tensorflow.Keras.ArgsDefinition; | |||
| using Tensorflow.Keras.ArgsDefinition.Core; | |||
| using Tensorflow.Keras.ArgsDefinition.Rnn; | |||
| @@ -471,20 +472,56 @@ namespace Tensorflow.Keras.Layers | |||
| /// In this case, values of 'None' in the 'shape' argument represent ragged dimensions. For more information about RaggedTensors, see this guide. | |||
| /// </param> | |||
| /// <returns>A tensor.</returns> | |||
| public Tensors Input(Shape shape, | |||
| public Tensors Input(Shape shape = null, | |||
| int batch_size = -1, | |||
| string name = null, | |||
| TF_DataType dtype = TF_DataType.DtInvalid, | |||
| bool sparse = false, | |||
| bool ragged = false) | |||
| Tensor tensor = null, | |||
| bool ragged = false, | |||
| TypeSpec type_spec = null, | |||
| Shape batch_input_shape = null, | |||
| Shape batch_shape = null) | |||
| { | |||
| var input_layer = new InputLayer(new InputLayerArgs | |||
| if(sparse && ragged) | |||
| { | |||
| throw new ValueError("Cannot set both `sparse` and `ragged` to `true` in a Keras `Input`."); | |||
| } | |||
| InputLayerArgs input_layer_config = new() | |||
| { | |||
| InputShape = shape, | |||
| BatchSize= batch_size, | |||
| Name = name, | |||
| DType = dtype, | |||
| Sparse = sparse, | |||
| Ragged = ragged | |||
| }); | |||
| Ragged = ragged, | |||
| InputTensor = tensor, | |||
| // skip the `type_spec` | |||
| }; | |||
| if(shape is not null && batch_input_shape is not null) | |||
| { | |||
| throw new ValueError("Only provide the `shape` OR `batch_input_shape` argument " | |||
| + "to Input, not both at the same time."); | |||
| } | |||
| if(batch_input_shape is null && shape is null && tensor is null && type_spec is null) | |||
| { | |||
| throw new ValueError("Please provide to Input a `shape` or a `tensor` or a `type_spec` argument. Note that " + | |||
| "`shape` does not include the batch dimension."); | |||
| } | |||
| if(batch_input_shape is not null) | |||
| { | |||
| shape = batch_input_shape["1:"]; | |||
| input_layer_config.BatchInputShape = batch_input_shape; | |||
| } | |||
| else | |||
| { | |||
| input_layer_config.BatchSize = batch_size; | |||
| input_layer_config.InputShape = shape; | |||
| } | |||
| var input_layer = new InputLayer(input_layer_config); | |||
| return input_layer.InboundNodes[0].Outputs; | |||
| } | |||
| @@ -158,7 +158,7 @@ namespace TensorFlowNET.Keras.UnitTest | |||
| var value = keras.Input(shape: (2, 8)); | |||
| var mask_tensor = keras.Input(shape:(4, 2)); | |||
| var attention_layer = keras.layers.MultiHeadAttention(num_heads: 2, key_dim: 2); | |||
| attention_layer.Apply(new[] { query, value, mask_tensor }); | |||
| attention_layer.Apply(new Tensor[] { query, value, mask_tensor }); | |||
| var from_data = 10 * np.random.randn(batch_size, 4, 8); | |||
| var to_data = 10 * np.random.randn(batch_size, 2, 8); | |||