Skip to content

Commit 9c228ca

Browse files
committed
Merge pull request #4 from ikostrikov/otto
Added Otto example and many layers
2 parents 0abe63f + 0875553 commit 9c228ca

File tree

18 files changed

+330
-5
lines changed

18 files changed

+330
-5
lines changed

beacon8/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from .layers import *
22
from .containers import *
3-
from .criteria import *
3+
from .criteria import *

beacon8/containers/Concat.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from .Container import Container
2+
3+
import theano.tensor as _T
4+
5+
6+
class Concat(Container):
7+
def __init__(self, axis=1):
8+
Container.__init__(self)
9+
self.axis = axis
10+
11+
def symb_forward(self, symb_input):
12+
symb_outputs = [module.symb_forward(symb_input) for module in self.modules]
13+
return _T.concatenate(symb_outputs, self.axis)

beacon8/containers/Container.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,11 @@ def parameters(self):
3030

3131
return params, grads
3232

33+
def get_stat_updates(self):
34+
stat_updates = []
35+
for module in self.modules:
36+
stat_updates += module.get_stat_updates()
37+
return stat_updates
38+
3339
def add(self, module):
3440
self.modules.append(module)

beacon8/containers/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from .Container import *
2-
from .Sequential import *
2+
from .Sequential import *
3+
from .Concat import *

beacon8/layers/AddConstant.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from .Module import Module
2+
3+
4+
class AddConstant(Module):
5+
def __init__(self, scalar):
6+
self.scalar = scalar
7+
8+
def symb_forward(self, symb_input):
9+
return symb_input + self.scalar
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from .Module import Module
2+
3+
import numpy as _np
4+
import theano as _th
5+
import theano.tensor as _T
6+
7+
8+
class BatchNormalization(Module):
9+
def __init__(self, n_features, eps=None):
10+
Module.__init__(self)
11+
12+
self.weight = _th.shared(_np.ones(shape=(n_features,), dtype=_th.config.floatX))
13+
self.bias = _th.shared(_np.zeros(shape=(n_features, ), dtype=_th.config.floatX))
14+
self.grad_weight = _th.shared(_np.zeros(shape=(n_features,), dtype=_th.config.floatX))
15+
self.grad_bias = _th.shared(_np.zeros(shape=(n_features, ), dtype=_th.config.floatX))
16+
17+
self.inference_weight = _th.shared(_np.ones(shape=(n_features,), dtype=_th.config.floatX))
18+
self.inference_bias = _th.shared(_np.zeros(shape=(n_features, ), dtype=_th.config.floatX))
19+
20+
self.buffer_variance = _th.shared(_np.ones(shape=(n_features, ), dtype=_th.config.floatX))
21+
self.buffer_mean = _th.shared(_np.zeros(shape=(n_features, ), dtype=_th.config.floatX))
22+
self.buffer_counts = _th.shared(_np.asarray(0., dtype=_th.config.floatX))
23+
24+
self.eps = eps or 1e-5
25+
26+
self.batch_mean = None
27+
self.batch_var = None
28+
29+
def symb_forward(self, symb_input):
30+
d_shuffle = ('x', 0)
31+
axis = (0,)
32+
33+
if symb_input.ndim == 4:
34+
d_shuffle += ('x', 'x')
35+
axis += (2, 3)
36+
37+
if self.training_mode:
38+
self.batch_mean = _th.tensor.mean(symb_input, axis=axis)
39+
self.batch_var = _th.tensor.var(symb_input, axis=axis)
40+
41+
return (symb_input - self.batch_mean.dimshuffle(*d_shuffle)) / _th.tensor.sqrt(self.batch_var + self.eps).dimshuffle(*d_shuffle) * self.weight.dimshuffle(*d_shuffle) + self.bias.dimshuffle(*d_shuffle)
42+
else:
43+
return symb_input * self.inference_weight.dimshuffle(*d_shuffle) + self.inference_bias.dimshuffle(*d_shuffle)
44+
45+
def get_stat_updates(self,):
46+
assert (self.batch_mean is not None) and (self.batch_var is not None), "You need to do a forward pass first"
47+
48+
stat_updates = list()
49+
stat_updates.append((self.buffer_mean,
50+
(self.buffer_mean * self.buffer_counts + self.batch_mean) / (self.buffer_counts + 1.0)))
51+
52+
stat_updates.append((self.buffer_variance,
53+
(self.buffer_variance * self.buffer_counts + self.batch_var) / (self.buffer_counts + 1.0)))
54+
55+
stat_updates.append((self.buffer_counts,
56+
self.buffer_counts + 1.0))
57+
58+
return stat_updates
59+
60+
def training(self):
61+
Module.training(self)
62+
self.buffer_counts.set_value(0)
63+
self.batch_mean = None
64+
self.batch_var = None
65+
66+
def evaluate(self):
67+
Module.evaluate(self)
68+
self.inference_weight.set_value(self.weight.get_value() / _np.sqrt(self.buffer_variance.get_value() + self.eps))
69+
self.inference_bias.set_value(self.bias.get_value() - self.inference_weight.get_value() * self.buffer_mean.get_value())

beacon8/layers/Dropout.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from .Module import Module
2+
3+
import theano as _th
4+
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams
5+
_srng = RandomStreams()
6+
7+
class Dropout(Module):
8+
def __init__(self, dropout):
9+
Module.__init__(self)
10+
self.dropout = dropout
11+
12+
def symb_forward(self, symb_input):
13+
if self.training_mode:
14+
shuffle_shape = (0, 1)
15+
if symb_input.ndim == 4:
16+
shuffle_shape += ('x', 'x')
17+
18+
mask = _srng.binomial((symb_input.shape[0], symb_input.shape[1]),
19+
p=(1. - self.dropout),
20+
dtype='int32'
21+
).astype(_th.config.floatX).dimshuffle(*shuffle_shape)
22+
23+
return symb_input / (1. - self.dropout) * mask
24+
else:
25+
return symb_input

beacon8/layers/Linear.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ def symb_forward(self, symb_input):
3838
out += self.bias
3939

4040
return out
41+

beacon8/layers/Log.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from .Module import Module
2+
3+
import theano.tensor as _T
4+
5+
6+
class Log(Module):
7+
def symb_forward(self, symb_input):
8+
return _T.log(symb_input)

beacon8/layers/Module.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def __init__(self):
99

1010
self.fn_forward = None
1111
self.fn_accum_grads = None
12+
self.fn_accum_stats = None
1213

1314
def reset(self):
1415
pass
@@ -70,3 +71,20 @@ def accumulate_gradients(self, data_in, data_tgt, loss):
7071
)
7172

7273
self.fn_accum_grads(data_in, data_tgt)
74+
75+
def get_stat_updates(self):
76+
return []
77+
78+
def accumulate_statistics(self, data_in):
79+
if self.fn_accum_stats is None:
80+
symb_in = _T.TensorType(_th.config.floatX, (False,) * data_in.ndim)('X')
81+
self.symb_forward(symb_in)
82+
83+
stat_updates = self.get_stat_updates()
84+
85+
self.fn_accum_stats = _th.function(
86+
inputs=[symb_in],
87+
updates=stat_updates
88+
)
89+
90+
self.fn_accum_stats(data_in)

0 commit comments

Comments
 (0)