Skip to content

Commit e309711

Browse files
authored
Merge pull request #88 from lucasb-eyer/bias-init
Unifies optional model parameter handling.
2 parents 7beb8da + b5535ad commit e309711

File tree

6 files changed

+24
-28
lines changed

6 files changed

+24
-28
lines changed

DeepFried2/Module.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,24 @@ def __init__(self):
2222
#def __hash__(self):
2323
# raise NotImplementedError("You *need* to reimplement hash, even if it's just python's default. See the documentation for more info.")
2424

25-
def _addparam(self, *a, **kw):
25+
def _addparam(self, shape, init, *a, **kw):
26+
assert init is not None and init is not False, "`{}` requires parameter `{}` to have initializer.".format(df.utils.typename(self), kw.get("name", "unnamed"))
27+
2628
# Add it here because many don't even have params. This avoids misuse.
2729
if not hasattr(self, '_params'):
2830
self._params = []
2931

30-
param = df.Param(*a, **kw)
32+
param = df.Param(shape, init, *a, **kw)
3133
self._params.append(param)
3234
return param
3335

36+
def _addparam_optional(self, shape, init, *a, **kw):
37+
if init is None or init is False:
38+
return None
39+
40+
return self._addparam(shape, init, *a, **kw)
41+
42+
3443
def zero_grad_parameters(self):
3544
for p in self.parameters(trainable_only=True):
3645
p.zero_grad()

