torch转ONNX:Upsample

torch转ONNX:Upsample#

%cd ../../..
import set_env
from d2py.utils.file import mkdir
temp_dir = ".temp"
mkdir(temp_dir)
/media/pc/data/lxw/ai/tvm-book/doc/tutorials/frontend
import torch
from torch import nn
nn.Upsample?
Init signature:
nn.Upsample(
    size: Union[int, Tuple[int, ...], NoneType] = None,
    scale_factor: Union[float, Tuple[float, ...], NoneType] = None,
    mode: str = 'nearest',
    align_corners: Optional[bool] = None,
    recompute_scale_factor: Optional[bool] = None,
) -> None
Docstring:     
Upsamples a given multi-channel 1D (temporal), 2D (spatial) or 3D (volumetric) data.

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.

The algorithms available for upsampling are nearest neighbor and linear,
bilinear, bicubic and trilinear for 3D, 4D and 5D input Tensor,
respectively.

One can either give a :attr:`scale_factor` or the target output :attr:`size` to
calculate the output size. (You cannot give both, as it is ambiguous)

Args:
    size (int or Tuple[int] or Tuple[int, int] or Tuple[int, int, int], optional):
        output spatial sizes
    scale_factor (float or Tuple[float] or Tuple[float, float] or Tuple[float, float, float], optional):
        multiplier for spatial size. Has to match input size if it is a tuple.
    mode (str, optional): the upsampling algorithm: one of ``'nearest'``,
        ``'linear'``, ``'bilinear'``, ``'bicubic'`` and ``'trilinear'``.
        Default: ``'nearest'``
    align_corners (bool, optional): 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 :attr:`mode` is
        ``'linear'``, ``'bilinear'``, ``'bicubic'``, or ``'trilinear'``.
        Default: ``False``
    recompute_scale_factor (bool, optional): 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.

Shape:
    - Input: :math:`(N, C, W_{in})`, :math:`(N, C, H_{in}, W_{in})` or :math:`(N, C, D_{in}, H_{in}, W_{in})`
    - Output: :math:`(N, C, W_{out})`, :math:`(N, C, H_{out}, W_{out})`
      or :math:`(N, C, D_{out}, H_{out}, W_{out})`, where

.. math::
    D_{out} = \left\lfloor D_{in} \times \text{scale\_factor} \right\rfloor

.. math::
    H_{out} = \left\lfloor H_{in} \times \text{scale\_factor} \right\rfloor

.. math::
    W_{out} = \left\lfloor W_{in} \times \text{scale\_factor} \right\rfloor

.. warning::
    With ``align_corners = True``, the linearly interpolating modes
    (`linear`, `bilinear`, `bicubic`, and `trilinear`) don't proportionally
    align the output and input pixels, and thus the output values can depend
    on the input size. This was the default behavior for these modes up to
    version 0.3.1. Since then, the default behavior is
    ``align_corners = False``. See below for concrete examples on how this
    affects the outputs.

.. note::
    If you want downsampling/general resizing, you should use :func:`~nn.functional.interpolate`.

Examples::

    >>> input = torch.arange(1, 5, dtype=torch.float32).view(1, 1, 2, 2)
    >>> input
    tensor([[[[1., 2.],
              [3., 4.]]]])

    >>> m = nn.Upsample(scale_factor=2, mode='nearest')
    >>> m(input)
    tensor([[[[1., 1., 2., 2.],
              [1., 1., 2., 2.],
              [3., 3., 4., 4.],
              [3., 3., 4., 4.]]]])

    >>> # xdoctest: +IGNORE_WANT("other tests seem to modify printing styles")
    >>> m = nn.Upsample(scale_factor=2, mode='bilinear')  # align_corners=False
    >>> m(input)
    tensor([[[[1.0000, 1.2500, 1.7500, 2.0000],
              [1.5000, 1.7500, 2.2500, 2.5000],
              [2.5000, 2.7500, 3.2500, 3.5000],
              [3.0000, 3.2500, 3.7500, 4.0000]]]])

    >>> m = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
    >>> m(input)
    tensor([[[[1.0000, 1.3333, 1.6667, 2.0000],
              [1.6667, 2.0000, 2.3333, 2.6667],
              [2.3333, 2.6667, 3.0000, 3.3333],
              [3.0000, 3.3333, 3.6667, 4.0000]]]])

    >>> # Try scaling the same data in a larger tensor
    >>> input_3x3 = torch.zeros(3, 3).view(1, 1, 3, 3)
    >>> input_3x3[:, :, :2, :2].copy_(input)
    tensor([[[[1., 2.],
              [3., 4.]]]])
    >>> input_3x3
    tensor([[[[1., 2., 0.],
              [3., 4., 0.],
              [0., 0., 0.]]]])

    >>> # xdoctest: +IGNORE_WANT("seems to fail when other tests are run in the same session")
    >>> m = nn.Upsample(scale_factor=2, mode='bilinear')  # align_corners=False
    >>> # Notice that values in top left corner are the same with the small input (except at boundary)
    >>> m(input_3x3)
    tensor([[[[1.0000, 1.2500, 1.7500, 1.5000, 0.5000, 0.0000],
              [1.5000, 1.7500, 2.2500, 1.8750, 0.6250, 0.0000],
              [2.5000, 2.7500, 3.2500, 2.6250, 0.8750, 0.0000],
              [2.2500, 2.4375, 2.8125, 2.2500, 0.7500, 0.0000],
              [0.7500, 0.8125, 0.9375, 0.7500, 0.2500, 0.0000],
              [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]]]])

    >>> m = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
    >>> # Notice that values in top left corner are now changed
    >>> m(input_3x3)
    tensor([[[[1.0000, 1.4000, 1.8000, 1.6000, 0.8000, 0.0000],
              [1.8000, 2.2000, 2.6000, 2.2400, 1.1200, 0.0000],
              [2.6000, 3.0000, 3.4000, 2.8800, 1.4400, 0.0000],
              [2.4000, 2.7200, 3.0400, 2.5600, 1.2800, 0.0000],
              [1.2000, 1.3600, 1.5200, 1.2800, 0.6400, 0.0000],
              [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]]]])
