feat: Add UpSampling1D layer and test.tags/v0.110.0-LSTM-Model
| @@ -7,7 +7,7 @@ namespace Tensorflow.Keras.ArgsDefinition | |||||
| [JsonProperty("size")] | [JsonProperty("size")] | ||||
| public Shape Size { get; set; } | public Shape Size { get; set; } | ||||
| [JsonProperty("data_format")] | [JsonProperty("data_format")] | ||||
| public string DataFormat { get; set; } | |||||
| public string DataFormat { get; set; } = "channels_last"; | |||||
| /// <summary> | /// <summary> | ||||
| /// 'nearest', 'bilinear' | /// 'nearest', 'bilinear' | ||||
| /// </summary> | /// </summary> | ||||
| @@ -0,0 +1,10 @@ | |||||
| using Newtonsoft.Json; | |||||
| namespace Tensorflow.Keras.ArgsDefinition | |||||
| { | |||||
| public class UpSampling1DArgs : AutoSerializeLayerArgs | |||||
| { | |||||
| [JsonProperty("size")] | |||||
| public int Size { get; set; } | |||||
| } | |||||
| } | |||||
| @@ -9,6 +9,10 @@ namespace Tensorflow.Keras.Layers | |||||
| public ILayer Reshape(Shape target_shape); | public ILayer Reshape(Shape target_shape); | ||||
| public ILayer Reshape(object[] target_shape); | public ILayer Reshape(object[] target_shape); | ||||
| public ILayer UpSampling1D( | |||||
| int size | |||||
| ); | |||||
| public ILayer UpSampling2D(Shape size = null, | public ILayer UpSampling2D(Shape size = null, | ||||
| string data_format = null, | string data_format = null, | ||||
| string interpolation = "nearest"); | string interpolation = "nearest"); | ||||
| @@ -956,6 +956,32 @@ namespace Tensorflow.Keras | |||||
| } | } | ||||
| /// <summary> | |||||
| /// Repeats the elements of a tensor along an axis, like `np.repeat`. | |||||
| /// </summary> | |||||
| /// <param name="x"></param> | |||||
| /// <param name="rep"></param> | |||||
| /// <param name="axis"></param> | |||||
| /// <returns></returns> | |||||
| 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) | public Tensor reverse(Tensor input, int axis) | ||||
| { | { | ||||
| return reverse(input, new int[] { axis }); | return reverse(input, new int[] { axis }); | ||||
| @@ -6,35 +6,48 @@ using Tensorflow.Keras.ArgsDefinition; | |||||
| namespace Tensorflow.Keras.Layers { | namespace Tensorflow.Keras.Layers { | ||||
| public partial class LayersApi { | public partial class LayersApi { | ||||
| /// <summary> | |||||
| /// Zero-padding layer for 2D input (e.g. picture). | |||||
| /// </summary> | |||||
| /// <param name="padding"></param> | |||||
| /// <returns></returns> | |||||
| public ILayer ZeroPadding2D ( NDArray padding ) | |||||
| /// <summary> | |||||
| /// Upsampling layer for 1D inputs. Repeats each temporal step `size` times along the time axis. | |||||
| /// </summary> | |||||
| /// <param name="size"></param> | |||||
| /// <returns></returns> | |||||
| public ILayer UpSampling1D(int size) | |||||
| => new UpSampling1D(new UpSampling1DArgs | |||||
| { | |||||
| Size = size | |||||
| }); | |||||
| /// <summary> | |||||
| /// Zero-padding layer for 2D input (e.g. picture). | |||||
| /// </summary> | |||||
| /// <param name="padding"></param> | |||||
| /// <returns></returns> | |||||
| public ILayer ZeroPadding2D ( NDArray padding ) | |||||
| => new ZeroPadding2D(new ZeroPadding2DArgs { | => new ZeroPadding2D(new ZeroPadding2DArgs { | ||||
| Padding = padding | Padding = padding | ||||
| }); | }); | ||||
| /// <summary> | |||||
| /// Upsampling layer for 2D inputs.<br/> | |||||
| /// Repeats the rows and columns of the data by size[0] and size[1] respectively. | |||||
| /// </summary> | |||||
| /// <param name="size"></param> | |||||
| /// <param name="data_format"></param> | |||||
| /// <param name="interpolation"></param> | |||||
| /// <returns></returns> | |||||
| public ILayer UpSampling2D ( Shape size = null, | |||||
| string data_format = null, | |||||
| string interpolation = "nearest" ) | |||||
| => new UpSampling2D(new UpSampling2DArgs { | |||||
| Size = size ?? (2, 2) | |||||
| }); | |||||
| /// <summary> | |||||
| /// Upsampling layer for 2D inputs.<br/> | |||||
| /// Repeats the rows and columns of the data by size[0] and size[1] respectively. | |||||
| /// </summary> | |||||
| /// <param name="size"></param> | |||||
| /// <param name="data_format"></param> | |||||
| /// <param name="interpolation"></param> | |||||
| /// <returns></returns> | |||||
| public ILayer UpSampling2D(Shape size, string data_format, string interpolation) | |||||
| => new UpSampling2D(new UpSampling2DArgs | |||||
| { | |||||
| Size = size, | |||||
| DataFormat = data_format, | |||||
| Interpolation = interpolation | |||||
| }); | |||||
| /// <summary> | |||||
| /// Permutes the dimensions of the input according to a given pattern. | |||||
| /// </summary> | |||||
| public ILayer Permute ( int[] dims ) | |||||
| /// <summary> | |||||
| /// Permutes the dimensions of the input according to a given pattern. | |||||
| /// </summary> | |||||
| public ILayer Permute ( int[] dims ) | |||||
| => new Permute(new PermuteArgs { | => new Permute(new PermuteArgs { | ||||
| dims = dims | dims = dims | ||||
| }); | }); | ||||
| @@ -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 | |||||
| { | |||||
| /// <summary> | |||||
| /// Upsampling layer for 1D inputs. | |||||
| /// </summary> | |||||
| 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; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -10,6 +10,9 @@ using Tensorflow.Common.Types; | |||||
| namespace Tensorflow.Keras.Layers | namespace Tensorflow.Keras.Layers | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Upsampling layer for 2D inputs. | |||||
| /// </summary> | |||||
| public class UpSampling2D : Layer | public class UpSampling2D : Layer | ||||
| { | { | ||||
| UpSampling2DArgs args; | UpSampling2DArgs args; | ||||
| @@ -1,4 +1,5 @@ | |||||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | using Microsoft.VisualStudio.TestTools.UnitTesting; | ||||
| using System; | |||||
| using Tensorflow.NumPy; | using Tensorflow.NumPy; | ||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| using static Tensorflow.KerasApi; | using static Tensorflow.KerasApi; | ||||
| @@ -18,6 +19,15 @@ namespace Tensorflow.Keras.UnitTest.Layers | |||||
| Assert.AreEqual((1, 2, 3, 2), y.shape); | 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] | [TestMethod] | ||||
| public void UpSampling2D() | public void UpSampling2D() | ||||
| { | { | ||||