提交 0e85602f authored 作者: Nicolas Ballas's avatar Nicolas Ballas

Update interface + doc

上级 f815f1e3
......@@ -2726,12 +2726,10 @@ def local_abstractconv_gemm(node):
prod1 = node.op.kshp[0] * node.op.kshp[1]
prod2 = ((node.op.imshp[-2] - node.op.kshp[0] + 1) *
(node.op.imshp[-1] - node.op.kshp[1] + 1))
if ((node.op.bsize is not None) and
(len(node.op.imshp) == 3) and
(node.op.imshp[0] is not None)):
if (None not in node.op.imshp[:1]):
# we also know batchsize and input channels
prod1 *= node.op.bsize
prod2 *= node.op.imshp[0]
prod1 *= node.op.imshp[0]
prod2 *= node.op.imshp[1]
# compare to decide
if prod1 > prod2:
# (we need to wrap the result in as_cuda_ndarray_variable,
......@@ -2784,7 +2782,7 @@ def local_abstractconv_gradinputs_gemm(node):
# which ones take precedence over others.
abstractconv_groupopt = theano.gof.optdb.LocalGroupDB()
abstractconv_groupopt.__name__ = "gpu_abstractconv_opts"
register_specialize_device()(abstractconv_groupopt, 'gpu', 'fast_compile')
register_specialize_device(abstractconv_groupopt, 'gpu', 'fast_compile')
# cuDNN is first, but only registered if cuDNN is available.
conv_groupopt.register('local_abstractconv_dnn', dnn.local_abstractconv_cudnn, 20,
......
......@@ -8,6 +8,12 @@ import theano.tensor.nnet.abstract_conv2d as conv
from theano.sandbox.cuda import float32_shared_constructor as gpu_shared
from theano.compile import shared as cpu_shared
from theano.sandbox.cuda.dnn import dnn_available, dnn_conv, dnn_gradweight, dnn_gradinput
from nose.plugins.skip import SkipTest
import theano.sandbox.cuda as cuda
if not cuda.cuda_available:
raise SkipTest('Optional package cuda disabled')
if theano.config.mode == 'FAST_COMPILE':
mode_with_gpu = theano.compile.mode.get_mode('FAST_RUN').including('gpu')
......@@ -84,7 +90,7 @@ class TestConv2d(unittest.TestCase):
utt.assert_allclose(res_ref, res)
if verify_grad:
utt.verify_grad(conv.AbstractConv2d(border_mode="valid", imshp=imshp, kshp=kshp,
bsize=inputs_shape[0], subsample=subsample),
subsample=subsample),
[inputs_val, filters_val],
mode=mode)
......@@ -180,7 +186,7 @@ class TestConv2d(unittest.TestCase):
def test_dnn_conv(self):
if not dnn_available():
return
raise SkipTest(cuda.dnn.dnn_available.msg)
mode = mode_with_gpu
# provide_shape is not used by the CuDNN impementation
provide_shape = False
......@@ -207,8 +213,10 @@ class TestConv2d(unittest.TestCase):
filters_flip=flip)
def test_cormm_conv(self):
mode = mode_with_gpu.excluding('cudnn')
if not dnn_available():
raise SkipTest(cuda.dnn.dnn_available.msg)
mode = mode_with_gpu.excluding('cudnn')
for (i, f), s, b, flip, provide_shape in itertools.product(
zip(self.inputs_shapes, self.filters_shapes),
self.subsamples,
......@@ -233,8 +241,10 @@ class TestConv2d(unittest.TestCase):
filters_flip=flip)
def test_cpu_conv(self):
mode = mode_without_gpu
if not dnn_available():
raise SkipTest(cuda.dnn.dnn_available.msg)
mode = mode_without_gpu
for (i, f), s, b, flip, provide_shape in itertools.product(
zip(self.inputs_shapes, self.filters_shapes),
self.subsamples,
......
......@@ -26,7 +26,6 @@ def conv2d(inputs,
filters,
inputs_shape=None,
filters_shape=None,
batch_size=None,
border_mode='valid',
subsample=(1, 1),
filters_flip=True):
......@@ -89,7 +88,6 @@ def conv2d(inputs,
conv_op = AbstractConv2d(imshp=inputs_shape,
kshp=filters_shape,
bsize=batch_size,
border_mode=border_mode,
subsample=subsample,
filters_flip=filters_flip)
......@@ -98,13 +96,53 @@ def conv2d(inputs,
class BaseAbstractConv2d(Op):
"""
Base class for ConvInferace
Base class for AbstractConv
Define an abstract convolution op that will be replaced with the appropriate implementation
:type imshp: None, tuple/list of len 4 of int or Constant variable
:param imshp: The shape of the input parameter.
Optional, possibly used to choose an optimal implementation.
You can give ``None`` for any element of the list to specify that this
element is not known at compile time.
imshp is defined w.r.t the forward conv.
:type kshp: None, tuple/list of len 4 of int or Constant variable
:param kshp: The shape of the filters parameter.
Optional, possibly used to choose an optimal implementation.
You can give ``None`` for any element of the list to specify that this
element is not known at compile time.
kshp is defined w.r.t the forward conv.
:type border_mode: str, int or tuple of two int
:param border_mode: Either of the following:
* ``'valid'``: apply filter wherever it completely overlaps with the
input. Generates output of shape: input shape - filter shape + 1
* ``'full'``: apply filter wherever it partly overlaps with the input.
Generates output of shape: input shape + filter shape - 1
* ``'half'``: pad input with a symmetric border of ``filter rows // 2``
rows and ``filter columns // 2`` columns, then perform a valid
convolution. For filters with an odd number of rows and columns, this
leads to the output shape being equal to the input shape.
* ``int``: pad input with a symmetric border of zeros of the given
width, then perform a valid convolution.
* ``(int1, int2)``: pad input with a symmetric border of ``int1`` rows
and ``int2`` columns, then perform a valid convolution.
:type subsample: tuple of len 2
:param subsample: factor by which to subsample the output.
Also called strides elsewhere.
:type filters_flip: bool
:param filters_flip: If ``True``, will flip the filter rows and columns
before sliding them over the input. This operation is normally referred
to as a convolution, and this is the default. If ``False``, the filters
are not flipped and the operation is referred to as a cross-correlation.
"""
check_broadcast = False
__props__ = ('border_mode', 'subsample', 'filters_flip', 'imshp', 'kshp', 'bsize')
__props__ = ('border_mode', 'subsample', 'filters_flip', 'imshp', 'kshp')
def __init__(self,
imshp=None, kshp=None, bsize=None,
imshp=None, kshp=None,
border_mode="valid", subsample=(1, 1),
filters_flip = True):
if isinstance(border_mode, int):
......@@ -121,7 +159,6 @@ class BaseAbstractConv2d(Op):
self.imshp = imshp
self.kshp = kshp
self.bsize = bsize
self.border_mode = border_mode
self.filters_flip = filters_flip
......@@ -146,15 +183,17 @@ class BaseAbstractConv2d(Op):
class AbstractConv2d(BaseAbstractConv2d):
"""
Abstract Op for the forward convolution.
"""
def __init__(self,
imshp=None,
kshp=None,
bsize=None,
border_mode="valid",
subsample=(1, 1),
filters_flip = True):
super(AbstractConv2d, self).__init__(imshp, kshp, bsize,
super(AbstractConv2d, self).__init__(imshp, kshp,
border_mode, subsample, filters_flip)
def make_node(self, img, kern):
......@@ -176,13 +215,11 @@ class AbstractConv2d(BaseAbstractConv2d):
bottom, weights = inp
top, = grads
d_bottom = AbstractConv2d_gradInputs(self.imshp, self.kshp,
self.bsize,
self.border_mode,
self.subsample,
self.filters_flip)(
weights, top, bottom.shape[-2:])
d_weights = AbstractConv2d_gradWeights(self.imshp, self.kshp,
self.bsize,
self.border_mode,
self.subsample,
self.filters_flip)(
......@@ -201,11 +238,10 @@ class AbstractConv2d_gradWeights(BaseAbstractConv2d):
def __init__(self,
imshp=None,
kshp=None,
bsize=None,
border_mode="valid",
subsample=(1, 1),
filters_flip=True):
super(AbstractConv2d_gradWeights, self).__init__(imshp, kshp, bsize,
super(AbstractConv2d_gradWeights, self).__init__(imshp, kshp,
border_mode, subsample, filters_flip)
# Update shape/height_width
......@@ -214,10 +250,6 @@ class AbstractConv2d_gradWeights(BaseAbstractConv2d):
raise TypeError('img must be 4D tensor')
if topgrad.type.ndim != 4:
raise TypeError('topgrad must be 4D tensor')
if self.subsample != (1, 1) or self.border_mode == "half":
if shape is None:
raise ValueError('shape must be given if subsample != (1, 1)'
' or border_mode == "half"')
shape = as_tensor_variable(shape)
broadcastable = [topgrad.broadcastable[1],
......@@ -233,13 +265,11 @@ class AbstractConv2d_gradWeights(BaseAbstractConv2d):
bottom, top = inp[:2]
weights, = grads
d_bottom = AbstractConv2d_gradInputs(self.imshp, self.kshp,
self.bsize,
self.border_mode,
self.subsample,
self.filters_flip)(weights, top, bottom.shape[-2:])
d_top = AbstractConv2d(self.imshp,
self.kshp,
self.bsize,
self.border_mode,
self.subsample,
self.filters_flip)(bottom, weights)
......@@ -262,11 +292,10 @@ class AbstractConv2d_gradInputs(BaseAbstractConv2d):
def __init__(self,
imshp=None,
kshp=None,
bsize=None,
border_mode="valid",
subsample=(1, 1),
filters_flip=True):
super(AbstractConv2d_gradInputs, self).__init__(imshp, kshp, bsize,
super(AbstractConv2d_gradInputs, self).__init__(imshp, kshp,
border_mode, subsample, filters_flip)
# Update shape/height_width
......@@ -275,8 +304,6 @@ class AbstractConv2d_gradInputs(BaseAbstractConv2d):
raise TypeError('kern must be 4D tensor')
if topgrad.type.ndim != 4:
raise TypeError('topgrad must be 4D tensor')
if self.subsample != (1, 1) and shape is None:
raise ValueError('shape must be given if subsample != (1, 1)')
shape = as_tensor_variable(shape)
broadcastable = [topgrad.type.broadcastable[0],
......@@ -292,10 +319,9 @@ class AbstractConv2d_gradInputs(BaseAbstractConv2d):
weights, top = inp[:2]
bottom, = grads
d_weights = AbstractConv2d_gradWeights(self.imshp, self.kshp,
self.bsize,
self.border_mode,
self.subsample)(bottom, top, weights.shape[-2:])
d_top = AbstractConv2d(self.imshp, self.kshp, self.bsize,
d_top = AbstractConv2d(self.imshp, self.kshp,
self.border_mode, self.subsample)(bottom, weights)
d_height_width = (theano.gradient.DisconnectedType()(),)
return (d_weights, d_top) + d_height_width
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论