diff linear_regression.py @ 110:8fa1ef2411a0

Worked on OneShotTLearner and implementation of LinearRegression
author bengioy@bengiomac.local
date Tue, 06 May 2008 22:24:55 -0400
parents c4916445e025
children 88257dfedf8c
line wrap: on
line diff
--- a/linear_regression.py	Tue May 06 20:01:34 2008 -0400
+++ b/linear_regression.py	Tue May 06 22:24:55 2008 -0400
@@ -55,50 +55,43 @@
        
        - 'lambda' 
        - 'b' 
-       - 'W' 
-       - 'regularization_term' 
+       - 'W'
+       - 'parameters' = (b, W) tuple
+       - 'regularization_term'
+       - 'XtX'
+       - 'XtY'
 
     """
 
     def attributeNames(self):
-        return ["lambda","b","W","regularization_term"]
-    
+        return ["lambda","parameters","b","W","regularization_term","XtX","XtY"]
+
+    def useInputAttributes(self):
+        return ["b","W"]
+
+    def useOutputAttributes(self):
+        return []
+
+    def updateInputAttributes(self):
+        return ["lambda","XtX","XtY"]
+
+    def updateOutputAttributes(self):
+        return ["parameters"] + self.updateMinibatchOutputAttributes() + self.updateEndOutputAttributes()
 
-    def __init__(self):
-        self.input = t.matrix('input') # n_examples x n_inputs
-        self.target = t.matrix('target') # n_examples x n_outputs
-        self.lambda = as_scalar(0.,'lambda')
-        self.theta = t.matrix('theta')
-        self.W = self.theta[:,1:] 
-        self.b = self.theta[:,0]
-        self.XtX = t.matrix('XtX')
-        self.XtY = t.matrix('XtY')
-        self.regularizer = self.lambda * t.dot(self.W,self.W)
-        self.squared_error = 
-        self.loss = self.regularizer + t.sum(self.squared_error) # this only makes sense if the whole training set fits in memory in a minibatch
-        self.loss_function = Function([self.W,self.lambda,self.squared_error],[self.loss])
-        self.new_XtX = self.XtX + t.dot(self.extended_input.T,self.extended_input)
-        self.new_XtY = self.XtY + t.dot(self.extended_input.T,self.target)
-        self.new_theta = t.solve(self.XtX,self.XtY)
+    def updateMinibatchInputFields(self):
+        return ["input","target"]
+    
+    def updateMinibatchInputAttributes(self):
+        return ["XtX","XtY"]
+    
+    def updateMinibatchOutputAttributes(self):
+        return ["new_XtX","new_XtY"]
+    
+    def updateEndInputAttributes(self):
+        return ["theta","XtX","XtY"]
 
-    def initialize(self):
-        self.XtX.resize((1+self.n_inputs,1+self.n_inputs))
-        self.XtY.resize((1+self.n_inputs,self.n_outputs))
-        self.XtX.data[:,:]=0
-        self.XtY.data[:,:]=0
-        numpy.diag(self.XtX.data)[1:]=self.lambda.data
-        
-    def updated_variables(self):
-    
-    def minibatch_wise_inputs(self):
-    def minibatch_wise_outputs(self):
-        # self.input is a (n_examples, n_inputs) minibatch matrix
-        self.extended_input = t.prepend_one_to_each_row(self.input)
-        self.output = t.dot(self.input,self.W.T) + self.b  # (n_examples , n_outputs) matrix
-        self.squared_error = t.sum_within_rows(t.sqr(self.output-self.target)) # (n_examples ) vector
-
-    def attributeNames(self):
-        return ["lambda","b","W","regularization_term","XtX","XtY"]
+    def updateEndOutputAttributes(self):
+        return ["new_theta","b","W","regularization_term"] # CHECK: WILL b AND W CONTAIN OLD OR NEW THETA? @todo i.e. order of computation = ?
 
     def defaultOutputFields(self, input_fields):
         output_fields = ["output"]
@@ -106,58 +99,49 @@
             output_fields.append("squared_error")
         return output_fields
         
-    # poutine generale basee sur ces fonctions
+    def __init__(self):
+        self._input = t.matrix('input') # n_examples x n_inputs
+        self._target = t.matrix('target') # n_examples x n_outputs
+        self._lambda = as_scalar(0.,'lambda')
+        self._theta = t.matrix('theta')
+        self._W = self._theta[:,1:] 
+        self._b = self._theta[:,0]
+        self._XtX = t.matrix('XtX')
+        self._XtY = t.matrix('XtY')
+        self._extended_input = t.prepend_one_to_each_row(self._input)
+        self._output = t.dot(self._input,self._W.T) + self._b  # (n_examples , n_outputs) matrix
+        self._squared_error = t.sum_within_rows(t.sqr(self._output-self._target)) # (n_examples ) vector
+        self._regularizer = self._lambda * t.dot(self._W,self._W)
+        self._new_XtX = add_inplace(self._XtX,t.dot(self._extended_input.T,self._extended_input))
+        self._new_XtY = add_inplace(self._XtY,t.dot(self._extended_input.T,self._target))
+        self._new_theta = t.solve_inplace(self._theta,self._XtX,self._XtY)
 
-    
-    def __init__(self,lambda=0.,max_memory_use=500):
-        """
-        @type lambda: float
-        @param lambda: regularization coefficient
-        """
-        
-        W=t.matrix('W')
-        # b is a broadcastable row vector (can be replicated into
-        # as many rows as there are examples in the minibach)
-        b=t.row('b')
-        minibatch_input = t.matrix('input') # n_examples x n_inputs
-        minibatch_target = t.matrix('target') # n_examples x n_outputs
-        minibatch_output = t.dot(minibatch_input,W.T) + b  # n_examples x n_outputs
-        lambda = as_scalar(lambda)
-        regularizer = self.lambda * t.dot(W,W)
-        example_squared_error = t.sum_within_rows(t.sqr(minibatch_output-minibatch_target))
-        self.output_function = Function([W,b,minibatch_input],[minibatch_output])
-        self.squared_error_function = Function([minibatch_output,minibatch_target],[self.example_squared_error])
-        self.loss_function = Function([W,squared_error],[self.regularizer + t.sum(self.example_squared_error)])
-        self.W=None
-        self.b=None
-        self.XtX=None
-        self.XtY=None
-        
+        OneShotTLearner.__init__(self)
+        self.allocate()
+            
+    def allocate(self,minibatch):
+        minibatch_n_inputs  = minibatch["input"].shape[1]
+        minibatch_n_outputs = minibatch["target"].shape[1]
+        if not self._n_inputs:
+            self._n_inputs = minibatch_n_inputs 
+            self._n_outputs = minibatch_n_outputs
+            self.XtX = numpy.zeros((1+self._n_inputs,1+self._n_inputs))
+            self.XtY = numpy.zeros((1+self._n_inputs,self._n_outputs))
+            self.theta = numpy.zeros((self._n_outputs,1+self._n_inputs))
+            self.forget()
+        elif self._n_inputs!=minibatch_n_inputs or self._n_outputs!=minibatch_n_outputs:
+            # if the input or target changes dimension on the fly, we forget everything
+            self.forget()
+            
     def forget(self):
-        if self.W:
-            self.XtX *= 0
-            self.XtY *= 0
+        if self._n_inputs and self._n_outputs:
+            self.XtX.resize((1+self.n_inputs,1+self.n_inputs))
+            self.XtY.resize((1+self.n_inputs,self.n_outputs))
+            self.XtX.data[:,:]=0
+            self.XtY.data[:,:]=0
+            numpy.diag(self.XtX.data)[1:]=self.lambda
 
-    def use(self,input_dataset,output_fieldnames=None,copy_inputs=True):
-        input_fieldnames = input_dataset.fieldNames()
-        assert "input" in input_fieldnames
-        if not output_fields:
-            output_fields = ["output"]
-            if "target" in input_fieldnames:
-                output_fields += ["squared_error"]
-        else:
-            if "squared_error" in output_fields or "total_loss" in output_fields:
-                assert "target" in input_fieldnames
+    def updateEnd(self):
+        TLearner.updateEnd(self)
+        self.parameters = (self.W,self.b)
 
-        use_functions = []
-        for output_fieldname in output_fieldnames:
-            if output_fieldname=="output":
-                use_functions.append(self.output_function)
-            elif output_fieldname=="squared_error":
-                use_functions.append(lambda self.output_function)
-    
-        n_examples = len(input_dataset)
-        
-        for minibatch in input_dataset.minibatches(minibatch_size=minibatch_size, allow_odd_last_minibatch=True):
-            use_function(
-