歡迎您光臨本站 註冊首頁

Pytorch上下采樣函數--interpolate用法

←手機掃碼閱讀     ljg58026 @ 2020-07-08 , reply:0

最近用到了上採樣下采樣操作,pytorch中使用interpolate可以很輕鬆的完成

  def interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None):    r"""    根據給定 size 或 scale_factor,上採樣或下采樣輸入數據input.        當前支持 temporal, spatial 和 volumetric 輸入數據的上採樣,其shape 分別為:3-D, 4-D 和 5-D.    輸入數據的形式為:mini-batch x channels x [optional depth] x [optional height] x width.      上採樣算法有:nearest, linear(3D-only), bilinear(4D-only), trilinear(5D-only).        參數:    - input (Tensor): input tensor    - size (int or Tuple[int] or Tuple[int, int] or Tuple[int, int, int]):輸出的 spatial 尺寸.    - scale_factor (float or Tuple[float]): spatial 尺寸的縮放因子.    - mode (string): 上採樣算法:nearest, linear, bilinear, trilinear, area. 默認為 nearest.    - align_corners (bool, optional): 如果 align_corners=True,則對齊 input 和 output 的角點像素(corner pixels),保持在角點像素的值. 只會對 mode=linear, bilinear 和 trilinear 有作用. 默認是 False.    """    from numbers import Integral    from .modules.utils import _ntuple      def _check_size_scale_factor(dim):      if size is None and scale_factor is None:        raise ValueError('either size or scale_factor should be defined')      if size is not None and scale_factor is not None:        raise ValueError('only one of size or scale_factor should be defined')      if scale_factor is not None and isinstance(scale_factor, tuple)          and len(scale_factor) != dim:        raise ValueError('scale_factor shape must match input shape. '                 'Input is {}D, scale_factor size is {}'.format(dim, len(scale_factor)))      def _output_size(dim):      _check_size_scale_factor(dim)      if size is not None:        return size      scale_factors = _ntuple(dim)(scale_factor)      # math.floor might return float in py2.7      return [int(math.floor(input.size(i + 2) * scale_factors[i])) for i in range(dim)]      if mode in ('nearest', 'area'):      if align_corners is not None:        raise ValueError("align_corners option can only be set with the "                 "interpolating modes: linear | bilinear | trilinear")    else:      if align_corners is None:        warnings.warn("Default upsampling behavior when mode={} is changed "               "to align_corners=False since 0.4.0. Please specify "               "align_corners=True if the old behavior is desired. "               "See the documentation of nn.Upsample for details.".format(mode))        align_corners = False      if input.dim() == 3 and mode == 'nearest':      return torch._C._nn.upsample_nearest1d(input, _output_size(1))    elif input.dim() == 4 and mode == 'nearest':      return torch._C._nn.upsample_nearest2d(input, _output_size(2))    elif input.dim() == 5 and mode == 'nearest':      return torch._C._nn.upsample_nearest3d(input, _output_size(3))    elif input.dim() == 3 and mode == 'area':      return adaptive_avg_pool1d(input, _output_size(1))    elif input.dim() == 4 and mode == 'area':      return adaptive_avg_pool2d(input, _output_size(2))    elif input.dim() == 5 and mode == 'area':      return adaptive_avg_pool3d(input, _output_size(3))    elif input.dim() == 3 and mode == 'linear':      return torch._C._nn.upsample_linear1d(input, _output_size(1), align_corners)    elif input.dim() == 3 and mode == 'bilinear':      raise NotImplementedError("Got 3D input, but bilinear mode needs 4D input")    elif input.dim() == 3 and mode == 'trilinear':      raise NotImplementedError("Got 3D input, but trilinear mode needs 5D input")    elif input.dim() == 4 and mode == 'linear':      raise NotImplementedError("Got 4D input, but linear mode needs 3D input")    elif input.dim() == 4 and mode == 'bilinear':      return torch._C._nn.upsample_bilinear2d(input, _output_size(2), align_corners)    elif input.dim() == 4 and mode == 'trilinear':      raise NotImplementedError("Got 4D input, but trilinear mode needs 5D input")    elif input.dim() == 5 and mode == 'linear':      raise NotImplementedError("Got 5D input, but linear mode needs 3D input")    elif input.dim() == 5 and mode == 'bilinear':      raise NotImplementedError("Got 5D input, but bilinear mode needs 4D input")    elif input.dim() == 5 and mode == 'trilinear':      return torch._C._nn.upsample_trilinear3d(input, _output_size(3), align_corners)    else:      raise NotImplementedError("Input Error: Only 3D, 4D and 5D input Tensors supported"                   " (got {}D) for the modes: nearest | linear | bilinear | trilinear"                   " (got {})".format(input.dim(), mode))

 

