use crate::ml::autograd::node::operation::BackwardStatus;
use crate::ml::autograd::tape::backward::accumulate_value_gradient;
use crate::{Matrix, Result};
use std::collections::HashMap;
pub(in crate::ml::autograd) struct GradNodeAvgPool2d {
pub(in crate::ml::autograd) input: Matrix,
pub(in crate::ml::autograd) kernel_size: usize,
pub(in crate::ml::autograd) stride: usize,
pub(in crate::ml::autograd) padding: usize,
pub(in crate::ml::autograd) output_id: u64,
}
impl GradNodeAvgPool2d {
pub(in crate::ml::autograd) fn backward(
&self,
gradients: &mut HashMap<u64, Matrix>,
) -> Result<BackwardStatus> {
let Self {
input,
output_id,
kernel_size,
stride,
padding,
} = self;
let Some(output_gradient) = gradients.remove(output_id) else {
return Ok(BackwardStatus::Skipped);
};
let input_gradient = crate::ml::matrix::avg_pool_2d_backward(
input,
&output_gradient,
*kernel_size,
*stride,
*padding,
)?;
accumulate_value_gradient(gradients, input.value_id(), input_gradient)?;
Ok(BackwardStatus::Recorded)
}
}
pub(in crate::ml::autograd) struct GradNodeMaxPool2d {
pub(in crate::ml::autograd) input: Matrix,
pub(in crate::ml::autograd) indices: Matrix,
pub(in crate::ml::autograd) kernel_size: usize,
pub(in crate::ml::autograd) stride: usize,
pub(in crate::ml::autograd) padding: usize,
pub(in crate::ml::autograd) output_id: u64,
}
impl GradNodeMaxPool2d {
pub(in crate::ml::autograd) fn backward(
&self,
gradients: &mut HashMap<u64, Matrix>,
) -> Result<BackwardStatus> {
let Self {
input,
indices,
output_id,
kernel_size,
stride,
padding,
} = self;
let Some(output_gradient) = gradients.remove(output_id) else {
return Ok(BackwardStatus::Skipped);
};
let input_gradient = crate::ml::matrix::max_pool_2d_backward(
input,
indices,
&output_gradient,
*kernel_size,
*stride,
*padding,
)?;
accumulate_value_gradient(gradients, input.value_id(), input_gradient)?;
Ok(BackwardStatus::Recorded)
}
}
pub(in crate::ml::autograd) struct GradNodeAdaptiveAvgPool2d {
pub(in crate::ml::autograd) input: Matrix,
pub(in crate::ml::autograd) output_height: usize,
pub(in crate::ml::autograd) output_width: usize,
pub(in crate::ml::autograd) output_id: u64,
}
impl GradNodeAdaptiveAvgPool2d {
pub(in crate::ml::autograd) fn backward(
&self,
gradients: &mut HashMap<u64, Matrix>,
) -> Result<BackwardStatus> {
let Self {
input,
output_id,
output_height,
output_width,
} = self;
let Some(output_gradient) = gradients.remove(output_id) else {
return Ok(BackwardStatus::Skipped);
};
let input_gradient = crate::ml::matrix::adaptive_avg_pool_2d_backward(
input,
&output_gradient,
*output_height,
*output_width,
)?;
accumulate_value_gradient(gradients, input.value_id(), input_gradient)?;
Ok(BackwardStatus::Recorded)
}
}