Init docstring: Initialize internal Module state, shared by both nn.Module and ScriptModule.
File:           /media/pc/data/tmp/cache/conda/envs/xin/lib/python3.12/site-packages/torch/nn/modules/upsampling.py
Type:           type
Subclasses:     UpsamplingNearest2d, UpsamplingBilinear2d

将给定的多通道 1D(时间)、2D(空间)或 3D(体积)数据进行上采样。

输入数据被假定为 minibatch x channels x [可选深度] x [可选高度] x 宽度 的形式。因此,对于空间输入,我们期望 4D 张量;对于体积输入,我们期望 5D 张量。

可用的上采样算法包括最近邻和线性、双线性、三次线性以及针对 3D、4D 和 5D 输入张量的三线性插值。

可以给出 scale_factor(缩放因子)或目标输出大小来计算输出大小。(两者不能同时给出,因为这样会产生歧义)

参数:

  • size (intTuple[int]Tuple[int, int]Tuple[int, int, int], 可选) – 输出空间大小

  • scale_factor (float或 Tuple[float]Tuple[float, float]Tuple[float, float, float], 可选) – 空间大小的乘数。如果是元组,则必须与输入大小匹配。

  • mode (str, 可选) – 上采样算法:'nearest'(最近邻)、'linear'(线性)、'bilinear'(双线性)、'bicubic'(三次)和 'trilinear'(三线性)中的一种。默认值: 'nearest'

  • align_corners (bool, 可选) – 如果为 True,则输入和输出张量的角像素对齐,从而保留这些像素的值。这只在模式为 'linear''bilinear''bicubic''trilinear' 时有效。默认值: False

  • recompute_scale_factor (bool, 可选) – 重新计算用于插值计算的 scale_factor。如果 recompute_scale_factorTrue,则必须传入 scale_factor,并且使用 scale_factor 来计算输出大小。计算出的输出大小将用于推断插值的新比例。请注意,当 scale_factor 为浮点数时,由于舍入和精度问题,它可能与重新计算的 scale_factor 不同。如果 recompute_scale_factorFalse,则直接使用 sizescale_factor 进行插值。

  • 输入:\((N, C, W_{in})\)\((N, C, H_{in}, W_{in})\) 或者 \((N, C, D_{in}, H_{in}, W_{in})\)

  • 输出:\((N, C, W_{out})\)\((N, C, H_{out}, W_{out})\) 或者 \((N, C, D_{out}, H_{out}, W_{out})\)

警告

align_cornersTrue 时,线性插值模式(linearbilinearbicubictrilinear)不会按比例对齐输出和输入像素,因此输出值可能依赖于输入大小。在版本 0.3.1 之前,这些模式的默认行为就是这样的。从那时起,默认行为变为 align_corners = False。具体示例请见下文,了解这如何影响输出。

小技巧

如果你想进行下采样/一般重采样,你应该使用 interpolate() 函数。

from PIL import Image
import numpy as np

im = Image.open("../vta/tests/cat.jpg").resize((128, 72))
im
../../../_images/55517b39e9ea6a231335277d832c4d8b1aa98f552b06ed9da93c863f7273b8fc.png
x = np.array(im, dtype="float32")
x = np.expand_dims(x.transpose((2, 0, 1)), axis=0)
x.shape
(1, 3, 72, 128)
m = nn.Upsample(scale_factor=2, mode='nearest')
y = m(torch.from_numpy(x)).numpy()[0].transpose((1, 2, 0)).astype("uint8")
Image.fromarray(y)
../../../_images/e813c2db9440881e64815124285aa202c297e84cbb2e5814cf96d4a3be34f6c9.png
m = nn.Upsample(scale_factor=2, mode='bilinear')  # align_corners=False
y = m(torch.from_numpy(x)).numpy()[0].transpose((1, 2, 0)).astype("uint8")
Image.fromarray(y)
../../../_images/c24902000917619bb840efc7740427ba510adcf57ceefbf5342b82a11490e371.png
m = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
y = m(torch.from_numpy(x)).numpy()[0].transpose((1, 2, 0)).astype("uint8")
Image.fromarray(y)
../../../_images/cd834e67c8d05691678a3f82a0e24450648e1bb6daeaf313e423fcb018bd2aad.png
import tvm
tvm.topi.shape??
Signature: tvm.topi.shape(array, dtype='int32')
Source:   
def shape(array, dtype="int32"):
    """Get the shape of input array

    Parameters
    ----------
    array : tvm.te.Tensor
        The source tensor.

    dtype : str, optional
        The target data type.

    Returns
    -------
    result : tvm.te.Tensor
        The resulting tensor.
    """
    return cpp.shape(array, dtype)
File:      /media/pc/data/lxw/ai/tvm/python/tvm/topi/transform.py
Type:      function