diff --git a/src/TensorFlowNET.Core/Keras/ArgsDefinition/Reshaping/UpSampling2DArgs.cs b/src/TensorFlowNET.Core/Keras/ArgsDefinition/Reshaping/UpSampling2DArgs.cs index b35e0e4b6..504b3d46d 100644 --- a/src/TensorFlowNET.Core/Keras/ArgsDefinition/Reshaping/UpSampling2DArgs.cs +++ b/src/TensorFlowNET.Core/Keras/ArgsDefinition/Reshaping/UpSampling2DArgs.cs @@ -7,7 +7,7 @@ public class UpSampling2DArgs : AutoSerializeLayerArgs [JsonProperty("size")] public Shape Size { get; set; } [JsonProperty("data_format")] - public string DataFormat { get; set; } + public string DataFormat { get; set; } = "channels_last"; /// /// 'nearest', 'bilinear' /// diff --git a/src/TensorFlowNET.Core/Keras/ArgsDefinition/Reshaping/Upsampling1DArgs.cs b/src/TensorFlowNET.Core/Keras/ArgsDefinition/Reshaping/Upsampling1DArgs.cs new file mode 100644 index 000000000..4e3dbf17a --- /dev/null +++ b/src/TensorFlowNET.Core/Keras/ArgsDefinition/Reshaping/Upsampling1DArgs.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace Tensorflow.Keras.ArgsDefinition +{ + public class UpSampling1DArgs : AutoSerializeLayerArgs + { + [JsonProperty("size")] + public int Size { get; set; } + } +} diff --git a/src/TensorFlowNET.Core/Keras/Layers/ILayersApi.Reshaping.cs b/src/TensorFlowNET.Core/Keras/Layers/ILayersApi.Reshaping.cs index d41e06887..ae34c514f 100644 --- a/src/TensorFlowNET.Core/Keras/Layers/ILayersApi.Reshaping.cs +++ b/src/TensorFlowNET.Core/Keras/Layers/ILayersApi.Reshaping.cs @@ -9,6 +9,10 @@ public partial interface ILayersApi public ILayer Reshape(Shape target_shape); public ILayer Reshape(object[] target_shape); + public ILayer UpSampling1D( + int size + ); + public ILayer UpSampling2D(Shape size = null, string data_format = null, string interpolation = "nearest"); diff --git a/src/TensorFlowNET.Keras/BackendImpl.cs b/src/TensorFlowNET.Keras/BackendImpl.cs index 8dbcf90d5..364800ae5 100644 --- a/src/TensorFlowNET.Keras/BackendImpl.cs +++ b/src/TensorFlowNET.Keras/BackendImpl.cs @@ -956,6 +956,32 @@ Tensors _step(Tensors tensors) } + /// + /// Repeats the elements of a tensor along an axis, like `np.repeat`. + /// + /// + /// + /// + /// + public Tensor repeat_elements(Tensor x, int rep, int axis) + { + var x_shape = x.shape.as_int_list(); + if (x_shape[axis] != -1) + { + var splits = tf.split(x, x_shape[axis], axis:axis); + var x_rep = splits.SelectMany(s => Enumerable.Repeat(s, rep)).ToArray(); + return concatenate(x_rep, axis); + } + //var auxiliary_axis = axis + 1; + //x_shape = x.shape; + //var x_rep = tf.expand_dims(x, auxiliary_axis); + //var reps = np.ones(x_shape.Length + 1); + //reps[auxiliary_axis] = rep; + //x_rep = tf.tile(x_rep, reps); + + throw new NotImplementedException(); + + } public Tensor reverse(Tensor input, int axis) { return reverse(input, new int[] { axis }); diff --git a/src/TensorFlowNET.Keras/Layers/LayersApi.Reshaping.cs b/src/TensorFlowNET.Keras/Layers/LayersApi.Reshaping.cs index d3db1d663..2ee99bc79 100644 --- a/src/TensorFlowNET.Keras/Layers/LayersApi.Reshaping.cs +++ b/src/TensorFlowNET.Keras/Layers/LayersApi.Reshaping.cs @@ -6,35 +6,48 @@ namespace Tensorflow.Keras.Layers { public partial class LayersApi { - /// - /// Zero-padding layer for 2D input (e.g. picture). - /// - /// - /// - public ILayer ZeroPadding2D ( NDArray padding ) + + /// + /// Upsampling layer for 1D inputs. Repeats each temporal step `size` times along the time axis. + /// + /// + /// + public ILayer UpSampling1D(int size) + => new UpSampling1D(new UpSampling1DArgs + { + Size = size + }); + + /// + /// Zero-padding layer for 2D input (e.g. picture). + /// + /// + /// + public ILayer ZeroPadding2D ( NDArray padding ) => new ZeroPadding2D(new ZeroPadding2DArgs { Padding = padding }); - /// - /// Upsampling layer for 2D inputs.
- /// Repeats the rows and columns of the data by size[0] and size[1] respectively. - ///
- /// - /// - /// - /// - public ILayer UpSampling2D ( Shape size = null, - string data_format = null, - string interpolation = "nearest" ) - => new UpSampling2D(new UpSampling2DArgs { - Size = size ?? (2, 2) - }); + /// + /// Upsampling layer for 2D inputs.
+ /// Repeats the rows and columns of the data by size[0] and size[1] respectively. + ///
+ /// + /// + /// + /// + public ILayer UpSampling2D(Shape size, string data_format, string interpolation) + => new UpSampling2D(new UpSampling2DArgs + { + Size = size, + DataFormat = data_format, + Interpolation = interpolation + }); - /// - /// Permutes the dimensions of the input according to a given pattern. - /// - public ILayer Permute ( int[] dims ) + /// + /// Permutes the dimensions of the input according to a given pattern. + /// + public ILayer Permute ( int[] dims ) => new Permute(new PermuteArgs { dims = dims }); diff --git a/src/TensorFlowNET.Keras/Layers/Reshaping/UpSampling1D.cs b/src/TensorFlowNET.Keras/Layers/Reshaping/UpSampling1D.cs new file mode 100644 index 000000000..3bc8d6c6b --- /dev/null +++ b/src/TensorFlowNET.Keras/Layers/Reshaping/UpSampling1D.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Tensorflow.Common.Types; +using Tensorflow.Keras.ArgsDefinition; +using Tensorflow.Keras.Engine; + + +namespace Tensorflow.Keras.Layers +{ + /// + /// Upsampling layer for 1D inputs. + /// + public class UpSampling1D : Layer + { + UpSampling1DArgs args; + int size; + + public UpSampling1D(UpSampling1DArgs args) : base(args) + { + this.args = args; + size = args.Size; + inputSpec = new InputSpec(ndim: 3); + } + + protected override Tensors Call(Tensors inputs, Tensors state = null, bool? training = null, IOptionalArgs? optional_args = null) + { + var output = keras.backend.repeat_elements(inputs, size, axis: 1); + return output; + } + } +} diff --git a/src/TensorFlowNET.Keras/Layers/Reshaping/UpSampling2D.cs b/src/TensorFlowNET.Keras/Layers/Reshaping/UpSampling2D.cs index 223f33d4f..cb579d61e 100644 --- a/src/TensorFlowNET.Keras/Layers/Reshaping/UpSampling2D.cs +++ b/src/TensorFlowNET.Keras/Layers/Reshaping/UpSampling2D.cs @@ -10,6 +10,9 @@ namespace Tensorflow.Keras.Layers { + /// + /// Upsampling layer for 2D inputs. + /// public class UpSampling2D : Layer { UpSampling2DArgs args; diff --git a/test/TensorFlowNET.Keras.UnitTest/Layers/Layers.Reshaping.Test.cs b/test/TensorFlowNET.Keras.UnitTest/Layers/Layers.Reshaping.Test.cs index 748544cb0..5b16cc908 100644 --- a/test/TensorFlowNET.Keras.UnitTest/Layers/Layers.Reshaping.Test.cs +++ b/test/TensorFlowNET.Keras.UnitTest/Layers/Layers.Reshaping.Test.cs @@ -1,4 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; using Tensorflow.NumPy; using static Tensorflow.Binding; using static Tensorflow.KerasApi; @@ -18,6 +19,15 @@ public void ZeroPadding2D() Assert.AreEqual((1, 2, 3, 2), y.shape); } + [TestMethod] + public void UpSampling1D() + { + Shape input_shape = (2, 2, 3); + var x = np.arange(input_shape.size).reshape(input_shape); + var y = tf.keras.layers.UpSampling1D(size: 2).Apply(x); + Assert.AreEqual((2, 4, 3), y.shape); + } + [TestMethod] public void UpSampling2D() {