Skip to content
This repository was archived by the owner on Jul 10, 2021. It is now read-only.

Commit 81e9a46

Browse files
committed
Adding upscaling support in the convolution layers so it's easy to build convolutional autoencoders manually.
1 parent 8bf26e4 commit 81e9a46

File tree

4 files changed

+48
-9
lines changed

4 files changed

+48
-9
lines changed

sknn/backend/lasagne/mlp.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def _create_trainer(self, params, cost):
9393
allow_input_downcast=True)
9494
return trainer, validator
9595

96-
def _get_activation(self, l):
96+
def _get_activation(self, l):
9797
nonlinearities = {'Rectifier': nl.rectify,
9898
'Sigmoid': nl.sigmoid,
9999
'Tanh': nl.tanh,
@@ -119,9 +119,14 @@ def _create_convolution_layer(self, name, layer, network):
119119

120120
if layer.pool_shape != (1, 1):
121121
network = lasagne.layers.Pool2DLayer(
122-
network,
123-
pool_size=layer.pool_shape,
124-
stride=layer.pool_shape)
122+
network,
123+
pool_size=layer.pool_shape,
124+
stride=layer.pool_shape)
125+
126+
if layer.scale_factor != (1, 1):
127+
network = lasagne.layers.Upscale2DLayer(
128+
network,
129+
scale_factor=layer.scale_factor)
125130

126131
return network
127132

sknn/mlp.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ def _create_specs(self, X, y=None):
7777
if l.border_mode == 'full':
7878
res = (int((res[0] + l.kernel_shape[0]) / l.pool_shape[0]) - 1,
7979
int((res[1] + l.kernel_shape[1]) / l.pool_shape[1]) - 1)
80+
81+
if l.scale_factor != (1, 1):
82+
res = (int(l.scale_factor[0] * res[0]), int(l.scale_factor[1] * res[1]))
83+
8084
unit_count = numpy.prod(res) * l.channels
8185
else:
8286
unit_count = l.units

sknn/nn.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,24 @@ class Convolution(Layer):
170170
but for `valid` (default) it will be smaller or equal.
171171
172172
pool_shape: tuple of ints, optional
173-
A two-dimensional tuple of integers corresponding to the pool size. This should be
174-
square, for example `(2,2)` to reduce the size by half, or `(4,4)` to make the output
175-
a quarter of the original.
173+
A two-dimensional tuple of integers corresponding to the pool size for downsampling.
174+
This should be square, for example `(2,2)` to reduce the size by half, or `(4,4)` to make
175+
the output a quarter of the original.
176+
177+
Pooling is applied after the convolution and calculation of its activation.
176178
177179
pool_type: str, optional
178180
Type of the pooling to be used; can be either `max` or `mean`. If a `pool_shape` is
179181
specified the default is to take the maximum value of all inputs that fall into this
180182
pool. Otherwise, the default is None and no pooling is used for performance.
181183
184+
scale_factor: tuple of ints, optional
185+
A two-dimensional tuple of integers corresponding to upscaling ration. This should be
186+
square, for example `(2,2)` to increase the size by double, or `(4,4)` to make the
187+
output four times the original.
188+
189+
Upscaling is applied after the convolution and calculation of its activation.
190+
182191
weight_decay: float, optional
183192
The coefficient for L1 or L2 regularization of the weights. For example, a value of
184193
0.0001 is multiplied by the L1 or L2 weight decay equation.
@@ -208,6 +217,7 @@ def __init__(
208217
border_mode='valid',
209218
pool_shape=None,
210219
pool_type=None,
220+
scale_factor=None,
211221
weight_decay=None,
212222
dropout=None,
213223
frozen=False):
@@ -229,11 +239,12 @@ def __init__(
229239
frozen=frozen)
230240

231241
self.channels = channels
232-
self.pool_shape = pool_shape or (1,1)
233-
self.pool_type = pool_type or ('max' if pool_shape else None)
234242
self.kernel_shape = kernel_shape
235243
self.kernel_stride = kernel_stride or (1,1)
236244
self.border_mode = border_mode
245+
self.pool_shape = pool_shape or (1,1)
246+
self.pool_type = pool_type or ('max' if pool_shape else None)
247+
self.scale_factor = scale_factor or (1,1)
237248

238249

239250
class NeuralNetwork(object):

sknn/tests/test_conv.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,16 @@ def test_PoolingMeanType(self):
110110
n_iter=1))
111111

112112

113+
class TestUpscaling(unittest.TestCase):
114+
115+
def test_Upscaling(self):
116+
TestConvolution._run(self, MLPR(
117+
layers=[
118+
C("Rectifier", channels=4, kernel_shape=(2,2), scale_factor=(2,2)),
119+
L("Linear")],
120+
n_iter=1))
121+
122+
113123
class TestConvolutionSpecs(unittest.TestCase):
114124

115125
def test_SmallSquareKernel(self):
@@ -180,6 +190,15 @@ def test_MultiLayerPooling(self):
180190
nn._initialize(a_in, a_out)
181191
assert_equal(nn.unit_counts, [1024, 900, 196, 16])
182192

193+
def test_Upscaling(self):
194+
nn = MLPR(layers=[
195+
C("Rectifier", channels=4, kernel_shape=(1,1), scale_factor=(2,2), border_mode='same'),
196+
L("Linear", units=5)])
197+
198+
a_in = numpy.zeros((8,32,32,1))
199+
nn._create_specs(a_in)
200+
assert_equal(nn.unit_counts, [1024, 64 * 64 * 4, 5])
201+
183202

184203
class TestActivationTypes(unittest.TestCase):
185204

0 commit comments

Comments
 (0)