Skip to content

Commit a6c4d0e

Browse files
committed
init
1 parent bff7b9b commit a6c4d0e

13 files changed

+510
-3
lines changed

CHANGELOG.rst

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
1.0.0:
2+
=======
3+
The begining of a new era

DESCRIPTION.rst

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Mariana:
2+
=======
3+
4+
A machine learning framework for buildung deep neural networks

MANIFEST.in

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include *.rst
2+
include LICENCE

Mariana/NeuralNet.py

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import numpy
2+
import theano
3+
import cPickle
4+
import theano.tensor as tt
5+
6+
class Layer(object) :
7+
8+
def __init__(self, name, inputs, nbInputs, nbOutputs, activation = None) :
9+
"A generic definition a layer"
10+
self.reset(name, inputs, nbInputs, nbOutputs, activation)
11+
12+
def reset(self, name, inputs, nbInputs, nbOutputs, activation = None) :
13+
"resets everything to new parameters"
14+
15+
self.nbInputs = nbInputs
16+
self.inputs = inputs
17+
self.nbOutputs = nbOutputs
18+
19+
self.name = name
20+
self.activation = activation
21+
22+
initWeights = numpy.random.random((nbInputs, nbOutputs))
23+
initWeights = (initWeights/sum(initWeights))
24+
initWeights = numpy.asarray(initWeights, dtype=theano.config.floatX)
25+
self.W = theano.shared(value = initWeights, name = self.name + "_W")
26+
27+
initBias = numpy.zeros((nbOutputs,), dtype=theano.config.floatX)
28+
self.b = theano.shared(value = initBias, name = self.name + "_b")
29+
30+
self.params = [self.W, self.b]
31+
32+
if self.activation is None :
33+
self.outputs = tt.dot(self.inputs, self.W) + self.b
34+
else :
35+
self.outputs = self.activation(tt.dot(self.inputs, self.W) + self.b)
36+
37+
def serialize(self) :
38+
"returns a dict {name, nbInputs, nbOutputs, activation, W, b}"
39+
return {
40+
"name" : self.name,
41+
"nbInputs" : self.nbInputs,
42+
"nbOutputs" : self.nbOutputs,
43+
"activation" : self.activation,
44+
"W" : self.W.get_value(borrow = True),
45+
"b" : self.b.get_value(borrow = True)
46+
}
47+
48+
def __str__ (self) :
49+
if self.nbOutputs < 21:
50+
o = " O"*self.nbOutputs
51+
else :
52+
o = " O O O ... O O O"
53+
return "%s: [%s ](%s x %s)" % (self.name, o, self.nbInputs, self.nbOutputs)
54+
55+
class NeuralNet(object) :
56+
57+
def __init__(self, name, nbInputs, costFct, lr = 0.01, momentum = 0, l1 = 0., l2 = 0.) :
58+
"A neural network"
59+
self.reset(name, nbInputs, costFct, lr, momentum, l1, l2)
60+
61+
def reset(self, name, nbInputs, costFct, lr, momentum, l1, l2) :
62+
self.name = name
63+
self.nbInputs = nbInputs
64+
self.costFct = costFct
65+
66+
self.inputs = tt.matrix(name = self.name + "_X")
67+
self.y = tt.ivector(name = self.name + "_Y")
68+
self.layers = []
69+
self.layersDct = {}
70+
self.params = []
71+
self.lr = lr
72+
self.momentum = momentum
73+
self.l1 = l1
74+
self.l2 = l2
75+
76+
self._mustInitUpdates = True
77+
78+
def stackLayer(self, name, nbOutputs, activation) :
79+
"adds a layer to the stack and returns it"
80+
if name in self.layersDct :
81+
raise KeyError("There's already a layer by the name '%s'" % name)
82+
83+
if len(self.layers) < 1 :
84+
layer = Layer(self.name + "_" + name, self.inputs, self.nbInputs, nbOutputs, activation)
85+
else :
86+
priorLayer = self.layers[-1]
87+
layer = Layer(self.name + "_" + name, priorLayer.outputs, priorLayer.nbOutputs, nbOutputs, activation)
88+
89+
self.layersDct[name] = (layer, len(self.layers))
90+
self.layers.append(layer)
91+
return layer
92+
93+
def popLayer(self) :
94+
"removes the last layer from the stack and returns it"
95+
layer = self.layers.pop()
96+
del(self.layersDct[layer.name])
97+
98+
self._mustInitUpdates = True
99+
100+
return layer
101+
102+
def _initUpdates(self) :
103+
self.outputs = self.layers[-1].outputs
104+
cost = self.costFct(self.y, self.outputs)
105+
self.updates = []
106+
for layer in self.layers :
107+
self.params.extend(layer.params)
108+
for param in layer.params :
109+
# gparam = tt.grad(cost, param) + self.momentun * ()
110+
gparam = tt.grad(cost, param)
111+
momentum_param = theano.shared(param.get_value()*0., broadcastable=param.broadcastable)
112+
self.updates.append((momentum_param, self.momentum * momentum_param + (1-self.momentum)*gparam))
113+
self.updates.append((param, param - self.lr * momentum_param))
114+
115+
116+
L1 = self.l1 * sum([abs(l.W).sum() for l in self.layers])
117+
L2 = self.l2 * sum([(l.W**2).sum() for l in self.layers])
118+
cost = self.costFct(self.y, self.outputs) + L1 + L2
119+
120+
self.theano_train = theano.function(inputs = [self.inputs, self.y], outputs = [cost, self.outputs], updates = self.updates)
121+
self.theano_test = theano.function(inputs = [self.inputs, self.y], outputs = [cost, self.outputs])
122+
self.theano_propagate = theano.function(inputs = [self.inputs], outputs = self.outputs)
123+
self.theano_prediction = theano.function(inputs = [self.inputs], outputs = tt.argmax(self.outputs, axis = 1))
124+
125+
self._mustInitUpdates = False
126+
127+
def train(self, x, y) :
128+
if self._mustInitUpdates :
129+
self._initUpdates()
130+
# print x.shape
131+
return self.theano_train(x, y)
132+
133+
def test(self, x, y) :
134+
"same function for both test and validation"
135+
if self._mustInitUpdates :
136+
self._initUpdates()
137+
return self.theano_test(x, y)
138+
139+
def propagate(self, x) :
140+
if self._mustInitUpdates :
141+
self._initUpdates()
142+
return self.theano_propagate(x)
143+
144+
def predict(self, x) :
145+
if self._mustInitUpdates :
146+
self._initUpdates()
147+
return self.theano_prediction(x)
148+
149+
def save(self, filename) :
150+
"save the whole model"
151+
fil = open(filename + '.mdl', 'wb')
152+
153+
model = {
154+
"name" : self.name,
155+
"nbInputs" : self.nbInputs,
156+
"costFct" : self.costFct,
157+
"lr" : self.lr,
158+
"momentum" : self.momentum,
159+
"l1" : self.l1,
160+
"l2" : self.l2,
161+
"layers" : []
162+
}
163+
164+
layers = []
165+
for layer in self.layers :
166+
params = []
167+
layers.append(layer.serialize())
168+
169+
model["layers"] = layers
170+
cPickle.dump(model, fil, -1)
171+
fil.close()
172+
173+
@classmethod
174+
def load(cls, filename) :
175+
"load a previously saved model"
176+
fil = open(filename)
177+
model = cPickle.load(fil)
178+
nn = NeuralNet( model["name"], model["nbInputs"], model["costFct"], model["lr"], model["momentum"], model["l1"], model["l2"])
179+
for layer in model.layers :
180+
l = nn.stackLayer(layer["name"], layer["nbOutputs"], layer["activation"])
181+
l.W = layer["W"]
182+
l.b = layer["b"]
183+
fil.close()
184+
return nn
185+
186+
def __getitem__(self, layerName) :
187+
return self.layersDct[layerName]
188+
189+
def __str__(self) :
190+
ls = []
191+
s = "<Net: %s (inputs: %s, cost: %s, lr: %s, momentum: %s, l1: %s, l2: %s)>" % (self.name, self.nbInputs, self.costFct.__name__, self.lr, self.momentum, self.l1, self.l2)
192+
for l in self.layers :
193+
strl = str(l)
194+
ls.append( ' '* (len(s)/2) + 'X' )
195+
ls.append(' '*( (len(s)-len(strl))/2) + strl)
196+
prevLen = strl
197+
198+
s += "\n\n%s" % ('\n'.join(ls))
199+
return s

