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