[docs]classAdaptiveAvgPool2d(nn.Module):r""" Applies a 2D adaptive average pooling over an input signal composed of several input planes. The output is of size :math:`H \times W`, for any input size. The number of output features is equal to the number of input planes. .. note:: This class is a re-implementation of ``torch.nn.AdaptiveAvgPool2d`` that can be exported to ONNX and serves as a drop-in replacement for torch's version. Args: output_size: the target output size of the image of the form :math:`H \times W`. Can be a tuple ``(H, W)`` or a single ``H`` for a square image :math:`H \times H`. ``H`` and ``W`` can be either a ``int``, or ``None`` which means the size will be the same as that of the input. """# noqa: E501def__init__(self,output_size:int|tuple[int|None,int|None]):"""Create the pool."""super().__init__()self._validate_output_size(output_size)ifisinstance(output_size,int):output_size=(output_size,output_size)self._output_size=output_sizedef_validate_output_size(self,output_size:int|tuple[int|None,int|None])->None:ifnotisinstance(output_size,int|tuple):raiseRuntimeError("error: output_size must be an int or a tuple")ifisinstance(output_size,tuple):iflen(output_size)!=2:raiseRuntimeError(f"error: output_size must have size 2 but received {len(output_size)}")ifany(notisinstance(o,int|None)foroinoutput_size):raiseRuntimeError("error: expected a tuple of int or None")def_get_output_size(self,x:torch.Tensor)->npt.NDArray:x_size=np.array(x.shape[-2:])ifself._output_sizeisNone:returnx_size# At this point, the output size should just be a tupleassertisinstance(self._output_size,tuple)x_size[0]=(self._output_size[0]ifself._output_size[0]isnotNoneelsex_size[0])x_size[1]=(self._output_size[1]ifself._output_size[1]isnotNoneelsex_size[1])returnx_size
[docs]defforward(self,x:torch.Tensor)->torch.Tensor:""" Evaluate the adaptive average pool on the input. Args: x: the input tensor. Returns: The pooled tensor. """output_size=self._get_output_size(x)stride_size=np.floor(np.array(x.shape[-2:])/output_size).astype(np.int32)kernel_size=np.array(x.shape[-2:])-(output_size-1)*stride_size# type: ignore[operator]x=F.avg_pool2d(x,kernel_size=list(kernel_size),stride=list(stride_size))returnx