Pytorch上下采样函数--interpolate用法


Posted in Python onJuly 07, 2020

最近用到了上采样下采样操作,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))

以上这篇Pytorch上下采样函数--interpolate用法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python打印斐波拉契数列实例
Jul 07 Python
Python在Console下显示文本进度条的方法
Feb 14 Python
视觉直观感受若干常用排序算法
Apr 13 Python
Python实现生成随机数据插入mysql数据库的方法
Dec 25 Python
Python使用matplotlib绘制多个图形单独显示的方法示例
Mar 14 Python
程序员写Python时的5个坏习惯,你有几条?
Nov 26 Python
详解Python正则表达式re模块
Mar 19 Python
远程部署工具Fabric详解(支持Python3)
Jul 04 Python
python Pillow图像处理方法汇总
Oct 16 Python
Python内置函数locals和globals对比
Apr 28 Python
如何通过Python3和ssl实现加密通信功能
May 09 Python
python实现马丁策略的实例详解
Jan 15 Python
pytorch随机采样操作SubsetRandomSampler()
Jul 07 #Python
pytorch加载自己的图像数据集实例
Jul 07 #Python
keras实现VGG16 CIFAR10数据集方式
Jul 07 #Python
使用darknet框架的imagenet数据分类预训练操作
Jul 07 #Python
Python调用C语言程序方法解析
Jul 07 #Python
keras实现VGG16方式(预测一张图片)
Jul 07 #Python
通过实例解析Python RPC实现原理及方法
Jul 07 #Python
You might like
php Undefined index和Undefined variable的解决方法
2008/03/27 PHP
elgg 获取文件图标地址的方法
2010/03/20 PHP
一组PHP加密解密函数分享
2014/06/05 PHP
php使用curl代理实现抓取数据的方法
2017/02/03 PHP
PHP的new static和new self的区别与使用
2019/11/27 PHP
jQuery-ui中自动完成实现方法
2010/06/10 Javascript
JS 操作符整理[推荐收藏]
2011/11/15 Javascript
通过Javascript将数据导出到外部Excel文档的函数代码
2012/06/15 Javascript
如何让页面加载完成后执行js
2013/06/26 Javascript
ff下JQuery无法监听input的keyup事件的解决方法
2013/12/12 Javascript
超简单JS二级、多级联动的简单实例
2014/02/18 Javascript
超炫的jquery仿flash导航栏特效
2014/11/11 Javascript
jQuery实现仿百度首页滑动伸缩展开的添加服务效果代码
2015/09/09 Javascript
详解微信小程序 通过控制CSS实现view隐藏与显示
2017/05/24 Javascript
为什么我们要做三份 Webpack 配置文件
2017/09/18 Javascript
详解vue mint-ui源码解析之loadmore组件
2017/10/11 Javascript
浅谈Webpack自动化构建实践指南
2017/12/18 Javascript
angularJs使用ng-repeat遍历后选中某一个的方法
2018/09/30 Javascript
Vue项目中使用WebUploader实现文件上传的方法
2019/07/21 Javascript
webpack 最佳配置指北(推荐)
2020/01/07 Javascript
Vue切换div显示隐藏,多选,单选代码解析
2020/07/14 Javascript
Python的Django框架中的select_related函数对QuerySet 查询的优化
2015/04/01 Python
Anaconda下安装mysql-python的包实例
2018/06/11 Python
让代码变得更易维护的7个Python库
2018/10/09 Python
pycharm重命名文件的方法步骤
2019/07/29 Python
python爬虫调度器用法及实例代码
2020/11/30 Python
html5嵌入内容_动力节点Java学院整理
2017/07/07 HTML / CSS
猫途鹰英国网站:TripAdvisor英国(旅游社区和旅游评论)
2016/08/30 全球购物
英国手机零售商:Carphone Warehouse
2018/06/06 全球购物
财务主管的岗位职责
2013/12/30 职场文书
《地震中的父与子》教学反思
2014/04/10 职场文书
单位员工收入证明样本
2014/10/09 职场文书
打架检讨书范文
2015/01/27 职场文书
利用python Pandas实现批量拆分Excel与合并Excel
2021/05/23 Python
Golang数据类型和相互转换
2022/04/12 Golang
Windows Server 版本 20H2 于 8 月 9 日停止支持,Win10 版本 21H1 将于 12 月结束支
2022/07/23 数码科技