提交 fb61eb6b authored 作者: Frederic Bastien's avatar Frederic Bastien

added test to the conv op and fix the new test that fail.

Some c_code regerated by the conv op was hard coding some shape info in some case. When those case are not true, their was no error generated.
上级 c47c2209
...@@ -871,7 +871,7 @@ class ConvOp(Op): ...@@ -871,7 +871,7 @@ class ConvOp(Op):
return ['<numpy/noprefix.h>', '<iostream>', '<sstream>' ] return ['<numpy/noprefix.h>', '<iostream>', '<sstream>' ]
def c_code_cache_version(self): def c_code_cache_version(self):
return (2) return (3)
def c_support_code(self): def c_support_code(self):
return """ return """
...@@ -1534,6 +1534,19 @@ if(%(filtersflipped)s->nd==3){ ...@@ -1534,6 +1534,19 @@ if(%(filtersflipped)s->nd==3){
%(fail)s; %(fail)s;
} }
if(img2d_dim[0] %% %(self_bsize)s!=0){
PyErr_Format(PyExc_ValueError,
"the batch size of the image(%%d) must be a multiple of the bsize value at ConvOp construction(%%d).",
img2d_dim[0],%(self_bsize)s);
%(fail)s;
}
if(kerns_dim[0] %% %(self_nkern)s!=0){
PyErr_Format(PyExc_ValueError,
"the number of kernel(%%d) must be a multiple of the nkern value at ConvOp construction(%%d).",
kerns_dim[0], %(self_nkern)s);
%(fail)s;
}
img2d = PyArray_Newshape(%(img2d)s,&img2d_shape, PyArray_CORDER); img2d = PyArray_Newshape(%(img2d)s,&img2d_shape, PyArray_CORDER);
img2d_arr = (PyArrayObject*)img2d; img2d_arr = (PyArrayObject*)img2d;
if ((img2d_arr->strides[3] != (npy_intp)sizeof(%(type)s)) if ((img2d_arr->strides[3] != (npy_intp)sizeof(%(type)s))
...@@ -1761,6 +1774,19 @@ if(%(filtersflipped)s->nd==3){ ...@@ -1761,6 +1774,19 @@ if(%(filtersflipped)s->nd==3){
%(fail)s; %(fail)s;
} }
if(img2d_dim[0] != %(self_bsize)s){
PyErr_Format(PyExc_ValueError,
"the batch size of the image(%%d) must be a multiple of the bsize value at ConvOp construction(%%d).",
img2d_dim[0],%(self_bsize)s);
%(fail)s;
}
if(kerns_dim[0] != %(self_nkern)s){
PyErr_Format(PyExc_ValueError,
"the number of kernel(%%d) must be a multiple of the nkern value at ConvOp construction(%%d).",
kerns_dim[0], %(self_nkern)s);
%(fail)s;
}
img2d = PyArray_Newshape(%(img2d)s,&img2d_shape, PyArray_CORDER); img2d = PyArray_Newshape(%(img2d)s,&img2d_shape, PyArray_CORDER);
img2d_arr = (PyArrayObject*)img2d; img2d_arr = (PyArrayObject*)img2d;
if ((img2d_arr->strides[3] != sizeof(%(type)s)) if ((img2d_arr->strides[3] != sizeof(%(type)s))
......
...@@ -22,8 +22,8 @@ class TestConv2D(unittest.TestCase): ...@@ -22,8 +22,8 @@ class TestConv2D(unittest.TestCase):
border_mode='valid', subsample=(1,1), border_mode='valid', subsample=(1,1),
N_image_shape=None, N_filter_shape=None, N_image_shape=None, N_filter_shape=None,
input=None, filters=None, input=None, filters=None,
unroll_batch=0, unroll_kern=0, unroll_patch=True, unroll_batch=None, unroll_kern=None, unroll_patch=None,
verify_grad=True): verify_grad=True, should_raise=False):
if N_image_shape is None: if N_image_shape is None:
N_image_shape = image_shape N_image_shape = image_shape
...@@ -50,7 +50,13 @@ class TestConv2D(unittest.TestCase): ...@@ -50,7 +50,13 @@ class TestConv2D(unittest.TestCase):
# initialize input and compute result # initialize input and compute result
image_data = numpy.random.random(N_image_shape) image_data = numpy.random.random(N_image_shape)
filter_data = numpy.random.random(N_filter_shape) filter_data = numpy.random.random(N_filter_shape)
theano_output = theano_conv(image_data, filter_data) try:
theano_output = theano_conv(image_data, filter_data)
except ValueError:
if not should_raise: raise
return
else:
if should_raise: raise Exception("ConvOp should have generated an error")
############# REFERENCE IMPLEMENTATION ############ ############# REFERENCE IMPLEMENTATION ############
s = 1. s = 1.
...@@ -99,14 +105,33 @@ class TestConv2D(unittest.TestCase): ...@@ -99,14 +105,33 @@ class TestConv2D(unittest.TestCase):
self.validate((3,2,3,3), (4,2,3,3), 'full') self.validate((3,2,3,3), (4,2,3,3), 'full')
self.validate((3,2,3,3), (4,2,3,3), 'valid') self.validate((3,2,3,3), (4,2,3,3), 'valid')
def test_unroll_patch_true(self):
"""
Test basic convs with True.
"""
self.validate((3,2,7,5), (5,2,2,3), 'valid', unroll_patch=True)
self.validate((3,2,7,5), (5,2,2,3), 'full', unroll_patch=True)
self.validate((3,2,3,3), (4,2,3,3), 'valid', unroll_patch=True, verify_grad=False)
def test_unroll_patch_false(self): def test_unroll_patch_false(self):
""" """
unroll_patch is True by default. Test basic convs with False. Test basic convs with False.
""" """
self.validate((3,2,7,5), (5,2,2,3), 'valid', unroll_patch=False) self.validate((3,2,7,5), (5,2,2,3), 'valid', unroll_patch=False)
self.validate((3,2,7,5), (5,2,2,3), 'full', unroll_patch=False) self.validate((3,2,7,5), (5,2,2,3), 'full', unroll_patch=False)
self.validate((3,2,3,3), (4,2,3,3), 'valid', unroll_patch=False, verify_grad=False) self.validate((3,2,3,3), (4,2,3,3), 'valid', unroll_patch=False, verify_grad=False)
def test_unroll_patch_true_fail(self):
"""
Test basic convs with True.
"""
self.validate((3,2,7,5), (5,2,2,3), 'valid', unroll_patch=True,
N_image_shape=(1,3,3,3), N_filter_shape=(6,3,2,2), should_raise=True)
self.validate((3,2,7,5), (5,2,2,3), 'full', unroll_patch=True,
N_image_shape=(1,3,3,3), N_filter_shape=(6,3,2,2), should_raise=True)
self.validate((3,2,3,3), (4,2,3,3), 'valid', unroll_patch=True,
N_image_shape=(1,3,3,3), N_filter_shape=(6,3,2,2), should_raise=True)
def test_unroll_special(self): def test_unroll_special(self):
""" """
(unroll_kern, unroll_batch) in (0,1),(1,0) is special case. (unroll_kern, unroll_batch) in (0,1),(1,0) is special case.
...@@ -129,6 +154,32 @@ class TestConv2D(unittest.TestCase): ...@@ -129,6 +154,32 @@ class TestConv2D(unittest.TestCase):
self.validate((2,3,3,3), (6,3,2,2), 'valid', unroll_kern=2, verify_grad=False) self.validate((2,3,3,3), (6,3,2,2), 'valid', unroll_kern=2, verify_grad=False)
self.validate((2,3,3,3), (6,3,2,2), 'valid', unroll_kern=3, verify_grad=False) self.validate((2,3,3,3), (6,3,2,2), 'valid', unroll_kern=3, verify_grad=False)
def test_unroll_batch_kern(self):
"""
Test mini-batch unrolling with kernel unrolling for various legal values.
"""
# mini-batch of size 6 is multiple of 2 and 3. Should work.
self.validate((6,2,3,3), (3,2,2,2), 'valid', unroll_batch=2, unroll_kern=3, verify_grad=False)
self.validate((6,2,3,3), (3,2,2,2), 'valid', unroll_batch=3, unroll_kern=3, verify_grad=False)
# 6 filters is a multiple of 2 and 3. Should work.
self.validate((2,3,3,3), (6,3,2,2), 'valid', unroll_batch=2, unroll_kern=2, verify_grad=False)
self.validate((2,3,3,3), (6,3,2,2), 'valid', unroll_batch=2, unroll_kern=3, verify_grad=False)
def test_unroll_batch_kern_fail(self):
"""
Test mini-batch unrolling with kernel unrolling for various legal values, but pass bad input.
All those test must generate errors
"""
# mini-batch of size 6 is multiple of 2 and 3. Should work.
self.validate((6,2,3,3), (3,2,2,2), 'valid', unroll_batch=2, unroll_kern=3,
N_image_shape=(7,2,3,3), N_filter_shape=(3,2,2,2), should_raise=True)
self.validate((6,2,3,3), (3,2,2,2), 'valid', unroll_batch=3, unroll_kern=3,
N_image_shape=(6,2,3,3), N_filter_shape=(4,2,2,2), should_raise=True)
self.validate((2,3,3,3), (6,3,2,2), 'valid', unroll_batch=2, unroll_kern=2,
N_image_shape=(1,3,3,3), N_filter_shape=(6,3,2,2), should_raise=True)
self.validate((2,3,3,3), (6,3,2,2), 'valid', unroll_batch=2, unroll_kern=3,
N_image_shape=(2,3,3,3), N_filter_shape=(5,3,2,2), should_raise=True)
def test_subsample(self): def test_subsample(self):
""" """
Tests convolution where subsampling != (1,1) Tests convolution where subsampling != (1,1)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论