diff mlp.py @ 186:562f308873f0

added ManualNNet
author James Bergstra <bergstrj@iro.umontreal.ca>
date Tue, 13 May 2008 20:10:03 -0400
parents 25d0a0c713da
children ebbb0e749565
line wrap: on
line diff
--- a/mlp.py	Tue May 13 19:37:29 2008 -0400
+++ b/mlp.py	Tue May 13 20:10:03 2008 -0400
@@ -11,6 +11,74 @@
 import math
 from misc import *
 
+def function(inputs, outputs, linker='c&py'):
+    return theano.function(inputs, outputs, unpack_single=False,linker=linker)
+
+def randshape(*shape): return (numpy.random.rand(*shape) -0.5) * 0.001
+
+class ManualNNet(object):
+    def __init__(self, ninputs, nhid, nclass, lr, nepochs, 
+            linker='c&yp', 
+            hidden_layer=None):
+        class Vars:
+            def __init__(self, lr):
+                lr = t.constant(lr)
+                input = t.matrix('input') # n_examples x n_inputs
+                target = t.ivector('target') # n_examples x 1
+                W2 = t.matrix('W2')
+                b2 = t.vector('b2')
+
+                if hidden_layer:
+                    hidden, hidden_params, hidden_ivals = hidden_layer(input)
+                else:
+                    W1 = t.matrix('W1')
+                    b1 = t.vector('b1')
+                    hidden = t.tanh(b1 + t.dot(input, W1))
+                    hidden_params = [W1, b1]
+                    hidden_ivals = [randshape(ninputs, nhid), randshape(nhid)]
+
+                params = [W2, b2] + hidden_params
+                ivals = [randshape(nhid, nclass), randshape(nclass)]\
+                        + hidden_ivals
+                nll, predictions = crossentropy_softmax_1hot( b2 + t.dot(hidden, W2), target)
+                output_class = t.argmax(predictions,1)
+                loss_01 = t.neq(output_class, target)
+                g_params = t.grad(nll, params)
+                new_params = [t.sub_inplace(p, lr * gp) for p,gp in zip(params, g_params)]
+                self.__dict__.update(locals()); del self.self
+        self.nhid = nhid
+        self.nclass = nclass
+        self.nepochs = nepochs
+        self.v = Vars(lr)
+        self.params = None
+
+    def update(self, trainset):
+        params = self.v.ivals
+        update_fn = function(
+                [self.v.input, self.v.target] + self.v.params,
+                [self.v.nll] + self.v.new_params)
+        for i in xrange(self.nepochs):
+            for input, target in trainset.minibatches(['input', 'target'],
+                    minibatch_size=min(32, len(trainset))):
+                dummy = update_fn(input, target[:,0], *params)
+                if 0: print dummy[0] #the nll
+        return self.use
+    __call__ = update
+
+    def use(self, dset,
+            output_fieldnames=['output_class'],
+            test_stats_collector=None,
+            copy_inputs=False,
+            put_stats_in_output_dataset=True,
+            output_attributes=[]):
+        inputs = [self.v.input, self.v.target] + self.v.params
+        fn = function(inputs, [getattr(self.v, name) for name in output_fieldnames])
+        target = dset.fields()['target'] if ('target' in dset.fields()) else numpy.zeros((1,1),dtype='int64')
+        return ApplyFunctionDataSet(dset, 
+            lambda input, target: fn(input, target[:,0], *self.v.ivals),
+            output_fieldnames)
+
+
 class OneHiddenLayerNNetClassifier(OnlineGradientTLearner):
     """
     Implement a straightforward classicial feedforward