From 39aa1c57cfa75cc406528ca26467bf779ca6d363 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 27 Feb 2023 11:22:23 -0800 Subject: [PATCH 01/47] Override 'Module._to()' overloads on some modules that do not have buffers or params. --- src/TorchSharp/NN/Activation/CELU.cs | 8 ++++++++ src/TorchSharp/NN/Activation/ELU.cs | 8 ++++++++ src/TorchSharp/NN/Activation/GELU.cs | 8 ++++++++ src/TorchSharp/NN/Activation/GLU.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Hardshrink.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Hardsigmoid.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Hardswish.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Hardtanh.cs | 8 ++++++++ src/TorchSharp/NN/Activation/LeakyReLU.cs | 8 ++++++++ src/TorchSharp/NN/Activation/LogSoftMax.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Mish.cs | 8 ++++++++ src/TorchSharp/NN/Activation/RReLU.cs | 8 ++++++++ src/TorchSharp/NN/Activation/ReLU6.cs | 8 ++++++++ src/TorchSharp/NN/Activation/ReLu.cs | 8 ++++++++ src/TorchSharp/NN/Activation/SELU.cs | 8 ++++++++ src/TorchSharp/NN/Activation/SiLU.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Sigmoid.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Softmax.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Softmax2d.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Softmin.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Softplus.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Softshrink.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Softsign.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Tanh.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Tanhshrink.cs | 8 ++++++++ src/TorchSharp/NN/Activation/Threshold.cs | 8 ++++++++ 26 files changed, 208 insertions(+) diff --git a/src/TorchSharp/NN/Activation/CELU.cs b/src/TorchSharp/NN/Activation/CELU.cs index 5477628d6..941558e1b 100644 --- a/src/TorchSharp/NN/Activation/CELU.cs +++ b/src/TorchSharp/NN/Activation/CELU.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(CELU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/ELU.cs b/src/TorchSharp/NN/Activation/ELU.cs index f135478f4..042dd4ec6 100644 --- a/src/TorchSharp/NN/Activation/ELU.cs +++ b/src/TorchSharp/NN/Activation/ELU.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(ELU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/GELU.cs b/src/TorchSharp/NN/Activation/GELU.cs index 66dc092d5..e6ad29be7 100644 --- a/src/TorchSharp/NN/Activation/GELU.cs +++ b/src/TorchSharp/NN/Activation/GELU.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(GELU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/GLU.cs b/src/TorchSharp/NN/Activation/GLU.cs index 04a6c9a50..30a37d216 100644 --- a/src/TorchSharp/NN/Activation/GLU.cs +++ b/src/TorchSharp/NN/Activation/GLU.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(GLU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Hardshrink.cs b/src/TorchSharp/NN/Activation/Hardshrink.cs index 08f14ae89..b56cba78a 100644 --- a/src/TorchSharp/NN/Activation/Hardshrink.cs +++ b/src/TorchSharp/NN/Activation/Hardshrink.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Hardshrink).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Hardsigmoid.cs b/src/TorchSharp/NN/Activation/Hardsigmoid.cs index ac9a649cd..99911f027 100644 --- a/src/TorchSharp/NN/Activation/Hardsigmoid.cs +++ b/src/TorchSharp/NN/Activation/Hardsigmoid.cs @@ -29,6 +29,14 @@ public override string GetName() { return typeof(Hardsigmoid).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Hardswish.cs b/src/TorchSharp/NN/Activation/Hardswish.cs index b5b43d094..876f2fce7 100644 --- a/src/TorchSharp/NN/Activation/Hardswish.cs +++ b/src/TorchSharp/NN/Activation/Hardswish.cs @@ -29,6 +29,14 @@ public override string GetName() { return typeof(Hardswish).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Hardtanh.cs b/src/TorchSharp/NN/Activation/Hardtanh.cs index 274808f06..6991b346a 100644 --- a/src/TorchSharp/NN/Activation/Hardtanh.cs +++ b/src/TorchSharp/NN/Activation/Hardtanh.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Hardtanh).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/LeakyReLU.cs b/src/TorchSharp/NN/Activation/LeakyReLU.cs index 59a24e35e..28ad13cd7 100644 --- a/src/TorchSharp/NN/Activation/LeakyReLU.cs +++ b/src/TorchSharp/NN/Activation/LeakyReLU.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(LeakyReLU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/LogSoftMax.cs b/src/TorchSharp/NN/Activation/LogSoftMax.cs index a27de9114..5235de7d3 100644 --- a/src/TorchSharp/NN/Activation/LogSoftMax.cs +++ b/src/TorchSharp/NN/Activation/LogSoftMax.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Mish.cs b/src/TorchSharp/NN/Activation/Mish.cs index 07b304c63..83b1b063a 100644 --- a/src/TorchSharp/NN/Activation/Mish.cs +++ b/src/TorchSharp/NN/Activation/Mish.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Mish).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/RReLU.cs b/src/TorchSharp/NN/Activation/RReLU.cs index 401e39da3..2f756906d 100644 --- a/src/TorchSharp/NN/Activation/RReLU.cs +++ b/src/TorchSharp/NN/Activation/RReLU.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(RReLU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/ReLU6.cs b/src/TorchSharp/NN/Activation/ReLU6.cs index 374f2c470..b7e218069 100644 --- a/src/TorchSharp/NN/Activation/ReLU6.cs +++ b/src/TorchSharp/NN/Activation/ReLU6.cs @@ -29,6 +29,14 @@ public override string GetName() { return typeof(ReLU6).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/ReLu.cs b/src/TorchSharp/NN/Activation/ReLu.cs index 733928558..5068c8016 100644 --- a/src/TorchSharp/NN/Activation/ReLu.cs +++ b/src/TorchSharp/NN/Activation/ReLu.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(ReLU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } public static partial class torch diff --git a/src/TorchSharp/NN/Activation/SELU.cs b/src/TorchSharp/NN/Activation/SELU.cs index bc2174d64..f5d311243 100644 --- a/src/TorchSharp/NN/Activation/SELU.cs +++ b/src/TorchSharp/NN/Activation/SELU.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(SELU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/SiLU.cs b/src/TorchSharp/NN/Activation/SiLU.cs index 1d4cd3bc5..34032d699 100644 --- a/src/TorchSharp/NN/Activation/SiLU.cs +++ b/src/TorchSharp/NN/Activation/SiLU.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(SiLU).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } public static partial class torch diff --git a/src/TorchSharp/NN/Activation/Sigmoid.cs b/src/TorchSharp/NN/Activation/Sigmoid.cs index d76b4aca2..6524a66f2 100644 --- a/src/TorchSharp/NN/Activation/Sigmoid.cs +++ b/src/TorchSharp/NN/Activation/Sigmoid.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Sigmoid).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } public static partial class torch diff --git a/src/TorchSharp/NN/Activation/Softmax.cs b/src/TorchSharp/NN/Activation/Softmax.cs index 4055feb50..e838d0f3b 100644 --- a/src/TorchSharp/NN/Activation/Softmax.cs +++ b/src/TorchSharp/NN/Activation/Softmax.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Softmax).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Softmax2d.cs b/src/TorchSharp/NN/Activation/Softmax2d.cs index 815556e43..87476e48d 100644 --- a/src/TorchSharp/NN/Activation/Softmax2d.cs +++ b/src/TorchSharp/NN/Activation/Softmax2d.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Softmax2d).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } public static partial class torch diff --git a/src/TorchSharp/NN/Activation/Softmin.cs b/src/TorchSharp/NN/Activation/Softmin.cs index 776ecd616..c2f35cfc7 100644 --- a/src/TorchSharp/NN/Activation/Softmin.cs +++ b/src/TorchSharp/NN/Activation/Softmin.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Softmin).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Softplus.cs b/src/TorchSharp/NN/Activation/Softplus.cs index 0c4d8e1c3..582f1bfb5 100644 --- a/src/TorchSharp/NN/Activation/Softplus.cs +++ b/src/TorchSharp/NN/Activation/Softplus.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Softplus).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Softshrink.cs b/src/TorchSharp/NN/Activation/Softshrink.cs index 5c6e10462..0a558d69d 100644 --- a/src/TorchSharp/NN/Activation/Softshrink.cs +++ b/src/TorchSharp/NN/Activation/Softshrink.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Softshrink).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Softsign.cs b/src/TorchSharp/NN/Activation/Softsign.cs index 5a46aeabd..7bc9e6c6c 100644 --- a/src/TorchSharp/NN/Activation/Softsign.cs +++ b/src/TorchSharp/NN/Activation/Softsign.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Softsign).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Tanh.cs b/src/TorchSharp/NN/Activation/Tanh.cs index ed8869fcf..4f81ea91d 100644 --- a/src/TorchSharp/NN/Activation/Tanh.cs +++ b/src/TorchSharp/NN/Activation/Tanh.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Tanh).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Tanhshrink.cs b/src/TorchSharp/NN/Activation/Tanhshrink.cs index c3ced565c..d19ce1157 100644 --- a/src/TorchSharp/NN/Activation/Tanhshrink.cs +++ b/src/TorchSharp/NN/Activation/Tanhshrink.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Tanhshrink).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Threshold.cs b/src/TorchSharp/NN/Activation/Threshold.cs index 0304d5d02..5dd86e13b 100644 --- a/src/TorchSharp/NN/Activation/Threshold.cs +++ b/src/TorchSharp/NN/Activation/Threshold.cs @@ -27,6 +27,14 @@ public override string GetName() { return typeof(Threshold).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } From 7b0350a5d35bbbcc39aa227843bad7fc93ecf1c9 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 28 Feb 2023 09:06:07 -0800 Subject: [PATCH 02/47] Shortcircuit '_to()' for modules that are known not to have buffers or parameters. --- src/TorchSharp/NN/AlphaDropout.cs | 8 ++++++++ src/TorchSharp/NN/CosineSimilarity.cs | 8 ++++++++ src/TorchSharp/NN/Dropout.cs | 8 ++++++++ src/TorchSharp/NN/Dropout1d.cs | 8 ++++++++ src/TorchSharp/NN/Dropout2d.cs | 8 ++++++++ src/TorchSharp/NN/Dropout3d.cs | 8 ++++++++ src/TorchSharp/NN/FeatureDropout.cs | 8 ++++++++ src/TorchSharp/NN/Flatten.cs | 8 ++++++++ src/TorchSharp/NN/Identity.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ConstantPad1d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ConstantPad2d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ConstantPad3d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ReflectionPad1d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ReflectionPad2d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ReflectionPad3d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ReplicationPad1d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ReplicationPad2d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ReplicationPad3d.cs | 8 ++++++++ src/TorchSharp/NN/Padding/ZeroPad2d.cs | 8 ++++++++ src/TorchSharp/NN/PairwiseDistance.cs | 8 ++++++++ src/TorchSharp/NN/PixelShuffle.cs | 8 ++++++++ src/TorchSharp/NN/PixelUnshuffle.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AvgPool1D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AvgPool2D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/AvgPool3D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/LPPool1d.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/LPPool2d.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/MaxPool1D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/MaxPool2D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/MaxPool3D.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/MaxUnpool1d.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/MaxUnpool2d.cs | 8 ++++++++ src/TorchSharp/NN/Pooling/MaxUnpool3d.cs | 8 ++++++++ src/TorchSharp/NN/Shuffle/ChannelShuffle.cs | 8 ++++++++ src/TorchSharp/NN/Unflatten.cs | 8 ++++++++ src/TorchSharp/NN/Upsample.cs | 8 ++++++++ test/TorchSharpTest/NN.cs | 6 ++++-- 45 files changed, 356 insertions(+), 2 deletions(-) diff --git a/src/TorchSharp/NN/AlphaDropout.cs b/src/TorchSharp/NN/AlphaDropout.cs index f6f5bd68a..12e1ceb20 100644 --- a/src/TorchSharp/NN/AlphaDropout.cs +++ b/src/TorchSharp/NN/AlphaDropout.cs @@ -32,6 +32,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/CosineSimilarity.cs b/src/TorchSharp/NN/CosineSimilarity.cs index e6b00724c..db0c02adf 100644 --- a/src/TorchSharp/NN/CosineSimilarity.cs +++ b/src/TorchSharp/NN/CosineSimilarity.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor input1, Tensor input2) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Dropout.cs b/src/TorchSharp/NN/Dropout.cs index 451911448..747edc080 100644 --- a/src/TorchSharp/NN/Dropout.cs +++ b/src/TorchSharp/NN/Dropout.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Dropout1d.cs b/src/TorchSharp/NN/Dropout1d.cs index fc715ada4..459bb7605 100644 --- a/src/TorchSharp/NN/Dropout1d.cs +++ b/src/TorchSharp/NN/Dropout1d.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Dropout2d.cs b/src/TorchSharp/NN/Dropout2d.cs index c2f13c8b0..a53c240cc 100644 --- a/src/TorchSharp/NN/Dropout2d.cs +++ b/src/TorchSharp/NN/Dropout2d.cs @@ -22,6 +22,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Dropout3d.cs b/src/TorchSharp/NN/Dropout3d.cs index 9bac8425b..3422bc723 100644 --- a/src/TorchSharp/NN/Dropout3d.cs +++ b/src/TorchSharp/NN/Dropout3d.cs @@ -22,6 +22,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/FeatureDropout.cs b/src/TorchSharp/NN/FeatureDropout.cs index 637a564e9..3cfd706b2 100644 --- a/src/TorchSharp/NN/FeatureDropout.cs +++ b/src/TorchSharp/NN/FeatureDropout.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Flatten.cs b/src/TorchSharp/NN/Flatten.cs index ad98c0be6..314de873a 100644 --- a/src/TorchSharp/NN/Flatten.cs +++ b/src/TorchSharp/NN/Flatten.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Identity.cs b/src/TorchSharp/NN/Identity.cs index a95290f92..84b6dd07f 100644 --- a/src/TorchSharp/NN/Identity.cs +++ b/src/TorchSharp/NN/Identity.cs @@ -20,6 +20,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ConstantPad1d.cs b/src/TorchSharp/NN/Padding/ConstantPad1d.cs index 58ec8e0f7..142433f8d 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad1d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad1d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ConstantPad2d.cs b/src/TorchSharp/NN/Padding/ConstantPad2d.cs index 2aa724c8a..e4c274da2 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad2d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad2d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ConstantPad3d.cs b/src/TorchSharp/NN/Padding/ConstantPad3d.cs index 60bff8c0d..aa255fd29 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad3d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad3d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ReflectionPad1d.cs b/src/TorchSharp/NN/Padding/ReflectionPad1d.cs index 94e556cd8..5315bc182 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad1d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad1d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs index 205eff0da..071e771de 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs index fa02d38da..5952b009c 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad1d.cs b/src/TorchSharp/NN/Padding/ReplicationPad1d.cs index 51d711032..da29902e7 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad1d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad1d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs index 43b5ce0c4..a068b47e3 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs index e174d3082..81c553b66 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Padding/ZeroPad2d.cs b/src/TorchSharp/NN/Padding/ZeroPad2d.cs index 86b678f8f..796b661dc 100644 --- a/src/TorchSharp/NN/Padding/ZeroPad2d.cs +++ b/src/TorchSharp/NN/Padding/ZeroPad2d.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/PairwiseDistance.cs b/src/TorchSharp/NN/PairwiseDistance.cs index de3a92339..90070352b 100644 --- a/src/TorchSharp/NN/PairwiseDistance.cs +++ b/src/TorchSharp/NN/PairwiseDistance.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor input1, Tensor input2) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/PixelShuffle.cs b/src/TorchSharp/NN/PixelShuffle.cs index c88e0f719..f629caa91 100644 --- a/src/TorchSharp/NN/PixelShuffle.cs +++ b/src/TorchSharp/NN/PixelShuffle.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/PixelUnshuffle.cs b/src/TorchSharp/NN/PixelUnshuffle.cs index 8f19bf953..509e1b544 100644 --- a/src/TorchSharp/NN/PixelUnshuffle.cs +++ b/src/TorchSharp/NN/PixelUnshuffle.cs @@ -27,6 +27,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs index 3516da10f..0bf802292 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs index cc44bc462..688bb31ee 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs index e5d6dfcc4..ae07340fa 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs index 4d2bafd9f..f4a3bc331 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs index 7da2c872e..c727b3844 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs index cb2306888..914011ad0 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool1D.cs b/src/TorchSharp/NN/Pooling/AvgPool1D.cs index ef839d06d..b6209f66b 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool1D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool2D.cs b/src/TorchSharp/NN/Pooling/AvgPool2D.cs index 3d8faa13a..2ecca3844 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool2D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool3D.cs b/src/TorchSharp/NN/Pooling/AvgPool3D.cs index adeed7ab6..b58abe7a1 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool3D.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs index 73ba6b79c..fd34da7a5 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs @@ -31,6 +31,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } return (new Tensor(res), new Tensor(indices)); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs index c96845e5a..a5a7cb0fa 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs @@ -41,6 +41,14 @@ public override Tensor forward(Tensor tensor) return (new Tensor(res), new Tensor(indices)); } + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; + private bool _used_ratio = false; } } diff --git a/src/TorchSharp/NN/Pooling/LPPool1d.cs b/src/TorchSharp/NN/Pooling/LPPool1d.cs index 46c4a7756..2ab11bd52 100644 --- a/src/TorchSharp/NN/Pooling/LPPool1d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool1d.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/LPPool2d.cs b/src/TorchSharp/NN/Pooling/LPPool2d.cs index ce6694e5e..195a5d9ed 100644 --- a/src/TorchSharp/NN/Pooling/LPPool2d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool2d.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool1D.cs b/src/TorchSharp/NN/Pooling/MaxPool1D.cs index e7e8d2162..3c3c0f7b0 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool1D.cs @@ -31,6 +31,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } return (new Tensor(res), new Tensor(indices)); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool2D.cs b/src/TorchSharp/NN/Pooling/MaxPool2D.cs index fa3539d36..6f94d0dd8 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool2D.cs @@ -30,6 +30,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } return (new Tensor(res), new Tensor(indices)); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool3D.cs b/src/TorchSharp/NN/Pooling/MaxPool3D.cs index 1832052c4..03c43730f 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool3D.cs @@ -31,6 +31,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } return (new Tensor(res), new Tensor(indices)); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs index e1b305287..4ffff16a4 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs @@ -33,6 +33,14 @@ public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size { return base.call(tensor, indices, output_size); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs index 081e85b40..42cb3d87e 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs @@ -33,6 +33,14 @@ public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size { return base.call(tensor, indices, output_size); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs index f8af4941b..ca1da4c97 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs @@ -33,6 +33,14 @@ public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size { return base.call(tensor, indices, output_size); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs index 4d05368fd..65b8e4fdd 100644 --- a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs +++ b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs @@ -28,6 +28,14 @@ public override string GetName() { return typeof(ChannelShuffle).Name; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Unflatten.cs b/src/TorchSharp/NN/Unflatten.cs index 25e001281..2f5d9c4cb 100644 --- a/src/TorchSharp/NN/Unflatten.cs +++ b/src/TorchSharp/NN/Unflatten.cs @@ -24,6 +24,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Upsample.cs b/src/TorchSharp/NN/Upsample.cs index 15670dcf8..49ccfc1a4 100644 --- a/src/TorchSharp/NN/Upsample.cs +++ b/src/TorchSharp/NN/Upsample.cs @@ -81,6 +81,14 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } } diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index 678a25fcc..0c72316a2 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -2061,7 +2061,7 @@ public void TestConv1d() var shape = new long[] { 16, 3, 28 }; foreach (var device in TestUtils.AvailableDevices(false)) { Tensor t = torch.rand(shape, device: device); - var conv = Conv1d(3, 64, 3, device: device); + var conv = Conv1d(3, 64, 5, device: device); var output = conv.call(t); Assert.Equal(device.type, output.device_type); Assert.Equal(16, output.shape[0]); @@ -4594,6 +4594,7 @@ public void TestMultiheadAttention() using (var V = torch.tensor(v_data, src_seq_len, batch_size, vembed_dim)) using (var Attn = torch.tensor(attn_data, batch_size, src_seq_len, src_seq_len)) { + var children = mha.children().ToList(); mha.eval(); Assert.False(mha.training); @@ -5325,7 +5326,8 @@ public void TestGRUCell1() Assert.Equal(h0.shape, hN.shape); } } - } } + } + } [Fact] public void TestGRUCell2() From 534baaaa9473d18264a1d284205c71c28f556a33 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Fri, 3 Mar 2023 10:17:28 -0800 Subject: [PATCH 03/47] Experimental rewrite of some modules. --- src/TorchSharp/NN/Linear.cs | 67 +++++++++++++++++++------------------ test/TorchSharpTest/NN.cs | 2 +- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/TorchSharp/NN/Linear.cs b/src/TorchSharp/NN/Linear.cs index 00534970a..971994665 100644 --- a/src/TorchSharp/NN/Linear.cs +++ b/src/TorchSharp/NN/Linear.cs @@ -4,7 +4,6 @@ using static TorchSharp.torch.nn; using static TorchSharp.PInvoke.LibTorchSharp; -#nullable enable namespace TorchSharp { using Modules; @@ -13,48 +12,55 @@ namespace Modules { public sealed class Linear : torch.nn.Module { - internal Linear(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal Linear(long inputSize, long outputSize, bool hasBias = true, Device device = null, ScalarType? dtype = null) : base(nameof(Linear)) { - } - - public new static Linear Load(string modelPath) - { - var res = Module.Load(modelPath); - return new Linear(res.handle.DangerousGetHandle(), IntPtr.Zero); + weight = torch.empty(outputSize, inputSize, device: device, dtype: dtype).AsParameter(); + init.kaiming_uniform_(weight, a: Math.Sqrt(5)); + + if (hasBias) { + bias = torch.empty(outputSize, device: device, dtype: dtype).AsParameter(); + var (fanIn, _) = init.CalculateFanInAndFanOut(weight); + var bound = fanIn > 0 ? 1 / Math.Sqrt(fanIn) : 0; + init.uniform_(bias, -bound, bound); + } + //NOTE: it's important not to call 'RegisterComponents' here. } public override Tensor forward(Tensor tensor) { - var res = THSNN_Linear_forward(handle, tensor.Handle); + var res = THSNN_functional_linear(tensor.Handle, weight!.Handle, bias is not null ? bias.Handle : IntPtr.Zero); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - public Parameter? bias { - get { - var res = THSNN_Linear_bias(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return ((res == IntPtr.Zero) ? null : new Parameter(res)); + protected override void Dispose(bool disposing) + { + if (disposing) { + weight.Dispose(); + if (bias is not null) bias.Dispose(); } + } + + public Parameter bias { set { - THSNN_Linear_set_bias(handle, value?.Handle ?? IntPtr.Zero); - torch.CheckForErrors(); - ConditionallyRegisterParameter("bias", value); + _bias = value; + ConditionallyRegisterParameter("bias", bias); } + get => _bias; } + private Parameter _bias; - public Parameter? weight { - get { - var res = THSNN_Linear_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } + public Parameter weight { + get => _weight; set { - THSNN_Linear_set_weight(handle, value!.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); + if (value is null) throw new ArgumentNullException("weight"); + _weight = value; + ConditionallyRegisterParameter("weight", weight); } } + + private Parameter _weight; + } } @@ -70,12 +76,9 @@ public static partial class nn /// If set to false, the layer will not learn an additive bias. /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module - public static Linear Linear(long inputSize, long outputSize, bool hasBias = true, Device? device = null, ScalarType? dtype = null) + public static Linear Linear(long inputSize, long outputSize, bool hasBias = true, Device device = null, ScalarType? dtype = null) { - var res = THSNN_Linear_ctor(inputSize, outputSize, hasBias, out var boxedHandle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - - return new Linear(res, boxedHandle).MoveModule(device, dtype); + return new Linear(inputSize, outputSize, hasBias, device, dtype); } public static partial class functional @@ -87,7 +90,7 @@ public static partial class functional /// Weights of shape (Hout,Hin) or (Hin) /// Bias of shape (Hout) or () /// A tensor of shape (*,Hout) where '*' is the same as the subshape of the input. - public static Tensor linear(Tensor input, Tensor weights, Tensor? bias = null) + public static Tensor linear(Tensor input, Tensor weights, Tensor bias = null) { IntPtr bPtr = bias?.Handle ?? IntPtr.Zero; var res = THSNN_functional_linear(input.Handle, weights.Handle, bPtr); diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index 0c72316a2..f34bef3ca 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -2066,7 +2066,7 @@ public void TestConv1d() Assert.Equal(device.type, output.device_type); Assert.Equal(16, output.shape[0]); Assert.Equal(64, output.shape[1]); - Assert.Equal(26, output.shape[2]); + Assert.Equal(24, output.shape[2]); } } From 7b89432ae6f14fb31bdfade426d6b9f9a0762c98 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 6 Mar 2023 12:31:00 -0800 Subject: [PATCH 04/47] Slight modification to the experimental re-implementation of Linear. --- src/TorchSharp/NN/Linear.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/TorchSharp/NN/Linear.cs b/src/TorchSharp/NN/Linear.cs index 971994665..787dc5175 100644 --- a/src/TorchSharp/NN/Linear.cs +++ b/src/TorchSharp/NN/Linear.cs @@ -28,9 +28,7 @@ internal Linear(long inputSize, long outputSize, bool hasBias = true, Device dev public override Tensor forward(Tensor tensor) { - var res = THSNN_functional_linear(tensor.Handle, weight!.Handle, bias is not null ? bias.Handle : IntPtr.Zero); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.linear(tensor, weight, bias); } protected override void Dispose(bool disposing) From bf32faf19b235d5370f03c491b3062ef2401b74f Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 6 Mar 2023 16:43:54 -0800 Subject: [PATCH 05/47] Implemented a number of modules as managed code calling into functional APIs. --- src/Native/LibTorchSharp/THSConvolution.cpp | 212 ------------------ src/Native/LibTorchSharp/THSNN.cpp | 34 --- src/Native/LibTorchSharp/THSNN.h | 42 ---- src/TorchSharp/NN/Linear.cs | 45 ++-- src/TorchSharp/NN/Module.cs | 4 +- src/TorchSharp/NN/Padding/ConstantPad1d.cs | 32 +-- src/TorchSharp/NN/Padding/ConstantPad2d.cs | 32 +-- src/TorchSharp/NN/Padding/ConstantPad3d.cs | 32 +-- src/TorchSharp/NN/Padding/PadBase.cs | 47 ++++ src/TorchSharp/NN/Padding/ReflectionPad1d.cs | 32 +-- src/TorchSharp/NN/Padding/ReflectionPad2d.cs | 32 +-- src/TorchSharp/NN/Padding/ReflectionPad3d.cs | 32 +-- src/TorchSharp/NN/Padding/ReplicationPad1d.cs | 32 +-- src/TorchSharp/NN/Padding/ReplicationPad2d.cs | 34 +-- src/TorchSharp/NN/Padding/ReplicationPad3d.cs | 32 +-- src/TorchSharp/NN/Padding/ZeroPad2d.cs | 32 +-- src/TorchSharp/NN/Parameter.cs | 7 +- src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 90 -------- 18 files changed, 121 insertions(+), 682 deletions(-) create mode 100644 src/TorchSharp/NN/Padding/PadBase.cs diff --git a/src/Native/LibTorchSharp/THSConvolution.cpp b/src/Native/LibTorchSharp/THSConvolution.cpp index e1500d939..fb51e4c91 100644 --- a/src/Native/LibTorchSharp/THSConvolution.cpp +++ b/src/Native/LibTorchSharp/THSConvolution.cpp @@ -408,218 +408,6 @@ Tensor THSNN_FractionalMaxPool3d_forward_with_indices(const NNModule module, con return ResultTensor(std::get<0>(res)); } -NNModule THSNN_ZeroPad2d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ZeroPad2dOptions(padding); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ZeroPad2d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ZeroPad2dOptions({ padding_left, padding_right, padding_top, padding_bottom }); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ZeroPad2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ConstantPad1d_ctor(const double value, const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ConstantPad1dOptions(padding, value); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ConstantPad1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ConstantPad2d_ctor(const double value, const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ConstantPad2dOptions(padding, value); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ConstantPad2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ConstantPad3d_ctor(const double value, const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ConstantPad3dOptions(padding, value); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ConstantPad3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ConstantPad1d_ctor_tuple(const double value, const int64_t padding_left, const int64_t padding_right, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ConstantPad1dOptions({ padding_left, padding_right }, value); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ConstantPad2d_ctor_tuple(const double value, const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ConstantPad2dOptions({ padding_left, padding_right, padding_top, padding_bottom }, value); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ConstantPad3d_ctor_tuple(const double value, const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, const int64_t padding_front, const int64_t padding_back, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ConstantPad3dOptions({ padding_left, padding_right, padding_top, padding_bottom, padding_front, padding_back }, value); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ReplicationPad1d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReplicationPad1dOptions(padding); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ReplicationPad1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ReplicationPad2d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReplicationPad2dOptions(padding); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ReplicationPad2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ReplicationPad3d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReplicationPad3dOptions(padding); - res = create_module(opts, outAsAnyModule); - ); -} - - -Tensor THSNN_ReplicationPad3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ReplicationPad1d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReplicationPad1dOptions({ padding_left, padding_right }); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ReplicationPad2d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReplicationPad2dOptions({ padding_left, padding_right, padding_top, padding_bottom }); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ReplicationPad3d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, const int64_t padding_front, const int64_t padding_back, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReplicationPad3dOptions({ padding_left, padding_right, padding_top, padding_bottom, padding_front, padding_back }); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ReflectionPad1d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReflectionPad1dOptions(padding); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ReflectionPad1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ReflectionPad2d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReflectionPad2dOptions(padding); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ReflectionPad2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ReflectionPad3d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReflectionPad3dOptions(padding); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ReflectionPad3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ReflectionPad1d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReflectionPad1dOptions({ padding_left, padding_right }); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ReflectionPad2d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReflectionPad2dOptions({ padding_left, padding_right, padding_top, padding_bottom }); - res = create_module(opts, outAsAnyModule); - ); -} - -NNModule THSNN_ReflectionPad3d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, const int64_t padding_front, const int64_t padding_back, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReflectionPad3dOptions({ padding_left, padding_right, padding_top, padding_bottom, padding_front, padding_back }); - res = create_module(opts, outAsAnyModule); - ); -} - - template void ApplyPaddingMode(T& opts, const int64_t padding) { diff --git a/src/Native/LibTorchSharp/THSNN.cpp b/src/Native/LibTorchSharp/THSNN.cpp index 974b897fa..86c73042d 100644 --- a/src/Native/LibTorchSharp/THSNN.cpp +++ b/src/Native/LibTorchSharp/THSNN.cpp @@ -16,40 +16,6 @@ Tensor THSNN_Identity_forward(const NNModule module, const Tensor tensor) CATCH_TENSOR((*module)->as()->forward(*tensor)); } -NNModule THSNN_Linear_ctor(const int64_t input_size, const int64_t output_size, const bool bias, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LinearOptions(input_size, output_size).bias(bias); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Linear_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_Linear_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_Linear_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_Linear_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_Linear_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - Tensor THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias) { CATCH_TENSOR(bias == nullptr ? diff --git a/src/Native/LibTorchSharp/THSNN.h b/src/Native/LibTorchSharp/THSNN.h index 0117d9b50..9890e25e6 100644 --- a/src/Native/LibTorchSharp/THSNN.h +++ b/src/Native/LibTorchSharp/THSNN.h @@ -94,42 +94,6 @@ EXPORT_API(Tensor) THSNN_LPPool1d_forward(const NNModule module, const Tensor EXPORT_API(NNModule) THSNN_LPPool2d_ctor(double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, bool ceil_mode, NNAnyModule* outAsAnyModule); EXPORT_API(Tensor) THSNN_LPPool2d_forward(const NNModule module, const Tensor tensor); -// Padding - -EXPORT_API(NNModule) THSNN_ZeroPad2d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ZeroPad2d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ZeroPad2d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_ConstantPad1d_ctor(const double value, const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ConstantPad1d_ctor_tuple(const double value, const int64_t padding_left, const int64_t padding_right, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ConstantPad1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_ConstantPad2d_ctor(const double value, const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ConstantPad2d_ctor_tuple(const double value, const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ConstantPad2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_ConstantPad3d_ctor(const double value, const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ConstantPad3d_ctor_tuple(const double value, const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, const int64_t padding_front, const int64_t padding_back, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ConstantPad3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_ReplicationPad1d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ReplicationPad1d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ReplicationPad1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_ReplicationPad2d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ReplicationPad2d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ReplicationPad2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_ReplicationPad3d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ReplicationPad3d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, const int64_t padding_front, const int64_t padding_back, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ReplicationPad3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_ReflectionPad1d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ReflectionPad1d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ReflectionPad1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_ReflectionPad2d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ReflectionPad2d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ReflectionPad2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_ReflectionPad3d_ctor(const int64_t padding, NNAnyModule* outAsAnyModule); -EXPORT_API(NNModule) THSNN_ReflectionPad3d_ctor_tuple(const int64_t padding_left, const int64_t padding_right, const int64_t padding_top, const int64_t padding_bottom, const int64_t padding_front, const int64_t padding_back, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ReflectionPad3d_forward(const NNModule module, const Tensor tensor); - // Convolution EXPORT_API(NNModule) THSNN_Conv1d_ctor(const int64_t inputChannel, const int64_t outputChannel, const int64_t kernelSize, const int64_t stride, const int64_t padding, const int64_t dilation, const int64_t paddingMode, const int64_t groups, const bool bias, NNAnyModule* outAsAnyModule); @@ -322,12 +286,6 @@ EXPORT_API(Tensor) THSNN_feature_alpha_dropout(const Tensor input, const double EXPORT_API(NNModule) THSNN_Identity_ctor(NNAnyModule* outAsAnyModule); EXPORT_API(Tensor) THSNN_Identity_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Linear_ctor(const int64_t input_size, const int64_t output_size, const bool with_bias, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Linear_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_Linear_bias(const NNModule module); -EXPORT_API(void) THSNN_Linear_set_bias(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_Linear_weight(const NNModule module); -EXPORT_API(void) THSNN_Linear_set_weight(const NNModule module, const Tensor tensor); EXPORT_API(Tensor) THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias); EXPORT_API(Tensor) THSNN_functional_bilinear(const Tensor input1, const Tensor input2, const Tensor weights, const Tensor bias); diff --git a/src/TorchSharp/NN/Linear.cs b/src/TorchSharp/NN/Linear.cs index 787dc5175..7c6654a1b 100644 --- a/src/TorchSharp/NN/Linear.cs +++ b/src/TorchSharp/NN/Linear.cs @@ -4,6 +4,7 @@ using static TorchSharp.torch.nn; using static TorchSharp.PInvoke.LibTorchSharp; +#nullable enable namespace TorchSharp { using Modules; @@ -12,53 +13,57 @@ namespace Modules { public sealed class Linear : torch.nn.Module { - internal Linear(long inputSize, long outputSize, bool hasBias = true, Device device = null, ScalarType? dtype = null) : base(nameof(Linear)) + internal Linear(long inputSize, long outputSize, bool hasBias = true, Device? device = null, ScalarType? dtype = null) : base(nameof(Linear)) { weight = torch.empty(outputSize, inputSize, device: device, dtype: dtype).AsParameter(); - init.kaiming_uniform_(weight, a: Math.Sqrt(5)); - + init.kaiming_uniform_(weight, a: _sqrt5); + if (hasBias) { bias = torch.empty(outputSize, device: device, dtype: dtype).AsParameter(); var (fanIn, _) = init.CalculateFanInAndFanOut(weight); var bound = fanIn > 0 ? 1 / Math.Sqrt(fanIn) : 0; - init.uniform_(bias, -bound, bound); + init.uniform_(_bias, -bound, bound); } //NOTE: it's important not to call 'RegisterComponents' here. } public override Tensor forward(Tensor tensor) { - return torch.nn.functional.linear(tensor, weight, bias); + return torch.nn.functional.linear(tensor, _weight!, _bias); } protected override void Dispose(bool disposing) { if (disposing) { - weight.Dispose(); - if (bias is not null) bias.Dispose(); + _weight?.Dispose(); + _bias?.Dispose(); } } - public Parameter bias { + public Parameter? bias { + get => _bias; set { - _bias = value; - ConditionallyRegisterParameter("bias", bias); + _bias?.Dispose(); + _bias = value?.DetachFromDisposeScope() as Parameter; + ConditionallyRegisterParameter(nameof(bias), _bias); } - get => _bias; } - private Parameter _bias; + private Parameter? _bias; public Parameter weight { - get => _weight; + get => _weight!; set { - if (value is null) throw new ArgumentNullException("weight"); - _weight = value; - ConditionallyRegisterParameter("weight", weight); + if (value is null) throw new ArgumentNullException(nameof(weight)); + if (value.Handle != _weight?.Handle) { + _weight?.Dispose(); + _weight = (value.DetachFromDisposeScope() as Parameter)!; + ConditionallyRegisterParameter(nameof(weight), _weight); + } } } - private Parameter _weight; - + private Parameter? _weight; + private static readonly double _sqrt5 = Math.Sqrt(5); } } @@ -74,7 +79,7 @@ public static partial class nn /// If set to false, the layer will not learn an additive bias. /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module - public static Linear Linear(long inputSize, long outputSize, bool hasBias = true, Device device = null, ScalarType? dtype = null) + public static Linear Linear(long inputSize, long outputSize, bool hasBias = true, Device? device = null, ScalarType? dtype = null) { return new Linear(inputSize, outputSize, hasBias, device, dtype); } @@ -88,7 +93,7 @@ public static partial class functional /// Weights of shape (Hout,Hin) or (Hin) /// Bias of shape (Hout) or () /// A tensor of shape (*,Hout) where '*' is the same as the subshape of the input. - public static Tensor linear(Tensor input, Tensor weights, Tensor bias = null) + public static Tensor linear(Tensor input, Tensor weights, Tensor? bias = null) { IntPtr bPtr = bias?.Handle ?? IntPtr.Zero; var res = THSNN_functional_linear(input.Handle, weights.Handle, bPtr); diff --git a/src/TorchSharp/NN/Module.cs b/src/TorchSharp/NN/Module.cs index 1dda5ea7d..7f9aba778 100644 --- a/src/TorchSharp/NN/Module.cs +++ b/src/TorchSharp/NN/Module.cs @@ -125,10 +125,10 @@ protected virtual void Dispose(bool disposing) if (disposing && !handle.IsInvalid) { foreach (var (_, p) in named_buffers(false)) { - p.Dispose(); + p.DetachFromDisposeScope().Dispose(); } foreach (var (_, b) in named_parameters(false)) { - b.Dispose(); + b.DetachFromDisposeScope().Dispose(); } foreach (var (_, m) in named_modules()) { diff --git a/src/TorchSharp/NN/Padding/ConstantPad1d.cs b/src/TorchSharp/NN/Padding/ConstantPad1d.cs index e7ac52d77..d20e65527 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad1d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad1d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ConstantPad1d module. /// - public sealed class ConstantPad1d : torch.nn.Module + public sealed class ConstantPad1d : PadBase { - internal ConstantPad1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ConstantPad1d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ConstantPad1d(double value, params long[] padding) : base(nameof(ConstantPad1d), PaddingModes.Constant, value, padding) { } } } @@ -50,9 +30,7 @@ public static partial class nn /// public static ConstantPad1d ConstantPad1d(long padding, double value) { - var handle = THSNN_ConstantPad1d_ctor(value, padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ConstantPad1d(handle, boxedHandle); + return new ConstantPad1d(value, padding, padding); } /// @@ -63,9 +41,7 @@ public static ConstantPad1d ConstantPad1d(long padding, double value) /// public static ConstantPad1d ConstantPad1d((long, long) padding, double value) { - var handle = THSNN_ConstantPad1d_ctor_tuple(value, padding.Item1, padding.Item2, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ConstantPad1d(handle, boxedHandle); + return new ConstantPad1d(value, padding.Item1, padding.Item2); } } } diff --git a/src/TorchSharp/NN/Padding/ConstantPad2d.cs b/src/TorchSharp/NN/Padding/ConstantPad2d.cs index 16110a3be..03b941fde 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad2d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad2d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ConstantPad2d module. /// - public sealed class ConstantPad2d : torch.nn.Module + public sealed class ConstantPad2d : PadBase { - internal ConstantPad2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ConstantPad2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ConstantPad2d(double value, params long[] padding) : base(nameof(ConstantPad2d), PaddingModes.Constant, value, padding) { } } } @@ -50,9 +30,7 @@ public static partial class nn /// public static ConstantPad2d ConstantPad2d(long padding, double value) { - var handle = THSNN_ConstantPad2d_ctor(value, padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ConstantPad2d(handle, boxedHandle); + return new ConstantPad2d(value, padding, padding, padding, padding); } /// @@ -63,9 +41,7 @@ public static ConstantPad2d ConstantPad2d(long padding, double value) /// public static ConstantPad2d ConstantPad2d((long, long, long, long) padding, double value) { - var handle = THSNN_ConstantPad2d_ctor_tuple(value, padding.Item1, padding.Item2, padding.Item3, padding.Item4, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ConstantPad2d(handle, boxedHandle); + return new ConstantPad2d(value, padding.Item1, padding.Item2, padding.Item3, padding.Item4); } } } diff --git a/src/TorchSharp/NN/Padding/ConstantPad3d.cs b/src/TorchSharp/NN/Padding/ConstantPad3d.cs index d65a20bd5..1bc14ab27 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad3d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad3d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ConstantPad3d module. /// - public sealed class ConstantPad3d : torch.nn.Module + public sealed class ConstantPad3d : PadBase { - internal ConstantPad3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ConstantPad3d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ConstantPad3d(double value, params long[] padding) : base(nameof(ConstantPad3d), PaddingModes.Constant, value, padding) { } } } @@ -50,9 +30,7 @@ public static partial class nn /// public static ConstantPad3d ConstantPad3d(long padding, double value) { - var handle = THSNN_ConstantPad3d_ctor(value, padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ConstantPad3d(handle, boxedHandle); + return new ConstantPad3d(value, padding, padding, padding, padding, padding, padding); } /// @@ -63,9 +41,7 @@ public static ConstantPad3d ConstantPad3d(long padding, double value) /// public static ConstantPad3d ConstantPad3d((long, long, long, long, long, long) padding, double value) { - var handle = THSNN_ConstantPad3d_ctor_tuple(value, padding.Item1, padding.Item2, padding.Item3, padding.Item4, padding.Item5, padding.Item6, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ConstantPad3d(handle, boxedHandle); + return new ConstantPad3d(value, padding.Item1, padding.Item2, padding.Item3, padding.Item4, padding.Item5, padding.Item6); } } } diff --git a/src/TorchSharp/NN/Padding/PadBase.cs b/src/TorchSharp/NN/Padding/PadBase.cs new file mode 100644 index 000000000..022a9b66b --- /dev/null +++ b/src/TorchSharp/NN/Padding/PadBase.cs @@ -0,0 +1,47 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. +using System; +using static TorchSharp.torch; +using static TorchSharp.PInvoke.LibTorchSharp; + +namespace TorchSharp +{ + using Modules; + + namespace Modules + { + /// + /// This class is used to represent the base of all padding-related modules. + /// + public class PadBase : nn.Module + { + protected PadBase(string name, PaddingModes mode, double value, params long[] padding) : base(name) + { + _value = value; + _padding = padding; + _paddingMode = mode; + } + + /// + /// Forward pass. + /// + /// Input tensor + /// + public override Tensor forward(Tensor input) + { + return nn.functional.pad(input, _padding, _paddingMode, _value); + } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; + + private PaddingModes _paddingMode; + private long[] _padding; + private double _value = 0.0; + } + } +} diff --git a/src/TorchSharp/NN/Padding/ReflectionPad1d.cs b/src/TorchSharp/NN/Padding/ReflectionPad1d.cs index a4d655d16..02e78333f 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad1d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad1d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ReflectionPad1d module. /// - public sealed class ReflectionPad1d : torch.nn.Module + public sealed class ReflectionPad1d : PadBase { - internal ReflectionPad1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ReflectionPad1d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ReflectionPad1d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } } } @@ -49,9 +29,7 @@ public static partial class nn /// public static ReflectionPad1d ReflectionPad1d(long padding) { - var handle = THSNN_ReflectionPad1d_ctor(padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReflectionPad1d(handle, boxedHandle); + return new ReflectionPad1d(padding, padding); } /// @@ -61,9 +39,7 @@ public static ReflectionPad1d ReflectionPad1d(long padding) /// public static ReflectionPad1d ReflectionPad1d((long, long) padding) { - var handle = THSNN_ReflectionPad1d_ctor_tuple(padding.Item1, padding.Item2, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReflectionPad1d(handle, boxedHandle); + return new ReflectionPad1d(padding.Item1, padding.Item2); } } } diff --git a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs index 9777d6332..3ee717d0b 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ReflectionPad2d module. /// - public sealed class ReflectionPad2d : torch.nn.Module + public sealed class ReflectionPad2d : PadBase { - internal ReflectionPad2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ReflectionPad2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ReflectionPad2d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } } } @@ -49,9 +29,7 @@ public static partial class nn /// public static ReflectionPad2d ReflectionPad2d(long padding) { - var handle = THSNN_ReflectionPad2d_ctor(padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReflectionPad2d(handle, boxedHandle); + return new ReflectionPad2d(padding, padding, padding, padding); } /// @@ -61,9 +39,7 @@ public static ReflectionPad2d ReflectionPad2d(long padding) /// public static ReflectionPad2d ReflectionPad2d((long, long, long, long) padding) { - var handle = THSNN_ReflectionPad2d_ctor_tuple(padding.Item1, padding.Item2, padding.Item3, padding.Item4, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReflectionPad2d(handle, boxedHandle); + return new ReflectionPad2d(padding.Item1, padding.Item2, padding.Item3, padding.Item4); } } } diff --git a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs index 2e029396a..2c3696c0b 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ReflectionPad3d module. /// - public sealed class ReflectionPad3d : torch.nn.Module + public sealed class ReflectionPad3d : PadBase { - internal ReflectionPad3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ReflectionPad3d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ReflectionPad3d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } } } @@ -49,9 +29,7 @@ public static partial class nn /// public static ReflectionPad3d ReflectionPad3d(long padding) { - var handle = THSNN_ReflectionPad3d_ctor(padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReflectionPad3d(handle, boxedHandle); + return new ReflectionPad3d(padding, padding, padding, padding, padding, padding); } /// @@ -61,9 +39,7 @@ public static ReflectionPad3d ReflectionPad3d(long padding) /// public static ReflectionPad3d ReflectionPad3d((long, long, long, long, long, long) padding) { - var handle = THSNN_ReflectionPad3d_ctor_tuple(padding.Item1, padding.Item2, padding.Item3, padding.Item4, padding.Item5, padding.Item6, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReflectionPad3d(handle, boxedHandle); + return new ReflectionPad3d(padding.Item1, padding.Item2, padding.Item3, padding.Item4, padding.Item5, padding.Item6); } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad1d.cs b/src/TorchSharp/NN/Padding/ReplicationPad1d.cs index 2a50b830b..c81cb84b4 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad1d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad1d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ReplicationPad1d module. /// - public sealed class ReplicationPad1d : torch.nn.Module + public sealed class ReplicationPad1d : PadBase { - internal ReplicationPad1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ReplicationPad1d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ReplicationPad1d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } } } @@ -49,9 +29,7 @@ public static partial class nn /// public static ReplicationPad1d ReplicationPad1d(long padding) { - var handle = THSNN_ReplicationPad1d_ctor(padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReplicationPad1d(handle, boxedHandle); + return new ReplicationPad1d(padding, padding); } /// @@ -61,9 +39,7 @@ public static ReplicationPad1d ReplicationPad1d(long padding) /// public static ReplicationPad1d ReplicationPad1d((long, long) padding) { - var handle = THSNN_ReplicationPad1d_ctor_tuple(padding.Item1, padding.Item2, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReplicationPad1d(handle, boxedHandle); + return new ReplicationPad1d(padding.Item1, padding.Item2); } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs index e7d30e145..d40ed9841 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ReplicationPad2d module. /// - public sealed class ReplicationPad2d : torch.nn.Module + public sealed class ReplicationPad2d : PadBase { - internal ReplicationPad2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ReplicationPad2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ReplicationPad2d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } } } @@ -43,15 +23,13 @@ public static partial class torch public static partial class nn { /// - /// Pads the input tensor using replication of the input boundary. + /// Pads the input tensor using the replication of the input boundary. /// /// The size of the padding. /// public static ReplicationPad2d ReplicationPad2d(long padding) { - var handle = THSNN_ReplicationPad2d_ctor(padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReplicationPad2d(handle, boxedHandle); + return new ReplicationPad2d(padding, padding, padding, padding); } /// @@ -61,9 +39,7 @@ public static ReplicationPad2d ReplicationPad2d(long padding) /// public static ReplicationPad2d ReplicationPad2d((long, long, long, long) padding) { - var handle = THSNN_ReplicationPad2d_ctor_tuple(padding.Item1, padding.Item2, padding.Item3, padding.Item4, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReplicationPad2d(handle, boxedHandle); + return new ReplicationPad2d(padding.Item1, padding.Item2, padding.Item3, padding.Item4); } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs index 34d71ed25..fc72202f6 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ReplicationPad3d module. /// - public sealed class ReplicationPad3d : torch.nn.Module + public sealed class ReplicationPad3d : PadBase { - internal ReplicationPad3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ReplicationPad3d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ReplicationPad3d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } } } @@ -49,9 +29,7 @@ public static partial class nn /// public static ReplicationPad3d ReplicationPad3d(long padding) { - var handle = THSNN_ReplicationPad3d_ctor(padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReplicationPad3d(handle, boxedHandle); + return new ReplicationPad3d(padding, padding, padding, padding, padding, padding); } /// @@ -61,9 +39,7 @@ public static ReplicationPad3d ReplicationPad3d(long padding) /// public static ReplicationPad3d ReplicationPad3d((long, long, long, long, long, long) padding) { - var handle = THSNN_ReplicationPad3d_ctor_tuple(padding.Item1, padding.Item2, padding.Item3, padding.Item4, padding.Item5, padding.Item6, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReplicationPad3d(handle, boxedHandle); + return new ReplicationPad3d(padding.Item1, padding.Item2, padding.Item3, padding.Item4, padding.Item5, padding.Item6); } } } diff --git a/src/TorchSharp/NN/Padding/ZeroPad2d.cs b/src/TorchSharp/NN/Padding/ZeroPad2d.cs index bb19cbe1b..01ec8d32b 100644 --- a/src/TorchSharp/NN/Padding/ZeroPad2d.cs +++ b/src/TorchSharp/NN/Padding/ZeroPad2d.cs @@ -12,29 +12,9 @@ namespace Modules /// /// This class is used to represent a ZeroPad2d module. /// - public sealed class ZeroPad2d : torch.nn.Module + public sealed class ZeroPad2d : PadBase { - internal ZeroPad2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ZeroPad2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + internal ZeroPad2d(params long[] padding) : base(nameof(ZeroPad2d), PaddingModes.Zeros, 0, padding) { } } } @@ -49,9 +29,7 @@ public static partial class nn /// public static ZeroPad2d ZeroPad2d(long padding) { - var handle = THSNN_ZeroPad2d_ctor(padding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ZeroPad2d(handle, boxedHandle); + return new ZeroPad2d(padding, padding, padding, padding); } /// @@ -61,9 +39,7 @@ public static ZeroPad2d ZeroPad2d(long padding) /// public static ZeroPad2d ZeroPad2d((long, long, long, long) padding) { - var handle = THSNN_ZeroPad2d_ctor_tuple(padding.Item1, padding.Item2, padding.Item3, padding.Item4, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ZeroPad2d(handle, boxedHandle); + return new ZeroPad2d(padding.Item1, padding.Item2, padding.Item3, padding.Item4); } } } diff --git a/src/TorchSharp/NN/Parameter.cs b/src/TorchSharp/NN/Parameter.cs index 81e9051d8..4c1faa01e 100644 --- a/src/TorchSharp/NN/Parameter.cs +++ b/src/TorchSharp/NN/Parameter.cs @@ -26,6 +26,12 @@ public class Parameter : Tensor public Parameter(Tensor data, bool requires_grad = true) : base(data.with_requires_grad(requires_grad).MoveHandle()) { + var scope = data.OwningDisposeScope; + if (scope is not null) { + this.OwningDisposeScope = scope; + scope.Include(this); + scope.Detach(data); + } } /// @@ -35,7 +41,6 @@ public Parameter(Tensor data, bool requires_grad = true) : internal Parameter(System.IntPtr handle) : base(handle) { } - }; } diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index dc24a02a6..deba93d55 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -1092,96 +1092,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_LocalResponseNorm_ctor(long size, double alpha, double beta, double k, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad1d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad1d_ctor(double value, long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad1d_ctor_tuple(double value, long padding_left, long padding_right, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad2d_ctor(double value, long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad2d_ctor_tuple(double value, long padding_left, long padding_right, long padding_top, long padding_bottom, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad3d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad3d_ctor(double value, long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ConstantPad3d_ctor_tuple(double value, long padding_left, long padding_right, long padding_top, long padding_bottom, long padding_front, long padding_back, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad1d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad1d_ctor(long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad1d_ctor_tuple(long padding_left, long padding_right, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad2d_ctor(long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad2d_ctor_tuple(long padding_left, long padding_right, long padding_top, long padding_bottom, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad3d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad3d_ctor(long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReflectionPad3d_ctor_tuple(long padding_left, long padding_right, long padding_top, long padding_bottom, long padding_front, long padding_back, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad1d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad1d_ctor(long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad1d_ctor_tuple(long padding_left, long padding_right, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad2d_ctor(long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad2d_ctor_tuple(long padding_left, long padding_right, long padding_top, long padding_bottom, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad3d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad3d_ctor(long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReplicationPad3d_ctor_tuple(long padding_left, long padding_right, long padding_top, long padding_bottom, long padding_front, long padding_back, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ZeroPad2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ZeroPad2d_ctor(long padding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ZeroPad2d_ctor_tuple(long padding_left, long padding_right, long padding_top, long padding_bottom, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_AdaptiveAvgPool1d_forward(IntPtr module, IntPtr tensor); From d5b64d3656af499391f49b30a156c839b7dd2575 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 7 Mar 2023 08:34:09 -0800 Subject: [PATCH 06/47] More modules implemented without native module instances --- src/TorchSharp/NN/Bilinear.cs | 79 +++++++++++++++------------- src/TorchSharp/NN/Dropout.cs | 25 ++++----- src/TorchSharp/NN/Flatten.cs | 31 +++++------ src/TorchSharp/NN/Identity.cs | 20 ++----- src/TorchSharp/NN/Padding/PadBase.cs | 10 +--- src/TorchSharp/NN/ParamLessModule.cs | 46 ++++++++++++++++ src/TorchSharp/NN/Unflatten.cs | 27 +++------- test/TorchSharpTest/NN.cs | 6 ++- 8 files changed, 127 insertions(+), 117 deletions(-) create mode 100644 src/TorchSharp/NN/ParamLessModule.cs diff --git a/src/TorchSharp/NN/Bilinear.cs b/src/TorchSharp/NN/Bilinear.cs index 66d9ba2cf..829d1532c 100644 --- a/src/TorchSharp/NN/Bilinear.cs +++ b/src/TorchSharp/NN/Bilinear.cs @@ -13,46 +13,57 @@ namespace Modules { public sealed class Bilinear : Module { - internal Bilinear(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public new static Bilinear Load(string modelPath) + internal Bilinear(long in1_features, long in2_features, long out_features, bool hasBias = true, Device? device = null, ScalarType? dtype = null) : base(nameof(Bilinear)) { - var res = Module.Load(modelPath); - return new Bilinear(res.handle.DangerousGetHandle(), IntPtr.Zero); + weight = torch.empty(out_features, in1_features, in2_features, device: device, dtype: dtype).AsParameter(); + var bound = 1 / Math.Sqrt(weight!.shape[1]); + + init.uniform_(_weight, -bound, bound); + + if (hasBias) { + bias = torch.empty(out_features, device: device, dtype: dtype).AsParameter(); + var (fanIn, _) = init.CalculateFanInAndFanOut(weight); + init.uniform_(_bias, -bound, bound); + } + //NOTE: it's important not to call 'RegisterComponents' here. } public override Tensor forward(Tensor input1, Tensor input2) { - var res = THSNN_Bilinear_forward(handle, input1.Handle, input2.Handle); - if (res == IntPtr.Zero) { CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.bilinear(input1, input2, _weight!, _bias); } - public Parameter? bias { - get { - var res = THSNN_Bilinear_bias(handle); - if (res == IntPtr.Zero) { CheckForErrors(); } - return ((res == IntPtr.Zero) ? null : new Parameter(res)); + protected override void Dispose(bool disposing) + { + if (disposing) { + _weight?.Dispose(); + _bias?.Dispose(); } + } + + public Parameter? bias { + get => _bias; set { - THSNN_Bilinear_set_bias(handle, value?.Handle ?? IntPtr.Zero); - CheckForErrors(); - ConditionallyRegisterParameter("bias", value); + _bias?.Dispose(); + _bias = value?.DetachFromDisposeScope() as Parameter; + ConditionallyRegisterParameter(nameof(bias), _bias); } } + private Parameter? _bias; - public Parameter? weight { - get { - var res = THSNN_Bilinear_weight(handle); - if (res == IntPtr.Zero) { CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } + public Parameter weight { + get => _weight!; set { - THSNN_Bilinear_set_weight(handle, value?.Handle ?? IntPtr.Zero); - CheckForErrors(); - ConditionallyRegisterParameter("weight", value); + if (value is null) throw new ArgumentNullException(nameof(weight)); + if (value.Handle != _weight?.Handle) { + _weight?.Dispose(); + _weight = (value.DetachFromDisposeScope() as Parameter)!; + ConditionallyRegisterParameter(nameof(weight), _weight); + } } } + + private Parameter? _weight; } } @@ -64,19 +75,16 @@ public static partial class nn /// /// Applies a bilinear transformation to the incoming data /// - /// size of each first input sample - /// size of each second input sample - /// size of each output sample + /// size of each first input sample + /// size of each second input sample + /// size of each output sample /// If set to false, the layer will not learn an additive bias /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module /// - public static Bilinear Bilinear(long in1Features, long in2Features, long outputSize, bool hasBias = true, Device? device = null, ScalarType? dtype = null) + public static Bilinear Bilinear(long in1_features, long in2_features, long out_features, bool hasBias = true, Device? device = null, ScalarType? dtype = null) { - var res = THSNN_Bilinear_ctor(in1Features, in2Features, outputSize, hasBias, out var boxedHandle); - if (res == IntPtr.Zero) { CheckForErrors(); } - - return new Bilinear(res, boxedHandle).MoveModule(device, dtype); + return new Bilinear(in1_features, in2_features, out_features, hasBias, device, dtype); } public static partial class functional @@ -92,10 +100,7 @@ public static partial class functional /// The '*' sub-shape must be the same among the two inputs. public static Tensor bilinear(Tensor input1, Tensor input2, Tensor weight, Tensor? bias = null) { - IntPtr bPtr = bias?.Handle ?? IntPtr.Zero; - var res = THSNN_functional_bilinear(input1.Handle, input2.Handle, weight.Handle, bPtr); - if (res == IntPtr.Zero) { CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.bilinear(input1, input2, weight, bias); } } } diff --git a/src/TorchSharp/NN/Dropout.cs b/src/TorchSharp/NN/Dropout.cs index 747edc080..76ff0fec1 100644 --- a/src/TorchSharp/NN/Dropout.cs +++ b/src/TorchSharp/NN/Dropout.cs @@ -12,9 +12,13 @@ namespace Modules /// /// This class is used to represent a dropout module. /// - public sealed class Dropout : torch.nn.Module + public sealed class Dropout : ParamLessModule { - internal Dropout(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal Dropout(double p = 0.5, bool inplace = false) : base(nameof(Dropout)) + { + this._p = p; + this._inplace = inplace; + } /// /// Forward pass. @@ -23,18 +27,11 @@ internal Dropout(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) /// public override Tensor forward(Tensor tensor) { - var res = THSNN_Dropout_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return nn.functional.dropout(tensor, _p, training, _inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + double _p = 0.5; + bool _inplace = false; } } @@ -51,9 +48,7 @@ public static partial class nn /// public static Dropout Dropout(double p = 0.5, bool inplace = false) { - var handle = THSNN_Dropout_ctor(p, inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Dropout(handle, boxedHandle); + return new Dropout(p, inplace); } public static partial class functional diff --git a/src/TorchSharp/NN/Flatten.cs b/src/TorchSharp/NN/Flatten.cs index 314de873a..bedbfb61c 100644 --- a/src/TorchSharp/NN/Flatten.cs +++ b/src/TorchSharp/NN/Flatten.cs @@ -10,28 +10,23 @@ namespace TorchSharp namespace Modules { /// - /// This class is used to represent a dropout module for 2d/3d convolutational layers. + /// This class is used to represent a flattening of the input tensors. /// - public sealed class Flatten : torch.nn.Module + public sealed class Flatten : ParamLessModule { - internal Flatten(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal Flatten(long startDim = 1, long endDim = -1) : base(nameof(Flatten)) { + _startDim = startDim; + _endDim = endDim; } public override Tensor forward(Tensor tensor) { - var res = THSNN_Flatten_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return tensor.flatten(_startDim, _endDim); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + private long _startDim; + private long _endDim; } } @@ -42,14 +37,12 @@ public static partial class nn /// /// Flattens a contiguous range of dims into a tensor. For use with Sequential. /// - /// First dim to flatten (default = 1). - /// Last dim to flatten (default = -1). + /// First dim to flatten (default = 1). + /// Last dim to flatten (default = -1). /// - public static Flatten Flatten(long startDim = 1, long endDim = -1) + public static Flatten Flatten(long start_dim = 1, long end_dim = -1) { - var handle = THSNN_Flatten_ctor(startDim, endDim, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Flatten(handle, boxedHandle); + return new Flatten(start_dim, end_dim); } } } diff --git a/src/TorchSharp/NN/Identity.cs b/src/TorchSharp/NN/Identity.cs index 84b6dd07f..172afe35a 100644 --- a/src/TorchSharp/NN/Identity.cs +++ b/src/TorchSharp/NN/Identity.cs @@ -10,24 +10,14 @@ namespace TorchSharp namespace Modules { - public sealed class Identity : torch.nn.Module + public sealed class Identity : ParamLessModule { - internal Identity(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal Identity() : base(nameof(Identity)) { } public override Tensor forward(Tensor tensor) { - var res = THSNN_Identity_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return tensor.alias(); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } @@ -41,9 +31,7 @@ public static partial class nn /// The same tensor as is input. public static Identity Identity() { - var res = THSNN_Identity_ctor(out var boxedHandle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Identity(res, boxedHandle); + return new Identity(); } } } diff --git a/src/TorchSharp/NN/Padding/PadBase.cs b/src/TorchSharp/NN/Padding/PadBase.cs index 022a9b66b..ed21f002a 100644 --- a/src/TorchSharp/NN/Padding/PadBase.cs +++ b/src/TorchSharp/NN/Padding/PadBase.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent the base of all padding-related modules. /// - public class PadBase : nn.Module + public class PadBase : ParamLessModule { protected PadBase(string name, PaddingModes mode, double value, params long[] padding) : base(name) { @@ -31,14 +31,6 @@ public override Tensor forward(Tensor input) return nn.functional.pad(input, _padding, _paddingMode, _value); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; - private PaddingModes _paddingMode; private long[] _padding; private double _value = 0.0; diff --git a/src/TorchSharp/NN/ParamLessModule.cs b/src/TorchSharp/NN/ParamLessModule.cs new file mode 100644 index 000000000..91b2cb2c1 --- /dev/null +++ b/src/TorchSharp/NN/ParamLessModule.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. +using System; +using static TorchSharp.torch; +using static TorchSharp.PInvoke.LibTorchSharp; + +namespace TorchSharp +{ + using Modules; + + namespace Modules + { + /// + /// Base class for all modules that do not have any parameters or buffers, and + /// for which the `_to()` implementation can therefore be simplified. + /// + public abstract class ParamLessModule : nn.Module + { + protected ParamLessModule(string name) : base(name) { } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; + } + + /// + /// Base class for all modules that do not have any parameters or buffers, and + /// for which the `_to()` implementation can therefore be simplified. + /// + public abstract class ParamLessModule : nn.Module + { + protected ParamLessModule(string name) : base(name) { } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; + } + } +} \ No newline at end of file diff --git a/src/TorchSharp/NN/Unflatten.cs b/src/TorchSharp/NN/Unflatten.cs index 2f5d9c4cb..7b4059f85 100644 --- a/src/TorchSharp/NN/Unflatten.cs +++ b/src/TorchSharp/NN/Unflatten.cs @@ -12,26 +12,21 @@ namespace Modules /// /// This class is used to represent an unflattening operation. /// - public sealed class Unflatten : torch.nn.Module + public sealed class Unflatten : ParamLessModule { - internal Unflatten(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal Unflatten(long dim, long[] unflattenedSize) : base(nameof(Unflatten)) { + this._dim = dim; + this._unflattenedSize = unflattenedSize; } public override Tensor forward(Tensor tensor) { - var res = THSNN_Unflatten_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return tensor.unflatten(_dim, _unflattenedSize); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + long _dim; + long[] _unflattenedSize; } } @@ -47,13 +42,7 @@ public static partial class nn /// public static Unflatten Unflatten(long dim, long[] unflattenedSize) { - unsafe { - fixed (long* pUnflattenedSize = unflattenedSize) { - var handle = THSNN_Unflatten_ctor(dim, (IntPtr)pUnflattenedSize, unflattenedSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { CheckForErrors(); } - return new Unflatten(handle, boxedHandle); - } - } + return new Unflatten(dim, unflattenedSize); } } } diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index 72103685c..d3bb3361b 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -325,6 +325,8 @@ public void TestIdentity() var input = torch.randn(new long[] { 1, 1000 }, device: device); var output = lin.call(input); + output[0, 511] = 10; // When we modify the copy, the original should be altered, too. + Assert.Equal(device.type, output.device_type); Assert.Equal(input.data(), output.data()); } @@ -4775,13 +4777,13 @@ public void TestFlatten() Assert.Equal(new long[] { 32, 360 }, output.shape); } - using (var flat = Flatten(startDim: 2)) { + using (var flat = Flatten(start_dim: 2)) { var output = flat.call(data); Assert.Equal(device.type, output.device_type); Assert.Equal(new long[] { 32, 3, 120 }, output.shape); } - using (var flat = Flatten(startDim: 0)) { + using (var flat = Flatten(start_dim: 0)) { var output = flat.call(data); Assert.Equal(device.type, output.device_type); Assert.Equal(new long[] { 32 * 360 }, output.shape); From 339e38141551b770e4e19100f4a3f719b32f6973 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 27 Mar 2023 15:16:50 -0700 Subject: [PATCH 07/47] Fixed infinite recursion in bilinear. --- src/TorchSharp/NN/Bilinear.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/TorchSharp/NN/Bilinear.cs b/src/TorchSharp/NN/Bilinear.cs index 829d1532c..a105257bc 100644 --- a/src/TorchSharp/NN/Bilinear.cs +++ b/src/TorchSharp/NN/Bilinear.cs @@ -100,7 +100,10 @@ public static partial class functional /// The '*' sub-shape must be the same among the two inputs. public static Tensor bilinear(Tensor input1, Tensor input2, Tensor weight, Tensor? bias = null) { - return torch.nn.functional.bilinear(input1, input2, weight, bias); + IntPtr bPtr = bias?.Handle ?? IntPtr.Zero; + var res = THSNN_functional_bilinear(input1.Handle, input2.Handle, weight.Handle, bPtr); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } } } From e311a075b642b1f64601d9c79e105940c7635650 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Thu, 18 May 2023 15:01:13 -0700 Subject: [PATCH 08/47] Corrected faulty merge. --- src/TorchSharp/NN/Padding/ConstantPad1d.cs | 2 +- src/TorchSharp/NN/Padding/ConstantPad2d.cs | 2 +- src/TorchSharp/NN/Padding/ConstantPad3d.cs | 2 +- src/TorchSharp/NN/Padding/PadBase.cs | 2 +- src/TorchSharp/NN/Padding/ReflectionPad1d.cs | 2 +- src/TorchSharp/NN/Padding/ReflectionPad2d.cs | 2 +- src/TorchSharp/NN/ParamLessModule.cs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/TorchSharp/NN/Padding/ConstantPad1d.cs b/src/TorchSharp/NN/Padding/ConstantPad1d.cs index d20e65527..ec905b4b7 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad1d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad1d.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. using System; using static TorchSharp.torch; -using static TorchSharp.PInvoke.LibTorchSharp; +using static TorchSharp.PInvoke.NativeMethods; namespace TorchSharp { diff --git a/src/TorchSharp/NN/Padding/ConstantPad2d.cs b/src/TorchSharp/NN/Padding/ConstantPad2d.cs index 03b941fde..9bc47b2be 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad2d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad2d.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. using System; using static TorchSharp.torch; -using static TorchSharp.PInvoke.LibTorchSharp; +using static TorchSharp.PInvoke.NativeMethods; namespace TorchSharp { diff --git a/src/TorchSharp/NN/Padding/ConstantPad3d.cs b/src/TorchSharp/NN/Padding/ConstantPad3d.cs index 1bc14ab27..4da9344e0 100644 --- a/src/TorchSharp/NN/Padding/ConstantPad3d.cs +++ b/src/TorchSharp/NN/Padding/ConstantPad3d.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. using System; using static TorchSharp.torch; -using static TorchSharp.PInvoke.LibTorchSharp; +using static TorchSharp.PInvoke.NativeMethods; namespace TorchSharp { diff --git a/src/TorchSharp/NN/Padding/PadBase.cs b/src/TorchSharp/NN/Padding/PadBase.cs index ed21f002a..20c0dde47 100644 --- a/src/TorchSharp/NN/Padding/PadBase.cs +++ b/src/TorchSharp/NN/Padding/PadBase.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. using System; using static TorchSharp.torch; -using static TorchSharp.PInvoke.LibTorchSharp; +using static TorchSharp.PInvoke.NativeMethods; namespace TorchSharp { diff --git a/src/TorchSharp/NN/Padding/ReflectionPad1d.cs b/src/TorchSharp/NN/Padding/ReflectionPad1d.cs index 02e78333f..780f77550 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad1d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad1d.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. using System; using static TorchSharp.torch; -using static TorchSharp.PInvoke.LibTorchSharp; +using static TorchSharp.PInvoke.NativeMethods; namespace TorchSharp { diff --git a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs index 3ee717d0b..1aa15f2e8 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. using System; using static TorchSharp.torch; -using static TorchSharp.PInvoke.LibTorchSharp; +using static TorchSharp.PInvoke.NativeMethods; namespace TorchSharp { diff --git a/src/TorchSharp/NN/ParamLessModule.cs b/src/TorchSharp/NN/ParamLessModule.cs index 91b2cb2c1..c2a274a52 100644 --- a/src/TorchSharp/NN/ParamLessModule.cs +++ b/src/TorchSharp/NN/ParamLessModule.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. using System; using static TorchSharp.torch; -using static TorchSharp.PInvoke.LibTorchSharp; +using static TorchSharp.PInvoke.NativeMethods; namespace TorchSharp { From 2cfde4ecb464493257cbac2d42d6fda06430fafc Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Fri, 23 Jun 2023 11:19:13 -0700 Subject: [PATCH 09/47] Adding more VS Copilot-driven unit tests for TV. --- src/TorchVision/Functional.cs | 11 +- test/TorchSharpTest/TestTorchVision.cs | 396 ++++++++++++++++++++++++- 2 files changed, 395 insertions(+), 12 deletions(-) diff --git a/src/TorchVision/Functional.cs b/src/TorchVision/Functional.cs index b46c80448..fc261d68a 100644 --- a/src/TorchVision/Functional.cs +++ b/src/TorchVision/Functional.cs @@ -681,12 +681,17 @@ public static Tensor posterize(Tensor input, int bits) /// Resize the input image to the given size. /// /// An image tensor. - /// - /// - /// + /// The height of the resized image. Must be > 0. + /// The width of the resized image. Must be > 0. + /// The maximum allowed for the longer edge of the resized image. /// public static Tensor resize(Tensor input, int height, int width, int? maxSize = null) { + if (height <= 0 || width <= 0) + throw new ArgumentException("the height and width parameters must both be greater than 0"); + if (maxSize.HasValue && maxSize.Value <= 0) + throw new ArgumentException("the maxSize parameter must be greater than 0"); + // For now, we don't allow any other modes. const InterpolationMode interpolation = InterpolationMode.Nearest; diff --git a/test/TorchSharpTest/TestTorchVision.cs b/test/TorchSharpTest/TestTorchVision.cs index 95329cd67..39cedfc72 100644 --- a/test/TorchSharpTest/TestTorchVision.cs +++ b/test/TorchSharpTest/TestTorchVision.cs @@ -842,7 +842,7 @@ public void TestConstructor_ThrowsArgumentException_IfMeansAndStdevsHaveDifferen double[] stdevs = { 0.229, 0.224, 0.225, 0.222 }; // Different length // Act & Assert - Assert.Throws(() => torchvision.transforms.Normalize(means, stdevs)); + Assert.Throws(() => Normalize(means, stdevs)); } [Fact] @@ -853,7 +853,7 @@ public void TestConstructor_ThrowsArgumentException_IfMeansAndStdevsHaveWrongLen double[] stdevs = { 0.229, 0.224 }; // Not 1 or 3 // Act & Assert - Assert.Throws(() => torchvision.transforms.Normalize(means, stdevs)); + Assert.Throws(() => Normalize(means, stdevs)); } [Fact] @@ -864,7 +864,7 @@ public void TestConstructor_CreatesNewNormalizeObject_WithValidArguments() double[] stdevs = { 0.229, 0.224, 0.225 }; // Act - var result = torchvision.transforms.Normalize(means, stdevs); + var result = Normalize(means, stdevs); // Assert Assert.NotNull(result); @@ -876,7 +876,7 @@ public void TestCall_ThrowsArgumentException_IfNumberOfChannelsIsNotEqual() // Arrange double[] means = { 0.485, 0.456, 0.406 }; double[] stdevs = { 0.229, 0.224, 0.225 }; - var sut = torchvision.transforms.Normalize(means, stdevs); + var sut = Normalize(means, stdevs); var wrongSizeInput = torch.rand(new long[] { 1, 4, 32, 32 }); // wrong number of input channels // Act & Assert @@ -889,7 +889,7 @@ public void TestCall_CallsOperatorsCorrectly() // Arrange double[] means = { 0.485, 0.456, 0.406 }; double[] stdevs = { 0.229, 0.224, 0.225 }; - var sut = torchvision.transforms.Normalize(means, stdevs); + var sut = Normalize(means, stdevs); var inputChannels = 3; var input = torch.rand(new long[] { 1, inputChannels, 32, 32 }, dtype: float64); @@ -906,11 +906,11 @@ public void TestCall_CallsOperatorsCorrectly() public void Call_ThrowsException_WithWrongNumberOfChannels() { // Act - Assert.Throws(() => torchvision.transforms.Grayscale(outputChannels: 2)); + Assert.Throws(() => Grayscale(outputChannels: 2)); Tensor input = torch.rand(new long[] { 1, 2, 128, 128 }); - var tfrm = torchvision.transforms.Grayscale(outputChannels: 1); + var tfrm = Grayscale(outputChannels: 1); Assert.Throws(() => tfrm.call(input)); } @@ -922,7 +922,7 @@ public void Resize_WithHeightAndWidth_ReturnsTensor() int height = 20; int width = 30; var input = torch.randn(1, 3, 256, 256); - var transform = torchvision.transforms.Resize(height, width); + var transform = Resize(height, width); //Act var result = transform.call(input); @@ -939,7 +939,7 @@ public void Resize_WithSizeAndMaxSize_ReturnsTensor() int size = 20; int? maxSize = 30; var input = torch.randn(1, 3, 256, 256); - var transform = torchvision.transforms.Resize(size, maxSize); + var transform = Resize(size, maxSize); //Act var result = transform.call(input); @@ -1206,5 +1206,383 @@ public void Solarize_ThresholdNegative_ThrowsException() var input = torch.arange(9).reshape(3, 3).to(float32) / 255.0f; Assert.Throws(() => functional.solarize(input, 25000)); } + + + [Fact] + public void RgbToGrayscale_ReturnsCorrectNumberOfChannels() + { + int numChannels = 3; + int numOutputChannels = 1; + var shape = new long[] { numChannels, 10, 10 }; + + var input = torch.rand(shape); + + var output = functional.rgb_to_grayscale(input, numOutputChannels); + + Assert.Equal(numOutputChannels, output.shape[0]); + } + + [Fact] + public void RgbToGrayscale_ThrowsArgumentException_ForInvalidOutputChannels() + { + int numChannels = 3; + int numOutputChannels = 2; + var shape = new long[] { numChannels, 10, 10 }; + + var input = torch.rand(shape); + + Assert.Throws(() => functional.rgb_to_grayscale(input, numOutputChannels)); + } + + [Fact] + public void RgbToGrayscale_AlreadyGrayscale_ReturnsInputTensorAsIs() + { + int numChannels = 1; + int numOutputChannels = 1; + var shape = new long[] { numChannels, 10, 10 }; + + var input = torch.rand(shape); + + var output = functional.rgb_to_grayscale(input, numOutputChannels); + + Assert.Equal(input, output); + } + + [Fact] + public void RgbToGrayscale_ConvertsInputToFloatTensor() + { + int numChannels = 3; + int numOutputChannels = 1; + var shape = new long[] { numChannels, 10, 10 }; + + var input = torch.randint(0, 255, shape, dtype:ScalarType.Byte); + + var output = functional.rgb_to_grayscale(input, numOutputChannels); + + Assert.True(output.is_floating_point()); + } + + [Fact] + public void RgbToGrayscale_ReturnsTensorWithCorrectShape() + { + int numChannels = 3; + int numOutputChannels = 1; + var shape = new long[] { numChannels, 10, 10 }; + + var input = torch.rand(shape); + + var output = functional.rgb_to_grayscale(input, numOutputChannels); + + Assert.Equal(new long[] { numOutputChannels, 10, 10 }, output.shape); + } + + [Fact] + public void Resize_WhenSizeNotChanged_ReturnsSameTensor() + { + // Arrange + var input = torch.rand( 3, 2, 2 ); + int height = 2; + int width = 2; + + // Act + var output = functional.resize(input, height, width); + + // Assert + Assert.Equal(input.Dimensions, output.Dimensions); + Assert.Equal(input.shape, output.shape); + Assert.Equal(input, output); + } + + [Fact] + public void Resize_WhenWidthChange_ReturnsTensorWithSameHeight() + { + // Arrange + var input = torch.rand( 3, 2, 4 ); + int height = 2; + int width = 3; + + // Act + var output = functional.resize(input, height, width); + + // Assert + Assert.Equal(input.Dimensions, output.Dimensions); + Assert.Equal(input.shape[0], output.shape[0]); + Assert.Equal(height, output.shape[1]); + Assert.Equal(width, output.shape[2]); + } + + [Fact] + public void Resize_WhenHeightChange_ReturnsTensorWithSameWidth() + { + // Arrange + var input = torch.rand( 3, 4, 2); + int height = 3; + int width = 2; + + // Act + var output = functional.resize(input, height, width); + + // Assert + Assert.Equal(input.Dimensions, output.Dimensions); + Assert.Equal(input.shape[0], output.shape[0]); + Assert.Equal(height, output.shape[1]); + Assert.Equal(width, output.shape[2]); + } + + [Fact] + public void Resize_WhenMaxSizeNotMet_ThrowsArgumentException() + { + // Arrange + var input = torch.rand( 3, 5, 4 ); + int height = 10; + int? maxSize = 8; + + // Act + Assert + Assert.Throws(() => functional.resize(input, height, -1, maxSize)); + } + + [Fact] + public void Resize_WhenMaxSizeMet_DoesNotThrowException() + { + // Arrange + var input = torch.rand( 3, 5, 4 ); + int height = 8; + int? maxSize = 10; + + // Act + Assert + functional.resize(input, height, -1, maxSize); + } + + + + [Fact] + public void CanApplyPerspective() + { + using var tensor = torch.rand(new long[] { 3, 256, 256 }); + + var startpoints = new List>() + { + new List(){ 10, 10 }, + new List(){ 10, 246 }, + new List(){ 246, 10 }, + new List(){ 246, 246 }, + }; + var endpoints = new List>() + { + new List(){ 0, 0 }, + new List(){ 0, 256 }, + new List(){ 256, 0 }, + new List(){ 256, 256 }, + }; + + using var output = functional.perspective(tensor, startpoints, endpoints); + + Assert.NotNull(output); + Assert.Equal(tensor.shape, output.shape); + } + + [Fact] + public void CanApplyPerspectiveWithInterpolation() + { + using var tensor = torch.rand(new long[] { 3, 256, 256 }); + + var startpoints = new List>() + { + new List(){ 10, 10 }, + new List(){ 10, 246 }, + new List(){ 246, 10 }, + new List(){ 246, 246 }, + }; + var endpoints = new List>() + { + new List(){ 0, 0 }, + new List(){ 0, 256 }, + new List(){ 256, 0 }, + new List(){ 256, 256 }, + }; + var interpolation = InterpolationMode.Nearest; + + using var output = functional.perspective(tensor, startpoints, endpoints, interpolation); + + Assert.NotNull(output); + Assert.Equal(tensor.shape, output.shape); + } + + [Fact] + public void CanApplyPerspectiveWithFill() + { + using var tensor = torch.rand(new long[] { 3, 256, 256 }); + + var startpoints = new List>() + { + new List(){ 10, 10 }, + new List(){ 10, 246 }, + new List(){ 246, 10 }, + new List(){ 246, 246 }, + }; + var endpoints = new List>() + { + new List(){ 0, 0 }, + new List(){ 0, 256 }, + new List(){ 256, 0 }, + new List(){ 256, 256 }, + }; + var fill = new List() { 0.5f }; + + using var output = functional.perspective(tensor, startpoints, endpoints, fill: fill); + + Assert.NotNull(output); + Assert.Equal(tensor.shape, output.shape); + } + + [Fact] + public void TestPadZeroes() + { + var input = torch.ones(3, 3, dtype: int64); + { + var padding = new long[] { 1, 2 }; + var padding_mode = PaddingModes.Zeros; + + var expectedOutput = torch.tensor(new long[,] { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0}, + {0, 1, 1, 1, 0}, + {0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }); + + var actualOutput = functional.pad(input, padding, padding_mode: padding_mode); + + Assert.Equal(expectedOutput, actualOutput); + } + { + var padding = new long[] { 1, 1, 2, 2 }; + var padding_mode = PaddingModes.Zeros; + + var expectedOutput = torch.tensor(new long[,] { + {0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0}, + {0, 1, 1, 1, 0, 0}, + {0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0} + }); + + var actualOutput = functional.pad(input, padding, padding_mode: padding_mode); + + Assert.Equal(expectedOutput, actualOutput); + } + } + + [Fact] + public void TestPadConstant() + { + var input = torch.ones(3, 3, dtype: int64); + { + var padding = new long[] { 1, 2 }; + var fill = 0; + var padding_mode = PaddingModes.Constant; + + var expectedOutput = torch.tensor(new long[,] { + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0}, + {0, 1, 1, 1, 0}, + {0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0} + }); + + var actualOutput = functional.pad(input, padding, fill, padding_mode); + + Assert.Equal(expectedOutput, actualOutput); + } + { + var padding = new long[] { 1, 1, 2, 2 }; + var fill = 0; + var padding_mode = PaddingModes.Constant; + + var expectedOutput = torch.tensor(new long[,] { + {0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0}, + {0, 1, 1, 1, 0, 0}, + {0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0} + }); + + var actualOutput = functional.pad(input, padding, fill, padding_mode); + + Assert.Equal(expectedOutput, actualOutput); + } + } + + [Fact] + public void TestPadReflect() + { + var input = torch.arange(1, 10, dtype:float32).reshape(1, 3, 3); + { + var padding = new long[] { 1, 2 }; + var padding_mode = PaddingModes.Reflect; + + var expectedOutput = torch.tensor(new float[,] { + {8, 7, 8, 9, 8}, + {5, 4, 5, 6, 5}, + {2, 1, 2, 3, 2}, + {5, 4, 5, 6, 5}, + {8, 7, 8, 9, 8}, + {5, 4, 5, 6, 5}, + {2, 1, 2, 3, 2} + }).reshape(1, 7, 5); + + var actualOutput = functional.pad(input, padding, padding_mode: padding_mode); + + Assert.Equal(expectedOutput, actualOutput); + } + { + var padding = new long[] { 1, 1, 2, 2 }; + var padding_mode = PaddingModes.Reflect; + + var expectedOutput = torch.tensor(new float[,] { + {5, 4, 5, 6, 5, 4}, + {2, 1, 2, 3, 2, 1}, + {5, 4, 5, 6, 5, 4}, + {8, 7, 8, 9, 8, 7}, + {5, 4, 5, 6, 5, 4}, + {2, 1, 2, 3, 2, 1} + }).reshape(1, 6, 6); + + var actualOutput = functional.pad(input, padding, padding_mode: padding_mode); + + Assert.Equal(expectedOutput, actualOutput); + } + } + + [Fact] + public void TestGaussianBlur() + { + var input = torch.arange(1 * 3 * 3 * 5).reshape(1, 3, 3, 5).to(float32) / 5.0f; + var kernelSize = new List { 3, 5 }; + var sigma = new List { 1.0f, 2.0f }; + + var actual = functional.gaussian_blur(input, kernelSize, sigma); + var expected = torch.tensor(new float[]{ + 2f, 2f, 2.2f, 2.4f, 2.4f, + 1.2f, 1.2f, 1.4f, 1.6f, 1.6f, + 0.4f, 0.4f, 0.6f, 0.8f, 0.8f, + 5f, 5f, 5.2f, 5.4f, 5.4f, + 4.2f, 4.2f, 4.4f, 4.6f, 4.6f, + 3.4f, 3.4f, 3.6f, 3.8f, 3.8f, + 8f, 8f, 8.2f, 8.4f, 8.4f, + 7.2f, 7.2f, 7.4f, 7.6f, 7.6f, + 6.4f, 6.4f, 6.6f, 6.8f, 6.8f + }).reshape(1, 3, 3, 5); + + var outputStr = actual.str("g6", style: TensorStringStyle.Numpy); + + Assert.True(expected.allclose(actual, rtol: 1e-4, atol: 1e-6)); + } } } From c0a38e6809cf15edc4f8c8adb1e535cc22092157 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Fri, 23 Jun 2023 11:41:56 -0700 Subject: [PATCH 10/47] More unit tests --- test/TorchSharpTest/TestTorchVision.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/TorchSharpTest/TestTorchVision.cs b/test/TorchSharpTest/TestTorchVision.cs index 39cedfc72..926d20ab1 100644 --- a/test/TorchSharpTest/TestTorchVision.cs +++ b/test/TorchSharpTest/TestTorchVision.cs @@ -905,7 +905,6 @@ public void TestCall_CallsOperatorsCorrectly() [Fact] public void Call_ThrowsException_WithWrongNumberOfChannels() { - // Act Assert.Throws(() => Grayscale(outputChannels: 2)); Tensor input = torch.rand(new long[] { 1, 2, 128, 128 }); @@ -1580,8 +1579,6 @@ public void TestGaussianBlur() 6.4f, 6.4f, 6.6f, 6.8f, 6.8f }).reshape(1, 3, 3, 5); - var outputStr = actual.str("g6", style: TensorStringStyle.Numpy); - Assert.True(expected.allclose(actual, rtol: 1e-4, atol: 1e-6)); } } From 3d734261c435ebf68d1e8f8197a4aa4d4e595cd6 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Wed, 9 Aug 2023 15:23:28 -0700 Subject: [PATCH 11/47] Manual merges --- src/TorchVision/Functional.cs | 2 +- test/TorchSharpTest/TestTorchVision.cs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/TorchVision/Functional.cs b/src/TorchVision/Functional.cs index fc261d68a..679b1d511 100644 --- a/src/TorchVision/Functional.cs +++ b/src/TorchVision/Functional.cs @@ -850,7 +850,7 @@ private static Tensor Blend(Tensor img1, Tensor img2, double ratio) using var t2 = img2 * (1.0 - ratio); using var t3 = (t0 + t2); using var t4 = t3.clamp(0, bound); - return t4.to(img2.dtype); + return t4.to(img1.dtype); } private static Tensor BlurredDegenerateImage(Tensor input) diff --git a/test/TorchSharpTest/TestTorchVision.cs b/test/TorchSharpTest/TestTorchVision.cs index 926d20ab1..3c6b54156 100644 --- a/test/TorchSharpTest/TestTorchVision.cs +++ b/test/TorchSharpTest/TestTorchVision.cs @@ -1581,5 +1581,13 @@ public void TestGaussianBlur() Assert.True(expected.allclose(actual, rtol: 1e-4, atol: 1e-6)); } + + [Fact] + public void Adjust_Contrast_ReturnsTensorWithCorrectDtype() + { + var img1 = torch.randn(1, 32, 32).to(torch.uint8); + var img2 = torchvision.transforms.functional.adjust_contrast(img1, 2); + Assert.Equal(img1.dtype, img2.dtype); + } } } From 86ffcfd16c3d8fb70f1189403317652ecef2fb24 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Fri, 2 Feb 2024 14:14:21 -0800 Subject: [PATCH 12/47] Stashing my changes. --- src/TorchSharp/NN/Linear.cs | 21 +++++++++++++++++++++ test/TorchSharpTest/NN.cs | 6 ++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/TorchSharp/NN/Linear.cs b/src/TorchSharp/NN/Linear.cs index 1b87c4a3a..8bcfbe871 100644 --- a/src/TorchSharp/NN/Linear.cs +++ b/src/TorchSharp/NN/Linear.cs @@ -62,6 +62,27 @@ public Parameter weight { } } + protected internal override nn.Module _to(Device device, ScalarType dtype) + { + weight = new Parameter(_weight!.to(dtype, device)); + if (bias is not null) bias = new Parameter(_bias!.to(dtype, device)); + return this; + } + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) + { + weight = new Parameter(_weight!.to(deviceType, deviceIndex)); + if (bias is not null) bias = new Parameter(_bias!.to(deviceType, deviceIndex)); + return this; + } + + protected internal override nn.Module _to(ScalarType dtype) + { + weight = new Parameter(_weight!.to(dtype)); + if (bias is not null) bias = new Parameter(_bias!.to(dtype)); + return this; + } + private Parameter? _weight; private static readonly double _sqrt5 = Math.Sqrt(5); } diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index 5e594e931..db91c1993 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -269,8 +269,10 @@ public void TestLinearNullBias() { var device = torch.CPU; - var lin = Linear(1000, 100, true, device: device); - Assert.Throws(() => lin.bias = null); + var lin = Linear(100, 100, true, device: device); + // This should not throw: + lin.bias = null; + lin.call(torch.rand(100)); } [Fact] From 6fafdbde3c5d79723a1199d613db6b836dbc8045 Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Wed, 28 Feb 2024 01:36:08 +0200 Subject: [PATCH 13/47] Added no grad in loadstatedict --- src/TorchSharp/NN/Module.cs | 4 ++++ test/TorchSharpTest/TestLoadSave.cs | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/TorchSharp/NN/Module.cs b/src/TorchSharp/NN/Module.cs index b40353ead..e898cc2f1 100644 --- a/src/TorchSharp/NN/Module.cs +++ b/src/TorchSharp/NN/Module.cs @@ -506,6 +506,10 @@ public virtual (IList missing_keys, IList unexpected_keyes) load if (strict && (missing.Count > 0 || unexpected.Count > 0)) throw new InvalidOperationException("The loaded state_dict is not identical to the target dictionary."); + // The copy_ operation is an in-place operation which can't be performed on a leaf variable which + // requires_grad. Therefore, we will perform the coyp in a no_grad context. + using var d = torch.no_grad(); + foreach (var key in source.Keys) { if (skip.Contains(key)) continue; if (destination.ContainsKey(key)) { diff --git a/test/TorchSharpTest/TestLoadSave.cs b/test/TorchSharpTest/TestLoadSave.cs index dfd99135d..47cfb4f5b 100644 --- a/test/TorchSharpTest/TestLoadSave.cs +++ b/test/TorchSharpTest/TestLoadSave.cs @@ -31,6 +31,14 @@ private void TestLoadSingleTensor() Assert.Equal(new long[] { 2, 3, 4, 5 }, tensor.shape); } + [Fact] + public void TestLoadStateDict() + { + var module1 = torch.nn.Linear(10, 10); + var module2 = torch.nn.Linear(10, 10); + + module2.load_state_dict(module1.state_dict()); + } #if false [Fact] public void TestSaveLoadLinear1() From 0742fb62963e47435ee709d24a4859766e0f0d4c Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Wed, 28 Feb 2024 01:36:41 +0200 Subject: [PATCH 14/47] typo --- src/TorchSharp/NN/Module.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TorchSharp/NN/Module.cs b/src/TorchSharp/NN/Module.cs index e898cc2f1..d40ada65b 100644 --- a/src/TorchSharp/NN/Module.cs +++ b/src/TorchSharp/NN/Module.cs @@ -507,7 +507,7 @@ public virtual (IList missing_keys, IList unexpected_keyes) load throw new InvalidOperationException("The loaded state_dict is not identical to the target dictionary."); // The copy_ operation is an in-place operation which can't be performed on a leaf variable which - // requires_grad. Therefore, we will perform the coyp in a no_grad context. + // requires_grad. Therefore, we will perform the copy in a no_grad context. using var d = torch.no_grad(); foreach (var key in source.Keys) { From 72b1261254e3f2676eb78aa593a35106d984bbcf Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Wed, 28 Feb 2024 20:45:32 +0200 Subject: [PATCH 15/47] Added release notes --- RELEASENOTES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a9f888a91..93606ba24 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,6 +2,12 @@ Releases, starting with 9/2/2021, are listed with the most recent release at the top. +# NuGet Version 0.102.1 + +__Bug Fixes__: + +`module.load_state_dict()` throws error for in-place operation on a leaf variable that requires grad.
+ ## NuGet Version 0.102.0 This release upgrades the libtorch backend to v2.2.0. From c5bd49473d14062f46ecb39ca242228792bdc8f9 Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Wed, 28 Feb 2024 20:49:07 +0200 Subject: [PATCH 16/47] Updated release notes for 0.102.0 --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 93606ba24..7a51bb793 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -10,7 +10,7 @@ __Bug Fixes__: ## NuGet Version 0.102.0 -This release upgrades the libtorch backend to v2.2.0. +This release upgrades the libtorch backend to v2.2.1. __Breaking Changes__: From e2ca473305eef2f06b82399d957a7aca3d6c91b9 Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Sun, 3 Mar 2024 00:08:46 +0200 Subject: [PATCH 17/47] Fixed average pool 1d + npstr/cstr with one dimension --- src/TorchSharp/NN/Pooling/AvgPool1D.cs | 2 +- src/TorchSharp/Tensor/Tensor.cs | 15 ++++++++++--- test/TorchSharpTest/TestTorchTensorBugs.cs | 25 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/TorchSharp/NN/Pooling/AvgPool1D.cs b/src/TorchSharp/NN/Pooling/AvgPool1D.cs index 9cd0b3f3f..b430e8436 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool1D.cs @@ -90,7 +90,7 @@ public static Tensor avg_pool1d(Tensor input, long kernelSize, long? stride = nu long? padding = null, bool ceil_mode = false, bool count_include_pad = true) { var kernelSizes = new long[] { kernelSize }; - var strides = new long[] { stride ?? 1 }; + var strides = new long[] { stride ?? kernelSize }; var paddings = new long[] { padding ?? 0 }; unsafe { fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { diff --git a/src/TorchSharp/Tensor/Tensor.cs b/src/TorchSharp/Tensor/Tensor.cs index 03e552229..5dcdd0ad2 100644 --- a/src/TorchSharp/Tensor/Tensor.cs +++ b/src/TorchSharp/Tensor/Tensor.cs @@ -6496,11 +6496,18 @@ private static string ToNumpyString(Tensor t, long mdim, bool isFCreate, string var leadingRows = torch.maxRows - trailingRows; var dim = t.dim(); + if (t.size().Length == 0) return ""; var sb = new StringBuilder(isFCreate ? string.Join("", Enumerable.Repeat(' ', (int)(mdim - dim))) : ""); sb.Append('['); var currentSize = t.size()[0]; - if (dim == 1) { + if (currentSize == 0) { + // print nothing + } + else if (dim == 0) { + PrintValue(sb, t.dtype, t.ToScalar(), fltFormat, actualCulturInfo); + } + else if (dim == 1) { if (currentSize <= torch.maxColumns) { for (var i = 0; i < currentSize - 1; i++) { PrintValue(sb, t.dtype, t[i].ToScalar(), fltFormat, actualCulturInfo); @@ -6572,7 +6579,6 @@ private static string ToCSharpString(Tensor t, long mdim, bool isFCreate, string var leadingRows = torch.maxRows - trailingRows; var dim = t.dim(); - if (t.size().Length == 0) return ""; var sb = new StringBuilder(); if (top) { @@ -6648,7 +6654,10 @@ private static string ToCSharpString(Tensor t, long mdim, bool isFCreate, string } var currentSize = t.size()[0]; - if (dim == 1) { + if (currentSize == 0) { + // do nothing + } + else if (dim == 1) { if (currentSize <= torch.maxColumns) { for (var i = 0; i < currentSize - 1; i++) { PrintValue(sb, t.dtype, t[i].ToScalar(), fltFormat, actualCulturInfo); diff --git a/test/TorchSharpTest/TestTorchTensorBugs.cs b/test/TorchSharpTest/TestTorchTensorBugs.cs index ee7b0041f..7e1a44036 100644 --- a/test/TorchSharpTest/TestTorchTensorBugs.cs +++ b/test/TorchSharpTest/TestTorchTensorBugs.cs @@ -1633,5 +1633,30 @@ public void ValidateLinearLR() scheduler.step(); Assert.Equal(0.05, Math.Round(scheduler.get_last_lr().First(), 2)); } + + [Fact] + public void Validate_1249() + { + var x = torch.zeros(5, 7, 128); + Console.WriteLine(x.metastr()); + // [5x7x128], type = Float32, device = cpu + + var y1 = torch.nn.functional.avg_pool1d(x, 2); + Console.WriteLine(y1.metastr()); + Assert.Equal(64, y1.size(-1)); + + var y2 = torch.nn.AvgPool1d(2).call(x); + Console.WriteLine(y2.metastr()); + Assert.Equal(64, y1.size(-1)); + } + + [Fact] + public void Validate_1250() + { + Assert.Equal("[]", torch.zeros(0).npstr()); + Assert.Equal("[0]", torch.zeros(1).npstr()); + Assert.Equal("[0], type = Float32, device = cpu, value = float [] {}", torch.zeros(0).cstr()); + Assert.Equal("[1], type = Float32, device = cpu, value = float [] {0f}", torch.zeros(1).cstr()); + } } } \ No newline at end of file From 428a66aa3f9b39814866673115c6aac58d0f2054 Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Sun, 3 Mar 2024 00:10:48 +0200 Subject: [PATCH 18/47] Added release notes --- RELEASENOTES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7a51bb793..2bfdfce9b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -4,9 +4,15 @@ Releases, starting with 9/2/2021, are listed with the most recent release at the # NuGet Version 0.102.1 +__Breaking Changes__: + +The `stride` parameter in the `torch.nn.functional.avg_pool1d` call now defaults to `kernelSize` instead of 1, to match the PyTorch behavior. + __Bug Fixes__: `module.load_state_dict()` throws error for in-place operation on a leaf variable that requires grad.
+#1250 cstr and npstr for 0d tensors
+#1249 torch.nn.functional.avg_pool1d is not working correctly
## NuGet Version 0.102.0 From 8c37c5cb23b2003f0bce3869222eb5b9917fdcff Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Mon, 4 Mar 2024 20:09:53 +0200 Subject: [PATCH 19/47] Renamed kernel_size --- RELEASENOTES.md | 4 +++- src/TorchSharp/NN/Pooling/AvgPool1D.cs | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2bfdfce9b..0c870050b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -6,7 +6,9 @@ Releases, starting with 9/2/2021, are listed with the most recent release at the __Breaking Changes__: -The `stride` parameter in the `torch.nn.functional.avg_pool1d` call now defaults to `kernelSize` instead of 1, to match the PyTorch behavior. +The `kernelSize` parameter in the function and class of `AvgPool1D` was renamed to `kernel_size` to match PyTorch naming. +The `stride` parameter in the `torch.nn.functional.avg_pool1d` call now defaults to `kernelSize` instead of 1, to match the PyTorch behavior. + __Bug Fixes__: diff --git a/src/TorchSharp/NN/Pooling/AvgPool1D.cs b/src/TorchSharp/NN/Pooling/AvgPool1D.cs index b430e8436..3430fcdaa 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool1D.cs @@ -40,32 +40,32 @@ public static partial class nn /// /// Applies a 1D average pooling over an input signal composed of several input planes. /// - /// The size of the window + /// The size of the window /// The stride of the window. Default value is kernel_size /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static AvgPool1d AvgPool1d(long kernelSize, long? stride = null, long padding = 0, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool1d AvgPool1d(long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { return stride.HasValue ? - AvgPool1d(new long[] { kernelSize }, new long[] { stride.Value }, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0) : - AvgPool1d(new long[] { kernelSize }, null, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0); + AvgPool1d(new long[] { kernel_size }, new long[] { stride.Value }, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0) : + AvgPool1d(new long[] { kernel_size }, null, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0); } /// /// Applies a 1D average pooling over an input signal composed of several input planes. /// - /// The size of the window + /// The size of the window /// The stride of the window. Default value is kernel_size /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - private static AvgPool1d AvgPool1d(long[] kernelSize, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + private static AvgPool1d AvgPool1d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding) { + fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { var handle = THSNN_AvgPool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)ppadding, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); if (handle == IntPtr.Zero) { torch.CheckForErrors(); } return new AvgPool1d(handle, boxedHandle); @@ -80,17 +80,17 @@ public static partial class functional /// Applies a 1D average pooling over an input signal composed of several input planes. ///
/// The input tensor. - /// + /// /// /// /// /// /// - public static Tensor avg_pool1d(Tensor input, long kernelSize, long? stride = null, + public static Tensor avg_pool1d(Tensor input, long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true) { - var kernelSizes = new long[] { kernelSize }; - var strides = new long[] { stride ?? kernelSize }; + var kernelSizes = new long[] { kernel_size }; + var strides = new long[] { stride ?? kernel_size }; var paddings = new long[] { padding ?? 0 }; unsafe { fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { From c9ec3b2ce94bb9b807063696d41929f4070d86a9 Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Thu, 29 Feb 2024 04:28:44 +0200 Subject: [PATCH 20/47] Fixed issue with read and added test + release notes --- RELEASENOTES.md | 1 + src/TorchSharp/Tensor/Tensor.cs | 11 +++++------ test/TorchSharpTest/TestTorchTensorBugs.cs | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0c870050b..012a84d30 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -15,6 +15,7 @@ __Bug Fixes__: `module.load_state_dict()` throws error for in-place operation on a leaf variable that requires grad.
#1250 cstr and npstr for 0d tensors
#1249 torch.nn.functional.avg_pool1d is not working correctly
+`module.load()` with streams which don't read the requested # of bytes throws error.
## NuGet Version 0.102.0 diff --git a/src/TorchSharp/Tensor/Tensor.cs b/src/TorchSharp/Tensor/Tensor.cs index 5dcdd0ad2..ded89d8f4 100644 --- a/src/TorchSharp/Tensor/Tensor.cs +++ b/src/TorchSharp/Tensor/Tensor.cs @@ -463,16 +463,15 @@ public void ReadBytesFromStream(Stream stream, int bufferSize = 1024) byte[] buffer = new byte[bufferSize]; while (totalSize > 0) { // Read in the current buffer size - int curBufferSize = (int)Math.Min(totalSize, bufferSize); - stream.Read(buffer, 0, curBufferSize); + int bytesRead = stream.Read(buffer, 0, (int)Math.Min(totalSize, bufferSize)); // Copy the contents over to the span - var span = new Span((void*)ptr, curBufferSize); - buffer.AsSpan(0, curBufferSize).CopyTo(span); + var span = new Span((void*)ptr, bytesRead); + buffer.AsSpan(0, bytesRead).CopyTo(span); // Increment our pointer and decrease the total size of elements we have to write - ptr += curBufferSize; - totalSize -= curBufferSize; + ptr += bytesRead; + totalSize -= bytesRead; } } } diff --git a/test/TorchSharpTest/TestTorchTensorBugs.cs b/test/TorchSharpTest/TestTorchTensorBugs.cs index 7e1a44036..bf28a69ed 100644 --- a/test/TorchSharpTest/TestTorchTensorBugs.cs +++ b/test/TorchSharpTest/TestTorchTensorBugs.cs @@ -18,6 +18,7 @@ using System.Reflection.Metadata; using System.Runtime.InteropServices; using TorchSharp.Modules; +using System.IO.Compression; #nullable enable @@ -1658,5 +1659,25 @@ public void Validate_1250() Assert.Equal("[0], type = Float32, device = cpu, value = float [] {}", torch.zeros(0).cstr()); Assert.Equal("[1], type = Float32, device = cpu, value = float [] {0f}", torch.zeros(1).cstr()); } + + [Fact] + public void ValidateLoadWithDeflateStream() + { + var seq = Sequential(Linear(100, 100), Linear(100, 100)); + + var ms = new MemoryStream(); + using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true)) { + var entry = archive.CreateEntry("seq"); + + using (var stream = entry.Open()) + seq.save(stream); + } + + // This test will succeed if the following code doesn't crash. + ms.Position = 0; + using (var archive = new ZipArchive(ms)) { + seq.load(archive.GetEntry("seq")!.Open()); + } + } } } \ No newline at end of file From d5d1fd08682347e38e4a5857a0f7b27babca8233 Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Thu, 29 Feb 2024 16:27:19 +0200 Subject: [PATCH 21/47] Added check for end of stream mid tensor --- src/TorchSharp/Tensor/Tensor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/TorchSharp/Tensor/Tensor.cs b/src/TorchSharp/Tensor/Tensor.cs index ded89d8f4..04fbb43da 100644 --- a/src/TorchSharp/Tensor/Tensor.cs +++ b/src/TorchSharp/Tensor/Tensor.cs @@ -465,6 +465,9 @@ public void ReadBytesFromStream(Stream stream, int bufferSize = 1024) // Read in the current buffer size int bytesRead = stream.Read(buffer, 0, (int)Math.Min(totalSize, bufferSize)); + if (bytesRead == 0) + throw new EndOfStreamException(); + // Copy the contents over to the span var span = new Span((void*)ptr, bytesRead); buffer.AsSpan(0, bytesRead).CopyTo(span); From 4fb25b6775be140902baba6c8fa8222a1a958420 Mon Sep 17 00:00:00 2001 From: Shaltiel Shmidman Date: Mon, 4 Mar 2024 18:52:27 +0200 Subject: [PATCH 22/47] Added check for net 6 --- test/TorchSharpTest/TestTorchTensorBugs.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/TorchSharpTest/TestTorchTensorBugs.cs b/test/TorchSharpTest/TestTorchTensorBugs.cs index bf28a69ed..1a3aec88b 100644 --- a/test/TorchSharpTest/TestTorchTensorBugs.cs +++ b/test/TorchSharpTest/TestTorchTensorBugs.cs @@ -1663,6 +1663,7 @@ public void Validate_1250() [Fact] public void ValidateLoadWithDeflateStream() { +#if NET6_0_OR_GREATER var seq = Sequential(Linear(100, 100), Linear(100, 100)); var ms = new MemoryStream(); @@ -1678,6 +1679,7 @@ public void ValidateLoadWithDeflateStream() using (var archive = new ZipArchive(ms)) { seq.load(archive.GetEntry("seq")!.Open()); } +#endif } } } \ No newline at end of file From 9191f9be9f8677d8b25010c1e9f51ba37278b734 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 4 Mar 2024 11:03:11 -0800 Subject: [PATCH 23/47] Update TestTorchTensorBugs.cs --- test/TorchSharpTest/TestTorchTensorBugs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TorchSharpTest/TestTorchTensorBugs.cs b/test/TorchSharpTest/TestTorchTensorBugs.cs index 1a3aec88b..7d97371dd 100644 --- a/test/TorchSharpTest/TestTorchTensorBugs.cs +++ b/test/TorchSharpTest/TestTorchTensorBugs.cs @@ -1682,4 +1682,4 @@ public void ValidateLoadWithDeflateStream() #endif } } -} \ No newline at end of file +} From 54ee83b774dc4613908dca7703450dba26e90ca3 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 4 Mar 2024 16:04:04 -0800 Subject: [PATCH 24/47] Address issue with ordering of initializations in the torch cctor. --- RELEASENOTES.md | 1 + src/TorchSharp/Torch.cs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 012a84d30..275cde5e6 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -16,6 +16,7 @@ __Bug Fixes__: #1250 cstr and npstr for 0d tensors
#1249 torch.nn.functional.avg_pool1d is not working correctly
`module.load()` with streams which don't read the requested # of bytes throws error.
+ #1246 Issue running in notebook on Apple Silicon
## NuGet Version 0.102.0 diff --git a/src/TorchSharp/Torch.cs b/src/TorchSharp/Torch.cs index 7ce8c527a..2fd1e0ff9 100644 --- a/src/TorchSharp/Torch.cs +++ b/src/TorchSharp/Torch.cs @@ -27,7 +27,9 @@ public static partial class torch #error "Please update cudaVersion to match CudaVersionDot" #endif - static bool isAppleSilicon = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && RuntimeInformation.OSArchitecture == Architecture.Arm64; + static bool isAppleSilicon => + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && + RuntimeInformation.OSArchitecture == Architecture.Arm64; static string nativeRid => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? $"win-x64" : From 06675eceec5673590a234b9b5ad90f5f75ed6aaa Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 4 Mar 2024 17:13:25 -0800 Subject: [PATCH 25/47] Update BranchInfo.props --- build/BranchInfo.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/BranchInfo.props b/build/BranchInfo.props index c899060f6..d802ecb74 100644 --- a/build/BranchInfo.props +++ b/build/BranchInfo.props @@ -2,7 +2,7 @@ 0 102 - 0 + 1 From 88bd9081b7326517ea8bf1367df55eb7b2712e68 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Mon, 4 Mar 2024 18:47:44 -0800 Subject: [PATCH 26/47] Update version number --- build/BranchInfo.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/BranchInfo.props b/build/BranchInfo.props index d802ecb74..9462394d5 100644 --- a/build/BranchInfo.props +++ b/build/BranchInfo.props @@ -2,7 +2,7 @@ 0 102 - 1 + 2 From 89f53c2602a22c3fd83986c7bc947037b6b7b946 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 5 Mar 2024 11:58:15 -0800 Subject: [PATCH 27/47] Finished merging a file that was missed. --- src/TorchVision/Functional.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/TorchVision/Functional.cs b/src/TorchVision/Functional.cs index 020f8be19..d3dc53e14 100644 --- a/src/TorchVision/Functional.cs +++ b/src/TorchVision/Functional.cs @@ -697,11 +697,6 @@ public static Tensor posterize(Tensor input, int bits) /// public static Tensor resize(Tensor input, int height, int width, int? maxSize = null) { - if (height <= 0 || width <= 0) - throw new ArgumentException("the height and width parameters must both be greater than 0"); - if (maxSize.HasValue && maxSize.Value <= 0) - throw new ArgumentException("the maxSize parameter must be greater than 0"); - // For now, we don't allow any other modes. const InterpolationMode interpolation = InterpolationMode.Nearest; From 6f23a5da83852aa6cc3cdb0534300d3dafc85a8e Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 5 Mar 2024 12:01:33 -0800 Subject: [PATCH 28/47] Remove duplicate test --- test/TorchSharpTest/TestTorchVision.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/TorchSharpTest/TestTorchVision.cs b/test/TorchSharpTest/TestTorchVision.cs index 847aafb95..c8f1bc341 100644 --- a/test/TorchSharpTest/TestTorchVision.cs +++ b/test/TorchSharpTest/TestTorchVision.cs @@ -1589,13 +1589,5 @@ public void TestGaussianBlur() Assert.True(expected.allclose(actual, rtol: 1e-4, atol: 1e-6)); } - - [Fact] - public void Adjust_Contrast_ReturnsTensorWithCorrectDtype() - { - var img1 = torch.randn(1, 32, 32).to(torch.uint8); - var img2 = torchvision.transforms.functional.adjust_contrast(img1, 2); - Assert.Equal(img1.dtype, img2.dtype); - } } } From c5470fe8aa9caaafe3df076a2079d12930d93ff2 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 5 Mar 2024 12:22:23 -0800 Subject: [PATCH 29/47] Added properties to a number of builtin modules. --- src/TorchSharp/NN/AlphaDropout.cs | 6 +++--- src/TorchSharp/NN/Dropout.cs | 4 ++-- src/TorchSharp/NN/Dropout1d.cs | 4 ++-- src/TorchSharp/NN/Dropout2d.cs | 4 ++-- src/TorchSharp/NN/Dropout3d.cs | 4 ++-- src/TorchSharp/NN/Flatten.cs | 10 +++++----- src/TorchSharp/NN/Fold.cs | 16 ++++++++-------- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/TorchSharp/NN/AlphaDropout.cs b/src/TorchSharp/NN/AlphaDropout.cs index ba9916c85..51634cb63 100644 --- a/src/TorchSharp/NN/AlphaDropout.cs +++ b/src/TorchSharp/NN/AlphaDropout.cs @@ -42,9 +42,9 @@ public override Tensor forward(Tensor tensor) protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; protected internal override nn.Module _to(ScalarType dtype) => this; - private bool inplace; - private double p; - } + public bool inplace { get; set; } + public double p { get; set;} + } } public static partial class torch diff --git a/src/TorchSharp/NN/Dropout.cs b/src/TorchSharp/NN/Dropout.cs index f1c3a04b0..675286a5f 100644 --- a/src/TorchSharp/NN/Dropout.cs +++ b/src/TorchSharp/NN/Dropout.cs @@ -36,8 +36,8 @@ public override Tensor forward(Tensor tensor) protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; protected internal override nn.Module _to(ScalarType dtype) => this; - private bool inplace; - private double p; + public bool inplace { get; set; } + public double p { get; set;} } } diff --git a/src/TorchSharp/NN/Dropout1d.cs b/src/TorchSharp/NN/Dropout1d.cs index e06eecafa..77389bf69 100644 --- a/src/TorchSharp/NN/Dropout1d.cs +++ b/src/TorchSharp/NN/Dropout1d.cs @@ -33,8 +33,8 @@ public override Tensor forward(Tensor tensor) protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; protected internal override nn.Module _to(ScalarType dtype) => this; - private bool inplace; - private double p; + public bool inplace { get; set; } + public double p { get; set;} } } diff --git a/src/TorchSharp/NN/Dropout2d.cs b/src/TorchSharp/NN/Dropout2d.cs index 363cb40d5..672fa4ad3 100644 --- a/src/TorchSharp/NN/Dropout2d.cs +++ b/src/TorchSharp/NN/Dropout2d.cs @@ -33,8 +33,8 @@ public override Tensor forward(Tensor input) protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; protected internal override nn.Module _to(ScalarType dtype) => this; - private bool inplace; - private double p; + public bool inplace { get; set; } + public double p { get; set;} } } diff --git a/src/TorchSharp/NN/Dropout3d.cs b/src/TorchSharp/NN/Dropout3d.cs index 8c70d2f79..7e7567502 100644 --- a/src/TorchSharp/NN/Dropout3d.cs +++ b/src/TorchSharp/NN/Dropout3d.cs @@ -33,8 +33,8 @@ public override Tensor forward(Tensor input) protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; protected internal override nn.Module _to(ScalarType dtype) => this; - private bool inplace; - private double p; + public bool inplace { get; set; } + public double p { get; set;} } } diff --git a/src/TorchSharp/NN/Flatten.cs b/src/TorchSharp/NN/Flatten.cs index e6bf6ccc9..95ec5e41b 100644 --- a/src/TorchSharp/NN/Flatten.cs +++ b/src/TorchSharp/NN/Flatten.cs @@ -16,17 +16,17 @@ public sealed class Flatten : ParamLessModule { internal Flatten(long startDim = 1, long endDim = -1) : base(nameof(Flatten)) { - _startDim = startDim; - _endDim = endDim; + start_dim = startDim; + end_dim = endDim; } public override Tensor forward(Tensor tensor) { - return tensor.flatten(_startDim, _endDim); + return tensor.flatten(start_dim, end_dim); } - private long _startDim; - private long _endDim; + public long start_dim {get; set;} + public long end_dim { get; set; } // Rather than spending cycles only to discover that this module has neither // parameters nor buffers, just shortcut the move completely. diff --git a/src/TorchSharp/NN/Fold.cs b/src/TorchSharp/NN/Fold.cs index 5c4de0ff0..03f6a2a44 100644 --- a/src/TorchSharp/NN/Fold.cs +++ b/src/TorchSharp/NN/Fold.cs @@ -15,8 +15,8 @@ public sealed class Fold : torch.nn.Module { internal Fold((long, long) output_size, (long, long) kernel_size, (long, long) dilation, (long, long) padding, (long, long) stride) : base(nameof(Fold)) { - this.outputSize = output_size; - this.kernelSize = kernel_size; + this.output_size = output_size; + this.kernel_size = kernel_size; this.dilation = dilation; this.padding = padding; this.stride = stride; @@ -24,14 +24,14 @@ internal Fold((long, long) output_size, (long, long) kernel_size, (long, long) d public override Tensor forward(Tensor tensor) { - return torch.nn.functional.fold(tensor, outputSize , kernelSize, dilation, padding, stride); + return torch.nn.functional.fold(tensor, output_size , kernel_size, dilation, padding, stride); } - private (long, long) outputSize; - private (long, long) kernelSize; - private (long, long) dilation; - private (long, long) padding; - private (long, long) stride; + public (long, long) output_size { get; set; } + public (long, long) kernel_size { get; set; } + public (long, long) dilation { get; set; } + public (long, long) padding { get; set; } + public (long, long) stride { get; set; } } } From 6c0f2a2f25f15969e9b9ffa614575e78e3ac63c8 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 5 Mar 2024 12:42:21 -0800 Subject: [PATCH 30/47] Introduced 'ParamLessModule' as the base class on more modules. --- src/TorchSharp/NN/AlphaDropout.cs | 9 +-------- src/TorchSharp/NN/Dropout1d.cs | 8 +------- src/TorchSharp/NN/Dropout2d.cs | 8 +------- src/TorchSharp/NN/Dropout3d.cs | 10 ++-------- src/TorchSharp/NN/Flatten.cs | 6 +++--- src/TorchSharp/NN/Fold.cs | 2 +- src/TorchSharp/NN/Shuffle/ChannelShuffle.cs | 12 ++---------- src/TorchSharp/NN/Unfold.cs | 8 +------- 8 files changed, 12 insertions(+), 51 deletions(-) diff --git a/src/TorchSharp/NN/AlphaDropout.cs b/src/TorchSharp/NN/AlphaDropout.cs index 51634cb63..663c8994b 100644 --- a/src/TorchSharp/NN/AlphaDropout.cs +++ b/src/TorchSharp/NN/AlphaDropout.cs @@ -17,7 +17,7 @@ namespace Modules /// The elements to masked are randomized on every forward call, and scaled and shifted to maintain zero mean and unit standard deviation. /// During evaluation the module simply computes an identity function. ///
- public sealed class AlphaDropout : torch.nn.Module + public sealed class AlphaDropout : ParamLessModule { internal AlphaDropout(double p = 0.5, bool inplace = false) : base(nameof(Dropout1d)) { @@ -35,13 +35,6 @@ public override Tensor forward(Tensor tensor) return torch.nn.functional.alpha_dropout(tensor, this.p, this.training, inplace); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - public bool inplace { get; set; } public double p { get; set;} } diff --git a/src/TorchSharp/NN/Dropout1d.cs b/src/TorchSharp/NN/Dropout1d.cs index 77389bf69..70a51f96f 100644 --- a/src/TorchSharp/NN/Dropout1d.cs +++ b/src/TorchSharp/NN/Dropout1d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a Dropout2d module. /// - public sealed class Dropout1d : torch.nn.Module + public sealed class Dropout1d : ParamLessModule { internal Dropout1d(double p = 0.5, bool inplace = false) : base(nameof(Dropout1d)) { @@ -27,12 +27,6 @@ public override Tensor forward(Tensor tensor) return torch.nn.functional.dropout1d(tensor, this.p, this.training, this.inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - public bool inplace { get; set; } public double p { get; set;} } diff --git a/src/TorchSharp/NN/Dropout2d.cs b/src/TorchSharp/NN/Dropout2d.cs index 672fa4ad3..0f3989ba2 100644 --- a/src/TorchSharp/NN/Dropout2d.cs +++ b/src/TorchSharp/NN/Dropout2d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a Dropout2d module. /// - public sealed class Dropout2d : torch.nn.Module + public sealed class Dropout2d : ParamLessModule { internal Dropout2d(double p = 0.5, bool inplace = false) : base(nameof(Dropout2d)) { @@ -27,12 +27,6 @@ public override Tensor forward(Tensor input) return new Tensor(res); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - public bool inplace { get; set; } public double p { get; set;} } diff --git a/src/TorchSharp/NN/Dropout3d.cs b/src/TorchSharp/NN/Dropout3d.cs index 7e7567502..2d4fe88e8 100644 --- a/src/TorchSharp/NN/Dropout3d.cs +++ b/src/TorchSharp/NN/Dropout3d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a Dropout3d module. /// - public sealed class Dropout3d : nn.Module + public sealed class Dropout3d : ParamLessModule { internal Dropout3d(double p = 0.5, bool inplace = false) : base(nameof(Dropout3d)) { @@ -26,13 +26,7 @@ public override Tensor forward(Tensor input) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - + public bool inplace { get; set; } public double p { get; set;} } diff --git a/src/TorchSharp/NN/Flatten.cs b/src/TorchSharp/NN/Flatten.cs index 95ec5e41b..80093d294 100644 --- a/src/TorchSharp/NN/Flatten.cs +++ b/src/TorchSharp/NN/Flatten.cs @@ -14,10 +14,10 @@ namespace Modules ///
public sealed class Flatten : ParamLessModule { - internal Flatten(long startDim = 1, long endDim = -1) : base(nameof(Flatten)) + internal Flatten(long start_dim = 1, long end_dim = -1) : base(nameof(Flatten)) { - start_dim = startDim; - end_dim = endDim; + this.start_dim = start_dim; + this.end_dim = end_dim; } public override Tensor forward(Tensor tensor) diff --git a/src/TorchSharp/NN/Fold.cs b/src/TorchSharp/NN/Fold.cs index 03f6a2a44..9d1c0a9b6 100644 --- a/src/TorchSharp/NN/Fold.cs +++ b/src/TorchSharp/NN/Fold.cs @@ -11,7 +11,7 @@ namespace TorchSharp namespace Modules { - public sealed class Fold : torch.nn.Module + public sealed class Fold : ParamLessModule { internal Fold((long, long) output_size, (long, long) kernel_size, (long, long) dilation, (long, long) padding, (long, long) stride) : base(nameof(Fold)) { diff --git a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs index 65b8e4fdd..b153acc9e 100644 --- a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs +++ b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs @@ -11,13 +11,13 @@ namespace Modules /// /// This class is used to represent a ChannelShuffle module. /// - public sealed class ChannelShuffle : torch.nn.Module + public sealed class ChannelShuffle : ParamLessModule { internal ChannelShuffle(long groups) : base(nameof(ChannelShuffle)) { this.groups = groups; } - private long groups; + private long groups {get; set;} public override Tensor forward(Tensor tensor) { @@ -28,14 +28,6 @@ public override string GetName() { return typeof(ChannelShuffle).Name; } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Unfold.cs b/src/TorchSharp/NN/Unfold.cs index 7575c6169..aa56705bb 100644 --- a/src/TorchSharp/NN/Unfold.cs +++ b/src/TorchSharp/NN/Unfold.cs @@ -11,7 +11,7 @@ namespace TorchSharp namespace Modules { - public sealed class Unfold : torch.nn.Module + public sealed class Unfold : ParamLessModule { internal Unfold((long, long) kernel_size, (long, long) dilation, (long, long) padding, (long, long) stride) : base(nameof(Unfold)) { @@ -26,12 +26,6 @@ public override Tensor forward(Tensor tensor) return torch.nn.functional.unfold(tensor, kernelSize, dilation, padding, stride); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - private (long, long) kernelSize; private (long, long) dilation; private (long, long) padding; From 4cb57e19c9682267d3065484bb1ede783144f1df Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 5 Mar 2024 14:16:12 -0800 Subject: [PATCH 31/47] Added properties to a number of modules. Added 'ParamLessModule' as a base class to more modules. --- src/TorchSharp/NN/CosineSimilarity.cs | 10 +------ src/TorchSharp/NN/FeatureDropout.cs | 8 +----- src/TorchSharp/NN/Normalization/LayerNorm.cs | 14 ++++++---- .../NN/Normalization/LocalResponseNorm.cs | 2 +- src/TorchSharp/NN/Padding/PadBase.cs | 14 +++++----- src/TorchSharp/NN/ParamLessModule.cs | 27 +++++++++++++++++-- .../NN/Pooling/AdaptiveAvgPool1D.cs | 8 +----- .../NN/Pooling/AdaptiveAvgPool2D.cs | 8 +----- .../NN/Pooling/AdaptiveAvgPool3D.cs | 8 +----- .../NN/Pooling/AdaptiveMaxPool1D.cs | 8 +----- .../NN/Pooling/AdaptiveMaxPool2D.cs | 8 +----- .../NN/Pooling/AdaptiveMaxPool3D.cs | 8 +----- src/TorchSharp/NN/Pooling/AvgPool1D.cs | 8 +----- src/TorchSharp/NN/Pooling/AvgPool2D.cs | 8 +----- src/TorchSharp/NN/Pooling/AvgPool3D.cs | 8 +----- .../NN/Pooling/FractionalMaxPool2d.cs | 10 +------ .../NN/Pooling/FractionalMaxPool3d.cs | 8 +----- src/TorchSharp/NN/Pooling/LPPool1d.cs | 2 +- src/TorchSharp/NN/Pooling/LPPool2d.cs | 10 +------ src/TorchSharp/NN/Pooling/MaxPool1D.cs | 10 +------ src/TorchSharp/NN/Pooling/MaxPool2D.cs | 10 +------ src/TorchSharp/NN/Pooling/MaxPool3D.cs | 10 +------ src/TorchSharp/NN/Pooling/MaxUnpool1d.cs | 10 +------ src/TorchSharp/NN/Pooling/MaxUnpool2d.cs | 10 +------ src/TorchSharp/NN/Pooling/MaxUnpool3d.cs | 10 +------ src/TorchSharp/NN/Upsample.cs | 2 +- 26 files changed, 64 insertions(+), 175 deletions(-) diff --git a/src/TorchSharp/NN/CosineSimilarity.cs b/src/TorchSharp/NN/CosineSimilarity.cs index 0ce4a84b6..44399a1f2 100644 --- a/src/TorchSharp/NN/CosineSimilarity.cs +++ b/src/TorchSharp/NN/CosineSimilarity.cs @@ -12,7 +12,7 @@ namespace Modules /// /// A cosine similarity module. /// - public sealed class CosineSimilarity : torch.nn.Module + public sealed class CosineSimilarity : ParamLessModule { internal CosineSimilarity(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,14 +24,6 @@ public override Tensor forward(Tensor input1, Tensor input2) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/FeatureDropout.cs b/src/TorchSharp/NN/FeatureDropout.cs index 0e016b385..2ea7b45c6 100644 --- a/src/TorchSharp/NN/FeatureDropout.cs +++ b/src/TorchSharp/NN/FeatureDropout.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a dropout module for 2d/3d convolutational layers. /// - public sealed class FeatureAlphaDropout : torch.nn.Module + public sealed class FeatureAlphaDropout : ParamLessModule { internal FeatureAlphaDropout(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Normalization/LayerNorm.cs b/src/TorchSharp/NN/Normalization/LayerNorm.cs index 7010e754e..949cfe4d0 100644 --- a/src/TorchSharp/NN/Normalization/LayerNorm.cs +++ b/src/TorchSharp/NN/Normalization/LayerNorm.cs @@ -18,13 +18,17 @@ namespace Modules ///
public sealed class LayerNorm : torch.nn.Module { - private long[] _normalized_shape; - private double _eps; + public long[] normalized_shape { get; set; } + public double eps { get; set; } + + public bool elementwise_affine { get; set; } internal LayerNorm(long[] normalized_shape, double eps, bool elementwise_affine, bool bias, Device? device, ScalarType? dtype) : base(nameof(LayerNorm)) { - _normalized_shape = normalized_shape; - _eps = eps; + this.normalized_shape = normalized_shape; + this.eps = eps; + this.elementwise_affine = elementwise_affine; + if (elementwise_affine) { weight = Parameter(torch.empty(normalized_shape, dtype, device)); @@ -52,7 +56,7 @@ private void reset_parameters(bool elementwise_affine) public override Tensor forward(Tensor tensor) { - return F.layer_norm(tensor, _normalized_shape, weight, bias, _eps); + return F.layer_norm(tensor, normalized_shape, weight, bias, eps); } public Parameter? bias { diff --git a/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs b/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs index 5fc5f07b7..ba74b2e5e 100644 --- a/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs +++ b/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a LocalResponseNorm module. /// - public sealed class LocalResponseNorm : torch.nn.Module + public sealed class LocalResponseNorm : ParamLessModule { internal LocalResponseNorm(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { diff --git a/src/TorchSharp/NN/Padding/PadBase.cs b/src/TorchSharp/NN/Padding/PadBase.cs index 20c0dde47..6ae9bd87e 100644 --- a/src/TorchSharp/NN/Padding/PadBase.cs +++ b/src/TorchSharp/NN/Padding/PadBase.cs @@ -16,9 +16,9 @@ public class PadBase : ParamLessModule { protected PadBase(string name, PaddingModes mode, double value, params long[] padding) : base(name) { - _value = value; - _padding = padding; - _paddingMode = mode; + this.value = value; + this.padding = padding; + padding_mode = mode; } /// @@ -28,12 +28,12 @@ protected PadBase(string name, PaddingModes mode, double value, params long[] pa /// public override Tensor forward(Tensor input) { - return nn.functional.pad(input, _padding, _paddingMode, _value); + return nn.functional.pad(input, padding, padding_mode, value); } - private PaddingModes _paddingMode; - private long[] _padding; - private double _value = 0.0; + private PaddingModes padding_mode { get; set; } + public long[] padding { get; set; } + public double value { get; set; } } } } diff --git a/src/TorchSharp/NN/ParamLessModule.cs b/src/TorchSharp/NN/ParamLessModule.cs index c2a274a52..9e06897d9 100644 --- a/src/TorchSharp/NN/ParamLessModule.cs +++ b/src/TorchSharp/NN/ParamLessModule.cs @@ -10,13 +10,15 @@ namespace TorchSharp namespace Modules { /// - /// Base class for all modules that do not have any parameters or buffers, and + /// Base class for all modules that do not have any tensor parameters or buffers, and /// for which the `_to()` implementation can therefore be simplified. /// public abstract class ParamLessModule : nn.Module { protected ParamLessModule(string name) : base(name) { } + protected ParamLessModule(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) {} + // Rather than spending cycles only to discover that this module has neither // parameters nor buffers, just shortcut the move completely. protected internal override nn.Module _to(Device device, ScalarType dtype) => this; @@ -27,13 +29,34 @@ protected ParamLessModule(string name) : base(name) { } } /// - /// Base class for all modules that do not have any parameters or buffers, and + /// Base class for all modules that do not have any tensor parameters or buffers, and /// for which the `_to()` implementation can therefore be simplified. /// public abstract class ParamLessModule : nn.Module { protected ParamLessModule(string name) : base(name) { } + protected ParamLessModule(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) {} + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; + } + + /// + /// Base class for all modules that do not have any tensor parameters or buffers, and + /// for which the `_to()` implementation can therefore be simplified. + /// + public abstract class ParamLessModule : nn.Module + { + protected ParamLessModule(string name) : base(name) { } + + protected ParamLessModule(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) {} + // Rather than spending cycles only to discover that this module has neither // parameters nor buffers, just shortcut the move completely. protected internal override nn.Module _to(Device device, ScalarType dtype) => this; diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs index ec03a74f6..a658fb364 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AdaptiveAvgPool1D module. /// - public sealed class AdaptiveAvgPool1d : torch.nn.Module + public sealed class AdaptiveAvgPool1d : ParamLessModule { internal AdaptiveAvgPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs index 3f481d9d2..91c61d096 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AdaptiveAvgPool2D module. /// - public sealed class AdaptiveAvgPool2d : torch.nn.Module + public sealed class AdaptiveAvgPool2d : ParamLessModule { internal AdaptiveAvgPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs index 862bf0b02..f89426962 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AdaptiveAvgPool3D module. /// - public sealed class AdaptiveAvgPool3d : torch.nn.Module + public sealed class AdaptiveAvgPool3d : ParamLessModule { internal AdaptiveAvgPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs index 269d5aeec..5c71475cc 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AdaptiveMaxPool1D module. /// - public sealed class AdaptiveMaxPool1d : torch.nn.Module + public sealed class AdaptiveMaxPool1d : ParamLessModule { internal AdaptiveMaxPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs index 15dae4187..764d29732 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AdaptiveMaxPool2D module. /// - public sealed class AdaptiveMaxPool2d : torch.nn.Module + public sealed class AdaptiveMaxPool2d : ParamLessModule { internal AdaptiveMaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs index 3a07b1aa8..ec3bfc32f 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AdaptiveMaxPool3D module. /// - public sealed class AdaptiveMaxPool3d : torch.nn.Module + public sealed class AdaptiveMaxPool3d : ParamLessModule { internal AdaptiveMaxPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool1D.cs b/src/TorchSharp/NN/Pooling/AvgPool1D.cs index 3430fcdaa..9df33da82 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool1D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AvgPool1D module. /// - public sealed class AvgPool1d : torch.nn.Module + public sealed class AvgPool1d : ParamLessModule { internal AvgPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool2D.cs b/src/TorchSharp/NN/Pooling/AvgPool2D.cs index bdbd3d41e..77fe8d991 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool2D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AvgPool2D module. /// - public sealed class AvgPool2d : torch.nn.Module + public sealed class AvgPool2d : ParamLessModule { internal AvgPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool3D.cs b/src/TorchSharp/NN/Pooling/AvgPool3D.cs index cf499c839..bedc81f0a 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool3D.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a AvgPool3D module. /// - public sealed class AvgPool3d : torch.nn.Module + public sealed class AvgPool3d : ParamLessModule { internal AvgPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,12 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs index 169215cde..eecc1c4a3 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a FractionalMaxPool2D module. /// - public sealed class FractionalMaxPool2d : torch.nn.Module + public sealed class FractionalMaxPool2d : ParamLessModule { internal FractionalMaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -31,14 +31,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } return (new Tensor(res), new Tensor(indices)); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs index 59be5e2b4..692f2210f 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a FractionalMaxPool3d module. /// - public sealed class FractionalMaxPool3d : torch.nn.Module + public sealed class FractionalMaxPool3d : ParamLessModule { internal FractionalMaxPool3d(IntPtr handle, IntPtr boxedHandle, bool ratio) : base(handle, boxedHandle) { @@ -41,12 +41,6 @@ public override Tensor forward(Tensor tensor) return (new Tensor(res), new Tensor(indices)); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - private bool _used_ratio = false; } } diff --git a/src/TorchSharp/NN/Pooling/LPPool1d.cs b/src/TorchSharp/NN/Pooling/LPPool1d.cs index bd0c7d9bd..62e4a2a4e 100644 --- a/src/TorchSharp/NN/Pooling/LPPool1d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool1d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a LPPool1D module. /// - public sealed class LPPool1d : torch.nn.Module + public sealed class LPPool1d : ParamLessModule { internal LPPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { diff --git a/src/TorchSharp/NN/Pooling/LPPool2d.cs b/src/TorchSharp/NN/Pooling/LPPool2d.cs index 811d97598..8555803de 100644 --- a/src/TorchSharp/NN/Pooling/LPPool2d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool2d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a LPPool2D module. /// - public sealed class LPPool2d : torch.nn.Module + public sealed class LPPool2d : ParamLessModule { internal LPPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -24,14 +24,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool1D.cs b/src/TorchSharp/NN/Pooling/MaxPool1D.cs index 6484c149e..46254dcd7 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool1D.cs @@ -13,7 +13,7 @@ namespace Modules /// /// This class is used to represent a MaxPool1D module. /// - public sealed class MaxPool1d : torch.nn.Module + public sealed class MaxPool1d : ParamLessModule { internal MaxPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -32,14 +32,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } return (new Tensor(res), new Tensor(indices)); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool2D.cs b/src/TorchSharp/NN/Pooling/MaxPool2D.cs index b8657ccb0..7d96145df 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool2D.cs @@ -13,7 +13,7 @@ namespace Modules /// /// This class is used to represent a MaxPool2D module. /// - public sealed class MaxPool2d : torch.nn.Module + public sealed class MaxPool2d : ParamLessModule { internal MaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -31,14 +31,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } return (new Tensor(res), new Tensor(indices)); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool3D.cs b/src/TorchSharp/NN/Pooling/MaxPool3D.cs index 165a0c847..1999c34dc 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool3D.cs @@ -13,7 +13,7 @@ namespace Modules /// /// This class is used to represent a MaxPool3D module. /// - public sealed class MaxPool3d : torch.nn.Module + public sealed class MaxPool3d : ParamLessModule { internal MaxPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -32,14 +32,6 @@ public override Tensor forward(Tensor tensor) if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } return (new Tensor(res), new Tensor(indices)); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs index 0f2fe9bd9..d2bf0ddeb 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a MaxUnpool1D module. /// - public sealed class MaxUnpool1d : torch.nn.Module + public sealed class MaxUnpool1d : ParamLessModule { internal MaxUnpool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -33,14 +33,6 @@ public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size { return base.call(tensor, indices, output_size); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs index ded7b81ee..e01e6ddcf 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a MaxUnpool2D module. /// - public sealed class MaxUnpool2d : torch.nn.Module + public sealed class MaxUnpool2d : ParamLessModule { internal MaxUnpool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -33,14 +33,6 @@ public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size { return base.call(tensor, indices, output_size); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs index 32b85ce5a..85d52e208 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent a MaxUnpool3d module. /// - public sealed class MaxUnpool3d : torch.nn.Module + public sealed class MaxUnpool3d : ParamLessModule { internal MaxUnpool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { @@ -33,14 +33,6 @@ public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size { return base.call(tensor, indices, output_size); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Upsample.cs b/src/TorchSharp/NN/Upsample.cs index f313677f8..2427cc5a9 100644 --- a/src/TorchSharp/NN/Upsample.cs +++ b/src/TorchSharp/NN/Upsample.cs @@ -204,7 +204,7 @@ namespace Modules /// /// This class is used to represent an Upsample module. /// - public sealed class Upsample : torch.nn.Module + public sealed class Upsample : ParamLessModule { internal Upsample(IntPtr handle, IntPtr boxedHandle, long[]? size, double[]? scale_factor, UpsampleMode mode, bool? align_corners) : base(handle, boxedHandle) { From 34405c60db633687fafabc2e8409bc29ae19894c Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 5 Mar 2024 14:44:36 -0800 Subject: [PATCH 32/47] Removed unused Bilinear native APIs. --- src/Native/LibTorchSharp/THSNN.cpp | 34 ------------------- src/Native/LibTorchSharp/THSNN.h | 7 ---- src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 18 ---------- 3 files changed, 59 deletions(-) diff --git a/src/Native/LibTorchSharp/THSNN.cpp b/src/Native/LibTorchSharp/THSNN.cpp index 7f4694bcc..256db0613 100644 --- a/src/Native/LibTorchSharp/THSNN.cpp +++ b/src/Native/LibTorchSharp/THSNN.cpp @@ -30,40 +30,6 @@ Tensor THSNN_functional_bilinear(const Tensor input1, const Tensor input2, const torch::nn::functional::bilinear(*input1, *input2, *weights, *bias)); } -NNModule THSNN_Bilinear_ctor(const int64_t input_size_1, const int64_t input_size_2, const int64_t output_size, const bool bias, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::BilinearOptions(input_size_1, input_size_2, output_size).bias(bias); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Bilinear_forward(const NNModule module, const Tensor x1, const Tensor x2) -{ - CATCH_TENSOR((*module)->as()->forward(*x1, *x2)); -} - -Tensor THSNN_Bilinear_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_Bilinear_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_Bilinear_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_Bilinear_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - Tensor THSNN_dropout(const Tensor input, const double p, bool training, bool inplace) { auto opts = torch::nn::functional::DropoutFuncOptions() diff --git a/src/Native/LibTorchSharp/THSNN.h b/src/Native/LibTorchSharp/THSNN.h index d1ec9594f..b48ea866a 100644 --- a/src/Native/LibTorchSharp/THSNN.h +++ b/src/Native/LibTorchSharp/THSNN.h @@ -293,13 +293,6 @@ EXPORT_API(Tensor) THSNN_Identity_forward(const NNModule module, const Tensor EXPORT_API(Tensor) THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias); EXPORT_API(Tensor) THSNN_functional_bilinear(const Tensor input1, const Tensor input2, const Tensor weights, const Tensor bias); -EXPORT_API(NNModule) THSNN_Bilinear_ctor(const int64_t input_size_1, const int64_t input_size_2, const int64_t output_size, const bool with_bias, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Bilinear_forward(const NNModule module, const Tensor x1, const Tensor x2); -EXPORT_API(Tensor) THSNN_Bilinear_bias(const NNModule module); -EXPORT_API(void) THSNN_Bilinear_set_bias(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_Bilinear_weight(const NNModule module); -EXPORT_API(void) THSNN_Bilinear_set_weight(const NNModule module, const Tensor tensor); - // Vision -- Modules EXPORT_API(NNModule) THSNN_PixelShuffle_ctor(const int64_t upscale_factor, NNAnyModule* outAsAnyModule); diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index ebb39f06e..6756b2795 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -59,24 +59,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_alpha_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Bilinear_forward(torch.nn.Module.HType module, IntPtr input1, IntPtr input2); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Bilinear_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_Bilinear_set_bias(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Bilinear_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_Bilinear_set_weight(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Bilinear_ctor(long in1_features, long in2_features, long output_size, [MarshalAs(UnmanagedType.U1)] bool bias, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_functional_bilinear(IntPtr input1, IntPtr input2, IntPtr weights, IntPtr bias); From f246c11aef0ca39cba51b313ba08fc2463656aa3 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 5 Mar 2024 14:55:09 -0800 Subject: [PATCH 33/47] Added Component name attribute to some classes. --- src/TorchSharp/NN/Bilinear.cs | 5 ++++- src/TorchSharp/NN/Linear.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/TorchSharp/NN/Bilinear.cs b/src/TorchSharp/NN/Bilinear.cs index 17a9dc903..5d37010e1 100644 --- a/src/TorchSharp/NN/Bilinear.cs +++ b/src/TorchSharp/NN/Bilinear.cs @@ -8,6 +8,7 @@ namespace TorchSharp { using Modules; + using TorchSharp.Utils; namespace Modules { @@ -49,7 +50,6 @@ public Parameter? bias { ConditionallyRegisterParameter(nameof(bias), _bias); } } - private Parameter? _bias; public Parameter weight { get => _weight!; @@ -63,6 +63,9 @@ public Parameter weight { } } + [ComponentName(Name = "bias")] + private Parameter? _bias; + [ComponentName(Name = "weight")] private Parameter? _weight; } } diff --git a/src/TorchSharp/NN/Linear.cs b/src/TorchSharp/NN/Linear.cs index 8bcfbe871..c2776fd5b 100644 --- a/src/TorchSharp/NN/Linear.cs +++ b/src/TorchSharp/NN/Linear.cs @@ -8,6 +8,7 @@ namespace TorchSharp { using Modules; + using TorchSharp.Utils; namespace Modules { @@ -48,7 +49,6 @@ public Parameter? bias { ConditionallyRegisterParameter(nameof(bias), _bias); } } - private Parameter? _bias; public Parameter weight { get => _weight!; @@ -83,6 +83,9 @@ protected internal override nn.Module _to(ScalarType dtype) return this; } + [ComponentName(Name = "bias")] + private Parameter? _bias; + [ComponentName(Name = "weight")] private Parameter? _weight; private static readonly double _sqrt5 = Math.Sqrt(5); } From cff452a44edd4b088082a0f2fa786f673e4eadee Mon Sep 17 00:00:00 2001 From: shaltielshmid Date: Tue, 12 Mar 2024 18:52:42 +0200 Subject: [PATCH 34/47] Reviewed all modified modules and continued, made adjustments and continued with rehaul (#16) * Reviewed all modified modules and continued, made adjustments and continued with rehaul * Added linear properties --- src/Examples/AlexNet.cs | 6 +- src/Examples/MNIST.cs | 2 +- src/Examples/VGG.cs | 2 +- src/FSharp.Examples/AlexNet.fs | 6 +- src/FSharp.Examples/MNIST.fs | 2 +- src/Native/LibTorchSharp/THSConvolution.cpp | 405 ------------------ src/Native/LibTorchSharp/THSNN.cpp | 203 +-------- src/Native/LibTorchSharp/THSNN.h | 106 +---- src/Native/LibTorchSharp/THSNormalization.cpp | 55 --- src/Native/LibTorchSharp/THSTensor.h | 71 +-- src/Native/LibTorchSharp/THSTensorConv.cpp | 273 ++++++++---- src/TorchSharp/NN/Bilinear.cs | 20 +- src/TorchSharp/NN/CosineSimilarity.cs | 21 +- src/TorchSharp/NN/Dropout.cs | 6 - src/TorchSharp/NN/Dropout2d.cs | 4 +- src/TorchSharp/NN/Dropout3d.cs | 4 +- src/TorchSharp/NN/FeatureDropout.cs | 20 +- src/TorchSharp/NN/Flatten.cs | 12 +- src/TorchSharp/NN/Identity.cs | 6 - src/TorchSharp/NN/Linear.cs | 39 +- src/TorchSharp/NN/Normalization/Functional.cs | 10 - src/TorchSharp/NN/Normalization/LayerNorm.cs | 36 +- .../NN/Normalization/LocalResponseNorm.cs | 40 +- src/TorchSharp/NN/Padding/PadBase.cs | 2 +- src/TorchSharp/NN/Padding/ReflectionPad2d.cs | 2 +- src/TorchSharp/NN/Padding/ReflectionPad3d.cs | 2 +- src/TorchSharp/NN/Padding/ReplicationPad2d.cs | 2 +- src/TorchSharp/NN/Padding/ReplicationPad3d.cs | 2 +- src/TorchSharp/NN/PixelShuffle.cs | 45 +- src/TorchSharp/NN/PixelUnshuffle.cs | 43 +- .../NN/Pooling/AdaptiveAvgPool1D.cs | 20 +- .../NN/Pooling/AdaptiveAvgPool2D.cs | 39 +- .../NN/Pooling/AdaptiveAvgPool3D.cs | 40 +- .../NN/Pooling/AdaptiveMaxPool1D.cs | 57 ++- .../NN/Pooling/AdaptiveMaxPool2D.cs | 57 ++- .../NN/Pooling/AdaptiveMaxPool3D.cs | 57 ++- src/TorchSharp/NN/Pooling/AvgPool1D.cs | 46 +- src/TorchSharp/NN/Pooling/AvgPool2D.cs | 132 +++--- src/TorchSharp/NN/Pooling/AvgPool3D.cs | 102 ++--- .../NN/Pooling/FractionalMaxPool2d.cs | 161 ++++++- .../NN/Pooling/FractionalMaxPool3d.cs | 173 ++++++-- src/TorchSharp/NN/Pooling/LPPool1d.cs | 60 +-- src/TorchSharp/NN/Pooling/LPPool2d.cs | 72 +++- src/TorchSharp/NN/Pooling/MaxPool1D.cs | 105 ++--- src/TorchSharp/NN/Pooling/MaxPool2D.cs | 214 ++++----- src/TorchSharp/NN/Pooling/MaxPool3D.cs | 117 +++-- src/TorchSharp/NN/Pooling/MaxUnpool1d.cs | 58 ++- src/TorchSharp/NN/Pooling/MaxUnpool2d.cs | 64 +-- src/TorchSharp/NN/Pooling/MaxUnpool3d.cs | 77 ++-- src/TorchSharp/NN/Shuffle/ChannelShuffle.cs | 5 +- src/TorchSharp/NN/Unflatten.cs | 25 +- src/TorchSharp/NN/Unfold.cs | 21 +- src/TorchSharp/NN/Upsample.cs | 107 ++--- src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 182 +------- .../PInvoke/LibTorchSharp.THSTensor.cs | 91 ++-- src/TorchVision/Ops/DropBlock.cs | 4 +- src/TorchVision/models/AlexNet.cs | 6 +- src/TorchVision/models/GoogleNet.cs | 10 +- src/TorchVision/models/InceptionV3.cs | 16 +- src/TorchVision/models/ResNet.cs | 2 +- src/TorchVision/models/VGG.cs | 2 +- test/TorchSharpTest/NN.cs | 2 +- test/TorchSharpTest/TestTorchTensorBugs.cs | 4 +- 63 files changed, 1459 insertions(+), 2116 deletions(-) diff --git a/src/Examples/AlexNet.cs b/src/Examples/AlexNet.cs index 17b08b7c3..aa893255e 100644 --- a/src/Examples/AlexNet.cs +++ b/src/Examples/AlexNet.cs @@ -19,17 +19,17 @@ public AlexNet(string name, int numClasses, torch.Device device = null) : base(n features = Sequential( ("c1", Conv2d(3, 64, kernelSize: 3, stride: 2, padding: 1)), ("r1", ReLU(inplace: true)), - ("mp1", MaxPool2d(kernelSize: new long[] { 2, 2 })), + ("mp1", MaxPool2d(kernel_size: new long[] { 2, 2 })), ("c2", Conv2d(64, 192, kernelSize: 3, padding: 1)), ("r2", ReLU(inplace: true)), - ("mp2", MaxPool2d(kernelSize: new long[] { 2, 2 })), + ("mp2", MaxPool2d(kernel_size: new long[] { 2, 2 })), ("c3", Conv2d(192, 384, kernelSize: 3, padding: 1)), ("r3", ReLU(inplace: true)), ("c4", Conv2d(384, 256, kernelSize: 3, padding: 1)), ("r4", ReLU(inplace: true)), ("c5", Conv2d(256, 256, kernelSize: 3, padding: 1)), ("r5", ReLU(inplace: true)), - ("mp3", MaxPool2d(kernelSize: new long[] { 2, 2 }))); + ("mp3", MaxPool2d(kernel_size: new long[] { 2, 2 }))); avgPool = AdaptiveAvgPool2d(new long[] { 2, 2 }); diff --git a/src/Examples/MNIST.cs b/src/Examples/MNIST.cs index 73c8e69b0..d3059406a 100644 --- a/src/Examples/MNIST.cs +++ b/src/Examples/MNIST.cs @@ -105,7 +105,7 @@ internal class Model : Module // These don't have any parameters, so the only reason to instantiate // them is performance, since they will be used over and over. - private Module pool1 = MaxPool2d(kernelSize: new long[] { 2, 2 }); + private Module pool1 = MaxPool2d(kernel_size: new long[] { 2, 2 }); private Module relu1 = ReLU(); private Module relu2 = ReLU(); diff --git a/src/Examples/VGG.cs b/src/Examples/VGG.cs index 0c12eca4e..033bf6491 100644 --- a/src/Examples/VGG.cs +++ b/src/Examples/VGG.cs @@ -38,7 +38,7 @@ public VGG(string name, int numClasses, Device device = null) : base(name) for (var i = 0; i < channels.Length; i++) { if (channels[i] == 0) { - modules.Add(($"MaxPool2d-{i}a", MaxPool2d(kernelSize: 2, stride: 2))); + modules.Add(($"MaxPool2d-{i}a", MaxPool2d(kernel_size: 2, stride: 2))); } else { modules.Add(($"conv2d-{i}a", Conv2d(in_channels, channels[i], kernelSize: 3, padding: 1))); modules.Add(($"bnrm2d-{i}a", BatchNorm2d(channels[i]))); diff --git a/src/FSharp.Examples/AlexNet.fs b/src/FSharp.Examples/AlexNet.fs index 9a1e3fbe1..5604f0923 100644 --- a/src/FSharp.Examples/AlexNet.fs +++ b/src/FSharp.Examples/AlexNet.fs @@ -49,17 +49,17 @@ type Model(name,device:torch.Device) as this = let features = Sequential(("c1", Conv2d(3L, 64L, kernelSize=3L, stride=2L, padding=1L) :> Module), ("r1", ReLU(inplace=true) :> Module), - ("mp1", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), + ("mp1", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), ("c2", Conv2d(64L, 192L, kernelSize=3L, padding=1L) :> Module), ("r2", ReLU(inplace=true) :> Module), - ("mp2", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), + ("mp2", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), ("c3", Conv2d(192L, 384L, kernelSize=3L, padding=1L) :> Module), ("r3", ReLU(inplace=true) :> Module), ("c4", Conv2d(384L, 256L, kernelSize=3L, padding=1L) :> Module), ("r4", ReLU(inplace=true) :> Module), ("c5", Conv2d(256L, 256L, kernelSize=3L, padding=1L) :> Module), ("r5", ReLU(inplace=true) :> Module), - ("mp3", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), + ("mp3", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), ("avg", AdaptiveAvgPool2d([|2L; 2L|]) :> Module)) let classifier = Sequential(("d1", Dropout() :> Module), diff --git a/src/FSharp.Examples/MNIST.fs b/src/FSharp.Examples/MNIST.fs index d042f6f97..6967ebdc6 100644 --- a/src/FSharp.Examples/MNIST.fs +++ b/src/FSharp.Examples/MNIST.fs @@ -51,7 +51,7 @@ type Model(name,device:torch.Device) as this = let fc1 = Linear(9216L, 128L) let fc2 = Linear(128L, 10L) - let pool1 = MaxPool2d(kernelSize=[|2L; 2L|]) + let pool1 = MaxPool2d(kernel_size=[|2L; 2L|]) let relu = ReLU() diff --git a/src/Native/LibTorchSharp/THSConvolution.cpp b/src/Native/LibTorchSharp/THSConvolution.cpp index fb51e4c91..17120ded9 100644 --- a/src/Native/LibTorchSharp/THSConvolution.cpp +++ b/src/Native/LibTorchSharp/THSConvolution.cpp @@ -3,411 +3,6 @@ #include - - -NNModule THSNN_AvgPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, - bool ceil_mode, bool count_include_pad, int64_t divisor_override, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AvgPool1dOptions(at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); - if (stride) - opts = opts.stride(at::ArrayRef(stride, 1)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, 1)); - if (divisor_override > 0) - opts = opts.divisor_override(divisor_override); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AvgPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, - bool ceil_mode, bool count_include_pad, int64_t divisor_override, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AvgPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - if (divisor_override > 0) - opts = opts.divisor_override(divisor_override); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AvgPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, - bool ceil_mode, bool count_include_pad, int64_t divisor_override, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AvgPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - if (divisor_override > 0) - opts = opts.divisor_override(divisor_override); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AvgPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveAvgPool1d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveAvgPool1dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveAvgPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveAvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveAvgPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveAvgPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveAvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveAvgPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveAvgPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveMaxPool1d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveMaxPool1dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveMaxPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveMaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveMaxPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveMaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveMaxPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_LPPool1d_ctor(double norm_type, const int64_t* kernelSize, const int64_t* stride, const bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LPPool1dOptions(norm_type, at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, 1)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LPPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_LPPool2d_ctor(double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LPPool2dOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LPPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_MaxPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, const int64_t* dilation, bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxPool1dOptions(at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, 1)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, 1)); - if (dilation) - opts = opts.dilation(at::ArrayRef(dilation, 1)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_MaxPool1d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - -NNModule THSNN_MaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - if (dilation) - opts = opts.dilation(at::ArrayRef(dilation, dilationLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_MaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - -NNModule THSNN_MaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - if (dilation) - opts = opts.dilation(at::ArrayRef(dilation, dilationLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_MaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - -NNModule THSNN_MaxUnpool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxUnpool1dOptions(at::ArrayRef(kernelSize, 1)); - if (stride) - opts = opts.stride(at::ArrayRef(stride, 1)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, 1)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxUnpool1d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize) -{ - if (outputSize != nullptr) { - std::vector outSize; - outSize.push_back(*outputSize); - - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); - } - else { - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); - } -} - -NNModule THSNN_MaxUnpool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxUnpool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxUnpool2d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength) -{ - if (outputSize != nullptr) { - std::vector outSize; - for (auto i = 0L; i < outputSizeLength; i++) { - outSize.push_back(outputSize[i]); - } - - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); - } - else { - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); - } -} - -NNModule THSNN_MaxUnpool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxUnpool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxUnpool3d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength) -{ - if (outputSize != nullptr) { - std::vector outSize; - for (auto i = 0L; i < outputSizeLength; i++) { - outSize.push_back(outputSize[i]); - } - - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); - } - else { - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); - } -} - - -NNModule THSNN_FractionalMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::FractionalMaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (outputSize) - opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); - if (outputRatio) - opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_FractionalMaxPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_FractionalMaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - -NNModule THSNN_FractionalMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::FractionalMaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (outputSize) - opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); - if (outputRatio) - opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_FractionalMaxPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_FractionalMaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - template void ApplyPaddingMode(T& opts, const int64_t padding) { diff --git a/src/Native/LibTorchSharp/THSNN.cpp b/src/Native/LibTorchSharp/THSNN.cpp index 256db0613..d1e6297e0 100644 --- a/src/Native/LibTorchSharp/THSNN.cpp +++ b/src/Native/LibTorchSharp/THSNN.cpp @@ -3,19 +3,6 @@ #include - -NNModule THSNN_Identity_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_Identity_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - Tensor THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias) { CATCH_TENSOR(bias == nullptr ? @@ -80,113 +67,16 @@ Tensor THSNN_feature_alpha_dropout(const Tensor input, const double p, bool trai CATCH_TENSOR(torch::nn::functional::feature_alpha_dropout(*input, opts)); } -NNModule THSNN_Dropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::DropoutOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Dropout_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AlphaDropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AlphaDropoutOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AlphaDropout_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Dropout1d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - // Creating a Dropout2d instance here is done on purpose. There's no torch::nn::Dropout1d - auto opts = torch::nn::Dropout2dOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Dropout1d_forward(const NNModule module, const Tensor tensor) -{ - auto drop1d = (*module)->as(); - CATCH_TENSOR(drop1d->options.inplace() - ? drop1d->forward((*tensor).unsqueeze_(-1)).squeeze_(-1) - : drop1d->forward((*tensor).unsqueeze(-1)).squeeze(-1)); -} - - -NNModule THSNN_Dropout2d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::Dropout2dOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Dropout2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Dropout3d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::Dropout3dOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Dropout3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_FeatureAlphaDropout_ctor(double probability, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::FeatureAlphaDropoutOptions(probability); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_FeatureAlphaDropout_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_PixelShuffle_ctor(const int64_t upscale_factor, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::PixelShuffleOptions(upscale_factor); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_PixelShuffle_forward(const NNModule module, const Tensor tensor) +Tensor THSNN_pixel_shuffle(const Tensor tensor, const int64_t upscale_factor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_PixelUnshuffle_ctor(const int64_t downscale_factor, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::PixelUnshuffleOptions(downscale_factor); - res = create_module(opts, outAsAnyModule); - ); + auto opts = torch::nn::functional::PixelShuffleFuncOptions(upscale_factor); + CATCH_TENSOR(torch::nn::functional::pixel_shuffle(*tensor, opts)); } -Tensor THSNN_PixelUnshuffle_forward(const NNModule module, const Tensor tensor) +Tensor THSNN_pixel_unshuffle(const Tensor tensor, const int64_t downscale_factor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); + auto opts = torch::nn::functional::PixelUnshuffleFuncOptions(downscale_factor); + CATCH_TENSOR(torch::nn::functional::pixel_unshuffle(*tensor, opts)); } template @@ -221,38 +111,6 @@ void ApplyInterpolateMode(T& opts, const int8_t mode) opts = opts.mode(torch::kArea); } -NNModule THSNN_Upsample_ctor(const int64_t* size, const int size_len, const double* scale_factor, const int scale_factor_len, const int8_t mode, const int8_t align_corners, NNAnyModule* outAsAnyModule) -{ - auto opts = torch::nn::UpsampleOptions(); - // align_corners -- 0=None, 1=true, 2=false - if (align_corners != 0) - opts.align_corners(align_corners == 1); - ApplyUpsampleMode(opts, mode); - - CATCH_RETURN_NNModule( - if (size_len > 0) { - std::vector sizes; - for (int i = 0; i < size_len; ++i) { - sizes.push_back(size[i]); - } - opts.size(sizes); - } - if (scale_factor_len > 0) { - std::vector scales; - for (int i = 0; i < scale_factor_len; ++i) { - scales.push_back(scale_factor[i]); - } - opts.scale_factor(scales); - } - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Upsample_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - template void ApplyPadMode(T& opts, const int64_t padding) { @@ -675,54 +533,9 @@ Tensor THSNN_TransformerDecoder_forward(const NNModule module, const Tensor tg ); } -NNModule THSNN_Flatten_ctor(const int64_t start_dim, const int64_t end_dim, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::FlattenOptions() - .start_dim(start_dim) - .end_dim(end_dim); - - res = create_module(opts, outAsAnyModule); - ); -} -Tensor THSNN_Flatten_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Unflatten_ctor(const int64_t dim, const int64_t* shape, const int64_t shape_len, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - std::vector sizes; - for (int64_t i = 0; i < shape_len; ++i) - { - sizes.push_back(shape[i]); - } - auto opts = torch::nn::UnflattenOptions(dim, sizes); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Unflatten_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_CosineSimilarity_ctor(const int64_t dim, double eps, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::CosineSimilarityOptions() - .dim(dim) - .eps(eps); - - res = create_module(opts, outAsAnyModule); - ); - -} - -Tensor THSNN_CosineSimilarity_forward(const NNModule module, const Tensor input1, const Tensor input2) +Tensor THSNN_cosine_similarity(const Tensor input1, const Tensor input2, int64_t dim, double eps) { - CATCH_TENSOR((*module)->as()->forward(*input1, *input2)); + CATCH_TENSOR(torch::nn::functional::cosine_similarity(*input1, *input2, torch::nn::functional::CosineSimilarityFuncOptions().dim(dim).eps(eps))); } NNModule THSNN_PairwiseDistance_ctor(double p, double eps, bool keep_dim, NNAnyModule* outAsAnyModule) diff --git a/src/Native/LibTorchSharp/THSNN.h b/src/Native/LibTorchSharp/THSNN.h index b48ea866a..94d1400ac 100644 --- a/src/Native/LibTorchSharp/THSNN.h +++ b/src/Native/LibTorchSharp/THSNN.h @@ -37,63 +37,6 @@ EXPORT_API(void) THSNN_AnyModule_dispose(const NNAnyModule module); EXPORT_API(NNModule) THSNN_custom_module(const char* name, Tensor(*forward)(Tensor), NNAnyModule* outAsAnyModule); -// Pooling - -EXPORT_API(NNModule) THSNN_MaxPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, const int64_t* dilation, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_MaxPool1d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor *indices); - -EXPORT_API(NNModule) THSNN_MaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_MaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); - -EXPORT_API(NNModule) THSNN_MaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxPool3d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_MaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); - -EXPORT_API(NNModule) THSNN_FractionalMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_FractionalMaxPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_FractionalMaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); - -EXPORT_API(NNModule) THSNN_FractionalMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_FractionalMaxPool3d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_FractionalMaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); - -EXPORT_API(NNModule) THSNN_MaxUnpool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxUnpool1d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize); - -EXPORT_API(NNModule) THSNN_MaxUnpool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxUnpool2d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength); - -EXPORT_API(NNModule) THSNN_MaxUnpool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxUnpool3d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength); - -EXPORT_API(NNModule) THSNN_AdaptiveAvgPool1d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveAvgPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AdaptiveAvgPool2d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveAvgPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AdaptiveAvgPool3d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveAvgPool3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_AdaptiveMaxPool1d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveMaxPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AdaptiveMaxPool2d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveMaxPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AdaptiveMaxPool3d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveMaxPool3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_AvgPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AvgPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AvgPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AvgPool3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_LPPool1d_ctor(double norm_type, const int64_t* kernelSize, const int64_t* stride, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LPPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_LPPool2d_ctor(double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LPPool2d_forward(const NNModule module, const Tensor tensor); - // Convolution EXPORT_API(NNModule) THSNN_Conv1d_ctor(const int64_t inputChannel, const int64_t outputChannel, const int64_t kernelSize, const int64_t stride, const int64_t padding, const int64_t dilation, const int64_t paddingMode, const int64_t groups, const bool bias, NNAnyModule* outAsAnyModule); @@ -230,16 +173,6 @@ EXPORT_API(Tensor) THSNN_InstanceNorm1d_get_batches(const NNModule module); EXPORT_API(Tensor) THSNN_InstanceNorm2d_get_batches(const NNModule module); EXPORT_API(Tensor) THSNN_InstanceNorm3d_get_batches(const NNModule module); - - -EXPORT_API(NNModule) THSNN_LayerNorm_ctor(const int64_t* norm_shape, const int64_t norm_shape_len, const double eps, const bool elementwise_affine, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LayerNorm_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(Tensor) THSNN_LayerNorm_bias(const NNModule module); -EXPORT_API(void) THSNN_LayerNorm_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_LayerNorm_weight(const NNModule module); -EXPORT_API(void) THSNN_LayerNorm_set_weight(const NNModule module, const Tensor weight); - EXPORT_API(NNModule) THSNN_GroupNorm_ctor(const int64_t num_groups, const int64_t num_channels, const double eps, const bool affine, NNAnyModule* outAsAnyModule); EXPORT_API(Tensor) THSNN_GroupNorm_forward(const NNModule module, const Tensor tensor); @@ -248,9 +181,6 @@ EXPORT_API(void) THSNN_GroupNorm_set_bias(const NNModule module, const Tenso EXPORT_API(Tensor) THSNN_GroupNorm_weight(const NNModule module); EXPORT_API(void) THSNN_GroupNorm_set_weight(const NNModule module, const Tensor weight); -EXPORT_API(NNModule) THSNN_LocalResponseNorm_ctor(const int64_t size, const double alpha, const double beta, const double k, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LocalResponseNorm_forward(const NNModule module, const Tensor tensor); - EXPORT_API(Tensor) THSNN_batch_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool training, const double momentum, const double eps); EXPORT_API(Tensor) THSNN_group_norm(const Tensor input, int64_t num_groups, const Tensor weight, const Tensor bias, const double eps); EXPORT_API(Tensor) THSNN_instance_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool use_input_stats, const double momentum, const double eps); @@ -258,22 +188,6 @@ EXPORT_API(Tensor) THSNN_layer_norm(const Tensor input, const int64_t* normali EXPORT_API(Tensor) THSNN_local_response_norm(const Tensor input, const int64_t size, const double alpha, const double beta, const double k); // Dropout - -EXPORT_API(NNModule) THSNN_Dropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Dropout_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Dropout1d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Dropout1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Dropout2d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Dropout2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Dropout3d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Dropout3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_AlphaDropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AlphaDropout_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_FeatureAlphaDropout_ctor(double probability, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_FeatureAlphaDropout_forward(const NNModule module, const Tensor tensor); - EXPORT_API(Tensor) THSNN_dropout(const Tensor input, const double p, bool training, bool inplace); EXPORT_API(Tensor) THSNN_dropout2d(const Tensor input, const double p, bool training, bool inplace); EXPORT_API(Tensor) THSNN_dropout3d(const Tensor input, const double p, bool training, bool inplace); @@ -287,20 +201,13 @@ EXPORT_API(Tensor) THSNN_unfold(const Tensor input, const int64_t kernel1, const // Linear -EXPORT_API(NNModule) THSNN_Identity_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Identity_forward(const NNModule module, const Tensor tensor); - EXPORT_API(Tensor) THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias); EXPORT_API(Tensor) THSNN_functional_bilinear(const Tensor input1, const Tensor input2, const Tensor weights, const Tensor bias); // Vision -- Modules -EXPORT_API(NNModule) THSNN_PixelShuffle_ctor(const int64_t upscale_factor, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_PixelShuffle_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_PixelUnshuffle_ctor(const int64_t downscale_factor, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_PixelUnshuffle_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Upsample_ctor(const int64_t* size, const int size_len, const double* scale_factor, const int scale_factor_len, const int8_t mode, const int8_t align_corners, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Upsample_forward(const NNModule module, const Tensor tensor); +EXPORT_API(Tensor) THSNN_pixel_shuffle(const Tensor tensor, const int64_t upscale_factor); +EXPORT_API(Tensor) THSNN_pixel_unshuffle(const Tensor tensor, const int64_t downscale_fasctor); // Vision -- Functions @@ -513,14 +420,7 @@ EXPORT_API(void) THSNN_SGD_set_lr(const Optimizer optimizer, const double lr); EXPORT_API(Tensor) THSNN_one_hot(const Tensor self, const int64_t num_classes); -EXPORT_API(NNModule) THSNN_Flatten_ctor(const int64_t start_dim, const int64_t end_dim, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Flatten_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_Unflatten_ctor(const int64_t dim, const int64_t* shape, const int64_t shape_len, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Unflatten_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_CosineSimilarity_ctor(const int64_t dim, double eps, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_CosineSimilarity_forward(const NNModule module, const Tensor input1, const Tensor input2); +EXPORT_API(Tensor) THSNN_cosine_similarity(const Tensor input1, const Tensor input2, int64_t dim, double eps); EXPORT_API(NNModule) THSNN_PairwiseDistance_ctor(double p, double eps, bool keep_dim, NNAnyModule* outAsAnyModule); EXPORT_API(Tensor) THSNN_PairwiseDistance_forward(const NNModule module, const Tensor input1, const Tensor input2); diff --git a/src/Native/LibTorchSharp/THSNormalization.cpp b/src/Native/LibTorchSharp/THSNormalization.cpp index 6d0e6d97e..c17c4b98e 100644 --- a/src/Native/LibTorchSharp/THSNormalization.cpp +++ b/src/Native/LibTorchSharp/THSNormalization.cpp @@ -145,61 +145,6 @@ Tensor THSNN_InstanceNorm3d_forward(const NNModule module, const Tensor tensor) CATCH_TENSOR((*module)->as()->forward(*tensor)); } -NNModule THSNN_LayerNorm_ctor(const int64_t* norm_shape, const int64_t norm_shape_len, const double eps, const bool elementwise_affine, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - std::vector normalized_shape; - for (int64_t i = 0; i < norm_shape_len; ++i) - { - normalized_shape.push_back(norm_shape[i]); - } - auto opts = torch::nn::LayerNormOptions(normalized_shape).eps(eps).elementwise_affine(elementwise_affine); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LayerNorm_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_LayerNorm_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_LayerNorm_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_LayerNorm_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_LayerNorm_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - - -NNModule THSNN_LocalResponseNorm_ctor(const int64_t size, const double alpha, const double beta, const double k, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LocalResponseNormOptions(size) - .alpha(alpha) - .beta(beta) - .k(k); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LocalResponseNorm_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - void THSNN_BatchNorm1d_reset_stats(const NNModule module) { CATCH((*module)->as()->reset_running_stats();); diff --git a/src/Native/LibTorchSharp/THSTensor.h b/src/Native/LibTorchSharp/THSTensor.h index 6af55912b..f391075f4 100644 --- a/src/Native/LibTorchSharp/THSTensor.h +++ b/src/Native/LibTorchSharp/THSTensor.h @@ -23,6 +23,20 @@ EXPORT_API(Tensor) THSTensor_adaptive_avg_pool3d(const Tensor tensor, const int6 EXPORT_API(Tensor) THSTensor_adaptive_avg_pool3d_backward_out(const Tensor grad_input, const Tensor grad_output, const Tensor tensor); +EXPORT_API(Tensor) THSTensor_adaptive_max_pool1d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_adaptive_max_pool2d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_adaptive_max_pool3d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_fractional_max_pool2d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_fractional_max_pool3d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_lp_pool1d(const Tensor tensor, const double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode); + +EXPORT_API(Tensor) THSTensor_lp_pool2d(const Tensor tensor, const double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode); + EXPORT_API(Tensor) THSTensor_add(const Tensor left, const Tensor right, const Scalar alpha); EXPORT_API(void) THSTensor_add_(const Tensor left, const Tensor right, const Scalar alpha); @@ -139,7 +153,8 @@ EXPORT_API(Tensor) THSTensor_avg_pool2d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad); + bool count_include_pad, + const int64_t divisor_override); EXPORT_API(Tensor) THSTensor_avg_pool2d_backward( const Tensor grad_output, @@ -157,7 +172,8 @@ EXPORT_API(Tensor) THSTensor_avg_pool3d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad); + bool count_include_pad, + const int64_t divisor_override); EXPORT_API(Tensor) THSTensor_avg_pool3d_backward( const Tensor grad_output, @@ -792,68 +808,53 @@ EXPORT_API(void) THSTensor_max_along_dimension(const Tensor tensor, Tensor* (*al EXPORT_API(Tensor) THSTensor_max_elementwise(const Tensor tensor, const Tensor other); -EXPORT_API(Tensor) THSTensor_max_pool1d( +EXPORT_API(Tensor) THSTensor_max_pool1d_with_indices( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode); + bool ceil_mode, Tensor *indices); -EXPORT_API(Tensor) THSTensor_max_pool2d( +EXPORT_API(Tensor) THSTensor_max_pool2d_with_indices( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode); + bool ceil_mode, Tensor* indices); -EXPORT_API(Tensor) THSTensor_max_pool3d( +EXPORT_API(Tensor) THSTensor_max_pool3d_with_indices( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode); + bool ceil_mode, Tensor* indices); -EXPORT_API(void) THSTensor_max_pool1d_with_indices( +EXPORT_API(Tensor) THSTensor_max_unpool1d( const Tensor tensor, - Tensor* (*allocator)(size_t length), - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode); - -EXPORT_API(void) THSTensor_max_pool2d_with_indices( - const Tensor tensor, - Tensor* (*allocator)(size_t length), + const Tensor indices, const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, + const int64_t* outputSize, const int outputSizeLength, const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode); + const int64_t* stride, const int strideLength); -EXPORT_API(void) THSTensor_max_pool3d_with_indices( +EXPORT_API(Tensor) THSTensor_max_unpool2d( const Tensor tensor, - Tensor* (*allocator)(size_t length), + const Tensor indices, const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, + const int64_t* outputSize, const int outputSizeLength, const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode); - -EXPORT_API(Tensor) THSTensor_maxunpool2d( - const Tensor tensor, - const Tensor indices, - const int64_t* outputSize, const int outputSizeLength); + const int64_t* stride, const int strideLength); -EXPORT_API(Tensor) THSTensor_maxunpool3d( +EXPORT_API(Tensor) THSTensor_max_unpool3d( const Tensor tensor, const Tensor indices, + const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength); + const int64_t* padding, const int paddingLength, + const int64_t* stride, const int strideLength); EXPORT_API(Tensor) THSTensor_mean(const Tensor tensor); diff --git a/src/Native/LibTorchSharp/THSTensorConv.cpp b/src/Native/LibTorchSharp/THSTensorConv.cpp index 10daa3e72..2783371e5 100644 --- a/src/Native/LibTorchSharp/THSTensorConv.cpp +++ b/src/Native/LibTorchSharp/THSTensorConv.cpp @@ -44,6 +44,110 @@ Tensor THSTensor_adaptive_avg_pool3d_backward_out( *tensor)); } +Tensor THSTensor_adaptive_max_pool1d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor *indices) +{ + Tensor output = nullptr; + *indices = nullptr; + CATCH( + auto result = torch::adaptive_max_pool1d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_adaptive_max_pool2d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices) +{ + Tensor output = nullptr; + *indices = nullptr; + CATCH( + auto result = torch::adaptive_max_pool2d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_adaptive_max_pool3d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices) +{ + Tensor output = nullptr; + *indices = nullptr; + CATCH( + auto result = torch::adaptive_max_pool3d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_fractional_max_pool2d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices) +{ + Tensor output = nullptr; + *indices = nullptr; + auto opts = torch::nn::functional::FractionalMaxPool2dFuncOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); + if (outputRatioLength > 0) + opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); + + CATCH( + auto result = torch::nn::functional::fractional_max_pool2d_with_indices(*tensor, opts); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_fractional_max_pool3d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices) +{ + Tensor output = nullptr; + *indices = nullptr; + auto opts = torch::nn::functional::FractionalMaxPool3dFuncOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); + if (outputRatioLength > 0) + opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); + + CATCH( + auto result = torch::nn::functional::fractional_max_pool3d_with_indices(*tensor, opts); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_lp_pool1d( + const Tensor tensor, + const double norm_type, + const int64_t* kernelSize, + const int kernelSizeLength, + const int64_t* stride, + const int strideLength, + const bool ceil_mode) +{ + auto opts = torch::nn::functional::LPPool1dFuncOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); + if (strideLength > 0) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + opts.ceil_mode(); + CATCH_TENSOR(torch::nn::functional::lp_pool1d(*tensor, opts)); +} + +Tensor THSTensor_lp_pool2d( + const Tensor tensor, + const double norm_type, + const int64_t* kernelSize, + const int kernelSizeLength, + const int64_t* stride, + const int strideLength, + const bool ceil_mode) +{ + auto opts = torch::nn::functional::LPPool2dFuncOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); + if (strideLength > 0) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + opts.ceil_mode(); + CATCH_TENSOR(torch::nn::functional::lp_pool2d(*tensor, opts)); +} + Tensor THSTensor_avg_pool1d( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, @@ -67,7 +171,8 @@ Tensor THSTensor_avg_pool2d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad) + bool count_include_pad, + const int64_t divisor_override) { CATCH_TENSOR(torch::avg_pool2d( *tensor, @@ -75,7 +180,8 @@ Tensor THSTensor_avg_pool2d( at::ArrayRef(stride, strideLength), at::ArrayRef(padding, paddingLength), ceil_mode, - count_include_pad)); + count_include_pad, + (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); } Tensor THSTensor_avg_pool2d_backward( @@ -96,7 +202,7 @@ Tensor THSTensor_avg_pool2d_backward( at::ArrayRef(padding, paddingLength), ceil_mode, count_include_pad, - (divisor_override == 0 ? c10::optional() : c10::optional(divisor_override)))); + (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); } Tensor THSTensor_avg_pool3d( @@ -105,7 +211,8 @@ Tensor THSTensor_avg_pool3d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad) + bool count_include_pad, + const int64_t divisor_override) { CATCH_TENSOR(torch::avg_pool3d( *tensor, @@ -113,7 +220,8 @@ Tensor THSTensor_avg_pool3d( at::ArrayRef(stride, strideLength), at::ArrayRef(padding, paddingLength), ceil_mode, - count_include_pad)); + count_include_pad, + (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); } Tensor THSTensor_avg_pool3d_backward( @@ -232,33 +340,16 @@ Tensor THSTensor_conv3d( groups)); } - -Tensor THSTensor_max_pool1d( - const Tensor tensor, - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode) -{ - CATCH_TENSOR(torch::max_pool1d( - *tensor, - at::ArrayRef(kernelSize, kernelSizeLength), - at::ArrayRef(stride, strideLength), - at::ArrayRef(padding, paddingLength), - at::ArrayRef(dilation, dilationLength), - ceil_mode)); -} - -void THSTensor_max_pool1d_with_indices( +Tensor THSTensor_max_pool1d_with_indices( const Tensor tensor, - Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode) + bool ceil_mode, Tensor *indices) { + Tensor output = nullptr; + *indices = nullptr; CATCH( auto res = torch::max_pool1d_with_indices( *tensor, @@ -268,38 +359,22 @@ void THSTensor_max_pool1d_with_indices( at::ArrayRef(dilation, dilationLength), ceil_mode); - Tensor * result = allocator(2); - result[0] = new torch::Tensor(std::get<0>(res)); - result[1] = new torch::Tensor(std::get<1>(res)); + output = new torch::Tensor(std::get<0>(res)); + *indices = new torch::Tensor(std::get<1>(res)); ) + return output; } -Tensor THSTensor_max_pool2d( +Tensor THSTensor_max_pool2d_with_indices( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode) -{ - CATCH_TENSOR(torch::max_pool2d( - *tensor, - at::ArrayRef(kernelSize, kernelSizeLength), - at::ArrayRef(stride, strideLength), - at::ArrayRef(padding, paddingLength), - at::ArrayRef(dilation, dilationLength), - ceil_mode)); -} - -void THSTensor_max_pool2d_with_indices( - const Tensor tensor, - Tensor* (*allocator)(size_t length), - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode) + bool ceil_mode, Tensor* indices) { + Tensor output = nullptr; + *indices = nullptr; CATCH( auto res = torch::max_pool2d_with_indices( *tensor, @@ -308,38 +383,22 @@ void THSTensor_max_pool2d_with_indices( at::ArrayRef(padding, paddingLength), at::ArrayRef(dilation, dilationLength), ceil_mode); - Tensor * result = allocator(2); - result[0] = new torch::Tensor(std::get<0>(res)); - result[1] = new torch::Tensor(std::get<1>(res)); + output = new torch::Tensor(std::get<0>(res)); + *indices = new torch::Tensor(std::get<1>(res)); ) + return output; } -Tensor THSTensor_max_pool3d( - const Tensor tensor, - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode) -{ - CATCH_TENSOR(torch::max_pool3d( - *tensor, - at::ArrayRef(kernelSize, kernelSizeLength), - at::ArrayRef(stride, strideLength), - at::ArrayRef(padding, paddingLength), - at::ArrayRef(dilation, dilationLength), - ceil_mode)); -} - -void THSTensor_max_pool3d_with_indices( +Tensor THSTensor_max_pool3d_with_indices( const Tensor tensor, - Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode) + bool ceil_mode, Tensor* indices) { + Tensor output = nullptr; + *indices = nullptr; CATCH( auto res = torch::max_pool3d_with_indices( *tensor, @@ -348,36 +407,70 @@ void THSTensor_max_pool3d_with_indices( at::ArrayRef(padding, paddingLength), at::ArrayRef(dilation, dilationLength), ceil_mode); - Tensor * result = allocator(2); - result[0] = new torch::Tensor(std::get<0>(res)); - result[1] = new torch::Tensor(std::get<1>(res)); + output = new torch::Tensor(std::get<0>(res)); + *indices = new torch::Tensor(std::get<1>(res)); ) + return output; } -Tensor THSTensor_maxunpool2d( +Tensor THSTensor_max_unpool1d( const Tensor tensor, const Tensor indices, - const int64_t* outputSize, const int outputSizeLength) + const int64_t* kernelSize, const int kernelSizeLength, + const int64_t* outputSize, const int outputSizeLength, + const int64_t* padding, const int paddingLength, + const int64_t* stride, const int strideLength) { - CATCH_TENSOR(torch::max_unpool2d( - *tensor, - *indices, - at::ArrayRef(outputSize, outputSizeLength))); + + auto opts = torch::nn::functional::MaxUnpool1dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); + if (paddingLength > 0) + opts = opts.padding(at::IntArrayRef(padding, paddingLength)); + if (paddingLength > 0) + opts = opts.stride(at::IntArrayRef(stride, strideLength)); + + CATCH_TENSOR(torch::nn::functional::max_unpool1d(*tensor, *indices, opts)); } -Tensor THSTensor_maxunpool3d( + +Tensor THSTensor_max_unpool2d( const Tensor tensor, const Tensor indices, + const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength) + const int64_t* padding, const int paddingLength, + const int64_t* stride, const int strideLength) { - CATCH_TENSOR(torch::max_unpool3d( - *tensor, - *indices, - at::ArrayRef(outputSize, outputSizeLength), - at::ArrayRef(stride, strideLength), - at::ArrayRef(padding, paddingLength))); + + auto opts = torch::nn::functional::MaxUnpool2dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); + if (paddingLength > 0) + opts = opts.padding(at::IntArrayRef(padding, paddingLength)); + if (paddingLength > 0) + opts = opts.stride(at::IntArrayRef(stride, strideLength)); + + CATCH_TENSOR(torch::nn::functional::max_unpool2d(*tensor, *indices, opts)); +} + +Tensor THSTensor_max_unpool3d( + const Tensor tensor, + const Tensor indices, + const int64_t* kernelSize, const int kernelSizeLength, + const int64_t* outputSize, const int outputSizeLength, + const int64_t* padding, const int paddingLength, + const int64_t* stride, const int strideLength) +{ + auto opts = torch::nn::functional::MaxUnpool3dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); + if (paddingLength > 0) + opts = opts.padding(at::IntArrayRef(padding, paddingLength)); + if (paddingLength > 0) + opts = opts.stride(at::IntArrayRef(stride, strideLength)); + + CATCH_TENSOR(torch::nn::functional::max_unpool3d(*tensor, *indices, opts)); } diff --git a/src/TorchSharp/NN/Bilinear.cs b/src/TorchSharp/NN/Bilinear.cs index 5d37010e1..8d281fc8c 100644 --- a/src/TorchSharp/NN/Bilinear.cs +++ b/src/TorchSharp/NN/Bilinear.cs @@ -14,8 +14,15 @@ namespace Modules { public sealed class Bilinear : Module { + const string WeightComponentName = nameof(weight); + const string BiasComponentName = nameof(bias); + internal Bilinear(long in1_features, long in2_features, long out_features, bool hasBias = true, Device? device = null, ScalarType? dtype = null) : base(nameof(Bilinear)) { + this.in1_features = in1_features; + this.in2_features = in2_features; + this.out_features = out_features; + weight = torch.empty(out_features, in1_features, in2_features, device: device, dtype: dtype).AsParameter(); var bound = 1 / Math.Sqrt(weight!.shape[1]); @@ -23,7 +30,6 @@ internal Bilinear(long in1_features, long in2_features, long out_features, bool if (hasBias) { bias = torch.empty(out_features, device: device, dtype: dtype).AsParameter(); - var (fanIn, _) = init.CalculateFanInAndFanOut(weight); init.uniform_(_bias, -bound, bound); } //NOTE: it's important not to call 'RegisterComponents' here. @@ -47,7 +53,7 @@ public Parameter? bias { set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(nameof(bias), _bias); + ConditionallyRegisterParameter(BiasComponentName, _bias); } } @@ -58,15 +64,19 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(nameof(weight), _weight); + ConditionallyRegisterParameter(WeightComponentName, _weight); } } } - [ComponentName(Name = "bias")] + [ComponentName(Name = BiasComponentName)] private Parameter? _bias; - [ComponentName(Name = "weight")] + [ComponentName(Name = WeightComponentName)] private Parameter? _weight; + + public long in1_features { get; set; } + public long in2_features { get; set; } + public long out_features { get; set; } } } diff --git a/src/TorchSharp/NN/CosineSimilarity.cs b/src/TorchSharp/NN/CosineSimilarity.cs index 44399a1f2..eab4e964e 100644 --- a/src/TorchSharp/NN/CosineSimilarity.cs +++ b/src/TorchSharp/NN/CosineSimilarity.cs @@ -14,16 +14,19 @@ namespace Modules /// public sealed class CosineSimilarity : ParamLessModule { - internal CosineSimilarity(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal CosineSimilarity(long dim = 1, double eps = 1e-8) : base(nameof(CosineSimilarity)) { + this.dim = dim; + this.eps = eps; } public override Tensor forward(Tensor input1, Tensor input2) { - var res = THSNN_CosineSimilarity_forward(handle, input1.Handle, input2.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.cosine_similarity(input1, input2, this.dim, this.eps); } + + public long dim { get; set; } + public double eps { get; set; } } } @@ -39,9 +42,7 @@ public static partial class nn /// public static CosineSimilarity CosineSimilarity(long dim = 1, double eps = 1e-8) { - var handle = THSNN_CosineSimilarity_ctor(dim, eps, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new CosineSimilarity(handle, boxedHandle); + return new CosineSimilarity(dim, eps); } public static partial class functional @@ -56,9 +57,9 @@ public static partial class functional /// public static Tensor cosine_similarity(Tensor x1, Tensor x2, long dim = 1, double eps = 1e-8) { - using (var f = nn.CosineSimilarity(dim, eps)) { - return f.call(x1, x2); - } + var res = THSNN_cosine_similarity(x1.Handle, x2.Handle, dim, eps); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } } } diff --git a/src/TorchSharp/NN/Dropout.cs b/src/TorchSharp/NN/Dropout.cs index 675286a5f..b8e351a80 100644 --- a/src/TorchSharp/NN/Dropout.cs +++ b/src/TorchSharp/NN/Dropout.cs @@ -30,12 +30,6 @@ public override Tensor forward(Tensor tensor) return torch.nn.functional.dropout(tensor, this.p, this.training, this.inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - public bool inplace { get; set; } public double p { get; set;} } diff --git a/src/TorchSharp/NN/Dropout2d.cs b/src/TorchSharp/NN/Dropout2d.cs index 0f3989ba2..9005c745a 100644 --- a/src/TorchSharp/NN/Dropout2d.cs +++ b/src/TorchSharp/NN/Dropout2d.cs @@ -22,9 +22,7 @@ internal Dropout2d(double p = 0.5, bool inplace = false) : base(nameof(Dropout2d public override Tensor forward(Tensor input) { - var res = THSNN_dropout2d(input.Handle, p, this.training, inplace); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.dropout2d(input, this.p, this.training, this.inplace); } public bool inplace { get; set; } diff --git a/src/TorchSharp/NN/Dropout3d.cs b/src/TorchSharp/NN/Dropout3d.cs index 2d4fe88e8..4f447a149 100644 --- a/src/TorchSharp/NN/Dropout3d.cs +++ b/src/TorchSharp/NN/Dropout3d.cs @@ -22,9 +22,7 @@ internal Dropout3d(double p = 0.5, bool inplace = false) : base(nameof(Dropout3d public override Tensor forward(Tensor input) { - var res = THSNN_dropout3d(input.Handle, p, this.training, inplace); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.dropout3d(input, this.p, this.training, this.inplace); } public bool inplace { get; set; } diff --git a/src/TorchSharp/NN/FeatureDropout.cs b/src/TorchSharp/NN/FeatureDropout.cs index 2ea7b45c6..16712c2ab 100644 --- a/src/TorchSharp/NN/FeatureDropout.cs +++ b/src/TorchSharp/NN/FeatureDropout.cs @@ -14,16 +14,19 @@ namespace Modules ///
public sealed class FeatureAlphaDropout : ParamLessModule { - internal FeatureAlphaDropout(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal FeatureAlphaDropout(double p = 0.5, bool inplace = false) : base(nameof(FeatureAlphaDropout)) { + this.p = p; + this.inplace = inplace; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_FeatureAlphaDropout_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.feature_alpha_dropout(input, this.p, this.training, this.inplace); } + + public bool inplace { get; set; } + public double p { get; set; } } } @@ -38,11 +41,10 @@ public static partial class nn /// randomized on every forward call, and scaled and shifted to maintain zero mean and unit variance. ///
/// Dropout probability of a channel to be zeroed. Default: 0.5 - public static FeatureAlphaDropout FeatureAlphaDropout(double p = 0.5) + /// If set to true, will do this operation in-place. Default: false + public static FeatureAlphaDropout FeatureAlphaDropout(double p = 0.5, bool inplace = false) { - var handle = THSNN_FeatureAlphaDropout_ctor(p, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new FeatureAlphaDropout(handle, boxedHandle); + return new FeatureAlphaDropout(p, inplace); } public static partial class functional diff --git a/src/TorchSharp/NN/Flatten.cs b/src/TorchSharp/NN/Flatten.cs index 80093d294..1301870b1 100644 --- a/src/TorchSharp/NN/Flatten.cs +++ b/src/TorchSharp/NN/Flatten.cs @@ -20,19 +20,13 @@ internal Flatten(long start_dim = 1, long end_dim = -1) : base(nameof(Flatten)) this.end_dim = end_dim; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - return tensor.flatten(start_dim, end_dim); + return input.flatten(start_dim, end_dim); } - public long start_dim {get; set;} + public long start_dim { get; set; } public long end_dim { get; set; } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Identity.cs b/src/TorchSharp/NN/Identity.cs index 97bd68098..fd0c26760 100644 --- a/src/TorchSharp/NN/Identity.cs +++ b/src/TorchSharp/NN/Identity.cs @@ -18,12 +18,6 @@ public override Tensor forward(Tensor tensor) { return tensor.alias(); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Linear.cs b/src/TorchSharp/NN/Linear.cs index c2776fd5b..e893ff115 100644 --- a/src/TorchSharp/NN/Linear.cs +++ b/src/TorchSharp/NN/Linear.cs @@ -14,8 +14,14 @@ namespace Modules { public sealed class Linear : torch.nn.Module { + const string WeightComponentName = nameof(weight); + const string BiasComponentName = nameof(bias); + internal Linear(long inputSize, long outputSize, bool hasBias = true, Device? device = null, ScalarType? dtype = null) : base(nameof(Linear)) { + this.in_features = inputSize; + this.out_features = outputSize; + weight = torch.empty(outputSize, inputSize, device: device, dtype: dtype).AsParameter(); init.kaiming_uniform_(weight, a: _sqrt5); @@ -46,7 +52,7 @@ public Parameter? bias { set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(nameof(bias), _bias); + ConditionallyRegisterParameter(BiasComponentName, _bias); } } @@ -57,36 +63,19 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(nameof(weight), _weight); + ConditionallyRegisterParameter(WeightComponentName, _weight); } } } - protected internal override nn.Module _to(Device device, ScalarType dtype) - { - weight = new Parameter(_weight!.to(dtype, device)); - if (bias is not null) bias = new Parameter(_bias!.to(dtype, device)); - return this; - } - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) - { - weight = new Parameter(_weight!.to(deviceType, deviceIndex)); - if (bias is not null) bias = new Parameter(_bias!.to(deviceType, deviceIndex)); - return this; - } - - protected internal override nn.Module _to(ScalarType dtype) - { - weight = new Parameter(_weight!.to(dtype)); - if (bias is not null) bias = new Parameter(_bias!.to(dtype)); - return this; - } - - [ComponentName(Name = "bias")] + [ComponentName(Name = BiasComponentName)] private Parameter? _bias; - [ComponentName(Name = "weight")] + [ComponentName(Name = WeightComponentName)] private Parameter? _weight; + + public int in_features { get; set; } + public int out_features { get; set; } + private static readonly double _sqrt5 = Math.Sqrt(5); } } diff --git a/src/TorchSharp/NN/Normalization/Functional.cs b/src/TorchSharp/NN/Normalization/Functional.cs index 2f8bcd1e4..2c0848279 100644 --- a/src/TorchSharp/NN/Normalization/Functional.cs +++ b/src/TorchSharp/NN/Normalization/Functional.cs @@ -84,16 +84,6 @@ public static Tensor layer_norm(Tensor input, long[] normalized_shape, Tensor we return new Tensor(res); } - /// - /// Applies Local Normalization. - /// - public static Tensor local_response_norm(Tensor input, long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) - { - var res = THSNN_local_response_norm(input.Handle, size, alpha, beta, k); - if (res == IntPtr.Zero) - torch.CheckForErrors(); - return new Tensor(res); - } } } } diff --git a/src/TorchSharp/NN/Normalization/LayerNorm.cs b/src/TorchSharp/NN/Normalization/LayerNorm.cs index 949cfe4d0..7ae96ee71 100644 --- a/src/TorchSharp/NN/Normalization/LayerNorm.cs +++ b/src/TorchSharp/NN/Normalization/LayerNorm.cs @@ -18,10 +18,8 @@ namespace Modules ///
public sealed class LayerNorm : torch.nn.Module { - public long[] normalized_shape { get; set; } - public double eps { get; set; } - - public bool elementwise_affine { get; set; } + const string WeightComponentName = nameof(weight); + const string BiasComponentName = nameof(bias); internal LayerNorm(long[] normalized_shape, double eps, bool elementwise_affine, bool bias, Device? device, ScalarType? dtype) : base(nameof(LayerNorm)) { @@ -38,11 +36,10 @@ internal LayerNorm(long[] normalized_shape, double eps, bool elementwise_affine, } } - - reset_parameters(elementwise_affine); + reset_parameters(); } - private void reset_parameters(bool elementwise_affine) + public void reset_parameters() { if (elementwise_affine) { @@ -59,12 +56,19 @@ public override Tensor forward(Tensor tensor) return F.layer_norm(tensor, normalized_shape, weight, bias, eps); } + protected override void Dispose(bool disposing) + { + _weight?.Dispose(); + _bias?.Dispose(); + base.Dispose(disposing); + } + public Parameter? bias { get => _bias; set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(nameof(bias), _bias); + ConditionallyRegisterParameter(BiasComponentName, _bias); } } @@ -75,22 +79,20 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(nameof(weight), _weight); + ConditionallyRegisterParameter(WeightComponentName, _weight); } } } - [ComponentName(Name = "bias")] + [ComponentName(Name = BiasComponentName)] private Parameter? _bias; - [ComponentName(Name = "weight")] + [ComponentName(Name = WeightComponentName)] private Parameter? _weight; - protected override void Dispose(bool disposing) - { - _weight?.Dispose(); - _bias?.Dispose(); - base.Dispose(disposing); - } + + public long[] normalized_shape { get; set; } + public double eps { get; set; } + public bool elementwise_affine { get; set; } } } diff --git a/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs b/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs index ba74b2e5e..6adad3d0c 100644 --- a/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs +++ b/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs @@ -14,17 +14,23 @@ namespace Modules ///
public sealed class LocalResponseNorm : ParamLessModule { - internal LocalResponseNorm(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal LocalResponseNorm(long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) : base(nameof(LocalResponseNorm)) { + this.size = size; + this.alpha = alpha; + this.beta = beta; + this.k = k; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - if (tensor.Dimensions < 3) throw new ArgumentException($"Invalid number of dimensions for LocalResponseNorm argument: {tensor.Dimensions}"); - var res = THSNN_LocalResponseNorm_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.local_response_norm(input, this.size, this.alpha, this.beta, this.k); } + + public long size { get; set; } + public double alpha { get; set; } + public double beta { get; set; } + public double k { get; set; } } } @@ -37,10 +43,24 @@ public static partial class nn ///
public static LocalResponseNorm LocalResponseNorm(long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) { - unsafe { - var handle = THSNN_LocalResponseNorm_ctor(size, alpha, beta, k, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new LocalResponseNorm(handle, boxedHandle); + return new LocalResponseNorm(size, alpha, beta, k); + } + + public static partial class functional + { + + /// + /// Applies local response normalization over an input signal. + /// The input signal is composed of several input planes, where channels occupy the second dimension. + /// Applies normalization across channels. + /// + public static Tensor local_response_norm(Tensor input, long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) + { + if (input.Dimensions < 3) throw new ArgumentException($"Invalid number of dimensions for LocalResponseNorm argument: {input.Dimensions}"); + var res = THSNN_local_response_norm(input.Handle, size, alpha, beta, k); + if (res == IntPtr.Zero) + torch.CheckForErrors(); + return new Tensor(res); } } } diff --git a/src/TorchSharp/NN/Padding/PadBase.cs b/src/TorchSharp/NN/Padding/PadBase.cs index 6ae9bd87e..3a10de24c 100644 --- a/src/TorchSharp/NN/Padding/PadBase.cs +++ b/src/TorchSharp/NN/Padding/PadBase.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent the base of all padding-related modules. /// - public class PadBase : ParamLessModule + public abstract class PadBase : ParamLessModule { protected PadBase(string name, PaddingModes mode, double value, params long[] padding) : base(name) { diff --git a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs index 1aa15f2e8..f2a505528 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs @@ -14,7 +14,7 @@ namespace Modules ///
public sealed class ReflectionPad2d : PadBase { - internal ReflectionPad2d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } + internal ReflectionPad2d(params long[] padding) : base(nameof(ReflectionPad2d), PaddingModes.Reflect, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs index cf26874ff..d1dbd584b 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs @@ -14,7 +14,7 @@ namespace Modules ///
public sealed class ReflectionPad3d : PadBase { - internal ReflectionPad3d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } + internal ReflectionPad3d(params long[] padding) : base(nameof(ReflectionPad3d), PaddingModes.Reflect, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs index 0bd779b0e..81b25ee27 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReplicationPad2d : PadBase { - internal ReplicationPad2d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } + internal ReplicationPad2d(params long[] padding) : base(nameof(ReplicationPad2d), PaddingModes.Replicate, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs index 5a243489e..7eddd4c8c 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReplicationPad3d : PadBase { - internal ReplicationPad3d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } + internal ReplicationPad3d(params long[] padding) : base(nameof(ReplicationPad3d), PaddingModes.Replicate, 0, padding) { } } } diff --git a/src/TorchSharp/NN/PixelShuffle.cs b/src/TorchSharp/NN/PixelShuffle.cs index e7054be2b..ddb459a57 100644 --- a/src/TorchSharp/NN/PixelShuffle.cs +++ b/src/TorchSharp/NN/PixelShuffle.cs @@ -12,29 +12,24 @@ namespace Modules /// /// This class is used to represent a dropout module. /// - public sealed class PixelShuffle : torch.nn.Module + public sealed class PixelShuffle : ParamLessModule { - internal PixelShuffle(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal PixelShuffle(long upscale_factor) : base(nameof(PixelShuffle)) + { + this.upscale_factor = upscale_factor; + } /// /// Forward pass. /// - /// Input tensor + /// Input tensor /// - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_PixelShuffle_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.pixel_shuffle(input, this.upscale_factor); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + + public long upscale_factor { get; set; } } } @@ -46,13 +41,11 @@ public static partial class nn /// Rearranges elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an upscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Factor to increase spatial resolution by + /// Factor to increase spatial resolution by /// - public static PixelShuffle PixelShuffle(long upscaleFactor) + public static PixelShuffle PixelShuffle(long upscale_factor) { - var handle = THSNN_PixelShuffle_ctor(upscaleFactor, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new PixelShuffle(handle, boxedHandle); + return new PixelShuffle(upscale_factor); } public static partial class functional @@ -61,15 +54,15 @@ public static partial class functional /// Rearranges elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an upscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Input tensor - /// Factor to increase spatial resolution by + /// Input tensor + /// Factor to increase spatial resolution by /// /// - public static Tensor pixel_shuffle(Tensor x, long upscaleFactor) + public static Tensor pixel_shuffle(Tensor input, long upscale_factor) { - using (var d = nn.PixelShuffle(upscaleFactor)) { - return d.call(x); - } + var res = THSNN_pixel_shuffle(input.Handle, upscale_factor); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } } } diff --git a/src/TorchSharp/NN/PixelUnshuffle.cs b/src/TorchSharp/NN/PixelUnshuffle.cs index 5467ab59b..6b4ab8b23 100644 --- a/src/TorchSharp/NN/PixelUnshuffle.cs +++ b/src/TorchSharp/NN/PixelUnshuffle.cs @@ -12,29 +12,24 @@ namespace Modules /// /// This class is used to represent a dropout module. /// - public sealed class PixelUnshuffle : torch.nn.Module + public sealed class PixelUnshuffle : ParamLessModule { - internal PixelUnshuffle(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal PixelUnshuffle(long downscale_factor) : base(nameof(PixelUnshuffle)) + { + this.downscale_factor = downscale_factor; + } /// /// Forward pass. /// - /// Input tensor + /// Input tensor /// - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_PixelUnshuffle_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.pixel_unshuffle(input, downscale_factor); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public long downscale_factor { get; set; } } } @@ -46,13 +41,11 @@ public static partial class nn /// /// Reverses the PixelShuffle operation by rearranging elements in a tensor of shape (*, C, H * r, W * r) to a tensor of shape (*, C * r^2, H, W), where r is an downscale factor. /// - /// Factor to increase spatial resolution by + /// Factor to increase spatial resolution by /// - public static PixelUnshuffle PixelUnshuffle(long downscaleFactor) + public static PixelUnshuffle PixelUnshuffle(long downscale_factor) { - var handle = THSNN_PixelUnshuffle_ctor(downscaleFactor, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new PixelUnshuffle(handle, boxedHandle); + return new PixelUnshuffle(downscale_factor); } public static partial class functional @@ -61,15 +54,15 @@ public static partial class functional /// Reverses the PixelShuffle operation by rearranging elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an downscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Input tensor - /// Factor to increase spatial resolution by + /// Input tensor + /// Factor to increase spatial resolution by /// /// - public static Tensor pixel_unshuffle(Tensor x, long downscaleFactor) + public static Tensor pixel_unshuffle(Tensor input, long downscale_factor) { - using (var d = nn.PixelUnshuffle(downscaleFactor)) { - return d.call(x); - } + var res = THSNN_pixel_unshuffle(input.Handle, downscale_factor); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs index a658fb364..f1136eaa1 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs @@ -14,16 +14,17 @@ namespace Modules /// public sealed class AdaptiveAvgPool1d : ParamLessModule { - internal AdaptiveAvgPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveAvgPool1d(long output_size) : base(nameof(AdaptiveAvgPool1d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveAvgPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_avg_pool1d(input, this.output_size); } + + public long output_size { get; set; } } } @@ -35,14 +36,11 @@ public static partial class nn /// Applies a 1D adaptive average pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// the target output size H + /// the target output size H /// - public static unsafe AdaptiveAvgPool1d AdaptiveAvgPool1d(long outputSize) + public static unsafe AdaptiveAvgPool1d AdaptiveAvgPool1d(long output_size) { - long* pkernelSize = stackalloc long[1] { outputSize }; - var handle = THSNN_AdaptiveAvgPool1d_ctor((IntPtr)pkernelSize, 1, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool1d(handle, boxedHandle); + return new AdaptiveAvgPool1d(output_size); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs index 91c61d096..04871729f 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs @@ -14,16 +14,17 @@ namespace Modules /// public sealed class AdaptiveAvgPool2d : ParamLessModule { - internal AdaptiveAvgPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveAvgPool2d(long[] output_size) : base(nameof(AdaptiveAvgPool2d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveAvgPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_avg_pool2d(input, this.output_size); } + + public long[] output_size { get; set; } } } @@ -35,43 +36,33 @@ public static partial class nn /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long[] outputSize) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long[] output_size) { - fixed (long* poutputSize = outputSize) { - var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, outputSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool2d(handle, boxedHandle); - } + return new AdaptiveAvgPool2d(output_size); } /// /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d((long,long) outputSize) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d((long,long) output_size) { - long* poutputSize = stackalloc long[2] { outputSize.Item1, outputSize.Item2 }; - var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, 2, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool2d(handle, boxedHandle); + return new AdaptiveAvgPool2d(new[] { output_size.Item1, output_size.Item2 }); } /// /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long outputSize) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long output_size) { - long* poutputSize = stackalloc long[2] { outputSize, outputSize }; - var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, 2, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool2d(handle, boxedHandle); + return new AdaptiveAvgPool2d(new[] { output_size, output_size }); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs index f89426962..ce37c4f67 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs @@ -14,16 +14,17 @@ namespace Modules /// public sealed class AdaptiveAvgPool3d : ParamLessModule { - internal AdaptiveAvgPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveAvgPool3d(long[] output_size) : base(nameof(AdaptiveAvgPool3d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveAvgPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_avg_pool3d(input, this.output_size); } + + public long[] output_size { get; set; } } } @@ -35,44 +36,33 @@ public static partial class nn /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size of the image of the form D x H x W. + /// The target output size of the image of the form D x H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long[] outputSize) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long[] output_size) { - fixed (long* pkernelSize = outputSize) { - var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool3d(handle, boxedHandle); - } + return new AdaptiveAvgPool3d(output_size); } /// /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (D,H,W) of the image of the form D x H x W. + /// The target output size (D,H,W) of the image of the form D x H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d((long, long, long) outputSize) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d((long, long, long) output_size) { - long* pkernelSize = stackalloc long[3] { outputSize.Item1, outputSize.Item2, outputSize.Item3 }; - - var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, 3, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool3d(handle, boxedHandle); + return new AdaptiveAvgPool3d(new[] { output_size.Item1, output_size.Item2, output_size.Item3 }); } /// /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (D,H,W) of the image of the form H x W. + /// The target output size (D,H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long outputSize) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long output_size) { - long* pkernelSize = stackalloc long[3] { outputSize, outputSize, outputSize }; - var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, 3, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool3d(handle, boxedHandle); + return new AdaptiveAvgPool3d(new [] { output_size, output_size, output_size }); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs index 5c71475cc..199aefaa5 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs @@ -14,16 +14,22 @@ namespace Modules /// public sealed class AdaptiveMaxPool1d : ParamLessModule { - internal AdaptiveMaxPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveMaxPool1d(long output_size) : base(nameof(AdaptiveMaxPool1d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_AdaptiveMaxPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_max_pool1d_with_indices(input, this.output_size); } + + public override Tensor forward(Tensor input) + { + return torch.nn.functional.adaptive_max_pool1d(input, this.output_size); + } + + public long output_size { get; set; } } } @@ -35,17 +41,11 @@ public static partial class nn /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size H. + /// The target output size H. /// - public static AdaptiveMaxPool1d AdaptiveMaxPool1d(long outputSize) + public static AdaptiveMaxPool1d AdaptiveMaxPool1d(long output_size) { - unsafe { - fixed (long* pkernelSize = new long[] { outputSize }) { - var handle = THSNN_AdaptiveMaxPool1d_ctor((IntPtr)pkernelSize, 1, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveMaxPool1d(handle, boxedHandle); - } - } + return new AdaptiveMaxPool1d(output_size); } public static partial class functional @@ -54,13 +54,32 @@ public static partial class functional /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// - /// The target output size H. + /// + /// The target output size H. + /// + public static Tensor adaptive_max_pool1d(Tensor input, long output_size) + { + var ret = adaptive_max_pool1d_with_indices(input, output_size); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. + /// The output size is H, for any input size.The number of output features is equal to the number of input planes. + /// + /// + /// The target output size H. /// - public static Tensor adaptive_max_pool1d(Tensor x, long outputSize) + public static (Tensor Values, Tensor Indices) adaptive_max_pool1d_with_indices(Tensor input, long output_size) { - using (var d = nn.AdaptiveMaxPool1d(outputSize)) { - return d.call(x); + var outputSizes = new long[] { output_size }; + unsafe { + fixed (long* poutputSize = outputSizes) { + var resOutput = THSTensor_adaptive_max_pool1d(input.Handle, (IntPtr)poutputSize, outputSizes.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs index 764d29732..8cba5c401 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs @@ -14,16 +14,22 @@ namespace Modules /// public sealed class AdaptiveMaxPool2d : ParamLessModule { - internal AdaptiveMaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveMaxPool2d(long[] output_size) : base(nameof(AdaptiveMaxPool2d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveMaxPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_max_pool2d(input, this.output_size); } + + public (Tensor output, Tensor indices) forward_with_indices(Tensor input) + { + return torch.nn.functional.adaptive_max_pool2d_with_indices(input, this.output_size); + } + + public long[] output_size { get; set; } } } @@ -35,18 +41,12 @@ public static partial class nn /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - public static AdaptiveMaxPool2d AdaptiveMaxPool2d(long[] outputSize) + public static AdaptiveMaxPool2d AdaptiveMaxPool2d(long[] output_size) { - unsafe { - fixed (long* pkernelSize = outputSize) { - var handle = THSNN_AdaptiveMaxPool2d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveMaxPool2d(handle, boxedHandle); - } - } + return new AdaptiveMaxPool2d(output_size); } public static partial class functional @@ -55,14 +55,33 @@ public static partial class functional /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// - /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. + /// + public static Tensor adaptive_max_pool2d(Tensor input, long[] output_size) + { + var ret = adaptive_max_pool2d_with_indices(input, output_size); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. + /// + /// + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - public static Tensor adaptive_max_pool2d(Tensor x, long[] outputSize) + public static (Tensor Values, Tensor Indices) adaptive_max_pool2d_with_indices(Tensor input, long[] output_size) { - using (var d = nn.AdaptiveMaxPool2d(outputSize)) { - return d.call(x); + unsafe { + fixed (long* poutputSize = output_size) { + var resOutput = THSTensor_adaptive_max_pool2d(input.Handle, (IntPtr)poutputSize, output_size.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs index ec3bfc32f..e59ce6565 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs @@ -14,16 +14,22 @@ namespace Modules /// public sealed class AdaptiveMaxPool3d : ParamLessModule { - internal AdaptiveMaxPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveMaxPool3d(long[] output_size) : base(nameof(AdaptiveMaxPool3d)) { } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveMaxPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_max_pool3d(input, output_size); } + + public (Tensor output, Tensor indices) forward_with_indices(Tensor input) + { + return torch.nn.functional.adaptive_max_pool3d_with_indices(input, output_size); + } + + + public long[] output_size { get; set; } } } @@ -35,18 +41,12 @@ public static partial class nn /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size of the image of the form D x H x W. + /// The target output size of the image of the form D x H x W. /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. /// - public static AdaptiveMaxPool3d AdaptiveMaxPool3d(long[] outputSize) + public static AdaptiveMaxPool3d AdaptiveMaxPool3d(long[] output_size) { - unsafe { - fixed (long* pkernelSize = outputSize) { - var handle = THSNN_AdaptiveMaxPool3d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveMaxPool3d(handle, boxedHandle); - } - } + return new AdaptiveMaxPool3d(output_size); } public static partial class functional @@ -55,14 +55,33 @@ public static partial class functional /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The input tensor - /// The target output size of the image of the form D x H x W. + /// The input tensor + /// The target output size of the image of the form D x H x W. + /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. + /// + public static Tensor adaptive_max_pool3d(Tensor input, long[] output_size) + { + var ret = adaptive_max_pool3d_with_indices(input, output_size); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. + /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. + /// + /// The input tensor + /// The target output size of the image of the form D x H x W. /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. /// - public static Tensor adaptive_max_pool3d(Tensor x, long[] outputSize) + public static (Tensor Values, Tensor Indices) adaptive_max_pool3d_with_indices(Tensor input, long[] output_size) { - using (var d = nn.AdaptiveMaxPool3d(outputSize)) { - return d.call(x); + unsafe { + fixed (long* poutputSize = output_size) { + var resOutput = THSTensor_adaptive_max_pool1d(input.Handle, (IntPtr)poutputSize, output_size.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool1D.cs b/src/TorchSharp/NN/Pooling/AvgPool1D.cs index 9df33da82..7dcd374b0 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool1D.cs @@ -14,16 +14,25 @@ namespace Modules /// public sealed class AvgPool1d : ParamLessModule { - internal AvgPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AvgPool1d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true) : base(nameof(AvgPool1d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.ceil_mode = ceil_mode; + this.count_include_pad = count_include_pad; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AvgPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.avg_pool1d(input, kernel_size, stride, padding, ceil_mode, count_include_pad); } + + public long kernel_size { get; set; } + public long? stride { get; set; } + public long? padding { get; set; } + public bool ceil_mode { get; set; } + public bool count_include_pad { get; set; } } } @@ -39,32 +48,9 @@ public static partial class nn /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation - /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static AvgPool1d AvgPool1d(long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool1d AvgPool1d(long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, bool count_include_pad = true) { - return stride.HasValue ? - AvgPool1d(new long[] { kernel_size }, new long[] { stride.Value }, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0) : - AvgPool1d(new long[] { kernel_size }, null, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0); - } - - /// - /// Applies a 1D average pooling over an input signal composed of several input planes. - /// - /// The size of the window - /// The stride of the window. Default value is kernel_size - /// implicit zero padding to be added on both sides - /// Whether to use ceil instead of floor to compute the output shape - /// Whether to include the zero-padding in the averaging calculation - /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - private static AvgPool1d AvgPool1d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) - { - unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { - var handle = THSNN_AvgPool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)ppadding, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool1d(handle, boxedHandle); - } - } + return new AvgPool1d(kernel_size, stride, padding, ceil_mode, count_include_pad); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AvgPool2D.cs b/src/TorchSharp/NN/Pooling/AvgPool2D.cs index 77fe8d991..f44dfe42c 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool2D.cs @@ -5,6 +5,7 @@ namespace TorchSharp { + using System.Data; using Modules; namespace Modules @@ -14,16 +15,27 @@ namespace Modules /// public sealed class AvgPool2d : ParamLessModule { - internal AvgPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AvgPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) : base(nameof(AvgPool2d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.ceil_mode = ceil_mode; + this.count_include_pad = count_include_pad; + this.divisor_override = divisor_override; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AvgPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.avg_pool2d(input, kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } + public bool ceil_mode { get; set; } + public bool count_include_pad { get; set; } + public long? divisor_override { get; set; } } } @@ -35,18 +47,14 @@ public static partial class nn /// Applies a 2D average pooling over an input signal composed of several input planes. /// /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static unsafe AvgPool2d AvgPool2d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool2d AvgPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { - var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)ppadding, (padding == null ? 0 : padding.Length), ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool2d(handle, boxedHandle); - } + return new AvgPool2d(kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); } /// @@ -60,19 +68,10 @@ public static unsafe AvgPool2d AvgPool2d(long[] kernel_size, long[] strides = nu /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool2d AvgPool2d((long,long) kernel_size, (long,long)? stride = null, (long,long)? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; - long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; - - long pvalue1 = (padding == null) ? 0 : padding.Value.Item1; - long pvalue2 = (padding == null) ? 0 : padding.Value.Item2; - - long* pkernelSize = stackalloc long[2] { kernel_size.Item1, kernel_size.Item2 }; - long* pstrides = stackalloc long[2] { svalue1, svalue2 }; - long* ppadding = stackalloc long[2] { pvalue1, pvalue2 }; - - var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool2d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; + long[] strideValue = stride == null ? null : new[] { stride.Value.Item1, stride.Value.Item2 }; + long[] paddingValue = padding == null ? null : new[] { padding.Value.Item1, padding.Value.Item2 }; + return new AvgPool2d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); } /// @@ -84,18 +83,12 @@ public static unsafe AvgPool2d AvgPool2d((long,long) kernel_size, (long,long)? s /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static unsafe AvgPool2d AvgPool2d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool2d AvgPool2d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long svalue = (stride == null) ? kernel_size : stride.Value; - long pvalue = (padding == null) ? 0 : padding.Value; - - long* pkernelSize = stackalloc long[2] { kernel_size, kernel_size }; - long* pstrides = stackalloc long[2] { svalue, svalue }; - long* ppadding = stackalloc long[2] { pvalue, pvalue }; - - var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool2d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size, kernel_size }; + long[] strideValue = stride == null ? null : new[] { stride.Value, stride.Value }; + long[] paddingValue = padding == null ? null : new[] { padding.Value, padding.Value }; + return new AvgPool2d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); } public static partial class functional @@ -104,29 +97,32 @@ public static partial class functional /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// - /// - /// + /// + /// + /// /// /// + /// /// - public static Tensor avg_pool2d(Tensor input, long[] kernelSizes, - long[] strides = null, - long[] paddings = null, + public static Tensor avg_pool2d(Tensor input, long[] kernel_size, + long[] stride = null, + long[] padding = null, bool ceil_mode = false, - bool count_include_pad = true) + bool count_include_pad = true, + long? divisor_override = null) { - strides = (strides == null) ? new long[] { 1 } : strides; - paddings = (paddings == null) ? new long[] { 0 } : paddings; + stride = (stride == null) ? kernel_size : stride; + padding = (padding == null) ? new long[] { 0 } : padding; unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { + fixed (long* pkernelSize = kernel_size, pstrides = stride, ppadding = padding) { var res = THSTensor_avg_pool2d(input.Handle, - (IntPtr)pkernelSize, kernelSizes.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, paddings.Length, + (IntPtr)pkernelSize, kernel_size.Length, + (IntPtr)pstrides, stride.Length, + (IntPtr)ppadding, padding.Length, ceil_mode, - count_include_pad); + count_include_pad, + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -137,21 +133,23 @@ public static Tensor avg_pool2d(Tensor input, long[] kernelSizes, /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// + /// /// /// /// /// + /// /// - public static unsafe Tensor avg_pool2d(Tensor input, long kernelSize, + public static unsafe Tensor avg_pool2d(Tensor input, long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, - bool count_include_pad = true) + bool count_include_pad = true, + long? divisor_override = null) { - long svalue = (stride == null) ? kernelSize : stride.Value; + long svalue = (stride == null) ? kernel_size : stride.Value; - long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; + long* pkernelSize = stackalloc long[2] { kernel_size, kernel_size }; long* pstrides = stackalloc long[2] { svalue, svalue }; long* ppadding = stackalloc long[2] { padding, padding }; @@ -161,7 +159,8 @@ public static unsafe Tensor avg_pool2d(Tensor input, long kernelSize, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, - count_include_pad); + count_include_pad, + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -170,27 +169,29 @@ public static unsafe Tensor avg_pool2d(Tensor input, long kernelSize, /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// + /// /// /// /// /// + /// /// - public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernelSize, + public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null, bool ceil_mode = false, - bool count_include_pad = true) + bool count_include_pad = true, + long? divisor_override = null) { - long svalue1 = (stride == null) ? kernelSize.Item1 : stride.Value.Item1; - long svalue2 = (stride == null) ? kernelSize.Item2 : stride.Value.Item2; + long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; + long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; long pvalue1 = padding != null ? padding.Value.Item1 : 0; long pvalue2 = padding != null ? padding.Value.Item2 : 0; long* pstrides = stackalloc long[2] { svalue1, svalue2 }; long* ppadding = stackalloc long[2] { pvalue1, pvalue2 }; - long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; + long* pkernelSize = stackalloc long[2] { kernel_size.Item1, kernel_size.Item2 }; var res = THSTensor_avg_pool2d(input.Handle, @@ -198,7 +199,8 @@ public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernelSize, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, - count_include_pad); + count_include_pad, + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -209,7 +211,7 @@ public static Tensor avg_pool2d_backward(Tensor input, Tensor originalInput, long[] paddings = null, bool ceil_mode = false, bool count_include_pad = true, - long divisorOverride = 0) + long? divisor_override = null) { strides = (strides == null) ? new long[] { 1 } : strides; paddings = (paddings == null) ? new long[] { 0 } : paddings; @@ -222,7 +224,7 @@ public static Tensor avg_pool2d_backward(Tensor input, Tensor originalInput, (IntPtr)ppadding, paddings.Length, ceil_mode, count_include_pad, - divisorOverride); + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/AvgPool3D.cs b/src/TorchSharp/NN/Pooling/AvgPool3D.cs index bedc81f0a..d08304bdc 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool3D.cs @@ -14,16 +14,27 @@ namespace Modules /// public sealed class AvgPool3d : ParamLessModule { - internal AvgPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AvgPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) : base(nameof(AvgPool3d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.ceil_mode = ceil_mode; + this.count_include_pad = count_include_pad; + this.divisor_override = divisor_override; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AvgPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.avg_pool3d(input, kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } + public bool ceil_mode { get; set; } + public bool count_include_pad { get; set; } + public long? divisor_override { get; set; } } } @@ -35,20 +46,14 @@ public static partial class nn /// Applies a 3D average pooling over an input signal composed of several input planes. /// /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static AvgPool3d AvgPool3d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool3d AvgPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { - var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)ppadding, (padding == null ? 0 : padding.Length), ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool3d(handle, boxedHandle); - } - } + return new AvgPool3d(kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); } /// @@ -62,21 +67,10 @@ public static AvgPool3d AvgPool3d(long[] kernel_size, long[] strides = null, lon /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool3d AvgPool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; - long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; - long svalue3 = (stride == null) ? kernel_size.Item3 : stride.Value.Item3; - - long pvalue1 = (padding == null) ? 0 : padding.Value.Item1; - long pvalue2 = (padding == null) ? 0 : padding.Value.Item2; - long pvalue3 = (padding == null) ? 0 : padding.Value.Item3; - - long* pkernelSize = stackalloc long[3] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }; - long* pstrides = stackalloc long[3] { svalue1, svalue2, svalue3 }; - long* ppadding = stackalloc long[3] { pvalue1, pvalue2, pvalue3 }; - - var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, 3, (IntPtr)pstrides, 3, (IntPtr)ppadding, 3, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool3d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }; + long[] strideValue = stride == null ? null : new[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 }; + long[] paddingValue = padding == null ? null : new[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 }; + return new AvgPool3d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); } /// @@ -90,16 +84,10 @@ public static unsafe AvgPool3d AvgPool3d((long, long, long) kernel_size, (long, /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool3d AvgPool3d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long svalue = (stride == null) ? kernel_size : stride.Value; - long pvalue = (padding == null) ? 0 : padding.Value; - - long* pkernelSize = stackalloc long[3] { kernel_size, kernel_size, kernel_size }; - long* pstrides = stackalloc long[3] { svalue, svalue, svalue }; - long* ppadding = stackalloc long[3] { pvalue, pvalue, pvalue }; - - var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, 3, (IntPtr)pstrides, 3, (IntPtr)ppadding, 3, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool3d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size, kernel_size, kernel_size }; + long[] strideValue = stride == null ? null : new[] { stride.Value, stride.Value, stride.Value }; + long[] paddingValue = padding == null ? null : new[] { padding.Value, padding.Value, padding.Value }; + return new AvgPool3d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); } public static partial class functional @@ -108,29 +96,31 @@ public static partial class functional /// Applies 3D average-pooling operation in kT x kH x kW regions by step size sT x sH x sW steps. /// /// The input tensor. - /// - /// - /// + /// + /// + /// /// /// + /// /// - public static Tensor avg_pool3d(Tensor input, long[] kernelSizes, - long[] strides = null, - long[] paddings = null, + public static Tensor avg_pool3d(Tensor input, long[] kernel_size, + long[] stride = null, + long[] padding = null, bool ceil_mode = false, - bool count_include_pad = true) + bool count_include_pad = true, + long? divisor_override = null) { - strides = (strides == null) ? new long[] { 1 } : strides; - paddings = (paddings == null) ? new long[] { 0 } : paddings; + stride = (stride == null) ? kernel_size : stride; + padding = (padding == null) ? new long[] { 0 } : padding; unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { + fixed (long* pkernelSize = kernel_size, pstrides = stride, ppadding = padding) { var res = THSTensor_avg_pool3d(input.Handle, - (IntPtr)pkernelSize, kernelSizes.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, paddings.Length, + (IntPtr)pkernelSize, kernel_size.Length, + (IntPtr)pstrides, stride.Length, + (IntPtr)ppadding, padding.Length, ceil_mode, - count_include_pad); + count_include_pad, divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -143,9 +133,9 @@ public static Tensor avg_pool3d_backward(Tensor input, Tensor originalInput, long[] paddings = null, bool ceil_mode = false, bool count_include_pad = true, - long divisorOverride = 0) + long? divisor_override = null) { - strides = (strides == null) ? new long[] { 1 } : strides; + strides = (strides == null) ? kernelSizes : strides; paddings = (paddings == null) ? new long[] { 0 } : paddings; unsafe { fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { @@ -156,7 +146,7 @@ public static Tensor avg_pool3d_backward(Tensor input, Tensor originalInput, (IntPtr)ppadding, paddings.Length, ceil_mode, count_include_pad, - divisorOverride); + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs index eecc1c4a3..e37d17083 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs @@ -5,6 +5,7 @@ namespace TorchSharp { + using System.Data; using Modules; namespace Modules @@ -14,23 +15,26 @@ namespace Modules /// public sealed class FractionalMaxPool2d : ParamLessModule { - internal FractionalMaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal FractionalMaxPool2d(long[] kernel_size, long[] output_size = null, double[] output_ratio = null) : base(nameof(FractionalMaxPool2d)) { + this.kernel_size = kernel_size; + this.output_size = output_size; + this.output_ratio = output_ratio; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_FractionalMaxPool2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.fractional_max_pool2d(input, kernel_size, output_size, output_ratio); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_FractionalMaxPool2d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.fractional_max_pool2d_with_indices(input, kernel_size, output_size, output_ratio); } + + public long[] kernel_size { get; set; } + public long[] output_size { get; set; } + public double[] output_ratio { get; set; } } } @@ -95,16 +99,135 @@ public static FractionalMaxPool2d FractionalMaxPool2d(long[] kernel_size, long[] if (output_size != null && output_ratio != null) throw new ArgumentNullException("FractionalMaxPool2d requires specifying either an output size, or a pooling ratio."); - unsafe { - fixed (long* pkernelSize = kernel_size, pSize = output_size) { - fixed (double* pRatio = output_ratio) { - var handle = THSNN_FractionalMaxPool2d_ctor( - (IntPtr)pkernelSize, kernel_size.Length, - (IntPtr)pSize, (output_size == null ? 0 : output_size.Length), - (IntPtr)pRatio, (output_ratio == null ? 0 : output_ratio.Length), - out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new FractionalMaxPool2d(handle, boxedHandle); + return new FractionalMaxPool2d(kernel_size, output_size, output_ratio); + } + + public static partial class functional + { + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool2d(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value } : null; + return fractional_max_pool2d(input, new long[] { kernel_size, kernel_size }, pSize, pRatio); + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool2d(Tensor input, (long, long) kernel_size, (long, long)? output_size = null, (double, double)? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2 } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2 } : null; + return fractional_max_pool2d(input, new long[] { kernel_size.Item1, kernel_size.Item2 }, pSize, pRatio); + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool2d(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) + { + var ret = fractional_max_pool2d_with_indices(input, kernel_size, output_size, output_ratio); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value } : null; + return fractional_max_pool2d_with_indices(input, new long[] { kernel_size, kernel_size }, pSize, pRatio); + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, (long, long) kernel_size, (long, long)? output_size = null, (double, double)? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2 } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2 } : null; + return fractional_max_pool2d_with_indices(input, new long[] { kernel_size.Item1, kernel_size.Item2 }, pSize, pRatio); + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) + { + if (kernel_size == null || kernel_size.Length != 2) + throw new ArgumentException("Kernel size must contain two elements."); + if (output_size != null && output_size.Length != 2) + throw new ArgumentException("output_size must contain two elements."); + if (output_ratio != null && output_ratio.Length != 2) + throw new ArgumentException("output_ratio must contain two elements."); + if (output_size == null && output_ratio == null) + throw new ArgumentNullException("Only one of output_size and output_ratio may be specified."); + if (output_size != null && output_ratio != null) + throw new ArgumentNullException("FractionalMaxPool2d requires specifying either an output size, or a pooling ratio."); + + output_size ??= Array.Empty(); + output_ratio ??= Array.Empty(); + + unsafe { + fixed (long* pkernelSize = kernel_size, poutputSize = output_size) { + fixed (double* poutputRatio = output_ratio) { + var resOutput = THSTensor_fractional_max_pool2d(input.Handle, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)poutputRatio, output_ratio.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs index 692f2210f..98ac3d0eb 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs @@ -14,34 +14,26 @@ namespace Modules /// public sealed class FractionalMaxPool3d : ParamLessModule { - internal FractionalMaxPool3d(IntPtr handle, IntPtr boxedHandle, bool ratio) : base(handle, boxedHandle) + internal FractionalMaxPool3d(long[] kernel_size, long[] output_size = null, double[] output_ratio = null) : base(nameof(FractionalMaxPool3d)) { - _used_ratio = ratio; + this.kernel_size = kernel_size; + this.output_size = output_size; + this.output_ratio = output_ratio; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - if (_used_ratio && tensor.ndim != 5) - // Not sure why this is the case, but there's an exception in the native runtime - // unless there's both a batch dimension and a channel dimension. - throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); - var res = THSNN_FractionalMaxPool3d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.fractional_max_pool3d(input, kernel_size, output_size, output_ratio); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - if (_used_ratio && tensor.ndim != 5) - // Not sure why this is the case, but there's an exception in the native runtime - // unless there's both a batch dimension and a channel dimension. - throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); - var res = THSNN_FractionalMaxPool3d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.fractional_max_pool3d_with_indices(input, kernel_size, output_size, output_ratio); } - private bool _used_ratio = false; + public long[] kernel_size { get; set; } + public long[] output_size { get; set; } + public double[] output_ratio { get; set; } } } @@ -106,16 +98,139 @@ public static FractionalMaxPool3d FractionalMaxPool3d(long[] kernel_size, long[] if (output_size != null && output_ratio != null) throw new ArgumentNullException("FractionalMaxPool3d requires specifying either an output size, or a pooling ratio."); - unsafe { - fixed (long* pkernelSize = kernel_size, pSize = output_size) { - fixed (double* pRatio = output_ratio) { - var handle = THSNN_FractionalMaxPool3d_ctor( - (IntPtr)pkernelSize, kernel_size.Length, - (IntPtr)pSize, (output_size == null ? 0 : output_size.Length), - (IntPtr)pRatio, (output_ratio == null ? 0 : output_ratio.Length), - out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new FractionalMaxPool3d(handle, boxedHandle, output_ratio != null); + return new FractionalMaxPool3d(kernel_size, output_size, output_ratio); + } + + public static partial class functional + { + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool3d(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value, output_size.Value } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value, output_ratio.Value } : null; + return fractional_max_pool3d(input, new long[] { kernel_size, kernel_size, kernel_size }, pSize, pRatio); + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool3d(Tensor input, (long, long, long) kernel_size, (long, long, long)? output_size = null, (double, double, double)? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2, output_size.Value.Item3 } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2, output_ratio.Value.Item3 } : null; + return fractional_max_pool3d(input, new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pSize, pRatio); + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool3d(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) + { + var ret = fractional_max_pool3d_with_indices(input, kernel_size, output_size, output_ratio); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value, output_size.Value } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value, output_ratio.Value } : null; + return fractional_max_pool3d_with_indices(input, new long[] { kernel_size, kernel_size, kernel_size }, pSize, pRatio); + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, (long, long, long) kernel_size, (long, long, long)? output_size = null, (double, double, double)? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2, output_size.Value.Item3 } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2, output_ratio.Value.Item3 } : null; + return fractional_max_pool3d_with_indices(input, new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pSize, pRatio); + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) + { + if (kernel_size == null || kernel_size.Length != 3) + throw new ArgumentException("Kernel size must contain three elements."); + if (output_size != null && output_size.Length != 3) + throw new ArgumentException("output_size must contain three elements."); + if (output_ratio != null && output_ratio.Length != 3) + throw new ArgumentException("output_ratio must contain three elements."); + if (output_size == null && output_ratio == null) + throw new ArgumentNullException("Only one of output_size and output_ratio may be specified."); + if (output_size != null && output_ratio != null) + throw new ArgumentNullException("FractionalMaxPool3d requires specifying either an output size, or a pooling ratio."); + if (output_ratio != null && input.ndim != 5) + // Not sure why this is the case, but there's an exception in the native runtime + // unless there's both a batch dimension and a channel dimension. + throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); + + output_size ??= Array.Empty(); + output_ratio ??= Array.Empty(); + + unsafe { + fixed (long* pkernelSize = kernel_size, poutputSize = output_size) { + fixed (double* poutputRatio = output_ratio) { + var resOutput = THSTensor_fractional_max_pool3d(input.Handle, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)poutputRatio, output_ratio.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/LPPool1d.cs b/src/TorchSharp/NN/Pooling/LPPool1d.cs index 62e4a2a4e..9babde806 100644 --- a/src/TorchSharp/NN/Pooling/LPPool1d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool1d.cs @@ -14,16 +14,23 @@ namespace Modules /// public sealed class LPPool1d : ParamLessModule { - internal LPPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal LPPool1d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) : base(nameof(LPPool1d)) { + this.norm_type = norm_type; + this.kernel_size = kernel_size; + this.stride = stride; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_LPPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.lp_pool1d(input, norm_type, kernel_size, stride, ceil_mode); } + + public double norm_type { get; set; } + public long kernel_size { get; set; } + public long? stride { get; set; } + public bool ceil_mode { get; set; } } } @@ -35,32 +42,37 @@ public static partial class nn /// Applies a 1D power-average pooling over an input signal composed of several input planes. /// /// The LP norm (exponent) - /// The size of the window + /// The size of the window /// The stride of the window. Default value is kernel_size /// Use ceil instead of floor to compute the output shape /// - public static LPPool1d LPPool1d(double norm_type, long kernelSize, long? stride = null, bool ceil_mode = false) + public static LPPool1d LPPool1d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) { - return stride.HasValue ? - LPPool1d(norm_type, new long[] { kernelSize }, new long[] { stride.Value }, ceil_mode) : - LPPool1d(norm_type, new long[] { kernelSize }, null); + return new LPPool1d(norm_type, kernel_size, stride, ceil_mode); } - /// - /// Applies a 1D power-average pooling over an input signal composed of several input planes. - /// - /// The LP norm (exponent) - /// The size of the window - /// The stride of the window. Default value is kernel_size - /// Use ceil instead of floor to compute the output shape - /// - private static LPPool1d LPPool1d(double norm_type, long[] kernelSize, long[] strides = null, bool ceil_mode = false) + public static partial class functional { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides) { - var handle = THSNN_LPPool1d_ctor(norm_type, (IntPtr)pkernelSize, (IntPtr)pstrides, ceil_mode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new LPPool1d(handle, boxedHandle); + /// + /// Applies a 1D power-average pooling over an input signal composed of several input planes. + /// + /// The input tensor + /// The LP norm (exponent) + /// The size of the window + /// The stride of the window. Default value is kernel_size + /// Use ceil instead of floor to compute the output shape + /// + public static Tensor lp_pool1d(Tensor input, double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) + { + var kernels = new[] { kernel_size }; + var strides = stride.HasValue ? new[] { stride.Value } : Array.Empty(); + + unsafe { + fixed (long* pkernelSize = kernels, pstrides = strides) { + var res = THSTensor_lp_pool1d(input.Handle, norm_type, (IntPtr)pkernelSize, kernels.Length, (IntPtr)pstrides, strides.Length, ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } } } } diff --git a/src/TorchSharp/NN/Pooling/LPPool2d.cs b/src/TorchSharp/NN/Pooling/LPPool2d.cs index 8555803de..4fe66dafd 100644 --- a/src/TorchSharp/NN/Pooling/LPPool2d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool2d.cs @@ -14,16 +14,23 @@ namespace Modules /// public sealed class LPPool2d : ParamLessModule { - internal LPPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal LPPool2d(double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) : base(nameof(LPPool2d)) { + this.norm_type = norm_type; + this.kernel_size = kernel_size; + this.stride = stride; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_LPPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.lp_pool2d(input, norm_type, kernel_size, stride, ceil_mode); } + + public double norm_type { get; set; } + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public bool ceil_mode { get; set; } } } @@ -36,18 +43,12 @@ public static partial class nn /// /// The LP norm (exponent) /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// Use ceil instead of floor to compute the output shape /// - public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] strides = null, bool ceil_mode = false) + public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) { - unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = strides) { - var handle = THSNN_LPPool2d_ctor(norm_type, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), ceil_mode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new LPPool2d(handle, boxedHandle); - } - } + return new LPPool2d(norm_type, kernel_size, stride, ceil_mode); } /// @@ -60,9 +61,46 @@ public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] str /// public static LPPool2d LPPool2d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) { - return stride.HasValue ? - LPPool2d(norm_type, new long[] { kernel_size, kernel_size }, new long[] { stride.Value, stride.Value }, ceil_mode) : - LPPool2d(norm_type, new long[] { kernel_size, kernel_size }, null, ceil_mode); + return new LPPool2d(norm_type, new[] { kernel_size, kernel_size }, stride.HasValue ? new[] { stride.Value, stride.Value } : null, ceil_mode); + } + + public static partial class functional + { + /// + /// Applies a 2D power-average pooling over an input signal composed of several input planes. + /// + /// The input tensor + /// The LP norm (exponent) + /// The size of the window + /// The stride of the window. Default value is kernel_size + /// Use ceil instead of floor to compute the output shape + /// + public static Tensor lp_pool2d(Tensor input, double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) + { + stride ??= Array.Empty(); + + unsafe { + fixed (long* pkernelSize = kernel_size, pstrides = stride) { + var res = THSTensor_lp_pool2d(input.Handle, norm_type, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, stride.Length, ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + } + } + + /// + /// Applies a 2D power-average pooling over an input signal composed of several input planes. + /// + /// The input tensor + /// The LP norm (exponent) + /// The size of the window + /// The stride of the window. + /// Use ceil instead of floor to compute the output shape + /// + public static Tensor lp_pool2d(Tensor input, double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) + { + return lp_pool2d(input, norm_type, new[] { kernel_size, kernel_size }, stride.HasValue ? new[] { stride.Value, stride.Value } : null, ceil_mode); + } } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool1D.cs b/src/TorchSharp/NN/Pooling/MaxPool1D.cs index 46254dcd7..558664c74 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool1D.cs @@ -15,23 +15,30 @@ namespace Modules /// public sealed class MaxPool1d : ParamLessModule { - internal MaxPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxPool1d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) : base(nameof(MaxPool1d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.dilation = dilation; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_MaxPool1d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.max_pool1d(input, kernel_size, stride, padding, dilation, ceil_mode); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_MaxPool1d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.max_pool1d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); } + + public long kernel_size { get; set; } + public long? stride { get; set; } + public long? padding { get; set; } + public long? dilation { get; set; } + public bool ceil_mode { get; set; } } } @@ -42,100 +49,56 @@ public static partial class nn /// /// Applies a 1D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool1d MaxPool1d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) + public static MaxPool1d MaxPool1d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - var pStride = stride.HasValue ? new long[] { stride.Value } : null; - var pPadding = padding.HasValue ? new long[] { padding.Value } : null; - var pDilation = dilation.HasValue ? new long[] { dilation.Value } : null; - return MaxPool1d(new long[] { kernelSize }, pStride, pPadding, pDilation, ceilMode); - } - - private static MaxPool1d MaxPool1d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) - { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { - var handle = THSNN_MaxPool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)pPadding, (IntPtr)pDilation, ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool1d(handle, boxedHandle); - } - } + return new MaxPool1d(kernel_size, stride, padding, dilation, ceil_mode); } public static partial class functional { - /// - /// Applies a 1D max pooling over an input signal composed of several input planes. - /// - /// The input tensor. - /// - /// - /// - /// - /// - /// - public static Tensor max_pool1d(Tensor input, long kernelSize, long? stride = null, + public static Tensor max_pool1d(Tensor input, long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - var kernelSizes = new long[] { kernelSize }; - var strides = new long[] { stride ?? kernelSize }; - var paddings = new long[] { padding ?? 0 }; - var dilations = new long[] { dilation ?? 1 }; - unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { - var res = - THSTensor_max_pool1d(input.Handle, - (IntPtr)pkernelSize, kernelSizes.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, paddings.Length, - (IntPtr)pdilation, dilations.Length, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + var ret = max_pool1d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// /// Applies a 1D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static (Tensor output, Tensor indices) max_pool1d_with_indices(Tensor input, long kernelSize, long? stride = null, + public static (Tensor Values, Tensor Indices) max_pool1d_with_indices(Tensor input, long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - var kernelSizes = new long[] { kernelSize }; - var strides = new long[] { stride ?? kernelSize }; + var kernelSizes = new long[] { kernel_size }; + var strides = new long[] { stride ?? kernel_size }; var paddings = new long[] { padding ?? 0 }; var dilations = new long[] { dilation ?? 1 }; - IntPtr[] ptrArray; - - using (var pa = new PinnedArray()) { - unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { - THSTensor_max_pool1d_with_indices(input.Handle, - pa.CreateArray, + unsafe { + fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { + var resOutput = THSTensor_max_pool1d_with_indices(input.Handle, (IntPtr)pkernelSize, kernelSizes.Length, (IntPtr)pstrides, strides.Length, (IntPtr)ppadding, paddings.Length, (IntPtr)pdilation, dilations.Length, - ceil_mode); - torch.CheckForErrors(); - } + ceil_mode, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); } - ptrArray = pa.Array; } - return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool2D.cs b/src/TorchSharp/NN/Pooling/MaxPool2D.cs index 7d96145df..2cef87ce6 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool2D.cs @@ -15,22 +15,30 @@ namespace Modules /// public sealed class MaxPool2d : ParamLessModule { - internal MaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) : base(nameof(MaxPool2d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.dilation = dilation; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_MaxPool2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.max_pool2d(input, kernel_size, stride, padding, dilation, ceil_mode); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_MaxPool2d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.max_pool2d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } + public long[] dilation { get; set; } + public bool ceil_mode { get; set; } } } @@ -41,74 +49,53 @@ public static partial class nn /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static unsafe MaxPool2d MaxPool2d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) + public static MaxPool2d MaxPool2d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - long svalue = stride.HasValue ? stride.Value : kernelSize; - long pvalue = padding.HasValue ? padding.Value : 0; - long dvalue = dilation.HasValue ? dilation.Value : 1; - - long* pStride = stackalloc long[2] { svalue, svalue }; - long* pPadding = stackalloc long[2] { pvalue, pvalue }; - long* pDilation = stackalloc long[2] { dvalue, dvalue }; + long[] kernelValue = new[] { kernel_size, kernel_size }; + long[] strideValue = stride.HasValue ? new[] { stride.Value, stride.Value } : kernelValue.ToArray(); + long[] paddingValue = padding.HasValue ? new[] { padding.Value, padding.Value } : new[] { 0L, 0L }; + long[] dilationValue = dilation.HasValue ? new[] { dilation.Value, dilation.Value } : new[] { 1L, 1L }; - long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; - - var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pStride, 2, (IntPtr)pPadding, 2, (IntPtr)pDilation, 2, ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool2d(handle, boxedHandle); + return new MaxPool2d(kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static unsafe MaxPool2d MaxPool2d((long, long) kernelSize, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceilMode = false) + public static unsafe MaxPool2d MaxPool2d((long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceil_mode = false) { - long svalue1 = stride != null ? stride.Value.Item1 : kernelSize.Item1; - long svalue2 = stride != null ? stride.Value.Item2 : kernelSize.Item2; - long pvalue1 = padding != null ? padding.Value.Item1 : 0; - long pvalue2 = padding != null ? padding.Value.Item2 : 0; - long dvalue1 = dilation != null ? dilation.Value.Item1 : 1; - long dvalue2 = dilation != null ? dilation.Value.Item2 : 1; - - long* pStride = stackalloc long[2] { svalue1, svalue2 }; - long* pPadding = stackalloc long[2] { pvalue1, pvalue2 }; - long* pDilation = stackalloc long[2] { dvalue1, dvalue2 }; - - long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; - - var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pStride, 2, (IntPtr)pPadding, 2, (IntPtr)pDilation, 2, ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool2d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; + long[] strideValue = stride.HasValue ? new[] { stride.Value.Item1, stride.Value.Item2 } : kernelValue.ToArray(); + long[] paddingValue = padding.HasValue ? new[] { padding.Value.Item1, padding.Value.Item2 } : new[] { 0L, 0L }; + long[] dilationValue = dilation.HasValue ? new[] { dilation.Value.Item1, dilation.Value.Item2 } : new[] { 1L, 1L }; + + return new MaxPool2d(kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static unsafe MaxPool2d MaxPool2d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) + public static MaxPool2d MaxPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { - var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), (IntPtr)pDilation, (dilation == null ? 0 : dilation.Length), ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool2d(handle, boxedHandle); - } + return new MaxPool2d(kernel_size, stride, padding, dilation, ceil_mode); } public static partial class functional @@ -117,100 +104,64 @@ public static partial class functional /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// - /// + /// + /// /// /// /// /// - public static Tensor max_pool2d(Tensor input, long[] kernelSize, long[] strides = null, + public static Tensor max_pool2d(Tensor input, long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides = strides ?? kernelSize; - padding = padding ?? kernelSize.Select(x => 0L).ToArray(); - dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - var res = - THSTensor_max_pool2d(input.Handle, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + var ret = max_pool2d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static unsafe Tensor max_pool2d(Tensor input, long kernelSize, long? stride = null, + public static Tensor max_pool2d(Tensor input, long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - long svalue = stride.HasValue ? stride.Value : kernelSize; - long pvalue = padding.HasValue ? padding.Value : 0; - long dvalue = dilation.HasValue ? dilation.Value : 1; - - long* pStride = stackalloc long[2] { svalue, svalue }; - long* pPadding = stackalloc long[2] { pvalue, pvalue }; - long* pDilation = stackalloc long[2] { dvalue, dvalue }; - - long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; - - var res = THSTensor_max_pool2d(input.Handle, - (IntPtr)pkernelSize, 2, - (IntPtr)pStride, 2, - (IntPtr)pPadding, 2, - (IntPtr)pDilation, 2, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + long[] kernelValue = new[] { kernel_size, kernel_size }; + long[] strideValue = stride.HasValue ? new[] { stride.Value, stride.Value } : kernelValue.ToArray(); + long[] paddingValue = padding.HasValue ? new[] { padding.Value, padding.Value } : new[] { 0L, 0L }; + long[] dilationValue = dilation.HasValue ? new[] { dilation.Value, dilation.Value } : new[] { 1L, 1L }; + + var ret = max_pool2d_with_indices(input, kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernelSize, (long, long)? stride = null, + public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceil_mode = false) { - long svalue1 = stride != null ? stride.Value.Item1 : kernelSize.Item1; - long svalue2 = stride != null ? stride.Value.Item2 : kernelSize.Item2; - long pvalue1 = padding != null ? padding.Value.Item1 : 0; - long pvalue2 = padding != null ? padding.Value.Item2 : 0; - long dvalue1 = dilation != null ? dilation.Value.Item1 : 1; - long dvalue2 = dilation != null ? dilation.Value.Item2 : 1; - - long* pStride = stackalloc long[2] { svalue1, svalue2 }; - long* pPadding = stackalloc long[2] { pvalue1, pvalue2 }; - long* pDilation = stackalloc long[2] { dvalue1, dvalue2 }; - - long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; - - var res = THSTensor_max_pool2d(input.Handle, - (IntPtr)pkernelSize, 2, - (IntPtr)pStride, 2, - (IntPtr)pPadding, 2, - (IntPtr)pDilation, 2, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; + long[] strideValue = stride.HasValue ? new[] { stride.Value.Item1, stride.Value.Item2 } : kernelValue.ToArray(); + long[] paddingValue = padding.HasValue ? new[] { padding.Value.Item1, padding.Value.Item2 } : new[] { 0L, 0L }; + long[] dilationValue = dilation.HasValue ? new[] { dilation.Value.Item1, dilation.Value.Item2 } : new[] { 1L, 1L }; + + var ret = max_pool2d_with_indices(input, kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// @@ -223,30 +174,25 @@ public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernelSize, (l /// /// /// - public static (Tensor output, Tensor indices) max_pool2d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, + public static (Tensor Values, Tensor Indices) max_pool2d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides = strides ?? kernelSize; - padding = padding ?? kernelSize.Select(x => 0L).ToArray(); - dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); - IntPtr[] ptrArray; - - using (var pa = new PinnedArray()) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - THSTensor_max_pool2d_with_indices(input.Handle, - pa.CreateArray, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode); - torch.CheckForErrors(); - } + strides ??= kernelSize; + padding ??= kernelSize.Select(x => 0L).ToArray(); + dilation ??= kernelSize.Select(x => 1L).ToArray(); + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { + var resOutput = THSTensor_max_pool2d_with_indices(input.Handle, + (IntPtr)pkernelSize, kernelSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length, + (IntPtr)pdilation, dilation.Length, + ceil_mode, out var resIndices); + + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); } - ptrArray = pa.Array; } - return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool3D.cs b/src/TorchSharp/NN/Pooling/MaxPool3D.cs index 1999c34dc..2b26b3dad 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool3D.cs @@ -6,6 +6,7 @@ namespace TorchSharp { + using Google.Protobuf.WellKnownTypes; using Modules; namespace Modules @@ -15,23 +16,30 @@ namespace Modules /// public sealed class MaxPool3d : ParamLessModule { - internal MaxPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) : base(nameof(MaxPool3d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.dilation = dilation; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_MaxPool3d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.max_pool3d(input, kernel_size, stride, padding, dilation, ceil_mode); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_MaxPool3d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.max_pool3d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } + public long[] dilation { get; set; } + public bool ceil_mode { get; set; } } } @@ -42,55 +50,49 @@ public static partial class nn /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) + public static MaxPool3d MaxPool3d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value, padding.Value } : null; var pDilation = dilation.HasValue ? new long[] { dilation.Value, dilation.Value, dilation.Value } : null; - return MaxPool3d(new long[] { kernelSize, kernelSize, kernelSize }, pStride, pPadding, pDilation, ceilMode); + return MaxPool3d(new long[] { kernel_size, kernel_size, kernel_size }, pStride, pPadding, pDilation, ceil_mode); } /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d((long, long, long) kernelSize, (long, long, long)? stride = null, (long, long, long)? padding = null, (long, long, long)? dilation = null, bool ceilMode = false) + public static MaxPool3d MaxPool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null, (long, long, long)? dilation = null, bool ceil_mode = false) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 } : null; var pDilation = dilation.HasValue ? new long[] { dilation.Value.Item1, dilation.Value.Item2, dilation.Value.Item3 } : null; - return MaxPool3d(new long[] { kernelSize.Item1, kernelSize.Item2, kernelSize.Item3 }, pStride, pPadding, pDilation, ceilMode); + return MaxPool3d(new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pStride, pPadding, pDilation, ceil_mode); } /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) + public static MaxPool3d MaxPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { - var handle = THSNN_MaxPool3d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), (IntPtr)pDilation, (dilation == null ? 0 : dilation.Length), ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool3d(handle, boxedHandle); - } - } + return new MaxPool3d(kernel_size, stride, padding, dilation, ceil_mode); } public static partial class functional @@ -99,31 +101,18 @@ public static partial class functional /// Applies a 3D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// - /// + /// + /// /// /// /// /// - public static Tensor max_pool3d(Tensor input, long[] kernelSize, long[] strides = null, + public static Tensor max_pool3d(Tensor input, long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides = strides ?? kernelSize; - padding = padding ?? kernelSize.Select(x => 0L).ToArray(); - dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - var res = - THSTensor_max_pool3d(input.Handle, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + var ret = max_pool3d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// @@ -136,30 +125,26 @@ public static Tensor max_pool3d(Tensor input, long[] kernelSize, long[] strides /// /// /// - public static (Tensor output, Tensor indices) max_pool3d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, + public static (Tensor Values, Tensor Indices) max_pool3d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides = strides ?? kernelSize; - padding = padding ?? kernelSize.Select(x => 0L).ToArray(); - dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); - IntPtr[] ptrArray; + strides ??= kernelSize; + padding ??= kernelSize.Select(x => 0L).ToArray(); + dilation ??= kernelSize.Select(x => 1L).ToArray(); + + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { + var resOutput = THSTensor_max_pool3d_with_indices(input.Handle, + (IntPtr)pkernelSize, kernelSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length, + (IntPtr)pdilation, dilation.Length, + ceil_mode, out var resIndices); - using (var pa = new PinnedArray()) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - THSTensor_max_pool3d_with_indices(input.Handle, - pa.CreateArray, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode); - torch.CheckForErrors(); - } + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); } - ptrArray = pa.Array; } - return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs index d2bf0ddeb..9c2afb04d 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs @@ -5,6 +5,7 @@ namespace TorchSharp { + using System.Runtime.CompilerServices; using Modules; namespace Modules @@ -14,25 +15,26 @@ namespace Modules /// public sealed class MaxUnpool1d : ParamLessModule { - internal MaxUnpool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxUnpool1d(long kernel_size, long? stride = null, long? padding = null) : base(nameof(MaxUnpool1d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - unsafe { - fixed (long* pOutSize = output_size) { - var res = THSNN_MaxUnpool1d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + return torch.nn.functional.max_unpool1d(tensor, indices, kernel_size, stride, padding, output_size); } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } + + public long kernel_size { get; set; } + public long? stride { get; set; } + public long? padding { get; set; } } } @@ -41,26 +43,42 @@ public static partial class torch public static partial class nn { /// - /// Applies a 1D max pooling over an input signal composed of several input planes. + /// Computes a partial inverse of :class:`MaxPool1d`. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool1d MaxUnpool1d(long kernelSize, long? stride = null, long? padding = null) + public static MaxUnpool1d MaxUnpool1d(long kernel_size, long? stride = null, long? padding = null) { - var pStride = stride.HasValue ? new long[] { stride.Value } : null; - var pPadding = padding.HasValue ? new long[] { padding.Value } : null; - return MaxUnpool1d(new long[] { kernelSize }, pStride, pPadding); + return new MaxUnpool1d(kernel_size, stride, padding); } - private static MaxUnpool1d MaxUnpool1d(long[] kernelSize, long[] strides = null, long[] padding = null) + public static partial class functional { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { - var handle = THSNN_MaxUnpool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)pPadding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxUnpool1d(handle, boxedHandle); + /// + /// Applies a 1D max pooling over an input signal composed of several input planes. + /// + /// the input Tensor to invert + /// the indices given out by :class:`~torch.nn.MaxPool1d` + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 + /// (optional): The targeted output size + /// + public static Tensor max_unpool1d(Tensor input, Tensor indices, long kernel_size, long? stride = null, long? padding = null, long[] output_size = null) + { + long[] kernels = new[] { kernel_size }; + long[] strides = stride.HasValue ? new[] { stride.Value } : Array.Empty(); + long[] paddings = padding.HasValue ? new[] { padding.Value } : Array.Empty(); + output_size ??= Array.Empty(); + + unsafe { + fixed (long* pkernels = kernels, pstrides = strides, ppaddings = paddings, poutputSize = output_size) { + var res = THSTensor_max_unpool1d(input.Handle, indices.Handle, (IntPtr)pkernels, kernels.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, paddings.Length, (IntPtr)pstrides, strides.Length); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } } } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs index e01e6ddcf..f342049fb 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs @@ -5,6 +5,7 @@ namespace TorchSharp { + using Microsoft.VisualBasic; using Modules; namespace Modules @@ -14,25 +15,26 @@ namespace Modules /// public sealed class MaxUnpool2d : ParamLessModule { - internal MaxUnpool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxUnpool2d(long[] kernel_size, long[] stride = null, long[] padding = null) : base(nameof(MaxUnpool2d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - unsafe { - fixed (long* pOutSize = output_size) { - var res = THSNN_MaxUnpool2d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize, output_size == null ? 0 : output_size.Length); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + return torch.nn.functional.max_unpool2d(tensor, indices, kernel_size, stride, padding, output_size); } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } } } @@ -43,47 +45,41 @@ public static partial class nn /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d(long kernelSize, long? stride = null, long? padding = null) + public static MaxUnpool2d MaxUnpool2d(long kernel_size, long? stride = null, long? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value } : null; - return MaxUnpool2d(new long[] { kernelSize, kernelSize }, pStride, pPadding); + return new MaxUnpool2d(new[] { kernel_size, kernel_size }, pStride, pPadding); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d((long, long) kernelSize, (long, long)? stride = null, (long, long)? padding = null) + public static MaxUnpool2d MaxUnpool2d((long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2 } : null; - return MaxUnpool2d(new long[] { kernelSize.Item1, kernelSize.Item2 }, pStride, pPadding); + return new MaxUnpool2d(new[] { kernel_size.Item1, kernel_size.Item2 }, pStride, pPadding); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d(long[] kernelSize, long[] strides = null, long[] padding = null) + public static MaxUnpool2d MaxUnpool2d(long[] kernel_size, long[] stride = null, long[] padding = null) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { - var handle = THSNN_MaxUnpool2d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxUnpool2d(handle, boxedHandle); - } - } + return new MaxUnpool2d(kernel_size, stride, padding); } public static partial class functional @@ -91,16 +87,22 @@ public static partial class functional /// /// Computes a partial inverse of MaxPool2d. /// - /// The input tensor. - /// - /// + /// the input Tensor to invert + /// the indices given out by :class:`~torch.nn.MaxPool2d` + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 + /// (optional): The targeted output size /// - public static Tensor max_unpool2d(Tensor input, Tensor indices, long[] outputSize) + public static Tensor max_unpool2d(Tensor input, Tensor indices, long[] kernel_size, long[] stride = null, long[] padding = null, long[] output_size = null) { + stride ??= Array.Empty(); + padding ??= Array.Empty(); + output_size ??= Array.Empty(); + unsafe { - fixed (long* poutputSize = outputSize) { - var res = THSTensor_maxunpool2d(input.Handle, indices.Handle, - (IntPtr)poutputSize, outputSize.Length); + fixed (long* pkernels = kernel_size, pstrides = stride, ppaddings = padding, poutputSize = output_size) { + var res = THSTensor_max_unpool2d(input.Handle, indices.Handle, (IntPtr)pkernels, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, padding.Length, (IntPtr)pstrides, stride.Length); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs index 85d52e208..33abc0429 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs @@ -5,34 +5,36 @@ namespace TorchSharp { + using Microsoft.VisualBasic; using Modules; namespace Modules { /// - /// This class is used to represent a MaxUnpool3d module. + /// This class is used to represent a MaxUnpool3D module. /// public sealed class MaxUnpool3d : ParamLessModule { - internal MaxUnpool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxUnpool3d(long[] kernel_size, long[] stride = null, long[] padding = null) : base(nameof(MaxUnpool3d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - unsafe { - fixed (long* pOutSize = output_size) { - var res = THSNN_MaxUnpool3d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize, output_size == null ? 0 : output_size.Length); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + return torch.nn.functional.max_unpool3d(tensor, indices, kernel_size, stride, padding, output_size); } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } } } @@ -41,69 +43,66 @@ public static partial class torch public static partial class nn { /// - /// Applies a 2D max pooling over an input signal composed of several input planes. + /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d(long kernelSize, long? stride = null, long? padding = null) + public static MaxUnpool3d MaxUnpool3d(long kernel_size, long? stride = null, long? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value, padding.Value } : null; - return MaxUnpool3d(new long[] { kernelSize, kernelSize, kernelSize }, pStride, pPadding); + return new MaxUnpool3d(new[] { kernel_size, kernel_size, kernel_size }, pStride, pPadding); } /// - /// Applies a 2D max pooling over an input signal composed of several input planes. + /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d((long, long, long) kernelSize, (long, long, long)? stride = null, (long, long, long)? padding = null) + public static MaxUnpool3d MaxUnpool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 } : null; - return MaxUnpool3d(new long[] { kernelSize.Item1, kernelSize.Item2, kernelSize.Item3 }, pStride, pPadding); + return new MaxUnpool3d(new[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pStride, pPadding); } /// - /// Applies a 2D max pooling over an input signal composed of several input planes. + /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d(long[] kernelSize, long[] strides = null, long[] padding = null) + public static MaxUnpool3d MaxUnpool3d(long[] kernel_size, long[] stride = null, long[] padding = null) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { - var handle = THSNN_MaxUnpool3d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxUnpool3d(handle, boxedHandle); - } - } + return new MaxUnpool3d(kernel_size, stride, padding); } + public static partial class functional { /// /// Computes a partial inverse of MaxPool3d. /// - /// The input tensor. - /// - /// - /// - /// + /// the input Tensor to invert + /// the indices given out by :class:`~torch.nn.MaxPool3d` + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 + /// (optional): The targeted output size /// - public static Tensor max_unpool3d(Tensor input, Tensor indices, long[] outputSize, long[] strides, long[] padding) + public static Tensor max_unpool3d(Tensor input, Tensor indices, long[] kernel_size, long[] stride = null, long[] padding = null, long[] output_size = null) { + stride ??= Array.Empty(); + padding ??= Array.Empty(); + output_size ??= Array.Empty(); + unsafe { - fixed (long* poutputSize = outputSize, pstrides = strides, ppadding = padding) { - var res = THSTensor_maxunpool3d(input.Handle, indices.Handle, - (IntPtr)poutputSize, outputSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length); + fixed (long* pkernels = kernel_size, pstrides = stride, ppaddings = padding, poutputSize = output_size) { + var res = THSTensor_max_unpool3d(input.Handle, indices.Handle, (IntPtr)pkernels, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, padding.Length, (IntPtr)pstrides, stride.Length); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs index b153acc9e..6d39ecb1c 100644 --- a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs +++ b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs @@ -17,8 +17,7 @@ internal ChannelShuffle(long groups) : base(nameof(ChannelShuffle)) { this.groups = groups; } - private long groups {get; set;} - + public override Tensor forward(Tensor tensor) { return tensor.channel_shuffle(groups); @@ -28,6 +27,8 @@ public override string GetName() { return typeof(ChannelShuffle).Name; } + + public long groups { get; set; } } } diff --git a/src/TorchSharp/NN/Unflatten.cs b/src/TorchSharp/NN/Unflatten.cs index fa5954f6b..eeb91e1a9 100644 --- a/src/TorchSharp/NN/Unflatten.cs +++ b/src/TorchSharp/NN/Unflatten.cs @@ -14,25 +14,20 @@ namespace Modules /// public sealed class Unflatten : ParamLessModule { - internal Unflatten(long dim, long[] unflattenedSize) : base(nameof(Unflatten)) + internal Unflatten(long dim, long[] unflattened_size) : base(nameof(Unflatten)) { - this._dim = dim; - this._unflattenedSize = unflattenedSize; + this.dim = dim; + this.unflattened_size = unflattened_size; } public override Tensor forward(Tensor tensor) { - return tensor.unflatten(_dim, _unflattenedSize); + return tensor.unflatten(dim, unflattened_size); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - - long _dim; - long[] _unflattenedSize; + + public long dim { get; set; } + public long[] unflattened_size { get; set; } } } @@ -44,11 +39,11 @@ public static partial class nn /// Unflattens a tensor dim expanding it to a desired shape. For use with Sequential. /// /// Dimension to be unflattened - /// New shape of the unflattened dimension + /// New shape of the unflattened dimension /// - public static Unflatten Unflatten(long dim, long[] unflattenedSize) + public static Unflatten Unflatten(long dim, long[] unflattened_size) { - return new Unflatten(dim, unflattenedSize); + return new Unflatten(dim, unflattened_size); } } } diff --git a/src/TorchSharp/NN/Unfold.cs b/src/TorchSharp/NN/Unfold.cs index aa56705bb..050479623 100644 --- a/src/TorchSharp/NN/Unfold.cs +++ b/src/TorchSharp/NN/Unfold.cs @@ -6,7 +6,6 @@ #nullable enable namespace TorchSharp { - using System.Security.Cryptography; using Modules; namespace Modules @@ -15,7 +14,7 @@ public sealed class Unfold : ParamLessModule { internal Unfold((long, long) kernel_size, (long, long) dilation, (long, long) padding, (long, long) stride) : base(nameof(Unfold)) { - this.kernelSize = kernel_size; + this.kernel_size = kernel_size; this.dilation = dilation; this.padding = padding; this.stride = stride; @@ -23,13 +22,13 @@ internal Unfold((long, long) kernel_size, (long, long) dilation, (long, long) pa public override Tensor forward(Tensor tensor) { - return torch.nn.functional.unfold(tensor, kernelSize, dilation, padding, stride); + return torch.nn.functional.unfold(tensor, kernel_size, dilation, padding, stride); } - private (long, long) kernelSize; - private (long, long) dilation; - private (long, long) padding; - private (long, long) stride; + public (long, long) kernel_size { get; set; } + public (long, long) dilation { get; set; } + public (long, long) padding { get; set; } + public (long, long) stride { get; set; } } } @@ -45,7 +44,7 @@ public static partial class nn /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. /// Currently, only 4-D input tensors (batched image-like tensors) are supported. - public unsafe static Unfold Unfold(long kernel_size, long dilation = 1, long padding = 0, long stride = 1) + public static Unfold Unfold(long kernel_size, long dilation = 1, long padding = 0, long stride = 1) { return new Unfold((kernel_size, kernel_size), (dilation, dilation), (padding, padding), (stride, stride)); } @@ -58,7 +57,7 @@ public unsafe static Unfold Unfold(long kernel_size, long dilation = 1, long pad /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. /// Currently, only 4-D input tensors (batched image-like tensors) are supported. - public unsafe static Unfold Unfold((long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) + public static Unfold Unfold((long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) { dilation ??= (1, 1); stride ??= (1, 1); @@ -77,7 +76,7 @@ public static partial class functional /// A parameter that controls the stride of elements within the neighborhood. /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. - public unsafe static Tensor unfold(Tensor input, long kernel_size, long dilation = 1, long padding = 0, long stride = 1) + public static Tensor unfold(Tensor input, long kernel_size, long dilation = 1, long padding = 0, long stride = 1) { var res = THSNN_unfold(input.Handle, kernel_size, kernel_size, stride, stride, padding, padding, dilation, dilation); if (res == IntPtr.Zero) { torch.CheckForErrors(); } @@ -92,7 +91,7 @@ public unsafe static Tensor unfold(Tensor input, long kernel_size, long dilation /// A parameter that controls the stride of elements within the neighborhood. /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. - public unsafe static Tensor unfold(Tensor input, (long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) + public static Tensor unfold(Tensor input, (long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) { dilation ??= (1, 1); stride ??= (1, 1); diff --git a/src/TorchSharp/NN/Upsample.cs b/src/TorchSharp/NN/Upsample.cs index 2427cc5a9..2f3b43707 100644 --- a/src/TorchSharp/NN/Upsample.cs +++ b/src/TorchSharp/NN/Upsample.cs @@ -8,6 +8,40 @@ namespace TorchSharp { using Modules; + namespace Modules + { + /// + /// This class is used to represent an Upsample module. + /// + public sealed class Upsample : ParamLessModule + { + internal Upsample(long[]? size, double[]? scale_factor, UpsampleMode mode, bool? align_corners, bool? recompute_scale_factor) : base(nameof(Upsample)) + { + this.size = size; + this.scale_factor = scale_factor; + this.mode = mode; + this.align_corners = align_corners; + this.recompute_scale_factor = recompute_scale_factor; + } + + /// + /// Forward pass. + /// + /// Input tensor + /// + public override Tensor forward(Tensor input) + { + return torch.nn.functional.interpolate(input, size, scale_factor, (InterpolationMode)mode, align_corners, recompute_scale_factor ?? false); + } + + public long[]? size { get; set; } + public double[]? scale_factor { get; set; } + public UpsampleMode mode { get; set; } + public bool? align_corners { get; set; } + public bool? recompute_scale_factor { get; set; } + } + } + public static partial class torch { public static partial class nn @@ -22,19 +56,11 @@ public static partial class nn /// The upsampling algorithm: one of 'nearest', 'linear', 'bilinear', 'bicubic' and 'trilinear'. Default: 'nearest' /// If true, the corner pixels of the input and output tensors are aligned, and thus preserving the values at those pixels. /// This only has effect when mode is 'linear', 'bilinear', or 'trilinear'. Default: false + /// recompute the scale_factor for use in the interpolation calculation. If `recompute_scale_factor` is ``True``, then `scale_factor` must be passed in and `scale_factor` is used to compute the output `size`. The computed output `size` will be used to infer new scales for the interpolation. Note that when `scale_factor` is floating-point, it may differ from the recomputed `scale_factor` due to rounding and precision issues. If `recompute_scale_factor` is ``False``, then `size` or `scale_factor` will be used directly for interpolation. /// - public static Upsample Upsample(long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool? align_corners = null) + public static Upsample Upsample(long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool? align_corners = null, bool? recompute_scale_factor = null) { - unsafe { - fixed (long* psize = size) { - fixed (double* pSF = scale_factor) { - byte ac = (byte)((align_corners.HasValue) ? (align_corners.Value ? 1 : 2) : 0); - var res = THSNN_Upsample_ctor((IntPtr)psize, size is null ? 0 : size.Length, (IntPtr)pSF, scale_factor is null ? 0 : scale_factor.Length, (byte)mode, ac, out var boxedHandle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Upsample(res, boxedHandle, size, scale_factor, mode, align_corners); - } - } - } + return new Upsample(size, scale_factor, mode, align_corners, recompute_scale_factor); } public static partial class functional @@ -44,21 +70,18 @@ public static partial class functional /// The input data is assumed to be of the form minibatch x channels x[optional depth] x[optional height] x width. /// Hence, for spatial inputs, we expect a 4D Tensor and for volumetric inputs, we expect a 5D Tensor. /// - /// Input tensor + /// Input tensor /// Output spatial sizes /// Multiplier for spatial size. Has to match input size /// The upsampling algorithm: one of 'nearest', 'linear', 'bilinear', 'bicubic' and 'trilinear'. Default: 'nearest' /// If true, the corner pixels of the input and output tensors are aligned, and thus preserving the values at those pixels. /// This only has effect when mode is 'linear', 'bilinear', or 'trilinear'. Default: false /// - public static Tensor upsample(Tensor x, long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool align_corners = false) + public static Tensor upsample(Tensor input, long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool align_corners = false) { - using (var d = nn.Upsample(size, scale_factor, mode, align_corners)) { - return d.call(x); - } + return interpolate(input, size, scale_factor, (InterpolationMode)mode, align_corners); } - /// /// Upsamples the input, using nearest neighbours’ pixel values. /// @@ -198,54 +221,4 @@ public static Tensor upsample_nearest3d(Tensor input, long[]? outputSizes = null } } } - - namespace Modules - { - /// - /// This class is used to represent an Upsample module. - /// - public sealed class Upsample : ParamLessModule - { - internal Upsample(IntPtr handle, IntPtr boxedHandle, long[]? size, double[]? scale_factor, UpsampleMode mode, bool? align_corners) : base(handle, boxedHandle) - { - this._size = size; - this._scale_factor = scale_factor; - this.mode = mode; - this.align_corners = align_corners; - } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_Upsample_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - public UpsampleMode mode { get; private set; } - - public bool? align_corners { get; private set; } - - public ReadOnlySpan size { - get { return _size is null ? null : new ReadOnlySpan(_size!); } - } - - public ReadOnlySpan scale_factor { - get { return _scale_factor is null ? null : new ReadOnlySpan(_scale_factor!); } - } - - private long[]? _size; - private double[]? _scale_factor; - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - } - } } diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index 6756b2795..5bfed781e 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -50,12 +50,6 @@ internal static extern IntPtr THSNN_custom_module( // align_corners -- 0=None, 1=true, 2=false internal static extern IntPtr THSNN_grid_sample(IntPtr input, IntPtr grid, byte mode, byte padding_mode, byte align_corners); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AlphaDropout_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AlphaDropout_ctor(double p, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_alpha_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -63,10 +57,7 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_functional_bilinear(IntPtr input1, IntPtr input2, IntPtr weights, IntPtr bias); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_CosineSimilarity_ctor(long dim, double eps, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_CosineSimilarity_forward(torch.nn.Module.HType module, IntPtr input1, IntPtr input2); + internal static extern IntPtr THSNN_cosine_similarity(IntPtr input1, IntPtr input2, long dim, double eps); [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -133,12 +124,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_EmbeddingBag_from_pretrained(IntPtr embeddings, [MarshalAs(UnmanagedType.U1)] bool freeze, double max_norm, [MarshalAs(UnmanagedType.U1)] bool hasMN, double norm_type, [MarshalAs(UnmanagedType.U1)] bool scale_grad_by_freq, long mode, [MarshalAs(UnmanagedType.U1)] bool sparse, [MarshalAs(UnmanagedType.U1)] bool include_last_offset, long padding_idx, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FeatureAlphaDropout_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FeatureAlphaDropout_ctor(double p, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_feature_alpha_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -423,16 +408,10 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_PairwiseDistance_ctor(double p, double eps, [MarshalAs(UnmanagedType.U1)] bool keep_dim, out IntPtr pBoxedModule); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PixelUnshuffle_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PixelUnshuffle_ctor(long downscaleFactor, out IntPtr pBoxedModule); + internal static extern IntPtr THSNN_pixel_unshuffle(IntPtr tensor, long downscale_factor); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PixelShuffle_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PixelShuffle_ctor(long upscaleFactor, out IntPtr pBoxedModule); + internal static extern IntPtr THSNN_pixel_shuffle(IntPtr tensor, long upscale_factor); [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_GRUCell_forward(torch.nn.Module.HType module, IntPtr input, IntPtr h_0); @@ -584,24 +563,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_InstanceNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LayerNorm_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LayerNorm_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_LayerNorm_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LayerNorm_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_LayerNorm_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LayerNorm_ctor(IntPtr norm_shape, long norm_shape_len, double eps, [MarshalAs(UnmanagedType.U1)] bool elementwise_affine, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_InstanceNorm2d_forward(IntPtr module, IntPtr tensor); @@ -935,21 +896,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_BatchNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool1d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool1d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool1d_ctor(IntPtr pkernelSize, IntPtr pStrides, IntPtr pPadding, IntPtr pDilation, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool3d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize, int outputSizeLength); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_ELU_forward(torch.nn.Module.HType module, IntPtr tensor); @@ -1089,127 +1035,7 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_Threshold_forward(torch.nn.Module.HType module, IntPtr tensor); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Threshold_ctor(double threshold, double value, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LocalResponseNorm_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LocalResponseNorm_ctor(long size, double alpha, double beta, double k, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool1d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool2d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool3d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool3d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool1d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool2d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool3d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool3d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool1d_ctor(IntPtr pkernelSize, IntPtr pstrides, IntPtr ppadding, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr ppadding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool3d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr ppadding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool2d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pOutputSize, int sizeLength, IntPtr pOutputRatio, int ratioLength, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool3d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool3d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pOutputSize, int sizeLength, IntPtr pOutputRatio, int ratioLength, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LPPool1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LPPool1d_ctor(double norm_type, IntPtr pkernelSize, IntPtr pstrides, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LPPool2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LPPool2d_ctor(double norm_type, IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool2d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, IntPtr pDilation, int dilationLength, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool3d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool3d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, IntPtr pDilation, int dilationLength, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool1d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool1d_ctor(IntPtr pkernelSize, IntPtr pStrides, IntPtr pPadding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool2d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize, int outputSizeLength); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, out IntPtr pBoxedModule); + internal static extern IntPtr THSNN_Threshold_ctor(double threshold, double value, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); } #pragma warning restore CA2101 } diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs index c82b659a3..0de92012c 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs @@ -64,56 +64,49 @@ internal static extern IntPtr THSTensor_conv_transpose3d(IntPtr input, IntPtr we long groups); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool1d(IntPtr input, + internal static extern IntPtr THSTensor_max_pool1d_with_indices(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); [DllImport("LibTorchSharp")] - internal static extern void THSTensor_max_pool1d_with_indices(IntPtr input, AllocatePinnedArray allocator, - IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + internal static extern IntPtr THSTensor_max_pool2d_with_indices(IntPtr input, + IntPtr kernelSize, int kernelSizeLength, + IntPtr strides, int stridesLength, + IntPtr padding, int paddingLength, + IntPtr dilation, int dilationLength, + [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool2d(IntPtr input, + internal static extern IntPtr THSTensor_max_pool3d_with_indices(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); [DllImport("LibTorchSharp")] - internal static extern void THSTensor_max_pool2d_with_indices(IntPtr input, AllocatePinnedArray allocator, - IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool3d(IntPtr input, - IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + internal static extern IntPtr THSTensor_max_unpool1d(IntPtr tensor, IntPtr indices, + IntPtr kernelSize, int kernelSizeLength, + IntPtr outputSize, int outputSizeLength, + IntPtr padding, int paddingLength, + IntPtr strides, int stridesLength); [DllImport("LibTorchSharp")] - internal static extern void THSTensor_max_pool3d_with_indices(IntPtr input, AllocatePinnedArray allocator, + internal static extern IntPtr THSTensor_max_unpool2d(IntPtr tensor, IntPtr indices, IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, + IntPtr outputSize, int outputSizeLength, IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + IntPtr strides, int stridesLength); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_maxunpool3d(IntPtr input, IntPtr indices, IntPtr outputSize, int outputSizeLength, IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength); + internal static extern IntPtr THSTensor_max_unpool3d(IntPtr tensor, IntPtr indices, + IntPtr kernelSize, int kernelSizeLength, + IntPtr outputSize, int outputSizeLength, + IntPtr padding, int paddingLength, + IntPtr strides, int stridesLength); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool1d(IntPtr input, @@ -129,7 +122,7 @@ internal static extern IntPtr THSTensor_avg_pool2d(IntPtr input, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, - [MarshalAs(UnmanagedType.U1)] bool count_include_pad); + [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool3d(IntPtr input, @@ -137,7 +130,7 @@ internal static extern IntPtr THSTensor_avg_pool3d(IntPtr input, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, - [MarshalAs(UnmanagedType.U1)] bool count_include_pad); + [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool2d_backward(IntPtr gradOutput, IntPtr originalInput, @@ -157,14 +150,6 @@ internal static extern IntPtr THSTensor_avg_pool3d_backward(IntPtr gradOutput, I [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisorOverride); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_avg_pool1d(IntPtr input, - IntPtr outputSize, int outputSizeLength); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_avg_pool2d(IntPtr input, - IntPtr outputSize, int outputSizeLength); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_upsample_nearest1d(IntPtr input, IntPtr outputSize, int outputSizeLength, @@ -2086,7 +2071,10 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, internal static extern IntPtr THSTensor_eye(long rows, long columns, sbyte scalarType, int deviceType, int deviceIndex, [MarshalAs(UnmanagedType.U1)] bool requires_grad); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_maxunpool2d(IntPtr input, IntPtr indices, IntPtr outputSize, int outputSizeLength); + internal static extern IntPtr THSTensor_adaptive_avg_pool1d(IntPtr input, IntPtr outputSize, int outputSizeLength); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_avg_pool2d(IntPtr input, IntPtr outputSize, int outputSizeLength); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_adaptive_avg_pool3d(IntPtr input, IntPtr outputSize, int outputSizeLength); @@ -2094,6 +2082,27 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_adaptive_avg_pool3d_backward_out(IntPtr gradInput, IntPtr gradOutput, IntPtr originalInput); + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_max_pool1d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_max_pool2d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_max_pool3d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_fractional_max_pool2d(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr outputSize, int outputSizeLength, IntPtr outputRatio, int outputRatioLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_fractional_max_pool3d(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr outputSize, int outputSizeLength, IntPtr outputRatio, int outputRatioLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_lp_pool1d(IntPtr input, double norm_type, IntPtr kernelSize, int kernelSizeLength, IntPtr stride, int strideLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_lp_pool2d(IntPtr input, double norm_type, IntPtr kernelSize, int kernelSizeLength, IntPtr stride, int strideLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_searchsorted_t(IntPtr sorted_sequence, IntPtr values, bool out_int32, bool right, IntPtr sorter); [DllImport("LibTorchSharp")] diff --git a/src/TorchVision/Ops/DropBlock.cs b/src/TorchVision/Ops/DropBlock.cs index 2aece98d0..dea7ed8a4 100644 --- a/src/TorchVision/Ops/DropBlock.cs +++ b/src/TorchVision/Ops/DropBlock.cs @@ -53,7 +53,7 @@ public static Tensor drop_block2d(Tensor input, double p, long block_size, bool var pad = block_size / 2; noise = torch.nn.functional.pad(noise, (pad, pad, pad, pad), value: 0); - noise = torch.nn.functional.max_pool2d(noise, stride: 1, kernelSize: block_size, padding: block_size / 2); + noise = torch.nn.functional.max_pool2d(noise, stride: 1, kernel_size: block_size, padding: block_size / 2); noise = 1 - noise; var normalize_scale = noise.numel() / (eps + noise.sum()); @@ -94,7 +94,7 @@ public static Tensor drop_block3d(Tensor input, double p, long block_size, bool var pad = block_size / 2; var padding = new[] { pad, pad, pad, pad, pad, pad }; noise = torch.nn.functional.pad(noise, padding, value: 0); - noise = torch.nn.functional.max_pool3d(noise, strides: new long[] { 1, 1, 1 }, kernelSize: new[] { block_size, block_size, block_size }, padding: new long[] { pad }); + noise = torch.nn.functional.max_pool3d(noise, stride: new long[] { 1, 1, 1 }, kernel_size: new[] { block_size, block_size, block_size }, padding: new long[] { pad }); noise = 1 - noise; var normalize_scale = noise.numel() / (eps + noise.sum()); diff --git a/src/TorchVision/models/AlexNet.cs b/src/TorchVision/models/AlexNet.cs index 33372af06..a26fd3718 100644 --- a/src/TorchVision/models/AlexNet.cs +++ b/src/TorchVision/models/AlexNet.cs @@ -76,17 +76,17 @@ public AlexNet(int numClasses, float dropout = 0.5f, string? weights_file = null features = Sequential( Conv2d(3, 64, kernelSize: 11, stride: 4, padding: 2), ReLU(inplace: true), - MaxPool2d(kernelSize: 3, stride: 2), + MaxPool2d(kernel_size: 3, stride: 2), Conv2d(64, 192, kernelSize: 5, padding: 2), ReLU(inplace: true), - MaxPool2d(kernelSize: 3, stride: 2), + MaxPool2d(kernel_size: 3, stride: 2), Conv2d(192, 384, kernelSize: 3, padding: 1), ReLU(inplace: true), Conv2d(384, 256, kernelSize: 3, padding: 1), ReLU(inplace: true), Conv2d(256, 256, kernelSize: 3, padding: 1), ReLU(inplace: true), - MaxPool2d(kernelSize: 3, stride: 2) + MaxPool2d(kernel_size: 3, stride: 2) ); avgpool = AdaptiveAvgPool2d(new long[] { 6, 6 }); diff --git a/src/TorchVision/models/GoogleNet.cs b/src/TorchVision/models/GoogleNet.cs index 861ccde6f..105c24d35 100644 --- a/src/TorchVision/models/GoogleNet.cs +++ b/src/TorchVision/models/GoogleNet.cs @@ -119,21 +119,21 @@ public GoogleNet(int numClasses = 1000, this.transform_input = transform_input; conv1 = conv_block(3, 64, kernel_size: 7, stride: 2, padding: 3); - maxpool1 = MaxPool2d(kernelSize: 3, stride: 2, ceilMode: true); + maxpool1 = MaxPool2d(kernel_size: 3, stride: 2, ceil_mode: true); conv2 = conv_block(64, 64, kernel_size: 1); conv3 = conv_block(64, 192, kernel_size: 3, padding: 1); - maxpool2 = MaxPool2d(kernelSize: 3, stride: 2, ceilMode: true); + maxpool2 = MaxPool2d(kernel_size: 3, stride: 2, ceil_mode: true); inception3a = inception_block(192, 64, 96, 128, 16, 32, 32); inception3b = inception_block(256, 128, 128, 192, 32, 96, 64); - maxpool3 = nn.MaxPool2d(3, stride: 2, ceilMode: true); + maxpool3 = nn.MaxPool2d(3, stride: 2, ceil_mode: true); inception4a = inception_block(480, 192, 96, 208, 16, 48, 64); inception4b = inception_block(512, 160, 112, 224, 24, 64, 64); inception4c = inception_block(512, 128, 128, 256, 24, 64, 64); inception4d = inception_block(512, 112, 144, 288, 32, 64, 64); inception4e = inception_block(528, 256, 160, 320, 32, 128, 128); - maxpool4 = nn.MaxPool2d(2, stride: 2, ceilMode: true); + maxpool4 = nn.MaxPool2d(2, stride: 2, ceil_mode: true); inception5a = inception_block(832, 256, 160, 320, 32, 128, 128); inception5b = inception_block(832, 384, 192, 384, 48, 128, 128); @@ -280,7 +280,7 @@ public Inception(int in_channels, int ch1x1, int ch3x3red, int ch3x3, int ch5x5r conv_block(ch5x5red, ch5x5, kernel_size: 3, padding: 1) ); branch4 = nn.Sequential( - nn.MaxPool2d(kernelSize: 3, stride: 1, padding: 1, ceilMode: true), + nn.MaxPool2d(kernel_size: 3, stride: 1, padding: 1, ceil_mode: true), conv_block(in_channels, pool_proj, kernel_size: 1) ); RegisterComponents(); diff --git a/src/TorchVision/models/InceptionV3.cs b/src/TorchVision/models/InceptionV3.cs index e7f7791c3..7b68b01f2 100644 --- a/src/TorchVision/models/InceptionV3.cs +++ b/src/TorchVision/models/InceptionV3.cs @@ -119,10 +119,10 @@ public InceptionV3(int numClasses = 1000, Conv2d_1a_3x3 = conv_block(3, 32, kernel_size: 3, stride: 2); Conv2d_2a_3x3 = conv_block(32, 32, kernel_size: 3); Conv2d_2b_3x3 = conv_block(32, 64, kernel_size: 3, padding: 1); - maxpool1 = MaxPool2d(kernelSize: 3, stride: 2); + maxpool1 = MaxPool2d(kernel_size: 3, stride: 2); Conv2d_3b_1x1 = conv_block(64, 80, kernel_size: 1); Conv2d_4a_3x3 = conv_block(80, 192, kernel_size: 3); - maxpool2 = MaxPool2d(kernelSize: 3, stride: 2); + maxpool2 = MaxPool2d(kernel_size: 3, stride: 2); Mixed_5b = inception_a(192, pool_features: 32); Mixed_5c = inception_a(256, pool_features: 64); @@ -292,7 +292,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = branch3x3dbl_3.call(branch3x3dbl); - var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new [] { branch1x1_, branch5x5, branch3x3dbl, branch_pool_ }; @@ -341,7 +341,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = branch3x3dbl_3.call(branch3x3dbl); - var branch_pool = functional.max_pool2d(x, kernelSize: 3, stride: 2); + var branch_pool = functional.max_pool2d(x, kernel_size: 3, stride: 2); var outputs = new[] { branch3x3_, branch3x3dbl, branch_pool }; @@ -425,7 +425,7 @@ public override Tensor forward(Tensor x) branch7x7dbl = branch7x7dbl_4.call(branch7x7dbl); branch7x7dbl = branch7x7dbl_5.call(branch7x7dbl); - var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new[] { branch1x1_, branch7x7, branch7x7dbl, branch_pool_ }; @@ -475,7 +475,7 @@ public override Tensor forward(Tensor x) branch7x7x3 = branch7x7x3_3.call(branch7x7x3); branch7x7x3 = branch7x7x3_4.call(branch7x7x3); - var branch_pool = functional.max_pool2d(x, kernelSize: 3, stride: 2); + var branch_pool = functional.max_pool2d(x, kernel_size: 3, stride: 2); var outputs = new[] { branch3x3, branch7x7x3, branch_pool }; @@ -537,7 +537,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = torch.cat(new[] { branch3x3dbl_3a.call(branch3x3dbl), branch3x3dbl_3b.call(branch3x3dbl) }, 1); - var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new[] { branch1x1_, branch3x3, branch3x3dbl, branch_pool_ }; @@ -575,7 +575,7 @@ public InceptionAux(int in_channels, int num_classes) : base("InceptionAux") public override Tensor forward(Tensor x) { // N x 768 x 17 x 17 - x = functional.avg_pool2d(x, kernelSize: 5, stride: 3); + x = functional.avg_pool2d(x, kernel_size: 5, stride: 3); // N x 768 x 5 x 5 x = conv0.call(x); // N x 128 x 5 x 5 diff --git a/src/TorchVision/models/ResNet.cs b/src/TorchVision/models/ResNet.cs index 654d587c3..91c6fa7c4 100644 --- a/src/TorchVision/models/ResNet.cs +++ b/src/TorchVision/models/ResNet.cs @@ -773,7 +773,7 @@ public ResNet(string name, conv1 = Conv2d(3, in_planes, kernelSize: 7, stride: 2, padding: 3, bias: false); bn1 = norm_layer(in_planes); relu = ReLU(inplace: true); - maxpool = MaxPool2d(kernelSize: 3, stride: 2, padding: 1); + maxpool = MaxPool2d(kernel_size: 3, stride: 2, padding: 1); MakeLayer(layer1, block, expansion, 64, layers[0], 1); MakeLayer(layer2, block, expansion, 128, layers[1], 2, rswd.Item1); diff --git a/src/TorchVision/models/VGG.cs b/src/TorchVision/models/VGG.cs index e79f9ddec..08e6d8a3c 100644 --- a/src/TorchVision/models/VGG.cs +++ b/src/TorchVision/models/VGG.cs @@ -363,7 +363,7 @@ public VGG(string name, for (var i = 0; i < channels.Length; i++) { if (channels[i] == 0) { - layers.Add(MaxPool2d(kernelSize: 2, stride: 2)); + layers.Add(MaxPool2d(kernel_size: 2, stride: 2)); } else { layers.Add(Conv2d(in_channels, channels[i], kernelSize: 3, padding: 1)); if (batch_norm) { diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index db91c1993..355c50baa 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -3461,7 +3461,7 @@ public void AvgPool3DBackwardTensorExplicitDivisor() var ones = torch.ones(new long[] { 4, 2, 2, 2, 2 }, device: device); var kernelSize = new long[] { 2, 2, 2 }; var avg = torch.ones(new long[] { 4, 2, 1, 1, 1 }, device: device); - var res = torch.nn.functional.avg_pool3d_backward(avg, ones, kernelSize, divisorOverride: 6) * 6.0; + var res = torch.nn.functional.avg_pool3d_backward(avg, ones, kernelSize, divisor_override: 6) * 6.0; var ones0000 = ones.cpu()[0, 0, 0, 0, 0].ToSingle(); var res0000 = res.cpu()[0, 0, 0, 0, 0].ToSingle(); diff --git a/test/TorchSharpTest/TestTorchTensorBugs.cs b/test/TorchSharpTest/TestTorchTensorBugs.cs index 7d97371dd..d1e09c2e5 100644 --- a/test/TorchSharpTest/TestTorchTensorBugs.cs +++ b/test/TorchSharpTest/TestTorchTensorBugs.cs @@ -1172,7 +1172,7 @@ public void Validate1089_2d() () => Assert.Equal(expectedShape, functional.max_pool2d(t, new long[] { 2, 2 }).shape) ); - Assert.Equal(expectedShape, functional.max_pool2d_with_indices(t, new long[] { 2, 2 }).output.shape); + Assert.Equal(expectedShape, functional.max_pool2d_with_indices(t, new long[] { 2, 2 }).Values.shape); } [Fact] @@ -1182,7 +1182,7 @@ public void Validate1089_3d() var expectedShape = new long[] { 1, 6, 14, 14, 14 }; Assert.Equal(expectedShape, functional.max_pool3d(t, new long[] { 2, 2, 2 }).shape); - Assert.Equal(expectedShape, functional.max_pool3d_with_indices(t, new long[] { 2, 2, 2 }).output.shape); + Assert.Equal(expectedShape, functional.max_pool3d_with_indices(t, new long[] { 2, 2, 2 }).Values.shape); } [Fact] From 5bcab464c011f6c0020dc9565761dc2d9632778c Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 12 Mar 2024 11:16:24 -0700 Subject: [PATCH 35/47] =?UTF-8?q?Revert=20"Reviewed=20all=20modified=20mod?= =?UTF-8?q?ules=20and=20continued,=20made=20adjustments=20and=20con?= =?UTF-8?q?=E2=80=A6"=20(#17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit cff452a44edd4b088082a0f2fa786f673e4eadee. --- src/Examples/AlexNet.cs | 6 +- src/Examples/MNIST.cs | 2 +- src/Examples/VGG.cs | 2 +- src/FSharp.Examples/AlexNet.fs | 6 +- src/FSharp.Examples/MNIST.fs | 2 +- src/Native/LibTorchSharp/THSConvolution.cpp | 405 ++++++++++++++++++ src/Native/LibTorchSharp/THSNN.cpp | 203 ++++++++- src/Native/LibTorchSharp/THSNN.h | 106 ++++- src/Native/LibTorchSharp/THSNormalization.cpp | 55 +++ src/Native/LibTorchSharp/THSTensor.h | 71 ++- src/Native/LibTorchSharp/THSTensorConv.cpp | 273 ++++-------- src/TorchSharp/NN/Bilinear.cs | 20 +- src/TorchSharp/NN/CosineSimilarity.cs | 21 +- src/TorchSharp/NN/Dropout.cs | 6 + src/TorchSharp/NN/Dropout2d.cs | 4 +- src/TorchSharp/NN/Dropout3d.cs | 4 +- src/TorchSharp/NN/FeatureDropout.cs | 20 +- src/TorchSharp/NN/Flatten.cs | 12 +- src/TorchSharp/NN/Identity.cs | 6 + src/TorchSharp/NN/Linear.cs | 39 +- src/TorchSharp/NN/Normalization/Functional.cs | 10 + src/TorchSharp/NN/Normalization/LayerNorm.cs | 36 +- .../NN/Normalization/LocalResponseNorm.cs | 40 +- src/TorchSharp/NN/Padding/PadBase.cs | 2 +- src/TorchSharp/NN/Padding/ReflectionPad2d.cs | 2 +- src/TorchSharp/NN/Padding/ReflectionPad3d.cs | 2 +- src/TorchSharp/NN/Padding/ReplicationPad2d.cs | 2 +- src/TorchSharp/NN/Padding/ReplicationPad3d.cs | 2 +- src/TorchSharp/NN/PixelShuffle.cs | 45 +- src/TorchSharp/NN/PixelUnshuffle.cs | 43 +- .../NN/Pooling/AdaptiveAvgPool1D.cs | 20 +- .../NN/Pooling/AdaptiveAvgPool2D.cs | 39 +- .../NN/Pooling/AdaptiveAvgPool3D.cs | 40 +- .../NN/Pooling/AdaptiveMaxPool1D.cs | 57 +-- .../NN/Pooling/AdaptiveMaxPool2D.cs | 57 +-- .../NN/Pooling/AdaptiveMaxPool3D.cs | 57 +-- src/TorchSharp/NN/Pooling/AvgPool1D.cs | 46 +- src/TorchSharp/NN/Pooling/AvgPool2D.cs | 132 +++--- src/TorchSharp/NN/Pooling/AvgPool3D.cs | 102 +++-- .../NN/Pooling/FractionalMaxPool2d.cs | 161 +------ .../NN/Pooling/FractionalMaxPool3d.cs | 173 ++------ src/TorchSharp/NN/Pooling/LPPool1d.cs | 60 ++- src/TorchSharp/NN/Pooling/LPPool2d.cs | 72 +--- src/TorchSharp/NN/Pooling/MaxPool1D.cs | 105 +++-- src/TorchSharp/NN/Pooling/MaxPool2D.cs | 214 +++++---- src/TorchSharp/NN/Pooling/MaxPool3D.cs | 117 ++--- src/TorchSharp/NN/Pooling/MaxUnpool1d.cs | 58 +-- src/TorchSharp/NN/Pooling/MaxUnpool2d.cs | 64 ++- src/TorchSharp/NN/Pooling/MaxUnpool3d.cs | 77 ++-- src/TorchSharp/NN/Shuffle/ChannelShuffle.cs | 5 +- src/TorchSharp/NN/Unflatten.cs | 25 +- src/TorchSharp/NN/Unfold.cs | 21 +- src/TorchSharp/NN/Upsample.cs | 107 +++-- src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 182 +++++++- .../PInvoke/LibTorchSharp.THSTensor.cs | 91 ++-- src/TorchVision/Ops/DropBlock.cs | 4 +- src/TorchVision/models/AlexNet.cs | 6 +- src/TorchVision/models/GoogleNet.cs | 10 +- src/TorchVision/models/InceptionV3.cs | 16 +- src/TorchVision/models/ResNet.cs | 2 +- src/TorchVision/models/VGG.cs | 2 +- test/TorchSharpTest/NN.cs | 2 +- test/TorchSharpTest/TestTorchTensorBugs.cs | 4 +- 63 files changed, 2116 insertions(+), 1459 deletions(-) diff --git a/src/Examples/AlexNet.cs b/src/Examples/AlexNet.cs index aa893255e..17b08b7c3 100644 --- a/src/Examples/AlexNet.cs +++ b/src/Examples/AlexNet.cs @@ -19,17 +19,17 @@ public AlexNet(string name, int numClasses, torch.Device device = null) : base(n features = Sequential( ("c1", Conv2d(3, 64, kernelSize: 3, stride: 2, padding: 1)), ("r1", ReLU(inplace: true)), - ("mp1", MaxPool2d(kernel_size: new long[] { 2, 2 })), + ("mp1", MaxPool2d(kernelSize: new long[] { 2, 2 })), ("c2", Conv2d(64, 192, kernelSize: 3, padding: 1)), ("r2", ReLU(inplace: true)), - ("mp2", MaxPool2d(kernel_size: new long[] { 2, 2 })), + ("mp2", MaxPool2d(kernelSize: new long[] { 2, 2 })), ("c3", Conv2d(192, 384, kernelSize: 3, padding: 1)), ("r3", ReLU(inplace: true)), ("c4", Conv2d(384, 256, kernelSize: 3, padding: 1)), ("r4", ReLU(inplace: true)), ("c5", Conv2d(256, 256, kernelSize: 3, padding: 1)), ("r5", ReLU(inplace: true)), - ("mp3", MaxPool2d(kernel_size: new long[] { 2, 2 }))); + ("mp3", MaxPool2d(kernelSize: new long[] { 2, 2 }))); avgPool = AdaptiveAvgPool2d(new long[] { 2, 2 }); diff --git a/src/Examples/MNIST.cs b/src/Examples/MNIST.cs index d3059406a..73c8e69b0 100644 --- a/src/Examples/MNIST.cs +++ b/src/Examples/MNIST.cs @@ -105,7 +105,7 @@ internal class Model : Module // These don't have any parameters, so the only reason to instantiate // them is performance, since they will be used over and over. - private Module pool1 = MaxPool2d(kernel_size: new long[] { 2, 2 }); + private Module pool1 = MaxPool2d(kernelSize: new long[] { 2, 2 }); private Module relu1 = ReLU(); private Module relu2 = ReLU(); diff --git a/src/Examples/VGG.cs b/src/Examples/VGG.cs index 033bf6491..0c12eca4e 100644 --- a/src/Examples/VGG.cs +++ b/src/Examples/VGG.cs @@ -38,7 +38,7 @@ public VGG(string name, int numClasses, Device device = null) : base(name) for (var i = 0; i < channels.Length; i++) { if (channels[i] == 0) { - modules.Add(($"MaxPool2d-{i}a", MaxPool2d(kernel_size: 2, stride: 2))); + modules.Add(($"MaxPool2d-{i}a", MaxPool2d(kernelSize: 2, stride: 2))); } else { modules.Add(($"conv2d-{i}a", Conv2d(in_channels, channels[i], kernelSize: 3, padding: 1))); modules.Add(($"bnrm2d-{i}a", BatchNorm2d(channels[i]))); diff --git a/src/FSharp.Examples/AlexNet.fs b/src/FSharp.Examples/AlexNet.fs index 5604f0923..9a1e3fbe1 100644 --- a/src/FSharp.Examples/AlexNet.fs +++ b/src/FSharp.Examples/AlexNet.fs @@ -49,17 +49,17 @@ type Model(name,device:torch.Device) as this = let features = Sequential(("c1", Conv2d(3L, 64L, kernelSize=3L, stride=2L, padding=1L) :> Module), ("r1", ReLU(inplace=true) :> Module), - ("mp1", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), + ("mp1", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), ("c2", Conv2d(64L, 192L, kernelSize=3L, padding=1L) :> Module), ("r2", ReLU(inplace=true) :> Module), - ("mp2", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), + ("mp2", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), ("c3", Conv2d(192L, 384L, kernelSize=3L, padding=1L) :> Module), ("r3", ReLU(inplace=true) :> Module), ("c4", Conv2d(384L, 256L, kernelSize=3L, padding=1L) :> Module), ("r4", ReLU(inplace=true) :> Module), ("c5", Conv2d(256L, 256L, kernelSize=3L, padding=1L) :> Module), ("r5", ReLU(inplace=true) :> Module), - ("mp3", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), + ("mp3", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), ("avg", AdaptiveAvgPool2d([|2L; 2L|]) :> Module)) let classifier = Sequential(("d1", Dropout() :> Module), diff --git a/src/FSharp.Examples/MNIST.fs b/src/FSharp.Examples/MNIST.fs index 6967ebdc6..d042f6f97 100644 --- a/src/FSharp.Examples/MNIST.fs +++ b/src/FSharp.Examples/MNIST.fs @@ -51,7 +51,7 @@ type Model(name,device:torch.Device) as this = let fc1 = Linear(9216L, 128L) let fc2 = Linear(128L, 10L) - let pool1 = MaxPool2d(kernel_size=[|2L; 2L|]) + let pool1 = MaxPool2d(kernelSize=[|2L; 2L|]) let relu = ReLU() diff --git a/src/Native/LibTorchSharp/THSConvolution.cpp b/src/Native/LibTorchSharp/THSConvolution.cpp index 17120ded9..fb51e4c91 100644 --- a/src/Native/LibTorchSharp/THSConvolution.cpp +++ b/src/Native/LibTorchSharp/THSConvolution.cpp @@ -3,6 +3,411 @@ #include + + +NNModule THSNN_AvgPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, + bool ceil_mode, bool count_include_pad, int64_t divisor_override, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AvgPool1dOptions(at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); + if (stride) + opts = opts.stride(at::ArrayRef(stride, 1)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, 1)); + if (divisor_override > 0) + opts = opts.divisor_override(divisor_override); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AvgPool1d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, + bool ceil_mode, bool count_include_pad, int64_t divisor_override, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AvgPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); + if (stride) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, paddingLength)); + if (divisor_override > 0) + opts = opts.divisor_override(divisor_override); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AvgPool2d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, + bool ceil_mode, bool count_include_pad, int64_t divisor_override, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AvgPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); + if (stride) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, paddingLength)); + if (divisor_override > 0) + opts = opts.divisor_override(divisor_override); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AvgPool3d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AdaptiveAvgPool1d_ctor(const int64_t* kernelSize, const int kernelSizeLength, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AdaptiveAvgPool1dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AdaptiveAvgPool1d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AdaptiveAvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AdaptiveAvgPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AdaptiveAvgPool2d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AdaptiveAvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AdaptiveAvgPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AdaptiveAvgPool3d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AdaptiveMaxPool1d_ctor(const int64_t* kernelSize, const int kernelSizeLength, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AdaptiveMaxPool1dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AdaptiveMaxPool1d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AdaptiveMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AdaptiveMaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AdaptiveMaxPool2d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AdaptiveMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AdaptiveMaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AdaptiveMaxPool3d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_LPPool1d_ctor(double norm_type, const int64_t* kernelSize, const int64_t* stride, const bool ceil_mode, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::LPPool1dOptions(norm_type, at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode); + if (stride) + opts = opts.stride(at::ArrayRef(stride, 1)); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_LPPool1d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_LPPool2d_ctor(double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::LPPool2dOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); + if (stride) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_LPPool2d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_MaxPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, const int64_t* dilation, bool ceil_mode, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::MaxPool1dOptions(at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode); + if (stride) + opts = opts.stride(at::ArrayRef(stride, 1)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, 1)); + if (dilation) + opts = opts.dilation(at::ArrayRef(dilation, 1)); + + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_MaxPool1d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +Tensor THSNN_MaxPool1d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) +{ + std::tuple res; + CATCH(res = (*module)->as()->forward_with_indices(*tensor);); + *indices = ResultTensor(std::get<1>(res)); + return ResultTensor(std::get<0>(res)); +} + +NNModule THSNN_MaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, + const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::MaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); + if (stride) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, paddingLength)); + if (dilation) + opts = opts.dilation(at::ArrayRef(dilation, dilationLength)); + + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_MaxPool2d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +Tensor THSNN_MaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) +{ + std::tuple res; + CATCH(res = (*module)->as()->forward_with_indices(*tensor);); + *indices = ResultTensor(std::get<1>(res)); + return ResultTensor(std::get<0>(res)); +} + +NNModule THSNN_MaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, + const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, + NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::MaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); + if (stride) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, paddingLength)); + if (dilation) + opts = opts.dilation(at::ArrayRef(dilation, dilationLength)); + + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_MaxPool3d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +Tensor THSNN_MaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) +{ + std::tuple res; + CATCH(res = (*module)->as()->forward_with_indices(*tensor);); + *indices = ResultTensor(std::get<1>(res)); + return ResultTensor(std::get<0>(res)); +} + +NNModule THSNN_MaxUnpool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::MaxUnpool1dOptions(at::ArrayRef(kernelSize, 1)); + if (stride) + opts = opts.stride(at::ArrayRef(stride, 1)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, 1)); + + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_MaxUnpool1d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize) +{ + if (outputSize != nullptr) { + std::vector outSize; + outSize.push_back(*outputSize); + + CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); + } + else { + CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); + } +} + +NNModule THSNN_MaxUnpool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::MaxUnpool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + if (stride) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, paddingLength)); + + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_MaxUnpool2d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength) +{ + if (outputSize != nullptr) { + std::vector outSize; + for (auto i = 0L; i < outputSizeLength; i++) { + outSize.push_back(outputSize[i]); + } + + CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); + } + else { + CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); + } +} + +NNModule THSNN_MaxUnpool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::MaxUnpool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + if (stride) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + if (padding) + opts = opts.padding(at::ArrayRef(padding, paddingLength)); + + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_MaxUnpool3d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength) +{ + if (outputSize != nullptr) { + std::vector outSize; + for (auto i = 0L; i < outputSizeLength; i++) { + outSize.push_back(outputSize[i]); + } + + CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); + } + else { + CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); + } +} + + +NNModule THSNN_FractionalMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::FractionalMaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + if (outputSize) + opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); + if (outputRatio) + opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); + + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_FractionalMaxPool2d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +Tensor THSNN_FractionalMaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) +{ + std::tuple res; + CATCH(res = (*module)->as()->forward_with_indices(*tensor);); + *indices = ResultTensor(std::get<1>(res)); + return ResultTensor(std::get<0>(res)); +} + +NNModule THSNN_FractionalMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::FractionalMaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + if (outputSize) + opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); + if (outputRatio) + opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); + + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_FractionalMaxPool3d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +Tensor THSNN_FractionalMaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) +{ + std::tuple res; + CATCH(res = (*module)->as()->forward_with_indices(*tensor);); + *indices = ResultTensor(std::get<1>(res)); + return ResultTensor(std::get<0>(res)); +} + template void ApplyPaddingMode(T& opts, const int64_t padding) { diff --git a/src/Native/LibTorchSharp/THSNN.cpp b/src/Native/LibTorchSharp/THSNN.cpp index d1e6297e0..256db0613 100644 --- a/src/Native/LibTorchSharp/THSNN.cpp +++ b/src/Native/LibTorchSharp/THSNN.cpp @@ -3,6 +3,19 @@ #include + +NNModule THSNN_Identity_ctor(NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + res = create_module(outAsAnyModule); + ); +} + +Tensor THSNN_Identity_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + Tensor THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias) { CATCH_TENSOR(bias == nullptr ? @@ -67,16 +80,113 @@ Tensor THSNN_feature_alpha_dropout(const Tensor input, const double p, bool trai CATCH_TENSOR(torch::nn::functional::feature_alpha_dropout(*input, opts)); } -Tensor THSNN_pixel_shuffle(const Tensor tensor, const int64_t upscale_factor) +NNModule THSNN_Dropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::DropoutOptions(probability).inplace(inplace); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_Dropout_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_AlphaDropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::AlphaDropoutOptions(probability).inplace(inplace); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_AlphaDropout_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_Dropout1d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + // Creating a Dropout2d instance here is done on purpose. There's no torch::nn::Dropout1d + auto opts = torch::nn::Dropout2dOptions(probability).inplace(inplace); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_Dropout1d_forward(const NNModule module, const Tensor tensor) +{ + auto drop1d = (*module)->as(); + CATCH_TENSOR(drop1d->options.inplace() + ? drop1d->forward((*tensor).unsqueeze_(-1)).squeeze_(-1) + : drop1d->forward((*tensor).unsqueeze(-1)).squeeze(-1)); +} + + +NNModule THSNN_Dropout2d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::Dropout2dOptions(probability).inplace(inplace); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_Dropout2d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_Dropout3d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::Dropout3dOptions(probability).inplace(inplace); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_Dropout3d_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_FeatureAlphaDropout_ctor(double probability, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::FeatureAlphaDropoutOptions(probability); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_FeatureAlphaDropout_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_PixelShuffle_ctor(const int64_t upscale_factor, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::PixelShuffleOptions(upscale_factor); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_PixelShuffle_forward(const NNModule module, const Tensor tensor) { - auto opts = torch::nn::functional::PixelShuffleFuncOptions(upscale_factor); - CATCH_TENSOR(torch::nn::functional::pixel_shuffle(*tensor, opts)); + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_PixelUnshuffle_ctor(const int64_t downscale_factor, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::PixelUnshuffleOptions(downscale_factor); + res = create_module(opts, outAsAnyModule); + ); } -Tensor THSNN_pixel_unshuffle(const Tensor tensor, const int64_t downscale_factor) +Tensor THSNN_PixelUnshuffle_forward(const NNModule module, const Tensor tensor) { - auto opts = torch::nn::functional::PixelUnshuffleFuncOptions(downscale_factor); - CATCH_TENSOR(torch::nn::functional::pixel_unshuffle(*tensor, opts)); + CATCH_TENSOR((*module)->as()->forward(*tensor)); } template @@ -111,6 +221,38 @@ void ApplyInterpolateMode(T& opts, const int8_t mode) opts = opts.mode(torch::kArea); } +NNModule THSNN_Upsample_ctor(const int64_t* size, const int size_len, const double* scale_factor, const int scale_factor_len, const int8_t mode, const int8_t align_corners, NNAnyModule* outAsAnyModule) +{ + auto opts = torch::nn::UpsampleOptions(); + // align_corners -- 0=None, 1=true, 2=false + if (align_corners != 0) + opts.align_corners(align_corners == 1); + ApplyUpsampleMode(opts, mode); + + CATCH_RETURN_NNModule( + if (size_len > 0) { + std::vector sizes; + for (int i = 0; i < size_len; ++i) { + sizes.push_back(size[i]); + } + opts.size(sizes); + } + if (scale_factor_len > 0) { + std::vector scales; + for (int i = 0; i < scale_factor_len; ++i) { + scales.push_back(scale_factor[i]); + } + opts.scale_factor(scales); + } + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_Upsample_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + template void ApplyPadMode(T& opts, const int64_t padding) { @@ -533,9 +675,54 @@ Tensor THSNN_TransformerDecoder_forward(const NNModule module, const Tensor tg ); } -Tensor THSNN_cosine_similarity(const Tensor input1, const Tensor input2, int64_t dim, double eps) +NNModule THSNN_Flatten_ctor(const int64_t start_dim, const int64_t end_dim, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::FlattenOptions() + .start_dim(start_dim) + .end_dim(end_dim); + + res = create_module(opts, outAsAnyModule); + ); +} +Tensor THSNN_Flatten_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_Unflatten_ctor(const int64_t dim, const int64_t* shape, const int64_t shape_len, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + std::vector sizes; + for (int64_t i = 0; i < shape_len; ++i) + { + sizes.push_back(shape[i]); + } + auto opts = torch::nn::UnflattenOptions(dim, sizes); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_Unflatten_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +NNModule THSNN_CosineSimilarity_ctor(const int64_t dim, double eps, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::CosineSimilarityOptions() + .dim(dim) + .eps(eps); + + res = create_module(opts, outAsAnyModule); + ); + +} + +Tensor THSNN_CosineSimilarity_forward(const NNModule module, const Tensor input1, const Tensor input2) { - CATCH_TENSOR(torch::nn::functional::cosine_similarity(*input1, *input2, torch::nn::functional::CosineSimilarityFuncOptions().dim(dim).eps(eps))); + CATCH_TENSOR((*module)->as()->forward(*input1, *input2)); } NNModule THSNN_PairwiseDistance_ctor(double p, double eps, bool keep_dim, NNAnyModule* outAsAnyModule) diff --git a/src/Native/LibTorchSharp/THSNN.h b/src/Native/LibTorchSharp/THSNN.h index 94d1400ac..b48ea866a 100644 --- a/src/Native/LibTorchSharp/THSNN.h +++ b/src/Native/LibTorchSharp/THSNN.h @@ -37,6 +37,63 @@ EXPORT_API(void) THSNN_AnyModule_dispose(const NNAnyModule module); EXPORT_API(NNModule) THSNN_custom_module(const char* name, Tensor(*forward)(Tensor), NNAnyModule* outAsAnyModule); +// Pooling + +EXPORT_API(NNModule) THSNN_MaxPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, const int64_t* dilation, bool ceil_mode, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_MaxPool1d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(Tensor) THSNN_MaxPool1d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor *indices); + +EXPORT_API(NNModule) THSNN_MaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_MaxPool2d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(Tensor) THSNN_MaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); + +EXPORT_API(NNModule) THSNN_MaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_MaxPool3d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(Tensor) THSNN_MaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); + +EXPORT_API(NNModule) THSNN_FractionalMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_FractionalMaxPool2d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(Tensor) THSNN_FractionalMaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); + +EXPORT_API(NNModule) THSNN_FractionalMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_FractionalMaxPool3d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(Tensor) THSNN_FractionalMaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); + +EXPORT_API(NNModule) THSNN_MaxUnpool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_MaxUnpool1d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize); + +EXPORT_API(NNModule) THSNN_MaxUnpool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_MaxUnpool2d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength); + +EXPORT_API(NNModule) THSNN_MaxUnpool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_MaxUnpool3d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength); + +EXPORT_API(NNModule) THSNN_AdaptiveAvgPool1d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AdaptiveAvgPool1d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_AdaptiveAvgPool2d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AdaptiveAvgPool2d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_AdaptiveAvgPool3d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AdaptiveAvgPool3d_forward(const NNModule module, const Tensor tensor); + +EXPORT_API(NNModule) THSNN_AdaptiveMaxPool1d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AdaptiveMaxPool1d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_AdaptiveMaxPool2d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AdaptiveMaxPool2d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_AdaptiveMaxPool3d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AdaptiveMaxPool3d_forward(const NNModule module, const Tensor tensor); + +EXPORT_API(NNModule) THSNN_AvgPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AvgPool1d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_AvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AvgPool2d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_AvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AvgPool3d_forward(const NNModule module, const Tensor tensor); + +EXPORT_API(NNModule) THSNN_LPPool1d_ctor(double norm_type, const int64_t* kernelSize, const int64_t* stride, bool ceil_mode, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_LPPool1d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_LPPool2d_ctor(double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, bool ceil_mode, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_LPPool2d_forward(const NNModule module, const Tensor tensor); + // Convolution EXPORT_API(NNModule) THSNN_Conv1d_ctor(const int64_t inputChannel, const int64_t outputChannel, const int64_t kernelSize, const int64_t stride, const int64_t padding, const int64_t dilation, const int64_t paddingMode, const int64_t groups, const bool bias, NNAnyModule* outAsAnyModule); @@ -173,6 +230,16 @@ EXPORT_API(Tensor) THSNN_InstanceNorm1d_get_batches(const NNModule module); EXPORT_API(Tensor) THSNN_InstanceNorm2d_get_batches(const NNModule module); EXPORT_API(Tensor) THSNN_InstanceNorm3d_get_batches(const NNModule module); + + +EXPORT_API(NNModule) THSNN_LayerNorm_ctor(const int64_t* norm_shape, const int64_t norm_shape_len, const double eps, const bool elementwise_affine, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_LayerNorm_forward(const NNModule module, const Tensor tensor); + +EXPORT_API(Tensor) THSNN_LayerNorm_bias(const NNModule module); +EXPORT_API(void) THSNN_LayerNorm_set_bias(const NNModule module, const Tensor bias); +EXPORT_API(Tensor) THSNN_LayerNorm_weight(const NNModule module); +EXPORT_API(void) THSNN_LayerNorm_set_weight(const NNModule module, const Tensor weight); + EXPORT_API(NNModule) THSNN_GroupNorm_ctor(const int64_t num_groups, const int64_t num_channels, const double eps, const bool affine, NNAnyModule* outAsAnyModule); EXPORT_API(Tensor) THSNN_GroupNorm_forward(const NNModule module, const Tensor tensor); @@ -181,6 +248,9 @@ EXPORT_API(void) THSNN_GroupNorm_set_bias(const NNModule module, const Tenso EXPORT_API(Tensor) THSNN_GroupNorm_weight(const NNModule module); EXPORT_API(void) THSNN_GroupNorm_set_weight(const NNModule module, const Tensor weight); +EXPORT_API(NNModule) THSNN_LocalResponseNorm_ctor(const int64_t size, const double alpha, const double beta, const double k, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_LocalResponseNorm_forward(const NNModule module, const Tensor tensor); + EXPORT_API(Tensor) THSNN_batch_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool training, const double momentum, const double eps); EXPORT_API(Tensor) THSNN_group_norm(const Tensor input, int64_t num_groups, const Tensor weight, const Tensor bias, const double eps); EXPORT_API(Tensor) THSNN_instance_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool use_input_stats, const double momentum, const double eps); @@ -188,6 +258,22 @@ EXPORT_API(Tensor) THSNN_layer_norm(const Tensor input, const int64_t* normali EXPORT_API(Tensor) THSNN_local_response_norm(const Tensor input, const int64_t size, const double alpha, const double beta, const double k); // Dropout + +EXPORT_API(NNModule) THSNN_Dropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_Dropout_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_Dropout1d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_Dropout1d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_Dropout2d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_Dropout2d_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_Dropout3d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_Dropout3d_forward(const NNModule module, const Tensor tensor); + +EXPORT_API(NNModule) THSNN_AlphaDropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_AlphaDropout_forward(const NNModule module, const Tensor tensor); + +EXPORT_API(NNModule) THSNN_FeatureAlphaDropout_ctor(double probability, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_FeatureAlphaDropout_forward(const NNModule module, const Tensor tensor); + EXPORT_API(Tensor) THSNN_dropout(const Tensor input, const double p, bool training, bool inplace); EXPORT_API(Tensor) THSNN_dropout2d(const Tensor input, const double p, bool training, bool inplace); EXPORT_API(Tensor) THSNN_dropout3d(const Tensor input, const double p, bool training, bool inplace); @@ -201,13 +287,20 @@ EXPORT_API(Tensor) THSNN_unfold(const Tensor input, const int64_t kernel1, const // Linear +EXPORT_API(NNModule) THSNN_Identity_ctor(NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_Identity_forward(const NNModule module, const Tensor tensor); + EXPORT_API(Tensor) THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias); EXPORT_API(Tensor) THSNN_functional_bilinear(const Tensor input1, const Tensor input2, const Tensor weights, const Tensor bias); // Vision -- Modules -EXPORT_API(Tensor) THSNN_pixel_shuffle(const Tensor tensor, const int64_t upscale_factor); -EXPORT_API(Tensor) THSNN_pixel_unshuffle(const Tensor tensor, const int64_t downscale_fasctor); +EXPORT_API(NNModule) THSNN_PixelShuffle_ctor(const int64_t upscale_factor, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_PixelShuffle_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_PixelUnshuffle_ctor(const int64_t downscale_factor, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_PixelUnshuffle_forward(const NNModule module, const Tensor tensor); +EXPORT_API(NNModule) THSNN_Upsample_ctor(const int64_t* size, const int size_len, const double* scale_factor, const int scale_factor_len, const int8_t mode, const int8_t align_corners, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_Upsample_forward(const NNModule module, const Tensor tensor); // Vision -- Functions @@ -420,7 +513,14 @@ EXPORT_API(void) THSNN_SGD_set_lr(const Optimizer optimizer, const double lr); EXPORT_API(Tensor) THSNN_one_hot(const Tensor self, const int64_t num_classes); -EXPORT_API(Tensor) THSNN_cosine_similarity(const Tensor input1, const Tensor input2, int64_t dim, double eps); +EXPORT_API(NNModule) THSNN_Flatten_ctor(const int64_t start_dim, const int64_t end_dim, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_Flatten_forward(const NNModule module, const Tensor tensor); + +EXPORT_API(NNModule) THSNN_Unflatten_ctor(const int64_t dim, const int64_t* shape, const int64_t shape_len, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_Unflatten_forward(const NNModule module, const Tensor tensor); + +EXPORT_API(NNModule) THSNN_CosineSimilarity_ctor(const int64_t dim, double eps, NNAnyModule* outAsAnyModule); +EXPORT_API(Tensor) THSNN_CosineSimilarity_forward(const NNModule module, const Tensor input1, const Tensor input2); EXPORT_API(NNModule) THSNN_PairwiseDistance_ctor(double p, double eps, bool keep_dim, NNAnyModule* outAsAnyModule); EXPORT_API(Tensor) THSNN_PairwiseDistance_forward(const NNModule module, const Tensor input1, const Tensor input2); diff --git a/src/Native/LibTorchSharp/THSNormalization.cpp b/src/Native/LibTorchSharp/THSNormalization.cpp index c17c4b98e..6d0e6d97e 100644 --- a/src/Native/LibTorchSharp/THSNormalization.cpp +++ b/src/Native/LibTorchSharp/THSNormalization.cpp @@ -145,6 +145,61 @@ Tensor THSNN_InstanceNorm3d_forward(const NNModule module, const Tensor tensor) CATCH_TENSOR((*module)->as()->forward(*tensor)); } +NNModule THSNN_LayerNorm_ctor(const int64_t* norm_shape, const int64_t norm_shape_len, const double eps, const bool elementwise_affine, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + std::vector normalized_shape; + for (int64_t i = 0; i < norm_shape_len; ++i) + { + normalized_shape.push_back(norm_shape[i]); + } + auto opts = torch::nn::LayerNormOptions(normalized_shape).eps(eps).elementwise_affine(elementwise_affine); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_LayerNorm_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + +Tensor THSNN_LayerNorm_bias(const NNModule module) +{ + return get_bias(module); +} + +void THSNN_LayerNorm_set_bias(const NNModule module, const Tensor bias) +{ + set_bias(module, bias); +} + +Tensor THSNN_LayerNorm_weight(const NNModule module) +{ + return get_weight(module); +} + +void THSNN_LayerNorm_set_weight(const NNModule module, const Tensor weight) +{ + set_weight(module, weight); +} + + +NNModule THSNN_LocalResponseNorm_ctor(const int64_t size, const double alpha, const double beta, const double k, NNAnyModule* outAsAnyModule) +{ + CATCH_RETURN_NNModule( + auto opts = torch::nn::LocalResponseNormOptions(size) + .alpha(alpha) + .beta(beta) + .k(k); + res = create_module(opts, outAsAnyModule); + ); +} + +Tensor THSNN_LocalResponseNorm_forward(const NNModule module, const Tensor tensor) +{ + CATCH_TENSOR((*module)->as()->forward(*tensor)); +} + void THSNN_BatchNorm1d_reset_stats(const NNModule module) { CATCH((*module)->as()->reset_running_stats();); diff --git a/src/Native/LibTorchSharp/THSTensor.h b/src/Native/LibTorchSharp/THSTensor.h index f391075f4..6af55912b 100644 --- a/src/Native/LibTorchSharp/THSTensor.h +++ b/src/Native/LibTorchSharp/THSTensor.h @@ -23,20 +23,6 @@ EXPORT_API(Tensor) THSTensor_adaptive_avg_pool3d(const Tensor tensor, const int6 EXPORT_API(Tensor) THSTensor_adaptive_avg_pool3d_backward_out(const Tensor grad_input, const Tensor grad_output, const Tensor tensor); -EXPORT_API(Tensor) THSTensor_adaptive_max_pool1d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); - -EXPORT_API(Tensor) THSTensor_adaptive_max_pool2d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); - -EXPORT_API(Tensor) THSTensor_adaptive_max_pool3d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); - -EXPORT_API(Tensor) THSTensor_fractional_max_pool2d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices); - -EXPORT_API(Tensor) THSTensor_fractional_max_pool3d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices); - -EXPORT_API(Tensor) THSTensor_lp_pool1d(const Tensor tensor, const double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode); - -EXPORT_API(Tensor) THSTensor_lp_pool2d(const Tensor tensor, const double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode); - EXPORT_API(Tensor) THSTensor_add(const Tensor left, const Tensor right, const Scalar alpha); EXPORT_API(void) THSTensor_add_(const Tensor left, const Tensor right, const Scalar alpha); @@ -153,8 +139,7 @@ EXPORT_API(Tensor) THSTensor_avg_pool2d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad, - const int64_t divisor_override); + bool count_include_pad); EXPORT_API(Tensor) THSTensor_avg_pool2d_backward( const Tensor grad_output, @@ -172,8 +157,7 @@ EXPORT_API(Tensor) THSTensor_avg_pool3d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad, - const int64_t divisor_override); + bool count_include_pad); EXPORT_API(Tensor) THSTensor_avg_pool3d_backward( const Tensor grad_output, @@ -808,53 +792,68 @@ EXPORT_API(void) THSTensor_max_along_dimension(const Tensor tensor, Tensor* (*al EXPORT_API(Tensor) THSTensor_max_elementwise(const Tensor tensor, const Tensor other); -EXPORT_API(Tensor) THSTensor_max_pool1d_with_indices( +EXPORT_API(Tensor) THSTensor_max_pool1d( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode, Tensor *indices); + bool ceil_mode); -EXPORT_API(Tensor) THSTensor_max_pool2d_with_indices( +EXPORT_API(Tensor) THSTensor_max_pool2d( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode, Tensor* indices); + bool ceil_mode); -EXPORT_API(Tensor) THSTensor_max_pool3d_with_indices( +EXPORT_API(Tensor) THSTensor_max_pool3d( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode, Tensor* indices); + bool ceil_mode); -EXPORT_API(Tensor) THSTensor_max_unpool1d( +EXPORT_API(void) THSTensor_max_pool1d_with_indices( const Tensor tensor, - const Tensor indices, + Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* outputSize, const int outputSizeLength, + const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, - const int64_t* stride, const int strideLength); + const int64_t* dilation, const int dilationLength, + bool ceil_mode); -EXPORT_API(Tensor) THSTensor_max_unpool2d( +EXPORT_API(void) THSTensor_max_pool2d_with_indices( const Tensor tensor, - const Tensor indices, + Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* outputSize, const int outputSizeLength, + const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, - const int64_t* stride, const int strideLength); + const int64_t* dilation, const int dilationLength, + bool ceil_mode); -EXPORT_API(Tensor) THSTensor_max_unpool3d( +EXPORT_API(void) THSTensor_max_pool3d_with_indices( const Tensor tensor, - const Tensor indices, + Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* outputSize, const int outputSizeLength, + const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, - const int64_t* stride, const int strideLength); + const int64_t* dilation, const int dilationLength, + bool ceil_mode); + +EXPORT_API(Tensor) THSTensor_maxunpool2d( + const Tensor tensor, + const Tensor indices, + const int64_t* outputSize, const int outputSizeLength); + +EXPORT_API(Tensor) THSTensor_maxunpool3d( + const Tensor tensor, + const Tensor indices, + const int64_t* outputSize, const int outputSizeLength, + const int64_t* stride, const int strideLength, + const int64_t* padding, const int paddingLength); EXPORT_API(Tensor) THSTensor_mean(const Tensor tensor); diff --git a/src/Native/LibTorchSharp/THSTensorConv.cpp b/src/Native/LibTorchSharp/THSTensorConv.cpp index 2783371e5..10daa3e72 100644 --- a/src/Native/LibTorchSharp/THSTensorConv.cpp +++ b/src/Native/LibTorchSharp/THSTensorConv.cpp @@ -44,110 +44,6 @@ Tensor THSTensor_adaptive_avg_pool3d_backward_out( *tensor)); } -Tensor THSTensor_adaptive_max_pool1d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor *indices) -{ - Tensor output = nullptr; - *indices = nullptr; - CATCH( - auto result = torch::adaptive_max_pool1d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); - output = new torch::Tensor(std::get<0>(result)); - *indices = new torch::Tensor(std::get<1>(result)); - ); - return output; -} - -Tensor THSTensor_adaptive_max_pool2d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices) -{ - Tensor output = nullptr; - *indices = nullptr; - CATCH( - auto result = torch::adaptive_max_pool2d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); - output = new torch::Tensor(std::get<0>(result)); - *indices = new torch::Tensor(std::get<1>(result)); - ); - return output; -} - -Tensor THSTensor_adaptive_max_pool3d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices) -{ - Tensor output = nullptr; - *indices = nullptr; - CATCH( - auto result = torch::adaptive_max_pool3d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); - output = new torch::Tensor(std::get<0>(result)); - *indices = new torch::Tensor(std::get<1>(result)); - ); - return output; -} - -Tensor THSTensor_fractional_max_pool2d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices) -{ - Tensor output = nullptr; - *indices = nullptr; - auto opts = torch::nn::functional::FractionalMaxPool2dFuncOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (outputSizeLength > 0) - opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); - if (outputRatioLength > 0) - opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); - - CATCH( - auto result = torch::nn::functional::fractional_max_pool2d_with_indices(*tensor, opts); - output = new torch::Tensor(std::get<0>(result)); - *indices = new torch::Tensor(std::get<1>(result)); - ); - return output; -} - -Tensor THSTensor_fractional_max_pool3d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices) -{ - Tensor output = nullptr; - *indices = nullptr; - auto opts = torch::nn::functional::FractionalMaxPool3dFuncOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (outputSizeLength > 0) - opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); - if (outputRatioLength > 0) - opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); - - CATCH( - auto result = torch::nn::functional::fractional_max_pool3d_with_indices(*tensor, opts); - output = new torch::Tensor(std::get<0>(result)); - *indices = new torch::Tensor(std::get<1>(result)); - ); - return output; -} - -Tensor THSTensor_lp_pool1d( - const Tensor tensor, - const double norm_type, - const int64_t* kernelSize, - const int kernelSizeLength, - const int64_t* stride, - const int strideLength, - const bool ceil_mode) -{ - auto opts = torch::nn::functional::LPPool1dFuncOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); - if (strideLength > 0) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - opts.ceil_mode(); - CATCH_TENSOR(torch::nn::functional::lp_pool1d(*tensor, opts)); -} - -Tensor THSTensor_lp_pool2d( - const Tensor tensor, - const double norm_type, - const int64_t* kernelSize, - const int kernelSizeLength, - const int64_t* stride, - const int strideLength, - const bool ceil_mode) -{ - auto opts = torch::nn::functional::LPPool2dFuncOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); - if (strideLength > 0) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - opts.ceil_mode(); - CATCH_TENSOR(torch::nn::functional::lp_pool2d(*tensor, opts)); -} - Tensor THSTensor_avg_pool1d( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, @@ -171,8 +67,7 @@ Tensor THSTensor_avg_pool2d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad, - const int64_t divisor_override) + bool count_include_pad) { CATCH_TENSOR(torch::avg_pool2d( *tensor, @@ -180,8 +75,7 @@ Tensor THSTensor_avg_pool2d( at::ArrayRef(stride, strideLength), at::ArrayRef(padding, paddingLength), ceil_mode, - count_include_pad, - (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); + count_include_pad)); } Tensor THSTensor_avg_pool2d_backward( @@ -202,7 +96,7 @@ Tensor THSTensor_avg_pool2d_backward( at::ArrayRef(padding, paddingLength), ceil_mode, count_include_pad, - (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); + (divisor_override == 0 ? c10::optional() : c10::optional(divisor_override)))); } Tensor THSTensor_avg_pool3d( @@ -211,8 +105,7 @@ Tensor THSTensor_avg_pool3d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad, - const int64_t divisor_override) + bool count_include_pad) { CATCH_TENSOR(torch::avg_pool3d( *tensor, @@ -220,8 +113,7 @@ Tensor THSTensor_avg_pool3d( at::ArrayRef(stride, strideLength), at::ArrayRef(padding, paddingLength), ceil_mode, - count_include_pad, - (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); + count_include_pad)); } Tensor THSTensor_avg_pool3d_backward( @@ -340,16 +232,33 @@ Tensor THSTensor_conv3d( groups)); } -Tensor THSTensor_max_pool1d_with_indices( + +Tensor THSTensor_max_pool1d( + const Tensor tensor, + const int64_t* kernelSize, const int kernelSizeLength, + const int64_t* stride, const int strideLength, + const int64_t* padding, const int paddingLength, + const int64_t* dilation, const int dilationLength, + bool ceil_mode) +{ + CATCH_TENSOR(torch::max_pool1d( + *tensor, + at::ArrayRef(kernelSize, kernelSizeLength), + at::ArrayRef(stride, strideLength), + at::ArrayRef(padding, paddingLength), + at::ArrayRef(dilation, dilationLength), + ceil_mode)); +} + +void THSTensor_max_pool1d_with_indices( const Tensor tensor, + Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode, Tensor *indices) + bool ceil_mode) { - Tensor output = nullptr; - *indices = nullptr; CATCH( auto res = torch::max_pool1d_with_indices( *tensor, @@ -359,22 +268,38 @@ Tensor THSTensor_max_pool1d_with_indices( at::ArrayRef(dilation, dilationLength), ceil_mode); - output = new torch::Tensor(std::get<0>(res)); - *indices = new torch::Tensor(std::get<1>(res)); + Tensor * result = allocator(2); + result[0] = new torch::Tensor(std::get<0>(res)); + result[1] = new torch::Tensor(std::get<1>(res)); ) - return output; } -Tensor THSTensor_max_pool2d_with_indices( +Tensor THSTensor_max_pool2d( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode, Tensor* indices) + bool ceil_mode) +{ + CATCH_TENSOR(torch::max_pool2d( + *tensor, + at::ArrayRef(kernelSize, kernelSizeLength), + at::ArrayRef(stride, strideLength), + at::ArrayRef(padding, paddingLength), + at::ArrayRef(dilation, dilationLength), + ceil_mode)); +} + +void THSTensor_max_pool2d_with_indices( + const Tensor tensor, + Tensor* (*allocator)(size_t length), + const int64_t* kernelSize, const int kernelSizeLength, + const int64_t* stride, const int strideLength, + const int64_t* padding, const int paddingLength, + const int64_t* dilation, const int dilationLength, + bool ceil_mode) { - Tensor output = nullptr; - *indices = nullptr; CATCH( auto res = torch::max_pool2d_with_indices( *tensor, @@ -383,22 +308,38 @@ Tensor THSTensor_max_pool2d_with_indices( at::ArrayRef(padding, paddingLength), at::ArrayRef(dilation, dilationLength), ceil_mode); - output = new torch::Tensor(std::get<0>(res)); - *indices = new torch::Tensor(std::get<1>(res)); + Tensor * result = allocator(2); + result[0] = new torch::Tensor(std::get<0>(res)); + result[1] = new torch::Tensor(std::get<1>(res)); ) - return output; } -Tensor THSTensor_max_pool3d_with_indices( +Tensor THSTensor_max_pool3d( + const Tensor tensor, + const int64_t* kernelSize, const int kernelSizeLength, + const int64_t* stride, const int strideLength, + const int64_t* padding, const int paddingLength, + const int64_t* dilation, const int dilationLength, + bool ceil_mode) +{ + CATCH_TENSOR(torch::max_pool3d( + *tensor, + at::ArrayRef(kernelSize, kernelSizeLength), + at::ArrayRef(stride, strideLength), + at::ArrayRef(padding, paddingLength), + at::ArrayRef(dilation, dilationLength), + ceil_mode)); +} + +void THSTensor_max_pool3d_with_indices( const Tensor tensor, + Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode, Tensor* indices) + bool ceil_mode) { - Tensor output = nullptr; - *indices = nullptr; CATCH( auto res = torch::max_pool3d_with_indices( *tensor, @@ -407,70 +348,36 @@ Tensor THSTensor_max_pool3d_with_indices( at::ArrayRef(padding, paddingLength), at::ArrayRef(dilation, dilationLength), ceil_mode); - output = new torch::Tensor(std::get<0>(res)); - *indices = new torch::Tensor(std::get<1>(res)); + Tensor * result = allocator(2); + result[0] = new torch::Tensor(std::get<0>(res)); + result[1] = new torch::Tensor(std::get<1>(res)); ) - return output; } -Tensor THSTensor_max_unpool1d( +Tensor THSTensor_maxunpool2d( const Tensor tensor, const Tensor indices, - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* outputSize, const int outputSizeLength, - const int64_t* padding, const int paddingLength, - const int64_t* stride, const int strideLength) -{ - - auto opts = torch::nn::functional::MaxUnpool1dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); - if (outputSizeLength > 0) - opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); - if (paddingLength > 0) - opts = opts.padding(at::IntArrayRef(padding, paddingLength)); - if (paddingLength > 0) - opts = opts.stride(at::IntArrayRef(stride, strideLength)); - - CATCH_TENSOR(torch::nn::functional::max_unpool1d(*tensor, *indices, opts)); -} - - -Tensor THSTensor_max_unpool2d( - const Tensor tensor, - const Tensor indices, - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* outputSize, const int outputSizeLength, - const int64_t* padding, const int paddingLength, - const int64_t* stride, const int strideLength) + const int64_t* outputSize, const int outputSizeLength) { - - auto opts = torch::nn::functional::MaxUnpool2dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); - if (outputSizeLength > 0) - opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); - if (paddingLength > 0) - opts = opts.padding(at::IntArrayRef(padding, paddingLength)); - if (paddingLength > 0) - opts = opts.stride(at::IntArrayRef(stride, strideLength)); - - CATCH_TENSOR(torch::nn::functional::max_unpool2d(*tensor, *indices, opts)); + CATCH_TENSOR(torch::max_unpool2d( + *tensor, + *indices, + at::ArrayRef(outputSize, outputSizeLength))); } -Tensor THSTensor_max_unpool3d( +Tensor THSTensor_maxunpool3d( const Tensor tensor, const Tensor indices, - const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, - const int64_t* padding, const int paddingLength, - const int64_t* stride, const int strideLength) + const int64_t* stride, const int strideLength, + const int64_t* padding, const int paddingLength) { - auto opts = torch::nn::functional::MaxUnpool3dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); - if (outputSizeLength > 0) - opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); - if (paddingLength > 0) - opts = opts.padding(at::IntArrayRef(padding, paddingLength)); - if (paddingLength > 0) - opts = opts.stride(at::IntArrayRef(stride, strideLength)); - - CATCH_TENSOR(torch::nn::functional::max_unpool3d(*tensor, *indices, opts)); + CATCH_TENSOR(torch::max_unpool3d( + *tensor, + *indices, + at::ArrayRef(outputSize, outputSizeLength), + at::ArrayRef(stride, strideLength), + at::ArrayRef(padding, paddingLength))); } diff --git a/src/TorchSharp/NN/Bilinear.cs b/src/TorchSharp/NN/Bilinear.cs index 8d281fc8c..5d37010e1 100644 --- a/src/TorchSharp/NN/Bilinear.cs +++ b/src/TorchSharp/NN/Bilinear.cs @@ -14,15 +14,8 @@ namespace Modules { public sealed class Bilinear : Module { - const string WeightComponentName = nameof(weight); - const string BiasComponentName = nameof(bias); - internal Bilinear(long in1_features, long in2_features, long out_features, bool hasBias = true, Device? device = null, ScalarType? dtype = null) : base(nameof(Bilinear)) { - this.in1_features = in1_features; - this.in2_features = in2_features; - this.out_features = out_features; - weight = torch.empty(out_features, in1_features, in2_features, device: device, dtype: dtype).AsParameter(); var bound = 1 / Math.Sqrt(weight!.shape[1]); @@ -30,6 +23,7 @@ internal Bilinear(long in1_features, long in2_features, long out_features, bool if (hasBias) { bias = torch.empty(out_features, device: device, dtype: dtype).AsParameter(); + var (fanIn, _) = init.CalculateFanInAndFanOut(weight); init.uniform_(_bias, -bound, bound); } //NOTE: it's important not to call 'RegisterComponents' here. @@ -53,7 +47,7 @@ public Parameter? bias { set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(BiasComponentName, _bias); + ConditionallyRegisterParameter(nameof(bias), _bias); } } @@ -64,19 +58,15 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(WeightComponentName, _weight); + ConditionallyRegisterParameter(nameof(weight), _weight); } } } - [ComponentName(Name = BiasComponentName)] + [ComponentName(Name = "bias")] private Parameter? _bias; - [ComponentName(Name = WeightComponentName)] + [ComponentName(Name = "weight")] private Parameter? _weight; - - public long in1_features { get; set; } - public long in2_features { get; set; } - public long out_features { get; set; } } } diff --git a/src/TorchSharp/NN/CosineSimilarity.cs b/src/TorchSharp/NN/CosineSimilarity.cs index eab4e964e..44399a1f2 100644 --- a/src/TorchSharp/NN/CosineSimilarity.cs +++ b/src/TorchSharp/NN/CosineSimilarity.cs @@ -14,19 +14,16 @@ namespace Modules /// public sealed class CosineSimilarity : ParamLessModule { - internal CosineSimilarity(long dim = 1, double eps = 1e-8) : base(nameof(CosineSimilarity)) + internal CosineSimilarity(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.dim = dim; - this.eps = eps; } public override Tensor forward(Tensor input1, Tensor input2) { - return torch.nn.functional.cosine_similarity(input1, input2, this.dim, this.eps); + var res = THSNN_CosineSimilarity_forward(handle, input1.Handle, input2.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long dim { get; set; } - public double eps { get; set; } } } @@ -42,7 +39,9 @@ public static partial class nn /// public static CosineSimilarity CosineSimilarity(long dim = 1, double eps = 1e-8) { - return new CosineSimilarity(dim, eps); + var handle = THSNN_CosineSimilarity_ctor(dim, eps, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new CosineSimilarity(handle, boxedHandle); } public static partial class functional @@ -57,9 +56,9 @@ public static partial class functional /// public static Tensor cosine_similarity(Tensor x1, Tensor x2, long dim = 1, double eps = 1e-8) { - var res = THSNN_cosine_similarity(x1.Handle, x2.Handle, dim, eps); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + using (var f = nn.CosineSimilarity(dim, eps)) { + return f.call(x1, x2); + } } } } diff --git a/src/TorchSharp/NN/Dropout.cs b/src/TorchSharp/NN/Dropout.cs index b8e351a80..675286a5f 100644 --- a/src/TorchSharp/NN/Dropout.cs +++ b/src/TorchSharp/NN/Dropout.cs @@ -30,6 +30,12 @@ public override Tensor forward(Tensor tensor) return torch.nn.functional.dropout(tensor, this.p, this.training, this.inplace); } + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace { get; set; } public double p { get; set;} } diff --git a/src/TorchSharp/NN/Dropout2d.cs b/src/TorchSharp/NN/Dropout2d.cs index 9005c745a..0f3989ba2 100644 --- a/src/TorchSharp/NN/Dropout2d.cs +++ b/src/TorchSharp/NN/Dropout2d.cs @@ -22,7 +22,9 @@ internal Dropout2d(double p = 0.5, bool inplace = false) : base(nameof(Dropout2d public override Tensor forward(Tensor input) { - return torch.nn.functional.dropout2d(input, this.p, this.training, this.inplace); + var res = THSNN_dropout2d(input.Handle, p, this.training, inplace); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } public bool inplace { get; set; } diff --git a/src/TorchSharp/NN/Dropout3d.cs b/src/TorchSharp/NN/Dropout3d.cs index 4f447a149..2d4fe88e8 100644 --- a/src/TorchSharp/NN/Dropout3d.cs +++ b/src/TorchSharp/NN/Dropout3d.cs @@ -22,7 +22,9 @@ internal Dropout3d(double p = 0.5, bool inplace = false) : base(nameof(Dropout3d public override Tensor forward(Tensor input) { - return torch.nn.functional.dropout3d(input, this.p, this.training, this.inplace); + var res = THSNN_dropout3d(input.Handle, p, this.training, inplace); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } public bool inplace { get; set; } diff --git a/src/TorchSharp/NN/FeatureDropout.cs b/src/TorchSharp/NN/FeatureDropout.cs index 16712c2ab..2ea7b45c6 100644 --- a/src/TorchSharp/NN/FeatureDropout.cs +++ b/src/TorchSharp/NN/FeatureDropout.cs @@ -14,19 +14,16 @@ namespace Modules /// public sealed class FeatureAlphaDropout : ParamLessModule { - internal FeatureAlphaDropout(double p = 0.5, bool inplace = false) : base(nameof(FeatureAlphaDropout)) + internal FeatureAlphaDropout(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.p = p; - this.inplace = inplace; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.feature_alpha_dropout(input, this.p, this.training, this.inplace); + var res = THSNN_FeatureAlphaDropout_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public bool inplace { get; set; } - public double p { get; set; } } } @@ -41,10 +38,11 @@ public static partial class nn /// randomized on every forward call, and scaled and shifted to maintain zero mean and unit variance. /// /// Dropout probability of a channel to be zeroed. Default: 0.5 - /// If set to true, will do this operation in-place. Default: false - public static FeatureAlphaDropout FeatureAlphaDropout(double p = 0.5, bool inplace = false) + public static FeatureAlphaDropout FeatureAlphaDropout(double p = 0.5) { - return new FeatureAlphaDropout(p, inplace); + var handle = THSNN_FeatureAlphaDropout_ctor(p, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new FeatureAlphaDropout(handle, boxedHandle); } public static partial class functional diff --git a/src/TorchSharp/NN/Flatten.cs b/src/TorchSharp/NN/Flatten.cs index 1301870b1..80093d294 100644 --- a/src/TorchSharp/NN/Flatten.cs +++ b/src/TorchSharp/NN/Flatten.cs @@ -20,13 +20,19 @@ internal Flatten(long start_dim = 1, long end_dim = -1) : base(nameof(Flatten)) this.end_dim = end_dim; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return input.flatten(start_dim, end_dim); + return tensor.flatten(start_dim, end_dim); } - public long start_dim { get; set; } + public long start_dim {get; set;} public long end_dim { get; set; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Identity.cs b/src/TorchSharp/NN/Identity.cs index fd0c26760..97bd68098 100644 --- a/src/TorchSharp/NN/Identity.cs +++ b/src/TorchSharp/NN/Identity.cs @@ -18,6 +18,12 @@ public override Tensor forward(Tensor tensor) { return tensor.alias(); } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Linear.cs b/src/TorchSharp/NN/Linear.cs index e893ff115..c2776fd5b 100644 --- a/src/TorchSharp/NN/Linear.cs +++ b/src/TorchSharp/NN/Linear.cs @@ -14,14 +14,8 @@ namespace Modules { public sealed class Linear : torch.nn.Module { - const string WeightComponentName = nameof(weight); - const string BiasComponentName = nameof(bias); - internal Linear(long inputSize, long outputSize, bool hasBias = true, Device? device = null, ScalarType? dtype = null) : base(nameof(Linear)) { - this.in_features = inputSize; - this.out_features = outputSize; - weight = torch.empty(outputSize, inputSize, device: device, dtype: dtype).AsParameter(); init.kaiming_uniform_(weight, a: _sqrt5); @@ -52,7 +46,7 @@ public Parameter? bias { set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(BiasComponentName, _bias); + ConditionallyRegisterParameter(nameof(bias), _bias); } } @@ -63,19 +57,36 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(WeightComponentName, _weight); + ConditionallyRegisterParameter(nameof(weight), _weight); } } } - [ComponentName(Name = BiasComponentName)] - private Parameter? _bias; - [ComponentName(Name = WeightComponentName)] - private Parameter? _weight; + protected internal override nn.Module _to(Device device, ScalarType dtype) + { + weight = new Parameter(_weight!.to(dtype, device)); + if (bias is not null) bias = new Parameter(_bias!.to(dtype, device)); + return this; + } - public int in_features { get; set; } - public int out_features { get; set; } + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) + { + weight = new Parameter(_weight!.to(deviceType, deviceIndex)); + if (bias is not null) bias = new Parameter(_bias!.to(deviceType, deviceIndex)); + return this; + } + + protected internal override nn.Module _to(ScalarType dtype) + { + weight = new Parameter(_weight!.to(dtype)); + if (bias is not null) bias = new Parameter(_bias!.to(dtype)); + return this; + } + [ComponentName(Name = "bias")] + private Parameter? _bias; + [ComponentName(Name = "weight")] + private Parameter? _weight; private static readonly double _sqrt5 = Math.Sqrt(5); } } diff --git a/src/TorchSharp/NN/Normalization/Functional.cs b/src/TorchSharp/NN/Normalization/Functional.cs index 2c0848279..2f8bcd1e4 100644 --- a/src/TorchSharp/NN/Normalization/Functional.cs +++ b/src/TorchSharp/NN/Normalization/Functional.cs @@ -84,6 +84,16 @@ public static Tensor layer_norm(Tensor input, long[] normalized_shape, Tensor we return new Tensor(res); } + /// + /// Applies Local Normalization. + /// + public static Tensor local_response_norm(Tensor input, long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) + { + var res = THSNN_local_response_norm(input.Handle, size, alpha, beta, k); + if (res == IntPtr.Zero) + torch.CheckForErrors(); + return new Tensor(res); + } } } } diff --git a/src/TorchSharp/NN/Normalization/LayerNorm.cs b/src/TorchSharp/NN/Normalization/LayerNorm.cs index 7ae96ee71..949cfe4d0 100644 --- a/src/TorchSharp/NN/Normalization/LayerNorm.cs +++ b/src/TorchSharp/NN/Normalization/LayerNorm.cs @@ -18,8 +18,10 @@ namespace Modules /// public sealed class LayerNorm : torch.nn.Module { - const string WeightComponentName = nameof(weight); - const string BiasComponentName = nameof(bias); + public long[] normalized_shape { get; set; } + public double eps { get; set; } + + public bool elementwise_affine { get; set; } internal LayerNorm(long[] normalized_shape, double eps, bool elementwise_affine, bool bias, Device? device, ScalarType? dtype) : base(nameof(LayerNorm)) { @@ -36,10 +38,11 @@ internal LayerNorm(long[] normalized_shape, double eps, bool elementwise_affine, } } - reset_parameters(); + + reset_parameters(elementwise_affine); } - public void reset_parameters() + private void reset_parameters(bool elementwise_affine) { if (elementwise_affine) { @@ -56,19 +59,12 @@ public override Tensor forward(Tensor tensor) return F.layer_norm(tensor, normalized_shape, weight, bias, eps); } - protected override void Dispose(bool disposing) - { - _weight?.Dispose(); - _bias?.Dispose(); - base.Dispose(disposing); - } - public Parameter? bias { get => _bias; set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(BiasComponentName, _bias); + ConditionallyRegisterParameter(nameof(bias), _bias); } } @@ -79,20 +75,22 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(WeightComponentName, _weight); + ConditionallyRegisterParameter(nameof(weight), _weight); } } } - [ComponentName(Name = BiasComponentName)] + [ComponentName(Name = "bias")] private Parameter? _bias; - [ComponentName(Name = WeightComponentName)] + [ComponentName(Name = "weight")] private Parameter? _weight; - - public long[] normalized_shape { get; set; } - public double eps { get; set; } - public bool elementwise_affine { get; set; } + protected override void Dispose(bool disposing) + { + _weight?.Dispose(); + _bias?.Dispose(); + base.Dispose(disposing); + } } } diff --git a/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs b/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs index 6adad3d0c..ba74b2e5e 100644 --- a/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs +++ b/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs @@ -14,23 +14,17 @@ namespace Modules /// public sealed class LocalResponseNorm : ParamLessModule { - internal LocalResponseNorm(long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) : base(nameof(LocalResponseNorm)) + internal LocalResponseNorm(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.size = size; - this.alpha = alpha; - this.beta = beta; - this.k = k; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.local_response_norm(input, this.size, this.alpha, this.beta, this.k); + if (tensor.Dimensions < 3) throw new ArgumentException($"Invalid number of dimensions for LocalResponseNorm argument: {tensor.Dimensions}"); + var res = THSNN_LocalResponseNorm_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long size { get; set; } - public double alpha { get; set; } - public double beta { get; set; } - public double k { get; set; } } } @@ -43,24 +37,10 @@ public static partial class nn /// public static LocalResponseNorm LocalResponseNorm(long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) { - return new LocalResponseNorm(size, alpha, beta, k); - } - - public static partial class functional - { - - /// - /// Applies local response normalization over an input signal. - /// The input signal is composed of several input planes, where channels occupy the second dimension. - /// Applies normalization across channels. - /// - public static Tensor local_response_norm(Tensor input, long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) - { - if (input.Dimensions < 3) throw new ArgumentException($"Invalid number of dimensions for LocalResponseNorm argument: {input.Dimensions}"); - var res = THSNN_local_response_norm(input.Handle, size, alpha, beta, k); - if (res == IntPtr.Zero) - torch.CheckForErrors(); - return new Tensor(res); + unsafe { + var handle = THSNN_LocalResponseNorm_ctor(size, alpha, beta, k, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new LocalResponseNorm(handle, boxedHandle); } } } diff --git a/src/TorchSharp/NN/Padding/PadBase.cs b/src/TorchSharp/NN/Padding/PadBase.cs index 3a10de24c..6ae9bd87e 100644 --- a/src/TorchSharp/NN/Padding/PadBase.cs +++ b/src/TorchSharp/NN/Padding/PadBase.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent the base of all padding-related modules. /// - public abstract class PadBase : ParamLessModule + public class PadBase : ParamLessModule { protected PadBase(string name, PaddingModes mode, double value, params long[] padding) : base(name) { diff --git a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs index f2a505528..1aa15f2e8 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReflectionPad2d : PadBase { - internal ReflectionPad2d(params long[] padding) : base(nameof(ReflectionPad2d), PaddingModes.Reflect, 0, padding) { } + internal ReflectionPad2d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs index d1dbd584b..cf26874ff 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReflectionPad3d : PadBase { - internal ReflectionPad3d(params long[] padding) : base(nameof(ReflectionPad3d), PaddingModes.Reflect, 0, padding) { } + internal ReflectionPad3d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs index 81b25ee27..0bd779b0e 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReplicationPad2d : PadBase { - internal ReplicationPad2d(params long[] padding) : base(nameof(ReplicationPad2d), PaddingModes.Replicate, 0, padding) { } + internal ReplicationPad2d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs index 7eddd4c8c..5a243489e 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReplicationPad3d : PadBase { - internal ReplicationPad3d(params long[] padding) : base(nameof(ReplicationPad3d), PaddingModes.Replicate, 0, padding) { } + internal ReplicationPad3d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } } } diff --git a/src/TorchSharp/NN/PixelShuffle.cs b/src/TorchSharp/NN/PixelShuffle.cs index ddb459a57..e7054be2b 100644 --- a/src/TorchSharp/NN/PixelShuffle.cs +++ b/src/TorchSharp/NN/PixelShuffle.cs @@ -12,24 +12,29 @@ namespace Modules /// /// This class is used to represent a dropout module. /// - public sealed class PixelShuffle : ParamLessModule + public sealed class PixelShuffle : torch.nn.Module { - internal PixelShuffle(long upscale_factor) : base(nameof(PixelShuffle)) - { - this.upscale_factor = upscale_factor; - } + internal PixelShuffle(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } /// /// Forward pass. /// - /// Input tensor + /// Input tensor /// - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.pixel_shuffle(input, this.upscale_factor); + var res = THSNN_PixelShuffle_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long upscale_factor { get; set; } + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } @@ -41,11 +46,13 @@ public static partial class nn /// Rearranges elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an upscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Factor to increase spatial resolution by + /// Factor to increase spatial resolution by /// - public static PixelShuffle PixelShuffle(long upscale_factor) + public static PixelShuffle PixelShuffle(long upscaleFactor) { - return new PixelShuffle(upscale_factor); + var handle = THSNN_PixelShuffle_ctor(upscaleFactor, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new PixelShuffle(handle, boxedHandle); } public static partial class functional @@ -54,15 +61,15 @@ public static partial class functional /// Rearranges elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an upscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Input tensor - /// Factor to increase spatial resolution by + /// Input tensor + /// Factor to increase spatial resolution by /// /// - public static Tensor pixel_shuffle(Tensor input, long upscale_factor) + public static Tensor pixel_shuffle(Tensor x, long upscaleFactor) { - var res = THSNN_pixel_shuffle(input.Handle, upscale_factor); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + using (var d = nn.PixelShuffle(upscaleFactor)) { + return d.call(x); + } } } } diff --git a/src/TorchSharp/NN/PixelUnshuffle.cs b/src/TorchSharp/NN/PixelUnshuffle.cs index 6b4ab8b23..5467ab59b 100644 --- a/src/TorchSharp/NN/PixelUnshuffle.cs +++ b/src/TorchSharp/NN/PixelUnshuffle.cs @@ -12,24 +12,29 @@ namespace Modules /// /// This class is used to represent a dropout module. /// - public sealed class PixelUnshuffle : ParamLessModule + public sealed class PixelUnshuffle : torch.nn.Module { - internal PixelUnshuffle(long downscale_factor) : base(nameof(PixelUnshuffle)) - { - this.downscale_factor = downscale_factor; - } + internal PixelUnshuffle(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } /// /// Forward pass. /// - /// Input tensor + /// Input tensor /// - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.pixel_unshuffle(input, downscale_factor); + var res = THSNN_PixelUnshuffle_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - public long downscale_factor { get; set; } + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + + protected internal override nn.Module _to(ScalarType dtype) => this; } } @@ -41,11 +46,13 @@ public static partial class nn /// /// Reverses the PixelShuffle operation by rearranging elements in a tensor of shape (*, C, H * r, W * r) to a tensor of shape (*, C * r^2, H, W), where r is an downscale factor. /// - /// Factor to increase spatial resolution by + /// Factor to increase spatial resolution by /// - public static PixelUnshuffle PixelUnshuffle(long downscale_factor) + public static PixelUnshuffle PixelUnshuffle(long downscaleFactor) { - return new PixelUnshuffle(downscale_factor); + var handle = THSNN_PixelUnshuffle_ctor(downscaleFactor, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new PixelUnshuffle(handle, boxedHandle); } public static partial class functional @@ -54,15 +61,15 @@ public static partial class functional /// Reverses the PixelShuffle operation by rearranging elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an downscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Input tensor - /// Factor to increase spatial resolution by + /// Input tensor + /// Factor to increase spatial resolution by /// /// - public static Tensor pixel_unshuffle(Tensor input, long downscale_factor) + public static Tensor pixel_unshuffle(Tensor x, long downscaleFactor) { - var res = THSNN_pixel_unshuffle(input.Handle, downscale_factor); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + using (var d = nn.PixelUnshuffle(downscaleFactor)) { + return d.call(x); + } } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs index f1136eaa1..a658fb364 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs @@ -14,17 +14,16 @@ namespace Modules /// public sealed class AdaptiveAvgPool1d : ParamLessModule { - internal AdaptiveAvgPool1d(long output_size) : base(nameof(AdaptiveAvgPool1d)) + internal AdaptiveAvgPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.output_size = output_size; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.adaptive_avg_pool1d(input, this.output_size); + var res = THSNN_AdaptiveAvgPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long output_size { get; set; } } } @@ -36,11 +35,14 @@ public static partial class nn /// Applies a 1D adaptive average pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// the target output size H + /// the target output size H /// - public static unsafe AdaptiveAvgPool1d AdaptiveAvgPool1d(long output_size) + public static unsafe AdaptiveAvgPool1d AdaptiveAvgPool1d(long outputSize) { - return new AdaptiveAvgPool1d(output_size); + long* pkernelSize = stackalloc long[1] { outputSize }; + var handle = THSNN_AdaptiveAvgPool1d_ctor((IntPtr)pkernelSize, 1, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveAvgPool1d(handle, boxedHandle); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs index 04871729f..91c61d096 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs @@ -14,17 +14,16 @@ namespace Modules /// public sealed class AdaptiveAvgPool2d : ParamLessModule { - internal AdaptiveAvgPool2d(long[] output_size) : base(nameof(AdaptiveAvgPool2d)) + internal AdaptiveAvgPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.output_size = output_size; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.adaptive_avg_pool2d(input, this.output_size); + var res = THSNN_AdaptiveAvgPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long[] output_size { get; set; } } } @@ -36,33 +35,43 @@ public static partial class nn /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long[] output_size) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long[] outputSize) { - return new AdaptiveAvgPool2d(output_size); + fixed (long* poutputSize = outputSize) { + var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, outputSize.Length, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveAvgPool2d(handle, boxedHandle); + } } /// /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d((long,long) output_size) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d((long,long) outputSize) { - return new AdaptiveAvgPool2d(new[] { output_size.Item1, output_size.Item2 }); + long* poutputSize = stackalloc long[2] { outputSize.Item1, outputSize.Item2 }; + var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, 2, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveAvgPool2d(handle, boxedHandle); } /// /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long output_size) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long outputSize) { - return new AdaptiveAvgPool2d(new[] { output_size, output_size }); + long* poutputSize = stackalloc long[2] { outputSize, outputSize }; + var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, 2, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveAvgPool2d(handle, boxedHandle); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs index ce37c4f67..f89426962 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs @@ -14,17 +14,16 @@ namespace Modules /// public sealed class AdaptiveAvgPool3d : ParamLessModule { - internal AdaptiveAvgPool3d(long[] output_size) : base(nameof(AdaptiveAvgPool3d)) + internal AdaptiveAvgPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.output_size = output_size; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.adaptive_avg_pool3d(input, this.output_size); + var res = THSNN_AdaptiveAvgPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long[] output_size { get; set; } } } @@ -36,33 +35,44 @@ public static partial class nn /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size of the image of the form D x H x W. + /// The target output size of the image of the form D x H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long[] output_size) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long[] outputSize) { - return new AdaptiveAvgPool3d(output_size); + fixed (long* pkernelSize = outputSize) { + var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveAvgPool3d(handle, boxedHandle); + } } /// /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (D,H,W) of the image of the form D x H x W. + /// The target output size (D,H,W) of the image of the form D x H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d((long, long, long) output_size) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d((long, long, long) outputSize) { - return new AdaptiveAvgPool3d(new[] { output_size.Item1, output_size.Item2, output_size.Item3 }); + long* pkernelSize = stackalloc long[3] { outputSize.Item1, outputSize.Item2, outputSize.Item3 }; + + var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, 3, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveAvgPool3d(handle, boxedHandle); } /// /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (D,H,W) of the image of the form H x W. + /// The target output size (D,H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long output_size) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long outputSize) { - return new AdaptiveAvgPool3d(new [] { output_size, output_size, output_size }); + long* pkernelSize = stackalloc long[3] { outputSize, outputSize, outputSize }; + var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, 3, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveAvgPool3d(handle, boxedHandle); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs index 199aefaa5..5c71475cc 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs @@ -14,22 +14,16 @@ namespace Modules /// public sealed class AdaptiveMaxPool1d : ParamLessModule { - internal AdaptiveMaxPool1d(long output_size) : base(nameof(AdaptiveMaxPool1d)) + internal AdaptiveMaxPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.output_size = output_size; } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.adaptive_max_pool1d_with_indices(input, this.output_size); + var res = THSNN_AdaptiveMaxPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public override Tensor forward(Tensor input) - { - return torch.nn.functional.adaptive_max_pool1d(input, this.output_size); - } - - public long output_size { get; set; } } } @@ -41,11 +35,17 @@ public static partial class nn /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size H. + /// The target output size H. /// - public static AdaptiveMaxPool1d AdaptiveMaxPool1d(long output_size) + public static AdaptiveMaxPool1d AdaptiveMaxPool1d(long outputSize) { - return new AdaptiveMaxPool1d(output_size); + unsafe { + fixed (long* pkernelSize = new long[] { outputSize }) { + var handle = THSNN_AdaptiveMaxPool1d_ctor((IntPtr)pkernelSize, 1, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveMaxPool1d(handle, boxedHandle); + } + } } public static partial class functional @@ -54,32 +54,13 @@ public static partial class functional /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// - /// The target output size H. - /// - public static Tensor adaptive_max_pool1d(Tensor input, long output_size) - { - var ret = adaptive_max_pool1d_with_indices(input, output_size); - ret.Indices.Dispose(); - return ret.Values; - } - - /// - /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. - /// The output size is H, for any input size.The number of output features is equal to the number of input planes. - /// - /// - /// The target output size H. + /// + /// The target output size H. /// - public static (Tensor Values, Tensor Indices) adaptive_max_pool1d_with_indices(Tensor input, long output_size) + public static Tensor adaptive_max_pool1d(Tensor x, long outputSize) { - var outputSizes = new long[] { output_size }; - unsafe { - fixed (long* poutputSize = outputSizes) { - var resOutput = THSTensor_adaptive_max_pool1d(input.Handle, (IntPtr)poutputSize, outputSizes.Length, out var resIndices); - if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(resOutput), new Tensor(resIndices)); - } + using (var d = nn.AdaptiveMaxPool1d(outputSize)) { + return d.call(x); } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs index 8cba5c401..764d29732 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs @@ -14,22 +14,16 @@ namespace Modules /// public sealed class AdaptiveMaxPool2d : ParamLessModule { - internal AdaptiveMaxPool2d(long[] output_size) : base(nameof(AdaptiveMaxPool2d)) + internal AdaptiveMaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.output_size = output_size; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.adaptive_max_pool2d(input, this.output_size); + var res = THSNN_AdaptiveMaxPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public (Tensor output, Tensor indices) forward_with_indices(Tensor input) - { - return torch.nn.functional.adaptive_max_pool2d_with_indices(input, this.output_size); - } - - public long[] output_size { get; set; } } } @@ -41,12 +35,18 @@ public static partial class nn /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - public static AdaptiveMaxPool2d AdaptiveMaxPool2d(long[] output_size) + public static AdaptiveMaxPool2d AdaptiveMaxPool2d(long[] outputSize) { - return new AdaptiveMaxPool2d(output_size); + unsafe { + fixed (long* pkernelSize = outputSize) { + var handle = THSNN_AdaptiveMaxPool2d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveMaxPool2d(handle, boxedHandle); + } + } } public static partial class functional @@ -55,33 +55,14 @@ public static partial class functional /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// - /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. - /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. - /// - public static Tensor adaptive_max_pool2d(Tensor input, long[] output_size) - { - var ret = adaptive_max_pool2d_with_indices(input, output_size); - ret.Indices.Dispose(); - return ret.Values; - } - - /// - /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. - /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. - /// - /// - /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - public static (Tensor Values, Tensor Indices) adaptive_max_pool2d_with_indices(Tensor input, long[] output_size) + public static Tensor adaptive_max_pool2d(Tensor x, long[] outputSize) { - unsafe { - fixed (long* poutputSize = output_size) { - var resOutput = THSTensor_adaptive_max_pool2d(input.Handle, (IntPtr)poutputSize, output_size.Length, out var resIndices); - if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(resOutput), new Tensor(resIndices)); - } + using (var d = nn.AdaptiveMaxPool2d(outputSize)) { + return d.call(x); } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs index e59ce6565..ec3bfc32f 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs @@ -14,22 +14,16 @@ namespace Modules /// public sealed class AdaptiveMaxPool3d : ParamLessModule { - internal AdaptiveMaxPool3d(long[] output_size) : base(nameof(AdaptiveMaxPool3d)) + internal AdaptiveMaxPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.adaptive_max_pool3d(input, output_size); + var res = THSNN_AdaptiveMaxPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public (Tensor output, Tensor indices) forward_with_indices(Tensor input) - { - return torch.nn.functional.adaptive_max_pool3d_with_indices(input, output_size); - } - - - public long[] output_size { get; set; } } } @@ -41,12 +35,18 @@ public static partial class nn /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size of the image of the form D x H x W. + /// The target output size of the image of the form D x H x W. /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. /// - public static AdaptiveMaxPool3d AdaptiveMaxPool3d(long[] output_size) + public static AdaptiveMaxPool3d AdaptiveMaxPool3d(long[] outputSize) { - return new AdaptiveMaxPool3d(output_size); + unsafe { + fixed (long* pkernelSize = outputSize) { + var handle = THSNN_AdaptiveMaxPool3d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AdaptiveMaxPool3d(handle, boxedHandle); + } + } } public static partial class functional @@ -55,33 +55,14 @@ public static partial class functional /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The input tensor - /// The target output size of the image of the form D x H x W. - /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. - /// - public static Tensor adaptive_max_pool3d(Tensor input, long[] output_size) - { - var ret = adaptive_max_pool3d_with_indices(input, output_size); - ret.Indices.Dispose(); - return ret.Values; - } - - /// - /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. - /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. - /// - /// The input tensor - /// The target output size of the image of the form D x H x W. + /// The input tensor + /// The target output size of the image of the form D x H x W. /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. /// - public static (Tensor Values, Tensor Indices) adaptive_max_pool3d_with_indices(Tensor input, long[] output_size) + public static Tensor adaptive_max_pool3d(Tensor x, long[] outputSize) { - unsafe { - fixed (long* poutputSize = output_size) { - var resOutput = THSTensor_adaptive_max_pool1d(input.Handle, (IntPtr)poutputSize, output_size.Length, out var resIndices); - if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(resOutput), new Tensor(resIndices)); - } + using (var d = nn.AdaptiveMaxPool3d(outputSize)) { + return d.call(x); } } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool1D.cs b/src/TorchSharp/NN/Pooling/AvgPool1D.cs index 7dcd374b0..9df33da82 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool1D.cs @@ -14,25 +14,16 @@ namespace Modules /// public sealed class AvgPool1d : ParamLessModule { - internal AvgPool1d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true) : base(nameof(AvgPool1d)) + internal AvgPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; - this.ceil_mode = ceil_mode; - this.count_include_pad = count_include_pad; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.avg_pool1d(input, kernel_size, stride, padding, ceil_mode, count_include_pad); + var res = THSNN_AvgPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long kernel_size { get; set; } - public long? stride { get; set; } - public long? padding { get; set; } - public bool ceil_mode { get; set; } - public bool count_include_pad { get; set; } } } @@ -48,9 +39,32 @@ public static partial class nn /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation - public static AvgPool1d AvgPool1d(long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, bool count_include_pad = true) + /// If specified, it will be used as divisor, otherwise size of the pooling region will be used + public static AvgPool1d AvgPool1d(long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - return new AvgPool1d(kernel_size, stride, padding, ceil_mode, count_include_pad); + return stride.HasValue ? + AvgPool1d(new long[] { kernel_size }, new long[] { stride.Value }, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0) : + AvgPool1d(new long[] { kernel_size }, null, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0); + } + + /// + /// Applies a 1D average pooling over an input signal composed of several input planes. + /// + /// The size of the window + /// The stride of the window. Default value is kernel_size + /// implicit zero padding to be added on both sides + /// Whether to use ceil instead of floor to compute the output shape + /// Whether to include the zero-padding in the averaging calculation + /// If specified, it will be used as divisor, otherwise size of the pooling region will be used + private static AvgPool1d AvgPool1d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + { + unsafe { + fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { + var handle = THSNN_AvgPool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)ppadding, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AvgPool1d(handle, boxedHandle); + } + } } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AvgPool2D.cs b/src/TorchSharp/NN/Pooling/AvgPool2D.cs index f44dfe42c..77fe8d991 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool2D.cs @@ -5,7 +5,6 @@ namespace TorchSharp { - using System.Data; using Modules; namespace Modules @@ -15,27 +14,16 @@ namespace Modules /// public sealed class AvgPool2d : ParamLessModule { - internal AvgPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) : base(nameof(AvgPool2d)) + internal AvgPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; - this.ceil_mode = ceil_mode; - this.count_include_pad = count_include_pad; - this.divisor_override = divisor_override; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.avg_pool2d(input, kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); + var res = THSNN_AvgPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long[] kernel_size { get; set; } - public long[] stride { get; set; } - public long[] padding { get; set; } - public bool ceil_mode { get; set; } - public bool count_include_pad { get; set; } - public long? divisor_override { get; set; } } } @@ -47,14 +35,18 @@ public static partial class nn /// Applies a 2D average pooling over an input signal composed of several input planes. /// /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static AvgPool2d AvgPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static unsafe AvgPool2d AvgPool2d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - return new AvgPool2d(kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); + fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { + var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)ppadding, (padding == null ? 0 : padding.Length), ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AvgPool2d(handle, boxedHandle); + } } /// @@ -68,10 +60,19 @@ public static AvgPool2d AvgPool2d(long[] kernel_size, long[] stride = null, long /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool2d AvgPool2d((long,long) kernel_size, (long,long)? stride = null, (long,long)? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; - long[] strideValue = stride == null ? null : new[] { stride.Value.Item1, stride.Value.Item2 }; - long[] paddingValue = padding == null ? null : new[] { padding.Value.Item1, padding.Value.Item2 }; - return new AvgPool2d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); + long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; + long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; + + long pvalue1 = (padding == null) ? 0 : padding.Value.Item1; + long pvalue2 = (padding == null) ? 0 : padding.Value.Item2; + + long* pkernelSize = stackalloc long[2] { kernel_size.Item1, kernel_size.Item2 }; + long* pstrides = stackalloc long[2] { svalue1, svalue2 }; + long* ppadding = stackalloc long[2] { pvalue1, pvalue2 }; + + var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AvgPool2d(handle, boxedHandle); } /// @@ -83,12 +84,18 @@ public static unsafe AvgPool2d AvgPool2d((long,long) kernel_size, (long,long)? s /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static AvgPool2d AvgPool2d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static unsafe AvgPool2d AvgPool2d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long[] kernelValue = new[] { kernel_size, kernel_size }; - long[] strideValue = stride == null ? null : new[] { stride.Value, stride.Value }; - long[] paddingValue = padding == null ? null : new[] { padding.Value, padding.Value }; - return new AvgPool2d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); + long svalue = (stride == null) ? kernel_size : stride.Value; + long pvalue = (padding == null) ? 0 : padding.Value; + + long* pkernelSize = stackalloc long[2] { kernel_size, kernel_size }; + long* pstrides = stackalloc long[2] { svalue, svalue }; + long* ppadding = stackalloc long[2] { pvalue, pvalue }; + + var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AvgPool2d(handle, boxedHandle); } public static partial class functional @@ -97,32 +104,29 @@ public static partial class functional /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// - /// - /// + /// + /// + /// /// /// - /// /// - public static Tensor avg_pool2d(Tensor input, long[] kernel_size, - long[] stride = null, - long[] padding = null, + public static Tensor avg_pool2d(Tensor input, long[] kernelSizes, + long[] strides = null, + long[] paddings = null, bool ceil_mode = false, - bool count_include_pad = true, - long? divisor_override = null) + bool count_include_pad = true) { - stride = (stride == null) ? kernel_size : stride; - padding = (padding == null) ? new long[] { 0 } : padding; + strides = (strides == null) ? new long[] { 1 } : strides; + paddings = (paddings == null) ? new long[] { 0 } : paddings; unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = stride, ppadding = padding) { + fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { var res = THSTensor_avg_pool2d(input.Handle, - (IntPtr)pkernelSize, kernel_size.Length, - (IntPtr)pstrides, stride.Length, - (IntPtr)ppadding, padding.Length, + (IntPtr)pkernelSize, kernelSizes.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, paddings.Length, ceil_mode, - count_include_pad, - divisor_override ?? 0); + count_include_pad); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -133,23 +137,21 @@ public static Tensor avg_pool2d(Tensor input, long[] kernel_size, /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// + /// /// /// /// /// - /// /// - public static unsafe Tensor avg_pool2d(Tensor input, long kernel_size, + public static unsafe Tensor avg_pool2d(Tensor input, long kernelSize, long? stride = null, long padding = 0, bool ceil_mode = false, - bool count_include_pad = true, - long? divisor_override = null) + bool count_include_pad = true) { - long svalue = (stride == null) ? kernel_size : stride.Value; + long svalue = (stride == null) ? kernelSize : stride.Value; - long* pkernelSize = stackalloc long[2] { kernel_size, kernel_size }; + long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; long* pstrides = stackalloc long[2] { svalue, svalue }; long* ppadding = stackalloc long[2] { padding, padding }; @@ -159,8 +161,7 @@ public static unsafe Tensor avg_pool2d(Tensor input, long kernel_size, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, - count_include_pad, - divisor_override ?? 0); + count_include_pad); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -169,29 +170,27 @@ public static unsafe Tensor avg_pool2d(Tensor input, long kernel_size, /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// + /// /// /// /// /// - /// /// - public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernel_size, + public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernelSize, (long, long)? stride = null, (long, long)? padding = null, bool ceil_mode = false, - bool count_include_pad = true, - long? divisor_override = null) + bool count_include_pad = true) { - long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; - long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; + long svalue1 = (stride == null) ? kernelSize.Item1 : stride.Value.Item1; + long svalue2 = (stride == null) ? kernelSize.Item2 : stride.Value.Item2; long pvalue1 = padding != null ? padding.Value.Item1 : 0; long pvalue2 = padding != null ? padding.Value.Item2 : 0; long* pstrides = stackalloc long[2] { svalue1, svalue2 }; long* ppadding = stackalloc long[2] { pvalue1, pvalue2 }; - long* pkernelSize = stackalloc long[2] { kernel_size.Item1, kernel_size.Item2 }; + long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; var res = THSTensor_avg_pool2d(input.Handle, @@ -199,8 +198,7 @@ public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernel_size, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, - count_include_pad, - divisor_override ?? 0); + count_include_pad); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -211,7 +209,7 @@ public static Tensor avg_pool2d_backward(Tensor input, Tensor originalInput, long[] paddings = null, bool ceil_mode = false, bool count_include_pad = true, - long? divisor_override = null) + long divisorOverride = 0) { strides = (strides == null) ? new long[] { 1 } : strides; paddings = (paddings == null) ? new long[] { 0 } : paddings; @@ -224,7 +222,7 @@ public static Tensor avg_pool2d_backward(Tensor input, Tensor originalInput, (IntPtr)ppadding, paddings.Length, ceil_mode, count_include_pad, - divisor_override ?? 0); + divisorOverride); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/AvgPool3D.cs b/src/TorchSharp/NN/Pooling/AvgPool3D.cs index d08304bdc..bedc81f0a 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool3D.cs @@ -14,27 +14,16 @@ namespace Modules /// public sealed class AvgPool3d : ParamLessModule { - internal AvgPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) : base(nameof(AvgPool3d)) + internal AvgPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; - this.ceil_mode = ceil_mode; - this.count_include_pad = count_include_pad; - this.divisor_override = divisor_override; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.avg_pool3d(input, kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); + var res = THSNN_AvgPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public long[] kernel_size { get; set; } - public long[] stride { get; set; } - public long[] padding { get; set; } - public bool ceil_mode { get; set; } - public bool count_include_pad { get; set; } - public long? divisor_override { get; set; } } } @@ -46,14 +35,20 @@ public static partial class nn /// Applies a 3D average pooling over an input signal composed of several input planes. /// /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static AvgPool3d AvgPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool3d AvgPool3d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - return new AvgPool3d(kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); + unsafe { + fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { + var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)ppadding, (padding == null ? 0 : padding.Length), ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AvgPool3d(handle, boxedHandle); + } + } } /// @@ -67,10 +62,21 @@ public static AvgPool3d AvgPool3d(long[] kernel_size, long[] stride = null, long /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool3d AvgPool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }; - long[] strideValue = stride == null ? null : new[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 }; - long[] paddingValue = padding == null ? null : new[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 }; - return new AvgPool3d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); + long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; + long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; + long svalue3 = (stride == null) ? kernel_size.Item3 : stride.Value.Item3; + + long pvalue1 = (padding == null) ? 0 : padding.Value.Item1; + long pvalue2 = (padding == null) ? 0 : padding.Value.Item2; + long pvalue3 = (padding == null) ? 0 : padding.Value.Item3; + + long* pkernelSize = stackalloc long[3] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }; + long* pstrides = stackalloc long[3] { svalue1, svalue2, svalue3 }; + long* ppadding = stackalloc long[3] { pvalue1, pvalue2, pvalue3 }; + + var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, 3, (IntPtr)pstrides, 3, (IntPtr)ppadding, 3, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AvgPool3d(handle, boxedHandle); } /// @@ -84,10 +90,16 @@ public static unsafe AvgPool3d AvgPool3d((long, long, long) kernel_size, (long, /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool3d AvgPool3d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long[] kernelValue = new[] { kernel_size, kernel_size, kernel_size }; - long[] strideValue = stride == null ? null : new[] { stride.Value, stride.Value, stride.Value }; - long[] paddingValue = padding == null ? null : new[] { padding.Value, padding.Value, padding.Value }; - return new AvgPool3d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); + long svalue = (stride == null) ? kernel_size : stride.Value; + long pvalue = (padding == null) ? 0 : padding.Value; + + long* pkernelSize = stackalloc long[3] { kernel_size, kernel_size, kernel_size }; + long* pstrides = stackalloc long[3] { svalue, svalue, svalue }; + long* ppadding = stackalloc long[3] { pvalue, pvalue, pvalue }; + + var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, 3, (IntPtr)pstrides, 3, (IntPtr)ppadding, 3, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new AvgPool3d(handle, boxedHandle); } public static partial class functional @@ -96,31 +108,29 @@ public static partial class functional /// Applies 3D average-pooling operation in kT x kH x kW regions by step size sT x sH x sW steps. /// /// The input tensor. - /// - /// - /// + /// + /// + /// /// /// - /// /// - public static Tensor avg_pool3d(Tensor input, long[] kernel_size, - long[] stride = null, - long[] padding = null, + public static Tensor avg_pool3d(Tensor input, long[] kernelSizes, + long[] strides = null, + long[] paddings = null, bool ceil_mode = false, - bool count_include_pad = true, - long? divisor_override = null) + bool count_include_pad = true) { - stride = (stride == null) ? kernel_size : stride; - padding = (padding == null) ? new long[] { 0 } : padding; + strides = (strides == null) ? new long[] { 1 } : strides; + paddings = (paddings == null) ? new long[] { 0 } : paddings; unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = stride, ppadding = padding) { + fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { var res = THSTensor_avg_pool3d(input.Handle, - (IntPtr)pkernelSize, kernel_size.Length, - (IntPtr)pstrides, stride.Length, - (IntPtr)ppadding, padding.Length, + (IntPtr)pkernelSize, kernelSizes.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, paddings.Length, ceil_mode, - count_include_pad, divisor_override ?? 0); + count_include_pad); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -133,9 +143,9 @@ public static Tensor avg_pool3d_backward(Tensor input, Tensor originalInput, long[] paddings = null, bool ceil_mode = false, bool count_include_pad = true, - long? divisor_override = null) + long divisorOverride = 0) { - strides = (strides == null) ? kernelSizes : strides; + strides = (strides == null) ? new long[] { 1 } : strides; paddings = (paddings == null) ? new long[] { 0 } : paddings; unsafe { fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { @@ -146,7 +156,7 @@ public static Tensor avg_pool3d_backward(Tensor input, Tensor originalInput, (IntPtr)ppadding, paddings.Length, ceil_mode, count_include_pad, - divisor_override ?? 0); + divisorOverride); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs index e37d17083..eecc1c4a3 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs @@ -5,7 +5,6 @@ namespace TorchSharp { - using System.Data; using Modules; namespace Modules @@ -15,26 +14,23 @@ namespace Modules /// public sealed class FractionalMaxPool2d : ParamLessModule { - internal FractionalMaxPool2d(long[] kernel_size, long[] output_size = null, double[] output_ratio = null) : base(nameof(FractionalMaxPool2d)) + internal FractionalMaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.output_size = output_size; - this.output_ratio = output_ratio; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.fractional_max_pool2d(input, kernel_size, output_size, output_ratio); + var res = THSNN_FractionalMaxPool2d_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) { - return torch.nn.functional.fractional_max_pool2d_with_indices(input, kernel_size, output_size, output_ratio); + var res = THSNN_FractionalMaxPool2d_forward_with_indices(handle, tensor.Handle, out var indices); + if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(res), new Tensor(indices)); } - - public long[] kernel_size { get; set; } - public long[] output_size { get; set; } - public double[] output_ratio { get; set; } } } @@ -99,135 +95,16 @@ public static FractionalMaxPool2d FractionalMaxPool2d(long[] kernel_size, long[] if (output_size != null && output_ratio != null) throw new ArgumentNullException("FractionalMaxPool2d requires specifying either an output size, or a pooling ratio."); - return new FractionalMaxPool2d(kernel_size, output_size, output_ratio); - } - - public static partial class functional - { - /// - /// Applies a 2D fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static Tensor fractional_max_pool2d(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) - { - var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value } : null; - var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value } : null; - return fractional_max_pool2d(input, new long[] { kernel_size, kernel_size }, pSize, pRatio); - } - - /// - /// Applies a 2D fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static Tensor fractional_max_pool2d(Tensor input, (long, long) kernel_size, (long, long)? output_size = null, (double, double)? output_ratio = null) - { - var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2 } : null; - var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2 } : null; - return fractional_max_pool2d(input, new long[] { kernel_size.Item1, kernel_size.Item2 }, pSize, pRatio); - } - - /// - /// Applies a 2D fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static Tensor fractional_max_pool2d(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) - { - var ret = fractional_max_pool2d_with_indices(input, kernel_size, output_size, output_ratio); - ret.Indices.Dispose(); - return ret.Values; - } - - /// - /// Applies a 2D fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) - { - var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value } : null; - var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value } : null; - return fractional_max_pool2d_with_indices(input, new long[] { kernel_size, kernel_size }, pSize, pRatio); - } - - /// - /// Applies a 2D fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, (long, long) kernel_size, (long, long)? output_size = null, (double, double)? output_ratio = null) - { - var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2 } : null; - var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2 } : null; - return fractional_max_pool2d_with_indices(input, new long[] { kernel_size.Item1, kernel_size.Item2 }, pSize, pRatio); - } - - /// - /// Applies a 2D fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) - { - if (kernel_size == null || kernel_size.Length != 2) - throw new ArgumentException("Kernel size must contain two elements."); - if (output_size != null && output_size.Length != 2) - throw new ArgumentException("output_size must contain two elements."); - if (output_ratio != null && output_ratio.Length != 2) - throw new ArgumentException("output_ratio must contain two elements."); - if (output_size == null && output_ratio == null) - throw new ArgumentNullException("Only one of output_size and output_ratio may be specified."); - if (output_size != null && output_ratio != null) - throw new ArgumentNullException("FractionalMaxPool2d requires specifying either an output size, or a pooling ratio."); - - output_size ??= Array.Empty(); - output_ratio ??= Array.Empty(); - - unsafe { - fixed (long* pkernelSize = kernel_size, poutputSize = output_size) { - fixed (double* poutputRatio = output_ratio) { - var resOutput = THSTensor_fractional_max_pool2d(input.Handle, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)poutputRatio, output_ratio.Length, out var resIndices); - if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(resOutput), new Tensor(resIndices)); - } + unsafe { + fixed (long* pkernelSize = kernel_size, pSize = output_size) { + fixed (double* pRatio = output_ratio) { + var handle = THSNN_FractionalMaxPool2d_ctor( + (IntPtr)pkernelSize, kernel_size.Length, + (IntPtr)pSize, (output_size == null ? 0 : output_size.Length), + (IntPtr)pRatio, (output_ratio == null ? 0 : output_ratio.Length), + out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new FractionalMaxPool2d(handle, boxedHandle); } } } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs index 98ac3d0eb..692f2210f 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs @@ -14,26 +14,34 @@ namespace Modules /// public sealed class FractionalMaxPool3d : ParamLessModule { - internal FractionalMaxPool3d(long[] kernel_size, long[] output_size = null, double[] output_ratio = null) : base(nameof(FractionalMaxPool3d)) + internal FractionalMaxPool3d(IntPtr handle, IntPtr boxedHandle, bool ratio) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.output_size = output_size; - this.output_ratio = output_ratio; + _used_ratio = ratio; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.fractional_max_pool3d(input, kernel_size, output_size, output_ratio); + if (_used_ratio && tensor.ndim != 5) + // Not sure why this is the case, but there's an exception in the native runtime + // unless there's both a batch dimension and a channel dimension. + throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); + var res = THSNN_FractionalMaxPool3d_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) { - return torch.nn.functional.fractional_max_pool3d_with_indices(input, kernel_size, output_size, output_ratio); + if (_used_ratio && tensor.ndim != 5) + // Not sure why this is the case, but there's an exception in the native runtime + // unless there's both a batch dimension and a channel dimension. + throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); + var res = THSNN_FractionalMaxPool3d_forward_with_indices(handle, tensor.Handle, out var indices); + if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(res), new Tensor(indices)); } - public long[] kernel_size { get; set; } - public long[] output_size { get; set; } - public double[] output_ratio { get; set; } + private bool _used_ratio = false; } } @@ -98,139 +106,16 @@ public static FractionalMaxPool3d FractionalMaxPool3d(long[] kernel_size, long[] if (output_size != null && output_ratio != null) throw new ArgumentNullException("FractionalMaxPool3d requires specifying either an output size, or a pooling ratio."); - return new FractionalMaxPool3d(kernel_size, output_size, output_ratio); - } - - public static partial class functional - { - /// - /// Applies a 3d fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static Tensor fractional_max_pool3d(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) - { - var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value, output_size.Value } : null; - var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value, output_ratio.Value } : null; - return fractional_max_pool3d(input, new long[] { kernel_size, kernel_size, kernel_size }, pSize, pRatio); - } - - /// - /// Applies a 3d fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static Tensor fractional_max_pool3d(Tensor input, (long, long, long) kernel_size, (long, long, long)? output_size = null, (double, double, double)? output_ratio = null) - { - var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2, output_size.Value.Item3 } : null; - var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2, output_ratio.Value.Item3 } : null; - return fractional_max_pool3d(input, new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pSize, pRatio); - } - - /// - /// Applies a 3d fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static Tensor fractional_max_pool3d(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) - { - var ret = fractional_max_pool3d_with_indices(input, kernel_size, output_size, output_ratio); - ret.Indices.Dispose(); - return ret.Values; - } - - /// - /// Applies a 3d fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) - { - var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value, output_size.Value } : null; - var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value, output_ratio.Value } : null; - return fractional_max_pool3d_with_indices(input, new long[] { kernel_size, kernel_size, kernel_size }, pSize, pRatio); - } - - /// - /// Applies a 3d fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, (long, long, long) kernel_size, (long, long, long)? output_size = null, (double, double, double)? output_ratio = null) - { - var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2, output_size.Value.Item3 } : null; - var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2, output_ratio.Value.Item3 } : null; - return fractional_max_pool3d_with_indices(input, new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pSize, pRatio); - } - - /// - /// Applies a 3d fractional max pooling over an input signal composed of several input planes. - /// - /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, - /// see: https://arxiv.org/abs/1412.6071 - /// - /// The input tensor - /// The size of the sliding window, must be > 0. - /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH - /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) - /// - public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) - { - if (kernel_size == null || kernel_size.Length != 3) - throw new ArgumentException("Kernel size must contain three elements."); - if (output_size != null && output_size.Length != 3) - throw new ArgumentException("output_size must contain three elements."); - if (output_ratio != null && output_ratio.Length != 3) - throw new ArgumentException("output_ratio must contain three elements."); - if (output_size == null && output_ratio == null) - throw new ArgumentNullException("Only one of output_size and output_ratio may be specified."); - if (output_size != null && output_ratio != null) - throw new ArgumentNullException("FractionalMaxPool3d requires specifying either an output size, or a pooling ratio."); - if (output_ratio != null && input.ndim != 5) - // Not sure why this is the case, but there's an exception in the native runtime - // unless there's both a batch dimension and a channel dimension. - throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); - - output_size ??= Array.Empty(); - output_ratio ??= Array.Empty(); - - unsafe { - fixed (long* pkernelSize = kernel_size, poutputSize = output_size) { - fixed (double* poutputRatio = output_ratio) { - var resOutput = THSTensor_fractional_max_pool3d(input.Handle, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)poutputRatio, output_ratio.Length, out var resIndices); - if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(resOutput), new Tensor(resIndices)); - } + unsafe { + fixed (long* pkernelSize = kernel_size, pSize = output_size) { + fixed (double* pRatio = output_ratio) { + var handle = THSNN_FractionalMaxPool3d_ctor( + (IntPtr)pkernelSize, kernel_size.Length, + (IntPtr)pSize, (output_size == null ? 0 : output_size.Length), + (IntPtr)pRatio, (output_ratio == null ? 0 : output_ratio.Length), + out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new FractionalMaxPool3d(handle, boxedHandle, output_ratio != null); } } } diff --git a/src/TorchSharp/NN/Pooling/LPPool1d.cs b/src/TorchSharp/NN/Pooling/LPPool1d.cs index 9babde806..62e4a2a4e 100644 --- a/src/TorchSharp/NN/Pooling/LPPool1d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool1d.cs @@ -14,23 +14,16 @@ namespace Modules /// public sealed class LPPool1d : ParamLessModule { - internal LPPool1d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) : base(nameof(LPPool1d)) + internal LPPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.norm_type = norm_type; - this.kernel_size = kernel_size; - this.stride = stride; - this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.lp_pool1d(input, norm_type, kernel_size, stride, ceil_mode); + var res = THSNN_LPPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public double norm_type { get; set; } - public long kernel_size { get; set; } - public long? stride { get; set; } - public bool ceil_mode { get; set; } } } @@ -42,37 +35,32 @@ public static partial class nn /// Applies a 1D power-average pooling over an input signal composed of several input planes. /// /// The LP norm (exponent) - /// The size of the window + /// The size of the window /// The stride of the window. Default value is kernel_size /// Use ceil instead of floor to compute the output shape /// - public static LPPool1d LPPool1d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) + public static LPPool1d LPPool1d(double norm_type, long kernelSize, long? stride = null, bool ceil_mode = false) { - return new LPPool1d(norm_type, kernel_size, stride, ceil_mode); + return stride.HasValue ? + LPPool1d(norm_type, new long[] { kernelSize }, new long[] { stride.Value }, ceil_mode) : + LPPool1d(norm_type, new long[] { kernelSize }, null); } - public static partial class functional + /// + /// Applies a 1D power-average pooling over an input signal composed of several input planes. + /// + /// The LP norm (exponent) + /// The size of the window + /// The stride of the window. Default value is kernel_size + /// Use ceil instead of floor to compute the output shape + /// + private static LPPool1d LPPool1d(double norm_type, long[] kernelSize, long[] strides = null, bool ceil_mode = false) { - /// - /// Applies a 1D power-average pooling over an input signal composed of several input planes. - /// - /// The input tensor - /// The LP norm (exponent) - /// The size of the window - /// The stride of the window. Default value is kernel_size - /// Use ceil instead of floor to compute the output shape - /// - public static Tensor lp_pool1d(Tensor input, double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) - { - var kernels = new[] { kernel_size }; - var strides = stride.HasValue ? new[] { stride.Value } : Array.Empty(); - - unsafe { - fixed (long* pkernelSize = kernels, pstrides = strides) { - var res = THSTensor_lp_pool1d(input.Handle, norm_type, (IntPtr)pkernelSize, kernels.Length, (IntPtr)pstrides, strides.Length, ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides) { + var handle = THSNN_LPPool1d_ctor(norm_type, (IntPtr)pkernelSize, (IntPtr)pstrides, ceil_mode, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new LPPool1d(handle, boxedHandle); } } } diff --git a/src/TorchSharp/NN/Pooling/LPPool2d.cs b/src/TorchSharp/NN/Pooling/LPPool2d.cs index 4fe66dafd..8555803de 100644 --- a/src/TorchSharp/NN/Pooling/LPPool2d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool2d.cs @@ -14,23 +14,16 @@ namespace Modules /// public sealed class LPPool2d : ParamLessModule { - internal LPPool2d(double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) : base(nameof(LPPool2d)) + internal LPPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.norm_type = norm_type; - this.kernel_size = kernel_size; - this.stride = stride; - this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.lp_pool2d(input, norm_type, kernel_size, stride, ceil_mode); + var res = THSNN_LPPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public double norm_type { get; set; } - public long[] kernel_size { get; set; } - public long[] stride { get; set; } - public bool ceil_mode { get; set; } } } @@ -43,12 +36,18 @@ public static partial class nn /// /// The LP norm (exponent) /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// Use ceil instead of floor to compute the output shape /// - public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) + public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] strides = null, bool ceil_mode = false) { - return new LPPool2d(norm_type, kernel_size, stride, ceil_mode); + unsafe { + fixed (long* pkernelSize = kernel_size, pstrides = strides) { + var handle = THSNN_LPPool2d_ctor(norm_type, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), ceil_mode, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new LPPool2d(handle, boxedHandle); + } + } } /// @@ -61,46 +60,9 @@ public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] str /// public static LPPool2d LPPool2d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) { - return new LPPool2d(norm_type, new[] { kernel_size, kernel_size }, stride.HasValue ? new[] { stride.Value, stride.Value } : null, ceil_mode); - } - - public static partial class functional - { - /// - /// Applies a 2D power-average pooling over an input signal composed of several input planes. - /// - /// The input tensor - /// The LP norm (exponent) - /// The size of the window - /// The stride of the window. Default value is kernel_size - /// Use ceil instead of floor to compute the output shape - /// - public static Tensor lp_pool2d(Tensor input, double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) - { - stride ??= Array.Empty(); - - unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = stride) { - var res = THSTensor_lp_pool2d(input.Handle, norm_type, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, stride.Length, ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } - } - - /// - /// Applies a 2D power-average pooling over an input signal composed of several input planes. - /// - /// The input tensor - /// The LP norm (exponent) - /// The size of the window - /// The stride of the window. - /// Use ceil instead of floor to compute the output shape - /// - public static Tensor lp_pool2d(Tensor input, double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) - { - return lp_pool2d(input, norm_type, new[] { kernel_size, kernel_size }, stride.HasValue ? new[] { stride.Value, stride.Value } : null, ceil_mode); - } + return stride.HasValue ? + LPPool2d(norm_type, new long[] { kernel_size, kernel_size }, new long[] { stride.Value, stride.Value }, ceil_mode) : + LPPool2d(norm_type, new long[] { kernel_size, kernel_size }, null, ceil_mode); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool1D.cs b/src/TorchSharp/NN/Pooling/MaxPool1D.cs index 558664c74..46254dcd7 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool1D.cs @@ -15,30 +15,23 @@ namespace Modules /// public sealed class MaxPool1d : ParamLessModule { - internal MaxPool1d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) : base(nameof(MaxPool1d)) + internal MaxPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; - this.dilation = dilation; - this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.max_pool1d(input, kernel_size, stride, padding, dilation, ceil_mode); + var res = THSNN_MaxPool1d_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) { - return torch.nn.functional.max_pool1d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + var res = THSNN_MaxPool1d_forward_with_indices(handle, tensor.Handle, out var indices); + if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(res), new Tensor(indices)); } - - public long kernel_size { get; set; } - public long? stride { get; set; } - public long? padding { get; set; } - public long? dilation { get; set; } - public bool ceil_mode { get; set; } } } @@ -49,56 +42,100 @@ public static partial class nn /// /// Applies a 1D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool1d MaxPool1d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) + public static MaxPool1d MaxPool1d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) { - return new MaxPool1d(kernel_size, stride, padding, dilation, ceil_mode); + var pStride = stride.HasValue ? new long[] { stride.Value } : null; + var pPadding = padding.HasValue ? new long[] { padding.Value } : null; + var pDilation = dilation.HasValue ? new long[] { dilation.Value } : null; + return MaxPool1d(new long[] { kernelSize }, pStride, pPadding, pDilation, ceilMode); + } + + private static MaxPool1d MaxPool1d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) + { + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { + var handle = THSNN_MaxPool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)pPadding, (IntPtr)pDilation, ceilMode, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new MaxPool1d(handle, boxedHandle); + } + } } public static partial class functional { - public static Tensor max_pool1d(Tensor input, long kernel_size, long? stride = null, + /// + /// Applies a 1D max pooling over an input signal composed of several input planes. + /// + /// The input tensor. + /// + /// + /// + /// + /// + /// + public static Tensor max_pool1d(Tensor input, long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - var ret = max_pool1d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); - ret.Indices.Dispose(); - return ret.Values; + var kernelSizes = new long[] { kernelSize }; + var strides = new long[] { stride ?? kernelSize }; + var paddings = new long[] { padding ?? 0 }; + var dilations = new long[] { dilation ?? 1 }; + unsafe { + fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { + var res = + THSTensor_max_pool1d(input.Handle, + (IntPtr)pkernelSize, kernelSizes.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, paddings.Length, + (IntPtr)pdilation, dilations.Length, + ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + } } /// /// Applies a 1D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static (Tensor Values, Tensor Indices) max_pool1d_with_indices(Tensor input, long kernel_size, long? stride = null, + public static (Tensor output, Tensor indices) max_pool1d_with_indices(Tensor input, long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - var kernelSizes = new long[] { kernel_size }; - var strides = new long[] { stride ?? kernel_size }; + var kernelSizes = new long[] { kernelSize }; + var strides = new long[] { stride ?? kernelSize }; var paddings = new long[] { padding ?? 0 }; var dilations = new long[] { dilation ?? 1 }; - unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { - var resOutput = THSTensor_max_pool1d_with_indices(input.Handle, + IntPtr[] ptrArray; + + using (var pa = new PinnedArray()) { + unsafe { + fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { + THSTensor_max_pool1d_with_indices(input.Handle, + pa.CreateArray, (IntPtr)pkernelSize, kernelSizes.Length, (IntPtr)pstrides, strides.Length, (IntPtr)ppadding, paddings.Length, (IntPtr)pdilation, dilations.Length, - ceil_mode, out var resIndices); - if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(resOutput), new Tensor(resIndices)); + ceil_mode); + torch.CheckForErrors(); + } } + ptrArray = pa.Array; } + return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool2D.cs b/src/TorchSharp/NN/Pooling/MaxPool2D.cs index 2cef87ce6..7d96145df 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool2D.cs @@ -15,30 +15,22 @@ namespace Modules /// public sealed class MaxPool2d : ParamLessModule { - internal MaxPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) : base(nameof(MaxPool2d)) + internal MaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; - this.dilation = dilation; - this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.max_pool2d(input, kernel_size, stride, padding, dilation, ceil_mode); + var res = THSNN_MaxPool2d_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) { - return torch.nn.functional.max_pool2d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + var res = THSNN_MaxPool2d_forward_with_indices(handle, tensor.Handle, out var indices); + if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(res), new Tensor(indices)); } - - public long[] kernel_size { get; set; } - public long[] stride { get; set; } - public long[] padding { get; set; } - public long[] dilation { get; set; } - public bool ceil_mode { get; set; } } } @@ -49,53 +41,74 @@ public static partial class nn /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool2d MaxPool2d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) + public static unsafe MaxPool2d MaxPool2d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) { - long[] kernelValue = new[] { kernel_size, kernel_size }; - long[] strideValue = stride.HasValue ? new[] { stride.Value, stride.Value } : kernelValue.ToArray(); - long[] paddingValue = padding.HasValue ? new[] { padding.Value, padding.Value } : new[] { 0L, 0L }; - long[] dilationValue = dilation.HasValue ? new[] { dilation.Value, dilation.Value } : new[] { 1L, 1L }; + long svalue = stride.HasValue ? stride.Value : kernelSize; + long pvalue = padding.HasValue ? padding.Value : 0; + long dvalue = dilation.HasValue ? dilation.Value : 1; + + long* pStride = stackalloc long[2] { svalue, svalue }; + long* pPadding = stackalloc long[2] { pvalue, pvalue }; + long* pDilation = stackalloc long[2] { dvalue, dvalue }; - return new MaxPool2d(kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); + long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; + + var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pStride, 2, (IntPtr)pPadding, 2, (IntPtr)pDilation, 2, ceilMode, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new MaxPool2d(handle, boxedHandle); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static unsafe MaxPool2d MaxPool2d((long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceil_mode = false) + public static unsafe MaxPool2d MaxPool2d((long, long) kernelSize, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceilMode = false) { - long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; - long[] strideValue = stride.HasValue ? new[] { stride.Value.Item1, stride.Value.Item2 } : kernelValue.ToArray(); - long[] paddingValue = padding.HasValue ? new[] { padding.Value.Item1, padding.Value.Item2 } : new[] { 0L, 0L }; - long[] dilationValue = dilation.HasValue ? new[] { dilation.Value.Item1, dilation.Value.Item2 } : new[] { 1L, 1L }; - - return new MaxPool2d(kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); + long svalue1 = stride != null ? stride.Value.Item1 : kernelSize.Item1; + long svalue2 = stride != null ? stride.Value.Item2 : kernelSize.Item2; + long pvalue1 = padding != null ? padding.Value.Item1 : 0; + long pvalue2 = padding != null ? padding.Value.Item2 : 0; + long dvalue1 = dilation != null ? dilation.Value.Item1 : 1; + long dvalue2 = dilation != null ? dilation.Value.Item2 : 1; + + long* pStride = stackalloc long[2] { svalue1, svalue2 }; + long* pPadding = stackalloc long[2] { pvalue1, pvalue2 }; + long* pDilation = stackalloc long[2] { dvalue1, dvalue2 }; + + long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; + + var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pStride, 2, (IntPtr)pPadding, 2, (IntPtr)pDilation, 2, ceilMode, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new MaxPool2d(handle, boxedHandle); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool2d MaxPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) + public static unsafe MaxPool2d MaxPool2d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) { - return new MaxPool2d(kernel_size, stride, padding, dilation, ceil_mode); + fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { + var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), (IntPtr)pDilation, (dilation == null ? 0 : dilation.Length), ceilMode, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new MaxPool2d(handle, boxedHandle); + } } public static partial class functional @@ -104,64 +117,100 @@ public static partial class functional /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// - /// + /// + /// /// /// /// /// - public static Tensor max_pool2d(Tensor input, long[] kernel_size, long[] stride = null, + public static Tensor max_pool2d(Tensor input, long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - var ret = max_pool2d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); - ret.Indices.Dispose(); - return ret.Values; + strides = strides ?? kernelSize; + padding = padding ?? kernelSize.Select(x => 0L).ToArray(); + dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { + var res = + THSTensor_max_pool2d(input.Handle, + (IntPtr)pkernelSize, kernelSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length, + (IntPtr)pdilation, dilation.Length, + ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + } } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static Tensor max_pool2d(Tensor input, long kernel_size, long? stride = null, + public static unsafe Tensor max_pool2d(Tensor input, long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - long[] kernelValue = new[] { kernel_size, kernel_size }; - long[] strideValue = stride.HasValue ? new[] { stride.Value, stride.Value } : kernelValue.ToArray(); - long[] paddingValue = padding.HasValue ? new[] { padding.Value, padding.Value } : new[] { 0L, 0L }; - long[] dilationValue = dilation.HasValue ? new[] { dilation.Value, dilation.Value } : new[] { 1L, 1L }; - - var ret = max_pool2d_with_indices(input, kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); - ret.Indices.Dispose(); - return ret.Values; + long svalue = stride.HasValue ? stride.Value : kernelSize; + long pvalue = padding.HasValue ? padding.Value : 0; + long dvalue = dilation.HasValue ? dilation.Value : 1; + + long* pStride = stackalloc long[2] { svalue, svalue }; + long* pPadding = stackalloc long[2] { pvalue, pvalue }; + long* pDilation = stackalloc long[2] { dvalue, dvalue }; + + long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; + + var res = THSTensor_max_pool2d(input.Handle, + (IntPtr)pkernelSize, 2, + (IntPtr)pStride, 2, + (IntPtr)pPadding, 2, + (IntPtr)pDilation, 2, + ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernel_size, (long, long)? stride = null, + public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernelSize, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceil_mode = false) { - long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; - long[] strideValue = stride.HasValue ? new[] { stride.Value.Item1, stride.Value.Item2 } : kernelValue.ToArray(); - long[] paddingValue = padding.HasValue ? new[] { padding.Value.Item1, padding.Value.Item2 } : new[] { 0L, 0L }; - long[] dilationValue = dilation.HasValue ? new[] { dilation.Value.Item1, dilation.Value.Item2 } : new[] { 1L, 1L }; - - var ret = max_pool2d_with_indices(input, kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); - ret.Indices.Dispose(); - return ret.Values; + long svalue1 = stride != null ? stride.Value.Item1 : kernelSize.Item1; + long svalue2 = stride != null ? stride.Value.Item2 : kernelSize.Item2; + long pvalue1 = padding != null ? padding.Value.Item1 : 0; + long pvalue2 = padding != null ? padding.Value.Item2 : 0; + long dvalue1 = dilation != null ? dilation.Value.Item1 : 1; + long dvalue2 = dilation != null ? dilation.Value.Item2 : 1; + + long* pStride = stackalloc long[2] { svalue1, svalue2 }; + long* pPadding = stackalloc long[2] { pvalue1, pvalue2 }; + long* pDilation = stackalloc long[2] { dvalue1, dvalue2 }; + + long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; + + var res = THSTensor_max_pool2d(input.Handle, + (IntPtr)pkernelSize, 2, + (IntPtr)pStride, 2, + (IntPtr)pPadding, 2, + (IntPtr)pDilation, 2, + ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } /// @@ -174,25 +223,30 @@ public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernel_size, ( /// /// /// - public static (Tensor Values, Tensor Indices) max_pool2d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, + public static (Tensor output, Tensor indices) max_pool2d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides ??= kernelSize; - padding ??= kernelSize.Select(x => 0L).ToArray(); - dilation ??= kernelSize.Select(x => 1L).ToArray(); - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - var resOutput = THSTensor_max_pool2d_with_indices(input.Handle, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode, out var resIndices); - - if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(resOutput), new Tensor(resIndices)); + strides = strides ?? kernelSize; + padding = padding ?? kernelSize.Select(x => 0L).ToArray(); + dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); + IntPtr[] ptrArray; + + using (var pa = new PinnedArray()) { + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { + THSTensor_max_pool2d_with_indices(input.Handle, + pa.CreateArray, + (IntPtr)pkernelSize, kernelSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length, + (IntPtr)pdilation, dilation.Length, + ceil_mode); + torch.CheckForErrors(); + } } + ptrArray = pa.Array; } + return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool3D.cs b/src/TorchSharp/NN/Pooling/MaxPool3D.cs index 2b26b3dad..1999c34dc 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool3D.cs @@ -6,7 +6,6 @@ namespace TorchSharp { - using Google.Protobuf.WellKnownTypes; using Modules; namespace Modules @@ -16,30 +15,23 @@ namespace Modules /// public sealed class MaxPool3d : ParamLessModule { - internal MaxPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) : base(nameof(MaxPool3d)) + internal MaxPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; - this.dilation = dilation; - this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor input) + public override Tensor forward(Tensor tensor) { - return torch.nn.functional.max_pool3d(input, kernel_size, stride, padding, dilation, ceil_mode); + var res = THSNN_MaxPool3d_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) { - return torch.nn.functional.max_pool3d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + var res = THSNN_MaxPool3d_forward_with_indices(handle, tensor.Handle, out var indices); + if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(res), new Tensor(indices)); } - - public long[] kernel_size { get; set; } - public long[] stride { get; set; } - public long[] padding { get; set; } - public long[] dilation { get; set; } - public bool ceil_mode { get; set; } } } @@ -50,49 +42,55 @@ public static partial class nn /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) + public static MaxPool3d MaxPool3d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value, padding.Value } : null; var pDilation = dilation.HasValue ? new long[] { dilation.Value, dilation.Value, dilation.Value } : null; - return MaxPool3d(new long[] { kernel_size, kernel_size, kernel_size }, pStride, pPadding, pDilation, ceil_mode); + return MaxPool3d(new long[] { kernelSize, kernelSize, kernelSize }, pStride, pPadding, pDilation, ceilMode); } /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null, (long, long, long)? dilation = null, bool ceil_mode = false) + public static MaxPool3d MaxPool3d((long, long, long) kernelSize, (long, long, long)? stride = null, (long, long, long)? padding = null, (long, long, long)? dilation = null, bool ceilMode = false) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 } : null; var pDilation = dilation.HasValue ? new long[] { dilation.Value.Item1, dilation.Value.Item2, dilation.Value.Item3 } : null; - return MaxPool3d(new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pStride, pPadding, pDilation, ceil_mode); + return MaxPool3d(new long[] { kernelSize.Item1, kernelSize.Item2, kernelSize.Item3 }, pStride, pPadding, pDilation, ceilMode); } /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) + public static MaxPool3d MaxPool3d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) { - return new MaxPool3d(kernel_size, stride, padding, dilation, ceil_mode); + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { + var handle = THSNN_MaxPool3d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), (IntPtr)pDilation, (dilation == null ? 0 : dilation.Length), ceilMode, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new MaxPool3d(handle, boxedHandle); + } + } } public static partial class functional @@ -101,18 +99,31 @@ public static partial class functional /// Applies a 3D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// - /// + /// + /// /// /// /// /// - public static Tensor max_pool3d(Tensor input, long[] kernel_size, long[] stride = null, + public static Tensor max_pool3d(Tensor input, long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - var ret = max_pool3d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); - ret.Indices.Dispose(); - return ret.Values; + strides = strides ?? kernelSize; + padding = padding ?? kernelSize.Select(x => 0L).ToArray(); + dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { + var res = + THSTensor_max_pool3d(input.Handle, + (IntPtr)pkernelSize, kernelSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length, + (IntPtr)pdilation, dilation.Length, + ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + } } /// @@ -125,26 +136,30 @@ public static Tensor max_pool3d(Tensor input, long[] kernel_size, long[] stride /// /// /// - public static (Tensor Values, Tensor Indices) max_pool3d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, + public static (Tensor output, Tensor indices) max_pool3d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides ??= kernelSize; - padding ??= kernelSize.Select(x => 0L).ToArray(); - dilation ??= kernelSize.Select(x => 1L).ToArray(); - - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - var resOutput = THSTensor_max_pool3d_with_indices(input.Handle, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode, out var resIndices); + strides = strides ?? kernelSize; + padding = padding ?? kernelSize.Select(x => 0L).ToArray(); + dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); + IntPtr[] ptrArray; - if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(resOutput), new Tensor(resIndices)); + using (var pa = new PinnedArray()) { + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { + THSTensor_max_pool3d_with_indices(input.Handle, + pa.CreateArray, + (IntPtr)pkernelSize, kernelSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length, + (IntPtr)pdilation, dilation.Length, + ceil_mode); + torch.CheckForErrors(); + } } + ptrArray = pa.Array; } + return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs index 9c2afb04d..d2bf0ddeb 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs @@ -5,7 +5,6 @@ namespace TorchSharp { - using System.Runtime.CompilerServices; using Modules; namespace Modules @@ -15,26 +14,25 @@ namespace Modules /// public sealed class MaxUnpool1d : ParamLessModule { - internal MaxUnpool1d(long kernel_size, long? stride = null, long? padding = null) : base(nameof(MaxUnpool1d)) + internal MaxUnpool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - return torch.nn.functional.max_unpool1d(tensor, indices, kernel_size, stride, padding, output_size); + unsafe { + fixed (long* pOutSize = output_size) { + var res = THSNN_MaxUnpool1d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + } } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } - - public long kernel_size { get; set; } - public long? stride { get; set; } - public long? padding { get; set; } } } @@ -43,42 +41,26 @@ public static partial class torch public static partial class nn { /// - /// Computes a partial inverse of :class:`MaxPool1d`. + /// Applies a 1D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool1d MaxUnpool1d(long kernel_size, long? stride = null, long? padding = null) + public static MaxUnpool1d MaxUnpool1d(long kernelSize, long? stride = null, long? padding = null) { - return new MaxUnpool1d(kernel_size, stride, padding); + var pStride = stride.HasValue ? new long[] { stride.Value } : null; + var pPadding = padding.HasValue ? new long[] { padding.Value } : null; + return MaxUnpool1d(new long[] { kernelSize }, pStride, pPadding); } - public static partial class functional + private static MaxUnpool1d MaxUnpool1d(long[] kernelSize, long[] strides = null, long[] padding = null) { - /// - /// Applies a 1D max pooling over an input signal composed of several input planes. - /// - /// the input Tensor to invert - /// the indices given out by :class:`~torch.nn.MaxPool1d` - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. - /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 - /// (optional): The targeted output size - /// - public static Tensor max_unpool1d(Tensor input, Tensor indices, long kernel_size, long? stride = null, long? padding = null, long[] output_size = null) - { - long[] kernels = new[] { kernel_size }; - long[] strides = stride.HasValue ? new[] { stride.Value } : Array.Empty(); - long[] paddings = padding.HasValue ? new[] { padding.Value } : Array.Empty(); - output_size ??= Array.Empty(); - - unsafe { - fixed (long* pkernels = kernels, pstrides = strides, ppaddings = paddings, poutputSize = output_size) { - var res = THSTensor_max_unpool1d(input.Handle, indices.Handle, (IntPtr)pkernels, kernels.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, paddings.Length, (IntPtr)pstrides, strides.Length); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { + var handle = THSNN_MaxUnpool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)pPadding, out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new MaxUnpool1d(handle, boxedHandle); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs index f342049fb..e01e6ddcf 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs @@ -5,7 +5,6 @@ namespace TorchSharp { - using Microsoft.VisualBasic; using Modules; namespace Modules @@ -15,26 +14,25 @@ namespace Modules /// public sealed class MaxUnpool2d : ParamLessModule { - internal MaxUnpool2d(long[] kernel_size, long[] stride = null, long[] padding = null) : base(nameof(MaxUnpool2d)) + internal MaxUnpool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - return torch.nn.functional.max_unpool2d(tensor, indices, kernel_size, stride, padding, output_size); + unsafe { + fixed (long* pOutSize = output_size) { + var res = THSNN_MaxUnpool2d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize, output_size == null ? 0 : output_size.Length); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + } } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } - - public long[] kernel_size { get; set; } - public long[] stride { get; set; } - public long[] padding { get; set; } } } @@ -45,41 +43,47 @@ public static partial class nn /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d(long kernel_size, long? stride = null, long? padding = null) + public static MaxUnpool2d MaxUnpool2d(long kernelSize, long? stride = null, long? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value } : null; - return new MaxUnpool2d(new[] { kernel_size, kernel_size }, pStride, pPadding); + return MaxUnpool2d(new long[] { kernelSize, kernelSize }, pStride, pPadding); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d((long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null) + public static MaxUnpool2d MaxUnpool2d((long, long) kernelSize, (long, long)? stride = null, (long, long)? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2 } : null; - return new MaxUnpool2d(new[] { kernel_size.Item1, kernel_size.Item2 }, pStride, pPadding); + return MaxUnpool2d(new long[] { kernelSize.Item1, kernelSize.Item2 }, pStride, pPadding); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d(long[] kernel_size, long[] stride = null, long[] padding = null) + public static MaxUnpool2d MaxUnpool2d(long[] kernelSize, long[] strides = null, long[] padding = null) { - return new MaxUnpool2d(kernel_size, stride, padding); + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { + var handle = THSNN_MaxUnpool2d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new MaxUnpool2d(handle, boxedHandle); + } + } } public static partial class functional @@ -87,22 +91,16 @@ public static partial class functional /// /// Computes a partial inverse of MaxPool2d. /// - /// the input Tensor to invert - /// the indices given out by :class:`~torch.nn.MaxPool2d` - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. - /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 - /// (optional): The targeted output size + /// The input tensor. + /// + /// /// - public static Tensor max_unpool2d(Tensor input, Tensor indices, long[] kernel_size, long[] stride = null, long[] padding = null, long[] output_size = null) + public static Tensor max_unpool2d(Tensor input, Tensor indices, long[] outputSize) { - stride ??= Array.Empty(); - padding ??= Array.Empty(); - output_size ??= Array.Empty(); - unsafe { - fixed (long* pkernels = kernel_size, pstrides = stride, ppaddings = padding, poutputSize = output_size) { - var res = THSTensor_max_unpool2d(input.Handle, indices.Handle, (IntPtr)pkernels, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, padding.Length, (IntPtr)pstrides, stride.Length); + fixed (long* poutputSize = outputSize) { + var res = THSTensor_maxunpool2d(input.Handle, indices.Handle, + (IntPtr)poutputSize, outputSize.Length); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs index 33abc0429..85d52e208 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs @@ -5,36 +5,34 @@ namespace TorchSharp { - using Microsoft.VisualBasic; using Modules; namespace Modules { /// - /// This class is used to represent a MaxUnpool3D module. + /// This class is used to represent a MaxUnpool3d module. /// public sealed class MaxUnpool3d : ParamLessModule { - internal MaxUnpool3d(long[] kernel_size, long[] stride = null, long[] padding = null) : base(nameof(MaxUnpool3d)) + internal MaxUnpool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { - this.kernel_size = kernel_size; - this.stride = stride; - this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - return torch.nn.functional.max_unpool3d(tensor, indices, kernel_size, stride, padding, output_size); + unsafe { + fixed (long* pOutSize = output_size) { + var res = THSNN_MaxUnpool3d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize, output_size == null ? 0 : output_size.Length); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + } } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } - - public long[] kernel_size { get; set; } - public long[] stride { get; set; } - public long[] padding { get; set; } } } @@ -43,66 +41,69 @@ public static partial class torch public static partial class nn { /// - /// Applies a 3D max pooling over an input signal composed of several input planes. + /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d(long kernel_size, long? stride = null, long? padding = null) + public static MaxUnpool3d MaxUnpool3d(long kernelSize, long? stride = null, long? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value, padding.Value } : null; - return new MaxUnpool3d(new[] { kernel_size, kernel_size, kernel_size }, pStride, pPadding); + return MaxUnpool3d(new long[] { kernelSize, kernelSize, kernelSize }, pStride, pPadding); } /// - /// Applies a 3D max pooling over an input signal composed of several input planes. + /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null) + public static MaxUnpool3d MaxUnpool3d((long, long, long) kernelSize, (long, long, long)? stride = null, (long, long, long)? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 } : null; - return new MaxUnpool3d(new[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pStride, pPadding); + return MaxUnpool3d(new long[] { kernelSize.Item1, kernelSize.Item2, kernelSize.Item3 }, pStride, pPadding); } /// - /// Applies a 3D max pooling over an input signal composed of several input planes. + /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d(long[] kernel_size, long[] stride = null, long[] padding = null) + public static MaxUnpool3d MaxUnpool3d(long[] kernelSize, long[] strides = null, long[] padding = null) { - return new MaxUnpool3d(kernel_size, stride, padding); + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { + var handle = THSNN_MaxUnpool3d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), out var boxedHandle); + if (handle == IntPtr.Zero) { torch.CheckForErrors(); } + return new MaxUnpool3d(handle, boxedHandle); + } + } } - public static partial class functional { /// /// Computes a partial inverse of MaxPool3d. /// - /// the input Tensor to invert - /// the indices given out by :class:`~torch.nn.MaxPool3d` - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. - /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 - /// (optional): The targeted output size + /// The input tensor. + /// + /// + /// + /// /// - public static Tensor max_unpool3d(Tensor input, Tensor indices, long[] kernel_size, long[] stride = null, long[] padding = null, long[] output_size = null) + public static Tensor max_unpool3d(Tensor input, Tensor indices, long[] outputSize, long[] strides, long[] padding) { - stride ??= Array.Empty(); - padding ??= Array.Empty(); - output_size ??= Array.Empty(); - unsafe { - fixed (long* pkernels = kernel_size, pstrides = stride, ppaddings = padding, poutputSize = output_size) { - var res = THSTensor_max_unpool3d(input.Handle, indices.Handle, (IntPtr)pkernels, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, padding.Length, (IntPtr)pstrides, stride.Length); + fixed (long* poutputSize = outputSize, pstrides = strides, ppadding = padding) { + var res = THSTensor_maxunpool3d(input.Handle, indices.Handle, + (IntPtr)poutputSize, outputSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs index 6d39ecb1c..b153acc9e 100644 --- a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs +++ b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs @@ -17,7 +17,8 @@ internal ChannelShuffle(long groups) : base(nameof(ChannelShuffle)) { this.groups = groups; } - + private long groups {get; set;} + public override Tensor forward(Tensor tensor) { return tensor.channel_shuffle(groups); @@ -27,8 +28,6 @@ public override string GetName() { return typeof(ChannelShuffle).Name; } - - public long groups { get; set; } } } diff --git a/src/TorchSharp/NN/Unflatten.cs b/src/TorchSharp/NN/Unflatten.cs index eeb91e1a9..fa5954f6b 100644 --- a/src/TorchSharp/NN/Unflatten.cs +++ b/src/TorchSharp/NN/Unflatten.cs @@ -14,20 +14,25 @@ namespace Modules /// public sealed class Unflatten : ParamLessModule { - internal Unflatten(long dim, long[] unflattened_size) : base(nameof(Unflatten)) + internal Unflatten(long dim, long[] unflattenedSize) : base(nameof(Unflatten)) { - this.dim = dim; - this.unflattened_size = unflattened_size; + this._dim = dim; + this._unflattenedSize = unflattenedSize; } public override Tensor forward(Tensor tensor) { - return tensor.unflatten(dim, unflattened_size); + return tensor.unflatten(_dim, _unflattenedSize); } - - public long dim { get; set; } - public long[] unflattened_size { get; set; } + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + protected internal override nn.Module _to(ScalarType dtype) => this; + + long _dim; + long[] _unflattenedSize; } } @@ -39,11 +44,11 @@ public static partial class nn /// Unflattens a tensor dim expanding it to a desired shape. For use with Sequential. /// /// Dimension to be unflattened - /// New shape of the unflattened dimension + /// New shape of the unflattened dimension /// - public static Unflatten Unflatten(long dim, long[] unflattened_size) + public static Unflatten Unflatten(long dim, long[] unflattenedSize) { - return new Unflatten(dim, unflattened_size); + return new Unflatten(dim, unflattenedSize); } } } diff --git a/src/TorchSharp/NN/Unfold.cs b/src/TorchSharp/NN/Unfold.cs index 050479623..aa56705bb 100644 --- a/src/TorchSharp/NN/Unfold.cs +++ b/src/TorchSharp/NN/Unfold.cs @@ -6,6 +6,7 @@ #nullable enable namespace TorchSharp { + using System.Security.Cryptography; using Modules; namespace Modules @@ -14,7 +15,7 @@ public sealed class Unfold : ParamLessModule { internal Unfold((long, long) kernel_size, (long, long) dilation, (long, long) padding, (long, long) stride) : base(nameof(Unfold)) { - this.kernel_size = kernel_size; + this.kernelSize = kernel_size; this.dilation = dilation; this.padding = padding; this.stride = stride; @@ -22,13 +23,13 @@ internal Unfold((long, long) kernel_size, (long, long) dilation, (long, long) pa public override Tensor forward(Tensor tensor) { - return torch.nn.functional.unfold(tensor, kernel_size, dilation, padding, stride); + return torch.nn.functional.unfold(tensor, kernelSize, dilation, padding, stride); } - public (long, long) kernel_size { get; set; } - public (long, long) dilation { get; set; } - public (long, long) padding { get; set; } - public (long, long) stride { get; set; } + private (long, long) kernelSize; + private (long, long) dilation; + private (long, long) padding; + private (long, long) stride; } } @@ -44,7 +45,7 @@ public static partial class nn /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. /// Currently, only 4-D input tensors (batched image-like tensors) are supported. - public static Unfold Unfold(long kernel_size, long dilation = 1, long padding = 0, long stride = 1) + public unsafe static Unfold Unfold(long kernel_size, long dilation = 1, long padding = 0, long stride = 1) { return new Unfold((kernel_size, kernel_size), (dilation, dilation), (padding, padding), (stride, stride)); } @@ -57,7 +58,7 @@ public static Unfold Unfold(long kernel_size, long dilation = 1, long padding = /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. /// Currently, only 4-D input tensors (batched image-like tensors) are supported. - public static Unfold Unfold((long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) + public unsafe static Unfold Unfold((long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) { dilation ??= (1, 1); stride ??= (1, 1); @@ -76,7 +77,7 @@ public static partial class functional /// A parameter that controls the stride of elements within the neighborhood. /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. - public static Tensor unfold(Tensor input, long kernel_size, long dilation = 1, long padding = 0, long stride = 1) + public unsafe static Tensor unfold(Tensor input, long kernel_size, long dilation = 1, long padding = 0, long stride = 1) { var res = THSNN_unfold(input.Handle, kernel_size, kernel_size, stride, stride, padding, padding, dilation, dilation); if (res == IntPtr.Zero) { torch.CheckForErrors(); } @@ -91,7 +92,7 @@ public static Tensor unfold(Tensor input, long kernel_size, long dilation = 1, l /// A parameter that controls the stride of elements within the neighborhood. /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. - public static Tensor unfold(Tensor input, (long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) + public unsafe static Tensor unfold(Tensor input, (long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) { dilation ??= (1, 1); stride ??= (1, 1); diff --git a/src/TorchSharp/NN/Upsample.cs b/src/TorchSharp/NN/Upsample.cs index 2f3b43707..2427cc5a9 100644 --- a/src/TorchSharp/NN/Upsample.cs +++ b/src/TorchSharp/NN/Upsample.cs @@ -8,40 +8,6 @@ namespace TorchSharp { using Modules; - namespace Modules - { - /// - /// This class is used to represent an Upsample module. - /// - public sealed class Upsample : ParamLessModule - { - internal Upsample(long[]? size, double[]? scale_factor, UpsampleMode mode, bool? align_corners, bool? recompute_scale_factor) : base(nameof(Upsample)) - { - this.size = size; - this.scale_factor = scale_factor; - this.mode = mode; - this.align_corners = align_corners; - this.recompute_scale_factor = recompute_scale_factor; - } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor input) - { - return torch.nn.functional.interpolate(input, size, scale_factor, (InterpolationMode)mode, align_corners, recompute_scale_factor ?? false); - } - - public long[]? size { get; set; } - public double[]? scale_factor { get; set; } - public UpsampleMode mode { get; set; } - public bool? align_corners { get; set; } - public bool? recompute_scale_factor { get; set; } - } - } - public static partial class torch { public static partial class nn @@ -56,11 +22,19 @@ public static partial class nn /// The upsampling algorithm: one of 'nearest', 'linear', 'bilinear', 'bicubic' and 'trilinear'. Default: 'nearest' /// If true, the corner pixels of the input and output tensors are aligned, and thus preserving the values at those pixels. /// This only has effect when mode is 'linear', 'bilinear', or 'trilinear'. Default: false - /// recompute the scale_factor for use in the interpolation calculation. If `recompute_scale_factor` is ``True``, then `scale_factor` must be passed in and `scale_factor` is used to compute the output `size`. The computed output `size` will be used to infer new scales for the interpolation. Note that when `scale_factor` is floating-point, it may differ from the recomputed `scale_factor` due to rounding and precision issues. If `recompute_scale_factor` is ``False``, then `size` or `scale_factor` will be used directly for interpolation. /// - public static Upsample Upsample(long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool? align_corners = null, bool? recompute_scale_factor = null) + public static Upsample Upsample(long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool? align_corners = null) { - return new Upsample(size, scale_factor, mode, align_corners, recompute_scale_factor); + unsafe { + fixed (long* psize = size) { + fixed (double* pSF = scale_factor) { + byte ac = (byte)((align_corners.HasValue) ? (align_corners.Value ? 1 : 2) : 0); + var res = THSNN_Upsample_ctor((IntPtr)psize, size is null ? 0 : size.Length, (IntPtr)pSF, scale_factor is null ? 0 : scale_factor.Length, (byte)mode, ac, out var boxedHandle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Upsample(res, boxedHandle, size, scale_factor, mode, align_corners); + } + } + } } public static partial class functional @@ -70,18 +44,21 @@ public static partial class functional /// The input data is assumed to be of the form minibatch x channels x[optional depth] x[optional height] x width. /// Hence, for spatial inputs, we expect a 4D Tensor and for volumetric inputs, we expect a 5D Tensor. /// - /// Input tensor + /// Input tensor /// Output spatial sizes /// Multiplier for spatial size. Has to match input size /// The upsampling algorithm: one of 'nearest', 'linear', 'bilinear', 'bicubic' and 'trilinear'. Default: 'nearest' /// If true, the corner pixels of the input and output tensors are aligned, and thus preserving the values at those pixels. /// This only has effect when mode is 'linear', 'bilinear', or 'trilinear'. Default: false /// - public static Tensor upsample(Tensor input, long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool align_corners = false) + public static Tensor upsample(Tensor x, long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool align_corners = false) { - return interpolate(input, size, scale_factor, (InterpolationMode)mode, align_corners); + using (var d = nn.Upsample(size, scale_factor, mode, align_corners)) { + return d.call(x); + } } + /// /// Upsamples the input, using nearest neighbours’ pixel values. /// @@ -221,4 +198,54 @@ public static Tensor upsample_nearest3d(Tensor input, long[]? outputSizes = null } } } + + namespace Modules + { + /// + /// This class is used to represent an Upsample module. + /// + public sealed class Upsample : ParamLessModule + { + internal Upsample(IntPtr handle, IntPtr boxedHandle, long[]? size, double[]? scale_factor, UpsampleMode mode, bool? align_corners) : base(handle, boxedHandle) + { + this._size = size; + this._scale_factor = scale_factor; + this.mode = mode; + this.align_corners = align_corners; + } + + /// + /// Forward pass. + /// + /// Input tensor + /// + public override Tensor forward(Tensor tensor) + { + var res = THSNN_Upsample_forward(handle, tensor.Handle); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + + public UpsampleMode mode { get; private set; } + + public bool? align_corners { get; private set; } + + public ReadOnlySpan size { + get { return _size is null ? null : new ReadOnlySpan(_size!); } + } + + public ReadOnlySpan scale_factor { + get { return _scale_factor is null ? null : new ReadOnlySpan(_scale_factor!); } + } + + private long[]? _size; + private double[]? _scale_factor; + + // Rather than spending cycles only to discover that this module has neither + // parameters nor buffers, just shortcut the move completely. + protected internal override nn.Module _to(Device device, ScalarType dtype) => this; + protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; + protected internal override nn.Module _to(ScalarType dtype) => this; + } + } } diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index 5bfed781e..6756b2795 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -50,6 +50,12 @@ internal static extern IntPtr THSNN_custom_module( // align_corners -- 0=None, 1=true, 2=false internal static extern IntPtr THSNN_grid_sample(IntPtr input, IntPtr grid, byte mode, byte padding_mode, byte align_corners); + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AlphaDropout_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AlphaDropout_ctor(double p, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_alpha_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -57,7 +63,10 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_functional_bilinear(IntPtr input1, IntPtr input2, IntPtr weights, IntPtr bias); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_cosine_similarity(IntPtr input1, IntPtr input2, long dim, double eps); + internal static extern IntPtr THSNN_CosineSimilarity_ctor(long dim, double eps, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_CosineSimilarity_forward(torch.nn.Module.HType module, IntPtr input1, IntPtr input2); [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -124,6 +133,12 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_EmbeddingBag_from_pretrained(IntPtr embeddings, [MarshalAs(UnmanagedType.U1)] bool freeze, double max_norm, [MarshalAs(UnmanagedType.U1)] bool hasMN, double norm_type, [MarshalAs(UnmanagedType.U1)] bool scale_grad_by_freq, long mode, [MarshalAs(UnmanagedType.U1)] bool sparse, [MarshalAs(UnmanagedType.U1)] bool include_last_offset, long padding_idx, out IntPtr pBoxedModule); + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_FeatureAlphaDropout_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_FeatureAlphaDropout_ctor(double p, out IntPtr pBoxedModule); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_feature_alpha_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -408,10 +423,16 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_PairwiseDistance_ctor(double p, double eps, [MarshalAs(UnmanagedType.U1)] bool keep_dim, out IntPtr pBoxedModule); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_pixel_unshuffle(IntPtr tensor, long downscale_factor); + internal static extern IntPtr THSNN_PixelUnshuffle_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_PixelUnshuffle_ctor(long downscaleFactor, out IntPtr pBoxedModule); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_pixel_shuffle(IntPtr tensor, long upscale_factor); + internal static extern IntPtr THSNN_PixelShuffle_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_PixelShuffle_ctor(long upscaleFactor, out IntPtr pBoxedModule); [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_GRUCell_forward(torch.nn.Module.HType module, IntPtr input, IntPtr h_0); @@ -563,6 +584,24 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_InstanceNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LayerNorm_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LayerNorm_bias(torch.nn.Module.HType module); + + [DllImport("LibTorchSharp")] + internal static extern void THSNN_LayerNorm_set_bias(torch.nn.Module.HType module, IntPtr bias); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LayerNorm_weight(torch.nn.Module.HType module); + + [DllImport("LibTorchSharp")] + internal static extern void THSNN_LayerNorm_set_weight(torch.nn.Module.HType module, IntPtr weight); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LayerNorm_ctor(IntPtr norm_shape, long norm_shape_len, double eps, [MarshalAs(UnmanagedType.U1)] bool elementwise_affine, out IntPtr pBoxedModule); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_InstanceNorm2d_forward(IntPtr module, IntPtr tensor); @@ -896,6 +935,21 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_BatchNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool1d_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool1d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool1d_ctor(IntPtr pkernelSize, IntPtr pStrides, IntPtr pPadding, IntPtr pDilation, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxUnpool3d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize, int outputSizeLength); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxUnpool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, out IntPtr pBoxedModule); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_ELU_forward(torch.nn.Module.HType module, IntPtr tensor); @@ -1035,7 +1089,127 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_Threshold_forward(torch.nn.Module.HType module, IntPtr tensor); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Threshold_ctor(double threshold, double value, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); + internal static extern IntPtr THSNN_Threshold_ctor(double threshold, double value, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LocalResponseNorm_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LocalResponseNorm_ctor(long size, double alpha, double beta, double k, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveAvgPool1d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveAvgPool1d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveAvgPool2d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveAvgPool2d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveAvgPool3d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveAvgPool3d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveMaxPool1d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveMaxPool1d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveMaxPool2d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveMaxPool2d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveMaxPool3d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AdaptiveMaxPool3d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AvgPool1d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AvgPool1d_ctor(IntPtr pkernelSize, IntPtr pstrides, IntPtr ppadding, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AvgPool2d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AvgPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr ppadding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AvgPool3d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_AvgPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr ppadding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_FractionalMaxPool2d_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_FractionalMaxPool2d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_FractionalMaxPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pOutputSize, int sizeLength, IntPtr pOutputRatio, int ratioLength, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_FractionalMaxPool3d_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_FractionalMaxPool3d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_FractionalMaxPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pOutputSize, int sizeLength, IntPtr pOutputRatio, int ratioLength, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LPPool1d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LPPool1d_ctor(double norm_type, IntPtr pkernelSize, IntPtr pstrides, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LPPool2d_forward(IntPtr module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_LPPool2d_ctor(double norm_type, IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool2d_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool2d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, IntPtr pDilation, int dilationLength, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool3d_forward(torch.nn.Module.HType module, IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool3d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, IntPtr pDilation, int dilationLength, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxUnpool1d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxUnpool1d_ctor(IntPtr pkernelSize, IntPtr pStrides, IntPtr pPadding, out IntPtr pBoxedModule); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxUnpool2d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize, int outputSizeLength); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_MaxUnpool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, out IntPtr pBoxedModule); } #pragma warning restore CA2101 } diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs index 0de92012c..c82b659a3 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs @@ -64,49 +64,56 @@ internal static extern IntPtr THSTensor_conv_transpose3d(IntPtr input, IntPtr we long groups); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool1d_with_indices(IntPtr input, + internal static extern IntPtr THSTensor_max_pool1d(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); + [MarshalAs(UnmanagedType.U1)] bool ceil_mode); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool2d_with_indices(IntPtr input, - IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool3d_with_indices(IntPtr input, + internal static extern void THSTensor_max_pool1d_with_indices(IntPtr input, AllocatePinnedArray allocator, IntPtr kernelSize, int kernelSizeLength, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); + [MarshalAs(UnmanagedType.U1)] bool ceil_mode); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_unpool1d(IntPtr tensor, IntPtr indices, + internal static extern IntPtr THSTensor_max_pool2d(IntPtr input, IntPtr kernelSize, int kernelSizeLength, - IntPtr outputSize, int outputSizeLength, + IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, - IntPtr strides, int stridesLength); + IntPtr dilation, int dilationLength, + [MarshalAs(UnmanagedType.U1)] bool ceil_mode); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_unpool2d(IntPtr tensor, IntPtr indices, + internal static extern void THSTensor_max_pool2d_with_indices(IntPtr input, AllocatePinnedArray allocator, + IntPtr kernelSize, int kernelSizeLength, + IntPtr strides, int stridesLength, + IntPtr padding, int paddingLength, + IntPtr dilation, int dilationLength, + [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_max_pool3d(IntPtr input, + IntPtr kernelSize, int kernelSizeLength, + IntPtr strides, int stridesLength, + IntPtr padding, int paddingLength, + IntPtr dilation, int dilationLength, + [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + + [DllImport("LibTorchSharp")] + internal static extern void THSTensor_max_pool3d_with_indices(IntPtr input, AllocatePinnedArray allocator, IntPtr kernelSize, int kernelSizeLength, - IntPtr outputSize, int outputSizeLength, + IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, - IntPtr strides, int stridesLength); + IntPtr dilation, int dilationLength, + [MarshalAs(UnmanagedType.U1)] bool ceil_mode); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_unpool3d(IntPtr tensor, IntPtr indices, - IntPtr kernelSize, int kernelSizeLength, - IntPtr outputSize, int outputSizeLength, - IntPtr padding, int paddingLength, - IntPtr strides, int stridesLength); + internal static extern IntPtr THSTensor_maxunpool3d(IntPtr input, IntPtr indices, IntPtr outputSize, int outputSizeLength, IntPtr strides, int stridesLength, + IntPtr padding, int paddingLength); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool1d(IntPtr input, @@ -122,7 +129,7 @@ internal static extern IntPtr THSTensor_avg_pool2d(IntPtr input, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, - [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override); + [MarshalAs(UnmanagedType.U1)] bool count_include_pad); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool3d(IntPtr input, @@ -130,7 +137,7 @@ internal static extern IntPtr THSTensor_avg_pool3d(IntPtr input, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, - [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override); + [MarshalAs(UnmanagedType.U1)] bool count_include_pad); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool2d_backward(IntPtr gradOutput, IntPtr originalInput, @@ -150,6 +157,14 @@ internal static extern IntPtr THSTensor_avg_pool3d_backward(IntPtr gradOutput, I [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisorOverride); + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_avg_pool1d(IntPtr input, + IntPtr outputSize, int outputSizeLength); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_avg_pool2d(IntPtr input, + IntPtr outputSize, int outputSizeLength); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_upsample_nearest1d(IntPtr input, IntPtr outputSize, int outputSizeLength, @@ -2071,10 +2086,7 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, internal static extern IntPtr THSTensor_eye(long rows, long columns, sbyte scalarType, int deviceType, int deviceIndex, [MarshalAs(UnmanagedType.U1)] bool requires_grad); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_avg_pool1d(IntPtr input, IntPtr outputSize, int outputSizeLength); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_avg_pool2d(IntPtr input, IntPtr outputSize, int outputSizeLength); + internal static extern IntPtr THSTensor_maxunpool2d(IntPtr input, IntPtr indices, IntPtr outputSize, int outputSizeLength); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_adaptive_avg_pool3d(IntPtr input, IntPtr outputSize, int outputSizeLength); @@ -2082,27 +2094,6 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_adaptive_avg_pool3d_backward_out(IntPtr gradInput, IntPtr gradOutput, IntPtr originalInput); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_max_pool1d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_max_pool2d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_max_pool3d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_fractional_max_pool2d(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr outputSize, int outputSizeLength, IntPtr outputRatio, int outputRatioLength, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_fractional_max_pool3d(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr outputSize, int outputSizeLength, IntPtr outputRatio, int outputRatioLength, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_lp_pool1d(IntPtr input, double norm_type, IntPtr kernelSize, int kernelSizeLength, IntPtr stride, int strideLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_lp_pool2d(IntPtr input, double norm_type, IntPtr kernelSize, int kernelSizeLength, IntPtr stride, int strideLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_searchsorted_t(IntPtr sorted_sequence, IntPtr values, bool out_int32, bool right, IntPtr sorter); [DllImport("LibTorchSharp")] diff --git a/src/TorchVision/Ops/DropBlock.cs b/src/TorchVision/Ops/DropBlock.cs index dea7ed8a4..2aece98d0 100644 --- a/src/TorchVision/Ops/DropBlock.cs +++ b/src/TorchVision/Ops/DropBlock.cs @@ -53,7 +53,7 @@ public static Tensor drop_block2d(Tensor input, double p, long block_size, bool var pad = block_size / 2; noise = torch.nn.functional.pad(noise, (pad, pad, pad, pad), value: 0); - noise = torch.nn.functional.max_pool2d(noise, stride: 1, kernel_size: block_size, padding: block_size / 2); + noise = torch.nn.functional.max_pool2d(noise, stride: 1, kernelSize: block_size, padding: block_size / 2); noise = 1 - noise; var normalize_scale = noise.numel() / (eps + noise.sum()); @@ -94,7 +94,7 @@ public static Tensor drop_block3d(Tensor input, double p, long block_size, bool var pad = block_size / 2; var padding = new[] { pad, pad, pad, pad, pad, pad }; noise = torch.nn.functional.pad(noise, padding, value: 0); - noise = torch.nn.functional.max_pool3d(noise, stride: new long[] { 1, 1, 1 }, kernel_size: new[] { block_size, block_size, block_size }, padding: new long[] { pad }); + noise = torch.nn.functional.max_pool3d(noise, strides: new long[] { 1, 1, 1 }, kernelSize: new[] { block_size, block_size, block_size }, padding: new long[] { pad }); noise = 1 - noise; var normalize_scale = noise.numel() / (eps + noise.sum()); diff --git a/src/TorchVision/models/AlexNet.cs b/src/TorchVision/models/AlexNet.cs index a26fd3718..33372af06 100644 --- a/src/TorchVision/models/AlexNet.cs +++ b/src/TorchVision/models/AlexNet.cs @@ -76,17 +76,17 @@ public AlexNet(int numClasses, float dropout = 0.5f, string? weights_file = null features = Sequential( Conv2d(3, 64, kernelSize: 11, stride: 4, padding: 2), ReLU(inplace: true), - MaxPool2d(kernel_size: 3, stride: 2), + MaxPool2d(kernelSize: 3, stride: 2), Conv2d(64, 192, kernelSize: 5, padding: 2), ReLU(inplace: true), - MaxPool2d(kernel_size: 3, stride: 2), + MaxPool2d(kernelSize: 3, stride: 2), Conv2d(192, 384, kernelSize: 3, padding: 1), ReLU(inplace: true), Conv2d(384, 256, kernelSize: 3, padding: 1), ReLU(inplace: true), Conv2d(256, 256, kernelSize: 3, padding: 1), ReLU(inplace: true), - MaxPool2d(kernel_size: 3, stride: 2) + MaxPool2d(kernelSize: 3, stride: 2) ); avgpool = AdaptiveAvgPool2d(new long[] { 6, 6 }); diff --git a/src/TorchVision/models/GoogleNet.cs b/src/TorchVision/models/GoogleNet.cs index 105c24d35..861ccde6f 100644 --- a/src/TorchVision/models/GoogleNet.cs +++ b/src/TorchVision/models/GoogleNet.cs @@ -119,21 +119,21 @@ public GoogleNet(int numClasses = 1000, this.transform_input = transform_input; conv1 = conv_block(3, 64, kernel_size: 7, stride: 2, padding: 3); - maxpool1 = MaxPool2d(kernel_size: 3, stride: 2, ceil_mode: true); + maxpool1 = MaxPool2d(kernelSize: 3, stride: 2, ceilMode: true); conv2 = conv_block(64, 64, kernel_size: 1); conv3 = conv_block(64, 192, kernel_size: 3, padding: 1); - maxpool2 = MaxPool2d(kernel_size: 3, stride: 2, ceil_mode: true); + maxpool2 = MaxPool2d(kernelSize: 3, stride: 2, ceilMode: true); inception3a = inception_block(192, 64, 96, 128, 16, 32, 32); inception3b = inception_block(256, 128, 128, 192, 32, 96, 64); - maxpool3 = nn.MaxPool2d(3, stride: 2, ceil_mode: true); + maxpool3 = nn.MaxPool2d(3, stride: 2, ceilMode: true); inception4a = inception_block(480, 192, 96, 208, 16, 48, 64); inception4b = inception_block(512, 160, 112, 224, 24, 64, 64); inception4c = inception_block(512, 128, 128, 256, 24, 64, 64); inception4d = inception_block(512, 112, 144, 288, 32, 64, 64); inception4e = inception_block(528, 256, 160, 320, 32, 128, 128); - maxpool4 = nn.MaxPool2d(2, stride: 2, ceil_mode: true); + maxpool4 = nn.MaxPool2d(2, stride: 2, ceilMode: true); inception5a = inception_block(832, 256, 160, 320, 32, 128, 128); inception5b = inception_block(832, 384, 192, 384, 48, 128, 128); @@ -280,7 +280,7 @@ public Inception(int in_channels, int ch1x1, int ch3x3red, int ch3x3, int ch5x5r conv_block(ch5x5red, ch5x5, kernel_size: 3, padding: 1) ); branch4 = nn.Sequential( - nn.MaxPool2d(kernel_size: 3, stride: 1, padding: 1, ceil_mode: true), + nn.MaxPool2d(kernelSize: 3, stride: 1, padding: 1, ceilMode: true), conv_block(in_channels, pool_proj, kernel_size: 1) ); RegisterComponents(); diff --git a/src/TorchVision/models/InceptionV3.cs b/src/TorchVision/models/InceptionV3.cs index 7b68b01f2..e7f7791c3 100644 --- a/src/TorchVision/models/InceptionV3.cs +++ b/src/TorchVision/models/InceptionV3.cs @@ -119,10 +119,10 @@ public InceptionV3(int numClasses = 1000, Conv2d_1a_3x3 = conv_block(3, 32, kernel_size: 3, stride: 2); Conv2d_2a_3x3 = conv_block(32, 32, kernel_size: 3); Conv2d_2b_3x3 = conv_block(32, 64, kernel_size: 3, padding: 1); - maxpool1 = MaxPool2d(kernel_size: 3, stride: 2); + maxpool1 = MaxPool2d(kernelSize: 3, stride: 2); Conv2d_3b_1x1 = conv_block(64, 80, kernel_size: 1); Conv2d_4a_3x3 = conv_block(80, 192, kernel_size: 3); - maxpool2 = MaxPool2d(kernel_size: 3, stride: 2); + maxpool2 = MaxPool2d(kernelSize: 3, stride: 2); Mixed_5b = inception_a(192, pool_features: 32); Mixed_5c = inception_a(256, pool_features: 64); @@ -292,7 +292,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = branch3x3dbl_3.call(branch3x3dbl); - var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new [] { branch1x1_, branch5x5, branch3x3dbl, branch_pool_ }; @@ -341,7 +341,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = branch3x3dbl_3.call(branch3x3dbl); - var branch_pool = functional.max_pool2d(x, kernel_size: 3, stride: 2); + var branch_pool = functional.max_pool2d(x, kernelSize: 3, stride: 2); var outputs = new[] { branch3x3_, branch3x3dbl, branch_pool }; @@ -425,7 +425,7 @@ public override Tensor forward(Tensor x) branch7x7dbl = branch7x7dbl_4.call(branch7x7dbl); branch7x7dbl = branch7x7dbl_5.call(branch7x7dbl); - var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new[] { branch1x1_, branch7x7, branch7x7dbl, branch_pool_ }; @@ -475,7 +475,7 @@ public override Tensor forward(Tensor x) branch7x7x3 = branch7x7x3_3.call(branch7x7x3); branch7x7x3 = branch7x7x3_4.call(branch7x7x3); - var branch_pool = functional.max_pool2d(x, kernel_size: 3, stride: 2); + var branch_pool = functional.max_pool2d(x, kernelSize: 3, stride: 2); var outputs = new[] { branch3x3, branch7x7x3, branch_pool }; @@ -537,7 +537,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = torch.cat(new[] { branch3x3dbl_3a.call(branch3x3dbl), branch3x3dbl_3b.call(branch3x3dbl) }, 1); - var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new[] { branch1x1_, branch3x3, branch3x3dbl, branch_pool_ }; @@ -575,7 +575,7 @@ public InceptionAux(int in_channels, int num_classes) : base("InceptionAux") public override Tensor forward(Tensor x) { // N x 768 x 17 x 17 - x = functional.avg_pool2d(x, kernel_size: 5, stride: 3); + x = functional.avg_pool2d(x, kernelSize: 5, stride: 3); // N x 768 x 5 x 5 x = conv0.call(x); // N x 128 x 5 x 5 diff --git a/src/TorchVision/models/ResNet.cs b/src/TorchVision/models/ResNet.cs index 91c6fa7c4..654d587c3 100644 --- a/src/TorchVision/models/ResNet.cs +++ b/src/TorchVision/models/ResNet.cs @@ -773,7 +773,7 @@ public ResNet(string name, conv1 = Conv2d(3, in_planes, kernelSize: 7, stride: 2, padding: 3, bias: false); bn1 = norm_layer(in_planes); relu = ReLU(inplace: true); - maxpool = MaxPool2d(kernel_size: 3, stride: 2, padding: 1); + maxpool = MaxPool2d(kernelSize: 3, stride: 2, padding: 1); MakeLayer(layer1, block, expansion, 64, layers[0], 1); MakeLayer(layer2, block, expansion, 128, layers[1], 2, rswd.Item1); diff --git a/src/TorchVision/models/VGG.cs b/src/TorchVision/models/VGG.cs index 08e6d8a3c..e79f9ddec 100644 --- a/src/TorchVision/models/VGG.cs +++ b/src/TorchVision/models/VGG.cs @@ -363,7 +363,7 @@ public VGG(string name, for (var i = 0; i < channels.Length; i++) { if (channels[i] == 0) { - layers.Add(MaxPool2d(kernel_size: 2, stride: 2)); + layers.Add(MaxPool2d(kernelSize: 2, stride: 2)); } else { layers.Add(Conv2d(in_channels, channels[i], kernelSize: 3, padding: 1)); if (batch_norm) { diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index 355c50baa..db91c1993 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -3461,7 +3461,7 @@ public void AvgPool3DBackwardTensorExplicitDivisor() var ones = torch.ones(new long[] { 4, 2, 2, 2, 2 }, device: device); var kernelSize = new long[] { 2, 2, 2 }; var avg = torch.ones(new long[] { 4, 2, 1, 1, 1 }, device: device); - var res = torch.nn.functional.avg_pool3d_backward(avg, ones, kernelSize, divisor_override: 6) * 6.0; + var res = torch.nn.functional.avg_pool3d_backward(avg, ones, kernelSize, divisorOverride: 6) * 6.0; var ones0000 = ones.cpu()[0, 0, 0, 0, 0].ToSingle(); var res0000 = res.cpu()[0, 0, 0, 0, 0].ToSingle(); diff --git a/test/TorchSharpTest/TestTorchTensorBugs.cs b/test/TorchSharpTest/TestTorchTensorBugs.cs index d1e09c2e5..7d97371dd 100644 --- a/test/TorchSharpTest/TestTorchTensorBugs.cs +++ b/test/TorchSharpTest/TestTorchTensorBugs.cs @@ -1172,7 +1172,7 @@ public void Validate1089_2d() () => Assert.Equal(expectedShape, functional.max_pool2d(t, new long[] { 2, 2 }).shape) ); - Assert.Equal(expectedShape, functional.max_pool2d_with_indices(t, new long[] { 2, 2 }).Values.shape); + Assert.Equal(expectedShape, functional.max_pool2d_with_indices(t, new long[] { 2, 2 }).output.shape); } [Fact] @@ -1182,7 +1182,7 @@ public void Validate1089_3d() var expectedShape = new long[] { 1, 6, 14, 14, 14 }; Assert.Equal(expectedShape, functional.max_pool3d(t, new long[] { 2, 2, 2 }).shape); - Assert.Equal(expectedShape, functional.max_pool3d_with_indices(t, new long[] { 2, 2, 2 }).Values.shape); + Assert.Equal(expectedShape, functional.max_pool3d_with_indices(t, new long[] { 2, 2, 2 }).output.shape); } [Fact] From 66cab2058fd3da20bafeffe26dcc6ea9354ef361 Mon Sep 17 00:00:00 2001 From: shaltielshmid Date: Wed, 13 Mar 2024 17:31:38 +0200 Subject: [PATCH 36/47] Reopening PR after testing on Mac (#18) * Reviewed all modified modules and continued, made adjustments and continued with rehaul * Added linear properties * Fixed int/long in linear --- src/Examples/AlexNet.cs | 6 +- src/Examples/MNIST.cs | 2 +- src/Examples/VGG.cs | 2 +- src/FSharp.Examples/AlexNet.fs | 6 +- src/FSharp.Examples/MNIST.fs | 2 +- src/Native/LibTorchSharp/THSConvolution.cpp | 405 ------------------ src/Native/LibTorchSharp/THSNN.cpp | 203 +-------- src/Native/LibTorchSharp/THSNN.h | 106 +---- src/Native/LibTorchSharp/THSNormalization.cpp | 55 --- src/Native/LibTorchSharp/THSTensor.h | 71 +-- src/Native/LibTorchSharp/THSTensorConv.cpp | 273 ++++++++---- src/TorchSharp/NN/Bilinear.cs | 20 +- src/TorchSharp/NN/CosineSimilarity.cs | 21 +- src/TorchSharp/NN/Dropout.cs | 6 - src/TorchSharp/NN/Dropout2d.cs | 4 +- src/TorchSharp/NN/Dropout3d.cs | 4 +- src/TorchSharp/NN/FeatureDropout.cs | 20 +- src/TorchSharp/NN/Flatten.cs | 12 +- src/TorchSharp/NN/Identity.cs | 6 - src/TorchSharp/NN/Linear.cs | 39 +- src/TorchSharp/NN/Normalization/Functional.cs | 10 - src/TorchSharp/NN/Normalization/LayerNorm.cs | 36 +- .../NN/Normalization/LocalResponseNorm.cs | 40 +- src/TorchSharp/NN/Padding/PadBase.cs | 2 +- src/TorchSharp/NN/Padding/ReflectionPad2d.cs | 2 +- src/TorchSharp/NN/Padding/ReflectionPad3d.cs | 2 +- src/TorchSharp/NN/Padding/ReplicationPad2d.cs | 2 +- src/TorchSharp/NN/Padding/ReplicationPad3d.cs | 2 +- src/TorchSharp/NN/PixelShuffle.cs | 45 +- src/TorchSharp/NN/PixelUnshuffle.cs | 43 +- .../NN/Pooling/AdaptiveAvgPool1D.cs | 20 +- .../NN/Pooling/AdaptiveAvgPool2D.cs | 39 +- .../NN/Pooling/AdaptiveAvgPool3D.cs | 40 +- .../NN/Pooling/AdaptiveMaxPool1D.cs | 57 ++- .../NN/Pooling/AdaptiveMaxPool2D.cs | 57 ++- .../NN/Pooling/AdaptiveMaxPool3D.cs | 57 ++- src/TorchSharp/NN/Pooling/AvgPool1D.cs | 46 +- src/TorchSharp/NN/Pooling/AvgPool2D.cs | 132 +++--- src/TorchSharp/NN/Pooling/AvgPool3D.cs | 102 ++--- .../NN/Pooling/FractionalMaxPool2d.cs | 161 ++++++- .../NN/Pooling/FractionalMaxPool3d.cs | 173 ++++++-- src/TorchSharp/NN/Pooling/LPPool1d.cs | 60 +-- src/TorchSharp/NN/Pooling/LPPool2d.cs | 72 +++- src/TorchSharp/NN/Pooling/MaxPool1D.cs | 105 ++--- src/TorchSharp/NN/Pooling/MaxPool2D.cs | 214 ++++----- src/TorchSharp/NN/Pooling/MaxPool3D.cs | 117 +++-- src/TorchSharp/NN/Pooling/MaxUnpool1d.cs | 58 ++- src/TorchSharp/NN/Pooling/MaxUnpool2d.cs | 64 +-- src/TorchSharp/NN/Pooling/MaxUnpool3d.cs | 77 ++-- src/TorchSharp/NN/Shuffle/ChannelShuffle.cs | 5 +- src/TorchSharp/NN/Unflatten.cs | 25 +- src/TorchSharp/NN/Unfold.cs | 21 +- src/TorchSharp/NN/Upsample.cs | 107 ++--- src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 182 +------- .../PInvoke/LibTorchSharp.THSTensor.cs | 91 ++-- src/TorchVision/Ops/DropBlock.cs | 4 +- src/TorchVision/models/AlexNet.cs | 6 +- src/TorchVision/models/GoogleNet.cs | 10 +- src/TorchVision/models/InceptionV3.cs | 16 +- src/TorchVision/models/ResNet.cs | 2 +- src/TorchVision/models/VGG.cs | 2 +- test/TorchSharpTest/NN.cs | 2 +- test/TorchSharpTest/TestTorchTensorBugs.cs | 4 +- 63 files changed, 1459 insertions(+), 2116 deletions(-) diff --git a/src/Examples/AlexNet.cs b/src/Examples/AlexNet.cs index 17b08b7c3..aa893255e 100644 --- a/src/Examples/AlexNet.cs +++ b/src/Examples/AlexNet.cs @@ -19,17 +19,17 @@ public AlexNet(string name, int numClasses, torch.Device device = null) : base(n features = Sequential( ("c1", Conv2d(3, 64, kernelSize: 3, stride: 2, padding: 1)), ("r1", ReLU(inplace: true)), - ("mp1", MaxPool2d(kernelSize: new long[] { 2, 2 })), + ("mp1", MaxPool2d(kernel_size: new long[] { 2, 2 })), ("c2", Conv2d(64, 192, kernelSize: 3, padding: 1)), ("r2", ReLU(inplace: true)), - ("mp2", MaxPool2d(kernelSize: new long[] { 2, 2 })), + ("mp2", MaxPool2d(kernel_size: new long[] { 2, 2 })), ("c3", Conv2d(192, 384, kernelSize: 3, padding: 1)), ("r3", ReLU(inplace: true)), ("c4", Conv2d(384, 256, kernelSize: 3, padding: 1)), ("r4", ReLU(inplace: true)), ("c5", Conv2d(256, 256, kernelSize: 3, padding: 1)), ("r5", ReLU(inplace: true)), - ("mp3", MaxPool2d(kernelSize: new long[] { 2, 2 }))); + ("mp3", MaxPool2d(kernel_size: new long[] { 2, 2 }))); avgPool = AdaptiveAvgPool2d(new long[] { 2, 2 }); diff --git a/src/Examples/MNIST.cs b/src/Examples/MNIST.cs index 73c8e69b0..d3059406a 100644 --- a/src/Examples/MNIST.cs +++ b/src/Examples/MNIST.cs @@ -105,7 +105,7 @@ internal class Model : Module // These don't have any parameters, so the only reason to instantiate // them is performance, since they will be used over and over. - private Module pool1 = MaxPool2d(kernelSize: new long[] { 2, 2 }); + private Module pool1 = MaxPool2d(kernel_size: new long[] { 2, 2 }); private Module relu1 = ReLU(); private Module relu2 = ReLU(); diff --git a/src/Examples/VGG.cs b/src/Examples/VGG.cs index 0c12eca4e..033bf6491 100644 --- a/src/Examples/VGG.cs +++ b/src/Examples/VGG.cs @@ -38,7 +38,7 @@ public VGG(string name, int numClasses, Device device = null) : base(name) for (var i = 0; i < channels.Length; i++) { if (channels[i] == 0) { - modules.Add(($"MaxPool2d-{i}a", MaxPool2d(kernelSize: 2, stride: 2))); + modules.Add(($"MaxPool2d-{i}a", MaxPool2d(kernel_size: 2, stride: 2))); } else { modules.Add(($"conv2d-{i}a", Conv2d(in_channels, channels[i], kernelSize: 3, padding: 1))); modules.Add(($"bnrm2d-{i}a", BatchNorm2d(channels[i]))); diff --git a/src/FSharp.Examples/AlexNet.fs b/src/FSharp.Examples/AlexNet.fs index 9a1e3fbe1..5604f0923 100644 --- a/src/FSharp.Examples/AlexNet.fs +++ b/src/FSharp.Examples/AlexNet.fs @@ -49,17 +49,17 @@ type Model(name,device:torch.Device) as this = let features = Sequential(("c1", Conv2d(3L, 64L, kernelSize=3L, stride=2L, padding=1L) :> Module), ("r1", ReLU(inplace=true) :> Module), - ("mp1", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), + ("mp1", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), ("c2", Conv2d(64L, 192L, kernelSize=3L, padding=1L) :> Module), ("r2", ReLU(inplace=true) :> Module), - ("mp2", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), + ("mp2", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), ("c3", Conv2d(192L, 384L, kernelSize=3L, padding=1L) :> Module), ("r3", ReLU(inplace=true) :> Module), ("c4", Conv2d(384L, 256L, kernelSize=3L, padding=1L) :> Module), ("r4", ReLU(inplace=true) :> Module), ("c5", Conv2d(256L, 256L, kernelSize=3L, padding=1L) :> Module), ("r5", ReLU(inplace=true) :> Module), - ("mp3", MaxPool2d(kernelSize=[|2L; 2L|]) :> Module), + ("mp3", MaxPool2d(kernel_size=[|2L; 2L|]) :> Module), ("avg", AdaptiveAvgPool2d([|2L; 2L|]) :> Module)) let classifier = Sequential(("d1", Dropout() :> Module), diff --git a/src/FSharp.Examples/MNIST.fs b/src/FSharp.Examples/MNIST.fs index d042f6f97..6967ebdc6 100644 --- a/src/FSharp.Examples/MNIST.fs +++ b/src/FSharp.Examples/MNIST.fs @@ -51,7 +51,7 @@ type Model(name,device:torch.Device) as this = let fc1 = Linear(9216L, 128L) let fc2 = Linear(128L, 10L) - let pool1 = MaxPool2d(kernelSize=[|2L; 2L|]) + let pool1 = MaxPool2d(kernel_size=[|2L; 2L|]) let relu = ReLU() diff --git a/src/Native/LibTorchSharp/THSConvolution.cpp b/src/Native/LibTorchSharp/THSConvolution.cpp index fb51e4c91..17120ded9 100644 --- a/src/Native/LibTorchSharp/THSConvolution.cpp +++ b/src/Native/LibTorchSharp/THSConvolution.cpp @@ -3,411 +3,6 @@ #include - - -NNModule THSNN_AvgPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, - bool ceil_mode, bool count_include_pad, int64_t divisor_override, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AvgPool1dOptions(at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); - if (stride) - opts = opts.stride(at::ArrayRef(stride, 1)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, 1)); - if (divisor_override > 0) - opts = opts.divisor_override(divisor_override); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AvgPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, - bool ceil_mode, bool count_include_pad, int64_t divisor_override, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AvgPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - if (divisor_override > 0) - opts = opts.divisor_override(divisor_override); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AvgPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, - bool ceil_mode, bool count_include_pad, int64_t divisor_override, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AvgPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode).count_include_pad(count_include_pad); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - if (divisor_override > 0) - opts = opts.divisor_override(divisor_override); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AvgPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveAvgPool1d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveAvgPool1dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveAvgPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveAvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveAvgPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveAvgPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveAvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveAvgPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveAvgPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveMaxPool1d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveMaxPool1dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveMaxPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveMaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveMaxPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AdaptiveMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AdaptiveMaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AdaptiveMaxPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_LPPool1d_ctor(double norm_type, const int64_t* kernelSize, const int64_t* stride, const bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LPPool1dOptions(norm_type, at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, 1)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LPPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_LPPool2d_ctor(double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LPPool2dOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LPPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_MaxPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, const int64_t* dilation, bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxPool1dOptions(at::ArrayRef(kernelSize, 1)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, 1)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, 1)); - if (dilation) - opts = opts.dilation(at::ArrayRef(dilation, 1)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxPool1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_MaxPool1d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - -NNModule THSNN_MaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - if (dilation) - opts = opts.dilation(at::ArrayRef(dilation, dilationLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_MaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - -NNModule THSNN_MaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, - NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - if (dilation) - opts = opts.dilation(at::ArrayRef(dilation, dilationLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_MaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - -NNModule THSNN_MaxUnpool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxUnpool1dOptions(at::ArrayRef(kernelSize, 1)); - if (stride) - opts = opts.stride(at::ArrayRef(stride, 1)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, 1)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxUnpool1d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize) -{ - if (outputSize != nullptr) { - std::vector outSize; - outSize.push_back(*outputSize); - - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); - } - else { - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); - } -} - -NNModule THSNN_MaxUnpool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxUnpool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxUnpool2d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength) -{ - if (outputSize != nullptr) { - std::vector outSize; - for (auto i = 0L; i < outputSizeLength; i++) { - outSize.push_back(outputSize[i]); - } - - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); - } - else { - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); - } -} - -NNModule THSNN_MaxUnpool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::MaxUnpool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (stride) - opts = opts.stride(at::ArrayRef(stride, strideLength)); - if (padding) - opts = opts.padding(at::ArrayRef(padding, paddingLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_MaxUnpool3d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength) -{ - if (outputSize != nullptr) { - std::vector outSize; - for (auto i = 0L; i < outputSizeLength; i++) { - outSize.push_back(outputSize[i]); - } - - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices, outSize)); - } - else { - CATCH_TENSOR((*module)->as()->forward(*tensor, *indices)); - } -} - - -NNModule THSNN_FractionalMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::FractionalMaxPool2dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (outputSize) - opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); - if (outputRatio) - opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_FractionalMaxPool2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_FractionalMaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - -NNModule THSNN_FractionalMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::FractionalMaxPool3dOptions(at::ArrayRef(kernelSize, kernelSizeLength)); - if (outputSize) - opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); - if (outputRatio) - opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_FractionalMaxPool3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_FractionalMaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices) -{ - std::tuple res; - CATCH(res = (*module)->as()->forward_with_indices(*tensor);); - *indices = ResultTensor(std::get<1>(res)); - return ResultTensor(std::get<0>(res)); -} - template void ApplyPaddingMode(T& opts, const int64_t padding) { diff --git a/src/Native/LibTorchSharp/THSNN.cpp b/src/Native/LibTorchSharp/THSNN.cpp index 256db0613..d1e6297e0 100644 --- a/src/Native/LibTorchSharp/THSNN.cpp +++ b/src/Native/LibTorchSharp/THSNN.cpp @@ -3,19 +3,6 @@ #include - -NNModule THSNN_Identity_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_Identity_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - Tensor THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias) { CATCH_TENSOR(bias == nullptr ? @@ -80,113 +67,16 @@ Tensor THSNN_feature_alpha_dropout(const Tensor input, const double p, bool trai CATCH_TENSOR(torch::nn::functional::feature_alpha_dropout(*input, opts)); } -NNModule THSNN_Dropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::DropoutOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Dropout_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_AlphaDropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::AlphaDropoutOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_AlphaDropout_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Dropout1d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - // Creating a Dropout2d instance here is done on purpose. There's no torch::nn::Dropout1d - auto opts = torch::nn::Dropout2dOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Dropout1d_forward(const NNModule module, const Tensor tensor) -{ - auto drop1d = (*module)->as(); - CATCH_TENSOR(drop1d->options.inplace() - ? drop1d->forward((*tensor).unsqueeze_(-1)).squeeze_(-1) - : drop1d->forward((*tensor).unsqueeze(-1)).squeeze(-1)); -} - - -NNModule THSNN_Dropout2d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::Dropout2dOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Dropout2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Dropout3d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::Dropout3dOptions(probability).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Dropout3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_FeatureAlphaDropout_ctor(double probability, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::FeatureAlphaDropoutOptions(probability); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_FeatureAlphaDropout_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_PixelShuffle_ctor(const int64_t upscale_factor, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::PixelShuffleOptions(upscale_factor); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_PixelShuffle_forward(const NNModule module, const Tensor tensor) +Tensor THSNN_pixel_shuffle(const Tensor tensor, const int64_t upscale_factor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_PixelUnshuffle_ctor(const int64_t downscale_factor, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::PixelUnshuffleOptions(downscale_factor); - res = create_module(opts, outAsAnyModule); - ); + auto opts = torch::nn::functional::PixelShuffleFuncOptions(upscale_factor); + CATCH_TENSOR(torch::nn::functional::pixel_shuffle(*tensor, opts)); } -Tensor THSNN_PixelUnshuffle_forward(const NNModule module, const Tensor tensor) +Tensor THSNN_pixel_unshuffle(const Tensor tensor, const int64_t downscale_factor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); + auto opts = torch::nn::functional::PixelUnshuffleFuncOptions(downscale_factor); + CATCH_TENSOR(torch::nn::functional::pixel_unshuffle(*tensor, opts)); } template @@ -221,38 +111,6 @@ void ApplyInterpolateMode(T& opts, const int8_t mode) opts = opts.mode(torch::kArea); } -NNModule THSNN_Upsample_ctor(const int64_t* size, const int size_len, const double* scale_factor, const int scale_factor_len, const int8_t mode, const int8_t align_corners, NNAnyModule* outAsAnyModule) -{ - auto opts = torch::nn::UpsampleOptions(); - // align_corners -- 0=None, 1=true, 2=false - if (align_corners != 0) - opts.align_corners(align_corners == 1); - ApplyUpsampleMode(opts, mode); - - CATCH_RETURN_NNModule( - if (size_len > 0) { - std::vector sizes; - for (int i = 0; i < size_len; ++i) { - sizes.push_back(size[i]); - } - opts.size(sizes); - } - if (scale_factor_len > 0) { - std::vector scales; - for (int i = 0; i < scale_factor_len; ++i) { - scales.push_back(scale_factor[i]); - } - opts.scale_factor(scales); - } - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Upsample_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - template void ApplyPadMode(T& opts, const int64_t padding) { @@ -675,54 +533,9 @@ Tensor THSNN_TransformerDecoder_forward(const NNModule module, const Tensor tg ); } -NNModule THSNN_Flatten_ctor(const int64_t start_dim, const int64_t end_dim, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::FlattenOptions() - .start_dim(start_dim) - .end_dim(end_dim); - - res = create_module(opts, outAsAnyModule); - ); -} -Tensor THSNN_Flatten_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Unflatten_ctor(const int64_t dim, const int64_t* shape, const int64_t shape_len, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - std::vector sizes; - for (int64_t i = 0; i < shape_len; ++i) - { - sizes.push_back(shape[i]); - } - auto opts = torch::nn::UnflattenOptions(dim, sizes); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Unflatten_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_CosineSimilarity_ctor(const int64_t dim, double eps, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::CosineSimilarityOptions() - .dim(dim) - .eps(eps); - - res = create_module(opts, outAsAnyModule); - ); - -} - -Tensor THSNN_CosineSimilarity_forward(const NNModule module, const Tensor input1, const Tensor input2) +Tensor THSNN_cosine_similarity(const Tensor input1, const Tensor input2, int64_t dim, double eps) { - CATCH_TENSOR((*module)->as()->forward(*input1, *input2)); + CATCH_TENSOR(torch::nn::functional::cosine_similarity(*input1, *input2, torch::nn::functional::CosineSimilarityFuncOptions().dim(dim).eps(eps))); } NNModule THSNN_PairwiseDistance_ctor(double p, double eps, bool keep_dim, NNAnyModule* outAsAnyModule) diff --git a/src/Native/LibTorchSharp/THSNN.h b/src/Native/LibTorchSharp/THSNN.h index b48ea866a..94d1400ac 100644 --- a/src/Native/LibTorchSharp/THSNN.h +++ b/src/Native/LibTorchSharp/THSNN.h @@ -37,63 +37,6 @@ EXPORT_API(void) THSNN_AnyModule_dispose(const NNAnyModule module); EXPORT_API(NNModule) THSNN_custom_module(const char* name, Tensor(*forward)(Tensor), NNAnyModule* outAsAnyModule); -// Pooling - -EXPORT_API(NNModule) THSNN_MaxPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, const int64_t* dilation, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_MaxPool1d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor *indices); - -EXPORT_API(NNModule) THSNN_MaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_MaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); - -EXPORT_API(NNModule) THSNN_MaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxPool3d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_MaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); - -EXPORT_API(NNModule) THSNN_FractionalMaxPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_FractionalMaxPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_FractionalMaxPool2d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); - -EXPORT_API(NNModule) THSNN_FractionalMaxPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_FractionalMaxPool3d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_FractionalMaxPool3d_forward_with_indices(const NNModule module, const Tensor tensor, Tensor* indices); - -EXPORT_API(NNModule) THSNN_MaxUnpool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxUnpool1d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize); - -EXPORT_API(NNModule) THSNN_MaxUnpool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxUnpool2d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength); - -EXPORT_API(NNModule) THSNN_MaxUnpool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_MaxUnpool3d_forward(const NNModule module, const Tensor tensor, const Tensor indices, const int64_t* outputSize, const int outputSizeLength); - -EXPORT_API(NNModule) THSNN_AdaptiveAvgPool1d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveAvgPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AdaptiveAvgPool2d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveAvgPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AdaptiveAvgPool3d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveAvgPool3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_AdaptiveMaxPool1d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveMaxPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AdaptiveMaxPool2d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveMaxPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AdaptiveMaxPool3d_ctor(const int64_t* sizes, const int length, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AdaptiveMaxPool3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_AvgPool1d_ctor(const int64_t* kernelSize, const int64_t* stride, const int64_t* padding, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AvgPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AvgPool2d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AvgPool2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_AvgPool3d_ctor(const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, bool count_include_pad, int64_t divisor_override, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AvgPool3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_LPPool1d_ctor(double norm_type, const int64_t* kernelSize, const int64_t* stride, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LPPool1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_LPPool2d_ctor(double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, bool ceil_mode, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LPPool2d_forward(const NNModule module, const Tensor tensor); - // Convolution EXPORT_API(NNModule) THSNN_Conv1d_ctor(const int64_t inputChannel, const int64_t outputChannel, const int64_t kernelSize, const int64_t stride, const int64_t padding, const int64_t dilation, const int64_t paddingMode, const int64_t groups, const bool bias, NNAnyModule* outAsAnyModule); @@ -230,16 +173,6 @@ EXPORT_API(Tensor) THSNN_InstanceNorm1d_get_batches(const NNModule module); EXPORT_API(Tensor) THSNN_InstanceNorm2d_get_batches(const NNModule module); EXPORT_API(Tensor) THSNN_InstanceNorm3d_get_batches(const NNModule module); - - -EXPORT_API(NNModule) THSNN_LayerNorm_ctor(const int64_t* norm_shape, const int64_t norm_shape_len, const double eps, const bool elementwise_affine, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LayerNorm_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(Tensor) THSNN_LayerNorm_bias(const NNModule module); -EXPORT_API(void) THSNN_LayerNorm_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_LayerNorm_weight(const NNModule module); -EXPORT_API(void) THSNN_LayerNorm_set_weight(const NNModule module, const Tensor weight); - EXPORT_API(NNModule) THSNN_GroupNorm_ctor(const int64_t num_groups, const int64_t num_channels, const double eps, const bool affine, NNAnyModule* outAsAnyModule); EXPORT_API(Tensor) THSNN_GroupNorm_forward(const NNModule module, const Tensor tensor); @@ -248,9 +181,6 @@ EXPORT_API(void) THSNN_GroupNorm_set_bias(const NNModule module, const Tenso EXPORT_API(Tensor) THSNN_GroupNorm_weight(const NNModule module); EXPORT_API(void) THSNN_GroupNorm_set_weight(const NNModule module, const Tensor weight); -EXPORT_API(NNModule) THSNN_LocalResponseNorm_ctor(const int64_t size, const double alpha, const double beta, const double k, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LocalResponseNorm_forward(const NNModule module, const Tensor tensor); - EXPORT_API(Tensor) THSNN_batch_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool training, const double momentum, const double eps); EXPORT_API(Tensor) THSNN_group_norm(const Tensor input, int64_t num_groups, const Tensor weight, const Tensor bias, const double eps); EXPORT_API(Tensor) THSNN_instance_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool use_input_stats, const double momentum, const double eps); @@ -258,22 +188,6 @@ EXPORT_API(Tensor) THSNN_layer_norm(const Tensor input, const int64_t* normali EXPORT_API(Tensor) THSNN_local_response_norm(const Tensor input, const int64_t size, const double alpha, const double beta, const double k); // Dropout - -EXPORT_API(NNModule) THSNN_Dropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Dropout_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Dropout1d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Dropout1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Dropout2d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Dropout2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Dropout3d_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Dropout3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_AlphaDropout_ctor(double probability, bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_AlphaDropout_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_FeatureAlphaDropout_ctor(double probability, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_FeatureAlphaDropout_forward(const NNModule module, const Tensor tensor); - EXPORT_API(Tensor) THSNN_dropout(const Tensor input, const double p, bool training, bool inplace); EXPORT_API(Tensor) THSNN_dropout2d(const Tensor input, const double p, bool training, bool inplace); EXPORT_API(Tensor) THSNN_dropout3d(const Tensor input, const double p, bool training, bool inplace); @@ -287,20 +201,13 @@ EXPORT_API(Tensor) THSNN_unfold(const Tensor input, const int64_t kernel1, const // Linear -EXPORT_API(NNModule) THSNN_Identity_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Identity_forward(const NNModule module, const Tensor tensor); - EXPORT_API(Tensor) THSNN_functional_linear(const Tensor input, const Tensor weights, const Tensor bias); EXPORT_API(Tensor) THSNN_functional_bilinear(const Tensor input1, const Tensor input2, const Tensor weights, const Tensor bias); // Vision -- Modules -EXPORT_API(NNModule) THSNN_PixelShuffle_ctor(const int64_t upscale_factor, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_PixelShuffle_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_PixelUnshuffle_ctor(const int64_t downscale_factor, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_PixelUnshuffle_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Upsample_ctor(const int64_t* size, const int size_len, const double* scale_factor, const int scale_factor_len, const int8_t mode, const int8_t align_corners, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Upsample_forward(const NNModule module, const Tensor tensor); +EXPORT_API(Tensor) THSNN_pixel_shuffle(const Tensor tensor, const int64_t upscale_factor); +EXPORT_API(Tensor) THSNN_pixel_unshuffle(const Tensor tensor, const int64_t downscale_fasctor); // Vision -- Functions @@ -513,14 +420,7 @@ EXPORT_API(void) THSNN_SGD_set_lr(const Optimizer optimizer, const double lr); EXPORT_API(Tensor) THSNN_one_hot(const Tensor self, const int64_t num_classes); -EXPORT_API(NNModule) THSNN_Flatten_ctor(const int64_t start_dim, const int64_t end_dim, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Flatten_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_Unflatten_ctor(const int64_t dim, const int64_t* shape, const int64_t shape_len, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Unflatten_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(NNModule) THSNN_CosineSimilarity_ctor(const int64_t dim, double eps, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_CosineSimilarity_forward(const NNModule module, const Tensor input1, const Tensor input2); +EXPORT_API(Tensor) THSNN_cosine_similarity(const Tensor input1, const Tensor input2, int64_t dim, double eps); EXPORT_API(NNModule) THSNN_PairwiseDistance_ctor(double p, double eps, bool keep_dim, NNAnyModule* outAsAnyModule); EXPORT_API(Tensor) THSNN_PairwiseDistance_forward(const NNModule module, const Tensor input1, const Tensor input2); diff --git a/src/Native/LibTorchSharp/THSNormalization.cpp b/src/Native/LibTorchSharp/THSNormalization.cpp index 6d0e6d97e..c17c4b98e 100644 --- a/src/Native/LibTorchSharp/THSNormalization.cpp +++ b/src/Native/LibTorchSharp/THSNormalization.cpp @@ -145,61 +145,6 @@ Tensor THSNN_InstanceNorm3d_forward(const NNModule module, const Tensor tensor) CATCH_TENSOR((*module)->as()->forward(*tensor)); } -NNModule THSNN_LayerNorm_ctor(const int64_t* norm_shape, const int64_t norm_shape_len, const double eps, const bool elementwise_affine, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - std::vector normalized_shape; - for (int64_t i = 0; i < norm_shape_len; ++i) - { - normalized_shape.push_back(norm_shape[i]); - } - auto opts = torch::nn::LayerNormOptions(normalized_shape).eps(eps).elementwise_affine(elementwise_affine); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LayerNorm_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_LayerNorm_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_LayerNorm_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_LayerNorm_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_LayerNorm_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - - -NNModule THSNN_LocalResponseNorm_ctor(const int64_t size, const double alpha, const double beta, const double k, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LocalResponseNormOptions(size) - .alpha(alpha) - .beta(beta) - .k(k); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LocalResponseNorm_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - void THSNN_BatchNorm1d_reset_stats(const NNModule module) { CATCH((*module)->as()->reset_running_stats();); diff --git a/src/Native/LibTorchSharp/THSTensor.h b/src/Native/LibTorchSharp/THSTensor.h index 6af55912b..f391075f4 100644 --- a/src/Native/LibTorchSharp/THSTensor.h +++ b/src/Native/LibTorchSharp/THSTensor.h @@ -23,6 +23,20 @@ EXPORT_API(Tensor) THSTensor_adaptive_avg_pool3d(const Tensor tensor, const int6 EXPORT_API(Tensor) THSTensor_adaptive_avg_pool3d_backward_out(const Tensor grad_input, const Tensor grad_output, const Tensor tensor); +EXPORT_API(Tensor) THSTensor_adaptive_max_pool1d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_adaptive_max_pool2d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_adaptive_max_pool3d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_fractional_max_pool2d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_fractional_max_pool3d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices); + +EXPORT_API(Tensor) THSTensor_lp_pool1d(const Tensor tensor, const double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode); + +EXPORT_API(Tensor) THSTensor_lp_pool2d(const Tensor tensor, const double norm_type, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const bool ceil_mode); + EXPORT_API(Tensor) THSTensor_add(const Tensor left, const Tensor right, const Scalar alpha); EXPORT_API(void) THSTensor_add_(const Tensor left, const Tensor right, const Scalar alpha); @@ -139,7 +153,8 @@ EXPORT_API(Tensor) THSTensor_avg_pool2d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad); + bool count_include_pad, + const int64_t divisor_override); EXPORT_API(Tensor) THSTensor_avg_pool2d_backward( const Tensor grad_output, @@ -157,7 +172,8 @@ EXPORT_API(Tensor) THSTensor_avg_pool3d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad); + bool count_include_pad, + const int64_t divisor_override); EXPORT_API(Tensor) THSTensor_avg_pool3d_backward( const Tensor grad_output, @@ -792,68 +808,53 @@ EXPORT_API(void) THSTensor_max_along_dimension(const Tensor tensor, Tensor* (*al EXPORT_API(Tensor) THSTensor_max_elementwise(const Tensor tensor, const Tensor other); -EXPORT_API(Tensor) THSTensor_max_pool1d( +EXPORT_API(Tensor) THSTensor_max_pool1d_with_indices( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode); + bool ceil_mode, Tensor *indices); -EXPORT_API(Tensor) THSTensor_max_pool2d( +EXPORT_API(Tensor) THSTensor_max_pool2d_with_indices( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode); + bool ceil_mode, Tensor* indices); -EXPORT_API(Tensor) THSTensor_max_pool3d( +EXPORT_API(Tensor) THSTensor_max_pool3d_with_indices( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode); + bool ceil_mode, Tensor* indices); -EXPORT_API(void) THSTensor_max_pool1d_with_indices( +EXPORT_API(Tensor) THSTensor_max_unpool1d( const Tensor tensor, - Tensor* (*allocator)(size_t length), - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode); - -EXPORT_API(void) THSTensor_max_pool2d_with_indices( - const Tensor tensor, - Tensor* (*allocator)(size_t length), + const Tensor indices, const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, + const int64_t* outputSize, const int outputSizeLength, const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode); + const int64_t* stride, const int strideLength); -EXPORT_API(void) THSTensor_max_pool3d_with_indices( +EXPORT_API(Tensor) THSTensor_max_unpool2d( const Tensor tensor, - Tensor* (*allocator)(size_t length), + const Tensor indices, const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, + const int64_t* outputSize, const int outputSizeLength, const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode); - -EXPORT_API(Tensor) THSTensor_maxunpool2d( - const Tensor tensor, - const Tensor indices, - const int64_t* outputSize, const int outputSizeLength); + const int64_t* stride, const int strideLength); -EXPORT_API(Tensor) THSTensor_maxunpool3d( +EXPORT_API(Tensor) THSTensor_max_unpool3d( const Tensor tensor, const Tensor indices, + const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength); + const int64_t* padding, const int paddingLength, + const int64_t* stride, const int strideLength); EXPORT_API(Tensor) THSTensor_mean(const Tensor tensor); diff --git a/src/Native/LibTorchSharp/THSTensorConv.cpp b/src/Native/LibTorchSharp/THSTensorConv.cpp index 10daa3e72..2783371e5 100644 --- a/src/Native/LibTorchSharp/THSTensorConv.cpp +++ b/src/Native/LibTorchSharp/THSTensorConv.cpp @@ -44,6 +44,110 @@ Tensor THSTensor_adaptive_avg_pool3d_backward_out( *tensor)); } +Tensor THSTensor_adaptive_max_pool1d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor *indices) +{ + Tensor output = nullptr; + *indices = nullptr; + CATCH( + auto result = torch::adaptive_max_pool1d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_adaptive_max_pool2d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices) +{ + Tensor output = nullptr; + *indices = nullptr; + CATCH( + auto result = torch::adaptive_max_pool2d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_adaptive_max_pool3d(const Tensor tensor, const int64_t* outputSize, const int outputSizeLength, Tensor* indices) +{ + Tensor output = nullptr; + *indices = nullptr; + CATCH( + auto result = torch::adaptive_max_pool3d(*tensor, at::ArrayRef(outputSize, outputSizeLength)); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_fractional_max_pool2d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices) +{ + Tensor output = nullptr; + *indices = nullptr; + auto opts = torch::nn::functional::FractionalMaxPool2dFuncOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); + if (outputRatioLength > 0) + opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); + + CATCH( + auto result = torch::nn::functional::fractional_max_pool2d_with_indices(*tensor, opts); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_fractional_max_pool3d(const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, const double* outputRatio, const int outputRatioLength, Tensor* indices) +{ + Tensor output = nullptr; + *indices = nullptr; + auto opts = torch::nn::functional::FractionalMaxPool3dFuncOptions(at::ArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(at::ArrayRef(outputSize, outputSizeLength)); + if (outputRatioLength > 0) + opts = opts.output_ratio(at::ArrayRef(outputRatio, outputRatioLength)); + + CATCH( + auto result = torch::nn::functional::fractional_max_pool3d_with_indices(*tensor, opts); + output = new torch::Tensor(std::get<0>(result)); + *indices = new torch::Tensor(std::get<1>(result)); + ); + return output; +} + +Tensor THSTensor_lp_pool1d( + const Tensor tensor, + const double norm_type, + const int64_t* kernelSize, + const int kernelSizeLength, + const int64_t* stride, + const int strideLength, + const bool ceil_mode) +{ + auto opts = torch::nn::functional::LPPool1dFuncOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); + if (strideLength > 0) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + opts.ceil_mode(); + CATCH_TENSOR(torch::nn::functional::lp_pool1d(*tensor, opts)); +} + +Tensor THSTensor_lp_pool2d( + const Tensor tensor, + const double norm_type, + const int64_t* kernelSize, + const int kernelSizeLength, + const int64_t* stride, + const int strideLength, + const bool ceil_mode) +{ + auto opts = torch::nn::functional::LPPool2dFuncOptions(norm_type, at::ArrayRef(kernelSize, kernelSizeLength)).ceil_mode(ceil_mode); + if (strideLength > 0) + opts = opts.stride(at::ArrayRef(stride, strideLength)); + opts.ceil_mode(); + CATCH_TENSOR(torch::nn::functional::lp_pool2d(*tensor, opts)); +} + Tensor THSTensor_avg_pool1d( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, @@ -67,7 +171,8 @@ Tensor THSTensor_avg_pool2d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad) + bool count_include_pad, + const int64_t divisor_override) { CATCH_TENSOR(torch::avg_pool2d( *tensor, @@ -75,7 +180,8 @@ Tensor THSTensor_avg_pool2d( at::ArrayRef(stride, strideLength), at::ArrayRef(padding, paddingLength), ceil_mode, - count_include_pad)); + count_include_pad, + (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); } Tensor THSTensor_avg_pool2d_backward( @@ -96,7 +202,7 @@ Tensor THSTensor_avg_pool2d_backward( at::ArrayRef(padding, paddingLength), ceil_mode, count_include_pad, - (divisor_override == 0 ? c10::optional() : c10::optional(divisor_override)))); + (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); } Tensor THSTensor_avg_pool3d( @@ -105,7 +211,8 @@ Tensor THSTensor_avg_pool3d( const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, bool ceil_mode, - bool count_include_pad) + bool count_include_pad, + const int64_t divisor_override) { CATCH_TENSOR(torch::avg_pool3d( *tensor, @@ -113,7 +220,8 @@ Tensor THSTensor_avg_pool3d( at::ArrayRef(stride, strideLength), at::ArrayRef(padding, paddingLength), ceil_mode, - count_include_pad)); + count_include_pad, + (divisor_override == 0 ? c10::nullopt : c10::optional(divisor_override)))); } Tensor THSTensor_avg_pool3d_backward( @@ -232,33 +340,16 @@ Tensor THSTensor_conv3d( groups)); } - -Tensor THSTensor_max_pool1d( - const Tensor tensor, - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode) -{ - CATCH_TENSOR(torch::max_pool1d( - *tensor, - at::ArrayRef(kernelSize, kernelSizeLength), - at::ArrayRef(stride, strideLength), - at::ArrayRef(padding, paddingLength), - at::ArrayRef(dilation, dilationLength), - ceil_mode)); -} - -void THSTensor_max_pool1d_with_indices( +Tensor THSTensor_max_pool1d_with_indices( const Tensor tensor, - Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode) + bool ceil_mode, Tensor *indices) { + Tensor output = nullptr; + *indices = nullptr; CATCH( auto res = torch::max_pool1d_with_indices( *tensor, @@ -268,38 +359,22 @@ void THSTensor_max_pool1d_with_indices( at::ArrayRef(dilation, dilationLength), ceil_mode); - Tensor * result = allocator(2); - result[0] = new torch::Tensor(std::get<0>(res)); - result[1] = new torch::Tensor(std::get<1>(res)); + output = new torch::Tensor(std::get<0>(res)); + *indices = new torch::Tensor(std::get<1>(res)); ) + return output; } -Tensor THSTensor_max_pool2d( +Tensor THSTensor_max_pool2d_with_indices( const Tensor tensor, const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode) -{ - CATCH_TENSOR(torch::max_pool2d( - *tensor, - at::ArrayRef(kernelSize, kernelSizeLength), - at::ArrayRef(stride, strideLength), - at::ArrayRef(padding, paddingLength), - at::ArrayRef(dilation, dilationLength), - ceil_mode)); -} - -void THSTensor_max_pool2d_with_indices( - const Tensor tensor, - Tensor* (*allocator)(size_t length), - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode) + bool ceil_mode, Tensor* indices) { + Tensor output = nullptr; + *indices = nullptr; CATCH( auto res = torch::max_pool2d_with_indices( *tensor, @@ -308,38 +383,22 @@ void THSTensor_max_pool2d_with_indices( at::ArrayRef(padding, paddingLength), at::ArrayRef(dilation, dilationLength), ceil_mode); - Tensor * result = allocator(2); - result[0] = new torch::Tensor(std::get<0>(res)); - result[1] = new torch::Tensor(std::get<1>(res)); + output = new torch::Tensor(std::get<0>(res)); + *indices = new torch::Tensor(std::get<1>(res)); ) + return output; } -Tensor THSTensor_max_pool3d( - const Tensor tensor, - const int64_t* kernelSize, const int kernelSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength, - const int64_t* dilation, const int dilationLength, - bool ceil_mode) -{ - CATCH_TENSOR(torch::max_pool3d( - *tensor, - at::ArrayRef(kernelSize, kernelSizeLength), - at::ArrayRef(stride, strideLength), - at::ArrayRef(padding, paddingLength), - at::ArrayRef(dilation, dilationLength), - ceil_mode)); -} - -void THSTensor_max_pool3d_with_indices( +Tensor THSTensor_max_pool3d_with_indices( const Tensor tensor, - Tensor* (*allocator)(size_t length), const int64_t* kernelSize, const int kernelSizeLength, const int64_t* stride, const int strideLength, const int64_t* padding, const int paddingLength, const int64_t* dilation, const int dilationLength, - bool ceil_mode) + bool ceil_mode, Tensor* indices) { + Tensor output = nullptr; + *indices = nullptr; CATCH( auto res = torch::max_pool3d_with_indices( *tensor, @@ -348,36 +407,70 @@ void THSTensor_max_pool3d_with_indices( at::ArrayRef(padding, paddingLength), at::ArrayRef(dilation, dilationLength), ceil_mode); - Tensor * result = allocator(2); - result[0] = new torch::Tensor(std::get<0>(res)); - result[1] = new torch::Tensor(std::get<1>(res)); + output = new torch::Tensor(std::get<0>(res)); + *indices = new torch::Tensor(std::get<1>(res)); ) + return output; } -Tensor THSTensor_maxunpool2d( +Tensor THSTensor_max_unpool1d( const Tensor tensor, const Tensor indices, - const int64_t* outputSize, const int outputSizeLength) + const int64_t* kernelSize, const int kernelSizeLength, + const int64_t* outputSize, const int outputSizeLength, + const int64_t* padding, const int paddingLength, + const int64_t* stride, const int strideLength) { - CATCH_TENSOR(torch::max_unpool2d( - *tensor, - *indices, - at::ArrayRef(outputSize, outputSizeLength))); + + auto opts = torch::nn::functional::MaxUnpool1dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); + if (paddingLength > 0) + opts = opts.padding(at::IntArrayRef(padding, paddingLength)); + if (paddingLength > 0) + opts = opts.stride(at::IntArrayRef(stride, strideLength)); + + CATCH_TENSOR(torch::nn::functional::max_unpool1d(*tensor, *indices, opts)); } -Tensor THSTensor_maxunpool3d( + +Tensor THSTensor_max_unpool2d( const Tensor tensor, const Tensor indices, + const int64_t* kernelSize, const int kernelSizeLength, const int64_t* outputSize, const int outputSizeLength, - const int64_t* stride, const int strideLength, - const int64_t* padding, const int paddingLength) + const int64_t* padding, const int paddingLength, + const int64_t* stride, const int strideLength) { - CATCH_TENSOR(torch::max_unpool3d( - *tensor, - *indices, - at::ArrayRef(outputSize, outputSizeLength), - at::ArrayRef(stride, strideLength), - at::ArrayRef(padding, paddingLength))); + + auto opts = torch::nn::functional::MaxUnpool2dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); + if (paddingLength > 0) + opts = opts.padding(at::IntArrayRef(padding, paddingLength)); + if (paddingLength > 0) + opts = opts.stride(at::IntArrayRef(stride, strideLength)); + + CATCH_TENSOR(torch::nn::functional::max_unpool2d(*tensor, *indices, opts)); +} + +Tensor THSTensor_max_unpool3d( + const Tensor tensor, + const Tensor indices, + const int64_t* kernelSize, const int kernelSizeLength, + const int64_t* outputSize, const int outputSizeLength, + const int64_t* padding, const int paddingLength, + const int64_t* stride, const int strideLength) +{ + auto opts = torch::nn::functional::MaxUnpool3dFuncOptions(at::IntArrayRef(kernelSize, kernelSizeLength)); + if (outputSizeLength > 0) + opts = opts.output_size(std::vector(outputSize, outputSize + outputSizeLength)); + if (paddingLength > 0) + opts = opts.padding(at::IntArrayRef(padding, paddingLength)); + if (paddingLength > 0) + opts = opts.stride(at::IntArrayRef(stride, strideLength)); + + CATCH_TENSOR(torch::nn::functional::max_unpool3d(*tensor, *indices, opts)); } diff --git a/src/TorchSharp/NN/Bilinear.cs b/src/TorchSharp/NN/Bilinear.cs index 5d37010e1..8d281fc8c 100644 --- a/src/TorchSharp/NN/Bilinear.cs +++ b/src/TorchSharp/NN/Bilinear.cs @@ -14,8 +14,15 @@ namespace Modules { public sealed class Bilinear : Module { + const string WeightComponentName = nameof(weight); + const string BiasComponentName = nameof(bias); + internal Bilinear(long in1_features, long in2_features, long out_features, bool hasBias = true, Device? device = null, ScalarType? dtype = null) : base(nameof(Bilinear)) { + this.in1_features = in1_features; + this.in2_features = in2_features; + this.out_features = out_features; + weight = torch.empty(out_features, in1_features, in2_features, device: device, dtype: dtype).AsParameter(); var bound = 1 / Math.Sqrt(weight!.shape[1]); @@ -23,7 +30,6 @@ internal Bilinear(long in1_features, long in2_features, long out_features, bool if (hasBias) { bias = torch.empty(out_features, device: device, dtype: dtype).AsParameter(); - var (fanIn, _) = init.CalculateFanInAndFanOut(weight); init.uniform_(_bias, -bound, bound); } //NOTE: it's important not to call 'RegisterComponents' here. @@ -47,7 +53,7 @@ public Parameter? bias { set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(nameof(bias), _bias); + ConditionallyRegisterParameter(BiasComponentName, _bias); } } @@ -58,15 +64,19 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(nameof(weight), _weight); + ConditionallyRegisterParameter(WeightComponentName, _weight); } } } - [ComponentName(Name = "bias")] + [ComponentName(Name = BiasComponentName)] private Parameter? _bias; - [ComponentName(Name = "weight")] + [ComponentName(Name = WeightComponentName)] private Parameter? _weight; + + public long in1_features { get; set; } + public long in2_features { get; set; } + public long out_features { get; set; } } } diff --git a/src/TorchSharp/NN/CosineSimilarity.cs b/src/TorchSharp/NN/CosineSimilarity.cs index 44399a1f2..eab4e964e 100644 --- a/src/TorchSharp/NN/CosineSimilarity.cs +++ b/src/TorchSharp/NN/CosineSimilarity.cs @@ -14,16 +14,19 @@ namespace Modules /// public sealed class CosineSimilarity : ParamLessModule { - internal CosineSimilarity(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal CosineSimilarity(long dim = 1, double eps = 1e-8) : base(nameof(CosineSimilarity)) { + this.dim = dim; + this.eps = eps; } public override Tensor forward(Tensor input1, Tensor input2) { - var res = THSNN_CosineSimilarity_forward(handle, input1.Handle, input2.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.cosine_similarity(input1, input2, this.dim, this.eps); } + + public long dim { get; set; } + public double eps { get; set; } } } @@ -39,9 +42,7 @@ public static partial class nn /// public static CosineSimilarity CosineSimilarity(long dim = 1, double eps = 1e-8) { - var handle = THSNN_CosineSimilarity_ctor(dim, eps, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new CosineSimilarity(handle, boxedHandle); + return new CosineSimilarity(dim, eps); } public static partial class functional @@ -56,9 +57,9 @@ public static partial class functional /// public static Tensor cosine_similarity(Tensor x1, Tensor x2, long dim = 1, double eps = 1e-8) { - using (var f = nn.CosineSimilarity(dim, eps)) { - return f.call(x1, x2); - } + var res = THSNN_cosine_similarity(x1.Handle, x2.Handle, dim, eps); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } } } diff --git a/src/TorchSharp/NN/Dropout.cs b/src/TorchSharp/NN/Dropout.cs index 675286a5f..b8e351a80 100644 --- a/src/TorchSharp/NN/Dropout.cs +++ b/src/TorchSharp/NN/Dropout.cs @@ -30,12 +30,6 @@ public override Tensor forward(Tensor tensor) return torch.nn.functional.dropout(tensor, this.p, this.training, this.inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - public bool inplace { get; set; } public double p { get; set;} } diff --git a/src/TorchSharp/NN/Dropout2d.cs b/src/TorchSharp/NN/Dropout2d.cs index 0f3989ba2..9005c745a 100644 --- a/src/TorchSharp/NN/Dropout2d.cs +++ b/src/TorchSharp/NN/Dropout2d.cs @@ -22,9 +22,7 @@ internal Dropout2d(double p = 0.5, bool inplace = false) : base(nameof(Dropout2d public override Tensor forward(Tensor input) { - var res = THSNN_dropout2d(input.Handle, p, this.training, inplace); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.dropout2d(input, this.p, this.training, this.inplace); } public bool inplace { get; set; } diff --git a/src/TorchSharp/NN/Dropout3d.cs b/src/TorchSharp/NN/Dropout3d.cs index 2d4fe88e8..4f447a149 100644 --- a/src/TorchSharp/NN/Dropout3d.cs +++ b/src/TorchSharp/NN/Dropout3d.cs @@ -22,9 +22,7 @@ internal Dropout3d(double p = 0.5, bool inplace = false) : base(nameof(Dropout3d public override Tensor forward(Tensor input) { - var res = THSNN_dropout3d(input.Handle, p, this.training, inplace); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.dropout3d(input, this.p, this.training, this.inplace); } public bool inplace { get; set; } diff --git a/src/TorchSharp/NN/FeatureDropout.cs b/src/TorchSharp/NN/FeatureDropout.cs index 2ea7b45c6..16712c2ab 100644 --- a/src/TorchSharp/NN/FeatureDropout.cs +++ b/src/TorchSharp/NN/FeatureDropout.cs @@ -14,16 +14,19 @@ namespace Modules /// public sealed class FeatureAlphaDropout : ParamLessModule { - internal FeatureAlphaDropout(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal FeatureAlphaDropout(double p = 0.5, bool inplace = false) : base(nameof(FeatureAlphaDropout)) { + this.p = p; + this.inplace = inplace; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_FeatureAlphaDropout_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.feature_alpha_dropout(input, this.p, this.training, this.inplace); } + + public bool inplace { get; set; } + public double p { get; set; } } } @@ -38,11 +41,10 @@ public static partial class nn /// randomized on every forward call, and scaled and shifted to maintain zero mean and unit variance. /// /// Dropout probability of a channel to be zeroed. Default: 0.5 - public static FeatureAlphaDropout FeatureAlphaDropout(double p = 0.5) + /// If set to true, will do this operation in-place. Default: false + public static FeatureAlphaDropout FeatureAlphaDropout(double p = 0.5, bool inplace = false) { - var handle = THSNN_FeatureAlphaDropout_ctor(p, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new FeatureAlphaDropout(handle, boxedHandle); + return new FeatureAlphaDropout(p, inplace); } public static partial class functional diff --git a/src/TorchSharp/NN/Flatten.cs b/src/TorchSharp/NN/Flatten.cs index 80093d294..1301870b1 100644 --- a/src/TorchSharp/NN/Flatten.cs +++ b/src/TorchSharp/NN/Flatten.cs @@ -20,19 +20,13 @@ internal Flatten(long start_dim = 1, long end_dim = -1) : base(nameof(Flatten)) this.end_dim = end_dim; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - return tensor.flatten(start_dim, end_dim); + return input.flatten(start_dim, end_dim); } - public long start_dim {get; set;} + public long start_dim { get; set; } public long end_dim { get; set; } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Identity.cs b/src/TorchSharp/NN/Identity.cs index 97bd68098..fd0c26760 100644 --- a/src/TorchSharp/NN/Identity.cs +++ b/src/TorchSharp/NN/Identity.cs @@ -18,12 +18,6 @@ public override Tensor forward(Tensor tensor) { return tensor.alias(); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Linear.cs b/src/TorchSharp/NN/Linear.cs index c2776fd5b..c9adb78cd 100644 --- a/src/TorchSharp/NN/Linear.cs +++ b/src/TorchSharp/NN/Linear.cs @@ -14,8 +14,14 @@ namespace Modules { public sealed class Linear : torch.nn.Module { + const string WeightComponentName = nameof(weight); + const string BiasComponentName = nameof(bias); + internal Linear(long inputSize, long outputSize, bool hasBias = true, Device? device = null, ScalarType? dtype = null) : base(nameof(Linear)) { + this.in_features = inputSize; + this.out_features = outputSize; + weight = torch.empty(outputSize, inputSize, device: device, dtype: dtype).AsParameter(); init.kaiming_uniform_(weight, a: _sqrt5); @@ -46,7 +52,7 @@ public Parameter? bias { set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(nameof(bias), _bias); + ConditionallyRegisterParameter(BiasComponentName, _bias); } } @@ -57,36 +63,19 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(nameof(weight), _weight); + ConditionallyRegisterParameter(WeightComponentName, _weight); } } } - protected internal override nn.Module _to(Device device, ScalarType dtype) - { - weight = new Parameter(_weight!.to(dtype, device)); - if (bias is not null) bias = new Parameter(_bias!.to(dtype, device)); - return this; - } - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) - { - weight = new Parameter(_weight!.to(deviceType, deviceIndex)); - if (bias is not null) bias = new Parameter(_bias!.to(deviceType, deviceIndex)); - return this; - } - - protected internal override nn.Module _to(ScalarType dtype) - { - weight = new Parameter(_weight!.to(dtype)); - if (bias is not null) bias = new Parameter(_bias!.to(dtype)); - return this; - } - - [ComponentName(Name = "bias")] + [ComponentName(Name = BiasComponentName)] private Parameter? _bias; - [ComponentName(Name = "weight")] + [ComponentName(Name = WeightComponentName)] private Parameter? _weight; + + public long in_features { get; set; } + public long out_features { get; set; } + private static readonly double _sqrt5 = Math.Sqrt(5); } } diff --git a/src/TorchSharp/NN/Normalization/Functional.cs b/src/TorchSharp/NN/Normalization/Functional.cs index 2f8bcd1e4..2c0848279 100644 --- a/src/TorchSharp/NN/Normalization/Functional.cs +++ b/src/TorchSharp/NN/Normalization/Functional.cs @@ -84,16 +84,6 @@ public static Tensor layer_norm(Tensor input, long[] normalized_shape, Tensor we return new Tensor(res); } - /// - /// Applies Local Normalization. - /// - public static Tensor local_response_norm(Tensor input, long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) - { - var res = THSNN_local_response_norm(input.Handle, size, alpha, beta, k); - if (res == IntPtr.Zero) - torch.CheckForErrors(); - return new Tensor(res); - } } } } diff --git a/src/TorchSharp/NN/Normalization/LayerNorm.cs b/src/TorchSharp/NN/Normalization/LayerNorm.cs index 949cfe4d0..7ae96ee71 100644 --- a/src/TorchSharp/NN/Normalization/LayerNorm.cs +++ b/src/TorchSharp/NN/Normalization/LayerNorm.cs @@ -18,10 +18,8 @@ namespace Modules /// public sealed class LayerNorm : torch.nn.Module { - public long[] normalized_shape { get; set; } - public double eps { get; set; } - - public bool elementwise_affine { get; set; } + const string WeightComponentName = nameof(weight); + const string BiasComponentName = nameof(bias); internal LayerNorm(long[] normalized_shape, double eps, bool elementwise_affine, bool bias, Device? device, ScalarType? dtype) : base(nameof(LayerNorm)) { @@ -38,11 +36,10 @@ internal LayerNorm(long[] normalized_shape, double eps, bool elementwise_affine, } } - - reset_parameters(elementwise_affine); + reset_parameters(); } - private void reset_parameters(bool elementwise_affine) + public void reset_parameters() { if (elementwise_affine) { @@ -59,12 +56,19 @@ public override Tensor forward(Tensor tensor) return F.layer_norm(tensor, normalized_shape, weight, bias, eps); } + protected override void Dispose(bool disposing) + { + _weight?.Dispose(); + _bias?.Dispose(); + base.Dispose(disposing); + } + public Parameter? bias { get => _bias; set { _bias?.Dispose(); _bias = value?.DetachFromDisposeScope() as Parameter; - ConditionallyRegisterParameter(nameof(bias), _bias); + ConditionallyRegisterParameter(BiasComponentName, _bias); } } @@ -75,22 +79,20 @@ public Parameter weight { if (value.Handle != _weight?.Handle) { _weight?.Dispose(); _weight = (value.DetachFromDisposeScope() as Parameter)!; - ConditionallyRegisterParameter(nameof(weight), _weight); + ConditionallyRegisterParameter(WeightComponentName, _weight); } } } - [ComponentName(Name = "bias")] + [ComponentName(Name = BiasComponentName)] private Parameter? _bias; - [ComponentName(Name = "weight")] + [ComponentName(Name = WeightComponentName)] private Parameter? _weight; - protected override void Dispose(bool disposing) - { - _weight?.Dispose(); - _bias?.Dispose(); - base.Dispose(disposing); - } + + public long[] normalized_shape { get; set; } + public double eps { get; set; } + public bool elementwise_affine { get; set; } } } diff --git a/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs b/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs index ba74b2e5e..6adad3d0c 100644 --- a/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs +++ b/src/TorchSharp/NN/Normalization/LocalResponseNorm.cs @@ -14,17 +14,23 @@ namespace Modules /// public sealed class LocalResponseNorm : ParamLessModule { - internal LocalResponseNorm(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal LocalResponseNorm(long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) : base(nameof(LocalResponseNorm)) { + this.size = size; + this.alpha = alpha; + this.beta = beta; + this.k = k; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - if (tensor.Dimensions < 3) throw new ArgumentException($"Invalid number of dimensions for LocalResponseNorm argument: {tensor.Dimensions}"); - var res = THSNN_LocalResponseNorm_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.local_response_norm(input, this.size, this.alpha, this.beta, this.k); } + + public long size { get; set; } + public double alpha { get; set; } + public double beta { get; set; } + public double k { get; set; } } } @@ -37,10 +43,24 @@ public static partial class nn /// public static LocalResponseNorm LocalResponseNorm(long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) { - unsafe { - var handle = THSNN_LocalResponseNorm_ctor(size, alpha, beta, k, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new LocalResponseNorm(handle, boxedHandle); + return new LocalResponseNorm(size, alpha, beta, k); + } + + public static partial class functional + { + + /// + /// Applies local response normalization over an input signal. + /// The input signal is composed of several input planes, where channels occupy the second dimension. + /// Applies normalization across channels. + /// + public static Tensor local_response_norm(Tensor input, long size, double alpha = 0.0001, double beta = 0.75, double k = 1.0) + { + if (input.Dimensions < 3) throw new ArgumentException($"Invalid number of dimensions for LocalResponseNorm argument: {input.Dimensions}"); + var res = THSNN_local_response_norm(input.Handle, size, alpha, beta, k); + if (res == IntPtr.Zero) + torch.CheckForErrors(); + return new Tensor(res); } } } diff --git a/src/TorchSharp/NN/Padding/PadBase.cs b/src/TorchSharp/NN/Padding/PadBase.cs index 6ae9bd87e..3a10de24c 100644 --- a/src/TorchSharp/NN/Padding/PadBase.cs +++ b/src/TorchSharp/NN/Padding/PadBase.cs @@ -12,7 +12,7 @@ namespace Modules /// /// This class is used to represent the base of all padding-related modules. /// - public class PadBase : ParamLessModule + public abstract class PadBase : ParamLessModule { protected PadBase(string name, PaddingModes mode, double value, params long[] padding) : base(name) { diff --git a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs index 1aa15f2e8..f2a505528 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad2d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReflectionPad2d : PadBase { - internal ReflectionPad2d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } + internal ReflectionPad2d(params long[] padding) : base(nameof(ReflectionPad2d), PaddingModes.Reflect, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs index cf26874ff..d1dbd584b 100644 --- a/src/TorchSharp/NN/Padding/ReflectionPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReflectionPad3d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReflectionPad3d : PadBase { - internal ReflectionPad3d(params long[] padding) : base(nameof(ReflectionPad1d), PaddingModes.Reflect, 0, padding) { } + internal ReflectionPad3d(params long[] padding) : base(nameof(ReflectionPad3d), PaddingModes.Reflect, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs index 0bd779b0e..81b25ee27 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad2d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad2d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReplicationPad2d : PadBase { - internal ReplicationPad2d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } + internal ReplicationPad2d(params long[] padding) : base(nameof(ReplicationPad2d), PaddingModes.Replicate, 0, padding) { } } } diff --git a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs index 5a243489e..7eddd4c8c 100644 --- a/src/TorchSharp/NN/Padding/ReplicationPad3d.cs +++ b/src/TorchSharp/NN/Padding/ReplicationPad3d.cs @@ -14,7 +14,7 @@ namespace Modules /// public sealed class ReplicationPad3d : PadBase { - internal ReplicationPad3d(params long[] padding) : base(nameof(ReplicationPad1d), PaddingModes.Replicate, 0, padding) { } + internal ReplicationPad3d(params long[] padding) : base(nameof(ReplicationPad3d), PaddingModes.Replicate, 0, padding) { } } } diff --git a/src/TorchSharp/NN/PixelShuffle.cs b/src/TorchSharp/NN/PixelShuffle.cs index e7054be2b..ddb459a57 100644 --- a/src/TorchSharp/NN/PixelShuffle.cs +++ b/src/TorchSharp/NN/PixelShuffle.cs @@ -12,29 +12,24 @@ namespace Modules /// /// This class is used to represent a dropout module. /// - public sealed class PixelShuffle : torch.nn.Module + public sealed class PixelShuffle : ParamLessModule { - internal PixelShuffle(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal PixelShuffle(long upscale_factor) : base(nameof(PixelShuffle)) + { + this.upscale_factor = upscale_factor; + } /// /// Forward pass. /// - /// Input tensor + /// Input tensor /// - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_PixelShuffle_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.pixel_shuffle(input, this.upscale_factor); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + + public long upscale_factor { get; set; } } } @@ -46,13 +41,11 @@ public static partial class nn /// Rearranges elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an upscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Factor to increase spatial resolution by + /// Factor to increase spatial resolution by /// - public static PixelShuffle PixelShuffle(long upscaleFactor) + public static PixelShuffle PixelShuffle(long upscale_factor) { - var handle = THSNN_PixelShuffle_ctor(upscaleFactor, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new PixelShuffle(handle, boxedHandle); + return new PixelShuffle(upscale_factor); } public static partial class functional @@ -61,15 +54,15 @@ public static partial class functional /// Rearranges elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an upscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Input tensor - /// Factor to increase spatial resolution by + /// Input tensor + /// Factor to increase spatial resolution by /// /// - public static Tensor pixel_shuffle(Tensor x, long upscaleFactor) + public static Tensor pixel_shuffle(Tensor input, long upscale_factor) { - using (var d = nn.PixelShuffle(upscaleFactor)) { - return d.call(x); - } + var res = THSNN_pixel_shuffle(input.Handle, upscale_factor); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } } } diff --git a/src/TorchSharp/NN/PixelUnshuffle.cs b/src/TorchSharp/NN/PixelUnshuffle.cs index 5467ab59b..6b4ab8b23 100644 --- a/src/TorchSharp/NN/PixelUnshuffle.cs +++ b/src/TorchSharp/NN/PixelUnshuffle.cs @@ -12,29 +12,24 @@ namespace Modules /// /// This class is used to represent a dropout module. /// - public sealed class PixelUnshuffle : torch.nn.Module + public sealed class PixelUnshuffle : ParamLessModule { - internal PixelUnshuffle(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal PixelUnshuffle(long downscale_factor) : base(nameof(PixelUnshuffle)) + { + this.downscale_factor = downscale_factor; + } /// /// Forward pass. /// - /// Input tensor + /// Input tensor /// - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_PixelUnshuffle_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.pixel_unshuffle(input, downscale_factor); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public long downscale_factor { get; set; } } } @@ -46,13 +41,11 @@ public static partial class nn /// /// Reverses the PixelShuffle operation by rearranging elements in a tensor of shape (*, C, H * r, W * r) to a tensor of shape (*, C * r^2, H, W), where r is an downscale factor. /// - /// Factor to increase spatial resolution by + /// Factor to increase spatial resolution by /// - public static PixelUnshuffle PixelUnshuffle(long downscaleFactor) + public static PixelUnshuffle PixelUnshuffle(long downscale_factor) { - var handle = THSNN_PixelUnshuffle_ctor(downscaleFactor, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new PixelUnshuffle(handle, boxedHandle); + return new PixelUnshuffle(downscale_factor); } public static partial class functional @@ -61,15 +54,15 @@ public static partial class functional /// Reverses the PixelShuffle operation by rearranging elements in a tensor of shape (*, C * r^2, H, W) to a tensor of shape(*, C, H * r, W * r), where r is an downscale factor. /// This is useful for implementing efficient sub-pixel convolution with a stride of 1/r. /// - /// Input tensor - /// Factor to increase spatial resolution by + /// Input tensor + /// Factor to increase spatial resolution by /// /// - public static Tensor pixel_unshuffle(Tensor x, long downscaleFactor) + public static Tensor pixel_unshuffle(Tensor input, long downscale_factor) { - using (var d = nn.PixelUnshuffle(downscaleFactor)) { - return d.call(x); - } + var res = THSNN_pixel_unshuffle(input.Handle, downscale_factor); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs index a658fb364..f1136eaa1 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool1D.cs @@ -14,16 +14,17 @@ namespace Modules /// public sealed class AdaptiveAvgPool1d : ParamLessModule { - internal AdaptiveAvgPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveAvgPool1d(long output_size) : base(nameof(AdaptiveAvgPool1d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveAvgPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_avg_pool1d(input, this.output_size); } + + public long output_size { get; set; } } } @@ -35,14 +36,11 @@ public static partial class nn /// Applies a 1D adaptive average pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// the target output size H + /// the target output size H /// - public static unsafe AdaptiveAvgPool1d AdaptiveAvgPool1d(long outputSize) + public static unsafe AdaptiveAvgPool1d AdaptiveAvgPool1d(long output_size) { - long* pkernelSize = stackalloc long[1] { outputSize }; - var handle = THSNN_AdaptiveAvgPool1d_ctor((IntPtr)pkernelSize, 1, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool1d(handle, boxedHandle); + return new AdaptiveAvgPool1d(output_size); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs index 91c61d096..04871729f 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool2D.cs @@ -14,16 +14,17 @@ namespace Modules /// public sealed class AdaptiveAvgPool2d : ParamLessModule { - internal AdaptiveAvgPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveAvgPool2d(long[] output_size) : base(nameof(AdaptiveAvgPool2d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveAvgPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_avg_pool2d(input, this.output_size); } + + public long[] output_size { get; set; } } } @@ -35,43 +36,33 @@ public static partial class nn /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long[] outputSize) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long[] output_size) { - fixed (long* poutputSize = outputSize) { - var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, outputSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool2d(handle, boxedHandle); - } + return new AdaptiveAvgPool2d(output_size); } /// /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d((long,long) outputSize) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d((long,long) output_size) { - long* poutputSize = stackalloc long[2] { outputSize.Item1, outputSize.Item2 }; - var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, 2, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool2d(handle, boxedHandle); + return new AdaptiveAvgPool2d(new[] { output_size.Item1, output_size.Item2 }); } /// /// Applies a 2D adaptive average pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (H,W) of the image of the form H x W. + /// The target output size (H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long outputSize) + public static unsafe AdaptiveAvgPool2d AdaptiveAvgPool2d(long output_size) { - long* poutputSize = stackalloc long[2] { outputSize, outputSize }; - var handle = THSNN_AdaptiveAvgPool2d_ctor((IntPtr)poutputSize, 2, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool2d(handle, boxedHandle); + return new AdaptiveAvgPool2d(new[] { output_size, output_size }); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs index f89426962..ce37c4f67 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveAvgPool3D.cs @@ -14,16 +14,17 @@ namespace Modules /// public sealed class AdaptiveAvgPool3d : ParamLessModule { - internal AdaptiveAvgPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveAvgPool3d(long[] output_size) : base(nameof(AdaptiveAvgPool3d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveAvgPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_avg_pool3d(input, this.output_size); } + + public long[] output_size { get; set; } } } @@ -35,44 +36,33 @@ public static partial class nn /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size of the image of the form D x H x W. + /// The target output size of the image of the form D x H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long[] outputSize) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long[] output_size) { - fixed (long* pkernelSize = outputSize) { - var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool3d(handle, boxedHandle); - } + return new AdaptiveAvgPool3d(output_size); } /// /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (D,H,W) of the image of the form D x H x W. + /// The target output size (D,H,W) of the image of the form D x H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d((long, long, long) outputSize) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d((long, long, long) output_size) { - long* pkernelSize = stackalloc long[3] { outputSize.Item1, outputSize.Item2, outputSize.Item3 }; - - var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, 3, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool3d(handle, boxedHandle); + return new AdaptiveAvgPool3d(new[] { output_size.Item1, output_size.Item2, output_size.Item3 }); } /// /// Applies a 3D adaptive average pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size (D,H,W) of the image of the form H x W. + /// The target output size (D,H,W) of the image of the form H x W. /// - public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long outputSize) + public static unsafe AdaptiveAvgPool3d AdaptiveAvgPool3d(long output_size) { - long* pkernelSize = stackalloc long[3] { outputSize, outputSize, outputSize }; - var handle = THSNN_AdaptiveAvgPool3d_ctor((IntPtr)pkernelSize, 3, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveAvgPool3d(handle, boxedHandle); + return new AdaptiveAvgPool3d(new [] { output_size, output_size, output_size }); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs index 5c71475cc..199aefaa5 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool1D.cs @@ -14,16 +14,22 @@ namespace Modules /// public sealed class AdaptiveMaxPool1d : ParamLessModule { - internal AdaptiveMaxPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveMaxPool1d(long output_size) : base(nameof(AdaptiveMaxPool1d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_AdaptiveMaxPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_max_pool1d_with_indices(input, this.output_size); } + + public override Tensor forward(Tensor input) + { + return torch.nn.functional.adaptive_max_pool1d(input, this.output_size); + } + + public long output_size { get; set; } } } @@ -35,17 +41,11 @@ public static partial class nn /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size H. + /// The target output size H. /// - public static AdaptiveMaxPool1d AdaptiveMaxPool1d(long outputSize) + public static AdaptiveMaxPool1d AdaptiveMaxPool1d(long output_size) { - unsafe { - fixed (long* pkernelSize = new long[] { outputSize }) { - var handle = THSNN_AdaptiveMaxPool1d_ctor((IntPtr)pkernelSize, 1, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveMaxPool1d(handle, boxedHandle); - } - } + return new AdaptiveMaxPool1d(output_size); } public static partial class functional @@ -54,13 +54,32 @@ public static partial class functional /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. /// The output size is H, for any input size.The number of output features is equal to the number of input planes. /// - /// - /// The target output size H. + /// + /// The target output size H. + /// + public static Tensor adaptive_max_pool1d(Tensor input, long output_size) + { + var ret = adaptive_max_pool1d_with_indices(input, output_size); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 1D adaptive max pooling over an input signal composed of several input planes. + /// The output size is H, for any input size.The number of output features is equal to the number of input planes. + /// + /// + /// The target output size H. /// - public static Tensor adaptive_max_pool1d(Tensor x, long outputSize) + public static (Tensor Values, Tensor Indices) adaptive_max_pool1d_with_indices(Tensor input, long output_size) { - using (var d = nn.AdaptiveMaxPool1d(outputSize)) { - return d.call(x); + var outputSizes = new long[] { output_size }; + unsafe { + fixed (long* poutputSize = outputSizes) { + var resOutput = THSTensor_adaptive_max_pool1d(input.Handle, (IntPtr)poutputSize, outputSizes.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs index 764d29732..8cba5c401 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool2D.cs @@ -14,16 +14,22 @@ namespace Modules /// public sealed class AdaptiveMaxPool2d : ParamLessModule { - internal AdaptiveMaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveMaxPool2d(long[] output_size) : base(nameof(AdaptiveMaxPool2d)) { + this.output_size = output_size; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveMaxPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_max_pool2d(input, this.output_size); } + + public (Tensor output, Tensor indices) forward_with_indices(Tensor input) + { + return torch.nn.functional.adaptive_max_pool2d_with_indices(input, this.output_size); + } + + public long[] output_size { get; set; } } } @@ -35,18 +41,12 @@ public static partial class nn /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - public static AdaptiveMaxPool2d AdaptiveMaxPool2d(long[] outputSize) + public static AdaptiveMaxPool2d AdaptiveMaxPool2d(long[] output_size) { - unsafe { - fixed (long* pkernelSize = outputSize) { - var handle = THSNN_AdaptiveMaxPool2d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveMaxPool2d(handle, boxedHandle); - } - } + return new AdaptiveMaxPool2d(output_size); } public static partial class functional @@ -55,14 +55,33 @@ public static partial class functional /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// - /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. + /// + public static Tensor adaptive_max_pool2d(Tensor input, long[] output_size) + { + var ret = adaptive_max_pool2d_with_indices(input, output_size); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. + /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. + /// + /// + /// Applies a 2D adaptive max pooling over an input signal composed of several input planes. /// The output is of size H x W, for any input size.The number of output features is equal to the number of input planes. /// - public static Tensor adaptive_max_pool2d(Tensor x, long[] outputSize) + public static (Tensor Values, Tensor Indices) adaptive_max_pool2d_with_indices(Tensor input, long[] output_size) { - using (var d = nn.AdaptiveMaxPool2d(outputSize)) { - return d.call(x); + unsafe { + fixed (long* poutputSize = output_size) { + var resOutput = THSTensor_adaptive_max_pool2d(input.Handle, (IntPtr)poutputSize, output_size.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs index ec3bfc32f..e59ce6565 100644 --- a/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AdaptiveMaxPool3D.cs @@ -14,16 +14,22 @@ namespace Modules /// public sealed class AdaptiveMaxPool3d : ParamLessModule { - internal AdaptiveMaxPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AdaptiveMaxPool3d(long[] output_size) : base(nameof(AdaptiveMaxPool3d)) { } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AdaptiveMaxPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.adaptive_max_pool3d(input, output_size); } + + public (Tensor output, Tensor indices) forward_with_indices(Tensor input) + { + return torch.nn.functional.adaptive_max_pool3d_with_indices(input, output_size); + } + + + public long[] output_size { get; set; } } } @@ -35,18 +41,12 @@ public static partial class nn /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The target output size of the image of the form D x H x W. + /// The target output size of the image of the form D x H x W. /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. /// - public static AdaptiveMaxPool3d AdaptiveMaxPool3d(long[] outputSize) + public static AdaptiveMaxPool3d AdaptiveMaxPool3d(long[] output_size) { - unsafe { - fixed (long* pkernelSize = outputSize) { - var handle = THSNN_AdaptiveMaxPool3d_ctor((IntPtr)pkernelSize, outputSize.Length, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AdaptiveMaxPool3d(handle, boxedHandle); - } - } + return new AdaptiveMaxPool3d(output_size); } public static partial class functional @@ -55,14 +55,33 @@ public static partial class functional /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. /// - /// The input tensor - /// The target output size of the image of the form D x H x W. + /// The input tensor + /// The target output size of the image of the form D x H x W. + /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. + /// + public static Tensor adaptive_max_pool3d(Tensor input, long[] output_size) + { + var ret = adaptive_max_pool3d_with_indices(input, output_size); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 3D adaptive max pooling over an input signal composed of several input planes. + /// The output is of size D x H x W, for any input size.The number of output features is equal to the number of input planes. + /// + /// The input tensor + /// The target output size of the image of the form D x H x W. /// Can be a tuple (D, H, W) or a single D for a cube D x D x D. D, H and W can be either a int, or null which means the size will be the same as that of the input. /// - public static Tensor adaptive_max_pool3d(Tensor x, long[] outputSize) + public static (Tensor Values, Tensor Indices) adaptive_max_pool3d_with_indices(Tensor input, long[] output_size) { - using (var d = nn.AdaptiveMaxPool3d(outputSize)) { - return d.call(x); + unsafe { + fixed (long* poutputSize = output_size) { + var resOutput = THSTensor_adaptive_max_pool1d(input.Handle, (IntPtr)poutputSize, output_size.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/AvgPool1D.cs b/src/TorchSharp/NN/Pooling/AvgPool1D.cs index 9df33da82..7dcd374b0 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool1D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool1D.cs @@ -14,16 +14,25 @@ namespace Modules /// public sealed class AvgPool1d : ParamLessModule { - internal AvgPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AvgPool1d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true) : base(nameof(AvgPool1d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.ceil_mode = ceil_mode; + this.count_include_pad = count_include_pad; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AvgPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.avg_pool1d(input, kernel_size, stride, padding, ceil_mode, count_include_pad); } + + public long kernel_size { get; set; } + public long? stride { get; set; } + public long? padding { get; set; } + public bool ceil_mode { get; set; } + public bool count_include_pad { get; set; } } } @@ -39,32 +48,9 @@ public static partial class nn /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation - /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static AvgPool1d AvgPool1d(long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool1d AvgPool1d(long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, bool count_include_pad = true) { - return stride.HasValue ? - AvgPool1d(new long[] { kernel_size }, new long[] { stride.Value }, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0) : - AvgPool1d(new long[] { kernel_size }, null, new long[] { padding }, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0); - } - - /// - /// Applies a 1D average pooling over an input signal composed of several input planes. - /// - /// The size of the window - /// The stride of the window. Default value is kernel_size - /// implicit zero padding to be added on both sides - /// Whether to use ceil instead of floor to compute the output shape - /// Whether to include the zero-padding in the averaging calculation - /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - private static AvgPool1d AvgPool1d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) - { - unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { - var handle = THSNN_AvgPool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)ppadding, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool1d(handle, boxedHandle); - } - } + return new AvgPool1d(kernel_size, stride, padding, ceil_mode, count_include_pad); } public static partial class functional diff --git a/src/TorchSharp/NN/Pooling/AvgPool2D.cs b/src/TorchSharp/NN/Pooling/AvgPool2D.cs index 77fe8d991..f44dfe42c 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool2D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool2D.cs @@ -5,6 +5,7 @@ namespace TorchSharp { + using System.Data; using Modules; namespace Modules @@ -14,16 +15,27 @@ namespace Modules /// public sealed class AvgPool2d : ParamLessModule { - internal AvgPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AvgPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) : base(nameof(AvgPool2d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.ceil_mode = ceil_mode; + this.count_include_pad = count_include_pad; + this.divisor_override = divisor_override; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AvgPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.avg_pool2d(input, kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } + public bool ceil_mode { get; set; } + public bool count_include_pad { get; set; } + public long? divisor_override { get; set; } } } @@ -35,18 +47,14 @@ public static partial class nn /// Applies a 2D average pooling over an input signal composed of several input planes. /// /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static unsafe AvgPool2d AvgPool2d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool2d AvgPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { - var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)ppadding, (padding == null ? 0 : padding.Length), ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool2d(handle, boxedHandle); - } + return new AvgPool2d(kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); } /// @@ -60,19 +68,10 @@ public static unsafe AvgPool2d AvgPool2d(long[] kernel_size, long[] strides = nu /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool2d AvgPool2d((long,long) kernel_size, (long,long)? stride = null, (long,long)? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; - long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; - - long pvalue1 = (padding == null) ? 0 : padding.Value.Item1; - long pvalue2 = (padding == null) ? 0 : padding.Value.Item2; - - long* pkernelSize = stackalloc long[2] { kernel_size.Item1, kernel_size.Item2 }; - long* pstrides = stackalloc long[2] { svalue1, svalue2 }; - long* ppadding = stackalloc long[2] { pvalue1, pvalue2 }; - - var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool2d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; + long[] strideValue = stride == null ? null : new[] { stride.Value.Item1, stride.Value.Item2 }; + long[] paddingValue = padding == null ? null : new[] { padding.Value.Item1, padding.Value.Item2 }; + return new AvgPool2d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); } /// @@ -84,18 +83,12 @@ public static unsafe AvgPool2d AvgPool2d((long,long) kernel_size, (long,long)? s /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static unsafe AvgPool2d AvgPool2d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool2d AvgPool2d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long svalue = (stride == null) ? kernel_size : stride.Value; - long pvalue = (padding == null) ? 0 : padding.Value; - - long* pkernelSize = stackalloc long[2] { kernel_size, kernel_size }; - long* pstrides = stackalloc long[2] { svalue, svalue }; - long* ppadding = stackalloc long[2] { pvalue, pvalue }; - - var handle = THSNN_AvgPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool2d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size, kernel_size }; + long[] strideValue = stride == null ? null : new[] { stride.Value, stride.Value }; + long[] paddingValue = padding == null ? null : new[] { padding.Value, padding.Value }; + return new AvgPool2d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); } public static partial class functional @@ -104,29 +97,32 @@ public static partial class functional /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// - /// - /// + /// + /// + /// /// /// + /// /// - public static Tensor avg_pool2d(Tensor input, long[] kernelSizes, - long[] strides = null, - long[] paddings = null, + public static Tensor avg_pool2d(Tensor input, long[] kernel_size, + long[] stride = null, + long[] padding = null, bool ceil_mode = false, - bool count_include_pad = true) + bool count_include_pad = true, + long? divisor_override = null) { - strides = (strides == null) ? new long[] { 1 } : strides; - paddings = (paddings == null) ? new long[] { 0 } : paddings; + stride = (stride == null) ? kernel_size : stride; + padding = (padding == null) ? new long[] { 0 } : padding; unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { + fixed (long* pkernelSize = kernel_size, pstrides = stride, ppadding = padding) { var res = THSTensor_avg_pool2d(input.Handle, - (IntPtr)pkernelSize, kernelSizes.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, paddings.Length, + (IntPtr)pkernelSize, kernel_size.Length, + (IntPtr)pstrides, stride.Length, + (IntPtr)ppadding, padding.Length, ceil_mode, - count_include_pad); + count_include_pad, + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -137,21 +133,23 @@ public static Tensor avg_pool2d(Tensor input, long[] kernelSizes, /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// + /// /// /// /// /// + /// /// - public static unsafe Tensor avg_pool2d(Tensor input, long kernelSize, + public static unsafe Tensor avg_pool2d(Tensor input, long kernel_size, long? stride = null, long padding = 0, bool ceil_mode = false, - bool count_include_pad = true) + bool count_include_pad = true, + long? divisor_override = null) { - long svalue = (stride == null) ? kernelSize : stride.Value; + long svalue = (stride == null) ? kernel_size : stride.Value; - long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; + long* pkernelSize = stackalloc long[2] { kernel_size, kernel_size }; long* pstrides = stackalloc long[2] { svalue, svalue }; long* ppadding = stackalloc long[2] { padding, padding }; @@ -161,7 +159,8 @@ public static unsafe Tensor avg_pool2d(Tensor input, long kernelSize, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, - count_include_pad); + count_include_pad, + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -170,27 +169,29 @@ public static unsafe Tensor avg_pool2d(Tensor input, long kernelSize, /// Applies 2D average-pooling operation in kH × kW regions by step size sH * sW steps. The number of output features is equal to the number of input planes. /// /// The input tensor. - /// + /// /// /// /// /// + /// /// - public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernelSize, + public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null, bool ceil_mode = false, - bool count_include_pad = true) + bool count_include_pad = true, + long? divisor_override = null) { - long svalue1 = (stride == null) ? kernelSize.Item1 : stride.Value.Item1; - long svalue2 = (stride == null) ? kernelSize.Item2 : stride.Value.Item2; + long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; + long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; long pvalue1 = padding != null ? padding.Value.Item1 : 0; long pvalue2 = padding != null ? padding.Value.Item2 : 0; long* pstrides = stackalloc long[2] { svalue1, svalue2 }; long* ppadding = stackalloc long[2] { pvalue1, pvalue2 }; - long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; + long* pkernelSize = stackalloc long[2] { kernel_size.Item1, kernel_size.Item2 }; var res = THSTensor_avg_pool2d(input.Handle, @@ -198,7 +199,8 @@ public static unsafe Tensor avg_pool2d(Tensor input, (long, long) kernelSize, (IntPtr)pstrides, 2, (IntPtr)ppadding, 2, ceil_mode, - count_include_pad); + count_include_pad, + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -209,7 +211,7 @@ public static Tensor avg_pool2d_backward(Tensor input, Tensor originalInput, long[] paddings = null, bool ceil_mode = false, bool count_include_pad = true, - long divisorOverride = 0) + long? divisor_override = null) { strides = (strides == null) ? new long[] { 1 } : strides; paddings = (paddings == null) ? new long[] { 0 } : paddings; @@ -222,7 +224,7 @@ public static Tensor avg_pool2d_backward(Tensor input, Tensor originalInput, (IntPtr)ppadding, paddings.Length, ceil_mode, count_include_pad, - divisorOverride); + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/AvgPool3D.cs b/src/TorchSharp/NN/Pooling/AvgPool3D.cs index bedc81f0a..d08304bdc 100644 --- a/src/TorchSharp/NN/Pooling/AvgPool3D.cs +++ b/src/TorchSharp/NN/Pooling/AvgPool3D.cs @@ -14,16 +14,27 @@ namespace Modules /// public sealed class AvgPool3d : ParamLessModule { - internal AvgPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal AvgPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) : base(nameof(AvgPool3d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.ceil_mode = ceil_mode; + this.count_include_pad = count_include_pad; + this.divisor_override = divisor_override; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_AvgPool3d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.avg_pool3d(input, kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } + public bool ceil_mode { get; set; } + public bool count_include_pad { get; set; } + public long? divisor_override { get; set; } } } @@ -35,20 +46,14 @@ public static partial class nn /// Applies a 3D average pooling over an input signal composed of several input planes. /// /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// implicit zero padding to be added on both sides /// Whether to use ceil instead of floor to compute the output shape /// Whether to include the zero-padding in the averaging calculation /// If specified, it will be used as divisor, otherwise size of the pooling region will be used - public static AvgPool3d AvgPool3d(long[] kernel_size, long[] strides = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) + public static AvgPool3d AvgPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = strides, ppadding = padding) { - var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)ppadding, (padding == null ? 0 : padding.Length), ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool3d(handle, boxedHandle); - } - } + return new AvgPool3d(kernel_size, stride, padding, ceil_mode, count_include_pad, divisor_override); } /// @@ -62,21 +67,10 @@ public static AvgPool3d AvgPool3d(long[] kernel_size, long[] strides = null, lon /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool3d AvgPool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long svalue1 = (stride == null) ? kernel_size.Item1 : stride.Value.Item1; - long svalue2 = (stride == null) ? kernel_size.Item2 : stride.Value.Item2; - long svalue3 = (stride == null) ? kernel_size.Item3 : stride.Value.Item3; - - long pvalue1 = (padding == null) ? 0 : padding.Value.Item1; - long pvalue2 = (padding == null) ? 0 : padding.Value.Item2; - long pvalue3 = (padding == null) ? 0 : padding.Value.Item3; - - long* pkernelSize = stackalloc long[3] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }; - long* pstrides = stackalloc long[3] { svalue1, svalue2, svalue3 }; - long* ppadding = stackalloc long[3] { pvalue1, pvalue2, pvalue3 }; - - var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, 3, (IntPtr)pstrides, 3, (IntPtr)ppadding, 3, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool3d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }; + long[] strideValue = stride == null ? null : new[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 }; + long[] paddingValue = padding == null ? null : new[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 }; + return new AvgPool3d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); } /// @@ -90,16 +84,10 @@ public static unsafe AvgPool3d AvgPool3d((long, long, long) kernel_size, (long, /// If specified, it will be used as divisor, otherwise size of the pooling region will be used public static unsafe AvgPool3d AvgPool3d(long kernel_size, long? stride = null, long? padding = null, bool ceil_mode = false, bool count_include_pad = true, long? divisor_override = null) { - long svalue = (stride == null) ? kernel_size : stride.Value; - long pvalue = (padding == null) ? 0 : padding.Value; - - long* pkernelSize = stackalloc long[3] { kernel_size, kernel_size, kernel_size }; - long* pstrides = stackalloc long[3] { svalue, svalue, svalue }; - long* ppadding = stackalloc long[3] { pvalue, pvalue, pvalue }; - - var handle = THSNN_AvgPool3d_ctor((IntPtr)pkernelSize, 3, (IntPtr)pstrides, 3, (IntPtr)ppadding, 3, ceil_mode, count_include_pad, divisor_override.HasValue ? divisor_override.Value : 0, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new AvgPool3d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size, kernel_size, kernel_size }; + long[] strideValue = stride == null ? null : new[] { stride.Value, stride.Value, stride.Value }; + long[] paddingValue = padding == null ? null : new[] { padding.Value, padding.Value, padding.Value }; + return new AvgPool3d(kernelValue, strideValue, paddingValue, ceil_mode, count_include_pad, divisor_override); } public static partial class functional @@ -108,29 +96,31 @@ public static partial class functional /// Applies 3D average-pooling operation in kT x kH x kW regions by step size sT x sH x sW steps. /// /// The input tensor. - /// - /// - /// + /// + /// + /// /// /// + /// /// - public static Tensor avg_pool3d(Tensor input, long[] kernelSizes, - long[] strides = null, - long[] paddings = null, + public static Tensor avg_pool3d(Tensor input, long[] kernel_size, + long[] stride = null, + long[] padding = null, bool ceil_mode = false, - bool count_include_pad = true) + bool count_include_pad = true, + long? divisor_override = null) { - strides = (strides == null) ? new long[] { 1 } : strides; - paddings = (paddings == null) ? new long[] { 0 } : paddings; + stride = (stride == null) ? kernel_size : stride; + padding = (padding == null) ? new long[] { 0 } : padding; unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { + fixed (long* pkernelSize = kernel_size, pstrides = stride, ppadding = padding) { var res = THSTensor_avg_pool3d(input.Handle, - (IntPtr)pkernelSize, kernelSizes.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, paddings.Length, + (IntPtr)pkernelSize, kernel_size.Length, + (IntPtr)pstrides, stride.Length, + (IntPtr)ppadding, padding.Length, ceil_mode, - count_include_pad); + count_include_pad, divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } @@ -143,9 +133,9 @@ public static Tensor avg_pool3d_backward(Tensor input, Tensor originalInput, long[] paddings = null, bool ceil_mode = false, bool count_include_pad = true, - long divisorOverride = 0) + long? divisor_override = null) { - strides = (strides == null) ? new long[] { 1 } : strides; + strides = (strides == null) ? kernelSizes : strides; paddings = (paddings == null) ? new long[] { 0 } : paddings; unsafe { fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings) { @@ -156,7 +146,7 @@ public static Tensor avg_pool3d_backward(Tensor input, Tensor originalInput, (IntPtr)ppadding, paddings.Length, ceil_mode, count_include_pad, - divisorOverride); + divisor_override ?? 0); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs index eecc1c4a3..e37d17083 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool2d.cs @@ -5,6 +5,7 @@ namespace TorchSharp { + using System.Data; using Modules; namespace Modules @@ -14,23 +15,26 @@ namespace Modules /// public sealed class FractionalMaxPool2d : ParamLessModule { - internal FractionalMaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal FractionalMaxPool2d(long[] kernel_size, long[] output_size = null, double[] output_ratio = null) : base(nameof(FractionalMaxPool2d)) { + this.kernel_size = kernel_size; + this.output_size = output_size; + this.output_ratio = output_ratio; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_FractionalMaxPool2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.fractional_max_pool2d(input, kernel_size, output_size, output_ratio); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_FractionalMaxPool2d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.fractional_max_pool2d_with_indices(input, kernel_size, output_size, output_ratio); } + + public long[] kernel_size { get; set; } + public long[] output_size { get; set; } + public double[] output_ratio { get; set; } } } @@ -95,16 +99,135 @@ public static FractionalMaxPool2d FractionalMaxPool2d(long[] kernel_size, long[] if (output_size != null && output_ratio != null) throw new ArgumentNullException("FractionalMaxPool2d requires specifying either an output size, or a pooling ratio."); - unsafe { - fixed (long* pkernelSize = kernel_size, pSize = output_size) { - fixed (double* pRatio = output_ratio) { - var handle = THSNN_FractionalMaxPool2d_ctor( - (IntPtr)pkernelSize, kernel_size.Length, - (IntPtr)pSize, (output_size == null ? 0 : output_size.Length), - (IntPtr)pRatio, (output_ratio == null ? 0 : output_ratio.Length), - out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new FractionalMaxPool2d(handle, boxedHandle); + return new FractionalMaxPool2d(kernel_size, output_size, output_ratio); + } + + public static partial class functional + { + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool2d(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value } : null; + return fractional_max_pool2d(input, new long[] { kernel_size, kernel_size }, pSize, pRatio); + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool2d(Tensor input, (long, long) kernel_size, (long, long)? output_size = null, (double, double)? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2 } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2 } : null; + return fractional_max_pool2d(input, new long[] { kernel_size.Item1, kernel_size.Item2 }, pSize, pRatio); + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool2d(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) + { + var ret = fractional_max_pool2d_with_indices(input, kernel_size, output_size, output_ratio); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value } : null; + return fractional_max_pool2d_with_indices(input, new long[] { kernel_size, kernel_size }, pSize, pRatio); + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, (long, long) kernel_size, (long, long)? output_size = null, (double, double)? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2 } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2 } : null; + return fractional_max_pool2d_with_indices(input, new long[] { kernel_size.Item1, kernel_size.Item2 }, pSize, pRatio); + } + + /// + /// Applies a 2D fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool2d_with_indices(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) + { + if (kernel_size == null || kernel_size.Length != 2) + throw new ArgumentException("Kernel size must contain two elements."); + if (output_size != null && output_size.Length != 2) + throw new ArgumentException("output_size must contain two elements."); + if (output_ratio != null && output_ratio.Length != 2) + throw new ArgumentException("output_ratio must contain two elements."); + if (output_size == null && output_ratio == null) + throw new ArgumentNullException("Only one of output_size and output_ratio may be specified."); + if (output_size != null && output_ratio != null) + throw new ArgumentNullException("FractionalMaxPool2d requires specifying either an output size, or a pooling ratio."); + + output_size ??= Array.Empty(); + output_ratio ??= Array.Empty(); + + unsafe { + fixed (long* pkernelSize = kernel_size, poutputSize = output_size) { + fixed (double* poutputRatio = output_ratio) { + var resOutput = THSTensor_fractional_max_pool2d(input.Handle, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)poutputRatio, output_ratio.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs index 692f2210f..98ac3d0eb 100644 --- a/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs +++ b/src/TorchSharp/NN/Pooling/FractionalMaxPool3d.cs @@ -14,34 +14,26 @@ namespace Modules /// public sealed class FractionalMaxPool3d : ParamLessModule { - internal FractionalMaxPool3d(IntPtr handle, IntPtr boxedHandle, bool ratio) : base(handle, boxedHandle) + internal FractionalMaxPool3d(long[] kernel_size, long[] output_size = null, double[] output_ratio = null) : base(nameof(FractionalMaxPool3d)) { - _used_ratio = ratio; + this.kernel_size = kernel_size; + this.output_size = output_size; + this.output_ratio = output_ratio; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - if (_used_ratio && tensor.ndim != 5) - // Not sure why this is the case, but there's an exception in the native runtime - // unless there's both a batch dimension and a channel dimension. - throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); - var res = THSNN_FractionalMaxPool3d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.fractional_max_pool3d(input, kernel_size, output_size, output_ratio); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - if (_used_ratio && tensor.ndim != 5) - // Not sure why this is the case, but there's an exception in the native runtime - // unless there's both a batch dimension and a channel dimension. - throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); - var res = THSNN_FractionalMaxPool3d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.fractional_max_pool3d_with_indices(input, kernel_size, output_size, output_ratio); } - private bool _used_ratio = false; + public long[] kernel_size { get; set; } + public long[] output_size { get; set; } + public double[] output_ratio { get; set; } } } @@ -106,16 +98,139 @@ public static FractionalMaxPool3d FractionalMaxPool3d(long[] kernel_size, long[] if (output_size != null && output_ratio != null) throw new ArgumentNullException("FractionalMaxPool3d requires specifying either an output size, or a pooling ratio."); - unsafe { - fixed (long* pkernelSize = kernel_size, pSize = output_size) { - fixed (double* pRatio = output_ratio) { - var handle = THSNN_FractionalMaxPool3d_ctor( - (IntPtr)pkernelSize, kernel_size.Length, - (IntPtr)pSize, (output_size == null ? 0 : output_size.Length), - (IntPtr)pRatio, (output_ratio == null ? 0 : output_ratio.Length), - out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new FractionalMaxPool3d(handle, boxedHandle, output_ratio != null); + return new FractionalMaxPool3d(kernel_size, output_size, output_ratio); + } + + public static partial class functional + { + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool3d(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value, output_size.Value } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value, output_ratio.Value } : null; + return fractional_max_pool3d(input, new long[] { kernel_size, kernel_size, kernel_size }, pSize, pRatio); + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool3d(Tensor input, (long, long, long) kernel_size, (long, long, long)? output_size = null, (double, double, double)? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2, output_size.Value.Item3 } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2, output_ratio.Value.Item3 } : null; + return fractional_max_pool3d(input, new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pSize, pRatio); + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static Tensor fractional_max_pool3d(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) + { + var ret = fractional_max_pool3d_with_indices(input, kernel_size, output_size, output_ratio); + ret.Indices.Dispose(); + return ret.Values; + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, long kernel_size, long? output_size = null, double? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value, output_size.Value, output_size.Value } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value, output_ratio.Value, output_ratio.Value } : null; + return fractional_max_pool3d_with_indices(input, new long[] { kernel_size, kernel_size, kernel_size }, pSize, pRatio); + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, (long, long, long) kernel_size, (long, long, long)? output_size = null, (double, double, double)? output_ratio = null) + { + var pSize = output_size.HasValue ? new long[] { output_size.Value.Item1, output_size.Value.Item2, output_size.Value.Item3 } : null; + var pRatio = output_ratio.HasValue ? new double[] { output_ratio.Value.Item1, output_ratio.Value.Item2, output_ratio.Value.Item3 } : null; + return fractional_max_pool3d_with_indices(input, new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pSize, pRatio); + } + + /// + /// Applies a 3d fractional max pooling over an input signal composed of several input planes. + /// + /// Fractional MaxPooling is described in detail in the paper Fractional MaxPooling by Ben Graham, + /// see: https://arxiv.org/abs/1412.6071 + /// + /// The input tensor + /// The size of the sliding window, must be > 0. + /// The target output size of the image of the form oH x oW. Can be a tuple (oH, oW) or a single number oH for a square image oH x oH + /// If one wants to have an output size as a ratio of the input size, this option can be given. This has to be a number or tuple in the range (0, 1) + /// + public static (Tensor Values, Tensor Indices) fractional_max_pool3d_with_indices(Tensor input, long[] kernel_size, long[] output_size = null, double[] output_ratio = null) + { + if (kernel_size == null || kernel_size.Length != 3) + throw new ArgumentException("Kernel size must contain three elements."); + if (output_size != null && output_size.Length != 3) + throw new ArgumentException("output_size must contain three elements."); + if (output_ratio != null && output_ratio.Length != 3) + throw new ArgumentException("output_ratio must contain three elements."); + if (output_size == null && output_ratio == null) + throw new ArgumentNullException("Only one of output_size and output_ratio may be specified."); + if (output_size != null && output_ratio != null) + throw new ArgumentNullException("FractionalMaxPool3d requires specifying either an output size, or a pooling ratio."); + if (output_ratio != null && input.ndim != 5) + // Not sure why this is the case, but there's an exception in the native runtime + // unless there's both a batch dimension and a channel dimension. + throw new ArgumentException("FractionalMaxPool3d: input tensor must have 5 dimensions: [N, C, D, H, W]"); + + output_size ??= Array.Empty(); + output_ratio ??= Array.Empty(); + + unsafe { + fixed (long* pkernelSize = kernel_size, poutputSize = output_size) { + fixed (double* poutputRatio = output_ratio) { + var resOutput = THSTensor_fractional_max_pool3d(input.Handle, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)poutputRatio, output_ratio.Length, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); + } } } } diff --git a/src/TorchSharp/NN/Pooling/LPPool1d.cs b/src/TorchSharp/NN/Pooling/LPPool1d.cs index 62e4a2a4e..9babde806 100644 --- a/src/TorchSharp/NN/Pooling/LPPool1d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool1d.cs @@ -14,16 +14,23 @@ namespace Modules /// public sealed class LPPool1d : ParamLessModule { - internal LPPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal LPPool1d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) : base(nameof(LPPool1d)) { + this.norm_type = norm_type; + this.kernel_size = kernel_size; + this.stride = stride; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_LPPool1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.lp_pool1d(input, norm_type, kernel_size, stride, ceil_mode); } + + public double norm_type { get; set; } + public long kernel_size { get; set; } + public long? stride { get; set; } + public bool ceil_mode { get; set; } } } @@ -35,32 +42,37 @@ public static partial class nn /// Applies a 1D power-average pooling over an input signal composed of several input planes. /// /// The LP norm (exponent) - /// The size of the window + /// The size of the window /// The stride of the window. Default value is kernel_size /// Use ceil instead of floor to compute the output shape /// - public static LPPool1d LPPool1d(double norm_type, long kernelSize, long? stride = null, bool ceil_mode = false) + public static LPPool1d LPPool1d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) { - return stride.HasValue ? - LPPool1d(norm_type, new long[] { kernelSize }, new long[] { stride.Value }, ceil_mode) : - LPPool1d(norm_type, new long[] { kernelSize }, null); + return new LPPool1d(norm_type, kernel_size, stride, ceil_mode); } - /// - /// Applies a 1D power-average pooling over an input signal composed of several input planes. - /// - /// The LP norm (exponent) - /// The size of the window - /// The stride of the window. Default value is kernel_size - /// Use ceil instead of floor to compute the output shape - /// - private static LPPool1d LPPool1d(double norm_type, long[] kernelSize, long[] strides = null, bool ceil_mode = false) + public static partial class functional { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides) { - var handle = THSNN_LPPool1d_ctor(norm_type, (IntPtr)pkernelSize, (IntPtr)pstrides, ceil_mode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new LPPool1d(handle, boxedHandle); + /// + /// Applies a 1D power-average pooling over an input signal composed of several input planes. + /// + /// The input tensor + /// The LP norm (exponent) + /// The size of the window + /// The stride of the window. Default value is kernel_size + /// Use ceil instead of floor to compute the output shape + /// + public static Tensor lp_pool1d(Tensor input, double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) + { + var kernels = new[] { kernel_size }; + var strides = stride.HasValue ? new[] { stride.Value } : Array.Empty(); + + unsafe { + fixed (long* pkernelSize = kernels, pstrides = strides) { + var res = THSTensor_lp_pool1d(input.Handle, norm_type, (IntPtr)pkernelSize, kernels.Length, (IntPtr)pstrides, strides.Length, ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } } } } diff --git a/src/TorchSharp/NN/Pooling/LPPool2d.cs b/src/TorchSharp/NN/Pooling/LPPool2d.cs index 8555803de..4fe66dafd 100644 --- a/src/TorchSharp/NN/Pooling/LPPool2d.cs +++ b/src/TorchSharp/NN/Pooling/LPPool2d.cs @@ -14,16 +14,23 @@ namespace Modules /// public sealed class LPPool2d : ParamLessModule { - internal LPPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal LPPool2d(double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) : base(nameof(LPPool2d)) { + this.norm_type = norm_type; + this.kernel_size = kernel_size; + this.stride = stride; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_LPPool2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.lp_pool2d(input, norm_type, kernel_size, stride, ceil_mode); } + + public double norm_type { get; set; } + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public bool ceil_mode { get; set; } } } @@ -36,18 +43,12 @@ public static partial class nn /// /// The LP norm (exponent) /// The size of the window - /// The stride of the window. Default value is kernel_size + /// The stride of the window. Default value is kernel_size /// Use ceil instead of floor to compute the output shape /// - public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] strides = null, bool ceil_mode = false) + public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) { - unsafe { - fixed (long* pkernelSize = kernel_size, pstrides = strides) { - var handle = THSNN_LPPool2d_ctor(norm_type, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), ceil_mode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new LPPool2d(handle, boxedHandle); - } - } + return new LPPool2d(norm_type, kernel_size, stride, ceil_mode); } /// @@ -60,9 +61,46 @@ public static LPPool2d LPPool2d(double norm_type, long[] kernel_size, long[] str /// public static LPPool2d LPPool2d(double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) { - return stride.HasValue ? - LPPool2d(norm_type, new long[] { kernel_size, kernel_size }, new long[] { stride.Value, stride.Value }, ceil_mode) : - LPPool2d(norm_type, new long[] { kernel_size, kernel_size }, null, ceil_mode); + return new LPPool2d(norm_type, new[] { kernel_size, kernel_size }, stride.HasValue ? new[] { stride.Value, stride.Value } : null, ceil_mode); + } + + public static partial class functional + { + /// + /// Applies a 2D power-average pooling over an input signal composed of several input planes. + /// + /// The input tensor + /// The LP norm (exponent) + /// The size of the window + /// The stride of the window. Default value is kernel_size + /// Use ceil instead of floor to compute the output shape + /// + public static Tensor lp_pool2d(Tensor input, double norm_type, long[] kernel_size, long[] stride = null, bool ceil_mode = false) + { + stride ??= Array.Empty(); + + unsafe { + fixed (long* pkernelSize = kernel_size, pstrides = stride) { + var res = THSTensor_lp_pool2d(input.Handle, norm_type, (IntPtr)pkernelSize, kernel_size.Length, (IntPtr)pstrides, stride.Length, ceil_mode); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } + } + } + + /// + /// Applies a 2D power-average pooling over an input signal composed of several input planes. + /// + /// The input tensor + /// The LP norm (exponent) + /// The size of the window + /// The stride of the window. + /// Use ceil instead of floor to compute the output shape + /// + public static Tensor lp_pool2d(Tensor input, double norm_type, long kernel_size, long? stride = null, bool ceil_mode = false) + { + return lp_pool2d(input, norm_type, new[] { kernel_size, kernel_size }, stride.HasValue ? new[] { stride.Value, stride.Value } : null, ceil_mode); + } } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool1D.cs b/src/TorchSharp/NN/Pooling/MaxPool1D.cs index 46254dcd7..558664c74 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool1D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool1D.cs @@ -15,23 +15,30 @@ namespace Modules /// public sealed class MaxPool1d : ParamLessModule { - internal MaxPool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxPool1d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) : base(nameof(MaxPool1d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.dilation = dilation; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_MaxPool1d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.max_pool1d(input, kernel_size, stride, padding, dilation, ceil_mode); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_MaxPool1d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.max_pool1d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); } + + public long kernel_size { get; set; } + public long? stride { get; set; } + public long? padding { get; set; } + public long? dilation { get; set; } + public bool ceil_mode { get; set; } } } @@ -42,100 +49,56 @@ public static partial class nn /// /// Applies a 1D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool1d MaxPool1d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) + public static MaxPool1d MaxPool1d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - var pStride = stride.HasValue ? new long[] { stride.Value } : null; - var pPadding = padding.HasValue ? new long[] { padding.Value } : null; - var pDilation = dilation.HasValue ? new long[] { dilation.Value } : null; - return MaxPool1d(new long[] { kernelSize }, pStride, pPadding, pDilation, ceilMode); - } - - private static MaxPool1d MaxPool1d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) - { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { - var handle = THSNN_MaxPool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)pPadding, (IntPtr)pDilation, ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool1d(handle, boxedHandle); - } - } + return new MaxPool1d(kernel_size, stride, padding, dilation, ceil_mode); } public static partial class functional { - /// - /// Applies a 1D max pooling over an input signal composed of several input planes. - /// - /// The input tensor. - /// - /// - /// - /// - /// - /// - public static Tensor max_pool1d(Tensor input, long kernelSize, long? stride = null, + public static Tensor max_pool1d(Tensor input, long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - var kernelSizes = new long[] { kernelSize }; - var strides = new long[] { stride ?? kernelSize }; - var paddings = new long[] { padding ?? 0 }; - var dilations = new long[] { dilation ?? 1 }; - unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { - var res = - THSTensor_max_pool1d(input.Handle, - (IntPtr)pkernelSize, kernelSizes.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, paddings.Length, - (IntPtr)pdilation, dilations.Length, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + var ret = max_pool1d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// /// Applies a 1D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static (Tensor output, Tensor indices) max_pool1d_with_indices(Tensor input, long kernelSize, long? stride = null, + public static (Tensor Values, Tensor Indices) max_pool1d_with_indices(Tensor input, long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - var kernelSizes = new long[] { kernelSize }; - var strides = new long[] { stride ?? kernelSize }; + var kernelSizes = new long[] { kernel_size }; + var strides = new long[] { stride ?? kernel_size }; var paddings = new long[] { padding ?? 0 }; var dilations = new long[] { dilation ?? 1 }; - IntPtr[] ptrArray; - - using (var pa = new PinnedArray()) { - unsafe { - fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { - THSTensor_max_pool1d_with_indices(input.Handle, - pa.CreateArray, + unsafe { + fixed (long* pkernelSize = kernelSizes, pstrides = strides, ppadding = paddings, pdilation = dilations) { + var resOutput = THSTensor_max_pool1d_with_indices(input.Handle, (IntPtr)pkernelSize, kernelSizes.Length, (IntPtr)pstrides, strides.Length, (IntPtr)ppadding, paddings.Length, (IntPtr)pdilation, dilations.Length, - ceil_mode); - torch.CheckForErrors(); - } + ceil_mode, out var resIndices); + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); } - ptrArray = pa.Array; } - return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool2D.cs b/src/TorchSharp/NN/Pooling/MaxPool2D.cs index 7d96145df..2cef87ce6 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool2D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool2D.cs @@ -15,22 +15,30 @@ namespace Modules /// public sealed class MaxPool2d : ParamLessModule { - internal MaxPool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) : base(nameof(MaxPool2d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.dilation = dilation; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_MaxPool2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.max_pool2d(input, kernel_size, stride, padding, dilation, ceil_mode); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_MaxPool2d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.max_pool2d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } + public long[] dilation { get; set; } + public bool ceil_mode { get; set; } } } @@ -41,74 +49,53 @@ public static partial class nn /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static unsafe MaxPool2d MaxPool2d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) + public static MaxPool2d MaxPool2d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - long svalue = stride.HasValue ? stride.Value : kernelSize; - long pvalue = padding.HasValue ? padding.Value : 0; - long dvalue = dilation.HasValue ? dilation.Value : 1; - - long* pStride = stackalloc long[2] { svalue, svalue }; - long* pPadding = stackalloc long[2] { pvalue, pvalue }; - long* pDilation = stackalloc long[2] { dvalue, dvalue }; + long[] kernelValue = new[] { kernel_size, kernel_size }; + long[] strideValue = stride.HasValue ? new[] { stride.Value, stride.Value } : kernelValue.ToArray(); + long[] paddingValue = padding.HasValue ? new[] { padding.Value, padding.Value } : new[] { 0L, 0L }; + long[] dilationValue = dilation.HasValue ? new[] { dilation.Value, dilation.Value } : new[] { 1L, 1L }; - long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; - - var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pStride, 2, (IntPtr)pPadding, 2, (IntPtr)pDilation, 2, ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool2d(handle, boxedHandle); + return new MaxPool2d(kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static unsafe MaxPool2d MaxPool2d((long, long) kernelSize, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceilMode = false) + public static unsafe MaxPool2d MaxPool2d((long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceil_mode = false) { - long svalue1 = stride != null ? stride.Value.Item1 : kernelSize.Item1; - long svalue2 = stride != null ? stride.Value.Item2 : kernelSize.Item2; - long pvalue1 = padding != null ? padding.Value.Item1 : 0; - long pvalue2 = padding != null ? padding.Value.Item2 : 0; - long dvalue1 = dilation != null ? dilation.Value.Item1 : 1; - long dvalue2 = dilation != null ? dilation.Value.Item2 : 1; - - long* pStride = stackalloc long[2] { svalue1, svalue2 }; - long* pPadding = stackalloc long[2] { pvalue1, pvalue2 }; - long* pDilation = stackalloc long[2] { dvalue1, dvalue2 }; - - long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; - - var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, 2, (IntPtr)pStride, 2, (IntPtr)pPadding, 2, (IntPtr)pDilation, 2, ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool2d(handle, boxedHandle); + long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; + long[] strideValue = stride.HasValue ? new[] { stride.Value.Item1, stride.Value.Item2 } : kernelValue.ToArray(); + long[] paddingValue = padding.HasValue ? new[] { padding.Value.Item1, padding.Value.Item2 } : new[] { 0L, 0L }; + long[] dilationValue = dilation.HasValue ? new[] { dilation.Value.Item1, dilation.Value.Item2 } : new[] { 1L, 1L }; + + return new MaxPool2d(kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static unsafe MaxPool2d MaxPool2d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) + public static MaxPool2d MaxPool2d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { - var handle = THSNN_MaxPool2d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), (IntPtr)pDilation, (dilation == null ? 0 : dilation.Length), ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool2d(handle, boxedHandle); - } + return new MaxPool2d(kernel_size, stride, padding, dilation, ceil_mode); } public static partial class functional @@ -117,100 +104,64 @@ public static partial class functional /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// - /// + /// + /// /// /// /// /// - public static Tensor max_pool2d(Tensor input, long[] kernelSize, long[] strides = null, + public static Tensor max_pool2d(Tensor input, long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides = strides ?? kernelSize; - padding = padding ?? kernelSize.Select(x => 0L).ToArray(); - dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - var res = - THSTensor_max_pool2d(input.Handle, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + var ret = max_pool2d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static unsafe Tensor max_pool2d(Tensor input, long kernelSize, long? stride = null, + public static Tensor max_pool2d(Tensor input, long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { - long svalue = stride.HasValue ? stride.Value : kernelSize; - long pvalue = padding.HasValue ? padding.Value : 0; - long dvalue = dilation.HasValue ? dilation.Value : 1; - - long* pStride = stackalloc long[2] { svalue, svalue }; - long* pPadding = stackalloc long[2] { pvalue, pvalue }; - long* pDilation = stackalloc long[2] { dvalue, dvalue }; - - long* pkernelSize = stackalloc long[2] { kernelSize, kernelSize }; - - var res = THSTensor_max_pool2d(input.Handle, - (IntPtr)pkernelSize, 2, - (IntPtr)pStride, 2, - (IntPtr)pPadding, 2, - (IntPtr)pDilation, 2, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + long[] kernelValue = new[] { kernel_size, kernel_size }; + long[] strideValue = stride.HasValue ? new[] { stride.Value, stride.Value } : kernelValue.ToArray(); + long[] paddingValue = padding.HasValue ? new[] { padding.Value, padding.Value } : new[] { 0L, 0L }; + long[] dilationValue = dilation.HasValue ? new[] { dilation.Value, dilation.Value } : new[] { 1L, 1L }; + + var ret = max_pool2d_with_indices(input, kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// + /// /// /// /// /// /// - public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernelSize, (long, long)? stride = null, + public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null, (long, long)? dilation = null, bool ceil_mode = false) { - long svalue1 = stride != null ? stride.Value.Item1 : kernelSize.Item1; - long svalue2 = stride != null ? stride.Value.Item2 : kernelSize.Item2; - long pvalue1 = padding != null ? padding.Value.Item1 : 0; - long pvalue2 = padding != null ? padding.Value.Item2 : 0; - long dvalue1 = dilation != null ? dilation.Value.Item1 : 1; - long dvalue2 = dilation != null ? dilation.Value.Item2 : 1; - - long* pStride = stackalloc long[2] { svalue1, svalue2 }; - long* pPadding = stackalloc long[2] { pvalue1, pvalue2 }; - long* pDilation = stackalloc long[2] { dvalue1, dvalue2 }; - - long* pkernelSize = stackalloc long[2] { kernelSize.Item1, kernelSize.Item2 }; - - var res = THSTensor_max_pool2d(input.Handle, - (IntPtr)pkernelSize, 2, - (IntPtr)pStride, 2, - (IntPtr)pPadding, 2, - (IntPtr)pDilation, 2, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + long[] kernelValue = new[] { kernel_size.Item1, kernel_size.Item2 }; + long[] strideValue = stride.HasValue ? new[] { stride.Value.Item1, stride.Value.Item2 } : kernelValue.ToArray(); + long[] paddingValue = padding.HasValue ? new[] { padding.Value.Item1, padding.Value.Item2 } : new[] { 0L, 0L }; + long[] dilationValue = dilation.HasValue ? new[] { dilation.Value.Item1, dilation.Value.Item2 } : new[] { 1L, 1L }; + + var ret = max_pool2d_with_indices(input, kernelValue, strideValue, paddingValue, dilationValue, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// @@ -223,30 +174,25 @@ public static unsafe Tensor max_pool2d(Tensor input, (long, long) kernelSize, (l /// /// /// - public static (Tensor output, Tensor indices) max_pool2d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, + public static (Tensor Values, Tensor Indices) max_pool2d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides = strides ?? kernelSize; - padding = padding ?? kernelSize.Select(x => 0L).ToArray(); - dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); - IntPtr[] ptrArray; - - using (var pa = new PinnedArray()) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - THSTensor_max_pool2d_with_indices(input.Handle, - pa.CreateArray, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode); - torch.CheckForErrors(); - } + strides ??= kernelSize; + padding ??= kernelSize.Select(x => 0L).ToArray(); + dilation ??= kernelSize.Select(x => 1L).ToArray(); + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { + var resOutput = THSTensor_max_pool2d_with_indices(input.Handle, + (IntPtr)pkernelSize, kernelSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length, + (IntPtr)pdilation, dilation.Length, + ceil_mode, out var resIndices); + + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); } - ptrArray = pa.Array; } - return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxPool3D.cs b/src/TorchSharp/NN/Pooling/MaxPool3D.cs index 1999c34dc..2b26b3dad 100644 --- a/src/TorchSharp/NN/Pooling/MaxPool3D.cs +++ b/src/TorchSharp/NN/Pooling/MaxPool3D.cs @@ -6,6 +6,7 @@ namespace TorchSharp { + using Google.Protobuf.WellKnownTypes; using Modules; namespace Modules @@ -15,23 +16,30 @@ namespace Modules /// public sealed class MaxPool3d : ParamLessModule { - internal MaxPool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) : base(nameof(MaxPool3d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; + this.dilation = dilation; + this.ceil_mode = ceil_mode; } - public override Tensor forward(Tensor tensor) + public override Tensor forward(Tensor input) { - var res = THSNN_MaxPool3d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.max_pool3d(input, kernel_size, stride, padding, dilation, ceil_mode); } - public (Tensor Values, Tensor Indices) forward_with_indices(Tensor tensor) + public (Tensor Values, Tensor Indices) forward_with_indices(Tensor input) { - var res = THSNN_MaxPool3d_forward_with_indices(handle, tensor.Handle, out var indices); - if (res == IntPtr.Zero || indices == IntPtr.Zero) { torch.CheckForErrors(); } - return (new Tensor(res), new Tensor(indices)); + return torch.nn.functional.max_pool3d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } + public long[] dilation { get; set; } + public bool ceil_mode { get; set; } } } @@ -42,55 +50,49 @@ public static partial class nn /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d(long kernelSize, long? stride = null, long? padding = null, long? dilation = null, bool ceilMode = false) + public static MaxPool3d MaxPool3d(long kernel_size, long? stride = null, long? padding = null, long? dilation = null, bool ceil_mode = false) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value, padding.Value } : null; var pDilation = dilation.HasValue ? new long[] { dilation.Value, dilation.Value, dilation.Value } : null; - return MaxPool3d(new long[] { kernelSize, kernelSize, kernelSize }, pStride, pPadding, pDilation, ceilMode); + return MaxPool3d(new long[] { kernel_size, kernel_size, kernel_size }, pStride, pPadding, pDilation, ceil_mode); } /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d((long, long, long) kernelSize, (long, long, long)? stride = null, (long, long, long)? padding = null, (long, long, long)? dilation = null, bool ceilMode = false) + public static MaxPool3d MaxPool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null, (long, long, long)? dilation = null, bool ceil_mode = false) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 } : null; var pDilation = dilation.HasValue ? new long[] { dilation.Value.Item1, dilation.Value.Item2, dilation.Value.Item3 } : null; - return MaxPool3d(new long[] { kernelSize.Item1, kernelSize.Item2, kernelSize.Item3 }, pStride, pPadding, pDilation, ceilMode); + return MaxPool3d(new long[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pStride, pPadding, pDilation, ceil_mode); } /// /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// The stride between elements within a sliding window, must be > 0. - /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. + /// If true, will use ceil instead of floor to compute the output shape. This ensures that every element in the input tensor is covered by a sliding window. /// - public static MaxPool3d MaxPool3d(long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceilMode = false) + public static MaxPool3d MaxPool3d(long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding, pDilation = dilation) { - var handle = THSNN_MaxPool3d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), (IntPtr)pDilation, (dilation == null ? 0 : dilation.Length), ceilMode, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxPool3d(handle, boxedHandle); - } - } + return new MaxPool3d(kernel_size, stride, padding, dilation, ceil_mode); } public static partial class functional @@ -99,31 +101,18 @@ public static partial class functional /// Applies a 3D max pooling over an input signal composed of several input planes. /// /// The input tensor. - /// - /// + /// + /// /// /// /// /// - public static Tensor max_pool3d(Tensor input, long[] kernelSize, long[] strides = null, + public static Tensor max_pool3d(Tensor input, long[] kernel_size, long[] stride = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides = strides ?? kernelSize; - padding = padding ?? kernelSize.Select(x => 0L).ToArray(); - dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - var res = - THSTensor_max_pool3d(input.Handle, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + var ret = max_pool3d_with_indices(input, kernel_size, stride, padding, dilation, ceil_mode); + ret.Indices.Dispose(); + return ret.Values; } /// @@ -136,30 +125,26 @@ public static Tensor max_pool3d(Tensor input, long[] kernelSize, long[] strides /// /// /// - public static (Tensor output, Tensor indices) max_pool3d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, + public static (Tensor Values, Tensor Indices) max_pool3d_with_indices(Tensor input, long[] kernelSize, long[] strides = null, long[] padding = null, long[] dilation = null, bool ceil_mode = false) { - strides = strides ?? kernelSize; - padding = padding ?? kernelSize.Select(x => 0L).ToArray(); - dilation = dilation ?? kernelSize.Select(x => 1L).ToArray(); - IntPtr[] ptrArray; + strides ??= kernelSize; + padding ??= kernelSize.Select(x => 0L).ToArray(); + dilation ??= kernelSize.Select(x => 1L).ToArray(); + + unsafe { + fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { + var resOutput = THSTensor_max_pool3d_with_indices(input.Handle, + (IntPtr)pkernelSize, kernelSize.Length, + (IntPtr)pstrides, strides.Length, + (IntPtr)ppadding, padding.Length, + (IntPtr)pdilation, dilation.Length, + ceil_mode, out var resIndices); - using (var pa = new PinnedArray()) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, ppadding = padding, pdilation = dilation) { - THSTensor_max_pool3d_with_indices(input.Handle, - pa.CreateArray, - (IntPtr)pkernelSize, kernelSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length, - (IntPtr)pdilation, dilation.Length, - ceil_mode); - torch.CheckForErrors(); - } + if (resOutput == IntPtr.Zero || resIndices == IntPtr.Zero) { torch.CheckForErrors(); } + return (new Tensor(resOutput), new Tensor(resIndices)); } - ptrArray = pa.Array; } - return (new Tensor(ptrArray[0]), new Tensor(ptrArray[1])); } } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs index d2bf0ddeb..9c2afb04d 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool1d.cs @@ -5,6 +5,7 @@ namespace TorchSharp { + using System.Runtime.CompilerServices; using Modules; namespace Modules @@ -14,25 +15,26 @@ namespace Modules /// public sealed class MaxUnpool1d : ParamLessModule { - internal MaxUnpool1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxUnpool1d(long kernel_size, long? stride = null, long? padding = null) : base(nameof(MaxUnpool1d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - unsafe { - fixed (long* pOutSize = output_size) { - var res = THSNN_MaxUnpool1d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + return torch.nn.functional.max_unpool1d(tensor, indices, kernel_size, stride, padding, output_size); } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } + + public long kernel_size { get; set; } + public long? stride { get; set; } + public long? padding { get; set; } } } @@ -41,26 +43,42 @@ public static partial class torch public static partial class nn { /// - /// Applies a 1D max pooling over an input signal composed of several input planes. + /// Computes a partial inverse of :class:`MaxPool1d`. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool1d MaxUnpool1d(long kernelSize, long? stride = null, long? padding = null) + public static MaxUnpool1d MaxUnpool1d(long kernel_size, long? stride = null, long? padding = null) { - var pStride = stride.HasValue ? new long[] { stride.Value } : null; - var pPadding = padding.HasValue ? new long[] { padding.Value } : null; - return MaxUnpool1d(new long[] { kernelSize }, pStride, pPadding); + return new MaxUnpool1d(kernel_size, stride, padding); } - private static MaxUnpool1d MaxUnpool1d(long[] kernelSize, long[] strides = null, long[] padding = null) + public static partial class functional { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { - var handle = THSNN_MaxUnpool1d_ctor((IntPtr)pkernelSize, (IntPtr)pstrides, (IntPtr)pPadding, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxUnpool1d(handle, boxedHandle); + /// + /// Applies a 1D max pooling over an input signal composed of several input planes. + /// + /// the input Tensor to invert + /// the indices given out by :class:`~torch.nn.MaxPool1d` + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 + /// (optional): The targeted output size + /// + public static Tensor max_unpool1d(Tensor input, Tensor indices, long kernel_size, long? stride = null, long? padding = null, long[] output_size = null) + { + long[] kernels = new[] { kernel_size }; + long[] strides = stride.HasValue ? new[] { stride.Value } : Array.Empty(); + long[] paddings = padding.HasValue ? new[] { padding.Value } : Array.Empty(); + output_size ??= Array.Empty(); + + unsafe { + fixed (long* pkernels = kernels, pstrides = strides, ppaddings = paddings, poutputSize = output_size) { + var res = THSTensor_max_unpool1d(input.Handle, indices.Handle, (IntPtr)pkernels, kernels.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, paddings.Length, (IntPtr)pstrides, strides.Length); + if (res == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(res); + } } } } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs index e01e6ddcf..f342049fb 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool2d.cs @@ -5,6 +5,7 @@ namespace TorchSharp { + using Microsoft.VisualBasic; using Modules; namespace Modules @@ -14,25 +15,26 @@ namespace Modules /// public sealed class MaxUnpool2d : ParamLessModule { - internal MaxUnpool2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxUnpool2d(long[] kernel_size, long[] stride = null, long[] padding = null) : base(nameof(MaxUnpool2d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - unsafe { - fixed (long* pOutSize = output_size) { - var res = THSNN_MaxUnpool2d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize, output_size == null ? 0 : output_size.Length); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + return torch.nn.functional.max_unpool2d(tensor, indices, kernel_size, stride, padding, output_size); } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } } } @@ -43,47 +45,41 @@ public static partial class nn /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d(long kernelSize, long? stride = null, long? padding = null) + public static MaxUnpool2d MaxUnpool2d(long kernel_size, long? stride = null, long? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value } : null; - return MaxUnpool2d(new long[] { kernelSize, kernelSize }, pStride, pPadding); + return new MaxUnpool2d(new[] { kernel_size, kernel_size }, pStride, pPadding); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d((long, long) kernelSize, (long, long)? stride = null, (long, long)? padding = null) + public static MaxUnpool2d MaxUnpool2d((long, long) kernel_size, (long, long)? stride = null, (long, long)? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2 } : null; - return MaxUnpool2d(new long[] { kernelSize.Item1, kernelSize.Item2 }, pStride, pPadding); + return new MaxUnpool2d(new[] { kernel_size.Item1, kernel_size.Item2 }, pStride, pPadding); } /// /// Applies a 2D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool2d MaxUnpool2d(long[] kernelSize, long[] strides = null, long[] padding = null) + public static MaxUnpool2d MaxUnpool2d(long[] kernel_size, long[] stride = null, long[] padding = null) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { - var handle = THSNN_MaxUnpool2d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxUnpool2d(handle, boxedHandle); - } - } + return new MaxUnpool2d(kernel_size, stride, padding); } public static partial class functional @@ -91,16 +87,22 @@ public static partial class functional /// /// Computes a partial inverse of MaxPool2d. /// - /// The input tensor. - /// - /// + /// the input Tensor to invert + /// the indices given out by :class:`~torch.nn.MaxPool2d` + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 + /// (optional): The targeted output size /// - public static Tensor max_unpool2d(Tensor input, Tensor indices, long[] outputSize) + public static Tensor max_unpool2d(Tensor input, Tensor indices, long[] kernel_size, long[] stride = null, long[] padding = null, long[] output_size = null) { + stride ??= Array.Empty(); + padding ??= Array.Empty(); + output_size ??= Array.Empty(); + unsafe { - fixed (long* poutputSize = outputSize) { - var res = THSTensor_maxunpool2d(input.Handle, indices.Handle, - (IntPtr)poutputSize, outputSize.Length); + fixed (long* pkernels = kernel_size, pstrides = stride, ppaddings = padding, poutputSize = output_size) { + var res = THSTensor_max_unpool2d(input.Handle, indices.Handle, (IntPtr)pkernels, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, padding.Length, (IntPtr)pstrides, stride.Length); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs index 85d52e208..33abc0429 100644 --- a/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs +++ b/src/TorchSharp/NN/Pooling/MaxUnpool3d.cs @@ -5,34 +5,36 @@ namespace TorchSharp { + using Microsoft.VisualBasic; using Modules; namespace Modules { /// - /// This class is used to represent a MaxUnpool3d module. + /// This class is used to represent a MaxUnpool3D module. /// public sealed class MaxUnpool3d : ParamLessModule { - internal MaxUnpool3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal MaxUnpool3d(long[] kernel_size, long[] stride = null, long[] padding = null) : base(nameof(MaxUnpool3d)) { + this.kernel_size = kernel_size; + this.stride = stride; + this.padding = padding; } public override Tensor forward(Tensor tensor, Tensor indices, long[] output_size = null) { - unsafe { - fixed (long* pOutSize = output_size) { - var res = THSNN_MaxUnpool3d_forward(handle, tensor.Handle, indices.Handle, (IntPtr)pOutSize, output_size == null ? 0 : output_size.Length); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - } + return torch.nn.functional.max_unpool3d(tensor, indices, kernel_size, stride, padding, output_size); } public new Tensor call(Tensor tensor, Tensor indices, long[] output_size = null) { return base.call(tensor, indices, output_size); } + + public long[] kernel_size { get; set; } + public long[] stride { get; set; } + public long[] padding { get; set; } } } @@ -41,69 +43,66 @@ public static partial class torch public static partial class nn { /// - /// Applies a 2D max pooling over an input signal composed of several input planes. + /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d(long kernelSize, long? stride = null, long? padding = null) + public static MaxUnpool3d MaxUnpool3d(long kernel_size, long? stride = null, long? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value, stride.Value, stride.Value } : null; var pPadding = padding.HasValue ? new long[] { padding.Value, padding.Value, padding.Value } : null; - return MaxUnpool3d(new long[] { kernelSize, kernelSize, kernelSize }, pStride, pPadding); + return new MaxUnpool3d(new[] { kernel_size, kernel_size, kernel_size }, pStride, pPadding); } /// - /// Applies a 2D max pooling over an input signal composed of several input planes. + /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. + /// The size of the sliding window, must be > 0. /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d((long, long, long) kernelSize, (long, long, long)? stride = null, (long, long, long)? padding = null) + public static MaxUnpool3d MaxUnpool3d((long, long, long) kernel_size, (long, long, long)? stride = null, (long, long, long)? padding = null) { var pStride = stride.HasValue ? new long[] { stride.Value.Item1, stride.Value.Item2, stride.Value.Item3 } : null; var pPadding = padding.HasValue ? new long[] { padding.Value.Item1, padding.Value.Item2, padding.Value.Item3 } : null; - return MaxUnpool3d(new long[] { kernelSize.Item1, kernelSize.Item2, kernelSize.Item3 }, pStride, pPadding); + return new MaxUnpool3d(new[] { kernel_size.Item1, kernel_size.Item2, kernel_size.Item3 }, pStride, pPadding); } /// - /// Applies a 2D max pooling over an input signal composed of several input planes. + /// Applies a 3D max pooling over an input signal composed of several input planes. /// - /// The size of the sliding window, must be > 0. - /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 /// - public static MaxUnpool3d MaxUnpool3d(long[] kernelSize, long[] strides = null, long[] padding = null) + public static MaxUnpool3d MaxUnpool3d(long[] kernel_size, long[] stride = null, long[] padding = null) { - unsafe { - fixed (long* pkernelSize = kernelSize, pstrides = strides, pPadding = padding) { - var handle = THSNN_MaxUnpool3d_ctor((IntPtr)pkernelSize, kernelSize.Length, (IntPtr)pstrides, (strides == null ? 0 : strides.Length), (IntPtr)pPadding, (padding == null ? 0 : padding.Length), out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new MaxUnpool3d(handle, boxedHandle); - } - } + return new MaxUnpool3d(kernel_size, stride, padding); } + public static partial class functional { /// /// Computes a partial inverse of MaxPool3d. /// - /// The input tensor. - /// - /// - /// - /// + /// the input Tensor to invert + /// the indices given out by :class:`~torch.nn.MaxPool3d` + /// The size of the sliding window, must be > 0. + /// The stride of the sliding window, must be > 0. Default value is kernel_size. + /// Implicit negative infinity padding to be added on both sides, must be >= 0 and less than or equal to kernel_size / 2 + /// (optional): The targeted output size /// - public static Tensor max_unpool3d(Tensor input, Tensor indices, long[] outputSize, long[] strides, long[] padding) + public static Tensor max_unpool3d(Tensor input, Tensor indices, long[] kernel_size, long[] stride = null, long[] padding = null, long[] output_size = null) { + stride ??= Array.Empty(); + padding ??= Array.Empty(); + output_size ??= Array.Empty(); + unsafe { - fixed (long* poutputSize = outputSize, pstrides = strides, ppadding = padding) { - var res = THSTensor_maxunpool3d(input.Handle, indices.Handle, - (IntPtr)poutputSize, outputSize.Length, - (IntPtr)pstrides, strides.Length, - (IntPtr)ppadding, padding.Length); + fixed (long* pkernels = kernel_size, pstrides = stride, ppaddings = padding, poutputSize = output_size) { + var res = THSTensor_max_unpool3d(input.Handle, indices.Handle, (IntPtr)pkernels, kernel_size.Length, (IntPtr)poutputSize, output_size.Length, (IntPtr)ppaddings, padding.Length, (IntPtr)pstrides, stride.Length); if (res == IntPtr.Zero) { torch.CheckForErrors(); } return new Tensor(res); } diff --git a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs index b153acc9e..6d39ecb1c 100644 --- a/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs +++ b/src/TorchSharp/NN/Shuffle/ChannelShuffle.cs @@ -17,8 +17,7 @@ internal ChannelShuffle(long groups) : base(nameof(ChannelShuffle)) { this.groups = groups; } - private long groups {get; set;} - + public override Tensor forward(Tensor tensor) { return tensor.channel_shuffle(groups); @@ -28,6 +27,8 @@ public override string GetName() { return typeof(ChannelShuffle).Name; } + + public long groups { get; set; } } } diff --git a/src/TorchSharp/NN/Unflatten.cs b/src/TorchSharp/NN/Unflatten.cs index fa5954f6b..eeb91e1a9 100644 --- a/src/TorchSharp/NN/Unflatten.cs +++ b/src/TorchSharp/NN/Unflatten.cs @@ -14,25 +14,20 @@ namespace Modules /// public sealed class Unflatten : ParamLessModule { - internal Unflatten(long dim, long[] unflattenedSize) : base(nameof(Unflatten)) + internal Unflatten(long dim, long[] unflattened_size) : base(nameof(Unflatten)) { - this._dim = dim; - this._unflattenedSize = unflattenedSize; + this.dim = dim; + this.unflattened_size = unflattened_size; } public override Tensor forward(Tensor tensor) { - return tensor.unflatten(_dim, _unflattenedSize); + return tensor.unflatten(dim, unflattened_size); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - - long _dim; - long[] _unflattenedSize; + + public long dim { get; set; } + public long[] unflattened_size { get; set; } } } @@ -44,11 +39,11 @@ public static partial class nn /// Unflattens a tensor dim expanding it to a desired shape. For use with Sequential. /// /// Dimension to be unflattened - /// New shape of the unflattened dimension + /// New shape of the unflattened dimension /// - public static Unflatten Unflatten(long dim, long[] unflattenedSize) + public static Unflatten Unflatten(long dim, long[] unflattened_size) { - return new Unflatten(dim, unflattenedSize); + return new Unflatten(dim, unflattened_size); } } } diff --git a/src/TorchSharp/NN/Unfold.cs b/src/TorchSharp/NN/Unfold.cs index aa56705bb..050479623 100644 --- a/src/TorchSharp/NN/Unfold.cs +++ b/src/TorchSharp/NN/Unfold.cs @@ -6,7 +6,6 @@ #nullable enable namespace TorchSharp { - using System.Security.Cryptography; using Modules; namespace Modules @@ -15,7 +14,7 @@ public sealed class Unfold : ParamLessModule { internal Unfold((long, long) kernel_size, (long, long) dilation, (long, long) padding, (long, long) stride) : base(nameof(Unfold)) { - this.kernelSize = kernel_size; + this.kernel_size = kernel_size; this.dilation = dilation; this.padding = padding; this.stride = stride; @@ -23,13 +22,13 @@ internal Unfold((long, long) kernel_size, (long, long) dilation, (long, long) pa public override Tensor forward(Tensor tensor) { - return torch.nn.functional.unfold(tensor, kernelSize, dilation, padding, stride); + return torch.nn.functional.unfold(tensor, kernel_size, dilation, padding, stride); } - private (long, long) kernelSize; - private (long, long) dilation; - private (long, long) padding; - private (long, long) stride; + public (long, long) kernel_size { get; set; } + public (long, long) dilation { get; set; } + public (long, long) padding { get; set; } + public (long, long) stride { get; set; } } } @@ -45,7 +44,7 @@ public static partial class nn /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. /// Currently, only 4-D input tensors (batched image-like tensors) are supported. - public unsafe static Unfold Unfold(long kernel_size, long dilation = 1, long padding = 0, long stride = 1) + public static Unfold Unfold(long kernel_size, long dilation = 1, long padding = 0, long stride = 1) { return new Unfold((kernel_size, kernel_size), (dilation, dilation), (padding, padding), (stride, stride)); } @@ -58,7 +57,7 @@ public unsafe static Unfold Unfold(long kernel_size, long dilation = 1, long pad /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. /// Currently, only 4-D input tensors (batched image-like tensors) are supported. - public unsafe static Unfold Unfold((long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) + public static Unfold Unfold((long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) { dilation ??= (1, 1); stride ??= (1, 1); @@ -77,7 +76,7 @@ public static partial class functional /// A parameter that controls the stride of elements within the neighborhood. /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. - public unsafe static Tensor unfold(Tensor input, long kernel_size, long dilation = 1, long padding = 0, long stride = 1) + public static Tensor unfold(Tensor input, long kernel_size, long dilation = 1, long padding = 0, long stride = 1) { var res = THSNN_unfold(input.Handle, kernel_size, kernel_size, stride, stride, padding, padding, dilation, dilation); if (res == IntPtr.Zero) { torch.CheckForErrors(); } @@ -92,7 +91,7 @@ public unsafe static Tensor unfold(Tensor input, long kernel_size, long dilation /// A parameter that controls the stride of elements within the neighborhood. /// Implicit zero padding to be added on both sides of input. /// The stride of the sliding blocks in the input spatial dimensions. - public unsafe static Tensor unfold(Tensor input, (long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) + public static Tensor unfold(Tensor input, (long, long) kernel_size, (long, long)? dilation = null, (long, long)? padding = null, (long, long)? stride = null) { dilation ??= (1, 1); stride ??= (1, 1); diff --git a/src/TorchSharp/NN/Upsample.cs b/src/TorchSharp/NN/Upsample.cs index 2427cc5a9..2f3b43707 100644 --- a/src/TorchSharp/NN/Upsample.cs +++ b/src/TorchSharp/NN/Upsample.cs @@ -8,6 +8,40 @@ namespace TorchSharp { using Modules; + namespace Modules + { + /// + /// This class is used to represent an Upsample module. + /// + public sealed class Upsample : ParamLessModule + { + internal Upsample(long[]? size, double[]? scale_factor, UpsampleMode mode, bool? align_corners, bool? recompute_scale_factor) : base(nameof(Upsample)) + { + this.size = size; + this.scale_factor = scale_factor; + this.mode = mode; + this.align_corners = align_corners; + this.recompute_scale_factor = recompute_scale_factor; + } + + /// + /// Forward pass. + /// + /// Input tensor + /// + public override Tensor forward(Tensor input) + { + return torch.nn.functional.interpolate(input, size, scale_factor, (InterpolationMode)mode, align_corners, recompute_scale_factor ?? false); + } + + public long[]? size { get; set; } + public double[]? scale_factor { get; set; } + public UpsampleMode mode { get; set; } + public bool? align_corners { get; set; } + public bool? recompute_scale_factor { get; set; } + } + } + public static partial class torch { public static partial class nn @@ -22,19 +56,11 @@ public static partial class nn /// The upsampling algorithm: one of 'nearest', 'linear', 'bilinear', 'bicubic' and 'trilinear'. Default: 'nearest' /// If true, the corner pixels of the input and output tensors are aligned, and thus preserving the values at those pixels. /// This only has effect when mode is 'linear', 'bilinear', or 'trilinear'. Default: false + /// recompute the scale_factor for use in the interpolation calculation. If `recompute_scale_factor` is ``True``, then `scale_factor` must be passed in and `scale_factor` is used to compute the output `size`. The computed output `size` will be used to infer new scales for the interpolation. Note that when `scale_factor` is floating-point, it may differ from the recomputed `scale_factor` due to rounding and precision issues. If `recompute_scale_factor` is ``False``, then `size` or `scale_factor` will be used directly for interpolation. /// - public static Upsample Upsample(long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool? align_corners = null) + public static Upsample Upsample(long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool? align_corners = null, bool? recompute_scale_factor = null) { - unsafe { - fixed (long* psize = size) { - fixed (double* pSF = scale_factor) { - byte ac = (byte)((align_corners.HasValue) ? (align_corners.Value ? 1 : 2) : 0); - var res = THSNN_Upsample_ctor((IntPtr)psize, size is null ? 0 : size.Length, (IntPtr)pSF, scale_factor is null ? 0 : scale_factor.Length, (byte)mode, ac, out var boxedHandle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Upsample(res, boxedHandle, size, scale_factor, mode, align_corners); - } - } - } + return new Upsample(size, scale_factor, mode, align_corners, recompute_scale_factor); } public static partial class functional @@ -44,21 +70,18 @@ public static partial class functional /// The input data is assumed to be of the form minibatch x channels x[optional depth] x[optional height] x width. /// Hence, for spatial inputs, we expect a 4D Tensor and for volumetric inputs, we expect a 5D Tensor. /// - /// Input tensor + /// Input tensor /// Output spatial sizes /// Multiplier for spatial size. Has to match input size /// The upsampling algorithm: one of 'nearest', 'linear', 'bilinear', 'bicubic' and 'trilinear'. Default: 'nearest' /// If true, the corner pixels of the input and output tensors are aligned, and thus preserving the values at those pixels. /// This only has effect when mode is 'linear', 'bilinear', or 'trilinear'. Default: false /// - public static Tensor upsample(Tensor x, long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool align_corners = false) + public static Tensor upsample(Tensor input, long[]? size = null, double[]? scale_factor = null, UpsampleMode mode = UpsampleMode.Nearest, bool align_corners = false) { - using (var d = nn.Upsample(size, scale_factor, mode, align_corners)) { - return d.call(x); - } + return interpolate(input, size, scale_factor, (InterpolationMode)mode, align_corners); } - /// /// Upsamples the input, using nearest neighbours’ pixel values. /// @@ -198,54 +221,4 @@ public static Tensor upsample_nearest3d(Tensor input, long[]? outputSizes = null } } } - - namespace Modules - { - /// - /// This class is used to represent an Upsample module. - /// - public sealed class Upsample : ParamLessModule - { - internal Upsample(IntPtr handle, IntPtr boxedHandle, long[]? size, double[]? scale_factor, UpsampleMode mode, bool? align_corners) : base(handle, boxedHandle) - { - this._size = size; - this._scale_factor = scale_factor; - this.mode = mode; - this.align_corners = align_corners; - } - - /// - /// Forward pass. - /// - /// Input tensor - /// - public override Tensor forward(Tensor tensor) - { - var res = THSNN_Upsample_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - public UpsampleMode mode { get; private set; } - - public bool? align_corners { get; private set; } - - public ReadOnlySpan size { - get { return _size is null ? null : new ReadOnlySpan(_size!); } - } - - public ReadOnlySpan scale_factor { - get { return _scale_factor is null ? null : new ReadOnlySpan(_scale_factor!); } - } - - private long[]? _size; - private double[]? _scale_factor; - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; - } - } } diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index 6756b2795..5bfed781e 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -50,12 +50,6 @@ internal static extern IntPtr THSNN_custom_module( // align_corners -- 0=None, 1=true, 2=false internal static extern IntPtr THSNN_grid_sample(IntPtr input, IntPtr grid, byte mode, byte padding_mode, byte align_corners); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AlphaDropout_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AlphaDropout_ctor(double p, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_alpha_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -63,10 +57,7 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_functional_bilinear(IntPtr input1, IntPtr input2, IntPtr weights, IntPtr bias); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_CosineSimilarity_ctor(long dim, double eps, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_CosineSimilarity_forward(torch.nn.Module.HType module, IntPtr input1, IntPtr input2); + internal static extern IntPtr THSNN_cosine_similarity(IntPtr input1, IntPtr input2, long dim, double eps); [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -133,12 +124,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_EmbeddingBag_from_pretrained(IntPtr embeddings, [MarshalAs(UnmanagedType.U1)] bool freeze, double max_norm, [MarshalAs(UnmanagedType.U1)] bool hasMN, double norm_type, [MarshalAs(UnmanagedType.U1)] bool scale_grad_by_freq, long mode, [MarshalAs(UnmanagedType.U1)] bool sparse, [MarshalAs(UnmanagedType.U1)] bool include_last_offset, long padding_idx, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FeatureAlphaDropout_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FeatureAlphaDropout_ctor(double p, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_feature_alpha_dropout(IntPtr input, double p, [MarshalAs(UnmanagedType.U1)] bool training, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -423,16 +408,10 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_PairwiseDistance_ctor(double p, double eps, [MarshalAs(UnmanagedType.U1)] bool keep_dim, out IntPtr pBoxedModule); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PixelUnshuffle_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PixelUnshuffle_ctor(long downscaleFactor, out IntPtr pBoxedModule); + internal static extern IntPtr THSNN_pixel_unshuffle(IntPtr tensor, long downscale_factor); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PixelShuffle_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PixelShuffle_ctor(long upscaleFactor, out IntPtr pBoxedModule); + internal static extern IntPtr THSNN_pixel_shuffle(IntPtr tensor, long upscale_factor); [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_GRUCell_forward(torch.nn.Module.HType module, IntPtr input, IntPtr h_0); @@ -584,24 +563,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_InstanceNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LayerNorm_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LayerNorm_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_LayerNorm_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LayerNorm_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_LayerNorm_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LayerNorm_ctor(IntPtr norm_shape, long norm_shape_len, double eps, [MarshalAs(UnmanagedType.U1)] bool elementwise_affine, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_InstanceNorm2d_forward(IntPtr module, IntPtr tensor); @@ -935,21 +896,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_BatchNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool1d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool1d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool1d_ctor(IntPtr pkernelSize, IntPtr pStrides, IntPtr pPadding, IntPtr pDilation, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool3d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize, int outputSizeLength); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_ELU_forward(torch.nn.Module.HType module, IntPtr tensor); @@ -1089,127 +1035,7 @@ internal static extern IntPtr THSNN_custom_module( internal static extern IntPtr THSNN_Threshold_forward(torch.nn.Module.HType module, IntPtr tensor); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Threshold_ctor(double threshold, double value, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LocalResponseNorm_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LocalResponseNorm_ctor(long size, double alpha, double beta, double k, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool1d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool2d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool3d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveAvgPool3d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool1d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool2d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool3d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AdaptiveMaxPool3d_ctor(IntPtr psizes, int length, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool1d_ctor(IntPtr pkernelSize, IntPtr pstrides, IntPtr ppadding, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr ppadding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool3d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_AvgPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr ppadding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool2d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pOutputSize, int sizeLength, IntPtr pOutputRatio, int ratioLength, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool3d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool3d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_FractionalMaxPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pOutputSize, int sizeLength, IntPtr pOutputRatio, int ratioLength, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LPPool1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LPPool1d_ctor(double norm_type, IntPtr pkernelSize, IntPtr pstrides, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LPPool2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LPPool2d_ctor(double norm_type, IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool2d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, IntPtr pDilation, int dilationLength, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool3d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool3d_forward_with_indices(torch.nn.Module.HType module, IntPtr tensor, out IntPtr indices); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxPool3d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, IntPtr pDilation, int dilationLength, [MarshalAs(UnmanagedType.U1)] bool ceilMode, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool1d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool1d_ctor(IntPtr pkernelSize, IntPtr pStrides, IntPtr pPadding, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool2d_forward(torch.nn.Module.HType module, IntPtr tensor, IntPtr indices, IntPtr outSize, int outputSizeLength); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_MaxUnpool2d_ctor(IntPtr pkernelSize, int kernelSizeLength, IntPtr pstrides, int stridesLength, IntPtr pPadding, int paddingLength, out IntPtr pBoxedModule); + internal static extern IntPtr THSNN_Threshold_ctor(double threshold, double value, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); } #pragma warning restore CA2101 } diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs index c82b659a3..0de92012c 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs @@ -64,56 +64,49 @@ internal static extern IntPtr THSTensor_conv_transpose3d(IntPtr input, IntPtr we long groups); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool1d(IntPtr input, + internal static extern IntPtr THSTensor_max_pool1d_with_indices(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); [DllImport("LibTorchSharp")] - internal static extern void THSTensor_max_pool1d_with_indices(IntPtr input, AllocatePinnedArray allocator, - IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + internal static extern IntPtr THSTensor_max_pool2d_with_indices(IntPtr input, + IntPtr kernelSize, int kernelSizeLength, + IntPtr strides, int stridesLength, + IntPtr padding, int paddingLength, + IntPtr dilation, int dilationLength, + [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool2d(IntPtr input, + internal static extern IntPtr THSTensor_max_pool3d_with_indices(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + [MarshalAs(UnmanagedType.U1)] bool ceil_mode, out IntPtr indices); [DllImport("LibTorchSharp")] - internal static extern void THSTensor_max_pool2d_with_indices(IntPtr input, AllocatePinnedArray allocator, - IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_max_pool3d(IntPtr input, - IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + internal static extern IntPtr THSTensor_max_unpool1d(IntPtr tensor, IntPtr indices, + IntPtr kernelSize, int kernelSizeLength, + IntPtr outputSize, int outputSizeLength, + IntPtr padding, int paddingLength, + IntPtr strides, int stridesLength); [DllImport("LibTorchSharp")] - internal static extern void THSTensor_max_pool3d_with_indices(IntPtr input, AllocatePinnedArray allocator, + internal static extern IntPtr THSTensor_max_unpool2d(IntPtr tensor, IntPtr indices, IntPtr kernelSize, int kernelSizeLength, - IntPtr strides, int stridesLength, + IntPtr outputSize, int outputSizeLength, IntPtr padding, int paddingLength, - IntPtr dilation, int dilationLength, - [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + IntPtr strides, int stridesLength); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_maxunpool3d(IntPtr input, IntPtr indices, IntPtr outputSize, int outputSizeLength, IntPtr strides, int stridesLength, - IntPtr padding, int paddingLength); + internal static extern IntPtr THSTensor_max_unpool3d(IntPtr tensor, IntPtr indices, + IntPtr kernelSize, int kernelSizeLength, + IntPtr outputSize, int outputSizeLength, + IntPtr padding, int paddingLength, + IntPtr strides, int stridesLength); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool1d(IntPtr input, @@ -129,7 +122,7 @@ internal static extern IntPtr THSTensor_avg_pool2d(IntPtr input, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, - [MarshalAs(UnmanagedType.U1)] bool count_include_pad); + [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool3d(IntPtr input, @@ -137,7 +130,7 @@ internal static extern IntPtr THSTensor_avg_pool3d(IntPtr input, IntPtr strides, int stridesLength, IntPtr padding, int paddingLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode, - [MarshalAs(UnmanagedType.U1)] bool count_include_pad); + [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisor_override); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_avg_pool2d_backward(IntPtr gradOutput, IntPtr originalInput, @@ -157,14 +150,6 @@ internal static extern IntPtr THSTensor_avg_pool3d_backward(IntPtr gradOutput, I [MarshalAs(UnmanagedType.U1)] bool count_include_pad, long divisorOverride); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_avg_pool1d(IntPtr input, - IntPtr outputSize, int outputSizeLength); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_adaptive_avg_pool2d(IntPtr input, - IntPtr outputSize, int outputSizeLength); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_upsample_nearest1d(IntPtr input, IntPtr outputSize, int outputSizeLength, @@ -2086,7 +2071,10 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, internal static extern IntPtr THSTensor_eye(long rows, long columns, sbyte scalarType, int deviceType, int deviceIndex, [MarshalAs(UnmanagedType.U1)] bool requires_grad); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_maxunpool2d(IntPtr input, IntPtr indices, IntPtr outputSize, int outputSizeLength); + internal static extern IntPtr THSTensor_adaptive_avg_pool1d(IntPtr input, IntPtr outputSize, int outputSizeLength); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_avg_pool2d(IntPtr input, IntPtr outputSize, int outputSizeLength); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_adaptive_avg_pool3d(IntPtr input, IntPtr outputSize, int outputSizeLength); @@ -2094,6 +2082,27 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_adaptive_avg_pool3d_backward_out(IntPtr gradInput, IntPtr gradOutput, IntPtr originalInput); + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_max_pool1d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_max_pool2d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_adaptive_max_pool3d(IntPtr input, IntPtr outputSize, int outputSizeLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_fractional_max_pool2d(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr outputSize, int outputSizeLength, IntPtr outputRatio, int outputRatioLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_fractional_max_pool3d(IntPtr input, IntPtr kernelSize, int kernelSizeLength, IntPtr outputSize, int outputSizeLength, IntPtr outputRatio, int outputRatioLength, out IntPtr indices); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_lp_pool1d(IntPtr input, double norm_type, IntPtr kernelSize, int kernelSizeLength, IntPtr stride, int strideLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_lp_pool2d(IntPtr input, double norm_type, IntPtr kernelSize, int kernelSizeLength, IntPtr stride, int strideLength, [MarshalAs(UnmanagedType.U1)] bool ceil_mode); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_searchsorted_t(IntPtr sorted_sequence, IntPtr values, bool out_int32, bool right, IntPtr sorter); [DllImport("LibTorchSharp")] diff --git a/src/TorchVision/Ops/DropBlock.cs b/src/TorchVision/Ops/DropBlock.cs index 2aece98d0..dea7ed8a4 100644 --- a/src/TorchVision/Ops/DropBlock.cs +++ b/src/TorchVision/Ops/DropBlock.cs @@ -53,7 +53,7 @@ public static Tensor drop_block2d(Tensor input, double p, long block_size, bool var pad = block_size / 2; noise = torch.nn.functional.pad(noise, (pad, pad, pad, pad), value: 0); - noise = torch.nn.functional.max_pool2d(noise, stride: 1, kernelSize: block_size, padding: block_size / 2); + noise = torch.nn.functional.max_pool2d(noise, stride: 1, kernel_size: block_size, padding: block_size / 2); noise = 1 - noise; var normalize_scale = noise.numel() / (eps + noise.sum()); @@ -94,7 +94,7 @@ public static Tensor drop_block3d(Tensor input, double p, long block_size, bool var pad = block_size / 2; var padding = new[] { pad, pad, pad, pad, pad, pad }; noise = torch.nn.functional.pad(noise, padding, value: 0); - noise = torch.nn.functional.max_pool3d(noise, strides: new long[] { 1, 1, 1 }, kernelSize: new[] { block_size, block_size, block_size }, padding: new long[] { pad }); + noise = torch.nn.functional.max_pool3d(noise, stride: new long[] { 1, 1, 1 }, kernel_size: new[] { block_size, block_size, block_size }, padding: new long[] { pad }); noise = 1 - noise; var normalize_scale = noise.numel() / (eps + noise.sum()); diff --git a/src/TorchVision/models/AlexNet.cs b/src/TorchVision/models/AlexNet.cs index 33372af06..a26fd3718 100644 --- a/src/TorchVision/models/AlexNet.cs +++ b/src/TorchVision/models/AlexNet.cs @@ -76,17 +76,17 @@ public AlexNet(int numClasses, float dropout = 0.5f, string? weights_file = null features = Sequential( Conv2d(3, 64, kernelSize: 11, stride: 4, padding: 2), ReLU(inplace: true), - MaxPool2d(kernelSize: 3, stride: 2), + MaxPool2d(kernel_size: 3, stride: 2), Conv2d(64, 192, kernelSize: 5, padding: 2), ReLU(inplace: true), - MaxPool2d(kernelSize: 3, stride: 2), + MaxPool2d(kernel_size: 3, stride: 2), Conv2d(192, 384, kernelSize: 3, padding: 1), ReLU(inplace: true), Conv2d(384, 256, kernelSize: 3, padding: 1), ReLU(inplace: true), Conv2d(256, 256, kernelSize: 3, padding: 1), ReLU(inplace: true), - MaxPool2d(kernelSize: 3, stride: 2) + MaxPool2d(kernel_size: 3, stride: 2) ); avgpool = AdaptiveAvgPool2d(new long[] { 6, 6 }); diff --git a/src/TorchVision/models/GoogleNet.cs b/src/TorchVision/models/GoogleNet.cs index 861ccde6f..105c24d35 100644 --- a/src/TorchVision/models/GoogleNet.cs +++ b/src/TorchVision/models/GoogleNet.cs @@ -119,21 +119,21 @@ public GoogleNet(int numClasses = 1000, this.transform_input = transform_input; conv1 = conv_block(3, 64, kernel_size: 7, stride: 2, padding: 3); - maxpool1 = MaxPool2d(kernelSize: 3, stride: 2, ceilMode: true); + maxpool1 = MaxPool2d(kernel_size: 3, stride: 2, ceil_mode: true); conv2 = conv_block(64, 64, kernel_size: 1); conv3 = conv_block(64, 192, kernel_size: 3, padding: 1); - maxpool2 = MaxPool2d(kernelSize: 3, stride: 2, ceilMode: true); + maxpool2 = MaxPool2d(kernel_size: 3, stride: 2, ceil_mode: true); inception3a = inception_block(192, 64, 96, 128, 16, 32, 32); inception3b = inception_block(256, 128, 128, 192, 32, 96, 64); - maxpool3 = nn.MaxPool2d(3, stride: 2, ceilMode: true); + maxpool3 = nn.MaxPool2d(3, stride: 2, ceil_mode: true); inception4a = inception_block(480, 192, 96, 208, 16, 48, 64); inception4b = inception_block(512, 160, 112, 224, 24, 64, 64); inception4c = inception_block(512, 128, 128, 256, 24, 64, 64); inception4d = inception_block(512, 112, 144, 288, 32, 64, 64); inception4e = inception_block(528, 256, 160, 320, 32, 128, 128); - maxpool4 = nn.MaxPool2d(2, stride: 2, ceilMode: true); + maxpool4 = nn.MaxPool2d(2, stride: 2, ceil_mode: true); inception5a = inception_block(832, 256, 160, 320, 32, 128, 128); inception5b = inception_block(832, 384, 192, 384, 48, 128, 128); @@ -280,7 +280,7 @@ public Inception(int in_channels, int ch1x1, int ch3x3red, int ch3x3, int ch5x5r conv_block(ch5x5red, ch5x5, kernel_size: 3, padding: 1) ); branch4 = nn.Sequential( - nn.MaxPool2d(kernelSize: 3, stride: 1, padding: 1, ceilMode: true), + nn.MaxPool2d(kernel_size: 3, stride: 1, padding: 1, ceil_mode: true), conv_block(in_channels, pool_proj, kernel_size: 1) ); RegisterComponents(); diff --git a/src/TorchVision/models/InceptionV3.cs b/src/TorchVision/models/InceptionV3.cs index e7f7791c3..7b68b01f2 100644 --- a/src/TorchVision/models/InceptionV3.cs +++ b/src/TorchVision/models/InceptionV3.cs @@ -119,10 +119,10 @@ public InceptionV3(int numClasses = 1000, Conv2d_1a_3x3 = conv_block(3, 32, kernel_size: 3, stride: 2); Conv2d_2a_3x3 = conv_block(32, 32, kernel_size: 3); Conv2d_2b_3x3 = conv_block(32, 64, kernel_size: 3, padding: 1); - maxpool1 = MaxPool2d(kernelSize: 3, stride: 2); + maxpool1 = MaxPool2d(kernel_size: 3, stride: 2); Conv2d_3b_1x1 = conv_block(64, 80, kernel_size: 1); Conv2d_4a_3x3 = conv_block(80, 192, kernel_size: 3); - maxpool2 = MaxPool2d(kernelSize: 3, stride: 2); + maxpool2 = MaxPool2d(kernel_size: 3, stride: 2); Mixed_5b = inception_a(192, pool_features: 32); Mixed_5c = inception_a(256, pool_features: 64); @@ -292,7 +292,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = branch3x3dbl_3.call(branch3x3dbl); - var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new [] { branch1x1_, branch5x5, branch3x3dbl, branch_pool_ }; @@ -341,7 +341,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = branch3x3dbl_3.call(branch3x3dbl); - var branch_pool = functional.max_pool2d(x, kernelSize: 3, stride: 2); + var branch_pool = functional.max_pool2d(x, kernel_size: 3, stride: 2); var outputs = new[] { branch3x3_, branch3x3dbl, branch_pool }; @@ -425,7 +425,7 @@ public override Tensor forward(Tensor x) branch7x7dbl = branch7x7dbl_4.call(branch7x7dbl); branch7x7dbl = branch7x7dbl_5.call(branch7x7dbl); - var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new[] { branch1x1_, branch7x7, branch7x7dbl, branch_pool_ }; @@ -475,7 +475,7 @@ public override Tensor forward(Tensor x) branch7x7x3 = branch7x7x3_3.call(branch7x7x3); branch7x7x3 = branch7x7x3_4.call(branch7x7x3); - var branch_pool = functional.max_pool2d(x, kernelSize: 3, stride: 2); + var branch_pool = functional.max_pool2d(x, kernel_size: 3, stride: 2); var outputs = new[] { branch3x3, branch7x7x3, branch_pool }; @@ -537,7 +537,7 @@ public override Tensor forward(Tensor x) branch3x3dbl = branch3x3dbl_2.call(branch3x3dbl); branch3x3dbl = torch.cat(new[] { branch3x3dbl_3a.call(branch3x3dbl), branch3x3dbl_3b.call(branch3x3dbl) }, 1); - var branch_pool_ = functional.avg_pool2d(x, kernelSize: 3, stride: 1, padding: 1); + var branch_pool_ = functional.avg_pool2d(x, kernel_size: 3, stride: 1, padding: 1); branch_pool_ = branch_pool.call(branch_pool_); var outputs = new[] { branch1x1_, branch3x3, branch3x3dbl, branch_pool_ }; @@ -575,7 +575,7 @@ public InceptionAux(int in_channels, int num_classes) : base("InceptionAux") public override Tensor forward(Tensor x) { // N x 768 x 17 x 17 - x = functional.avg_pool2d(x, kernelSize: 5, stride: 3); + x = functional.avg_pool2d(x, kernel_size: 5, stride: 3); // N x 768 x 5 x 5 x = conv0.call(x); // N x 128 x 5 x 5 diff --git a/src/TorchVision/models/ResNet.cs b/src/TorchVision/models/ResNet.cs index 654d587c3..91c6fa7c4 100644 --- a/src/TorchVision/models/ResNet.cs +++ b/src/TorchVision/models/ResNet.cs @@ -773,7 +773,7 @@ public ResNet(string name, conv1 = Conv2d(3, in_planes, kernelSize: 7, stride: 2, padding: 3, bias: false); bn1 = norm_layer(in_planes); relu = ReLU(inplace: true); - maxpool = MaxPool2d(kernelSize: 3, stride: 2, padding: 1); + maxpool = MaxPool2d(kernel_size: 3, stride: 2, padding: 1); MakeLayer(layer1, block, expansion, 64, layers[0], 1); MakeLayer(layer2, block, expansion, 128, layers[1], 2, rswd.Item1); diff --git a/src/TorchVision/models/VGG.cs b/src/TorchVision/models/VGG.cs index e79f9ddec..08e6d8a3c 100644 --- a/src/TorchVision/models/VGG.cs +++ b/src/TorchVision/models/VGG.cs @@ -363,7 +363,7 @@ public VGG(string name, for (var i = 0; i < channels.Length; i++) { if (channels[i] == 0) { - layers.Add(MaxPool2d(kernelSize: 2, stride: 2)); + layers.Add(MaxPool2d(kernel_size: 2, stride: 2)); } else { layers.Add(Conv2d(in_channels, channels[i], kernelSize: 3, padding: 1)); if (batch_norm) { diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index db91c1993..355c50baa 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -3461,7 +3461,7 @@ public void AvgPool3DBackwardTensorExplicitDivisor() var ones = torch.ones(new long[] { 4, 2, 2, 2, 2 }, device: device); var kernelSize = new long[] { 2, 2, 2 }; var avg = torch.ones(new long[] { 4, 2, 1, 1, 1 }, device: device); - var res = torch.nn.functional.avg_pool3d_backward(avg, ones, kernelSize, divisorOverride: 6) * 6.0; + var res = torch.nn.functional.avg_pool3d_backward(avg, ones, kernelSize, divisor_override: 6) * 6.0; var ones0000 = ones.cpu()[0, 0, 0, 0, 0].ToSingle(); var res0000 = res.cpu()[0, 0, 0, 0, 0].ToSingle(); diff --git a/test/TorchSharpTest/TestTorchTensorBugs.cs b/test/TorchSharpTest/TestTorchTensorBugs.cs index 7d97371dd..d1e09c2e5 100644 --- a/test/TorchSharpTest/TestTorchTensorBugs.cs +++ b/test/TorchSharpTest/TestTorchTensorBugs.cs @@ -1172,7 +1172,7 @@ public void Validate1089_2d() () => Assert.Equal(expectedShape, functional.max_pool2d(t, new long[] { 2, 2 }).shape) ); - Assert.Equal(expectedShape, functional.max_pool2d_with_indices(t, new long[] { 2, 2 }).output.shape); + Assert.Equal(expectedShape, functional.max_pool2d_with_indices(t, new long[] { 2, 2 }).Values.shape); } [Fact] @@ -1182,7 +1182,7 @@ public void Validate1089_3d() var expectedShape = new long[] { 1, 6, 14, 14, 14 }; Assert.Equal(expectedShape, functional.max_pool3d(t, new long[] { 2, 2, 2 }).shape); - Assert.Equal(expectedShape, functional.max_pool3d_with_indices(t, new long[] { 2, 2, 2 }).output.shape); + Assert.Equal(expectedShape, functional.max_pool3d_with_indices(t, new long[] { 2, 2, 2 }).Values.shape); } [Fact] From e21aacfbe42f8613576461fa937fac58161d064f Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Wed, 13 Mar 2024 14:56:09 -0700 Subject: [PATCH 37/47] Moved all activation modules to managed code. --- .gitignore | 1 + src/Native/LibTorchSharp/THSActivation.cpp | 327 ------------------ src/Native/LibTorchSharp/THSNN.h | 55 --- src/Native/LibTorchSharp/THSTensor.cpp | 54 ++- src/Native/LibTorchSharp/THSTensor.h | 23 +- src/TorchSharp/NN/Activation/CELU.cs | 32 +- src/TorchSharp/NN/Activation/ELU.cs | 35 +- src/TorchSharp/NN/Activation/GELU.cs | 38 +- src/TorchSharp/NN/Activation/GLU.cs | 32 +- src/TorchSharp/NN/Activation/Hardshrink.cs | 37 +- src/TorchSharp/NN/Activation/Hardsigmoid.cs | 21 +- src/TorchSharp/NN/Activation/Hardswish.cs | 17 +- src/TorchSharp/NN/Activation/Hardtanh.cs | 29 +- src/TorchSharp/NN/Activation/LeakyReLU.cs | 30 +- src/TorchSharp/NN/Activation/LogSigmoid.cs | 17 +- src/TorchSharp/NN/Activation/LogSoftMax.cs | 21 +- src/TorchSharp/NN/Activation/Mish.cs | 38 +- src/TorchSharp/NN/Activation/PReLU.cs | 70 +++- src/TorchSharp/NN/Activation/RReLU.cs | 34 +- src/TorchSharp/NN/Activation/ReLU6.cs | 29 +- src/TorchSharp/NN/Activation/ReLu.cs | 24 +- src/TorchSharp/NN/Activation/SELU.cs | 24 +- src/TorchSharp/NN/Activation/SiLU.cs | 25 +- src/TorchSharp/NN/Activation/Sigmoid.cs | 32 +- src/TorchSharp/NN/Activation/Softmax.cs | 29 +- src/TorchSharp/NN/Activation/Softmax2d.cs | 27 +- src/TorchSharp/NN/Activation/Softmin.cs | 31 +- src/TorchSharp/NN/Activation/Softplus.cs | 36 +- src/TorchSharp/NN/Activation/Softshrink.cs | 41 +-- src/TorchSharp/NN/Activation/Softsign.cs | 37 +- src/TorchSharp/NN/Activation/Tanh.cs | 23 +- src/TorchSharp/NN/Activation/Tanhshrink.cs | 37 +- src/TorchSharp/NN/Activation/Threshold.cs | 36 +- src/TorchSharp/NN/Module.cs | 2 + src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 138 -------- .../PInvoke/LibTorchSharp.THSTensor.cs | 36 +- src/TorchSharp/Tensor/Tensor.cs | 79 ++++- test/TorchSharpTest/NN.cs | 11 +- 38 files changed, 503 insertions(+), 1105 deletions(-) diff --git a/.gitignore b/.gitignore index bab8676e1..4f8e77a3e 100644 --- a/.gitignore +++ b/.gitignore @@ -272,3 +272,4 @@ packages/ *.code-workspace /.idea /test/TorchSharpTest/exportsd.py +.vscode/settings.json diff --git a/src/Native/LibTorchSharp/THSActivation.cpp b/src/Native/LibTorchSharp/THSActivation.cpp index 21b2e14a9..c89beaab6 100644 --- a/src/Native/LibTorchSharp/THSActivation.cpp +++ b/src/Native/LibTorchSharp/THSActivation.cpp @@ -2,330 +2,3 @@ #include "THSNN.h" #include - -NNModule THSNN_CELU_ctor(const double alpha, const bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::CELUOptions().alpha(alpha).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_CELU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ELU_ctor(const double alpha, const bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ELUOptions().alpha(alpha).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ELU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_GELU_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_GELU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_GLU_ctor(const int64_t dim, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::GLUOptions().dim(dim); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_GLU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Hardshrink_ctor(const double lambda, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::HardshrinkOptions(lambda); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Hardshrink_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Hardtanh_ctor(const double min_val, const double max_val, const bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::HardtanhOptions() - .min_val(min_val) - .max_val(max_val) - .inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Hardtanh_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - - -NNModule THSNN_LeakyReLU_ctor(const double negative_sloope, const bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LeakyReLUOptions().negative_slope(negative_sloope).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LeakyReLU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_LogSoftmax_ctor(int64_t dim, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::LogSoftmaxOptions(dim); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_LogSoftmax_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Mish_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_Mish_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_PReLU_ctor(const int64_t nparams, const double init, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::PReLUOptions().num_parameters(nparams).init(init); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_PReLU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_PReLU_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_PReLU_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - -NNModule THSNN_ReLU_ctor(bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReLUOptions(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ReLU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_RReLU_ctor(const double lower, const double upper, const bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::RReLUOptions().lower(lower).upper(upper).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_RReLU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_ReLU6_ctor(bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ReLU6Options(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_ReLU6_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_SELU_ctor(bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::SELUOptions(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_SELU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Sigmoid_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_Sigmoid_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_SiLU_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_SiLU_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Softmax2d_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_Softmax2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Softmax_ctor(const int64_t dim, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::SoftmaxOptions(dim); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Softmax_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Softmin_ctor(const int64_t dim, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::SoftminOptions(dim); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Softmin_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Softplus_ctor(const double beta, const double threshold, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::SoftplusOptions().beta(beta).threshold(threshold); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Softplus_forward(const NNModule module, const Tensor tensor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Softshrink_ctor(const double lambda, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::SoftshrinkOptions().lambda(lambda); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Softshrink_forward(const NNModule module, const Tensor tensor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Softsign_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_Softsign_forward(const NNModule module, const Tensor tensor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Tanh_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_Tanh_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Tanhshrink_ctor(NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - res = create_module(outAsAnyModule); - ); -} - -Tensor THSNN_Tanhshrink_forward(const NNModule module, const Tensor tensor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_Threshold_ctor(const double threshold, const double value, const bool inplace, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::ThresholdOptions(threshold, value).inplace(inplace); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_Threshold_forward(const NNModule module, const Tensor tensor) { - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - diff --git a/src/Native/LibTorchSharp/THSNN.h b/src/Native/LibTorchSharp/THSNN.h index 94d1400ac..179b83b87 100644 --- a/src/Native/LibTorchSharp/THSNN.h +++ b/src/Native/LibTorchSharp/THSNN.h @@ -216,61 +216,6 @@ EXPORT_API(Tensor) THSNN_interpolate(const Tensor input, const int64_t* size, co EXPORT_API(Tensor) THSNN_grid_sample(const Tensor input, const Tensor grid, const int8_t mode, const int8_t padding_mode, const int8_t align_corners); EXPORT_API(Tensor) THSNN_affine_grid(const Tensor theta, const int64_t* size, const int size_len, const bool align_corners); -// Activation functions - -EXPORT_API(NNModule) THSNN_CELU_ctor(const double alpha, const bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_CELU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_ELU_ctor(const double alpha, const bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ELU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_GELU_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_GELU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_GLU_ctor(const int64_t dim, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_GLU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Hardshrink_ctor(const double lambda, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Hardshrink_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Hardtanh_ctor(const double min_val, const double max_val, const bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Hardtanh_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_LeakyReLU_ctor(const double negative_sloope, const bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LeakyReLU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Mish_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Mish_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_PReLU_ctor(const int64_t nparams, const double init, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_PReLU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(Tensor) THSNN_PReLU_weight(const NNModule module); -EXPORT_API(void) THSNN_PReLU_set_weight(const NNModule module, const Tensor weight); -EXPORT_API(NNModule) THSNN_ReLU_ctor(bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ReLU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_ReLU6_ctor(bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_ReLU6_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_RReLU_ctor(const double lower, const double upper, const bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_RReLU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_LogSoftmax_ctor(int64_t dim, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_LogSoftmax_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_SELU_ctor(bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_SELU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Sigmoid_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Sigmoid_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_SiLU_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_SiLU_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Softmax_ctor(const int64_t dim, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Softmax_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Softmax2d_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Softmax2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Softmin_ctor(const int64_t dim, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Softmin_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Softplus_ctor(const double beta, const double threshold, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Softplus_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Softshrink_ctor(const double lambda, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Softshrink_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Softsign_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Softsign_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Tanh_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Tanh_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Tanhshrink_ctor(NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Tanhshrink_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_Threshold_ctor(const double threshold, const double value, const bool inplace, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_Threshold_forward(const NNModule module, const Tensor tensor); - // Sparse EXPORT_API(NNModule) THSNN_Embedding_ctor(const int64_t num_embeddings, const int64_t embedding_dims, const int64_t padding_idx, bool has_pi, const double max_norm, const bool has_mn, const double norm_type, const bool scale_grad_by_freq, const bool sparse, NNAnyModule* outAsAnyModule); diff --git a/src/Native/LibTorchSharp/THSTensor.cpp b/src/Native/LibTorchSharp/THSTensor.cpp index 2bdc96a83..6f0e035d9 100644 --- a/src/Native/LibTorchSharp/THSTensor.cpp +++ b/src/Native/LibTorchSharp/THSTensor.cpp @@ -200,14 +200,29 @@ Tensor THSTensor_cat(const Tensor* tensors, const int length, const int64_t dim) CATCH_TENSOR(torch::cat(toTensors((torch::Tensor**)tensors, length), dim)); } -Tensor THSTensor_celu(const Tensor tensor) +Tensor THSTensor_celu(const Tensor tensor, const Scalar alpha) { - CATCH_TENSOR(torch::celu(*tensor)); + CATCH_TENSOR(torch::celu(*tensor, *alpha)); } -void THSTensor_celu_(const Tensor tensor) +void THSTensor_celu_(const Tensor tensor, const Scalar alpha) { - CATCH(torch::celu_(*tensor);); + CATCH(torch::celu_(*tensor, *alpha);); +} + +Tensor THSTensor_glu(const Tensor tensor, const int64_t dim) +{ + CATCH_TENSOR(torch::glu(*tensor, dim)); +} + +Tensor THSTensor_hardshrink(const Tensor tensor, const Scalar lambda) +{ + CATCH_TENSOR(torch::hardshrink(*tensor, *lambda)); +} + +Tensor THSTensor_softshrink(const Tensor tensor, const Scalar lambda) +{ + CATCH_TENSOR(torch::softshrink(*tensor, *lambda)); } void THSTensor_chunk(const Tensor tensor, Tensor* (*allocator)(size_t length), const int64_t chunks, const int64_t dim) @@ -561,6 +576,11 @@ Tensor THSTensor_gelu(const Tensor tensor) CATCH_TENSOR(torch::gelu(*tensor)); } +Tensor THSTensor_gelu_(const Tensor tensor) +{ + CATCH_TENSOR(torch::gelu_(*tensor)); +} + Tensor THSTensor_get1(const Tensor tensor, int64_t index) { CATCH_TENSOR((*tensor)[index]); @@ -1181,6 +1201,17 @@ void THSTensor_relu6_(const Tensor tensor) CATCH(torch::nn::functional::relu6(*tensor, torch::nn::functional::ReLU6FuncOptions().inplace(true));); } + +Tensor THSTensor_rrelu(const Tensor tensor, const double lower, const double upper) +{ + CATCH_TENSOR(torch::rrelu(*tensor, lower, upper)); +} + +void THSTensor_rrelu_(const Tensor tensor, const double lower, const double upper) +{ + CATCH(torch::rrelu_(*tensor, lower, upper);); +} + Tensor THSTensor_renorm(const Tensor tensor, const float p, const int64_t dim, const float maxnorm) { CATCH_TENSOR(tensor->renorm(p, dim, maxnorm)); @@ -1359,9 +1390,9 @@ Tensor THSTensor_slice(const Tensor tensor, int64_t dim, int64_t start, int64_t CATCH_TENSOR(tensor->slice(dim, start, finish, step)); } -Tensor THSTensor_softplus(const Tensor tensor) +Tensor THSTensor_softplus(const Tensor tensor, const Scalar beta, const Scalar threshold) { - CATCH_TENSOR(torch::softplus(*tensor)); + CATCH_TENSOR(torch::softplus(*tensor, *beta, *threshold)); } Tensor THSTensor_sort(const Tensor tensor, const int64_t dim, const bool descending, const bool stable, Tensor* indices) @@ -1873,6 +1904,17 @@ void THSTensor_transpose_(const Tensor tensor, const int64_t dim1, const int64_t CATCH(tensor->transpose_(dim1, dim2);); } +Tensor THSTensor_threshold(const Tensor tensor, const Scalar threshold, const Scalar value) +{ + CATCH_TENSOR(torch::threshold(*tensor, *threshold, *value)); +} + +void THSTensor_threshold_(const Tensor tensor, const Scalar threshold, const Scalar value) +{ + CATCH(torch::threshold_(*tensor, *threshold, *value);); +} + + Tensor THSTensor_view(const Tensor tensor, const int64_t* shape, const int length) { CATCH_TENSOR(tensor->view(at::ArrayRef(shape, length))); diff --git a/src/Native/LibTorchSharp/THSTensor.h b/src/Native/LibTorchSharp/THSTensor.h index f391075f4..5e60909c0 100644 --- a/src/Native/LibTorchSharp/THSTensor.h +++ b/src/Native/LibTorchSharp/THSTensor.h @@ -251,9 +251,13 @@ EXPORT_API(Tensor) THSTensor_ceil(const Tensor tensor); EXPORT_API(void) THSTensor_ceil_(const Tensor tensor); -EXPORT_API(Tensor) THSTensor_celu(const Tensor tensor); +EXPORT_API(Tensor) THSTensor_celu(const Tensor tensor, const Scalar alpha); -EXPORT_API(void) THSTensor_celu_(const Tensor tensor); +EXPORT_API(void) THSTensor_celu_(const Tensor tensor, const Scalar alpha); + +EXPORT_API(Tensor) THSTensor_hardshrink(const Tensor tensor, const Scalar lambda); + +EXPORT_API(Tensor) THSTensor_softshrink(const Tensor tensor, const Scalar lambda); EXPORT_API(Tensor) THSTensor_cholesky(const Tensor tensor, const bool upper); @@ -571,6 +575,9 @@ EXPORT_API(Tensor) THSTensor_ge_scalar(const Tensor left, const Scalar right); EXPORT_API(void) THSTensor_ge_scalar_(const Tensor left, const Scalar right); EXPORT_API(Tensor) THSTensor_gelu(const Tensor tensor); +EXPORT_API(Tensor) THSTensor_gelu_(const Tensor tensor); + +EXPORT_API(Tensor) THSTensor_glu(const Tensor tensor, const int64_t dim); EXPORT_API(Tensor) THSTensor_get1(const Tensor tensor, int64_t index); @@ -1077,17 +1084,17 @@ EXPORT_API(Tensor) THSTensor_ravel(const Tensor tensor); EXPORT_API(Tensor) THSTensor_real(const Tensor tensor); EXPORT_API(Tensor) THSTensor_reciprocal(const Tensor tensor); - EXPORT_API(void) THSTensor_reciprocal_(const Tensor tensor); EXPORT_API(Tensor) THSTensor_relu(const Tensor tensor); - EXPORT_API(void) THSTensor_relu_(const Tensor tensor); EXPORT_API(Tensor) THSTensor_relu6(const Tensor tensor); - EXPORT_API(void) THSTensor_relu6_(const Tensor tensor); +EXPORT_API(Tensor) THSTensor_rrelu(const Tensor tensor, const double lower, const double upper); +EXPORT_API(void) THSTensor_rrelu_(const Tensor tensor, const double lower, const double upper); + EXPORT_API(Tensor) THSTensor_repeat(const Tensor tensor, const int64_t* sizes, const int length); EXPORT_API(Tensor) THSTensor_repeat_interleave(const Tensor tensor, const Tensor repeats, const int64_t dim, const int64_t output_size); @@ -1159,7 +1166,7 @@ EXPORT_API(Tensor) THSTensor_sinh(const Tensor tensor); EXPORT_API(void) THSTensor_sinh_(const Tensor tensor); -EXPORT_API(Tensor) THSTensor_softplus(const Tensor tensor); +EXPORT_API(Tensor) THSTensor_softplus(const Tensor tensor, const Scalar beta, const Scalar threshold); EXPORT_API(Tensor) THSTensor_sort(const Tensor tensor, const int64_t dim, const bool descending, const bool stable, Tensor* indices); @@ -1314,9 +1321,11 @@ EXPORT_API(Tensor) THSTensor_tril_indices(const int64_t row, const int64_t col, EXPORT_API(Tensor) THSTensor_triu_indices(const int64_t row, const int64_t col, const int64_t offset, const int8_t scalar_type, const int device_type, const int device_index); EXPORT_API(Tensor) THSTensor_transpose(const Tensor tensor, const int64_t dim1, const int64_t dim2); - EXPORT_API(void) THSTensor_transpose_(const Tensor tensor, const int64_t dim1, const int64_t dim2); +EXPORT_API(Tensor) THSTensor_threshold(const Tensor tensor, const Scalar threshold, const Scalar value); +EXPORT_API(void) THSTensor_threshold_(const Tensor tensor, const Scalar threshold, const Scalar value); + EXPORT_API(Tensor) THSTensor_cumulative_trapezoid_x(const Tensor y, const Tensor x, int64_t dim); EXPORT_API(Tensor) THSTensor_cumulative_trapezoid_dx(const Tensor y, const double dx, int64_t dim); diff --git a/src/TorchSharp/NN/Activation/CELU.cs b/src/TorchSharp/NN/Activation/CELU.cs index 85ba92195..685919099 100644 --- a/src/TorchSharp/NN/Activation/CELU.cs +++ b/src/TorchSharp/NN/Activation/CELU.cs @@ -12,29 +12,21 @@ namespace Modules /// /// This class is used to represent a CELU module. /// - public sealed class CELU : torch.nn.Module + public sealed class CELU : ParamLessModule { - internal CELU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal CELU(double alpha, bool inplace) : base(nameof(CELU)) { - var res = THSNN_CELU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.alpha = alpha; + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(CELU).Name; + return torch.nn.functional.celu(tensor, alpha, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public double alpha {get; set;} + public bool inplace {get; set; } } } @@ -50,9 +42,7 @@ public static partial class nn /// public static CELU CELU(double alpha = 1.0, bool inplace = false) { - var handle = THSNN_CELU_ctor(alpha, inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new CELU(handle, boxedHandle); + return new CELU(alpha, inplace); } public static partial class functional @@ -66,9 +56,7 @@ public static partial class functional /// public static Tensor celu(Tensor x, double alpha, bool inplace = false) { - using (var m = nn.CELU(alpha, inplace)) { - return m.call(x); - } + return inplace ? x.celu_(alpha).alias() : x.celu(alpha); } } } diff --git a/src/TorchSharp/NN/Activation/ELU.cs b/src/TorchSharp/NN/Activation/ELU.cs index 4dc818b0a..078e29e2f 100644 --- a/src/TorchSharp/NN/Activation/ELU.cs +++ b/src/TorchSharp/NN/Activation/ELU.cs @@ -12,29 +12,22 @@ namespace Modules /// /// This class is used to represent a ELU module. /// - public sealed class ELU : torch.nn.Module + public sealed class ELU : ParamLessModule { - internal ELU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) - { - var res = THSNN_ELU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + internal ELU(double alpha, bool inplace) : base(nameof(ELU)) + { + this.alpha = alpha; + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(ELU).Name; + return torch.nn.functional.elu(tensor, alpha, inplace); } + + public double alpha {get; set;} - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set;} } } @@ -50,9 +43,7 @@ public static partial class nn /// public static ELU ELU(double alpha = 1.0, bool inplace = false) { - var handle = THSNN_ELU_ctor(alpha, inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ELU(handle, boxedHandle); + return new ELU(alpha, inplace); } public static partial class functional @@ -66,9 +57,7 @@ public static partial class functional /// public static Tensor elu(Tensor x, double alpha, bool inplace = false) { - using (var m = nn.ELU(alpha, inplace)) { - return m.call(x); - } + return inplace ? x.elu_(alpha).alias() : x.elu(alpha); } } } diff --git a/src/TorchSharp/NN/Activation/GELU.cs b/src/TorchSharp/NN/Activation/GELU.cs index c069ca639..7ccb08c8c 100644 --- a/src/TorchSharp/NN/Activation/GELU.cs +++ b/src/TorchSharp/NN/Activation/GELU.cs @@ -12,29 +12,19 @@ namespace Modules /// /// This class is used to represent a GELU module. /// - public sealed class GELU : torch.nn.Module + public sealed class GELU : ParamLessModule { - internal GELU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal GELU(bool inplace) : base(nameof(GELU)) { - var res = THSNN_GELU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(GELU).Name; + return torch.nn.functional.gelu(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } @@ -45,12 +35,10 @@ public static partial class nn /// /// Gaussian Error Linear Units /// - /// - public static GELU GELU() + /// Do the operation in-place. Default: False + public static GELU GELU(bool inplace = false) { - var handle = THSNN_GELU_ctor(out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new GELU(handle, boxedHandle); + return new GELU(inplace); } public static partial class functional @@ -59,12 +47,10 @@ public static partial class functional /// Gaussian Error Linear Units /// /// The input tensor - /// - public static Tensor gelu(Tensor x) + /// Do the operation in-place. Default: False + public static Tensor gelu(Tensor x, bool inplace = false) { - using (var m = nn.GELU()) { - return m.call(x); - } + return inplace ? x.gelu_().alias() : x.gelu(); } } } diff --git a/src/TorchSharp/NN/Activation/GLU.cs b/src/TorchSharp/NN/Activation/GLU.cs index 95ca2c25d..4fd759208 100644 --- a/src/TorchSharp/NN/Activation/GLU.cs +++ b/src/TorchSharp/NN/Activation/GLU.cs @@ -12,29 +12,19 @@ namespace Modules /// /// This class is used to represent a GLU (gated linear unit) module. /// - public sealed class GLU : torch.nn.Module + public sealed class GLU : ParamLessModule { - internal GLU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) - { - var res = THSNN_GLU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + internal GLU(long dim) : base(nameof(GLU)) + { + this.dim = dim; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(GLU).Name; + return torch.nn.functional.glu(tensor, dim); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public long dim {get; set;} } } @@ -49,9 +39,7 @@ public static partial class nn /// public static GLU GLU(long dim = -1) { - var handle = THSNN_GLU_ctor(dim, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new GLU(handle, boxedHandle); + return new GLU(dim); } public static partial class functional @@ -64,9 +52,7 @@ public static partial class functional /// public static Tensor glu(Tensor input, long dim = -1) { - using (var m = nn.GLU(dim)) { - return m.call(input); - } + return input.glu(dim); } } } diff --git a/src/TorchSharp/NN/Activation/Hardshrink.cs b/src/TorchSharp/NN/Activation/Hardshrink.cs index c4f880b72..57b692b68 100644 --- a/src/TorchSharp/NN/Activation/Hardshrink.cs +++ b/src/TorchSharp/NN/Activation/Hardshrink.cs @@ -12,29 +12,19 @@ namespace Modules /// /// This class is used to represent a Hardshrink module. /// - public sealed class Hardshrink : torch.nn.Module + public sealed class Hardshrink : ParamLessModule { - internal Hardshrink(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) - { - var res = THSNN_Hardshrink_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + internal Hardshrink(double lambda = 0.5) : base(nameof(Hardshrink)) + { + this.lambda = lambda; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Hardshrink).Name; + return torch.nn.functional.hardshrink(tensor, lambda); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public double lambda {get; set; } } } @@ -49,9 +39,7 @@ public static partial class nn /// public static Hardshrink Hardshrink(double lambda = 0.5) { - var handle = THSNN_Hardshrink_ctor(lambda, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Hardshrink(handle, boxedHandle); + return new Hardshrink(lambda); } public static partial class functional @@ -62,11 +50,12 @@ public static partial class functional /// The input tensor /// The λ value for the Hardshrink formulation. Default: 0.5 /// - public static Tensor Hardshrink(Tensor x, double lambda = 0.5) + public static Tensor hardshrink(Tensor x, double lambda = 0.5) { - using (var m = nn.Hardshrink(lambda)) { - return m.call(x); - } + using var sc = (Scalar)lambda; + var result = THSTensor_hardshrink(x.Handle, sc.Handle); + if (result == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(result); } } } diff --git a/src/TorchSharp/NN/Activation/Hardsigmoid.cs b/src/TorchSharp/NN/Activation/Hardsigmoid.cs index 66e0aa816..74ef6af56 100644 --- a/src/TorchSharp/NN/Activation/Hardsigmoid.cs +++ b/src/TorchSharp/NN/Activation/Hardsigmoid.cs @@ -11,32 +11,19 @@ namespace Modules /// /// This class is used to represent a Hardsigmoid module. /// - public sealed class Hardsigmoid : torch.nn.Module + public sealed class Hardsigmoid : ParamLessModule { - private readonly bool inplace; - - internal Hardsigmoid(bool inplace = false) : base(nameof(Hardsigmoid)) + internal Hardsigmoid(bool inplace) : base(nameof(Hardsigmoid)) { this.inplace = inplace; } public override Tensor forward(Tensor tensor) { - return torch.nn.functional.hardsigmoid(tensor, this.inplace); - } - - public override string GetName() - { - return typeof(Hardsigmoid).Name; + return torch.nn.functional.hardsigmoid(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } diff --git a/src/TorchSharp/NN/Activation/Hardswish.cs b/src/TorchSharp/NN/Activation/Hardswish.cs index d1065be3b..c9d39107a 100644 --- a/src/TorchSharp/NN/Activation/Hardswish.cs +++ b/src/TorchSharp/NN/Activation/Hardswish.cs @@ -11,9 +11,9 @@ namespace Modules /// /// This class is used to represent a Hardswish module. /// - public sealed class Hardswish : torch.nn.Module + public sealed class Hardswish : ParamLessModule { - private readonly bool inplace; + public bool inplace { get; set;} internal Hardswish(bool inplace = false) : base(nameof(Hardswish)) { @@ -24,19 +24,6 @@ public override Tensor forward(Tensor tensor) { return torch.nn.functional.hardswish(tensor, this.inplace); } - - public override string GetName() - { - return typeof(Hardswish).Name; - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; } } diff --git a/src/TorchSharp/NN/Activation/Hardtanh.cs b/src/TorchSharp/NN/Activation/Hardtanh.cs index 9451c2132..b245fec9d 100644 --- a/src/TorchSharp/NN/Activation/Hardtanh.cs +++ b/src/TorchSharp/NN/Activation/Hardtanh.cs @@ -12,15 +12,18 @@ namespace Modules /// /// This class is used to represent a Hardtanh module. /// - public sealed class Hardtanh : torch.nn.Module + public sealed class Hardtanh : ParamLessModule { - internal Hardtanh(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal Hardtanh(double min_val = -1.0, double max_val = 1.0, bool inplace = false) : base(nameof(Hardtanh)) + { + this.min_val = min_val; + this.max_val = max_val; + this.inplace = inplace; + } public override Tensor forward(Tensor tensor) { - var res = THSNN_Hardtanh_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.hardtanh(tensor, min_val, max_val, inplace); } public override string GetName() @@ -28,13 +31,9 @@ public override string GetName() return typeof(Hardtanh).Name; } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - - protected internal override nn.Module _to(ScalarType dtype) => this; + public double min_val { get; set; } + public double max_val { get; set; } + public bool inplace {get; set; } } } @@ -51,9 +50,7 @@ public static partial class nn /// public static Hardtanh Hardtanh(double min_val = -1.0, double max_val = 1.0, bool inplace = false) { - var handle = THSNN_Hardtanh_ctor(min_val, max_val, inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Hardtanh(handle, boxedHandle); + return new Hardtanh(min_val, max_val, inplace); } public static partial class functional @@ -66,7 +63,7 @@ public static partial class functional /// Maximum value of the linear region range. /// Do the operation in-place /// - public static Tensor Hardtanh(Tensor x, double min_val = -1.0, double max_val = 1.0, bool inplace = false) + public static Tensor hardtanh(Tensor x, double min_val = -1.0, double max_val = 1.0, bool inplace = false) { return inplace ? x.hardtanh_(min_val, max_val).alias() : x.hardtanh(min_val, max_val); } diff --git a/src/TorchSharp/NN/Activation/LeakyReLU.cs b/src/TorchSharp/NN/Activation/LeakyReLU.cs index 51ec4ae31..f40866190 100644 --- a/src/TorchSharp/NN/Activation/LeakyReLU.cs +++ b/src/TorchSharp/NN/Activation/LeakyReLU.cs @@ -12,27 +12,21 @@ namespace Modules /// /// This class is used to represent a LeakyReLU module. /// - public sealed class LeakyReLU : torch.nn.Module + public sealed class LeakyReLU : ParamLessModule { - internal LeakyReLU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal LeakyReLU(double negative_slope, bool inplace) : base(nameof(LeakyReLU)) { - var res = THSNN_LeakyReLU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; + this.negative_slope = negative_slope; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(LeakyReLU).Name; + return torch.nn.functional.leaky_relu(tensor, negative_slope, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } + public double negative_slope {get; set;} } } @@ -48,9 +42,7 @@ public static partial class nn /// public static LeakyReLU LeakyReLU(double negative_slope = 0.01, bool inplace = false) { - var handle = THSNN_LeakyReLU_ctor(negative_slope, inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new LeakyReLU(handle, boxedHandle); + return new LeakyReLU(negative_slope, inplace); } public static partial class functional @@ -64,9 +56,7 @@ public static partial class functional /// public static Tensor leaky_relu(Tensor input, double negative_slope = 0.01, bool inplace = false) { - using (var m = nn.LeakyReLU(negative_slope, inplace)) { - return m.call(input); - } + return inplace ? input.leaky_relu_(negative_slope).alias() : input.leaky_relu(negative_slope); } } } diff --git a/src/TorchSharp/NN/Activation/LogSigmoid.cs b/src/TorchSharp/NN/Activation/LogSigmoid.cs index 802784356..d9aaf1acd 100644 --- a/src/TorchSharp/NN/Activation/LogSigmoid.cs +++ b/src/TorchSharp/NN/Activation/LogSigmoid.cs @@ -12,25 +12,16 @@ namespace Modules /// /// This class is used to represent a LogSigmoid module. /// - public sealed class LogSigmoid : torch.nn.Module + public sealed class LogSigmoid : ParamLessModule { - internal LogSigmoid() : base(nameof(LogSigmoid)) { } - - public override Tensor forward(Tensor tensor) + internal LogSigmoid() : base(nameof(LogSigmoid)) { - return tensor.log_sigmoid(); } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(LogSigmoid).Name; + return torch.nn.functional.logsigmoid(tensor); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } public static partial class torch diff --git a/src/TorchSharp/NN/Activation/LogSoftMax.cs b/src/TorchSharp/NN/Activation/LogSoftMax.cs index 302627c38..c4889174a 100644 --- a/src/TorchSharp/NN/Activation/LogSoftMax.cs +++ b/src/TorchSharp/NN/Activation/LogSoftMax.cs @@ -12,24 +12,19 @@ namespace Modules /// /// This class is used to represent a log softmax module. /// - public sealed class LogSoftmax : torch.nn.Module + public sealed class LogSoftmax : ParamLessModule { - internal LogSoftmax(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal LogSoftmax(long dim) : base(nameof(LogSoftmax)) { + this.dim = dim; } public override Tensor forward(Tensor tensor) { - var res = THSNN_LogSoftmax_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.log_softmax(tensor, dim); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + + public long dim { get; set; } } } @@ -39,9 +34,7 @@ public static partial class nn { public static LogSoftmax LogSoftmax(long dim) { - var handle = THSNN_LogSoftmax_ctor(dim, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new LogSoftmax(handle, boxedHandle); + return new LogSoftmax(dim); } public static partial class functional diff --git a/src/TorchSharp/NN/Activation/Mish.cs b/src/TorchSharp/NN/Activation/Mish.cs index eb57c9914..9f1fc90cc 100644 --- a/src/TorchSharp/NN/Activation/Mish.cs +++ b/src/TorchSharp/NN/Activation/Mish.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a Mish module. /// - public sealed class Mish : torch.nn.Module + public sealed class Mish : ParamLessModule { - internal Mish(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal Mish(bool inplace) : base(nameof(Mish)) { - var res = THSNN_Mish_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Mish).Name; + return torch.nn.functional.mish(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } @@ -43,12 +35,10 @@ public static partial class nn /// /// A Self Regularized Non-Monotonic Neural Activation Function. /// - /// - public static Mish Mish() + /// Do the operation in-place. Default: False + public static Mish Mish(bool inplace = false) { - var handle = THSNN_Mish_ctor(out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Mish(handle, boxedHandle); + return new Mish(inplace); } public static partial class functional @@ -57,12 +47,12 @@ public static partial class functional /// A Self Regularized Non-Monotonic Neural Activation Function. /// /// The input tensor - /// - public static Tensor Mish(Tensor x) + /// Do the operation in-place. Default: False + public static Tensor mish(Tensor x, bool inplace = false) { - using (var m = nn.Mish()) { - return m.call(x); - } + using var t1 = softplus(x); + using var t2 = t1.tanh(); + return inplace ? x.mul_(t2) : x.mul(t2); } } } diff --git a/src/TorchSharp/NN/Activation/PReLU.cs b/src/TorchSharp/NN/Activation/PReLU.cs index 3c8d666f5..99ab72c18 100644 --- a/src/TorchSharp/NN/Activation/PReLU.cs +++ b/src/TorchSharp/NN/Activation/PReLU.cs @@ -7,6 +7,7 @@ namespace TorchSharp { using Modules; + using TorchSharp.Utils; namespace Modules { @@ -15,13 +16,16 @@ namespace Modules /// public sealed class PReLU : torch.nn.Module { - internal PReLU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal PReLU(long num_parameters, double init) : base(nameof(PReLU)) + { + this._init = init; + // This will also set the weights + this.num_parameters = num_parameters; + } public override Tensor forward(Tensor tensor) { - var res = THSNN_PReLU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.prelu(tensor, weight); } public override string GetName() @@ -29,19 +33,55 @@ public override string GetName() return typeof(PReLU).Name; } - public Parameter? weight { - get { - var res = THSNN_PReLU_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); + public Parameter weight { + get => _weight!; + set { + if (value is null) throw new ArgumentNullException(nameof(weight)); + if (value.Handle != _weight?.Handle) { + _weight?.Dispose(); + _weight = (value.DetachFromDisposeScope() as Parameter)!; + ConditionallyRegisterParameter(nameof(weight), _weight); + } } + } + + public long num_parameters { + get => _num_parameters; + set { + if (value != _num_parameters) + { + this._num_parameters = value; + var w = torch.empty(value); + w.fill_(_init); + this._weight = new Parameter(w); + } + } + + } + + public double init { + get => _init; set { - if (value is null) throw new ArgumentNullException("weight cannot be set to 'null'"); - THSNN_PReLU_set_weight(handle, value!.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); + if (value != _init) + { + this._init = value; + var w = torch.empty(_num_parameters); + w.fill_(value); + this._weight = new Parameter(w); + } } } + + protected override void Dispose(bool disposing) + { + _weight?.Dispose(); + } + + private double _init = 0; + private long _num_parameters = 0; + + [ComponentName(Name = nameof(weight))] + private Parameter? _weight; } } @@ -61,9 +101,7 @@ public static partial class nn /// The desired floating point or complex dtype of the parameters and buffers in this module public static PReLU PReLU(long num_parameters, double init = 0.25, Device? device = null, ScalarType? dtype = null) { - var handle = THSNN_PReLU_ctor(num_parameters, init, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new PReLU(handle, boxedHandle).MoveModule(device, dtype); + return new PReLU(num_parameters, init).MoveModule(device, dtype); } public static partial class functional diff --git a/src/TorchSharp/NN/Activation/RReLU.cs b/src/TorchSharp/NN/Activation/RReLU.cs index 289664874..1aea1e23c 100644 --- a/src/TorchSharp/NN/Activation/RReLU.cs +++ b/src/TorchSharp/NN/Activation/RReLU.cs @@ -12,27 +12,23 @@ namespace Modules /// /// This class is used to represent a RReLU module. /// - public sealed class RReLU : torch.nn.Module + public sealed class RReLU : ParamLessModule { - internal RReLU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal RReLU(double lower, double upper, bool inplace) : base(nameof(RReLU)) { - var res = THSNN_RReLU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.lower = lower; + this.upper = upper; + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(RReLU).Name; + return torch.nn.functional.rrelu(tensor, lower, upper, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public double lower {get; set;} + public double upper {get; set;} + public bool inplace {get; set;} } } @@ -49,9 +45,7 @@ public static partial class nn /// public static RReLU RReLU(double lower = one_eighth, double upper = one_third, bool inplace = false) { - var handle = THSNN_RReLU_ctor(lower, upper, inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new RReLU(handle, boxedHandle); + return new RReLU(lower, upper, inplace); } private const double one_eighth = 1.0 / 8.0; @@ -67,11 +61,9 @@ public static partial class functional /// Upper bound of the uniform distribution. Default: 1/3 /// Do the operation in-place. Default: False /// - public static Tensor rrelu(Tensor x, double lower, double upper, bool inplace = false) + public static Tensor rrelu(Tensor x, double lower = one_eighth, double upper = one_third, bool inplace = false) { - using (var m = nn.RReLU(lower, upper, inplace)) { - return m.call(x); - } + return inplace ? x.rrelu_(lower, upper).alias() : x.rrelu(lower, upper); } } } diff --git a/src/TorchSharp/NN/Activation/ReLU6.cs b/src/TorchSharp/NN/Activation/ReLU6.cs index 1b89d60da..3ebb2c67d 100644 --- a/src/TorchSharp/NN/Activation/ReLU6.cs +++ b/src/TorchSharp/NN/Activation/ReLU6.cs @@ -14,27 +14,20 @@ namespace Modules /// /// This class is used to represent a ReLU6 module. /// - public sealed class ReLU6 : torch.nn.Module + public sealed class ReLU6 : ParamLessModule { - internal ReLU6(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal ReLU6(bool inplace) : base(nameof(ReLU6)) { - var res = NativeMethods.THSNN_ReLU6_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; } - public override string GetName() + + public override Tensor forward(Tensor tensor) { - return typeof(ReLU6).Name; + return torch.nn.functional.relu6(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } @@ -51,9 +44,7 @@ public static partial class nn /// public static ReLU6 ReLU6(bool inplace = false) { - var handle = NativeMethods.THSNN_ReLU6_ctor(inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReLU6(handle, boxedHandle); + return new ReLU6(inplace); } public static partial class functional @@ -68,9 +59,7 @@ public static partial class functional /// public static Tensor relu6(Tensor x, bool inplace = false) { - using (var m = nn.ReLU6(inplace)) { - return m.call(x); - } + return inplace ? x.relu6_().alias() : x.relu6(); } } } diff --git a/src/TorchSharp/NN/Activation/ReLu.cs b/src/TorchSharp/NN/Activation/ReLu.cs index 050a03235..68a16ea04 100644 --- a/src/TorchSharp/NN/Activation/ReLu.cs +++ b/src/TorchSharp/NN/Activation/ReLu.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a ReLU module. /// - public sealed class ReLU : torch.nn.Module + public sealed class ReLU : ParamLessModule { - internal ReLU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal ReLU(bool inplace) : base(nameof(ReLU)) { - var res = THSNN_ReLU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(ReLU).Name; + return torch.nn.functional.relu(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } public static partial class torch @@ -46,9 +38,7 @@ public static partial class nn /// public static ReLU ReLU(bool inplace = false) { - var handle = THSNN_ReLU_ctor(inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new ReLU(handle, boxedHandle); + return new ReLU(inplace); } public static partial class functional diff --git a/src/TorchSharp/NN/Activation/SELU.cs b/src/TorchSharp/NN/Activation/SELU.cs index 774ab5a24..b75278bd3 100644 --- a/src/TorchSharp/NN/Activation/SELU.cs +++ b/src/TorchSharp/NN/Activation/SELU.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a SELU module. /// - public sealed class SELU : torch.nn.Module + public sealed class SELU : ParamLessModule { - internal SELU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal SELU(bool inplace) : base(nameof(SELU)) { - var res = THSNN_SELU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(SELU).Name; + return torch.nn.functional.selu(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } @@ -47,9 +39,7 @@ public static partial class nn /// public static SELU SELU(bool inplace = false) { - var handle = THSNN_SELU_ctor(inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new SELU(handle, boxedHandle); + return new SELU(inplace); } public static partial class functional diff --git a/src/TorchSharp/NN/Activation/SiLU.cs b/src/TorchSharp/NN/Activation/SiLU.cs index 051675f17..5abbc74ea 100644 --- a/src/TorchSharp/NN/Activation/SiLU.cs +++ b/src/TorchSharp/NN/Activation/SiLU.cs @@ -12,15 +12,16 @@ namespace Modules /// /// This class is used to represent a SiLU module. /// - public sealed class SiLU : torch.nn.Module + public sealed class SiLU : ParamLessModule { - internal SiLU(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal SiLU(bool inplace) : base(nameof(SiLU)) + { + this.inplace = inplace; + } public override Tensor forward(Tensor tensor) { - var res = THSNN_SiLU_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.silu(tensor, inplace); } public override string GetName() @@ -28,11 +29,7 @@ public override string GetName() return typeof(SiLU).Name; } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } public static partial class torch @@ -42,13 +39,9 @@ public static partial class nn /// /// Sigmoid-Weighted Linear Unit /// - /// - /// The native libreary does not take an 'inplace' option, even though the PyTorch documentation mentions the parameter. - public static SiLU SiLU() + public static SiLU SiLU(bool inplace = false) { - var handle = THSNN_SiLU_ctor(out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new SiLU(handle, boxedHandle); + return new SiLU(inplace); } public static partial class functional diff --git a/src/TorchSharp/NN/Activation/Sigmoid.cs b/src/TorchSharp/NN/Activation/Sigmoid.cs index 1513f06f5..4981c814a 100644 --- a/src/TorchSharp/NN/Activation/Sigmoid.cs +++ b/src/TorchSharp/NN/Activation/Sigmoid.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a Sigmoid module. /// - public sealed class Sigmoid : torch.nn.Module + public sealed class Sigmoid : ParamLessModule { - internal Sigmoid(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal Sigmoid(bool inplace) : base(nameof(Sigmoid)) { - var res = THSNN_Sigmoid_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Sigmoid).Name; + return torch.nn.functional.sigmoid(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } public static partial class torch @@ -42,12 +34,11 @@ public static partial class nn /// /// Sigmoid activation /// + /// Do the operation in-place. Default: False /// - public static Sigmoid Sigmoid() + public static Sigmoid Sigmoid(bool inplace = false) { - var handle = THSNN_Sigmoid_ctor(out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Sigmoid(handle, boxedHandle); + return new Sigmoid(inplace); } public static partial class functional @@ -56,10 +47,11 @@ public static partial class functional /// Sigmoid activation /// /// The input tensor + /// Do the operation in-place. Default: False /// - public static Tensor sigmoid(Tensor x) + public static Tensor sigmoid(Tensor x, bool inplace = false) { - return x.sigmoid(); + return inplace ? x.sigmoid_().alias() : x.sigmoid(); } } } diff --git a/src/TorchSharp/NN/Activation/Softmax.cs b/src/TorchSharp/NN/Activation/Softmax.cs index dc4fea3fe..32aeee6f4 100644 --- a/src/TorchSharp/NN/Activation/Softmax.cs +++ b/src/TorchSharp/NN/Activation/Softmax.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a Softmax module. /// - public sealed class Softmax : torch.nn.Module + public sealed class Softmax : ParamLessModule { - internal Softmax(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) - { - var res = THSNN_Softmax_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + internal Softmax(long dim) : base(nameof(Softmax)) + { + this.dim = dim; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Softmax).Name; + return torch.nn.functional.softmax(tensor, dim); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public long dim {get; set;} } } @@ -47,9 +39,7 @@ public static partial class nn /// public static Softmax Softmax(long dim) { - var handle = THSNN_Softmax_ctor(dim, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Softmax(handle, boxedHandle); + return new Softmax(dim); } public static partial class functional @@ -60,7 +50,8 @@ public static partial class functional /// The input tensor /// A dimension along which softmax will be computed. /// The desired data type of returned tensor. - public static Tensor softmax(Tensor input, long dim, ScalarType? dtype = null) => torch.special.softmax(input, dim, dtype); + public static Tensor softmax(Tensor input, long dim, ScalarType? dtype = null) => + torch.special.softmax(input, dim, dtype); } } } diff --git a/src/TorchSharp/NN/Activation/Softmax2d.cs b/src/TorchSharp/NN/Activation/Softmax2d.cs index 58014fdc9..ed3977d26 100644 --- a/src/TorchSharp/NN/Activation/Softmax2d.cs +++ b/src/TorchSharp/NN/Activation/Softmax2d.cs @@ -12,27 +12,14 @@ namespace Modules /// /// This class is used to represent a Softmax2d module. /// - public sealed class Softmax2d : torch.nn.Module + public sealed class Softmax2d : ParamLessModule { - internal Softmax2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal Softmax2d() : base(nameof(Softmax2d)) { } public override Tensor forward(Tensor tensor) { - var res = THSNN_Softmax2d_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.softmax2d(tensor); } - - public override string GetName() - { - return typeof(Softmax2d).Name; - } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; } } public static partial class torch @@ -45,9 +32,7 @@ public static partial class nn /// public static Softmax2d Softmax2d() { - var handle = THSNN_Softmax2d_ctor(out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Softmax2d(handle, boxedHandle); + return new Softmax2d(); } public static partial class functional @@ -59,9 +44,7 @@ public static partial class functional /// public static Tensor softmax2d(Tensor x) { - using (var m = nn.Softmax2d()) { - return m.call(x); - } + return torch.nn.functional.softmax(x, -3); } } } diff --git a/src/TorchSharp/NN/Activation/Softmin.cs b/src/TorchSharp/NN/Activation/Softmin.cs index 9c3c4eba7..be2b91761 100644 --- a/src/TorchSharp/NN/Activation/Softmin.cs +++ b/src/TorchSharp/NN/Activation/Softmin.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a Softmin module. /// - public sealed class Softmin : torch.nn.Module + public sealed class Softmin : ParamLessModule { - internal Softmin(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) - { - var res = THSNN_Softmin_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + internal Softmin(long dim) : base(nameof(Softmin)) + { + this.dim = dim; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Softmin).Name; + return torch.nn.functional.softmin(tensor, dim); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public long dim {get; set;} } } @@ -47,9 +39,7 @@ public static partial class nn /// public static Softmin Softmin(long dim) { - var handle = THSNN_Softmin_ctor(dim, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Softmin(handle, boxedHandle); + return new Softmin(dim); } public static partial class functional @@ -62,9 +52,8 @@ public static partial class functional /// public static Tensor softmin(Tensor x, long dim) { - using (var m = nn.Softmin(dim)) { - return m.call(x); - } + using var minus_x = -x; + return softmax(minus_x, dim); } } } diff --git a/src/TorchSharp/NN/Activation/Softplus.cs b/src/TorchSharp/NN/Activation/Softplus.cs index d814b1042..a8651aab3 100644 --- a/src/TorchSharp/NN/Activation/Softplus.cs +++ b/src/TorchSharp/NN/Activation/Softplus.cs @@ -12,27 +12,21 @@ namespace Modules /// /// This class is used to represent a Softplus module. /// - public sealed class Softplus : torch.nn.Module + public sealed class Softplus : ParamLessModule { - internal Softplus(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal Softplus(int beta = 1, int threshold = 20) : base(nameof(Softplus)) { - var res = THSNN_Softplus_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.beta = beta; + this.threshold = threshold; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Softplus).Name; + return torch.nn.functional.softplus(tensor, beta, threshold); } - - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + + public int beta {get; set;} + public int threshold {get; set;} } } @@ -46,11 +40,9 @@ public static partial class nn /// The β value for the Softplus formulation. /// Values above this revert to a linear function /// - public static Softplus Softplus(double beta = 1.0, double threshold = 20.0) + public static Softplus Softplus(int beta = 1, int threshold = 20) { - var handle = THSNN_Softplus_ctor(beta, threshold, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Softplus(handle, boxedHandle); + return new Softplus(beta, threshold); } public static partial class functional @@ -62,11 +54,9 @@ public static partial class functional /// The β value for the Softplus formulation. /// Values above this revert to a linear function /// - public static Tensor softplus(Tensor x, double beta = 1.0, double threshold = 20.0) + public static Tensor softplus(Tensor x, int beta = 1, int threshold = 20) { - using (var m = nn.Softplus(beta, threshold)) { - return m.call(x); - } + return x.softplus(beta, threshold); } } } diff --git a/src/TorchSharp/NN/Activation/Softshrink.cs b/src/TorchSharp/NN/Activation/Softshrink.cs index de32e4dfb..bfe2f6f19 100644 --- a/src/TorchSharp/NN/Activation/Softshrink.cs +++ b/src/TorchSharp/NN/Activation/Softshrink.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a Softshrink module. /// - public sealed class Softshrink : torch.nn.Module + public sealed class Softshrink : ParamLessModule { - internal Softshrink(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) - { - var res = THSNN_Softshrink_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + internal Softshrink(double lambda = 0.5) : base(nameof(Softshrink)) + { + this.lambda = lambda; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Softshrink).Name; + return torch.nn.functional.softshrink(tensor, lambda); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public double lambda {get; set; } } } @@ -41,30 +33,29 @@ public static partial class torch public static partial class nn { /// - /// Softshrink + /// Hardshrink /// /// the λ value for the Softshrink formulation. Default: 0.5 /// public static Softshrink Softshrink(double lambda = 0.5) { - var handle = THSNN_Softshrink_ctor(lambda, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Softshrink(handle, boxedHandle); + return new Softshrink(lambda); } public static partial class functional { /// - /// Softshrink + /// Hardshrink /// /// The input tensor - /// The λ value for the Softshrink formulation. Default: 0.5 + /// The λ value for the Hardshrink formulation. Default: 0.5 /// - public static Tensor Softshrink(Tensor x, double lambda = 0.5) + public static Tensor softshrink(Tensor x, double lambda = 0.5) { - using (var m = nn.Softshrink(lambda)) { - return m.call(x); - } + using var sc = (Scalar)lambda; + var result = THSTensor_softshrink(x.Handle, sc.Handle); + if (result == IntPtr.Zero) { torch.CheckForErrors(); } + return new Tensor(result); } } } diff --git a/src/TorchSharp/NN/Activation/Softsign.cs b/src/TorchSharp/NN/Activation/Softsign.cs index 6dbbffe96..f7bca1ec8 100644 --- a/src/TorchSharp/NN/Activation/Softsign.cs +++ b/src/TorchSharp/NN/Activation/Softsign.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a Softsign module. /// - public sealed class Softsign : torch.nn.Module + public sealed class Softsign : ParamLessModule { - internal Softsign(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal Softsign(bool inplace) : base(nameof(Softsign)) { - var res = THSNN_Softsign_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Softsign).Name; + return torch.nn.functional.softsign(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } @@ -43,12 +35,10 @@ public static partial class nn /// /// Softsign /// - /// - public static Softsign Softsign() + /// Do the operation in-place. Default: False + public static Softsign Softsign(bool inplace = false) { - var handle = THSNN_Softsign_ctor(out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Softsign(handle, boxedHandle); + return new Softsign(inplace); } public static partial class functional @@ -57,12 +47,11 @@ public static partial class functional /// Softsign /// /// The input tensor - /// - public static Tensor Softsign(Tensor x) + /// Do the operation in-place. Default: False + public static Tensor softsign(Tensor x, bool inplace = false) { - using (var m = nn.Softsign()) { - return m.call(x); - } + using var y = 1 + x.abs(); + return inplace ? x.div_(y) : x.div(y); } } } diff --git a/src/TorchSharp/NN/Activation/Tanh.cs b/src/TorchSharp/NN/Activation/Tanh.cs index 9ff611792..34bfb6e5a 100644 --- a/src/TorchSharp/NN/Activation/Tanh.cs +++ b/src/TorchSharp/NN/Activation/Tanh.cs @@ -12,15 +12,16 @@ namespace Modules /// /// This class is used to represent a Tanh module. /// - public sealed class Tanh : torch.nn.Module + public sealed class Tanh : ParamLessModule { - internal Tanh(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal Tanh(bool inplace) : base(nameof(Tanh)) + { + this.inplace = inplace; + } public override Tensor forward(Tensor tensor) { - var res = THSNN_Tanh_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.tanh(tensor, inplace); } public override string GetName() @@ -28,11 +29,7 @@ public override string GetName() return typeof(Tanh).Name; } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } @@ -44,11 +41,9 @@ public static partial class nn /// Tanh activation /// /// - public static Tanh Tanh() + public static Tanh Tanh(bool inplace = false) { - var handle = THSNN_Tanh_ctor(out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tanh(handle, boxedHandle); + return new Tanh(inplace); } public static partial class functional diff --git a/src/TorchSharp/NN/Activation/Tanhshrink.cs b/src/TorchSharp/NN/Activation/Tanhshrink.cs index 371200871..f2a3f3b3e 100644 --- a/src/TorchSharp/NN/Activation/Tanhshrink.cs +++ b/src/TorchSharp/NN/Activation/Tanhshrink.cs @@ -12,27 +12,19 @@ namespace Modules /// /// This class is used to represent a Tanhshrink module. /// - public sealed class Tanhshrink : torch.nn.Module + public sealed class Tanhshrink : ParamLessModule { - internal Tanhshrink(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } - - public override Tensor forward(Tensor tensor) + internal Tanhshrink(bool inplace) : base(nameof(Tanhshrink)) { - var res = THSNN_Tanhshrink_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + this.inplace = inplace; } - public override string GetName() + public override Tensor forward(Tensor tensor) { - return typeof(Tanhshrink).Name; + return torch.nn.functional.tanhshrink(tensor, inplace); } - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set; } } } @@ -43,12 +35,10 @@ public static partial class nn /// /// Tanhshrink /// - /// - public static Tanhshrink Tanhshrink() + /// Do the operation in-place. Default: False + public static Tanhshrink Tanhshrink(bool inplace = false) { - var handle = THSNN_Tanhshrink_ctor(out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tanhshrink(handle, boxedHandle); + return new Tanhshrink(inplace); } public static partial class functional @@ -57,12 +47,11 @@ public static partial class functional /// Tanhshrink /// /// The input tensor - /// - public static Tensor Tanhshrink(Tensor x) + /// Do the operation in-place. Default: False + public static Tensor tanhshrink(Tensor x, bool inplace = false) { - using (var m = nn.Tanhshrink()) { - return m.call(x); - } + using var tanh_x = x.tanh(); + return inplace ? x.sub_(tanh_x) : x.sub(tanh_x); } } } diff --git a/src/TorchSharp/NN/Activation/Threshold.cs b/src/TorchSharp/NN/Activation/Threshold.cs index cfd9ea1c7..a3139fdbb 100644 --- a/src/TorchSharp/NN/Activation/Threshold.cs +++ b/src/TorchSharp/NN/Activation/Threshold.cs @@ -12,27 +12,25 @@ namespace Modules /// /// This class is used to represent a Threshold module. /// - public sealed class Threshold : torch.nn.Module + public sealed class Threshold : ParamLessModule { - internal Threshold(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) { } + internal Threshold(double threshold, double value, bool inplace) : base(nameof(Threshold)) + { + this.inplace = inplace; + this.threshold = threshold; + this.value = value; + } public override Tensor forward(Tensor tensor) { - var res = THSNN_Threshold_forward(handle, tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + return torch.nn.functional.threshold(tensor, threshold, value, inplace); } + + public double threshold {get; set;} - public override string GetName() - { - return typeof(Threshold).Name; - } + public double value {get; set;} - // Rather than spending cycles only to discover that this module has neither - // parameters nor buffers, just shortcut the move completely. - protected internal override nn.Module _to(Device device, ScalarType dtype) => this; - protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; - protected internal override nn.Module _to(ScalarType dtype) => this; + public bool inplace {get; set;} } } @@ -49,9 +47,7 @@ public static partial class nn /// public static Threshold Threshold(double threshold, double value, bool inplace = false) { - var handle = THSNN_Threshold_ctor(threshold, value, inplace, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new Threshold(handle, boxedHandle); + return new Threshold(threshold, value, inplace); } public static partial class functional @@ -64,11 +60,9 @@ public static partial class functional /// The value to replace with /// Do the operation in-place /// - public static Tensor Threshold(Tensor x, double threshold, double value, bool inplace = false) + public static Tensor threshold(Tensor x, double threshold, double value, bool inplace = false) { - using (var m = nn.Threshold(threshold, value, inplace)) { - return m.call(x); - } + return inplace ? x.threshold_(threshold, value).alias() : x.threshold(threshold, value); } } } diff --git a/src/TorchSharp/NN/Module.cs b/src/TorchSharp/NN/Module.cs index d40ada65b..e4fbabcf3 100644 --- a/src/TorchSharp/NN/Module.cs +++ b/src/TorchSharp/NN/Module.cs @@ -785,6 +785,8 @@ protected void ConditionallyRegisterBuffer(string name, Tensor value, bool persi public virtual string GetName() { + if (!string.IsNullOrEmpty(this.name)) return this.name; + var res = THSNN_Module_name(handle); CheckForErrors(); return res; diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index 5bfed781e..4320e7bdf 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -509,24 +509,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_affine_grid(IntPtr theta, IntPtr size, int size_len, [MarshalAs(UnmanagedType.U1)] bool align_corners); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_CELU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_CELU_ctor(double alpha, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LeakyReLU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LeakyReLU_ctor(double negative_slope, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LogSoftmax_forward(torch.nn.Module.HType handle, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_LogSoftmax_ctor(long dim, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_InstanceNorm3d_forward(IntPtr module, IntPtr tensor); @@ -896,141 +878,21 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_BatchNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ELU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ELU_ctor(double alpha, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_GELU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_GELU_ctor(out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_GLU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_GLU_ctor(long dim, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Hardshrink_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Hardshrink_ctor(double lambd, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Hardtanh_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Hardtanh_ctor(double min_val, double max_val, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Mish_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Mish_ctor(out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PReLU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PReLU_ctor(long nparams, double init, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_PReLU_weight(torch.nn.Module.HType module); [DllImport("LibTorchSharp")] internal static extern void THSNN_PReLU_set_weight(torch.nn.Module.HType module, IntPtr tensor); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReLU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReLU_ctor([MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReLU6_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_ReLU6_ctor([MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_RReLU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_RReLU_ctor(double lower, double upper, [MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_scaled_dot_product_attention(IntPtr query, IntPtr key, IntPtr value, IntPtr attention_mask, double p, [MarshalAs(UnmanagedType.U1)] bool casual); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_SELU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_SELU_ctor([MarshalAs(UnmanagedType.U1)] bool inplace, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Sigmoid_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Sigmoid_ctor(out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_SiLU_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_SiLU_ctor(out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softmax_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softmax_ctor(long dim, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softmax2d_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softmax2d_ctor(out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softmin_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softmin_ctor(long dim, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softplus_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softplus_ctor(double beta, double threshold, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_Softshrink_forward(torch.nn.Module.HType module, IntPtr tensor); [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_Softshrink_ctor(double lambd, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softsign_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Softsign_ctor(out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Tanh_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Tanh_ctor(out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Tanhshrink_forward(torch.nn.Module.HType module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_Tanhshrink_ctor(out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_Threshold_forward(torch.nn.Module.HType module, IntPtr tensor); diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs index 0de92012c..3055e8c83 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSTensor.cs @@ -490,6 +490,15 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_transpose(IntPtr tensor, long dim1, long dim2); + [DllImport("LibTorchSharp")] + internal static extern void THSTensor_transpose_(IntPtr tensor, long dim1, long dim2); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_threshold(IntPtr tensor, IntPtr threshold, IntPtr value); + + [DllImport("LibTorchSharp")] + internal static extern void THSTensor_threshold_(IntPtr tensor, IntPtr threshold, IntPtr value); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_tril(IntPtr tensor, long diagonal, [MarshalAs(UnmanagedType.U1)] bool inplace); @@ -502,9 +511,6 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_triu_indices(long row, long col, long offset, sbyte scalar_type, int device_type, int device_index); - [DllImport("LibTorchSharp")] - internal static extern void THSTensor_transpose_(IntPtr tensor, long dim1, long dim2); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_view(IntPtr tensor, IntPtr shape, int length); @@ -605,7 +611,7 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, internal static extern IntPtr THSTensor_positive(IntPtr tensor); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_softplus(IntPtr tensor); + internal static extern IntPtr THSTensor_softplus(IntPtr tensor, IntPtr beta, IntPtr threshold); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_ravel(IntPtr tensor); @@ -623,10 +629,22 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, internal static extern void THSTensor_relu6_(IntPtr tensor); [DllImport("LibTorchSharp")] - internal static extern IntPtr THSTensor_celu(IntPtr tensor); + internal static extern IntPtr THSTensor_rrelu(IntPtr tensor, double lower, double upper); [DllImport("LibTorchSharp")] - internal static extern void THSTensor_celu_(IntPtr tensor); + internal static extern void THSTensor_rrelu_(IntPtr tensor, double lower, double upper); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_celu(IntPtr tensor, IntPtr alpha); + + [DllImport("LibTorchSharp")] + internal static extern void THSTensor_celu_(IntPtr tensor, IntPtr alpha); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_hardshrink(IntPtr tensor, IntPtr lambda); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_softshrink(IntPtr tensor, IntPtr lambda); [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_elu(IntPtr tensor, IntPtr alpha, IntPtr scale, IntPtr input_scale); @@ -637,6 +655,12 @@ internal static extern IntPtr THSTensor_upsample_nearest3d(IntPtr input, [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_gelu(IntPtr tensor); + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_gelu_(IntPtr tensor); + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSTensor_glu(IntPtr tensor, long dim); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSTensor_hardsigmoid(IntPtr tensor); diff --git a/src/TorchSharp/Tensor/Tensor.cs b/src/TorchSharp/Tensor/Tensor.cs index 04fbb43da..f72a2e812 100644 --- a/src/TorchSharp/Tensor/Tensor.cs +++ b/src/TorchSharp/Tensor/Tensor.cs @@ -2166,6 +2166,21 @@ public Tensor transpose_(long dim0, long dim1) CheckForErrors(); return this; } + + public Tensor threshold(Scalar threshold, Scalar value) + { + var res = NativeMethods.THSTensor_threshold(Handle, threshold.Handle, value.Handle); + if (res == IntPtr.Zero) + CheckForErrors(); + return new Tensor(res); + } + + public Tensor threshold_(Scalar threshold, Scalar value) + { + NativeMethods.THSTensor_threshold_(Handle, threshold.Handle, value.Handle); + CheckForErrors(); + return this; + } /// /// Returns a view of the tensor conjugated and with the last two dimensions transposed. @@ -2695,9 +2710,13 @@ public Tensor positive() public Tensor softmax(long dim, ScalarType? dtype = null) => torch.special.softmax(this, dim, dtype); - public Tensor softplus() + + public Tensor softplus(int beta = 1, int threshold = 20) => + softplus1(beta, threshold); + + private Tensor softplus1(Scalar beta, Scalar threshold) { - var res = NativeMethods.THSTensor_softplus(Handle); + var res = NativeMethods.THSTensor_softplus(Handle, beta.Handle, threshold.Handle); if (res == IntPtr.Zero) CheckForErrors(); return new Tensor(res); @@ -2741,22 +2760,50 @@ public Tensor relu6_() return this; } - public Tensor celu() + + + private const double one_eighth = 1.0 / 8.0; + private const double one_third = 1.0 / 3.0; + + public Tensor rrelu(double lower = one_eighth, double upper = one_third) { - var res = NativeMethods.THSTensor_celu(Handle); + var res = NativeMethods.THSTensor_rrelu(Handle, lower, upper); if (res == IntPtr.Zero) CheckForErrors(); return new Tensor(res); } - public Tensor celu_() + public Tensor rrelu_(double lower = one_eighth, double upper = one_third) { - NativeMethods.THSTensor_celu_(Handle); + NativeMethods.THSTensor_rrelu_(Handle, lower, upper); CheckForErrors(); return this; } - public Tensor elu(Scalar alpha, Scalar scale, Scalar input_scale) + public Tensor celu() => this.celu(1.0); + + public Tensor celu_() => this.celu_(1.0); + + public Tensor celu(Scalar alpha) + { + var res = NativeMethods.THSTensor_celu(Handle, alpha.Handle); + if (res == IntPtr.Zero) + CheckForErrors(); + return new Tensor(res); + } + + public Tensor celu_(Scalar alpha) + { + NativeMethods.THSTensor_celu_(Handle, alpha.Handle); + CheckForErrors(); + return this; + } + + public Tensor elu(double alpha = 1) => elu1(alpha, 1.0, 1.0); + + public Tensor elu_(double alpha = 1) => elu2(alpha, 1.0, 1.0); + + private Tensor elu1(Scalar alpha, Scalar scale, Scalar input_scale) { var res = NativeMethods.THSTensor_elu(Handle, alpha.Handle, scale.Handle, input_scale.Handle); if (res == IntPtr.Zero) @@ -2764,7 +2811,7 @@ public Tensor elu(Scalar alpha, Scalar scale, Scalar input_scale) return new Tensor(res); } - public Tensor elu_(Scalar alpha, Scalar scale, Scalar input_scale) + private Tensor elu2(Scalar alpha, Scalar scale, Scalar input_scale) { NativeMethods.THSTensor_elu_(Handle, alpha.Handle, scale.Handle, input_scale.Handle); CheckForErrors(); @@ -2779,6 +2826,22 @@ public Tensor gelu() return new Tensor(res); } + public Tensor gelu_() + { + var res = NativeMethods.THSTensor_gelu_(Handle); + if (res == IntPtr.Zero) + CheckForErrors(); + return new Tensor(res); + } + + public Tensor glu(long dim = -1) + { + var res = NativeMethods.THSTensor_glu(Handle, dim); + if (res == IntPtr.Zero) + CheckForErrors(); + return new Tensor(res); + } + public Tensor hardsigmoid() { var res = NativeMethods.THSTensor_hardsigmoid(Handle); diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index 355c50baa..dee565b1a 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -19,11 +19,12 @@ namespace TorchSharp { static internal class TestUtils { - public static IList AvailableDevices(bool cuda = true) + public static IList AvailableDevices(bool cuda = true, bool mps = false) { List result = new List(); result.Add(torch.CPU); if (cuda && torch.cuda_is_available()) result.Add(torch.CUDA); + if (mps && torch.mps_is_available()) result.Add(torch.MPS); return result; } } @@ -601,6 +602,10 @@ public void EvaluatePReLU() var rel = PReLU(1, 0.35, device); + Assert.Equal(1, rel.num_parameters); + Assert.Equal(0.35f, rel.weight.item()); + Assert.True(rel.weight.requires_grad); + var input = torch.randn(new long[] { 4, 3, 8, 8 }, device: device) * 5.0; var output = rel.call(input); Assert.Equal(device.type, output.device_type); @@ -717,11 +722,15 @@ public void EvaluateSiLU() public void EvaluateSoftmax2d() { var rel = Softmax2d(); + var rel_x = Softmax(-3); + foreach (var device in TestUtils.AvailableDevices()) { var input = torch.randn(new long[] { 64, 3, 8, 8 }, device: device) * 25.0; var output = rel.call(input); Assert.Equal(device.type, output.device_type); + Assert.True(torch.allclose(rel_x.call(input), output)); + var values = output.data().ToArray(); Assert.Equal(input.shape, output.shape); Assert.All(values, val => Assert.True(val >= 0.0 && val <= 1.0)); From 640b7bfabff341c9e4f65d345eaf75f79041024c Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Wed, 13 Mar 2024 15:00:05 -0700 Subject: [PATCH 38/47] Added check of 'disposing' in one place. --- src/TorchSharp/NN/Activation/PReLU.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/TorchSharp/NN/Activation/PReLU.cs b/src/TorchSharp/NN/Activation/PReLU.cs index 99ab72c18..1e0fc8421 100644 --- a/src/TorchSharp/NN/Activation/PReLU.cs +++ b/src/TorchSharp/NN/Activation/PReLU.cs @@ -74,7 +74,9 @@ public double init { protected override void Dispose(bool disposing) { - _weight?.Dispose(); + if (disposing) { + _weight?.Dispose(); + } } private double _init = 0; From 6c934296b79979d7614ac6d1712ab2abf7656aa2 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Wed, 13 Mar 2024 19:05:48 -0700 Subject: [PATCH 39/47] Address PR comments. --- src/TorchSharp/NN/Activation/Mish.cs | 2 +- src/TorchSharp/NN/Activation/Softsign.cs | 3 ++- src/TorchSharp/NN/Activation/Tanhshrink.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/TorchSharp/NN/Activation/Mish.cs b/src/TorchSharp/NN/Activation/Mish.cs index 9f1fc90cc..cc00fe288 100644 --- a/src/TorchSharp/NN/Activation/Mish.cs +++ b/src/TorchSharp/NN/Activation/Mish.cs @@ -52,7 +52,7 @@ public static Tensor mish(Tensor x, bool inplace = false) { using var t1 = softplus(x); using var t2 = t1.tanh(); - return inplace ? x.mul_(t2) : x.mul(t2); + return inplace ? x.mul_(t2).alias() : x.mul(t2); } } } diff --git a/src/TorchSharp/NN/Activation/Softsign.cs b/src/TorchSharp/NN/Activation/Softsign.cs index f7bca1ec8..c7386d0b8 100644 --- a/src/TorchSharp/NN/Activation/Softsign.cs +++ b/src/TorchSharp/NN/Activation/Softsign.cs @@ -50,7 +50,8 @@ public static partial class functional /// Do the operation in-place. Default: False public static Tensor softsign(Tensor x, bool inplace = false) { - using var y = 1 + x.abs(); + using var abs = x.abs(); + using var y = 1 + abs; return inplace ? x.div_(y) : x.div(y); } } diff --git a/src/TorchSharp/NN/Activation/Tanhshrink.cs b/src/TorchSharp/NN/Activation/Tanhshrink.cs index f2a3f3b3e..5e07d6c4c 100644 --- a/src/TorchSharp/NN/Activation/Tanhshrink.cs +++ b/src/TorchSharp/NN/Activation/Tanhshrink.cs @@ -51,7 +51,7 @@ public static partial class functional public static Tensor tanhshrink(Tensor x, bool inplace = false) { using var tanh_x = x.tanh(); - return inplace ? x.sub_(tanh_x) : x.sub(tanh_x); + return inplace ? x.sub_(tanh_x).alias() : x.sub(tanh_x); } } } From 0ef818baa8c93e9b82f88b1ed5d29cae18e3924c Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Wed, 13 Mar 2024 19:27:23 -0700 Subject: [PATCH 40/47] More PR adjustments --- src/TorchSharp/NN/Activation/PReLU.cs | 4 ++-- src/TorchSharp/NN/Activation/Softshrink.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/TorchSharp/NN/Activation/PReLU.cs b/src/TorchSharp/NN/Activation/PReLU.cs index 1e0fc8421..d1cacf7c1 100644 --- a/src/TorchSharp/NN/Activation/PReLU.cs +++ b/src/TorchSharp/NN/Activation/PReLU.cs @@ -47,7 +47,7 @@ public Parameter weight { public long num_parameters { get => _num_parameters; - set { + private set { if (value != _num_parameters) { this._num_parameters = value; @@ -61,7 +61,7 @@ public long num_parameters { public double init { get => _init; - set { + private set { if (value != _init) { this._init = value; diff --git a/src/TorchSharp/NN/Activation/Softshrink.cs b/src/TorchSharp/NN/Activation/Softshrink.cs index bfe2f6f19..beff46550 100644 --- a/src/TorchSharp/NN/Activation/Softshrink.cs +++ b/src/TorchSharp/NN/Activation/Softshrink.cs @@ -33,7 +33,7 @@ public static partial class torch public static partial class nn { /// - /// Hardshrink + /// Softshrink /// /// the λ value for the Softshrink formulation. Default: 0.5 /// @@ -45,10 +45,10 @@ public static Softshrink Softshrink(double lambda = 0.5) public static partial class functional { /// - /// Hardshrink + /// Softshrink /// /// The input tensor - /// The λ value for the Hardshrink formulation. Default: 0.5 + /// The λ value for the Softshrink formulation. Default: 0.5 /// public static Tensor softshrink(Tensor x, double lambda = 0.5) { From d4c04829ff4c9acf3258f9ad8e396620dd892d1c Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Thu, 14 Mar 2024 10:32:29 -0700 Subject: [PATCH 41/47] Moved GroupNorm to C# --- src/Native/LibTorchSharp/THSNN.h | 8 -- src/Native/LibTorchSharp/THSNormalization.cpp | 34 --------- src/TorchSharp/NN/Normalization/GroupNorm.cs | 74 +++++++++++-------- src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 18 ----- 4 files changed, 43 insertions(+), 91 deletions(-) diff --git a/src/Native/LibTorchSharp/THSNN.h b/src/Native/LibTorchSharp/THSNN.h index 179b83b87..51ca417f1 100644 --- a/src/Native/LibTorchSharp/THSNN.h +++ b/src/Native/LibTorchSharp/THSNN.h @@ -173,14 +173,6 @@ EXPORT_API(Tensor) THSNN_InstanceNorm1d_get_batches(const NNModule module); EXPORT_API(Tensor) THSNN_InstanceNorm2d_get_batches(const NNModule module); EXPORT_API(Tensor) THSNN_InstanceNorm3d_get_batches(const NNModule module); -EXPORT_API(NNModule) THSNN_GroupNorm_ctor(const int64_t num_groups, const int64_t num_channels, const double eps, const bool affine, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_GroupNorm_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(Tensor) THSNN_GroupNorm_bias(const NNModule module); -EXPORT_API(void) THSNN_GroupNorm_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_GroupNorm_weight(const NNModule module); -EXPORT_API(void) THSNN_GroupNorm_set_weight(const NNModule module, const Tensor weight); - EXPORT_API(Tensor) THSNN_batch_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool training, const double momentum, const double eps); EXPORT_API(Tensor) THSNN_group_norm(const Tensor input, int64_t num_groups, const Tensor weight, const Tensor bias, const double eps); EXPORT_API(Tensor) THSNN_instance_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool use_input_stats, const double momentum, const double eps); diff --git a/src/Native/LibTorchSharp/THSNormalization.cpp b/src/Native/LibTorchSharp/THSNormalization.cpp index c17c4b98e..dcb461a99 100644 --- a/src/Native/LibTorchSharp/THSNormalization.cpp +++ b/src/Native/LibTorchSharp/THSNormalization.cpp @@ -57,40 +57,6 @@ Tensor THSNN_BatchNorm3d_forward(const NNModule module, const Tensor tensor) CATCH_TENSOR((*module)->as()->forward(*tensor)); } -NNModule THSNN_GroupNorm_ctor(const int64_t num_groups, const int64_t num_channels, const double eps, const bool affine, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::GroupNormOptions(num_groups, num_channels).eps(eps).affine(affine); - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_GroupNorm_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -Tensor THSNN_GroupNorm_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_GroupNorm_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_GroupNorm_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_GroupNorm_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - - NNModule THSNN_InstanceNorm1d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule) { CATCH_RETURN_NNModule( diff --git a/src/TorchSharp/NN/Normalization/GroupNorm.cs b/src/TorchSharp/NN/Normalization/GroupNorm.cs index e63b5c8c7..e6bfcd991 100644 --- a/src/TorchSharp/NN/Normalization/GroupNorm.cs +++ b/src/TorchSharp/NN/Normalization/GroupNorm.cs @@ -1,12 +1,15 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. using System; using static TorchSharp.torch; +using static TorchSharp.torch.nn; using static TorchSharp.PInvoke.NativeMethods; #nullable enable namespace TorchSharp { using Modules; + using TorchSharp.Utils; + using F = TorchSharp.torch.nn.functional; namespace Modules { @@ -16,47 +19,60 @@ namespace Modules /// public sealed class GroupNorm : torch.nn.Module { - internal GroupNorm(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal GroupNorm(long num_groups, long num_channels, double eps, bool affine, Device? device, ScalarType? dtype) : base(nameof(GroupNorm)) { + this.eps = eps; + this.affine = affine; + this.num_groups = num_groups; + + if (affine) { + weight = Parameter(torch.empty(num_channels, dtype, device)); + this.bias = Parameter(torch.empty(num_channels, dtype, device)); + } } public override Tensor forward(Tensor tensor) { - if (tensor.Dimensions < 3) throw new ArgumentException($"Invalid number of dimensions for GroupNorm argument: {tensor.Dimensions}"); - var res = THSNN_GroupNorm_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); + if (tensor.Dimensions < 3) + throw new ArgumentException($"Invalid number of dimensions for GroupNorm argument: {tensor.Dimensions}"); + return F.group_norm(tensor, num_groups, weight, bias, eps); + } + + protected override void Dispose(bool disposing) + { + _weight?.Dispose(); + _bias?.Dispose(); + base.Dispose(disposing); } public Parameter? bias { - get { - var res = THSNN_GroupNorm_bias(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } + get => _bias; set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("bias cannot be set to 'null'"); - THSNN_GroupNorm_set_bias(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterParameter("bias", value); + _bias?.Dispose(); + _bias = value?.DetachFromDisposeScope() as Parameter; + ConditionallyRegisterParameter(nameof(bias), _bias); } } - public Parameter? weight { - get { - var res = THSNN_GroupNorm_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } + public Parameter weight { + get => _weight!; set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("weight cannot be set to 'null'"); - THSNN_GroupNorm_set_weight(handle, value is null ? IntPtr.Zero : value.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); + if (value is null) throw new ArgumentNullException(nameof(weight)); + if (value.Handle != _weight?.Handle) { + _weight?.Dispose(); + _weight = (value.DetachFromDisposeScope() as Parameter)!; + ConditionallyRegisterParameter(nameof(weight), _weight); + } } } + + [ComponentName(Name = nameof(bias))] + private Parameter? _bias; + [ComponentName(Name = nameof(weight))] + private Parameter? _weight; + public long num_groups { get; set; } + public double eps { get; set; } + public bool affine { get; set; } } } @@ -76,11 +92,7 @@ public static partial class nn /// public static GroupNorm GroupNorm(long num_groups, long num_channels, double eps = 1e-05, bool affine = true, Device? device = null, ScalarType? dtype = null) { - unsafe { - var handle = THSNN_GroupNorm_ctor(num_groups, num_channels, eps, affine, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new GroupNorm(handle, boxedHandle).MoveModule(device, dtype); - } + return new GroupNorm(num_groups, num_channels, eps, affine, device, dtype); } } } diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index 4320e7bdf..e86ad15dd 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -749,24 +749,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_BatchNorm1d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_GroupNorm_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_GroupNorm_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_GroupNorm_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_GroupNorm_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_GroupNorm_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_GroupNorm_ctor(long num_groups, long num_channels, double eps, [MarshalAs(UnmanagedType.U1)] bool affine, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_Unflatten_forward(torch.nn.Module.HType module, IntPtr tensor); From 4ba0a92eeb6b931a9366e082a4e66a719e6463f2 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Thu, 14 Mar 2024 16:03:31 -0700 Subject: [PATCH 42/47] Implement BatchNorm and InstanceNorm modules in terms of the functional APIs. --- src/Native/LibTorchSharp/THSNN.h | 92 ---- src/Native/LibTorchSharp/THSNormalization.cpp | 518 +----------------- src/TorchSharp/NN/Normalization/BatchNorm.cs | 53 ++ .../NN/Normalization/BatchNorm1D.cs | 102 +--- .../NN/Normalization/BatchNorm2D.cs | 102 +--- .../NN/Normalization/BatchNorm3D.cs | 102 +--- src/TorchSharp/NN/Normalization/Functional.cs | 4 +- .../NN/Normalization/InstanceNorm.cs | 57 ++ .../NN/Normalization/InstanceNorm1d.cs | 102 +--- .../NN/Normalization/InstanceNorm2d.cs | 102 +--- .../NN/Normalization/InstanceNorm3d.cs | 102 +--- src/TorchSharp/NN/Normalization/NormBase.cs | 145 +++++ src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 222 -------- test/TorchSharpTest/NN.cs | 91 ++- 14 files changed, 440 insertions(+), 1354 deletions(-) create mode 100644 src/TorchSharp/NN/Normalization/BatchNorm.cs create mode 100644 src/TorchSharp/NN/Normalization/InstanceNorm.cs create mode 100644 src/TorchSharp/NN/Normalization/NormBase.cs diff --git a/src/Native/LibTorchSharp/THSNN.h b/src/Native/LibTorchSharp/THSNN.h index 51ca417f1..967b164e9 100644 --- a/src/Native/LibTorchSharp/THSNN.h +++ b/src/Native/LibTorchSharp/THSNN.h @@ -81,98 +81,6 @@ EXPORT_API(void) THSNN_ConvTranspose3d_set_bias(const NNModule module, const // Normalization -EXPORT_API(NNModule) THSNN_BatchNorm1d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_BatchNorm1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_BatchNorm2d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_BatchNorm2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_BatchNorm3d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_BatchNorm3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(Tensor) THSNN_BatchNorm1d_bias(const NNModule module); -EXPORT_API(void) THSNN_BatchNorm1d_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_BatchNorm1d_weight(const NNModule module); -EXPORT_API(void) THSNN_BatchNorm1d_set_weight(const NNModule module, const Tensor weight); - -EXPORT_API(Tensor) THSNN_BatchNorm2d_bias(const NNModule module); -EXPORT_API(void) THSNN_BatchNorm2d_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_BatchNorm2d_weight(const NNModule module); -EXPORT_API(void) THSNN_BatchNorm2d_set_weight(const NNModule module, const Tensor weight); - -EXPORT_API(Tensor) THSNN_BatchNorm3d_bias(const NNModule module); -EXPORT_API(void) THSNN_BatchNorm3d_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_BatchNorm3d_weight(const NNModule module); -EXPORT_API(void) THSNN_BatchNorm3d_set_weight(const NNModule module, const Tensor weight); - -EXPORT_API(void) THSNN_BatchNorm1d_reset_stats(const NNModule module); -EXPORT_API(void) THSNN_BatchNorm2d_reset_stats(const NNModule module); -EXPORT_API(void) THSNN_BatchNorm3d_reset_stats(const NNModule module); - -EXPORT_API(Tensor) THSNN_BatchNorm1d_get_mean(const NNModule module); -EXPORT_API(Tensor) THSNN_BatchNorm2d_get_mean(const NNModule module); -EXPORT_API(Tensor) THSNN_BatchNorm3d_get_mean(const NNModule module); - -EXPORT_API(void) THSNN_BatchNorm1d_set_mean(const NNModule module, const Tensor weight); -EXPORT_API(void) THSNN_BatchNorm2d_set_mean(const NNModule module, const Tensor weight); -EXPORT_API(void) THSNN_BatchNorm3d_set_mean(const NNModule module, const Tensor weight); - -EXPORT_API(Tensor) THSNN_BatchNorm1d_get_var(const NNModule module); -EXPORT_API(Tensor) THSNN_BatchNorm2d_get_var(const NNModule module); -EXPORT_API(Tensor) THSNN_BatchNorm3d_get_var(const NNModule module); - -EXPORT_API(void) THSNN_BatchNorm1d_set_var(const NNModule module, const Tensor weight); -EXPORT_API(void) THSNN_BatchNorm2d_set_var(const NNModule module, const Tensor weight); -EXPORT_API(void) THSNN_BatchNorm3d_set_var(const NNModule module, const Tensor weight); - -EXPORT_API(Tensor) THSNN_BatchNorm1d_get_batches(const NNModule module); -EXPORT_API(Tensor) THSNN_BatchNorm2d_get_batches(const NNModule module); -EXPORT_API(Tensor) THSNN_BatchNorm3d_get_batches(const NNModule module); - -EXPORT_API(NNModule) THSNN_InstanceNorm1d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_InstanceNorm1d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_InstanceNorm2d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_InstanceNorm2d_forward(const NNModule module, const Tensor tensor); -EXPORT_API(NNModule) THSNN_InstanceNorm3d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule); -EXPORT_API(Tensor) THSNN_InstanceNorm3d_forward(const NNModule module, const Tensor tensor); - -EXPORT_API(Tensor) THSNN_InstanceNorm1d_bias(const NNModule module); -EXPORT_API(void) THSNN_InstanceNorm1d_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_InstanceNorm1d_weight(const NNModule module); -EXPORT_API(void) THSNN_InstanceNorm1d_set_weight(const NNModule module, const Tensor weight); - -EXPORT_API(Tensor) THSNN_InstanceNorm2d_bias(const NNModule module); -EXPORT_API(void) THSNN_InstanceNorm2d_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_InstanceNorm2d_weight(const NNModule module); -EXPORT_API(void) THSNN_InstanceNorm2d_set_weight(const NNModule module, const Tensor weight); - -EXPORT_API(Tensor) THSNN_InstanceNorm3d_bias(const NNModule module); -EXPORT_API(void) THSNN_InstanceNorm3d_set_bias(const NNModule module, const Tensor bias); -EXPORT_API(Tensor) THSNN_InstanceNorm3d_weight(const NNModule module); -EXPORT_API(void) THSNN_InstanceNorm3d_set_weight(const NNModule module, const Tensor weight); - -EXPORT_API(void) THSNN_InstanceNorm1d_reset_stats(const NNModule module); -EXPORT_API(void) THSNN_InstanceNorm2d_reset_stats(const NNModule module); -EXPORT_API(void) THSNN_InstanceNorm3d_reset_stats(const NNModule module); - -EXPORT_API(Tensor) THSNN_InstanceNorm1d_get_mean(const NNModule module); -EXPORT_API(Tensor) THSNN_InstanceNorm2d_get_mean(const NNModule module); -EXPORT_API(Tensor) THSNN_InstanceNorm3d_get_mean(const NNModule module); - -EXPORT_API(void) THSNN_InstanceNorm1d_set_mean(const NNModule module, const Tensor weight); -EXPORT_API(void) THSNN_InstanceNorm2d_set_mean(const NNModule module, const Tensor weight); -EXPORT_API(void) THSNN_InstanceNorm3d_set_mean(const NNModule module, const Tensor weight); - -EXPORT_API(Tensor) THSNN_InstanceNorm1d_get_var(const NNModule module); -EXPORT_API(Tensor) THSNN_InstanceNorm2d_get_var(const NNModule module); -EXPORT_API(Tensor) THSNN_InstanceNorm3d_get_var(const NNModule module); - -EXPORT_API(void) THSNN_InstanceNorm1d_set_var(const NNModule module, const Tensor weight); -EXPORT_API(void) THSNN_InstanceNorm2d_set_var(const NNModule module, const Tensor weight); -EXPORT_API(void) THSNN_InstanceNorm3d_set_var(const NNModule module, const Tensor weight); - -EXPORT_API(Tensor) THSNN_InstanceNorm1d_get_batches(const NNModule module); -EXPORT_API(Tensor) THSNN_InstanceNorm2d_get_batches(const NNModule module); -EXPORT_API(Tensor) THSNN_InstanceNorm3d_get_batches(const NNModule module); - EXPORT_API(Tensor) THSNN_batch_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool training, const double momentum, const double eps); EXPORT_API(Tensor) THSNN_group_norm(const Tensor input, int64_t num_groups, const Tensor weight, const Tensor bias, const double eps); EXPORT_API(Tensor) THSNN_instance_norm(const Tensor input, const Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool use_input_stats, const double momentum, const double eps); diff --git a/src/Native/LibTorchSharp/THSNormalization.cpp b/src/Native/LibTorchSharp/THSNormalization.cpp index dcb461a99..c94db9896 100644 --- a/src/Native/LibTorchSharp/THSNormalization.cpp +++ b/src/Native/LibTorchSharp/THSNormalization.cpp @@ -3,519 +3,15 @@ #include -NNModule THSNN_BatchNorm1d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::BatchNorm1dOptions(features) - .eps(eps) - .momentum(momentum) - .affine(affine) - .track_running_stats(track_running_stats); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_BatchNorm1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_BatchNorm2d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::BatchNorm2dOptions(features) - .eps(eps) - .momentum(momentum) - .affine(affine) - .track_running_stats(track_running_stats); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_BatchNorm2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_BatchNorm3d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::BatchNorm3dOptions(features) - .eps(eps) - .momentum(momentum) - .affine(affine) - .track_running_stats(track_running_stats); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_BatchNorm3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_InstanceNorm1d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::InstanceNorm1dOptions(features) - .eps(eps) - .momentum(momentum) - .affine(affine) - .track_running_stats(track_running_stats); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_InstanceNorm1d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_InstanceNorm2d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::InstanceNorm2dOptions(features) - .eps(eps) - .momentum(momentum) - .affine(affine) - .track_running_stats(track_running_stats); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_InstanceNorm2d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -NNModule THSNN_InstanceNorm3d_ctor(const int64_t features, const double eps, const double momentum, const bool affine, const bool track_running_stats, NNAnyModule* outAsAnyModule) -{ - CATCH_RETURN_NNModule( - auto opts = torch::nn::InstanceNorm3dOptions(features) - .eps(eps) - .momentum(momentum) - .affine(affine) - .track_running_stats(track_running_stats); - - res = create_module(opts, outAsAnyModule); - ); -} - -Tensor THSNN_InstanceNorm3d_forward(const NNModule module, const Tensor tensor) -{ - CATCH_TENSOR((*module)->as()->forward(*tensor)); -} - -void THSNN_BatchNorm1d_reset_stats(const NNModule module) -{ - CATCH((*module)->as()->reset_running_stats();); -} - -Tensor THSNN_BatchNorm1d_get_mean(const NNModule module) -{ - CATCH( - auto m = (*module)->as()->running_mean; - return m.defined() ? ResultTensor(m) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_BatchNorm1d_get_var(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->running_var; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_BatchNorm1d_get_batches(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->num_batches_tracked; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -void THSNN_BatchNorm1d_set_mean(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_mean = *bias; - ); -} - -void THSNN_BatchNorm1d_set_var(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_var = *bias; - ); -} - -Tensor THSNN_BatchNorm1d_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_BatchNorm1d_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_BatchNorm1d_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_BatchNorm1d_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - -void THSNN_BatchNorm2d_reset_stats(const NNModule module) -{ - CATCH((*module)->as()->reset_running_stats();); -} - -Tensor THSNN_BatchNorm2d_get_mean(const NNModule module) -{ - CATCH( - auto m = (*module)->as()->running_mean; - return m.defined() ? ResultTensor(m) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_BatchNorm2d_get_var(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->running_var; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_BatchNorm2d_get_batches(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->num_batches_tracked; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -void THSNN_BatchNorm2d_set_mean(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_mean = *bias; - ); -} - -void THSNN_BatchNorm2d_set_var(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_var = *bias; - ); -} - -Tensor THSNN_BatchNorm2d_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_BatchNorm2d_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_BatchNorm2d_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_BatchNorm2d_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - -void THSNN_BatchNorm3d_reset_stats(const NNModule module) -{ - CATCH((*module)->as()->reset_running_stats();); -} - -Tensor THSNN_BatchNorm3d_get_mean(const NNModule module) -{ - CATCH( - auto m = (*module)->as()->running_mean; - return m.defined() ? ResultTensor(m) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_BatchNorm3d_get_var(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->running_var; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_BatchNorm3d_get_batches(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->num_batches_tracked; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -void THSNN_BatchNorm3d_set_mean(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_mean = *bias; - ); -} - -void THSNN_BatchNorm3d_set_var(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_var = *bias; - ); -} - -Tensor THSNN_BatchNorm3d_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_BatchNorm3d_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_BatchNorm3d_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_BatchNorm3d_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - -void THSNN_InstanceNorm1d_reset_stats(const NNModule module) -{ - CATCH((*module)->as()->reset_running_stats();); -} - -Tensor THSNN_InstanceNorm1d_get_mean(const NNModule module) -{ - CATCH( - auto m = (*module)->as()->running_mean; - return m.defined() ? ResultTensor(m) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_InstanceNorm1d_get_var(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->running_var; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_InstanceNorm1d_get_batches(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->num_batches_tracked; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -void THSNN_InstanceNorm1d_set_mean(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_mean = *bias; - ); -} - -void THSNN_InstanceNorm1d_set_var(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_var = *bias; - ); -} - -Tensor THSNN_InstanceNorm1d_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_InstanceNorm1d_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_InstanceNorm1d_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_InstanceNorm1d_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - -void THSNN_InstanceNorm2d_reset_stats(const NNModule module) -{ - CATCH((*module)->as()->reset_running_stats();); -} - -Tensor THSNN_InstanceNorm2d_get_mean(const NNModule module) -{ - CATCH( - auto m = (*module)->as()->running_mean; - return m.defined() ? ResultTensor(m) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_InstanceNorm2d_get_var(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->running_var; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_InstanceNorm2d_get_batches(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->num_batches_tracked; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -void THSNN_InstanceNorm2d_set_mean(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_mean = *bias; - ); -} - -void THSNN_InstanceNorm2d_set_var(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_var = *bias; - ); -} - -Tensor THSNN_InstanceNorm2d_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_InstanceNorm2d_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_InstanceNorm2d_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_InstanceNorm2d_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - -void THSNN_InstanceNorm3d_reset_stats(const NNModule module) -{ - CATCH((*module)->as()->reset_running_stats();); -} - -Tensor THSNN_InstanceNorm3d_get_mean(const NNModule module) -{ - CATCH( - auto m = (*module)->as()->running_mean; - return m.defined() ? ResultTensor(m) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_InstanceNorm3d_get_var(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->running_var; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -Tensor THSNN_InstanceNorm3d_get_batches(const NNModule module) -{ - CATCH( - auto v = (*module)->as()->num_batches_tracked; - return v.defined() ? ResultTensor(v) : nullptr; - ); - return nullptr; -} - -void THSNN_InstanceNorm3d_set_mean(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_mean = *bias; - ); -} - -void THSNN_InstanceNorm3d_set_var(const NNModule module, const Tensor bias) -{ - CATCH( - (*module)->as()->running_var = *bias; - ); -} - -Tensor THSNN_InstanceNorm3d_bias(const NNModule module) -{ - return get_bias(module); -} - -void THSNN_InstanceNorm3d_set_bias(const NNModule module, const Tensor bias) -{ - set_bias(module, bias); -} - -Tensor THSNN_InstanceNorm3d_weight(const NNModule module) -{ - return get_weight(module); -} - -void THSNN_InstanceNorm3d_set_weight(const NNModule module, const Tensor weight) -{ - set_weight(module, weight); -} - Tensor THSNN_batch_norm(const Tensor input, Tensor running_mean, const Tensor running_var, const Tensor weight, const Tensor bias, const bool training, const double momentum, const double eps) { - auto opts = torch::nn::functional::BatchNormFuncOptions() - .training(training) - .momentum(momentum) - .eps(eps); - if (weight != nullptr) opts.weight(*weight); - if (bias != nullptr) opts.bias(*bias); - CATCH_TENSOR(torch::nn::functional::batch_norm(*input, *running_mean, *running_var, opts)); + c10::optional w, b, rm, rv; + if (weight != nullptr) w.emplace(*weight); + if (bias != nullptr) b.emplace(*bias); + if (running_mean != nullptr) rm.emplace(*running_mean); + if (running_var != nullptr) rv.emplace(*running_var); + + CATCH_TENSOR(torch::batch_norm(*input, w, b, rm, rv, training, momentum, eps, false)); } Tensor THSNN_group_norm(const Tensor input, const int64_t num_groups, const Tensor weight, const Tensor bias, const double eps) diff --git a/src/TorchSharp/NN/Normalization/BatchNorm.cs b/src/TorchSharp/NN/Normalization/BatchNorm.cs new file mode 100644 index 000000000..ceb1ba421 --- /dev/null +++ b/src/TorchSharp/NN/Normalization/BatchNorm.cs @@ -0,0 +1,53 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. +using System; +using static TorchSharp.torch; +using static TorchSharp.torch.nn; +using static TorchSharp.PInvoke.NativeMethods; +#nullable enable +namespace TorchSharp +{ + using System.Globalization; + using System.Transactions; + using Modules; + using TorchSharp.Utils; + using F = TorchSharp.torch.nn.functional; + + namespace Modules + { + public abstract class BatchNorm : NormBase + { + public BatchNorm(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype, + string name) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, name) + { + } + + public override Tensor forward(Tensor input) + { + ValidateInputDimensions(input); + + var exponential_average_factor = this.momentum; + + if (training && track_running_stats) + { + if (num_batches_tracked is not null) + { + num_batches_tracked.add_(1); + exponential_average_factor = momentum == 0 ? (1.0 / (double)num_batches_tracked) : momentum; + } + } + + var bn_training = training ? true : running_mean is not null && running_var is not null; + var pr = !training || track_running_stats; + + return F.batch_norm(input, pr ? running_mean : null, pr ? running_var : null, weight, bias, bn_training, exponential_average_factor, eps); + } + + } + } +} \ No newline at end of file diff --git a/src/TorchSharp/NN/Normalization/BatchNorm1D.cs b/src/TorchSharp/NN/Normalization/BatchNorm1D.cs index a28bb9057..3633f82b8 100644 --- a/src/TorchSharp/NN/Normalization/BatchNorm1D.cs +++ b/src/TorchSharp/NN/Normalization/BatchNorm1D.cs @@ -13,92 +13,22 @@ namespace Modules /// /// This class is used to represent a BatchNorm1D module. /// - public sealed class BatchNorm1d : torch.nn.Module + public sealed class BatchNorm1d : BatchNorm { - internal BatchNorm1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal BatchNorm1d(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, nameof(BatchNorm1d)) { } - public override Tensor forward(Tensor tensor) + protected override void ValidateInputDimensions(Tensor input) { - if (tensor.Dimensions < 2 || tensor.Dimensions > 3) throw new ArgumentException($"Invalid number of dimensions for BatchNorm argument: {tensor.Dimensions}"); - var res = THSNN_BatchNorm1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - public Parameter? bias { - get { - var res = THSNN_BatchNorm1d_bias(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("bias cannot be set to 'null'"); - THSNN_BatchNorm1d_set_bias(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterParameter("bias", value); - } - } - - public Parameter? weight { - get { - var res = THSNN_BatchNorm1d_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("weight cannot be set to 'null'"); - THSNN_BatchNorm1d_set_weight(handle, value is null ? IntPtr.Zero : value.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); - } - } - - public Tensor? running_mean { - get { - var res = THSNN_BatchNorm1d_get_mean(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_mean cannot be set to 'null'"); - THSNN_BatchNorm1d_set_mean(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_mean", value); - } - } - - public Tensor? running_var { - get { - var res = THSNN_BatchNorm1d_get_var(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_var cannot be set to 'null'"); - THSNN_BatchNorm1d_set_var(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_var", value); - } - } - - public Tensor? num_batches_tracked { - get { - var res = THSNN_BatchNorm1d_get_batches(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - } - - public void reset_running_stats() - { - THSNN_BatchNorm1d_reset_stats(handle); - torch.CheckForErrors(); + if (input.ndim != 2 && input.ndim != 3) + throw new ArgumentException($"expected 2D or 3D input, but got {input.ndim}D input."); } } } @@ -110,7 +40,7 @@ public static partial class nn /// /// Applies Batch Normalization over a 2D or 3D input (a mini-batch of 1D inputs with optional additional channel dimension) as described in the paper Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift . /// - /// C from an expected input of size (N,C,L) or LL from input of size (N, L) + /// C from an expected input of size (N,C,L) or LL from input of size (N, L) /// A value added to the denominator for numerical stability. Default: 1e-5 /// The value used for the running_mean and running_var computation. Can be set to None for cumulative moving average (i.e. simple average). Default: 0.1 /// A boolean value that when set to True, this module has learnable affine parameters. Default: true @@ -120,13 +50,9 @@ public static partial class nn /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module /// - public static BatchNorm1d BatchNorm1d(long features, double eps = 1e-05, double momentum = 0.1, bool affine = true, bool track_running_stats = true, Device? device = null, ScalarType? dtype = null) + public static BatchNorm1d BatchNorm1d(long num_features, double eps = 1e-05, double momentum = 0.1, bool affine = true, bool track_running_stats = true, Device? device = null, ScalarType? dtype = null) { - unsafe { - var handle = THSNN_BatchNorm1d_ctor(features, eps, momentum, affine, track_running_stats, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new BatchNorm1d(handle, boxedHandle).MoveModule(device, dtype); - } + return new BatchNorm1d(num_features, eps, momentum, affine, track_running_stats, device, dtype); } } } diff --git a/src/TorchSharp/NN/Normalization/BatchNorm2D.cs b/src/TorchSharp/NN/Normalization/BatchNorm2D.cs index 391b8a6eb..051605f30 100644 --- a/src/TorchSharp/NN/Normalization/BatchNorm2D.cs +++ b/src/TorchSharp/NN/Normalization/BatchNorm2D.cs @@ -13,92 +13,22 @@ namespace Modules /// /// This class is used to represent a BatchNorm2D module. /// - public sealed class BatchNorm2d : torch.nn.Module + public sealed class BatchNorm2d : BatchNorm { - internal BatchNorm2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal BatchNorm2d(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, nameof(BatchNorm1d)) { } - public override Tensor forward(Tensor tensor) + protected override void ValidateInputDimensions(Tensor input) { - if (tensor.Dimensions != 4) throw new ArgumentException($"Invalid number of dimensions for BatchNorm argument: {tensor.Dimensions}"); - var res = THSNN_BatchNorm2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - public Parameter? bias { - get { - var res = THSNN_BatchNorm2d_bias(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("bias cannot be set to 'null'"); - THSNN_BatchNorm2d_set_bias(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterParameter("bias", value); - } - } - - public Parameter? weight { - get { - var res = THSNN_BatchNorm2d_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("weight cannot be set to 'null'"); - THSNN_BatchNorm2d_set_weight(handle, value is null ? IntPtr.Zero : value.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); - } - } - - public Tensor? running_mean { - get { - var res = THSNN_BatchNorm2d_get_mean(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_mean cannot be set to 'null'"); - THSNN_BatchNorm2d_set_mean(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_mean", value); - } - } - - public Tensor? running_var { - get { - var res = THSNN_BatchNorm2d_get_var(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_var cannot be set to 'null'"); - THSNN_BatchNorm2d_set_var(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_var", value); - } - } - - public Tensor? num_batches_tracked { - get { - var res = THSNN_BatchNorm2d_get_batches(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - } - - public void reset_running_stats() - { - THSNN_BatchNorm2d_reset_stats(handle); - torch.CheckForErrors(); + if (input.ndim != 4) + throw new ArgumentException($"expected 4D input, but got {input.ndim}D input."); } } } @@ -110,7 +40,7 @@ public static partial class nn /// /// Applies Batch Normalization over a 4D input (a mini-batch of 2D inputs with additional channel dimension) as described in the paper Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. /// - /// C from an expected input of size (N,C,H,W) + /// C from an expected input of size (N,C,H,W) /// A value added to the denominator for numerical stability. Default: 1e-5 /// The value used for the running_mean and running_var computation. Can be set to None for cumulative moving average (i.e. simple average). Default: 0.1 /// A boolean value that when set to True, this module has learnable affine parameters. Default: true @@ -120,13 +50,9 @@ public static partial class nn /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module /// - public static BatchNorm2d BatchNorm2d(long features, double eps = 1e-05, double momentum = 0.1, bool affine = true, bool track_running_stats = true, Device? device = null, ScalarType? dtype = null) + public static BatchNorm2d BatchNorm2d(long num_features, double eps = 1e-05, double momentum = 0.1, bool affine = true, bool track_running_stats = true, Device? device = null, ScalarType? dtype = null) { - unsafe { - var handle = THSNN_BatchNorm2d_ctor(features, eps, momentum, affine, track_running_stats, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new BatchNorm2d(handle, boxedHandle).MoveModule(device, dtype); - } + return new BatchNorm2d(num_features, eps, momentum, affine, track_running_stats, device, dtype); } } } diff --git a/src/TorchSharp/NN/Normalization/BatchNorm3D.cs b/src/TorchSharp/NN/Normalization/BatchNorm3D.cs index 4af5f9f60..f434073d9 100644 --- a/src/TorchSharp/NN/Normalization/BatchNorm3D.cs +++ b/src/TorchSharp/NN/Normalization/BatchNorm3D.cs @@ -13,92 +13,22 @@ namespace Modules /// /// This class is used to represent a BatchNorm3D module. /// - public sealed class BatchNorm3d : torch.nn.Module + public sealed class BatchNorm3d : BatchNorm { - internal BatchNorm3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal BatchNorm3d(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, nameof(BatchNorm1d)) { } - public override Tensor forward(Tensor tensor) + protected override void ValidateInputDimensions(Tensor input) { - if (tensor.Dimensions != 5) throw new ArgumentException($"Invalid number of dimensions for BatchNorm argument: {tensor.Dimensions}"); - var res = THSNN_BatchNorm3d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - public Parameter? bias { - get { - var res = THSNN_BatchNorm3d_bias(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("bias cannot be set to 'null'"); - THSNN_BatchNorm3d_set_bias(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterParameter("bias", value); - } - } - - public Parameter? weight { - get { - var res = THSNN_BatchNorm3d_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("weight cannot be set to 'null'"); - THSNN_BatchNorm3d_set_weight(handle, value is null ? IntPtr.Zero : value.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); - } - } - - public Tensor? running_mean { - get { - var res = THSNN_BatchNorm3d_get_mean(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_mean cannot be set to 'null'"); - THSNN_BatchNorm3d_set_mean(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_mean", value); - } - } - - public Tensor? running_var { - get { - var res = THSNN_BatchNorm3d_get_var(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_var cannot be set to 'null'"); - THSNN_BatchNorm3d_set_var(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_var", value); - } - } - - public Tensor? num_batches_tracked { - get { - var res = THSNN_BatchNorm3d_get_batches(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - } - - public void reset_running_stats() - { - THSNN_BatchNorm3d_reset_stats(handle); - torch.CheckForErrors(); + if (input.ndim != 5) + throw new ArgumentException($"expected 4D input, but got {input.ndim}D input."); } } } @@ -110,7 +40,7 @@ public static partial class nn /// /// Applies Batch Normalization over a 5D input (a mini-batch of 3D inputs with additional channel dimension) as described in the paper Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. /// - /// C from an expected input of size (N,C,D,H,W) + /// C from an expected input of size (N,C,D,H,W) /// A value added to the denominator for numerical stability. Default: 1e-5 /// The value used for the running_mean and running_var computation. Can be set to None for cumulative moving average (i.e. simple average). Default: 0.1 /// A boolean value that when set to True, this module has learnable affine parameters. Default: true @@ -120,13 +50,9 @@ public static partial class nn /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module /// - public static BatchNorm3d BatchNorm3d(long features, double eps = 1e-05, double momentum = 0.1, bool affine = true, bool track_running_stats = true, Device? device = null, ScalarType? dtype = null) + public static BatchNorm3d BatchNorm3d(long num_features, double eps = 1e-05, double momentum = 0.1, bool affine = true, bool track_running_stats = true, Device? device = null, ScalarType? dtype = null) { - unsafe { - var handle = THSNN_BatchNorm3d_ctor(features, eps, momentum, affine, track_running_stats, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new BatchNorm3d(handle, boxedHandle).MoveModule(device, dtype); - } + return new BatchNorm3d(num_features, eps, momentum, affine, track_running_stats, device, dtype); } } } diff --git a/src/TorchSharp/NN/Normalization/Functional.cs b/src/TorchSharp/NN/Normalization/Functional.cs index 2c0848279..0fdbf1c54 100644 --- a/src/TorchSharp/NN/Normalization/Functional.cs +++ b/src/TorchSharp/NN/Normalization/Functional.cs @@ -17,8 +17,8 @@ public static Tensor batch_norm(Tensor input, Tensor running_mean, Tensor runnin { var res = THSNN_batch_norm( input.Handle, - running_mean.Handle, - running_var.Handle, + running_mean is not null ? running_mean.Handle : IntPtr.Zero, + running_var is not null ? running_var.Handle : IntPtr.Zero, weight is not null ? weight.Handle : IntPtr.Zero, bias is not null ? bias.Handle : IntPtr.Zero, training, diff --git a/src/TorchSharp/NN/Normalization/InstanceNorm.cs b/src/TorchSharp/NN/Normalization/InstanceNorm.cs new file mode 100644 index 000000000..02ae400c9 --- /dev/null +++ b/src/TorchSharp/NN/Normalization/InstanceNorm.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. +using System; +using static TorchSharp.torch; +using static TorchSharp.torch.nn; +using static TorchSharp.PInvoke.NativeMethods; +#nullable enable +namespace TorchSharp +{ + using System.Globalization; + using System.Transactions; + using Modules; + using TorchSharp.Utils; + using F = TorchSharp.torch.nn.functional; + + namespace Modules + { + public abstract class InstanceNorm : NormBase + { + public InstanceNorm(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype, + string name) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, name) + { + } + + protected abstract long GetNumberOfBatchDimensions(); + + public override Tensor forward(Tensor input) + { + ValidateInputDimensions(input); + + var feature_dim = (int)(input.ndim - GetNumberOfBatchDimensions()); + + if (input.size((int)feature_dim) != num_features) { + throw new ArgumentException($"expected input's size at dim={feature_dim} to match num_features ({this.num_features}), but got: {input.size(feature_dim)}."); + } + + if (feature_dim == 0) { + using var t0 = input.unsqueeze(0); + return ApplyInstanceNorm(t0).squeeze_(0); + } + else { + return ApplyInstanceNorm(input); + } + } + + private Tensor ApplyInstanceNorm(Tensor input) + { + return F.instance_norm(input, running_mean, running_var, weight, bias, training || !track_running_stats, momentum, eps); + } + } + } +} \ No newline at end of file diff --git a/src/TorchSharp/NN/Normalization/InstanceNorm1d.cs b/src/TorchSharp/NN/Normalization/InstanceNorm1d.cs index f9fb5836c..10040c349 100644 --- a/src/TorchSharp/NN/Normalization/InstanceNorm1d.cs +++ b/src/TorchSharp/NN/Normalization/InstanceNorm1d.cs @@ -14,92 +14,24 @@ namespace Modules /// /// This class is used to represent a InstanceNorm1D module. /// - public sealed class InstanceNorm1d : torch.nn.Module + public sealed class InstanceNorm1d : InstanceNorm { - internal InstanceNorm1d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal InstanceNorm1d(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, nameof(InstanceNorm1d)) { } - public override Tensor forward(Tensor tensor) - { - if (tensor.Dimensions < 2 || tensor.Dimensions > 3) throw new ArgumentException($"Invalid number of dimensions for InstanceNorm argument: {tensor.Dimensions}"); - var res = THSNN_InstanceNorm1d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - public Parameter? bias { - get { - var res = THSNN_InstanceNorm1d_bias(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("bias cannot be set to 'null'"); - THSNN_InstanceNorm1d_set_bias(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterParameter("bias", value); - } - } - - public Parameter? weight { - get { - var res = THSNN_InstanceNorm1d_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("weight cannot be set to 'null'"); - THSNN_InstanceNorm1d_set_weight(handle, value is null ? IntPtr.Zero : value.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); - } - } - - public Tensor? running_mean { - get { - var res = THSNN_InstanceNorm1d_get_mean(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_mean cannot be set to 'null'"); - THSNN_InstanceNorm1d_set_mean(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_mean", value); - } - } - - public Tensor? running_var { - get { - var res = THSNN_InstanceNorm1d_get_var(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_var cannot be set to 'null'"); - THSNN_InstanceNorm1d_set_var(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_var", value); - } - } - - public Tensor? num_batches_tracked { - get { - var res = THSNN_InstanceNorm1d_get_batches(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - } + protected override long GetNumberOfBatchDimensions() => 2; - public void reset_running_stats() + protected override void ValidateInputDimensions(Tensor input) { - THSNN_InstanceNorm1d_reset_stats(handle); - torch.CheckForErrors(); + if (input.ndim != 2 && input.ndim != 3) + throw new ArgumentException($"expected 2D or 3D input, but got {input.ndim}D input."); } } } @@ -111,7 +43,7 @@ public static partial class nn /// /// Applies Instance Normalization over a 3D input (a mini-batch of 1D inputs with optional additional channel dimension) as described in the paper Instance Normalization: The Missing Ingredient for Fast Stylization. /// - /// C from an expected input of size (N,C,L) or LL from input of size (N, L) + /// C from an expected input of size (N,C,L) or LL from input of size (N, L) /// A value added to the denominator for numerical stability. Default: 1e-5 /// The value used for the running_mean and running_var computation. Can be set to None for cumulative moving average (i.e. simple average). Default: 0.1 /// A boolean value that when set to True, this module has learnable affine parameters. Default: true @@ -121,13 +53,9 @@ public static partial class nn /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module /// - public static InstanceNorm1d InstanceNorm1d(long features, double eps = 1e-05, double momentum = 0.1, bool affine = false, bool track_running_stats = false, Device? device = null, ScalarType? dtype = null) + public static InstanceNorm1d InstanceNorm1d(long num_features, double eps = 1e-05, double momentum = 0.1, bool affine = false, bool track_running_stats = false, Device? device = null, ScalarType? dtype = null) { - unsafe { - var handle = THSNN_InstanceNorm1d_ctor(features, eps, momentum, affine, track_running_stats, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new InstanceNorm1d(handle, boxedHandle).MoveModule(device, dtype); - } + return new InstanceNorm1d(num_features, eps, momentum, affine, track_running_stats, device, dtype); } } } diff --git a/src/TorchSharp/NN/Normalization/InstanceNorm2d.cs b/src/TorchSharp/NN/Normalization/InstanceNorm2d.cs index 9a7b35d1d..7e5c6bd78 100644 --- a/src/TorchSharp/NN/Normalization/InstanceNorm2d.cs +++ b/src/TorchSharp/NN/Normalization/InstanceNorm2d.cs @@ -14,92 +14,24 @@ namespace Modules /// /// This class is used to represent a InstanceNorm2D module. /// - public sealed class InstanceNorm2d : torch.nn.Module + public sealed class InstanceNorm2d : InstanceNorm { - internal InstanceNorm2d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal InstanceNorm2d(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, nameof(InstanceNorm1d)) { } - public override Tensor forward(Tensor tensor) - { - if (tensor.Dimensions != 4) throw new ArgumentException($"Invalid number of dimensions for InstanceNorm argument: {tensor.Dimensions}"); - var res = THSNN_InstanceNorm2d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - public Parameter? bias { - get { - var res = THSNN_InstanceNorm2d_bias(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("bias cannot be set to 'null'"); - THSNN_InstanceNorm2d_set_bias(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterParameter("bias", value); - } - } - - public Parameter? weight { - get { - var res = THSNN_InstanceNorm2d_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("weight cannot be set to 'null'"); - THSNN_InstanceNorm2d_set_weight(handle, value is null ? IntPtr.Zero : value.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); - } - } - - public Tensor? running_mean { - get { - var res = THSNN_InstanceNorm2d_get_mean(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_mean cannot be set to 'null'"); - THSNN_InstanceNorm2d_set_mean(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_mean", value); - } - } - - public Tensor? running_var { - get { - var res = THSNN_InstanceNorm2d_get_var(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_var cannot be set to 'null'"); - THSNN_InstanceNorm2d_set_var(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_var", value); - } - } - - public Tensor? num_batches_tracked { - get { - var res = THSNN_InstanceNorm2d_get_batches(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - } + protected override long GetNumberOfBatchDimensions() => 3; - public void reset_running_stats() + protected override void ValidateInputDimensions(Tensor input) { - THSNN_InstanceNorm2d_reset_stats(handle); - torch.CheckForErrors(); + if (input.ndim != 3 && input.ndim != 4) + throw new ArgumentException($"expected 3D or 4D input, but got {input.ndim}D input."); } } } @@ -111,7 +43,7 @@ public static partial class nn /// /// Applies Instance Normalization over a 4D input (a mini-batch of 2D inputs with additional channel dimension) as described in the paper Instance Normalization: The Missing Ingredient for Fast Stylization. /// - /// C from an expected input of size (N,C,H,W) + /// C from an expected input of size (N,C,H,W) /// A value added to the denominator for numerical stability. Default: 1e-5 /// The value used for the running_mean and running_var computation. Can be set to None for cumulative moving average (i.e. simple average). Default: 0.1 /// A boolean value that when set to True, this module has learnable affine parameters. Default: true @@ -121,13 +53,9 @@ public static partial class nn /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module /// - public static InstanceNorm2d InstanceNorm2d(long features, double eps = 1e-05, double momentum = 0.1, bool affine = false, bool track_running_stats = false, Device? device = null, ScalarType? dtype = null) + public static InstanceNorm2d InstanceNorm2d(long num_features, double eps = 1e-05, double momentum = 0.1, bool affine = false, bool track_running_stats = false, Device? device = null, ScalarType? dtype = null) { - unsafe { - var handle = THSNN_InstanceNorm2d_ctor(features, eps, momentum, affine, track_running_stats, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new InstanceNorm2d(handle, boxedHandle).MoveModule(device, dtype); - } + return new InstanceNorm2d(num_features, eps, momentum, affine, track_running_stats, device, dtype); } } } diff --git a/src/TorchSharp/NN/Normalization/InstanceNorm3d.cs b/src/TorchSharp/NN/Normalization/InstanceNorm3d.cs index e74cbc278..99ca44a15 100644 --- a/src/TorchSharp/NN/Normalization/InstanceNorm3d.cs +++ b/src/TorchSharp/NN/Normalization/InstanceNorm3d.cs @@ -14,92 +14,24 @@ namespace Modules /// /// This class is used to represent a InstanceNorm3D module. /// - public sealed class InstanceNorm3d : torch.nn.Module + public sealed class InstanceNorm3d : InstanceNorm { - internal InstanceNorm3d(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + internal InstanceNorm3d(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, nameof(InstanceNorm3d)) { } - public override Tensor forward(Tensor tensor) - { - if (tensor.Dimensions != 5) throw new ArgumentException($"Invalid number of dimensions for InstanceNorm argument: {tensor.Dimensions}"); - var res = THSNN_InstanceNorm3d_forward(handle.DangerousGetHandle(), tensor.Handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return new Tensor(res); - } - - public Parameter? bias { - get { - var res = THSNN_InstanceNorm3d_bias(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("bias cannot be set to 'null'"); - THSNN_InstanceNorm3d_set_bias(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterParameter("bias", value); - } - } - - public Parameter? weight { - get { - var res = THSNN_InstanceNorm3d_weight(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); } - return (res == IntPtr.Zero) ? null : new Parameter(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("weight cannot be set to 'null'"); - THSNN_InstanceNorm3d_set_weight(handle, value is null ? IntPtr.Zero : value.Handle); - torch.CheckForErrors(); - ConditionallyRegisterParameter("weight", value); - } - } - - public Tensor? running_mean { - get { - var res = THSNN_InstanceNorm3d_get_mean(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_mean cannot be set to 'null'"); - THSNN_InstanceNorm3d_set_mean(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_mean", value); - } - } - - public Tensor? running_var { - get { - var res = THSNN_InstanceNorm3d_get_var(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - set { - // Please ignore, for now, that the litorch call thinks you *can* set it to null. - if (value is null) throw new ArgumentNullException("running_var cannot be set to 'null'"); - THSNN_InstanceNorm3d_set_var(handle, (value is null ? IntPtr.Zero : value.Handle)); - torch.CheckForErrors(); - ConditionallyRegisterBuffer("running_var", value); - } - } - - public Tensor? num_batches_tracked { - get { - var res = THSNN_InstanceNorm3d_get_batches(handle); - if (res == IntPtr.Zero) { torch.CheckForErrors(); return null; } - return new Tensor(res); - } - } + protected override long GetNumberOfBatchDimensions() => 4; - public void reset_running_stats() + protected override void ValidateInputDimensions(Tensor input) { - THSNN_InstanceNorm3d_reset_stats(handle); - torch.CheckForErrors(); + if (input.ndim != 4 && input.ndim != 5) + throw new ArgumentException($"expected 4D or 4D input, but got {input.ndim}D input."); } } } @@ -111,7 +43,7 @@ public static partial class nn /// /// Applies Instance Normalization over a 5D input (a mini-batch of 3D inputs with additional channel dimension) as described in the paper Instance Normalization: The Missing Ingredient for Fast Stylization. /// - /// C from an expected input of size (N,C,D,H,W) + /// C from an expected input of size (N,C,D,H,W) /// A value added to the denominator for numerical stability. Default: 1e-5 /// The value used for the running_mean and running_var computation. Can be set to None for cumulative moving average (i.e. simple average). Default: 0.1 /// A boolean value that when set to True, this module has learnable affine parameters. Default: true @@ -121,13 +53,9 @@ public static partial class nn /// The desired device of the parameters and buffers in this module /// The desired floating point or complex dtype of the parameters and buffers in this module /// - public static InstanceNorm3d InstanceNorm3d(long features, double eps = 1e-05, double momentum = 0.1, bool affine = false, bool track_running_stats = false, Device? device = null, ScalarType? dtype = null) + public static InstanceNorm3d InstanceNorm3d(long num_features, double eps = 1e-05, double momentum = 0.1, bool affine = false, bool track_running_stats = false, Device? device = null, ScalarType? dtype = null) { - unsafe { - var handle = THSNN_InstanceNorm3d_ctor(features, eps, momentum, affine, track_running_stats, out var boxedHandle); - if (handle == IntPtr.Zero) { torch.CheckForErrors(); } - return new InstanceNorm3d(handle, boxedHandle).MoveModule(device, dtype); - } + return new InstanceNorm3d(num_features, eps, momentum, affine, track_running_stats, device, dtype); } } } diff --git a/src/TorchSharp/NN/Normalization/NormBase.cs b/src/TorchSharp/NN/Normalization/NormBase.cs new file mode 100644 index 000000000..7750fb533 --- /dev/null +++ b/src/TorchSharp/NN/Normalization/NormBase.cs @@ -0,0 +1,145 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. See LICENSE in the project root for license information. +using System; +using static TorchSharp.torch; +using static TorchSharp.torch.nn; +using static TorchSharp.PInvoke.NativeMethods; +#nullable enable +namespace TorchSharp +{ + using Modules; + using TorchSharp.Utils; + using F = TorchSharp.torch.nn.functional; + + namespace Modules + { + public abstract class NormBase : torch.nn.Module + { + public NormBase(long num_features, + double eps, + double momentum, + bool affine, + bool track_running_stats, + Device? device, + ScalarType? dtype, + string name) : base(name) + { + this.num_features = num_features; + this.eps = eps; + this.momentum = momentum; + this.affine = affine; + this.track_running_stats = track_running_stats; + + if (affine) { + this.weight = Parameter(torch.empty(num_features, dtype, device)); + this.bias = Parameter(torch.empty(num_features, dtype, device)); + } + + if (track_running_stats) { + this.running_mean = torch.zeros(num_features, dtype, device); + this.running_var = torch.ones(num_features, dtype, device); + this.num_batches_tracked = torch.tensor(0L, dtype, device); + } + reset_parameters(); + } + + private void ResetRunningStats() + { + if (track_running_stats){ + init.zeros_(this._running_mean); + init.ones_(this._running_var); + init.zeros_(this._num_batches_tracked); + } + } + + public void reset_parameters() { + ResetRunningStats(); + if (affine) { + init.ones_(this._weight); + init.zeros_(this._bias); + } + } + + protected abstract void ValidateInputDimensions(Tensor input); + + protected override void Dispose(bool disposing) + { + _weight?.Dispose(); + _bias?.Dispose(); + base.Dispose(disposing); + } + + public Parameter? bias { + get => _bias; + set { + _bias?.Dispose(); + _bias = value?.DetachFromDisposeScope() as Parameter; + ConditionallyRegisterParameter(nameof(bias), _bias); + } + } + + public Parameter weight { + get => _weight!; + set { + if (value is null) throw new ArgumentNullException(nameof(weight)); + if (value.Handle != _weight?.Handle) { + _weight?.Dispose(); + _weight = (value.DetachFromDisposeScope() as Parameter)!; + ConditionallyRegisterParameter(nameof(weight), _weight); + } + } + } + + public Tensor? running_mean { + get => _running_mean; + set { + _running_mean?.Dispose(); + _running_mean = value?.DetachFromDisposeScope(); + ConditionallyRegisterBuffer(nameof(running_mean), _running_mean); + } + } + + public Tensor? running_var { + get => _running_var; + set { + _running_var?.Dispose(); + _running_var = value?.DetachFromDisposeScope(); + ConditionallyRegisterBuffer(nameof(running_var), _running_var); + } + } + + public Tensor? num_batches_tracked { + get => _num_batches_tracked; + set { + _num_batches_tracked?.Dispose(); + _num_batches_tracked = value?.DetachFromDisposeScope(); + ConditionallyRegisterBuffer(nameof(num_batches_tracked), _num_batches_tracked); + } + } + + public long num_features { get; private set; } + + public double eps { get; private set; } + + public double momentum { get; private set; } + + public bool affine { get; private set; } + + public bool track_running_stats { get; private set; } + + [ComponentName(Name = nameof(bias))] + private Parameter? _bias; + + [ComponentName(Name = nameof(weight))] + private Parameter? _weight; + + [ComponentName(Name = nameof(running_mean))] + private Tensor? _running_mean; + + [ComponentName(Name = nameof(running_var))] + private Tensor? _running_var; + + [ComponentName(Name = nameof(num_batches_tracked))] + private Tensor? _num_batches_tracked; + } + } +} \ No newline at end of file diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index e86ad15dd..e0a952ef5 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -509,114 +509,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_affine_grid(IntPtr theta, IntPtr size, int size_len, [MarshalAs(UnmanagedType.U1)] bool align_corners); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm3d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm3d_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm3d_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm3d_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm3d_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm3d_reset_stats(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm3d_get_mean(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm3d_get_var(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm3d_get_batches(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm3d_set_mean(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm3d_set_var(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm2d_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm2d_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm2d_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm2d_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm2d_reset_stats(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm2d_get_mean(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm2d_get_var(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm2d_get_batches(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm2d_set_mean(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm2d_set_var(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm2d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm1d_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm1d_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm1d_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm1d_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm1d_reset_stats(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm1d_get_mean(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm1d_get_var(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm1d_get_batches(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm1d_set_mean(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_InstanceNorm1d_set_var(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_InstanceNorm1d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_Conv1d_forward(torch.nn.Module.HType module, IntPtr tensor); @@ -713,42 +605,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_ConvTranspose3d_ctor(long inputChannel, long outputChannel, long kernelSize, long stride, long padding, long outputPadding, long dilation, long paddingMode, long groups, [MarshalAs(UnmanagedType.U1)] bool bias, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm1d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm1d_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm1d_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm1d_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm1d_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm1d_reset_stats(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm1d_get_mean(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm1d_get_var(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm1d_get_batches(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm1d_set_mean(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm1d_set_var(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm1d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_Unflatten_forward(torch.nn.Module.HType module, IntPtr tensor); @@ -788,84 +644,6 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_ConvTranspose2d_ctor(long inputChannel, long outputChannel, long kernelSize, long stride, long padding, long outputPadding, long dilation, long paddingMode, long groups, [MarshalAs(UnmanagedType.U1)] bool bias, out IntPtr pBoxedModule); - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm2d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm2d_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm2d_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm2d_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm2d_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm2d_reset_stats(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm2d_get_mean(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm2d_get_var(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm2d_get_batches(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm2d_set_mean(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm2d_set_var(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm2d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm3d_forward(IntPtr module, IntPtr tensor); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm3d_bias(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm3d_set_bias(torch.nn.Module.HType module, IntPtr bias); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm3d_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm3d_set_weight(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm3d_reset_stats(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm3d_get_mean(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm3d_get_var(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm3d_get_batches(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm3d_set_mean(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_BatchNorm3d_set_var(torch.nn.Module.HType module, IntPtr weight); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_BatchNorm3d_ctor(long features, double eps, double momentum, [MarshalAs(UnmanagedType.U1)] bool affine, [MarshalAs(UnmanagedType.U1)] bool track_running_stats, out IntPtr pBoxedModule); - - [DllImport("LibTorchSharp")] - internal static extern IntPtr THSNN_PReLU_weight(torch.nn.Module.HType module); - - [DllImport("LibTorchSharp")] - internal static extern void THSNN_PReLU_set_weight(torch.nn.Module.HType module, IntPtr tensor); - [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_scaled_dot_product_attention(IntPtr query, IntPtr key, IntPtr value, IntPtr attention_mask, double p, [MarshalAs(UnmanagedType.U1)] bool casual); diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index dee565b1a..b3845c1e9 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -4596,6 +4596,35 @@ public void TestInstanceNorm1D() } } + [Fact] + public void TestInstanceNorm1dWeightAndBias() + { + foreach (var device in TestUtils.AvailableDevices()) { + var ones = torch.ones(new long[] { 16, 3, 28 }, device: device); + + using (var norm = InstanceNorm1d(3, affine:true, track_running_stats: false, device: device)) { + var w = norm.weight; + var b = norm.bias; + + Assert.NotNull(w); + Assert.NotNull(b); + + Assert.Equal(device.type, w.device_type); + Assert.Equal(device.type, b.device_type); + + var pooled = norm.call(ones); + Assert.Equal(device.type, pooled.device_type); + Assert.Equal(ones.shape, pooled.shape); + + Assert.Null(norm.running_mean); + Assert.Null(norm.running_var); + + Assert.Equal(new long[] { 3 }, w.shape); + Assert.Equal(new long[] { 3 }, b.shape); + } + } + } + [Fact] public void TestInstanceNorm2D() { @@ -4610,7 +4639,7 @@ public void TestInstanceNorm2D() Assert.Null(pool.running_mean); Assert.Null(pool.running_var); Assert.Equal(ones.shape, pooled.shape); - Assert.Throws(() => pool.call(torch.ones(new long[] { 16, 2, 2 }, device: device))); + Assert.Throws(() => pool.call(torch.ones(new long[] { 16, 2 }, device: device))); Assert.Throws(() => pool.call(torch.ones(new long[] { 2, 2, 2, 2, 2 }, device: device))); } } @@ -4656,6 +4685,35 @@ public void TestInstanceNorm2D() } } + [Fact] + public void TestInstanceNorm2dWeightAndBias() + { + foreach (var device in TestUtils.AvailableDevices()) { + var ones = torch.ones(new long[] { 16, 3, 28, 28 }, device: device); + + using (var norm = InstanceNorm2d(3, affine:true, track_running_stats: false, device: device)) { + var w = norm.weight; + var b = norm.bias; + + Assert.NotNull(w); + Assert.NotNull(b); + + Assert.Equal(device.type, w.device_type); + Assert.Equal(device.type, b.device_type); + + var pooled = norm.call(ones); + Assert.Equal(device.type, pooled.device_type); + Assert.Equal(ones.shape, pooled.shape); + + Assert.Null(norm.running_mean); + Assert.Null(norm.running_var); + + Assert.Equal(new long[] { 3 }, w.shape); + Assert.Equal(new long[] { 3 }, b.shape); + } + } + } + [Fact] public void TestInstanceNorm3D() { @@ -4670,7 +4728,7 @@ public void TestInstanceNorm3D() Assert.Null(pool.running_mean); Assert.Null(pool.running_var); Assert.Equal(ones.shape, pooled.shape); - Assert.Throws(() => pool.call(torch.ones(new long[] { 16, 2, 2, 2 }, device: device))); + Assert.Throws(() => pool.call(torch.ones(new long[] { 16, 2, 2 }, device: device))); Assert.Throws(() => pool.call(torch.ones(new long[] { 2, 2, 2, 2, 2, 2 }, device: device))); } } @@ -4716,6 +4774,35 @@ public void TestInstanceNorm3D() } } + [Fact] + public void TestInstanceNorm3dWeightAndBias() + { + foreach (var device in TestUtils.AvailableDevices()) { + var ones = torch.ones(new long[] { 16, 3, 28, 28, 28 }, device: device); + + using (var norm = InstanceNorm3d(3, affine:true, track_running_stats: false, device: device)) { + var w = norm.weight; + var b = norm.bias; + + Assert.NotNull(w); + Assert.NotNull(b); + + Assert.Equal(device.type, w.device_type); + Assert.Equal(device.type, b.device_type); + + var pooled = norm.call(ones); + Assert.Equal(device.type, pooled.device_type); + Assert.Equal(ones.shape, pooled.shape); + + Assert.Null(norm.running_mean); + Assert.Null(norm.running_var); + + Assert.Equal(new long[] { 3 }, w.shape); + Assert.Equal(new long[] { 3 }, b.shape); + } + } + } + [Fact] public void TestLayerNorm() { From ed3ecd357dca6ad7ca36563477855de10bc738b7 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 19 Mar 2024 08:36:54 -0700 Subject: [PATCH 43/47] Address PR comments and a unit test failure. --- src/TorchSharp/NN/Activation/Softsign.cs | 2 +- src/TorchSharp/NN/Normalization/BatchNorm.cs | 6 +++--- src/TorchSharp/NN/Normalization/InstanceNorm.cs | 8 ++++---- src/TorchSharp/NN/Normalization/NormBase.cs | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/TorchSharp/NN/Activation/Softsign.cs b/src/TorchSharp/NN/Activation/Softsign.cs index c7386d0b8..9ac20d39a 100644 --- a/src/TorchSharp/NN/Activation/Softsign.cs +++ b/src/TorchSharp/NN/Activation/Softsign.cs @@ -52,7 +52,7 @@ public static Tensor softsign(Tensor x, bool inplace = false) { using var abs = x.abs(); using var y = 1 + abs; - return inplace ? x.div_(y) : x.div(y); + return inplace ? x.div_(y).alias() : x.div(y); } } } diff --git a/src/TorchSharp/NN/Normalization/BatchNorm.cs b/src/TorchSharp/NN/Normalization/BatchNorm.cs index ceb1ba421..398eae63c 100644 --- a/src/TorchSharp/NN/Normalization/BatchNorm.cs +++ b/src/TorchSharp/NN/Normalization/BatchNorm.cs @@ -31,18 +31,18 @@ public override Tensor forward(Tensor input) { ValidateInputDimensions(input); - var exponential_average_factor = this.momentum; + double exponential_average_factor = (this.momentum is null) ? 0.0 : this.momentum.Value; if (training && track_running_stats) { if (num_batches_tracked is not null) { num_batches_tracked.add_(1); - exponential_average_factor = momentum == 0 ? (1.0 / (double)num_batches_tracked) : momentum; + exponential_average_factor = (this.momentum is null) ? (1.0 / (double)num_batches_tracked) : momentum.Value; } } - var bn_training = training ? true : running_mean is not null && running_var is not null; + var bn_training = training ? true : running_mean is null && running_var is null; var pr = !training || track_running_stats; return F.batch_norm(input, pr ? running_mean : null, pr ? running_var : null, weight, bias, bn_training, exponential_average_factor, eps); diff --git a/src/TorchSharp/NN/Normalization/InstanceNorm.cs b/src/TorchSharp/NN/Normalization/InstanceNorm.cs index 02ae400c9..43ecd9023 100644 --- a/src/TorchSharp/NN/Normalization/InstanceNorm.cs +++ b/src/TorchSharp/NN/Normalization/InstanceNorm.cs @@ -18,12 +18,12 @@ public abstract class InstanceNorm : NormBase { public InstanceNorm(long num_features, double eps, - double momentum, + double? momentum, bool affine, - bool track_running_stats, + bool track_running_stats, Device? device, ScalarType? dtype, - string name) : base(num_features, eps, momentum, affine, track_running_stats, device, dtype, name) + string name) : base(num_features, eps, momentum.HasValue ? momentum : 0.1, affine, track_running_stats, device, dtype, name) { } @@ -50,7 +50,7 @@ public override Tensor forward(Tensor input) private Tensor ApplyInstanceNorm(Tensor input) { - return F.instance_norm(input, running_mean, running_var, weight, bias, training || !track_running_stats, momentum, eps); + return F.instance_norm(input, running_mean, running_var, weight, bias, training || !track_running_stats, momentum.HasValue ? momentum.Value : 0.1, eps); } } } diff --git a/src/TorchSharp/NN/Normalization/NormBase.cs b/src/TorchSharp/NN/Normalization/NormBase.cs index 7750fb533..13338b0d5 100644 --- a/src/TorchSharp/NN/Normalization/NormBase.cs +++ b/src/TorchSharp/NN/Normalization/NormBase.cs @@ -16,7 +16,7 @@ public abstract class NormBase : torch.nn.Module { public NormBase(long num_features, double eps, - double momentum, + double? momentum, bool affine, bool track_running_stats, Device? device, @@ -118,9 +118,9 @@ public Tensor? num_batches_tracked { public long num_features { get; private set; } - public double eps { get; private set; } + public double eps { get; set; } - public double momentum { get; private set; } + public double? momentum { get; set; } public bool affine { get; private set; } From b24ef9a020e6363a8822159b317c1e2b151f83f4 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 19 Mar 2024 16:28:49 -0700 Subject: [PATCH 44/47] Fixed unit test error and PRELU implementation. --- src/TorchSharp/NN/Activation/PReLU.cs | 36 +++++++-------------------- test/TorchSharpTest/NN.cs | 12 +++++---- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/src/TorchSharp/NN/Activation/PReLU.cs b/src/TorchSharp/NN/Activation/PReLU.cs index d1cacf7c1..2b48b4a6b 100644 --- a/src/TorchSharp/NN/Activation/PReLU.cs +++ b/src/TorchSharp/NN/Activation/PReLU.cs @@ -16,11 +16,15 @@ namespace Modules /// public sealed class PReLU : torch.nn.Module { - internal PReLU(long num_parameters, double init) : base(nameof(PReLU)) + internal PReLU(long num_parameters, double init, Device? device = null, ScalarType? dtype = null) : base(nameof(PReLU)) { - this._init = init; - // This will also set the weights + this.init = init; this.num_parameters = num_parameters; + + var w = torch.empty(num_parameters, device:device, dtype:dtype); + w.fill_(init); + + this.weight = new Parameter(w); } public override Tensor forward(Tensor tensor) @@ -46,30 +50,11 @@ public Parameter weight { } public long num_parameters { - get => _num_parameters; - private set { - if (value != _num_parameters) - { - this._num_parameters = value; - var w = torch.empty(value); - w.fill_(_init); - this._weight = new Parameter(w); - } - } - + get; private set; } public double init { - get => _init; - private set { - if (value != _init) - { - this._init = value; - var w = torch.empty(_num_parameters); - w.fill_(value); - this._weight = new Parameter(w); - } - } + get; private set; } protected override void Dispose(bool disposing) @@ -79,9 +64,6 @@ protected override void Dispose(bool disposing) } } - private double _init = 0; - private long _num_parameters = 0; - [ComponentName(Name = nameof(weight))] private Parameter? _weight; } diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index b3845c1e9..838148149 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -598,13 +598,15 @@ public void EvaluateGELU() [Fact] public void EvaluatePReLU() { - foreach (var device in TestUtils.AvailableDevices()) { + var rel = PReLU(1, 0.35, torch.CPU); + + Assert.Equal(1, rel.num_parameters); + Assert.Equal(0.35f, rel.weight.item()); + Assert.True(rel.weight.requires_grad); - var rel = PReLU(1, 0.35, device); + foreach (var device in TestUtils.AvailableDevices()) { - Assert.Equal(1, rel.num_parameters); - Assert.Equal(0.35f, rel.weight.item()); - Assert.True(rel.weight.requires_grad); + rel = rel.to(device); var input = torch.randn(new long[] { 4, 3, 8, 8 }, device: device) * 5.0; var output = rel.call(input); From 25e128ccb3f0fd1e949bde8bfea86da34f986842 Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Thu, 21 Mar 2024 10:24:05 -0700 Subject: [PATCH 45/47] Added some missing test files to the CUDA test project. --- .../TorchSharpTest.WithCudaBinaries.csproj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/TorchSharpTest.WithCudaBinaries/TorchSharpTest.WithCudaBinaries.csproj b/test/TorchSharpTest.WithCudaBinaries/TorchSharpTest.WithCudaBinaries.csproj index 055fb9ffc..e16e6025e 100644 --- a/test/TorchSharpTest.WithCudaBinaries/TorchSharpTest.WithCudaBinaries.csproj +++ b/test/TorchSharpTest.WithCudaBinaries/TorchSharpTest.WithCudaBinaries.csproj @@ -22,9 +22,11 @@ + Always + @@ -34,15 +36,16 @@ + + - From 254470ebc8ef9d79f6d053677ea0e26fdc6322fa Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Fri, 22 Mar 2024 11:56:32 -0700 Subject: [PATCH 46/47] Overrides on ParamLessModule --- src/TorchSharp/NN/ParamLessModule.cs | 60 ++++++++++++++++++++++++++-- test/TorchSharpTest/NN.cs | 32 +++++++++++++++ 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/TorchSharp/NN/ParamLessModule.cs b/src/TorchSharp/NN/ParamLessModule.cs index 9e06897d9..c3824a2ad 100644 --- a/src/TorchSharp/NN/ParamLessModule.cs +++ b/src/TorchSharp/NN/ParamLessModule.cs @@ -9,11 +9,14 @@ namespace TorchSharp namespace Modules { + public interface IParameterLessModule { + + } /// /// Base class for all modules that do not have any tensor parameters or buffers, and /// for which the `_to()` implementation can therefore be simplified. /// - public abstract class ParamLessModule : nn.Module + public abstract class ParamLessModule : nn.Module, IParameterLessModule { protected ParamLessModule(string name) : base(name) { } @@ -26,13 +29,30 @@ protected ParamLessModule(IntPtr handle, IntPtr boxedHandle) : base(handle, boxe protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; protected internal override nn.Module _to(ScalarType dtype) => this; + + public override void register_buffer(string name, Tensor tensor, bool persistent = true) + { + throw new InvalidOperationException($"Cannot register a buffer on a module that is declared 'parameter-less.'"); + } + + public override void register_parameter(string name, Parameter param) + { + throw new InvalidOperationException($"Cannot register a parameter on a module that is declared 'parameter-less.'"); + } + + public override void register_module(string name, nn.Module submodule) + { + if (submodule is not IParameterLessModule) + throw new InvalidOperationException($"Submodules of a parameter-less module must also be parameter-less."); + base.register_module(name, submodule); + } } /// /// Base class for all modules that do not have any tensor parameters or buffers, and /// for which the `_to()` implementation can therefore be simplified. /// - public abstract class ParamLessModule : nn.Module + public abstract class ParamLessModule : nn.Module, IParameterLessModule { protected ParamLessModule(string name) : base(name) { } @@ -45,13 +65,30 @@ protected ParamLessModule(IntPtr handle, IntPtr boxedHandle) : base(handle, boxe protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; protected internal override nn.Module _to(ScalarType dtype) => this; + + public override void register_buffer(string name, Tensor tensor, bool persistent = true) + { + throw new InvalidOperationException($"Cannot register a buffer on a module that is declared 'parameter-less.'"); + } + + public override void register_parameter(string name, Parameter param) + { + throw new InvalidOperationException($"Cannot register a parameter on a module that is declared 'parameter-less.'"); + } + + public override void register_module(string name, nn.Module submodule) + { + if (submodule is not IParameterLessModule) + throw new InvalidOperationException($"Submodules of a parameter-less module must also be parameter-less."); + base.register_module(name, submodule); + } } /// /// Base class for all modules that do not have any tensor parameters or buffers, and /// for which the `_to()` implementation can therefore be simplified. /// - public abstract class ParamLessModule : nn.Module + public abstract class ParamLessModule : nn.Module, IParameterLessModule { protected ParamLessModule(string name) : base(name) { } @@ -64,6 +101,23 @@ protected ParamLessModule(IntPtr handle, IntPtr boxedHandle) : base(handle, boxe protected internal override nn.Module _to(DeviceType deviceType, int deviceIndex = -1) => this; protected internal override nn.Module _to(ScalarType dtype) => this; + + public override void register_buffer(string name, Tensor tensor, bool persistent = true) + { + throw new InvalidOperationException($"Cannot register a buffer on a module that is declared 'parameter-less.'"); + } + + public override void register_parameter(string name, Parameter param) + { + throw new InvalidOperationException($"Cannot register a parameter on a module that is declared 'parameter-less.'"); + } + + public override void register_module(string name, nn.Module submodule) + { + if (submodule is not IParameterLessModule) + throw new InvalidOperationException($"Submodules of a parameter-less module must also be parameter-less."); + base.register_module(name, submodule); + } } } } \ No newline at end of file diff --git a/test/TorchSharpTest/NN.cs b/test/TorchSharpTest/NN.cs index 838148149..4a2738c81 100644 --- a/test/TorchSharpTest/NN.cs +++ b/test/TorchSharpTest/NN.cs @@ -6633,5 +6633,37 @@ public void TestModulePostHooks() lin1.call(input); Assert.Equal(1, counter); } + + [Fact] + public void TestCustomParameterLessModule() + { + var cnp = new CustomNoParameters("test"); + + // Should not throw + cnp.register_module("sub", new CustomNoParameters("test")); + + Assert.True(cnp.named_modules().Count() > 0); + Assert.Equal("sub", cnp.named_modules().First().name); + + Assert.Throws(() => cnp.register_module("test", torch.nn.Linear(10,10, true))); + Assert.Throws(() => cnp.register_buffer("test", torch.rand(10))); + Assert.Throws(() => cnp.register_parameter("test", new Parameter(torch.rand(10)))); + } + + class CustomNoParameters : ParamLessModule + { + public CustomNoParameters(string name) : base(name) + { + } + + public CustomNoParameters(IntPtr handle, IntPtr boxedHandle) : base(handle, boxedHandle) + { + } + + public override Tensor forward(Tensor input) + { + throw new NotImplementedException(); + } + } } } \ No newline at end of file From 72356a4cd68402c3ca87053ec398e819587de0db Mon Sep 17 00:00:00 2001 From: Niklas Gustafsson Date: Tue, 26 Mar 2024 08:33:37 -0700 Subject: [PATCH 47/47] Manual merge --- src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs index 8cfc02e61..57ac023fc 100644 --- a/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs +++ b/src/TorchSharp/PInvoke/LibTorchSharp.THSNN.cs @@ -646,7 +646,10 @@ internal static extern IntPtr THSNN_custom_module( [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_ConvTranspose2d_ctor(long inputChannel, long outputChannel, long kernelSize, long stride, long padding, long outputPadding, long dilation, long paddingMode, long groups, [MarshalAs(UnmanagedType.U1)] bool bias, out IntPtr pBoxedModule); - + + [DllImport("LibTorchSharp")] + internal static extern IntPtr THSNN_ConvTranspose2d_ctor_1(long inputChannel, long outputChannel, long kernelSizeX, long kernelSizeY, long strideX, long strideY, long paddingX, long paddingY, long outputPaddingX, long outputPaddingY, long dilationX, long dilationY, long paddingMode, long groups, [MarshalAs(UnmanagedType.U1)] bool bias, out IntPtr pBoxedModule); + [DllImport("LibTorchSharp")] internal static extern IntPtr THSNN_scaled_dot_product_attention(IntPtr query, IntPtr key, IntPtr value, IntPtr attention_mask, double p, [MarshalAs(UnmanagedType.U1)] bool casual);