DeepFried2/Param.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ def __init__(self, shape, init, fan=None, name=None, learn=True, decay=True, dty
1010
self.fan = fan
1111
self.decay = decay
1212

13-
# Support a useful shortcut for initializing with an array-like:
14-
# TODO: It would be nicer to use Python's buffer-interface.
13+
# Support a couple useful shortcut for initializing:
1514
if hasattr(init, 'shape') and hasattr(init, 'dtype'):
15+
# TODO: It would be nicer to use Python's buffer-interface.
1616
self.init = df.init.array(init)
17+
elif _np.isscalar(init):
18+
self.init = df.init.const(init)
1719

1820
val = self.init(self.shape, self.fan).astype(dtype)
1921
self.param = df.th.shared(val, name=name, **kw)

DeepFried2/layers/BackwardsConvolutionCUDNN.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88

99
class BackwardsConvolutionCUDNN(df.Module):
10-
def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border=0, mode='cross', init=df.init.xavier(), bias=df.init.const(0)):
10+
def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border=0, mode='cross', init=df.init.xavier(), bias=0):
1111
"""
1212
This is the backwards path through a convolution, sometimes is also
1313
referred to as transposed convolution and (wrongly) deconvolution.
@@ -43,11 +43,7 @@ def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border=0, mode='c
4343
w_fan = (np.prod(self.filter_size)*nchan_out, np.prod(self.filter_size)*nchan_in)
4444
w_name = ('Wconv_{},{}@{}' + 'x{}'*(len(w_shape) - 3)).format(*w_shape)
4545
self.W = self._addparam(w_shape, init, fan=w_fan, name=w_name)
46-
47-
if bias not in (None, False):
48-
self.b = self._addparam(nchan_out, bias, decay=False, name='bconv_{}'.format(nchan_out))
49-
else:
50-
self.b = None
46+
self.b = self._addparam_optional(nchan_out, bias, decay=False, name='bconv_{}'.format(nchan_out))
5147

5248

5349
def symb_forward(self, symb_input):

DeepFried2/layers/Linear.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,15 @@
55

66
class Linear(df.Module):
77

8-
def __init__(self, nin, nout, init=df.init.xavier(), bias=df.init.const(0)):
8+
def __init__(self, nin, nout, init=df.init.xavier(), bias=0):
99
df.Module.__init__(self)
1010

1111
self.nin = nin
1212
self.nout = nout
1313

1414
shape = (nin, nout)
1515
self.W = self._addparam(shape, init, fan=shape, name='Wlin_{}x{}'.format(*shape))
16-
if bias not in (None, False):
17-
self.b = self._addparam(nout, bias, decay=False, name='blin_{}'.format(nout))
18-
else:
19-
self.b = None
16+
self.b = self._addparam_optional(nout, bias, decay=False, name='blin_{}'.format(nout))
2017

2118
def symb_forward(self, symb_input):
2219
out = df.T.dot(symb_input, self.W.param)

DeepFried2/layers/SpatialConvolution.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from theano.tensor.nnet import conv3d2d
55

66
class SpatialConvolution(df.Module):
7-
def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border='valid', mode='cross', init=df.init.xavier(), bias=df.init.const(0), imshape=None):
7+
def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border='valid', mode='cross', init=df.init.xavier(), bias=0, imshape=None):
88
# See `SpatialConvolutionCUDNN` comment for the `mode` parameter. Only works in 2D
99
df.Module.__init__(self)
1010
self.nchan_in = nchan_in
@@ -31,11 +31,7 @@ def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border='valid', m
3131
w_fan = (nchan_in*np.prod(self.filter_size), nchan_out*np.prod(self.filter_size))
3232
w_name = ('Wconv_{},{}@{}' + 'x{}'*(len(self.w_shape) - 3)).format(*self.w_shape)
3333
self.W = self._addparam(self.w_shape, init, fan=w_fan, name=w_name)
34-
35-
if bias not in (None, False):
36-
self.b = self._addparam(nchan_out, bias, decay=False, name='bconv_{}'.format(nchan_out))
37-
else:
38-
self.b = None
34+
self.b = self._addparam_optional(nchan_out, bias, decay=False, name='bconv_{}'.format(nchan_out))
3935

4036

4137
def symb_forward(self, symb_input):

DeepFried2/layers/SpatialConvolutionCUDNN.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
import numpy as np
66

77
class SpatialConvolutionCUDNN(df.Module):
8-
def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border=0, mode='cross', init=df.init.xavier(), bias=df.init.const(0)):
8+
def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border=0, mode='cross', init=df.init.xavier(), bias=0):
99
# mode='cross' is the default in Lasagne[1], Torch[2], matConvNet[3], Caffee[4].
1010
#
1111
# 1: https://github.com/Lasagne/Lasagne/blob/63d44a0d/lasagne/layers/dnn.py#L299
1212
# 2: https://github.com/soumith/cudnn.torch/blob/840f0228/SpatialConvolution.lua#L83
1313
# 3: https://github.com/vlfeat/matconvnet/blob/b7dd9c96/matlab/src/bits/impl/nnconv_cudnn.cu#L133
1414
# 4: https://github.com/BVLC/caffe/blob/50ab52cb/include/caffe/util/cudnn.hpp#L104
1515
df.Module.__init__(self)
16-
16+
1717
# Catch a probably common bug while we transition the API.
1818
assert isinstance(filter_size, (list, tuple)), "New conv API: filter_size needs to be a tuple!"
1919

@@ -33,11 +33,7 @@ def __init__(self, nchan_in, nchan_out, filter_size, stride=1, border=0, mode='c
3333
w_fan = (np.prod(self.filter_size)*nchan_in, np.prod(self.filter_size)*nchan_out)
3434
w_name = ('Wconv_{},{}@{}' + 'x{}'*(len(w_shape) - 3)).format(*w_shape)
3535
self.W = self._addparam(w_shape, init, fan=w_fan, name=w_name)
36-
37-
if bias not in (None, False):
38-
self.b = self._addparam(nchan_out, bias, decay=False, name='bconv_{}'.format(nchan_out))
39-
else:
40-
self.b = None
36+
self.b = self._addparam_optional(nchan_out, bias, decay=False, name='bconv_{}'.format(nchan_out))
4137

4238

4339
def symb_forward(self, symb_input):

0 commit comments

Comments
 (0)