changeset 720:0594cba02fa8

Some fixes to FillMissing, and added MaskGradient (another Op to move elsewhere later)
author Olivier Delalleau <delallea@iro>
date Mon, 25 May 2009 23:11:38 -0400
parents 573e3370d0fa
children df3aef87d8d2
files pylearn/sandbox/scan_inputs_groups.py
diffstat 1 files changed, 36 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/pylearn/sandbox/scan_inputs_groups.py	Mon May 25 11:45:37 2009 -0400
+++ b/pylearn/sandbox/scan_inputs_groups.py	Mon May 25 23:11:38 2009 -0400
@@ -568,8 +568,13 @@
     Given an input, output two elements:
         - a copy of the input where missing values (NaN) are replaced by some
         constant (zero by default)
-        - a boolean (actually int8) mask of the same size as input, where each
-        element is True (i.e. 1) iff the corresponding input is not missing
+        - a mask of the same size and type as input, where each element is zero
+        iff the corresponding input is missing
+    Currently, the gradient is computed as if the input value was really zero.
+    It may be safer to replace the gradient w.r.t. missing values with either
+    zeros or missing values (?).
+    ***NOTE*** This is a debug implementation using a special code for missing
+    values (-123456)
     """
 
     def __init__(self, constant_val=0):
@@ -583,7 +588,7 @@
 		return hash(type(self))^hash(self.constant_val)
 	
     def make_node(self, input):
-        return Apply(self, [input], [input.type(), T.bmatrix()])
+        return Apply(self, [input], [input.type(), input.type()])
 
     def perform(self, node, inputs, output_storage):
         input = inputs[0]
@@ -591,15 +596,41 @@
         out[0] = input.copy()
         out = out[0]
         mask = output_storage[1]
-        mask[0] = numpy.ones(input.shape, dtype = numpy.int8)
+        mask[0] = numpy.ones(input.shape)
         mask = mask[0]
         for (idx, v) in numpy.ndenumerate(out):
-            if numpy.isnan(v):
+            if v == -123456:
                 out[idx] = self.constant_val
                 mask[idx] = 0
 
+    def grad(self, inputs, (out_grad, mask_grad, )):
+        return [out_grad]
+
 fill_missing_with_zeros = FillMissing(0)
 
+class MaskGradient(Op):
+    """
+    Takes as input a tensor and a mask. Outputs the same tensor, but setting
+    to zero the gradient for all elements where the mask's value is zero.
+    """
+
+    def __eq__(self, other):
+        return type(self) == type(other)
+
+	def __hash__(self):
+		return hash(type(self))
+	
+    def make_node(self, input, mask):
+        return Apply(self, [input, mask], [input.type()])
+
+    def perform(self, node, (input, mask), (output, )):
+        output[0] = input.copy()
+
+    def grad(self, (input, mask), (out_grad, )):
+        return [out_grad * T.neq(mask, 0), None]
+
+mask_gradient = MaskGradient()
+
 class MaskSelect(Op):
     """
     Given an input x and a mask m (both vectors), outputs a vector that