use alloc::format;
use burn::tensor::module::interpolate;
use burn_core as burn;
use burn::config::Config;
use burn::module::{Content, DisplaySettings, Module, ModuleDisplay};
use burn::tensor::Tensor;
use burn::tensor::ops::InterpolateOptions;
use super::InterpolateMode;
#[derive(Config, Debug)]
pub struct Interpolate2dConfig {
#[config(default = "None")]
pub output_size: Option<[usize; 2]>,
#[config(default = "None")]
pub scale_factor: Option<[f32; 2]>,
#[config(default = "InterpolateMode::Nearest")]
pub mode: InterpolateMode,
#[config(default = true)]
pub align_corners: bool,
}
#[derive(Module, Debug)]
#[module(custom_display)]
pub struct Interpolate2d {
pub output_size: Option<[usize; 2]>,
pub scale_factor: Option<[f32; 2]>,
#[module(skip)]
pub mode: InterpolateMode,
pub align_corners: bool,
}
impl Interpolate2dConfig {
pub fn init(self) -> Interpolate2d {
Interpolate2d {
output_size: self.output_size,
scale_factor: self.scale_factor,
mode: self.mode,
align_corners: self.align_corners,
}
}
}
impl Interpolate2d {
pub fn forward(&self, input: Tensor<4>) -> Tensor<4> {
let mut options = InterpolateOptions::new(self.mode.clone().into())
.with_align_corners(self.align_corners);
options.output_size = self.output_size;
options.scale_factor = self.scale_factor;
interpolate(input, options)
}
}
impl ModuleDisplay for Interpolate2d {
fn custom_settings(&self) -> Option<DisplaySettings> {
DisplaySettings::new()
.with_new_line_after_attribute(false)
.optional()
}
fn custom_content(&self, content: Content) -> Option<Content> {
content
.add_debug_attribute("mode", &self.mode)
.add("output_size", &format!("{:?}", self.output_size))
.add("scale_factor", &self.scale_factor)
.optional()
}
}
#[cfg(test)]
mod tests {
use burn::tensor::Distribution;
use super::*;
#[test]
fn test_module() {
let input = Tensor::<4>::random(
[2, 3, 4, 4],
Distribution::Uniform(0.0, 1.0),
&Default::default(),
);
let config = Interpolate2dConfig::new().with_output_size(Some([8, 8]));
let interpolate = config.init();
let output = interpolate.forward(input.clone());
assert_eq!(output.dims(), [2, 3, 8, 8]);
let non_square = Tensor::<4>::random(
[2, 3, 4, 6],
Distribution::Uniform(0.0, 1.0),
&Default::default(),
);
let config = Interpolate2dConfig::new().with_scale_factor(Some([0.5, 2.0]));
let interpolate = config.init();
let output = interpolate.forward(non_square);
assert_eq!(output.dims(), [2, 3, 2, 12]);
let config = Interpolate2dConfig::new()
.with_output_size(Some([6, 6]))
.with_mode(InterpolateMode::Linear);
let interpolate = config.init();
let output = interpolate.forward(input);
assert_eq!(output.dims(), [2, 3, 6, 6]);
}
#[test]
fn display() {
let config = Interpolate2dConfig::new().with_output_size(Some([20, 20]));
let layer = config.init();
assert_eq!(
alloc::format!("{layer}"),
"Interpolate2d {mode: Nearest, output_size: Some([20, 20]), \
scale_factor: None}"
);
}
}