提交 6ecfe0fe authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Merge pull request #4116 from ballasn/slowimpl

Add debugmode implementation for abstractconv
...@@ -53,7 +53,7 @@ class TestCorrMMConv2d(test_abstract_conv.BaseTestConv2d): ...@@ -53,7 +53,7 @@ class TestCorrMMConv2d(test_abstract_conv.BaseTestConv2d):
self.shared = gpu_shared self.shared = gpu_shared
self.mode = mode_with_gpu.excluding('cudnn') self.mode = mode_with_gpu.excluding('cudnn')
def test_gpucorrmm_conv(self, i, f, s, b, flip, provide_shape): def tcase(self, i, f, s, b, flip, provide_shape):
mode = self.mode mode = self.mode
o = self.get_output_shape(i, f, s, b) o = self.get_output_shape(i, f, s, b)
self.run_fwd(inputs_shape=i, filters_shape=f, subsample=s, self.run_fwd(inputs_shape=i, filters_shape=f, subsample=s,
......
...@@ -8,6 +8,16 @@ import theano ...@@ -8,6 +8,16 @@ import theano
from theano.tensor import as_tensor_variable, patternbroadcast from theano.tensor import as_tensor_variable, patternbroadcast
from theano.gof import Apply, Op from theano.gof import Apply, Op
from six.moves import xrange
import numpy
try:
from scipy.signal.signaltools import _valfrommode, _bvalfromboundary
from scipy.signal.sigtools import _convolve2d
imported_scipy_signal = True
except ImportError:
imported_scipy_signal = False
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
_logger = logging.getLogger("theano.tensor.nnet.abstract_conv") _logger = logging.getLogger("theano.tensor.nnet.abstract_conv")
...@@ -430,6 +440,32 @@ class BaseAbstractConv2d(Op): ...@@ -430,6 +440,32 @@ class BaseAbstractConv2d(Op):
# This may change in the future. # This may change in the future.
return False return False
def conv2d(self, img, kern, mode="valid"):
"""
Basic slow python implementatation for DebugMode
"""
if not imported_scipy_signal:
raise NotImplementedError(
"AbstractConv perform requires the python package"
" for scipy.signal to be installed.")
if not (mode in ('valid', 'full')):
raise ValueError(
'invalid mode {}, which must be either '
'"valid" or "full"'.format(mode))
out_shape = get_conv_output_shape(img.shape, kern.shape, mode, [1, 1])
out = numpy.zeros(out_shape, dtype=img.dtype)
val = _valfrommode(mode)
bval = _bvalfromboundary('fill')
for b in xrange(img.shape[0]):
for n in xrange(kern.shape[0]):
for im0 in xrange(img.shape[1]):
out[b, n, ...] += _convolve2d(img[b, im0, ...],
kern[n, im0, ...],
1, val, bval, 0)
return out
class AbstractConv2d(BaseAbstractConv2d): class AbstractConv2d(BaseAbstractConv2d):
""" Abstract Op for the forward convolution. """ Abstract Op for the forward convolution.
...@@ -465,10 +501,37 @@ class AbstractConv2d(BaseAbstractConv2d): ...@@ -465,10 +501,37 @@ class AbstractConv2d(BaseAbstractConv2d):
return Apply(self, [img, kern], [output]) return Apply(self, [img, kern], [output])
def perform(self, node, inp, out_): def perform(self, node, inp, out_):
raise NotImplementedError( img, kern = inp
'AbstractConv2d theano optimization failed. ' img = numpy.asarray(img)
'Did you exclude both "conv_dnn" and "conv_gemm" from ' kern = numpy.asarray(kern)
'the optimizer? Is cudnn available and does the GPU support it?') o, = out_
mode = self.border_mode
if not ((isinstance(mode, tuple) and min(mode) >= 0) or
mode in ('valid', 'full', 'half')):
raise ValueError(
'invalid border_mode {}, which must be either '
'"valid", "full", "half", an integer or a pair of'
' integers'.format(mode))
if mode == "full":
mode = (kern.shape[2] - 1, kern.shape[3] - 1)
elif mode == "half":
mode = (kern.shape[2] // 2, kern.shape[3] // 2)
if isinstance(mode, tuple):
pad_h, pad_w = map(int, mode)
mode = "valid"
new_img = numpy.zeros((img.shape[0], img.shape[1],
img.shape[2] + 2 * pad_h,
img.shape[3] + 2 * pad_w), dtype=img.dtype)
new_img[:, :, pad_h:img.shape[2] + pad_h, pad_w:img.shape[3] + pad_w] = img
img = new_img
if not self.filter_flip:
kern = kern[:, :, ::-1, ::-1]
conv_out = self.conv2d(img, kern, mode="valid")
conv_out = conv_out[:, :, ::self.subsample[0], ::self.subsample[1]]
o[0] = node.outputs[0].type.filter(conv_out)
def R_op(self, inputs, eval_points): def R_op(self, inputs, eval_points):
rval = None rval = None
...@@ -564,10 +627,49 @@ class AbstractConv2d_gradWeights(BaseAbstractConv2d): ...@@ -564,10 +627,49 @@ class AbstractConv2d_gradWeights(BaseAbstractConv2d):
return Apply(self, [img, topgrad, shape], [output]) return Apply(self, [img, topgrad, shape], [output])
def perform(self, node, inp, out_): def perform(self, node, inp, out_):
raise NotImplementedError( img, topgrad, shape = inp
'AbstractConv2d_gradWeights theano optimization failed. ' img = numpy.asarray(img)
'Did you exclude both "conv_dnn" and "conv_gemm" from ' topgrad = numpy.asarray(topgrad)
'the optimizer?')
o, = out_
mode = self.border_mode
if not ((isinstance(mode, tuple) and min(mode) >= 0) or
mode in ('valid', 'full', 'half')):
raise ValueError(
'invalid border_mode {}, which must be either '
'"valid", "full", "half", an integer or a pair of'
' integers'.format(mode))
if mode == "full":
mode = (shape[0] - 1, shape[1] - 1)
elif mode == "half":
mode = (shape[0] // 2, shape[1] // 2)
if isinstance(mode, tuple):
pad_h, pad_w = map(int, mode)
mode = "valid"
new_img = numpy.zeros((img.shape[0], img.shape[1],
img.shape[2] + 2 * pad_h,
img.shape[3] + 2 * pad_w), dtype=img.dtype)
new_img[:, :, pad_h:img.shape[2] + pad_h, pad_w:img.shape[3] + pad_w] = img
img = new_img
if self.subsample[0] > 1 or self.subsample[1] > 1:
new_shape = (topgrad.shape[0], topgrad.shape[1],
img.shape[2] - shape[0] + 1,
img.shape[3] - shape[1] + 1)
new_topgrad = numpy.zeros((new_shape), dtype=topgrad.dtype)
new_topgrad[:, :, ::self.subsample[0], ::self.subsample[1]] = topgrad
topgrad = new_topgrad
topgrad = topgrad.transpose(1, 0, 2, 3)[:, :, ::-1, ::-1]
img = img.transpose(1, 0, 2, 3)
kern = self.conv2d(img, topgrad, mode="valid")
if self.filter_flip:
kern = kern.transpose(1, 0, 2, 3)[:, :, ::-1, ::-1]
else:
kern = kern.transpose(1, 0, 2, 3)
o[0] = node.outputs[0].type.filter(kern)
def grad(self, inp, grads): def grad(self, inp, grads):
bottom, top = inp[:2] bottom, top = inp[:2]
...@@ -656,10 +758,42 @@ class AbstractConv2d_gradInputs(BaseAbstractConv2d): ...@@ -656,10 +758,42 @@ class AbstractConv2d_gradInputs(BaseAbstractConv2d):
return Apply(self, [kern, topgrad, shape], [output]) return Apply(self, [kern, topgrad, shape], [output])
def perform(self, node, inp, out_): def perform(self, node, inp, out_):
raise NotImplementedError( kern, topgrad, shape = inp
'AbstractConv2d_gradInputs theano optimization failed. ' kern = numpy.asarray(kern)
'Did you exclude both "conv_dnn" and "conv_gemm" from ' topgrad = numpy.asarray(topgrad)
'the optimizer?') o, = out_
mode = self.border_mode
if not ((isinstance(mode, tuple) and min(mode) >= 0) or
mode in ('valid', 'full', 'half')):
raise ValueError(
'invalid border_mode {}, which must be either '
'"valid", "full", "half", an integer or a pair of'
' integers'.format(mode))
pad_h, pad_w = 0, 0
if mode == "full":
pad_h, pad_w = (kern.shape[2] - 1, kern.shape[3] - 1)
elif mode == "half":
pad_h, pad_w = (kern.shape[2] // 2, kern.shape[3] // 2)
elif isinstance(mode, tuple):
pad_h, pad_w = map(int, self.border_mode)
if self.subsample[0] > 1 or self.subsample[1] > 1:
new_shape = (topgrad.shape[0], topgrad.shape[1],
shape[0] + 2 * pad_h - kern.shape[2] + 1,
shape[1] + 2 * pad_w - kern.shape[3] + 1)
new_topgrad = numpy.zeros((new_shape), dtype=topgrad.dtype)
new_topgrad[:, :, ::self.subsample[0], ::self.subsample[1]] = topgrad
topgrad = new_topgrad
kern = kern.transpose(1, 0, 2, 3)
if self.filter_flip:
topgrad = topgrad[:, :, ::-1, ::-1]
img = self.conv2d(topgrad, kern, mode="full")
if self.filter_flip:
img = img[:, :, ::-1, ::-1]
if pad_h > 0 or pad_w > 0:
img = img[:, :, pad_h:img.shape[2] - pad_h, pad_w:img.shape[3] - pad_w]
o[0] = node.outputs[0].type.filter(img)
def grad(self, inp, grads): def grad(self, inp, grads):
weights, top = inp[:2] weights, top = inp[:2]
......
...@@ -4,6 +4,7 @@ Optimizations addressing the ops in nnet root directory ...@@ -4,6 +4,7 @@ Optimizations addressing the ops in nnet root directory
import theano import theano
from theano import compile, gof from theano import compile, gof
from theano.compile import optdb
from theano.gof import local_optimizer from theano.gof import local_optimizer
from theano.tensor.nnet.corr import ( from theano.tensor.nnet.corr import (
...@@ -20,6 +21,7 @@ from theano.tensor.nnet.abstract_conv import get_conv_output_shape ...@@ -20,6 +21,7 @@ from theano.tensor.nnet.abstract_conv import get_conv_output_shape
from theano.tensor.opt import (copy_stack_trace, from theano.tensor.opt import (copy_stack_trace,
register_specialize_device) register_specialize_device)
from theano.tensor import TensorType from theano.tensor import TensorType
from theano.tensor import opt
# Cpu implementation # Cpu implementation
from theano.tensor.nnet.conv import conv2d, ConvOp from theano.tensor.nnet.conv import conv2d, ConvOp
...@@ -379,3 +381,30 @@ conv_groupopt.register('local_conv2d_gradweight_cpu', ...@@ -379,3 +381,30 @@ conv_groupopt.register('local_conv2d_gradweight_cpu',
conv_groupopt.register('local_conv2d_gradinputs_cpu', conv_groupopt.register('local_conv2d_gradinputs_cpu',
local_conv2d_gradinputs_cpu, 40, local_conv2d_gradinputs_cpu, 40,
'fast_compile', 'fast_run') 'fast_compile', 'fast_run')
# Verify that no AbstractConv are present in the graph
@local_optimizer([AbstractConv2d,
AbstractConv2d_gradWeights,
AbstractConv2d_gradInputs])
def local_abstractconv_check(node):
if isinstance(node.op, AbstractConv2d):
raise AssertionError(
'AbstractConv2d theano optimization failed. '
'Did you exclude both "conv_dnn" and "conv_gemm" from '
'the optimizer? Is cudnn available and does the GPU support it?')
elif isinstance(node.op, AbstractConv2d_gradWeights):
raise AssertionError(
'AbstractConv2d_gradWeights theano optimization failed. '
'Did you exclude both "conv_dnn" and "conv_gemm" from '
'the optimizer? Is cudnn available and does the GPU support it?')
elif isinstance(node.op, AbstractConv2d_gradInputs):
raise AssertionError(
'AbstractConv2d_gradInputs theano optimization failed. '
'Did you exclude both "conv_dnn" and "conv_gemm" from '
'the optimizer? Is cudnn available and does the GPU support it?')
optdb.register('AbstracConvCheck',
opt.in2out(local_abstractconv_check,
name="AbstractConvCheck"),
48.7, 'fast_compile', 'fast_run')
...@@ -312,7 +312,7 @@ class TestCpuConv2d(BaseTestConv2d): ...@@ -312,7 +312,7 @@ class TestCpuConv2d(BaseTestConv2d):
mode=mode, provide_shape=provide_shape, mode=mode, provide_shape=provide_shape,
border_mode=b, filter_flip=flip, target_op=ConvOp) border_mode=b, filter_flip=flip, target_op=ConvOp)
else: else:
self.assertRaises(NotImplementedError, self.assertRaises(AssertionError,
self.run_fwd, self.run_fwd,
inputs_shape=i, inputs_shape=i,
filters_shape=f, filters_shape=f,
...@@ -331,7 +331,7 @@ class TestCpuConv2d(BaseTestConv2d): ...@@ -331,7 +331,7 @@ class TestCpuConv2d(BaseTestConv2d):
filter_flip=flip, filter_flip=flip,
target_op=(ConvOp, ConvGrad3D)) target_op=(ConvOp, ConvGrad3D))
else: else:
self.assertRaises(NotImplementedError, self.assertRaises(AssertionError,
self.run_gradweight, self.run_gradweight,
inputs_shape=i, inputs_shape=i,
filters_shape=f, filters_shape=f,
...@@ -351,7 +351,7 @@ class TestCpuConv2d(BaseTestConv2d): ...@@ -351,7 +351,7 @@ class TestCpuConv2d(BaseTestConv2d):
filter_flip=flip, filter_flip=flip,
target_op=(ConvOp, ConvTransp3D)) target_op=(ConvOp, ConvTransp3D))
else: else:
self.assertRaises(NotImplementedError, self.assertRaises(AssertionError,
self.run_gradinput, self.run_gradinput,
inputs_shape=i, inputs_shape=i,
filters_shape=f, filters_shape=f,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论