提交 51c6ef71 authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Merge pull request #3721 from ballasn/cond2d_interface_update

Cond2d interface update
...@@ -233,7 +233,7 @@ optdb.register('uncanonicalize', gof.EquilibriumDB(), ...@@ -233,7 +233,7 @@ optdb.register('uncanonicalize', gof.EquilibriumDB(),
# misc special cases for speed that are dependent on the device. # misc special cases for speed that are dependent on the device.
optdb.register('specialize_device', gof.EquilibriumDB(), optdb.register('specialize_device', gof.EquilibriumDB(),
48.6, 'fast_run') # must be after gpu stuff at 48.5 48.6, 'fast_compile', 'fast_run') # must be after gpu stuff at 48.5
# especially constant merge # especially constant merge
optdb.register('merge2', gof.MergeOptimizer(), optdb.register('merge2', gof.MergeOptimizer(),
......
...@@ -11,7 +11,7 @@ from theano.gof.type import CDataType, Generic ...@@ -11,7 +11,7 @@ from theano.gof.type import CDataType, Generic
from theano.compile import optdb from theano.compile import optdb
from theano.compile.ops import shape_i from theano.compile.ops import shape_i
from theano.tensor.nnet import SoftmaxGrad from theano.tensor.nnet import SoftmaxGrad
from theano.tensor.nnet.abstract_conv2d import get_conv_output_shape from theano.tensor.nnet.abstract_conv import get_conv_output_shape
from theano.tensor.signal.downsample import ( from theano.tensor.signal.downsample import (
DownsampleFactorMax, MaxPoolGrad, AveragePoolGrad) DownsampleFactorMax, MaxPoolGrad, AveragePoolGrad)
from theano.sandbox.cuda.type import CudaNdarrayType from theano.sandbox.cuda.type import CudaNdarrayType
...@@ -30,7 +30,7 @@ from theano.sandbox.cuda import gpu_seqopt, register_opt ...@@ -30,7 +30,7 @@ from theano.sandbox.cuda import gpu_seqopt, register_opt
from theano.sandbox.cuda.nvcc_compiler import NVCC_compiler from theano.sandbox.cuda.nvcc_compiler import NVCC_compiler
from theano.tensor.nnet.abstract_conv2d import (AbstractConv2d, from theano.tensor.nnet.abstract_conv import (AbstractConv2d,
AbstractConv2d_gradWeights, AbstractConv2d_gradWeights,
AbstractConv2d_gradInputs) AbstractConv2d_gradInputs)
......
...@@ -75,7 +75,7 @@ from theano.tensor import slinalg ...@@ -75,7 +75,7 @@ from theano.tensor import slinalg
from theano.tensor.nnet.Conv3D import Conv3D from theano.tensor.nnet.Conv3D import Conv3D
from theano.tests.breakpoint import PdbBreakpoint from theano.tests.breakpoint import PdbBreakpoint
from theano.tensor.nnet.abstract_conv2d import (BaseAbstractConv2d, from theano.tensor.nnet.abstract_conv import (BaseAbstractConv2d,
AbstractConv2d, AbstractConv2d,
AbstractConv2d_gradWeights, AbstractConv2d_gradWeights,
AbstractConv2d_gradInputs) AbstractConv2d_gradInputs)
......
...@@ -4,7 +4,7 @@ import itertools ...@@ -4,7 +4,7 @@ import itertools
import theano import theano
from theano.tests import unittest_tools as utt from theano.tests import unittest_tools as utt
import theano.tensor.nnet.abstract_conv2d as conv import theano.tensor.nnet.abstract_conv as conv
from theano.sandbox.cuda import float32_shared_constructor as gpu_shared from theano.sandbox.cuda import float32_shared_constructor as gpu_shared
from theano.compile import shared as cpu_shared from theano.compile import shared as cpu_shared
from theano.sandbox.cuda.dnn import dnn_available, dnn_conv, dnn_gradweight, dnn_gradinput from theano.sandbox.cuda.dnn import dnn_available, dnn_conv, dnn_gradweight, dnn_gradinput
...@@ -14,7 +14,6 @@ import theano.sandbox.cuda as cuda ...@@ -14,7 +14,6 @@ import theano.sandbox.cuda as cuda
if not cuda.cuda_available: if not cuda.cuda_available:
raise SkipTest('Optional package cuda disabled') raise SkipTest('Optional package cuda disabled')
if theano.config.mode == 'FAST_COMPILE': if theano.config.mode == 'FAST_COMPILE':
mode_with_gpu = theano.compile.mode.get_mode('FAST_RUN').including('gpu') mode_with_gpu = theano.compile.mode.get_mode('FAST_RUN').including('gpu')
mode_without_gpu = theano.compile.mode.get_mode('FAST_RUN').excluding('gpu') mode_without_gpu = theano.compile.mode.get_mode('FAST_RUN').excluding('gpu')
...@@ -37,7 +36,6 @@ class TestConv2d(unittest.TestCase): ...@@ -37,7 +36,6 @@ class TestConv2d(unittest.TestCase):
self.filter_flip = [True, False] self.filter_flip = [True, False]
def get_output_shape(self, inputs_shape, filters_shape, subsample, border_mode): def get_output_shape(self, inputs_shape, filters_shape, subsample, border_mode):
if border_mode == "valid": if border_mode == "valid":
border_mode = (0, 0) border_mode = (0, 0)
if border_mode == "full": if border_mode == "full":
......
...@@ -12,7 +12,7 @@ from theano.gof.type import CDataType, Generic ...@@ -12,7 +12,7 @@ from theano.gof.type import CDataType, Generic
from theano.compile import optdb from theano.compile import optdb
from theano.compile.ops import shape_i from theano.compile.ops import shape_i
from theano.tensor.nnet import SoftmaxGrad from theano.tensor.nnet import SoftmaxGrad
from theano.tensor.nnet.abstract_conv2d import get_conv_output_shape from theano.tensor.nnet.abstract_conv import get_conv_output_shape
from theano.tensor.signal.downsample import ( from theano.tensor.signal.downsample import (
DownsampleFactorMax, MaxPoolGrad, AveragePoolGrad) DownsampleFactorMax, MaxPoolGrad, AveragePoolGrad)
......
...@@ -22,7 +22,7 @@ from .nnet import ( ...@@ -22,7 +22,7 @@ from .nnet import (
prepend_scalar_to_each_row, relu, softmax, softmax_grad, softmax_graph, prepend_scalar_to_each_row, relu, softmax, softmax_grad, softmax_graph,
softmax_op, softmax_simplifier, softmax_with_bias) softmax_op, softmax_simplifier, softmax_with_bias)
from . import opt from . import opt
from .conv import conv2d, ConvOp from .conv import ConvOp
from .Conv3D import * from .Conv3D import *
from .ConvGrad3D import * from .ConvGrad3D import *
from .ConvTransp3D import * from .ConvTransp3D import *
...@@ -30,3 +30,91 @@ from .sigm import (softplus, sigmoid, sigmoid_inplace, ...@@ -30,3 +30,91 @@ from .sigm import (softplus, sigmoid, sigmoid_inplace,
scalar_sigmoid, ultra_fast_sigmoid, scalar_sigmoid, ultra_fast_sigmoid,
hard_sigmoid) hard_sigmoid)
from .bn import batch_normalization from .bn import batch_normalization
import warnings
from .abstract_conv import conv2d as abstract_conv2d
def conv2d(input, filters, input_shape=None, image_shape=None, filter_shape=None,
border_mode='valid', subsample=(1, 1), filter_flip=True,
**kargs):
"""
This function will build the symbolic graph for convolving a mini-batch of a
stack of 2D inputs with a set of 2D filters. The implementation is modelled
after Convolutional Neural Networks (CNN).
:type input: symbolic 4D tensor
:param input: mini-batch of feature map stacks, of shape
(batch size, input channels, input rows, input columns).
See the optional parameter ``input_shape``.
:type filters: symbolic 4D tensor
:param filters: set of filters used in CNN layer of shape
(output channels, input channels, filter rows, filter columns).
See the optional parameter ``filter_shape``.
:type image_shape: None, tuple/list of len 4 of int or Constant variable
:param image_shape Deprecated, use input_shape instead
:type input_shape: None, tuple/list of len 4 of int or Constant variable
:param input_shape: 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.
:type filter_shape: None, tuple/list of len 4 of int or Constant variable
:param filter_shape: 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.
: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 filter_flip: bool
:param filter_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.
:rtype: symbolic 4D tensor
:return: set of feature maps generated by convolutional layer. Tensor is
of shape (batch size, output channels, output rows, output columns)
"""
if len(kargs.keys()) > 0:
warnings.warn(str(kargs.keys()) +
" are now deprecated in "
"`tensor.nnet.abstract_conv.conv2d` interface"
" and will be ignored.")
if image_shape is not None:
warnings.warn("image_shape is no longer supported in "
"`tensor.nnet.abstract_conv.conv2d` interface"
" use input_shape instead.")
if input_shape is None:
input_shape = image_shape
else:
raise ValueError("input_shape and image_shape should not"
" be provided at the same time.")
return abstract_conv2d(input, filters, input_shape, filter_shape,
border_mode, subsample=(1, 1))
""" """
Define abstract conv2d interface Define abstract conv2d interface
""" """
import logging
import logging
import theano import theano
from theano.tensor import as_tensor_variable from theano.tensor import as_tensor_variable
from theano.gof import Apply, Op from theano.gof import Apply, Op
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
_logger = logging.getLogger("theano.tensor.nnet.conv2d") _logger = logging.getLogger("theano.tensor.nnet.conv2d")
...@@ -187,6 +187,7 @@ class BaseAbstractConv2d(Op): ...@@ -187,6 +187,7 @@ class BaseAbstractConv2d(Op):
element is not known at compile time. element is not known at compile time.
kshp is defined w.r.t the forward conv. kshp is defined w.r.t the forward conv.
:type border_mode: str, int or tuple of two int :type border_mode: str, int or tuple of two int
:param border_mode: Either of the following: :param border_mode: Either of the following:
* ``'valid'``: apply filter wherever it completely overlaps with the * ``'valid'``: apply filter wherever it completely overlaps with the
...@@ -219,6 +220,7 @@ class BaseAbstractConv2d(Op): ...@@ -219,6 +220,7 @@ class BaseAbstractConv2d(Op):
imshp=None, kshp=None, imshp=None, kshp=None,
border_mode="valid", subsample=(1, 1), border_mode="valid", subsample=(1, 1),
filter_flip=True): filter_flip=True):
if isinstance(border_mode, int): if isinstance(border_mode, int):
border_mode = (border_mode, border_mode) border_mode = (border_mode, border_mode)
if isinstance(border_mode, tuple): if isinstance(border_mode, tuple):
...@@ -297,6 +299,7 @@ class AbstractConv2d(BaseAbstractConv2d): ...@@ -297,6 +299,7 @@ class AbstractConv2d(BaseAbstractConv2d):
self.border_mode, self.border_mode,
self.subsample, self.subsample,
self.filter_flip)( self.filter_flip)(
bottom, top, weights.shape[-2:]) bottom, top, weights.shape[-2:])
return d_bottom, d_weights return d_bottom, d_weights
......
...@@ -21,7 +21,7 @@ from theano import OpenMPOp ...@@ -21,7 +21,7 @@ from theano import OpenMPOp
from theano.tensor import (as_tensor_variable, blas, get_scalar_constant_value, from theano.tensor import (as_tensor_variable, blas, get_scalar_constant_value,
patternbroadcast, NotScalarConstantError) patternbroadcast, NotScalarConstantError)
from theano.gof import Apply from theano.gof import Apply
from theano.tensor.nnet.abstract_conv2d import (get_conv_output_shape, from theano.tensor.nnet.abstract_conv import (get_conv_output_shape,
get_conv_shape_1axis) get_conv_shape_1axis)
try: try:
......
...@@ -5,7 +5,7 @@ import theano ...@@ -5,7 +5,7 @@ import theano
from theano import Apply from theano import Apply
from theano import gof from theano import gof
from theano.tensor import as_tensor_variable, TensorType from theano.tensor import as_tensor_variable, TensorType
from theano.tensor.nnet.abstract_conv2d import get_conv_output_shape from theano.tensor.nnet.abstract_conv import get_conv_output_shape
from theano.tensor.blas_headers import blas_header_text from theano.tensor.blas_headers import blas_header_text
from theano.tensor.blas import ldflags from theano.tensor.blas import ldflags
......
...@@ -13,7 +13,7 @@ from theano.tensor.nnet.blocksparse import ( ...@@ -13,7 +13,7 @@ from theano.tensor.nnet.blocksparse import (
SparseBlockOuter, SparseBlockOuter,
sparse_block_gemv_inplace, sparse_block_gemv_inplace,
sparse_block_outer_inplace) sparse_block_outer_inplace)
from theano.tensor.nnet.abstract_conv2d import (AbstractConv2d, from theano.tensor.nnet.abstract_conv import (AbstractConv2d,
AbstractConv2d_gradWeights, AbstractConv2d_gradWeights,
AbstractConv2d_gradInputs) AbstractConv2d_gradInputs)
from theano.tensor.opt import register_specialize_device from theano.tensor.opt import register_specialize_device
......
...@@ -450,29 +450,6 @@ class TestConv2D(utt.InferShapeTester): ...@@ -450,29 +450,6 @@ class TestConv2D(utt.InferShapeTester):
print(t2 - t1, end=' ') print(t2 - t1, end=' ')
print() print()
def test_fail(self):
k = theano.shared(numpy.ones((1, 1, 3, 3), dtype='float32'))
im = T.ftensor4()
out = theano.function([im],
T.nnet.conv2d(im, k, image_shape=(1, 1, 10, 10)))
self.assertRaises(ValueError, out, numpy.ones((1, 1, 20, 10),
dtype='float32'))
out = theano.function([im],
T.nnet.conv2d(im, k, filter_shape=(1, 1, 3, 2)))
self.assertRaises(ValueError, out, numpy.ones((1, 1, 10, 10),
dtype='float32'))
out = theano.function([im],
T.nnet.conv2d(im, k, filter_shape=(2, None,
None, None)))
self.assertRaises(ValueError, out, numpy.ones((1, 1, 10, 10),
dtype='float32'))
out = theano.function([im],
T.nnet.conv2d(im, k, image_shape=(1, None,
None, None)))
self.assertRaises(ValueError, out, numpy.ones((2, 1, 10, 10),
dtype='float32'))
def test_infer_shape(self): def test_infer_shape(self):
# Note: infer_shape is incomplete and thus input and filter shapes # Note: infer_shape is incomplete and thus input and filter shapes
# must be provided explicitly # must be provided explicitly
......
...@@ -120,7 +120,7 @@ def test_conv3d(mode=mode_without_gpu, shared=theano.tensor._shared): ...@@ -120,7 +120,7 @@ def test_conv3d(mode=mode_without_gpu, shared=theano.tensor._shared):
signals = numpy.random.rand(Ns, Ts, C, Hs, Ws).astype('float32') signals = numpy.random.rand(Ns, Ts, C, Hs, Ws).astype('float32')
filters = numpy.random.rand(Nf, Tf, C, Hf, Wf).astype('float32') filters = numpy.random.rand(Nf, Tf, C, Hf, Wf).astype('float32')
utt.verify_grad(conv3d, [signals, filters], eps=1e-1) utt.verify_grad(conv3d, [signals, filters], eps=1e-1, mode=mode)
### Additional Test that covers the case of patched implementation for filter with Tf=1 ### Additional Test that covers the case of patched implementation for filter with Tf=1
Ns, Ts, C, Hs, Ws = 3, 10, 3, 32, 32 Ns, Ts, C, Hs, Ws = 3, 10, 3, 32, 32
...@@ -165,4 +165,4 @@ def test_conv3d(mode=mode_without_gpu, shared=theano.tensor._shared): ...@@ -165,4 +165,4 @@ def test_conv3d(mode=mode_without_gpu, shared=theano.tensor._shared):
signals = numpy.random.rand(Ns, Ts, C, Hs, Ws).astype('float32') signals = numpy.random.rand(Ns, Ts, C, Hs, Ws).astype('float32')
filters = numpy.random.rand(Nf, Tf, C, Hf, Wf).astype('float32') filters = numpy.random.rand(Nf, Tf, C, Hf, Wf).astype('float32')
utt.verify_grad(conv3d, [signals, filters], eps=1e-1) utt.verify_grad(conv3d, [signals, filters], eps=1e-1, mode=mode)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论