Mariana/OLDNeuralNet.py

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import numpy
2+
import theano
3+
import theano.tensor as tt
4+
5+
class Layer(object) :
6+
7+
def __init__(self, name, inputs, nbInputs, nbOutputs, activation = None) :
8+
9+
self.nbInputs = nbInputs
10+
self.nbOutputs = nbOutputs
11+
12+
self.inputs = inputs
13+
self.name = name
14+
self.activation = activation
15+
16+
#simply init with small random weights, should use glorot et al. 2010
17+
tmpW = numpy.random.random((nbInputs, nbOutputs))
18+
tmpW = (tmpW/sum(tmpW)) #*0.001
19+
initW = numpy.asarray(tmpW, dtype=theano.config.floatX)
20+
self.W = theano.shared(value = initW, name = self.name + "_W")
21+
22+
initB = numpy.zeros((nbOutputs,), dtype=theano.config.floatX)
23+
self.b = theano.shared(value = initB, name = self.name + "_b")
24+
25+
self.params = [self.W, self.b]
26+
27+
if self.activation is None :
28+
self.outputs = tt.dot(self.inputs, self.W) + self.b
29+
else :
30+
self.outputs = self.activation(tt.dot(self.inputs, self.W) + self.b)
31+
32+
def __str__ (self) :
33+
return "Layer: %s" % self.name
34+
35+
class NeuralNet(object) :
36+
37+
def __init__(self, name, nbInputs, costFct, lr = 0.01, l1 = 0., l2 = 0.) :
38+
self.name = name
39+
self.nbInputs = nbInputs
40+
self.costFct = costFct
41+
self.inputs = tt.lmatrix(name = self.name + "_X")
42+
self.y = tt.lvector(name = self.name + "_Y")
43+
self.layers = []
44+
self.layersDct = {}
45+
self.params = []
46+
self.lr = lr
47+
self.l1 = l1
48+
self.l2 = l2
49+
50+
self._mustInitUpdates = True
51+
52+
def stackLayer(self, name, nbOutputs, activation) :
53+
if name in self.layersDct :
54+
raise KeyError("There's already a layer by the name %s" % name)
55+
56+
if len(self.layers) < 1 :
57+
layer = Layer(self.name + "_" + name, self.inputs, self.nbInputs, nbOutputs, activation)
58+
else :
59+
priorLayer = self.layers[-1]
60+
layer = Layer(self.name + "_" + name, priorLayer.outputs, priorLayer.nbOutputs, nbOutputs, activation)
61+
62+
self.layersDct[name] = layer
63+
self.layers.append(layer)
64+
self.params.extend(layer.params)
65+
66+
def _initUpdates(self) :
67+
self.outputs = self.layers[-1].outputs
68+
self.cost = self.costFct(self.y, self.outputs)
69+
70+
self.updates = []
71+
self.gs = []
72+
for param in self.params :
73+
gparam = tt.grad(self.cost, param)
74+
self.updates.append((param, param - self.lr * gparam))
75+
self.gs.append(gparam)
76+
77+
self.theano_train = theano.function(inputs = [self.inputs, self.y], outputs = [self.cost, self.outputs], updates = self.updates)
78+
self.theano_test = theano.function(inputs = [self.inputs, self.y], outputs = [self.cost, self.outputs])
79+
self.theano_propagate = theano.function(inputs = [self.inputs], outputs = self.outputs)
80+
#~ self.theano_predict = theano.function(inputs = [self.inputs], outputs = tt.argmax(self.outputs))
81+
82+
self._mustInitUpdates = False
83+
84+
def train(self, x, y) :
85+
if self._mustInitUpdates :
86+
self._initUpdates()
87+
88+
return self.theano_train(x, y)
89+
90+
def test(self, x, y) :
91+
"same function for both test and validation"
92+
if self._mustInitUpdates :
93+
self._initUpdates()
94+
return self.theano_test(x, y)
95+
96+
def propagate(self, x) :
97+
if self._mustInitUpdates :
98+
self._initUpdates()
99+
return self.theano_propagate(x)
100+
101+
def predict(self, x) :
102+
if self._mustInitUpdates :
103+
self._initUpdates()
104+
return tt.argmax(self.theano_predict(x))
105+
106+
def L1(self) :
107+
return sum([abs(l.W).sum() for l in self.layers])
108+
109+
def L2(self) :
110+
return sum([(l.W**2).sum() for l in self.layers])
111+
112+
def __getitem__(self, layerName) :
113+
return self.layersDct[layerName]
114+
115+
def __str__(self) :
116+
ls = []
117+
for l in self.layers :
118+
ls.append(l.name)
119+
ls = " -> ".join(ls)
120+
s = "Net: %s (%s)" % (self.name, ls)
121+
return s
122+
123+
def negLogLikelihood(y, outputs) :
124+
"""cost fct for softmax"""
125+
cost = -tt.mean(tt.log(outputs)[tt.arange(y.shape[0]), y])
126+
return cost
127+
128+
def meanSquaredError(y, outputs) :
129+
"""cost fct"""
130+
cost = -tt.mean( tt.dot(outputs, y) **2 )
131+
#~ cost = -tt.mean(outputs - y)
132+
return cost

