提交 981d42a9 authored 作者: Frederic Bastien's avatar Frederic Bastien

Remove some scipy dependency. We disable the perform method of the convolution…

Remove some scipy dependency. We disable the perform method of the convolution when scipy is not available.
上级 26ec4d86
...@@ -18,6 +18,16 @@ from theano import gof, Op, tensor, config ...@@ -18,6 +18,16 @@ from theano import gof, Op, tensor, config
from theano.tensor.tsor_apply import Apply from theano.tensor.tsor_apply import Apply
from theano.gof.python25 import any from theano.gof.python25 import any
imported_scipy_signal = False
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:
pass
_logger=logging.getLogger("theano.signal.conv") _logger=logging.getLogger("theano.signal.conv")
def _debug(*msg): def _debug(*msg):
_logger.debug(' '.join([ str(x) for x in msg])) _logger.debug(' '.join([ str(x) for x in msg]))
...@@ -547,9 +557,12 @@ class ConvOp(Op): ...@@ -547,9 +557,12 @@ class ConvOp(Op):
""" """
By default if len(img2d.shape)==3, we By default if len(img2d.shape)==3, we
""" """
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.")
# TODO: move these back out to global scope when they no longer cause an atexit error # 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
imshp = self.imshp imshp = self.imshp
if imshp is None or any([x is None for x in imshp]): if imshp is None or any([x is None for x in imshp]):
imshp = tuple(img2d.shape[1:]) imshp = tuple(img2d.shape[1:])
...@@ -584,8 +597,6 @@ class ConvOp(Op): ...@@ -584,8 +597,6 @@ class ConvOp(Op):
z[0] = numpy.zeros((bsize,)+(nkern,)+fulloutshp, z[0] = numpy.zeros((bsize,)+(nkern,)+fulloutshp,
dtype=img2d.dtype) dtype=img2d.dtype)
zz=z[0] zz=z[0]
val = _valfrommode(self.out_mode)
bval = _bvalfromboundary('fill')
stacklen = imshp[0] stacklen = imshp[0]
...@@ -616,6 +627,9 @@ class ConvOp(Op): ...@@ -616,6 +627,9 @@ class ConvOp(Op):
filtersflipped = buf filtersflipped = buf
del buf, rstride, cstride del buf, rstride, cstride
val = _valfrommode(self.out_mode)
bval = _bvalfromboundary('fill')
for b in range(bsize): for b in range(bsize):
for n in range(nkern): for n in range(nkern):
zz[b,n,...].fill(0) zz[b,n,...].fill(0)
...@@ -623,6 +637,25 @@ class ConvOp(Op): ...@@ -623,6 +637,25 @@ class ConvOp(Op):
zz[b,n,...] += _convolve2d(\ zz[b,n,...] += _convolve2d(\
img2d[b,im0,...], filtersflipped[n,im0,...],1,val, bval, 0) img2d[b,im0,...], filtersflipped[n,im0,...],1,val, bval, 0)
if False:
if False and self.out_mode=="full":
img2d2 = numpy.zeros((bsize,stacklen,
imshp[1]+2*kshp[0]-2,
imshp[2]+2*kshp[1]-2))
img2d2[:,:,kshp[0]-1:kshp[0]-1+imshp[1],
kshp[1]-1:kshp[1]-1+imshp[2]] = img2d
img2d = img2d2
#N_image_shape = image_data.shape
for b in range(bsize):
for n in range(nkern):
zz[b,n,...].fill(0)
for im0 in range(stacklen):
for row in range(0,zz.shape[2],self.dx):
for col in range(0,zz.shape[3],self.dy):
zz[b,n,row,col] += (img2d[b,im0,row:row+kshp[0],col:col+kshp[1]]*\
filtersflipped[n,im0,::-1,::-1]).sum()
#We copy it to remove the Stride mismatch warning from DEBUG_MODE. #We copy it to remove the Stride mismatch warning from DEBUG_MODE.
#The copy make that we return an object with the same stride as the c version. #The copy make that we return an object with the same stride as the c version.
#The copy don't affect the performence during our experience as in that case we #The copy don't affect the performence during our experience as in that case we
......
import sys, time, unittest import sys, time, unittest
import numpy import numpy
from scipy import signal
import theano import theano
import theano.tensor as T import theano.tensor as T
...@@ -60,6 +59,7 @@ class TestConv2D(unittest.TestCase): ...@@ -60,6 +59,7 @@ class TestConv2D(unittest.TestCase):
############# REFERENCE IMPLEMENTATION ############ ############# REFERENCE IMPLEMENTATION ############
s = 1. s = 1.
orig_image_data = image_data
if border_mode is not 'full': s = -1. if border_mode is not 'full': s = -1.
out_shape2d = numpy.array(N_image_shape[-2:]) +\ out_shape2d = numpy.array(N_image_shape[-2:]) +\
s*numpy.array(N_filter_shape[-2:]) - s s*numpy.array(N_filter_shape[-2:]) - s
...@@ -68,26 +68,41 @@ class TestConv2D(unittest.TestCase): ...@@ -68,26 +68,41 @@ class TestConv2D(unittest.TestCase):
ref_output = numpy.zeros(out_shape) ref_output = numpy.zeros(out_shape)
# loop over output feature maps # loop over output feature maps
for k in range(N_filter_shape[0]): ref_output.fill(0)
# loop over input feature maps if border_mode=='full':
for l in range(N_filter_shape[1]): image_data2 = numpy.zeros((N_image_shape[0],N_image_shape[1],
N_image_shape[2]+2*N_filter_shape[2]-2,
filter2d = filter_data[k,l,:,:] N_image_shape[3]+2*N_filter_shape[3]-2))
image_data2[:,:,N_filter_shape[2]-1:N_filter_shape[2]-1+N_image_shape[2],
# loop over mini-batches N_filter_shape[3]-1:N_filter_shape[3]-1+N_image_shape[3]] = image_data
for b in range(N_image_shape[0]): image_data = image_data2
image2d = image_data[b,l,:,:] N_image_shape = image_data.shape
output2d = signal.convolve2d(image2d, filter2d, border_mode) for bb in range(N_image_shape[0]):
for nn in range(N_filter_shape[0]):
ref_output[b,k,:,:] +=\ for im0 in range(N_image_shape[1]):
output2d[::subsample[0],::subsample[1]] filter2d = filter_data[nn,im0,:,:]
image2d = image_data[bb,im0,:,:]
for row in range(ref_output.shape[2]):
irow = row * subsample[0]#image row
for col in range(ref_output.shape[3]):
icol = col * subsample[1]#image col
ref_output[bb,nn,row,col] += (image2d[irow:irow+N_filter_shape[2],
icol:icol+N_filter_shape[3]]*filter2d[::-1,::-1]
).sum()
self.failUnless(_allclose(theano_output, ref_output)) self.failUnless(_allclose(theano_output, ref_output))
############# TEST GRADIENT ############ ############# TEST GRADIENT ############
if verify_grad: if verify_grad:
utt.verify_grad(sym_conv2d, [image_data, filter_data]) utt.verify_grad(sym_conv2d, [orig_image_data, filter_data])
def test_basic1(self):
"""
Tests that basic convolutions work for odd and even dimensions of image and filter
shapes, as well as rectangular images and filters.
"""
self.validate((2,2,3,3), (2,2,2,2), 'valid', verify_grad=False)
def test_basic(self): def test_basic(self):
""" """
......
import sys, time, unittest import sys, time, unittest
import numpy import numpy
from scipy import signal
import theano import theano
import theano.tensor as T import theano.tensor as T
...@@ -59,7 +58,13 @@ class TestSignalConv2D(unittest.TestCase): ...@@ -59,7 +58,13 @@ class TestSignalConv2D(unittest.TestCase):
image2d = image_data3d[b,:,:] image2d = image_data3d[b,:,:]
filter2d = filter_data3d[k,:,:] filter2d = filter_data3d[k,:,:]
output2d = signal.convolve2d(image2d, filter2d, 'valid') output2d = numpy.zeros(ref_output.shape)
for row in range(ref_output.shape[0]):
for col in range(ref_output.shape[1]):
output2d[row,col] += (image2d[row:row+filter2d.shape[0],
col:col+filter2d.shape[1]]*filter2d[::-1,::-1]
).sum()
self.failUnless(_allclose(theano_output4d[b,k,:,:], output2d)) self.failUnless(_allclose(theano_output4d[b,k,:,:], output2d))
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论