Pytorch上下采样函数--interpolate⽤法
最近⽤到了上采样下采样操作,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 有作⽤. 默认是 Fal. """
from numbers import Integral
from .modules.utils import _ntuple
def _check_size_scale_factor(dim):
if size is None and scale_factor is None:
rai ValueError('either size or scale_factor should be defined')
if size is not None and scale_factor is not None:
rai 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:
rai 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:
rai ValueError("align_corners option can only be t with the "
"interpolating modes: linear | bilinear | trilinear")
el:
if align_corners is None:
warnings.warn("Default upsampling behavior when mode={} is changed "
"to align_corners=Fal since 0.4.0. Plea specify "
"align_corners=True if the old behavior is desired. "
"See the documentation of nn.Upsample for details.".format(mode))
align_corners = Fal
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':
rai NotImplementedError("Got 3D input, but bilinear mode needs 4D input")
elif input.dim() == 3 and mode == 'trilinear':
rai NotImplementedError("Got 3D input, but trilinear mode needs 5D input")
elif input.dim() == 4 and mode == 'linear':
rai 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':
rai NotImplementedError("Got 4D input, but trilinear mode needs 5D input")
elif input.dim() == 5 and mode == 'linear':
rai NotImplementedError("Got 5D input, but linear mode needs 3D input")
elif input.dim() == 5 and mode == 'bilinear':
rai 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)
el:
rai 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 quence
The zoom factor along the axes. If a float, `zoom` is the same for each
axis. If a quence, `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 = (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:
rai RuntimeError('spline order not supported')
input = numpy.asarray(input)
if numpy.iscomplexobj(input):
rai TypeError('Complex type not supported')
if input.ndim < 1:
rai 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)
el:
filtered = input
zoom = _ni_support._normalize_quence(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 the inputs the size of "
"the returned array has changed.", UrWarning)
zoom_div = numpy.array(output_shape, float) - 1
# Zooming to infinite values is unpredictable, so just choo
# zoom factor 1 instead
zoom = numpy.divide(numpy.array(input.shape) - 1, zoom_div,
s_like(input.shape, dtype=numpy.float64),
where=zoom_div != 0)
output = _ni_support._get_output(output, input,
shape=output_shape)
zoom = numpy.ascontiguousarray(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 类型,表⽰输⼊和输出中⼼是否对齐:
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 ud 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 ud 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 t to ``True``, the input and output tensors are aligned by the
center points of their corner pixels. If t to ``Fal``, the input and
output tensors are aligned by the corner points of their corner
pixels, and the interpolation us edge value padding for out-of-boundary values.
This only has effect when :attr:`mode` is ``'linear'``,
``'bilinear'``, ``'bicubic'``, or ``'trilinear'``.
Default: ``Fal``
.. 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 the modes up to version
0.3.1. Since then, the default behavior is ``align_corners = Fal``.
See :class:`~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:
rai ValueError('either size or scale_factor should be defined')
if size is not None and scale_factor is not None:
rai 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:
rai 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) * sor(float(scale_factors[i])))) for i in range(dim)]
el:
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:
rai ValueError("align_corners option can only be t with the "
"interpolating modes: linear | bilinear | bicubic | trilinear")
el:
if align_corners is None:
warnings.warn("Default upsampling behavior when mode={} is changed "
"to align_corners=Fal since 0.4.0. Plea specify "
"align_corners=True if the old behavior is desired. "
"See the documentation of nn.Upsample for details.".format(mode))
align_corners = Fal
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':
rai NotImplementedError("Got 3D input, but bilinear mode needs 4D input")
elif input.dim() == 3 and mode == 'trilinear':
rai NotImplementedError("Got 3D input, but trilinear mode needs 5D input")
elif input.dim() == 4 and mode == 'linear':
rai 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':
rai NotImplementedError("Got 4D input, but trilinear mode needs 5D input")
elif input.dim() == 5 and mode == 'linear':
rai NotImplementedError("Got 5D input, but linear mode needs 3D input")
elif input.dim() == 5 and mode == 'bilinear':
rai 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)
el:
rai 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⽤法就是⼩编分享给⼤家的全部内容了,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。