Reputation: 1243
I've read the previous responses regarding the theano conv1d
problem but I can't seem to make it work:
x = np.arange(50) * 1.
y = np.random.normal((x+0.1)/5, 1, 50)
def tophat(x, centre, width, amplitude):
return tt.switch((x < centre + (width/2)) & (x >= centre - (width/2)), np.float64(amplitude) / width, np.float64(0.))
import theano.tensor.signal.conv
def theano_convolve(x, y, filt_range, centre, width, amplitude):
a = tt.matrix('a', dtype='float64')
b = tt.matrix('b', dtype='float64')
filt = tophat(b, centre, width, amplitude)
func = tt.signal.conv.conv2d(a, filt, (1, y.shape[0]), (1, filt_range.shape[0]), border_mode='full') / filt.sum()
return theano.function([a, b], func)(y[None, :], filt_range[None, :])
from scipy.signal import convolve
def scipy_convolve(x, y, filt_range, centre, width, amplitude):
a = tt.vector('a')
filt = theano.function([a], tophat(a, centre, width, amplitude))(filt_range)
return convolve(y, filt, mode='same') / sum(filt)
convolved_theano = theano_convolve(x, y, np.linspace(-10, 10, len(x)), 0, 3, 1)
convolved_scipy = scipy_convolve(x, y, np.linspace(-10, 10, len(x)), 0, 3, 1)
plt.plot(x, y, '.', label='data')
plt.plot(r[0], label='theano')
plt.plot(convolved_scipy, label='scipy');
plt.legend();
This results in a zero-padded convolution with theano. I could just strip out the zeroes but I'd rather know what is going on!
How do you convolve a tophat function with some data (1-dimensional) in theano?
Thanks
Upvotes: 1
Views: 229
Reputation: 2738
The behavior you see is caused by the different mode
you use for the two convolutions.
In the scipy.signal.convolve
you use mode='same'
while in the theano.tensor.signal.conv.conv2d
you use mode='full'
.
Changing the scipy.signal.convolve
to use mode='full'
yields the exact same
vector. For the image I added .1
to the theano vector to make the line visible and not overlap with the sicpy.convolve one.
import numpy as np
import theano.tensor as tt
import seaborn as sns
plt = sns.plt
x = np.arange(50) * 1.
y = np.random.normal((x+0.1)/5, 1, 50)
def tophat(x, centre, width, amplitude):
return tt.switch((x < centre + (width/2)) & (x >= centre - (width/2)), np.float64(amplitude) / width, np.float64(0.))
import theano.tensor.signal.conv
def theano_convolve(x, y, filt_range, centre, width, amplitude):
a = tt.matrix('a', dtype='float64')
b = tt.matrix('b', dtype='float64')
filt = tophat(b, centre, width, amplitude)
func = tt.signal.conv.conv2d(a, filt, (1, y.shape[0]), (1, filt_range.shape[0]), border_mode='full') / filt.sum()
return theano.function([a, b], func)(y[None, :], filt_range[None, :])
from scipy.signal import convolve
def scipy_convolve(x, y, filt_range, centre, width, amplitude):
a = tt.vector('a')
filt = theano.function([a], tophat(a, centre, width, amplitude))(filt_range)
return convolve(y, filt, mode='full') / sum(filt)
convolved_theano = theano_convolve(x, y, np.linspace(-10, 10, len(x)), 0, 3, 1)
convolved_scipy = scipy_convolve(x, y, np.linspace(-10, 10, len(x)), 0, 3, 1)
plt.plot(x, y, '.', label='data')
plt.plot(convolved_theano[0]+0.1, label='theano')
plt.plot(convolved_scipy, label='scipy')
plt.legend()
plt.show(block=True)
Unfortunately looking at the theano documentation conv2d for theano does not support border_mode='same'
.
Upvotes: 1