提交 70653920 authored 作者: Nicolas Ballas's avatar Nicolas Ballas

add DebugMode implementation for conv2d

上级 0aa5ff77
......@@ -47,6 +47,33 @@ class TestDnnConv2d(test_abstract_conv.BaseTestConv2d):
filter_flip=flip, target_op=GpuDnnConvGradI)
class TestDnnConv2d(test_abstract_conv.BaseTestConv2d):
def setUp(self):
super(TestDnnConv2d, self).setUp()
# provide_shape is not used by the CuDNN impementation
self.provide_shape = [False]
self.shared = gpu_shared
def tcase(self, i, f, s, b, flip, provide_shape):
mode = "DebugMode"
o = self.get_output_shape(i, f, s, b)
self.run_fwd(inputs_shape=i, filters_shape=f, subsample=s,
verify_grad=True, mode=mode, mode_ref=mode_without_gpu,
device='cpu', provide_shape=provide_shape, border_mode=b,
filter_flip=flip, target_op=None)
self.run_gradweight(inputs_shape=i, filters_shape=f,
output_shape=o, subsample=s,
verify_grad=True, mode=mode, mode_ref=mode_without_gpu,
device='cpu', provide_shape=provide_shape, border_mode=b,
filter_flip=flip, target_op=None)
self.run_gradinput(inputs_shape=i, filters_shape=f,
output_shape=o, subsample=s,
verify_grad=True, mode=mode, mode_ref=mode_without_gpu,
device='cpu', provide_shape=provide_shape, border_mode=b,
filter_flip=flip, target_op=None)
class TestCorrMMConv2d(test_abstract_conv.TestConv2d):
def setUp(self):
super(TestCorrMMConv2d, self).setUp()
......
......@@ -9,6 +9,17 @@ from theano.tensor import as_tensor_variable, patternbroadcast
from theano.gof import Apply, Op
import numpy
try:
# TODO: move these back out to global scope when they no longer
# cause an atexit error
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"
_logger = logging.getLogger("theano.tensor.nnet.abstract_conv")
......@@ -430,6 +441,36 @@ class BaseAbstractConv2d(Op):
# This may change in the future.
return False
def corr2d(self, img, kern, mode="valid"):
"""
Basic slow python implementatation for DebugMode
"""
if not imported_scipy_signal:
raise theano.gof.utils.MethodNotDefined(
"c_headers", type(self), self.__class__.__name__,
"Need the python package for scipy.signal to be installed "
"for the python implementation. You can use the C"
" implementation instead.")
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):
""" Abstract Op for the forward convolution.
......@@ -465,10 +506,31 @@ class AbstractConv2d(BaseAbstractConv2d):
return Apply(self, [img, kern], [output])
def perform(self, node, inp, out_):
raise NotImplementedError(
'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?')
img, kern = inp
o, = out_
mode = self.border_mode
### Pad
if 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
### Filter flip
if not self.filter_flip:
kern = kern[:, :, ::-1, ::-1]
conv_out = self.corr2d(img, kern, mode)
### Subsample
conv_out =conv_out[:, :, ::self.subsample[0], ::self.subsample[1]]
o[0] = conv_out
def R_op(self, inputs, eval_points):
rval = None
......@@ -564,10 +626,39 @@ class AbstractConv2d_gradWeights(BaseAbstractConv2d):
return Apply(self, [img, topgrad, shape], [output])
def perform(self, node, inp, out_):
raise NotImplementedError(
'AbstractConv2d_gradWeights theano optimization failed. '
'Did you exclude both "conv_dnn" and "conv_gemm" from '
'the optimizer?')
img, topgrad, shape = inp
o, = out_
mode = self.border_mode
if 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.corr2d(img, topgrad, mode)
if self.filter_flip:
kern = kern.transpose(1, 0, 2, 3)[:, :, ::-1, ::-1]
else:
kern = kern.transpose(1, 0, 2, 3)
o[0] = kern
def grad(self, inp, grads):
bottom, top = inp[:2]
......@@ -656,10 +747,32 @@ class AbstractConv2d_gradInputs(BaseAbstractConv2d):
return Apply(self, [kern, topgrad, shape], [output])
def perform(self, node, inp, out_):
raise NotImplementedError(
'AbstractConv2d_gradInputs theano optimization failed. '
'Did you exclude both "conv_dnn" and "conv_gemm" from '
'the optimizer?')
kern, topgrad, shape = inp
o, = out_
mode = self.border_mode
pad_h, pad_w = 0, 0
if isinstance(mode, tuple):
mode = "valid"
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.corr2d(topgrad, kern, mode="full")
if self.filter_flip:
img = img[:, :, ::-1, ::-1]
if isinstance(self.border_mode, tuple):
pad_h, pad_w = map(int, self.border_mode)
img = img[:, :, pad_h:img.shape[2]-pad_h, pad_w:img.shape[2]-pad_w]
o[0] = img
def grad(self, inp, grads):
weights, top = inp[:2]
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论