溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Pytorch上下采樣函數(shù)--interpolate

發(fā)布時間:2020-07-08 11:15:28 來源:億速云 閱讀:843 作者:清晨 欄目:開發(fā)技術(shù)

小編給大家分享一下Pytorch上下采樣函數(shù)--interpolate,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

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

def interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None):
  r"""
  根據(jù)給定 size 或 scale_factor,上采樣或下采樣輸入數(shù)據(jù)input.
  
  當前支持 temporal, spatial 和 volumetric 輸入數(shù)據(jù)的上采樣,其shape 分別為:3-D, 4-D 和 5-D.
  輸入數(shù)據(jù)的形式為:mini-batch x channels x [optional depth] x [optional height] x width.

  上采樣算法有:nearest, linear(3D-only), bilinear(4D-only), trilinear(5D-only).
  
  參數(shù):
  - 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”

得到結(jié)果

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

補充知識:pytorch插值函數(shù)interpolate——圖像上采樣-下采樣,scipy插值函數(shù)zoom

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

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函數(shù)進行插值,

但是,如果此時的數(shù)據(jù)是tensor(張量)的時候,使用zoom函數(shù)的時候需要將tensor數(shù)據(jù)轉(zhuǎn)為numpy,將GPU數(shù)據(jù)轉(zhuǎn)換為CPU數(shù)據(jù)等,過程比較繁瑣,可以使用pytorch自帶的函數(shù)進行插值操作,interpolate函數(shù)有幾個參數(shù):size表示輸出大小,scale_factor表示縮放倍數(shù),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)) 

看完了這篇文章,相信你對Pytorch上下采樣函數(shù)--interpolate有了一定的了解,想了解更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI