-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
conv.py
127 lines (103 loc) · 3.61 KB
/
conv.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"""
Contains a wrapper function for tensor.nnet.ConvOp, which can be used to perform
generic 2D convolution.
"""
import warnings
import theano
import theano.tensor as tensor
from theano.tensor.nnet import conv
import logging
__docformat__ = "restructuredtext en"
_logger = logging.getLogger("theano.tensor.signal.conv")
def conv2d(
input,
filters,
image_shape=None,
filter_shape=None,
border_mode="valid",
subsample=(1, 1),
**kargs,
):
"""
signal.conv.conv2d performs a basic 2D convolution of the input with the
given filters. The input parameter can be a single 2D image or a 3D tensor,
containing a set of images. Similarly, filters can be a single 2D filter or
a 3D tensor, corresponding to a set of 2D filters.
Shape parameters are optional and will result in faster execution.
Parameters
----------
input : Symbolic theano tensor for images to be filtered.
Dimensions: ([num_images], image height, image width)
filters : Symbolic theano tensor for convolution filter(s).
Dimensions: ([num_filters], filter height, filter width)
border_mode: {'valid', 'full'}
See scipy.signal.convolve2d.
subsample
Factor by which to subsample output.
image_shape : tuple of length 2 or 3
([num_images,] image height, image width).
filter_shape : tuple of length 2 or 3
([num_filters,] filter height, filter width).
kwargs
See theano.tensor.nnet.conv.conv2d.
Returns
-------
symbolic 2D,3D or 4D tensor
Tensor of filtered images, with shape
([number images,] [number filters,] image height, image width).
"""
assert input.ndim in (2, 3)
assert filters.ndim in (2, 3)
# use shape information if it is given to us ###
if filter_shape and image_shape:
if input.ndim == 3:
bsize = image_shape[0]
else:
bsize = 1
imshp = (1,) + tuple(image_shape[-2:])
if filters.ndim == 3:
nkern = filter_shape[0]
else:
nkern = 1
kshp = filter_shape[-2:]
else:
nkern, kshp = None, None
bsize, imshp = None, None
# reshape tensors to 4D, for compatibility with ConvOp ###
if input.ndim == 3:
sym_bsize = input.shape[0]
else:
sym_bsize = 1
if filters.ndim == 3:
sym_nkern = filters.shape[0]
else:
sym_nkern = 1
new_input_shape = tensor.join(0, tensor.stack([sym_bsize, 1]), input.shape[-2:])
input4D = tensor.reshape(input, new_input_shape, ndim=4)
new_filter_shape = tensor.join(0, tensor.stack([sym_nkern, 1]), filters.shape[-2:])
filters4D = tensor.reshape(filters, new_filter_shape, ndim=4)
# perform actual convolution ###
op = conv.ConvOp(
output_mode=border_mode,
dx=subsample[0],
dy=subsample[1],
imshp=imshp,
kshp=kshp,
nkern=nkern,
bsize=bsize,
**kargs,
)
output = op(input4D, filters4D)
# flatten to 3D tensor if convolving with single filter or single image
if input.ndim == 2 and filters.ndim == 2:
if theano.config.warn.signal_conv2d_interface:
warnings.warn(
"theano.tensor.signal.conv2d() now outputs a 2d tensor when both"
" inputs are 2d. To disable this warning, set the Theano flag"
" warn.signal_conv2d_interface to False",
stacklevel=3,
)
output = tensor.flatten(output.T, ndim=2).T
elif input.ndim == 2 or filters.ndim == 2:
output = tensor.flatten(output.T, ndim=3).T
return output