Mariana/V2/layers.py

Whitespace-only changes.

Mariana/V2/model.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import layers as L
2+
3+
class Model(object) :
4+
5+
def __init__(self,name) :
6+
self.name = name
7+
self.layers = {}
8+
self.inputLayers = {}
9+
10+
def _registerLayer(self, layer) :
11+
if layer.name in layers :
12+
raise KeyError("The model '%s' has already a layer called '%s'" % (self.name, layer.name)
13+
self.layers[layer.name] = layer
14+
if layer.__class__ is L.InputLayer :
15+
self.inputLayers[layer.name] = layer

Mariana/V2/parser.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import json
2+
import layers as L
3+
4+
class MarianaParser(object) :
5+
"parse a json entry to create network"
6+
def __init__(self) :
7+
pass
8+
9+
def parseFile(self, jsonFile) :
10+
f = open(jsonFile)
11+
self.json = json.load(f)
12+
f.close()
13+
model = M.model(self.json['name'])
14+
15+
for jl in jsonLayers :
16+
if jl['function'] == 'input' :
17+
layers.append(L.InputLayer(model = model, **jl))
18+
else :
19+
if jl['function'] == 'hidden' :
20+
layers.append(L.HiddenLayer(model = model, **jl))
21+
elif jl['function'] == 'output' :
22+
layers.append(L.OutputLayer(model = model, **jl))
23+
else :
24+
raise ValueError("Unknown layer function '%s'" % jl['function'])
25+
return model

Mariana/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)