提交 6b363cb7 authored 作者: Frederic's avatar Frederic

Fix GPU downsample opt with new CPU parameter

上级 9636481a
...@@ -1576,7 +1576,9 @@ import theano.tensor.signal.downsample as downsample ...@@ -1576,7 +1576,9 @@ import theano.tensor.signal.downsample as downsample
@register_opt() @register_opt()
@local_optimizer([downsample.DownsampleFactorMax]) @local_optimizer([downsample.DownsampleFactorMax])
def local_gpu_downsample_factor_max(node): def local_gpu_downsample_factor_max(node):
if isinstance(node.op, downsample.DownsampleFactorMax): if (isinstance(node.op, downsample.DownsampleFactorMax)
and node.op.ds == node.op.st):
assert node.op.__props__ == ('ds', 'ignore_border', 'st')
x, = node.inputs x, = node.inputs
if (x.owner and isinstance(x.owner.op, HostFromGpu)): if (x.owner and isinstance(x.owner.op, HostFromGpu)):
gpu_ds = GpuDownsampleFactorMax(node.op.ds, node.op.ignore_border) gpu_ds = GpuDownsampleFactorMax(node.op.ds, node.op.ignore_border)
...@@ -1586,7 +1588,9 @@ def local_gpu_downsample_factor_max(node): ...@@ -1586,7 +1588,9 @@ def local_gpu_downsample_factor_max(node):
@register_opt() @register_opt()
@local_optimizer([downsample.DownsampleFactorMaxGrad]) @local_optimizer([downsample.DownsampleFactorMaxGrad])
def local_gpu_downsample_factor_max_grad(node): def local_gpu_downsample_factor_max_grad(node):
if isinstance(node.op, downsample.DownsampleFactorMaxGrad): if (isinstance(node.op, downsample.DownsampleFactorMaxGrad) and
node.op.ds == node.op.st):
assert node.op.__props__ == ('ds', 'ignore_border', 'st')
x, z, gz = node.inputs x, z, gz = node.inputs
if (x.owner and isinstance(x.owner.op, HostFromGpu)): if (x.owner and isinstance(x.owner.op, HostFromGpu)):
gpu_ds_grad = GpuDownsampleFactorMaxGrad(node.op.ds, gpu_ds_grad = GpuDownsampleFactorMaxGrad(node.op.ds,
......
...@@ -19,7 +19,7 @@ def max_pool2D(*args, **kwargs): ...@@ -19,7 +19,7 @@ def max_pool2D(*args, **kwargs):
return max_pool_2d(*args, **kwargs) return max_pool_2d(*args, **kwargs)
def max_pool_2d(input, ds, ignore_border=False): def max_pool_2d(input, ds, ignore_border=False, st=None):
""" """
Takes as input a N-D tensor, where N >= 2. It downscales the input image by Takes as input a N-D tensor, where N >= 2. It downscales the input image by
the specified factor, by keeping only the maximum value of non-overlapping the specified factor, by keeping only the maximum value of non-overlapping
...@@ -31,8 +31,15 @@ def max_pool_2d(input, ds, ignore_border=False): ...@@ -31,8 +31,15 @@ def max_pool_2d(input, ds, ignore_border=False):
:type ds: tuple of length 2 :type ds: tuple of length 2
:param ds: factor by which to downscale (vertical ds, horizontal ds). :param ds: factor by which to downscale (vertical ds, horizontal ds).
(2,2) will halve the image in each dimension. (2,2) will halve the image in each dimension.
:param ignore_border: boolean value. When True, (5,5) input with ds=(2,2) :type ignore_border: bool
:param ignore_border: When True, (5,5) input with ds=(2,2)
will generate a (2,2) output. (3,3) otherwise. will generate a (2,2) output. (3,3) otherwise.
:type st: tuple of lenght 2
:param st: stride size, which is the number of shifts
over rows/cols to get the the next pool region.
if st is None, it is considered equal to ds
(no overlap on pooling regions)
""" """
if input.ndim < 2: if input.ndim < 2:
raise NotImplementedError('max_pool_2d requires a dimension >= 2') raise NotImplementedError('max_pool_2d requires a dimension >= 2')
...@@ -51,7 +58,7 @@ def max_pool_2d(input, ds, ignore_border=False): ...@@ -51,7 +58,7 @@ def max_pool_2d(input, ds, ignore_border=False):
input_4D = tensor.reshape(input, new_shape, ndim=4) input_4D = tensor.reshape(input, new_shape, ndim=4)
# downsample mini-batch of images # downsample mini-batch of images
op = DownsampleFactorMax(ds, ignore_border) op = DownsampleFactorMax(ds, ignore_border, st=st)
output = op(input_4D) output = op(input_4D)
# restore to original shape # restore to original shape
...@@ -66,6 +73,7 @@ class DownsampleFactorMax(Op): ...@@ -66,6 +73,7 @@ class DownsampleFactorMax(Op):
regions. regions.
""" """
__props__ = ('ds', 'ignore_border', 'st')
@staticmethod @staticmethod
def out_shape(imgshape, ds, ignore_border=False, st=None): def out_shape(imgshape, ds, ignore_border=False, st=None):
...@@ -143,18 +151,17 @@ class DownsampleFactorMax(Op): ...@@ -143,18 +151,17 @@ class DownsampleFactorMax(Op):
ds indicates the pool region size. ds indicates the pool region size.
:type ds: list or tuple of two ints :type ds: list or tuple of two ints
:param ignore_border: if ds doesn't divide imgshape, do we include
an extra row/col of partial downsampling (False) or
ignore it (True).
:type ignore_border: bool
: param st: stride size, which is the number of shifts : param st: stride size, which is the number of shifts
over rows/cols to get the the next pool region. over rows/cols to get the the next pool region.
if st is None, it is considered equal to ds if st is None, it is considered equal to ds
(no overlap on pooling regions) (no overlap on pooling regions)
: type st: list or tuple of two ints : type st: list or tuple of two ints
:param ignore_border: if ds doesn't divide imgshape, do we include
an extra row/col of partial downsampling (False) or
ignore it (True).
:type ignore_border: bool
TODO: why is poolsize an op parameter here?
""" """
self.ds = tuple(ds) self.ds = tuple(ds)
if not all([isinstance(d, int) for d in ds]): if not all([isinstance(d, int) for d in ds]):
...@@ -166,16 +173,6 @@ class DownsampleFactorMax(Op): ...@@ -166,16 +173,6 @@ class DownsampleFactorMax(Op):
self.st = tuple(st) self.st = tuple(st)
self.ignore_border = ignore_border self.ignore_border = ignore_border
def __eq__(self, other):
return (type(self) == type(other) and
self.ds == other.ds and
self.st == other.st and
self.ignore_border == other.ignore_border)
def __hash__(self):
return hash(type(self)) ^ hash(self.ds) ^ \
hash(self.st) ^ hash(self.ignore_border)
def __str__(self): def __str__(self):
return '%s{%s,%s,%s}' % (self.__class__.__name__, return '%s{%s,%s,%s}' % (self.__class__.__name__,
self.ds, self.st, self.ignore_border) self.ds, self.st, self.ignore_border)
...@@ -321,6 +318,7 @@ class DownsampleFactorMax(Op): ...@@ -321,6 +318,7 @@ class DownsampleFactorMax(Op):
class DownsampleFactorMaxGrad(Op): class DownsampleFactorMaxGrad(Op):
__props__ = ('ds', 'ignore_border', 'st')
def __init__(self, ds, ignore_border, st=None): def __init__(self, ds, ignore_border, st=None):
self.ds = tuple(ds) self.ds = tuple(ds)
...@@ -329,16 +327,6 @@ class DownsampleFactorMaxGrad(Op): ...@@ -329,16 +327,6 @@ class DownsampleFactorMaxGrad(Op):
st = ds st = ds
self.st = tuple(st) self.st = tuple(st)
def __eq__(self, other):
return (type(self) == type(other) and
self.ds == other.ds and
self.st == other.st and
self.ignore_border == other.ignore_border)
def __hash__(self):
return hash(type(self)) ^ hash(self.ds) ^ \
hash(self.st) ^ hash(self.ignore_border)
def __str__(self): def __str__(self):
return '%s{%s,%s,%s}' % (self.__class__.__name__, return '%s{%s,%s,%s}' % (self.__class__.__name__,
self.ds, self.st, self.ignore_border) self.ds, self.st, self.ignore_border)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论