舉個例子:

  x = Variable(torch.randn([1, 3, 64, 64]))  y0 = F.interpolate(x, scale_factor=0.5)  y1 = F.interpolate(x, size=[32, 32])    y2 = F.interpolate(x, size=[128, 128], mode="bilinear")    print(y0.shape)  print(y1.shape)  print(y2.shape)

 

這裡注意上採樣的時候mode默認是“nearest”,這裡指定雙線性插值“bilinear”

得到結果

  torch.Size([1, 3, 32, 32])  torch.Size([1, 3, 32, 32])  torch.Size([1, 3, 128, 128])

 

補充知識:pytorch插值函數interpolate――圖像上採樣-下采樣,scipy插值函數zoom

在訓練過程中,需要對圖像數據進行插值,如果此時數據是numpy數據,那麼可以使用scipy中的zoom函數:

from scipy.ndimage.interpolation import zoom

  def zoom(input, zoom, output=None, order=3, mode='constant', cval=0.0,       prefilter=True):    """    Zoom an array.    The array is zoomed using spline interpolation of the requested order.    Parameters    ----------    %(input)s    zoom : float or sequence      The zoom factor along the axes. If a float, `zoom` is the same for each      axis. If a sequence, `zoom` should contain one value for each axis.    %(output)s    order : int, optional      The order of the spline interpolation, default is 3.      The order has to be in the range 0-5.    %(mode)s    %(cval)s    %(prefilter)s    Returns    -------    zoom : ndarray      The zoomed input.    Examples    --------    >>> from scipy import ndimage, misc    >>> import matplotlib.pyplot as plt    >>> fig = plt.figure()    >>> ax1 = fig.add_subplot(121) # left side    >>> ax2 = fig.add_subplot(122) # right side    >>> ascent = misc.ascent()    >>> result = ndimage.zoom(ascent, 3.0)    >>> ax1.imshow(ascent)    >>> ax2.imshow(result)    >>> plt.show()    >>> print(ascent.shape)    (512, 512)    >>> print(result.shape)    (1536, 1536)    """    if order < 0 or order > 5:      raise RuntimeError('spline order not supported')    input = numpy.asarray(input)    if numpy.iscomplexobj(input):      raise TypeError('Complex type not supported')    if input.ndim < 1:      raise RuntimeError('input and output rank must be > 0')    mode = _ni_support._extend_mode_to_code(mode)    if prefilter and order > 1:      filtered = spline_filter(input, order, output=numpy.float64)    else:      filtered = input    zoom = _ni_support._normalize_sequence(zoom, input.ndim)    output_shape = tuple(        [int(round(ii * jj)) for ii, jj in zip(input.shape, zoom)])       output_shape_old = tuple(        [int(ii * jj) for ii, jj in zip(input.shape, zoom)])    if output_shape != output_shape_old:      warnings.warn(          "From scipy 0.13.0, the output shape of zoom() is calculated "          "with round() instead of int() - for these inputs the size of "          "the returned array has changed.", UserWarning)       zoom_div = numpy.array(output_shape, float) - 1    # Zooming to infinite values is unpredictable, so just choose    # zoom factor 1 instead    zoom = numpy.divide(numpy.array(input.shape) - 1, zoom_div,              out=numpy.ones_like(input.shape, dtype=numpy.float64),              where=zoom_div != 0)       output = _ni_support._get_output(output, input,                            shape=output_shape)    zoom = numpy.ascontiguousarray(zoom)    _nd_image.zoom_shift(filtered, zoom, None, output, order, mode, cval)    return output

 

中的zoom函數進行插值,

但是,如果此時的數據是tensor(張量)的時候,使用zoom函數的時候需要將tensor數據轉為numpy,將GPU數據轉換為CPU數據等,過程比較繁瑣,可以使用pytorch自帶的函數進行插值操作,interpolate函數有幾個參數:size表示輸出大小,scale_factor表示縮放倍數,mode表示插值方式,align_corners是bool類型,表示輸入和輸出中心是否對齊:

from torch.nn.functional import interpolate

  def interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None):    r"""Down/up samples the input to either the given :attr:`size` or the given    :attr:`scale_factor`    The algorithm used for interpolation is determined by :attr:`mode`.    Currently temporal, spatial and volumetric sampling are supported, i.e.    expected inputs are 3-D, 4-D or 5-D in shape.    The input dimensions are interpreted in the form:    `mini-batch x channels x [optional depth] x [optional height] x width`.    The modes available for resizing are: `nearest`, `linear` (3D-only),    `bilinear`, `bicubic` (4D-only), `trilinear` (5D-only), `area`    Args:      input (Tensor): the input tensor      size (int or Tuple[int] or Tuple[int, int] or Tuple[int, int, int]):        output spatial size.      scale_factor (float or Tuple[float]): multiplier for spatial size. Has to match input size if it is a tuple.      mode (str): algorithm used for upsampling:        ``'nearest'`` | ``'linear'`` | ``'bilinear'`` | ``'bicubic'`` |        ``'trilinear'`` | ``'area'``. Default: ``'nearest'``      align_corners (bool, optional): Geometrically, we consider the pixels of the        input and output as squares rather than points.        If set to ``True``, the input and output tensors are aligned by the        center points of their corner pixels. If set to ``False``, the input and        output tensors are aligned by the corner points of their corner        pixels, and the interpolation uses edge value padding for out-of-boundary values.        This only has effect when :attr:`mode` is ``'linear'``,        ``'bilinear'``, ``'bicubic'``, or ``'trilinear'``.        Default: ``False``    .. warning::      With ``align_corners = True``, the linearly interpolating modes      (`linear`, `bilinear`, 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 :class:`~torch.nn.Upsample` for concrete examples on how this      affects the outputs.    .. include:: cuda_deterministic_backward.rst    """    from .modules.utils import _ntuple       def _check_size_scale_factor(dim):      if size is None and scale_factor is None:        raise ValueError('either size or scale_factor should be defined')      if size is not None and scale_factor is not None:        raise ValueError('only one of size or scale_factor should be defined')      if scale_factor is not None and isinstance(scale_factor, tuple)          and len(scale_factor) != dim:        raise ValueError('scale_factor shape must match input shape. '                 'Input is {}D, scale_factor size is {}'.format(dim, len(scale_factor)))       def _output_size(dim):      _check_size_scale_factor(dim)      if size is not None:        return size      scale_factors = _ntuple(dim)(scale_factor)      # math.floor might return float in py2.7         # make scale_factor a tensor in tracing so constant doesn't get baked in      if torch._C._get_tracing_state():        return [(torch.floor(input.size(i + 2) * torch.tensor(float(scale_factors[i])))) for i in range(dim)]      else:        return [int(math.floor(int(input.size(i + 2)) * scale_factors[i])) for i in range(dim)]       if mode in ('nearest', 'area'):      if align_corners is not None:        raise ValueError("align_corners option can only be set with the "                 "interpolating modes: linear | bilinear | bicubic | trilinear")    else:      if align_corners is None:        warnings.warn("Default upsampling behavior when mode={} is changed "               "to align_corners=False since 0.4.0. Please specify "               "align_corners=True if the old behavior is desired. "               "See the documentation of nn.Upsample for details.".format(mode))        align_corners = False       if input.dim() == 3 and mode == 'nearest':      return torch._C._nn.upsample_nearest1d(input, _output_size(1))    elif input.dim() == 4 and mode == 'nearest':      return torch._C._nn.upsample_nearest2d(input, _output_size(2))    elif input.dim() == 5 and mode == 'nearest':      return torch._C._nn.upsample_nearest3d(input, _output_size(3))    elif input.dim() == 3 and mode == 'area':      return adaptive_avg_pool1d(input, _output_size(1))    elif input.dim() == 4 and mode == 'area':      return adaptive_avg_pool2d(input, _output_size(2))    elif input.dim() == 5 and mode == 'area':      return adaptive_avg_pool3d(input, _output_size(3))    elif input.dim() == 3 and mode == 'linear':      return torch._C._nn.upsample_linear1d(input, _output_size(1), align_corners)    elif input.dim() == 3 and mode == 'bilinear':      raise NotImplementedError("Got 3D input, but bilinear mode needs 4D input")    elif input.dim() == 3 and mode == 'trilinear':      raise NotImplementedError("Got 3D input, but trilinear mode needs 5D input")    elif input.dim() == 4 and mode == 'linear':      raise NotImplementedError("Got 4D input, but linear mode needs 3D input")    elif input.dim() == 4 and mode == 'bilinear':      return torch._C._nn.upsample_bilinear2d(input, _output_size(2), align_corners)    elif input.dim() == 4 and mode == 'trilinear':      raise NotImplementedError("Got 4D input, but trilinear mode needs 5D input")    elif input.dim() == 5 and mode == 'linear':      raise NotImplementedError("Got 5D input, but linear mode needs 3D input")    elif input.dim() == 5 and mode == 'bilinear':      raise NotImplementedError("Got 5D input, but bilinear mode needs 4D input")    elif input.dim() == 5 and mode == 'trilinear':      return torch._C._nn.upsample_trilinear3d(input, _output_size(3), align_corners)    elif input.dim() == 4 and mode == 'bicubic':      return torch._C._nn.upsample_bicubic2d(input, _output_size(2), align_corners)    else:      raise NotImplementedError("Input Error: Only 3D, 4D and 5D input Tensors supported"                   " (got {}D) for the modes: nearest | linear | bilinear | bicubic | trilinear"                   " (got {})".format(input.dim(), mode))


   


[ljg58026 ] Pytorch上下采樣函數--interpolate用法已經有330次圍觀

http://coctec.com/docs/python/shhow-post-241833.html