Beispiel #1
0
    def _re_bound(self,plot_bounding_box,mat,box,density):

        # CEBHACKALERT: for Julien...
        # If plot_bounding_box is that of a Sheet, it will already have been
        # setup so that the density in the x direction and the density in the
        # y direction are equal.
        # If plot_bounding_box comes from elsewhere (i.e. you create it from
        # arbitrary bounds), it might need to be adjusted to ensure the density
        # in both directions is the same (see Sheet.__init__()). I don't know where
        # you want to do that; presumably the code should be common to Sheet and
        # where it's used in the plotting?
        #
        # It's possible we can move some of the functionality
        # into SheetCoordinateSystem.
        if plot_bounding_box.containsbb_exclusive(box):
             ct = SheetCoordinateSystem(plot_bounding_box,density,density)
             new_mat = zeros(ct.shape,Float)
             r1,r2,c1,c2 = Slice(box,ct)
             new_mat[r1:r2,c1:c2] = mat
        else:
             scs = SheetCoordinateSystem(box,density,density)
             s=Slice(plot_bounding_box,scs)
             s.crop_to_sheet(scs)
             new_mat = s.submatrix(mat)

        return new_mat
Beispiel #2
0
    def __init__(self,cf,input_sheet,x=0.0,y=0.0,template=BoundingBox(radius=0.1),
                 mask=patterngenerator.Constant(),
                 min_matrix_radius=1):
        """
        From an existing copy of ConnectionField (CF) that acts as a
        template, create a new CF that shares weights with the
        template CF.  Copies all the properties of CF to stay
        identical except the weights variable that actually contains
        the data.
        
        The only difference from a normal CF is that the weights of
        the CF are implemented as a numpy view into the single master
        copy of the weights stored in the CF template.
        """
        # CEBALERT: There's no call to super's __init__; see JAHACKALERT
        # below.
        template = copy(template)

        if not isinstance(template,Slice):
            template = Slice(template,input_sheet,force_odd=True,
                             min_matrix_radius=min_matrix_radius)

        # Note: if passed in, mask is shared between CFs (but not if created here)
        if not hasattr(mask,'view'):
            mask = _create_mask(patterngenerator.Constant(),
                               template.compute_bounds(input_sheet),
                               input_sheet,True,0.5) 



        self._has_norm_total=False
        self.mask=mask 
        weights_slice = self._create_input_sheet_slice(input_sheet,x,y,template,min_matrix_radius=min_matrix_radius)
        self.weights = weights_slice.submatrix(cf.weights)
Beispiel #3
0
    def __init__(self,cf,input_sheet,x=0.0,y=0.0,template=BoundingBox(radius=0.1),
                 mask=patterngenerator.Constant(),
                 min_matrix_radius=1):
        """
        From an existing copy of ConnectionField (CF) that acts as a
        template, create a new CF that shares weights with the
        template CF.  Copies all the properties of CF to stay
        identical except the weights variable that actually contains
        the data.
        
        The only difference from a normal CF is that the weights of
        the CF are implemented as a numpy view into the single master
        copy of the weights stored in the CF template.
        """
        # CEBALERT: There's no call to super's __init__; see JAHACKALERT
        # below.
        template = copy(template)

        if not isinstance(template,Slice):
            template = Slice(template,input_sheet,force_odd=True,
                             min_matrix_radius=min_matrix_radius)

        # Note: if passed in, mask is shared between CFs (but not if created here)
        if not hasattr(mask,'view'):
            mask = _create_mask(patterngenerator.Constant(),
                               template.compute_bounds(input_sheet),
                               input_sheet,True,0.5) 



        self._has_norm_total=False
        self.mask=mask 
        weights_slice = self._create_input_sheet_slice(input_sheet,x,y,template,min_matrix_radius=min_matrix_radius)
        self.weights = weights_slice.submatrix(cf.weights)
Beispiel #4
0
    def __init__(self, template, input_sheet, projection, **params):
        """
        Initializes the CF object and stores meta information about the CF's
        shape and position in the SparseCFProjection to allow for easier
        initialization.
        """

        super(SparseConnectionField, self).__init__(**params)

        self.input_sheet = input_sheet
        self.projection = projection

        self.matrix_idx = self.projection.dest.sheet2matrixidx(self.x, self.y)
        self.oned_idx = self.matrix_idx[0] * self.projection.dest.shape[
            1] + self.matrix_idx[1]

        template = copy(template)

        if not isinstance(template, Slice):
            template = Slice(template,
                             self.input_sheet,
                             force_odd=True,
                             min_matrix_radius=self.min_matrix_radius)
        self.weights_slice = self._create_input_sheet_slice(template)

        self.src_slice = tuple(self.input_sheet_slice.tolist())
Beispiel #5
0
    def __init__(self,initialize_cfs=True,**params):
        """
        Initialize the Projection with a set of cf_type objects
        (typically SparseConnectionFields), each located at the
        location in the source sheet corresponding to the unit in the
        target sheet. The cf_type objects are stored in the 'cfs'
        array.

        The nominal_bounds_template specified may be altered: the
        bounds must be fitted to the Sheet's matrix, and the weights
        matrix must have odd dimensions. These altered bounds are
        passed to the individual connection fields.

        A mask for the weights matrix is constructed. The shape is
        specified by cf_shape; the size defaults to the size
        of the nominal_bounds_template.
        """

        super(CFProjection,self).__init__(**params)

        self.weights_generator.set_dynamic_time_fn(None,sublistattr='generators')
        # get the actual bounds_template by adjusting a copy of the
        # nominal_bounds_template to ensure an odd slice, and to be
        # cropped to sheet if necessary
        self._slice_template = Slice(copy(self.nominal_bounds_template),
                                     self.src,force_odd=True,
                                     min_matrix_radius=self.min_matrix_radius)

        self.bounds_template = self._slice_template.compute_bounds(self.src)

        self.mask_template = _create_mask(self.cf_shape,self.bounds_template,
                                         self.src,self.autosize_mask,
                                         self.mask_threshold)

        self.n_units = self._calc_n_units()

        self.activity = np.array(self.dest.activity)
        self.norm_total = np.array(self.dest.activity,dtype=np.float64)
        self.has_norm_total = False

        if initialize_cfs:
            self._create_cfs()

        if self.apply_output_fns_init:
            self.apply_learn_output_fns()

        self.input_buffer = None
Beispiel #6
0
    def test_connection_field_like(self):
        # test a ConnectionField-like example
        sheet = Sheet(nominal_density=10,nominal_bounds=BoundingBox(radius=0.5))
        cf_bounds = BoundingBox(points=((0.3,0.3),(0.6,0.6)))

        slice_ = Slice(cf_bounds,sheet)
        slice_.crop_to_sheet(sheet)

        # check it's been cropped to fit onto sheet...
        self.assertEqual(slice_.tolist(),[0,2,8,10])

        # now check that it gives the correct bounds...
        cropped_bounds = slice_.compute_bounds(sheet)
        
        true_cropped_bounds = BoundingBox(points=((0.3,0.3),(0.5,0.5)))
        for a,b in zip(cropped_bounds.lbrt(),true_cropped_bounds.lbrt()):
            self.assertAlmostEqual(a,b)
Beispiel #7
0
    def test_slice2bounds(self):

        # test that if you ask to slice the matrix with the sheet's BoundingBox, you
        # get back the whole matrix
        # (I chose to use a 7 density, I don't know why I like 7 so much, it is kind of mystical)

        sheet_bb = BoundingBox(points=((-0.5, -0.5), (0.5, 0.5)))
        ct = SheetCoordinateSystem(sheet_bb, 7)
        slice_ = (0, 7, 0, 7)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5, -0.5, 0.5, 0.5)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        # for the following tests, the values have been all computed
        # by hand and then tested (by JC). The boundingbox and density
        # tested have been chosen randomly, then drawn to get the slice
        # from it.

        # Test for 10 density
        ct = SheetCoordinateSystem(sheet_bb, 10)
        slice_ = (0, 9, 1, 5)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.4, -0.4, 0, 0.5)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        slice_ = (2, 3, 7, 10)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (0.2, 0.2, 0.5, 0.3)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        # Test for 7 density
        ct = SheetCoordinateSystem(sheet_bb, 7)
        slice_ = (3, 7, 2, 5)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5 + 2.0 / 7.0, -0.5, -0.5 + 5.0 / 7.0, 0.5 - 3.0 / 7.0)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        slice_ = (2, 6, 0, 1)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5, 0.5 - 6.0 / 7.0, -0.5 + 1.0 / 7.0, 0.5 - 2.0 / 7.0)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        # Test for 25 density
        ct = SheetCoordinateSystem(sheet_bb, 25)
        slice_ = (0, 25, 4, 10)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5 + 4.0 / 25.0, -0.5, -0.5 + 10.0 / 25.0, 0.5)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        slice_ = (7, 18, 3, 11)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5 + 3.0 / 25.0, 0.5 - 18.0 / 25.0, -0.5 + 11.0 / 25.0, 0.5 - 7.0 / 25.0)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)
Beispiel #8
0
    def _re_bound(self,plot_bounding_box,mat,box,density):

        # CEBHACKALERT: for Julien...
        # If plot_bounding_box is that of a Sheet, it will already have been
        # setup so that the density in the x direction and the density in the
        # y direction are equal.
        # If plot_bounding_box comes from elsewhere (i.e. you create it from
        # arbitrary bounds), it might need to be adjusted to ensure the density
        # in both directions is the same (see Sheet.__init__()). I don't know where
        # you want to do that; presumably the code should be common to Sheet and
        # where it's used in the plotting?
        #
        # It's possible we can move some of the functionality
        # into SheetCoordinateSystem.
        if plot_bounding_box.containsbb_exclusive(box):
             ct = SheetCoordinateSystem(plot_bounding_box,density,density)
             new_mat = np.zeros(ct.shape,dtype=np.float)
             r1,r2,c1,c2 = Slice(box,ct)
             new_mat[r1:r2,c1:c2] = mat
        else:
             scs = SheetCoordinateSystem(box,density,density)
             s=Slice(plot_bounding_box,scs)
             s.crop_to_sheet(scs)
             new_mat = s.submatrix(mat)

        return new_mat
Beispiel #9
0
    def test_connection_field_like(self):
        # test a ConnectionField-like example
        sheet = Sheet(nominal_density=10,nominal_bounds=BoundingBox(radius=0.5))
        cf_bounds = BoundingBox(points=((0.3,0.3),(0.6,0.6)))

        slice_ = Slice(cf_bounds,sheet)
        slice_.crop_to_sheet(sheet)

        # check it's been cropped to fit onto sheet...
        self.assertEqual(slice_.tolist(),[0,2,8,10])

        # now check that it gives the correct bounds...
        cropped_bounds = slice_.compute_bounds(sheet)

        true_cropped_bounds = BoundingBox(points=((0.3,0.3),(0.5,0.5)))
        for a,b in zip(cropped_bounds.lbrt(),true_cropped_bounds.lbrt()):
            self.assertAlmostEqual(a,b)
Beispiel #10
0
class SparseCFProjection(CFProjection):
    """
    A projection composed of SparseConnectionFields from a Sheet into
    a ProjectionSheet.

    SparseCFProjection computes its activity using a response_fn which
    can either be an optimized function implemented as part of the
    sparse matrix class or an unoptimized function, which requests the
    weights in dense format.  The initial contents of the
    SparseConnectionFields mapping from the input Sheet into the
    target ProjectionSheet are controlled by the weights_generator,
    cf_shape, and weights_output_fn parameters, while the location of
    the ConnectionField is controlled by the coord_mapper parameter.

    Any subclass has to implement the interface activate(self) that
    computes the response from the input and stores it in the activity
    array.
    """

    cf_type = param.Parameter(default=SparseConnectionField,doc="""
        Type of ConnectionField to use when creating individual CFs.""")

    learning_fn = param.Callable(default=CFPLF_Hebbian_Sparse,doc="""
        Function for computing changes to the weights based on one activation step.""")

    response_fn = param.Callable(default=CFPRF_DotProduct_Sparse,doc="""
        Function for computing the Projection response to an input pattern.""")

    weights_output_fns = param.HookList(default=[CFPOF_DivisiveNormalizeL1_Sparse],doc="""
        Functions applied to each CF after learning.""")

    initialized = param.Boolean(default=False)


    def __init__(self,initialize_cfs=True,**params):
        """
        Initialize the Projection with a set of cf_type objects
        (typically SparseConnectionFields), each located at the
        location in the source sheet corresponding to the unit in the
        target sheet. The cf_type objects are stored in the 'cfs'
        array.

        The nominal_bounds_template specified may be altered: the
        bounds must be fitted to the Sheet's matrix, and the weights
        matrix must have odd dimensions. These altered bounds are
        passed to the individual connection fields.

        A mask for the weights matrix is constructed. The shape is
        specified by cf_shape; the size defaults to the size
        of the nominal_bounds_template.
        """

        super(CFProjection,self).__init__(**params)

        self.weights_generator.set_dynamic_time_fn(None,sublistattr='generators')
        # get the actual bounds_template by adjusting a copy of the
        # nominal_bounds_template to ensure an odd slice, and to be
        # cropped to sheet if necessary
        self._slice_template = Slice(copy(self.nominal_bounds_template),
                                     self.src,force_odd=True,
                                     min_matrix_radius=self.min_matrix_radius)

        self.bounds_template = self._slice_template.compute_bounds(self.src)

        self.mask_template = _create_mask(self.cf_shape,self.bounds_template,
                                         self.src,self.autosize_mask,
                                         self.mask_threshold)

        self.n_units = self._calc_n_units()

        self.activity = np.array(self.dest.activity)
        self.norm_total = np.array(self.dest.activity,dtype=np.float64)
        self.has_norm_total = False

        if initialize_cfs:
            self._create_cfs()

        self.input_buffer = None


    def __getstate__(self):
        """
        Method to support pickling of sparse weights object.
        """

        state_dict = self.__dict__.copy()
        state_dict['triplets'] = state_dict['weights'].getTriplets()
        state_dict['weight_shape'] = (self.src.activity.shape,self.dest.activity.shape)
        del state_dict['weights']
        return state_dict


    def __setstate__(self,state_dict):
        """
        Method to support unpickling of sparse weights object.
        """

        self.__dict__.update(state_dict)
        self.weights = sparse.csarray_float(self.weight_shape[0],self.weight_shape[1])
        rowInds, colInds, values = self.triplets
        self.weights.setTriplets(rowInds,colInds,values)
        del self.triplets
        del self.weight_shape


    def _create_cfs(self):
        """
        Creates the CF objects, initializing the weights one by one
        and adding them to the sparse weights object in chunks.
        """

        vectorized_create_cf = simple_vectorize(self._create_cf)
        self.cfs = vectorized_create_cf(*self._generate_coords())
        self.flatcfs = list(self.cfs.flat)
        self.weights = sparse.csarray_float(self.src.activity.shape,self.dest.activity.shape)

        cf_x,cf_y = self.dest.activity.shape
        src_x,src_y = self.src.activity.shape

        y_array = np.zeros((src_x*src_y*cf_y),dtype=np.int32)
        x_array = np.zeros((src_x*src_y*cf_y),dtype=np.int32)
        val_array = np.zeros((src_x*src_y*cf_y),dtype=np.float32)

        # Iterate over the CFs
        for x in range(cf_x):
            temp_sparse = sparse.csarray_float(self.src.activity.shape,self.dest.activity.shape)
            idx = 0
            for y in range(cf_y):
                x1,x2,y1,y2 = self.cfs[x][y].input_sheet_slice.tolist()
                if self.same_cf_shape_for_all_cfs:
                    mask_template = self.mask_template
                else:
                    mask_template = _create_mask(self.cf_shape,self.bounds_template,
                                                 self.src,self.autosize_mask,
                                                 self.mask_threshold)
                weights = self.cfs[x][y]._init_weights(mask_template)
                cn_x,cn_y = weights.shape
                y_val = x * cf_y + y
                for cnx in range(cn_x):
                    val_array[idx:idx+cn_y] = weights[cnx,:]
                    x_val = (x1+cnx) * src_y + y1
                    x_array[idx:idx+cn_y] = range(x_val,x_val+cn_y)
                    y_array[idx:idx+cn_y] = y_val
                    idx += cn_y
            nnz_idx = val_array.nonzero()
            temp_sparse.setTriplets(x_array[nnz_idx],y_array[nnz_idx],val_array[nnz_idx])
            self.weights += temp_sparse
            x_array *= 0; y_array *= 0; val_array *= 0.0
        del temp_sparse
        self.weights.compress()
        self.apply_learn_output_fns()
        print self.name , "loaded"


    def _create_cf(self,x,y):
        """
        Create a ConnectionField at x,y in the src sheet.
        """

        try:
            CF = self.cf_type(template=self._slice_template,projection=self,input_sheet=self.src,x=x,y=y,
                              weights_generator=self.weights_generator,
                              min_matrix_radius=self.min_matrix_radius)
        except NullCFError:
            if self.allow_null_cfs:
                CF = None
            else:
                raise

        return CF


    def activate(self,input_activity):
        """Activate using the specified response_fn and output_fn."""
        if self.input_fns:
            input_activity = input_activity.copy()
        for iaf in self.input_fns:
            iaf(input_activity)
        self.input_buffer = input_activity
        self.activity *=0.0
        self.response_fn(self)
        for of in self.output_fns:
            of(self.activity)


    def learn(self):
        """
        For a SparseCFProjection, learn consists of calling the learning_fn.
        """
        # Learning is performed if the input_buffer has already been set,
        # i.e. there is an input to the Projection.
        if self.input_buffer != None:
            self.learning_fn(self)


    def apply_learn_output_fns(self,active_units_mask=True):
        """
        Apply the weights_output_fns to each unit.
        """
        for of in self.weights_output_fns: of(self)


    def n_bytes(self):
        """
        Estimates the size on the basis of the number non-zeros in the
        sparse matrix, asssuming indices and values are stored using
        32-bit integers and floats respectively.
        """
        return self.n_conns() * (3 * 4)


    def n_conns(self):
        """
        Returns number of nonzero weights.
        """
        return self.weights.getnnz()
Beispiel #11
0
    def test_slice2bounds(self):

        # test that if you ask to slice the matrix with the sheet's BoundingBox, you
        # get back the whole matrix
        # (I chose to use a 7 density, I don't know why I like 7 so much, it is kind of mystical)

        sheet_bb = BoundingBox(points=((-0.5, -0.5), (0.5, 0.5)))
        ct = SheetCoordinateSystem(sheet_bb, 7)
        slice_ = (0, 7, 0, 7)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5, -0.5, 0.5, 0.5)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        # for the following tests, the values have been all computed
        # by hand and then tested (by JC). The boundingbox and density
        # tested have been chosen randomly, then drawn to get the slice
        # from it.

        # Test for 10 density
        ct = SheetCoordinateSystem(sheet_bb, 10)
        slice_ = (0, 9, 1, 5)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.4, -0.4, 0, 0.5)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        slice_ = (2, 3, 7, 10)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (0.2, 0.2, 0.5, 0.3)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        # Test for 7 density
        ct = SheetCoordinateSystem(sheet_bb, 7)
        slice_ = (3, 7, 2, 5)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5 + 2.0 / 7.0, -0.5, -0.5 + 5.0 / 7.0,
                            0.5 - 3.0 / 7.0)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        slice_ = (2, 6, 0, 1)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5, 0.5 - 6.0 / 7.0, -0.5 + 1.0 / 7.0,
                            0.5 - 2.0 / 7.0)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        # Test for 25 density
        ct = SheetCoordinateSystem(sheet_bb, 25)
        slice_ = (0, 25, 4, 10)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5 + 4.0 / 25.0, -0.5, -0.5 + 10.0 / 25.0, 0.5)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)

        slice_ = (7, 18, 3, 11)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        true_bounds_lbrt = (-0.5 + 3.0 / 25.0, 0.5 - 18.0 / 25.0,
                            -0.5 + 11.0 / 25.0, 0.5 - 7.0 / 25.0)
        for a, b in zip(bounds.lbrt(), true_bounds_lbrt):
            self.assertAlmostEqual(a, b)
Beispiel #12
0
    def test_bounds2slice(self):

        # test that if you ask to slice the matrix with the sheet's BoundingBox, you
        # get back the whole matrix
        sheet_bb = BoundingBox(points=((-0.5, -0.5), (0.5, 0.5)))
        ct = SheetCoordinateSystem(sheet_bb, 10)

        slice_ = Slice(sheet_bb, ct)
        true_slice = (0, 10, 0, 10
                      )  # inclusive left boundary, exclusive right boundary
        self.assertEqual(tuple(slice_.tolist()), true_slice)

        # for the following tests, the values have been all computed by hand and then
        # tested (by JC). The boundingbox and density tested have been chosen randomly,
        # then drawn to get the slice from it.

        # Test with 20 density.
        ct = SheetCoordinateSystem(sheet_bb, 20, 20)
        bb = BoundingBox(points=((-0.05, -0.20), (0.20, 0.05)))
        slice_ = Slice(bb, ct)

        true_slice = (9, 14, 9, 14)
        self.assertEqual(tuple(slice_.tolist()), true_slice)

        bb = BoundingBox(points=((-0.40, 0), (-0.30, 0.30)))
        slice_ = Slice(bb, ct)
        true_slice = (4, 10, 2, 4)
        self.assertEqual(tuple(slice_.tolist()), true_slice)

        bb = BoundingBox(points=((0.15, 0.10), (0.30, 0.30)))
        slice_ = Slice(bb, ct)
        true_slice = (4, 8, 13, 16)
        self.assertEqual(tuple(slice_.tolist()), true_slice)

        bb = BoundingBox(points=((-0.05, -0.45), (0.10, -0.25)))
        slice_ = Slice(bb, ct)
        true_slice = (15, 19, 9, 12)
        self.assertEqual(tuple(slice_.tolist()), true_slice)

        # test with 7 density sheet.

        bb = BoundingBox(points=((-0.5 + 2.0 / 7.0, 0.5 - 2.0 / 7.0),
                                 (-0.5 + 4.0 / 7.0, 0.5)))
        ct = SheetCoordinateSystem(sheet_bb, 7)

        slice_ = Slice(bb, ct)
        true_slice = (0, 2, 2, 4)
        self.assertEqual(tuple(slice_.tolist()), true_slice)

        #(4x4 matrix)
        ct = SheetCoordinateSystem(BoundingBox(radius=0.2),
                                   xdensity=10,
                                   ydensity=10)
        test_bounds = BoundingBox(radius=0.1)
        slice_ = Slice(test_bounds, ct)
        r1, r2, c1, c2 = slice_
        self.assertEqual((r1, r2, c1, c2), (1, 3, 1, 3))
Beispiel #13
0
    def test_slice2bounds_bounds2slice(self):

        bb = BoundingBox(points=((-0.5, -0.5), (0.5, 0.5)))
        ct = SheetCoordinateSystem(bb, 10)

        slice_ = (0, 3, 7, 8)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)

        slice_ = (4, 7, 8, 10)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)

        slice_ = (2, 3, 4, 8)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)

        slice_ = (0, 3, 9, 10)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)

        bb = BoundingBox(points=((-0.75, -0.5), (0.75, 0.5)))
        ct = SheetCoordinateSystem(bb, 20, 20)

        slice_ = (9, 14, 27, 29)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)

        slice_ = (0, 6, 0, 7)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)

        slice_ = (6, 10, 11, 29)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)

        bb = BoundingBox(points=((-0.5, -0.5), (0.5, 0.5)))
        ct = SheetCoordinateSystem(bb, 7)

        slice_ = (4, 7, 2, 3)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)

        slice_ = (0, 7, 0, 7)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_, ct))
        test_slice = Slice(bounds, ct)

        for a, b in zip(slice_, test_slice):
            self.assertEqual(a, b)
Beispiel #14
0
    def test_bounds2slice(self):
        
        # test that if you ask to slice the matrix with the sheet's BoundingBox, you
        # get back the whole matrix
        sheet_bb = BoundingBox(points=((-0.5,-0.5),(0.5,0.5)))
        ct = SheetCoordinateSystem(sheet_bb,10)
        
        slice_ = Slice(sheet_bb,ct)
        true_slice = (0,10,0,10) # inclusive left boundary, exclusive right boundary
        self.assertEqual(tuple(slice_.tolist()),true_slice) 

        # for the following tests, the values have been all computed by hand and then
        # tested (by JC). The boundingbox and density tested have been chosen randomly,
        # then drawn to get the slice from it.
       
        # Test with 20 density. 
        ct = SheetCoordinateSystem(sheet_bb,20,20)
        bb = BoundingBox(points=((-0.05,-0.20),(0.20,0.05)))
        slice_ = Slice(bb,ct)

        true_slice = (9,14,9,14) 
        self.assertEqual(tuple(slice_.tolist()),true_slice)

        bb = BoundingBox(points=((-0.40,0),(-0.30,0.30)))
        slice_ = Slice(bb,ct)
        true_slice = (4,10,2,4) 
        self.assertEqual(tuple(slice_.tolist()),true_slice)

        bb = BoundingBox(points=((0.15,0.10),(0.30,0.30)))
        slice_ = Slice(bb,ct)
        true_slice = (4,8,13,16) 
        self.assertEqual(tuple(slice_.tolist()),true_slice)

        bb = BoundingBox(points=((-0.05,-0.45),(0.10,-0.25)))
        slice_ = Slice(bb,ct)
        true_slice = (15,19,9,12) 
        self.assertEqual(tuple(slice_.tolist()),true_slice)
        
        # test with 7 density sheet.
        
        bb = BoundingBox(points=((-0.5+2.0/7.0,0.5-2.0/7.0),(-0.5+4.0/7.0,0.5)))
        ct = SheetCoordinateSystem(sheet_bb,7)
        
        slice_ = Slice(bb,ct)
        true_slice = (0,2,2,4) 
        self.assertEqual(tuple(slice_.tolist()),true_slice)

        #(4x4 matrix)
        ct = SheetCoordinateSystem(BoundingBox(radius=0.2),xdensity=10,ydensity=10)
        test_bounds = BoundingBox(radius=0.1)
        slice_=Slice(test_bounds,ct)
        r1,r2,c1,c2 = slice_
        self.assertEqual((r1,r2,c1,c2),(1,3,1,3))
Beispiel #15
0
    def test_slice2bounds_bounds2slice(self):

        bb = BoundingBox(points=((-0.5,-0.5),(0.5,0.5)))
        ct = SheetCoordinateSystem(bb,10)

        slice_ =(0,3,7,8)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)

        slice_ =(4,7,8,10)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)

        slice_ =(2,3,4,8)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)

        slice_ =(0,3,9,10)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)

        bb = BoundingBox(points=((-0.75,-0.5),(0.75,0.5)))
        ct = SheetCoordinateSystem(bb,20,20)

        slice_ =(9,14,27,29)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)

        slice_ =(0,6,0,7)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)

        slice_ =(6,10,11,29)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)

        bb = BoundingBox(points=((-0.5,-0.5),(0.5,0.5)))
        ct = SheetCoordinateSystem(bb,7)

        slice_ =(4,7,2,3)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)

        slice_ =(0,7,0,7)
        bounds = BoundingBox(points=Slice._slicespec2boundsspec(slice_,ct))
        test_slice = Slice(bounds,ct)

        for a,b in zip(slice_,test_slice):
            self.assertEqual(a,b)
Beispiel #16
0
class SparseCFProjection(CFProjection):
    """
    A projection composed of SparseConnectionFields from a Sheet into
    a ProjectionSheet.

    SparseCFProjection computes its activity using a response_fn which
    can either be an optimized function implemented as part of the
    sparse matrix class or an unoptimized function, which requests the
    weights in dense format.  The initial contents of the
    SparseConnectionFields mapping from the input Sheet into the
    target ProjectionSheet are controlled by the weights_generator,
    cf_shape, and weights_output_fn parameters, while the location of
    the ConnectionField is controlled by the coord_mapper parameter.

    Any subclass has to implement the interface activate(self) that
    computes the response from the input and stores it in the activity
    array.
    """

    cf_type = param.Parameter(default=SparseConnectionField,doc="""
        Type of ConnectionField to use when creating individual CFs.""")

    learning_fn = param.Callable(default=CFPLF_Hebbian_Sparse,doc="""
        Function for computing changes to the weights based on one activation step.""")

    response_fn = param.Callable(default=CFPRF_DotProduct_Sparse,doc="""
        Function for computing the Projection response to an input pattern.""")

    weights_output_fns = param.HookList(default=[CFPOF_DivisiveNormalizeL1_Sparse],doc="""
        Functions applied to each CF after learning.""")

    initialized = param.Boolean(default=False)


    def __init__(self,initialize_cfs=True,**params):
        """
        Initialize the Projection with a set of cf_type objects
        (typically SparseConnectionFields), each located at the
        location in the source sheet corresponding to the unit in the
        target sheet. The cf_type objects are stored in the 'cfs'
        array.

        The nominal_bounds_template specified may be altered: the
        bounds must be fitted to the Sheet's matrix, and the weights
        matrix must have odd dimensions. These altered bounds are
        passed to the individual connection fields.

        A mask for the weights matrix is constructed. The shape is
        specified by cf_shape; the size defaults to the size
        of the nominal_bounds_template.
        """

        super(CFProjection,self).__init__(**params)

        self.weights_generator.set_dynamic_time_fn(None,sublistattr='generators')
        # get the actual bounds_template by adjusting a copy of the
        # nominal_bounds_template to ensure an odd slice, and to be
        # cropped to sheet if necessary
        self._slice_template = Slice(copy(self.nominal_bounds_template),
                                     self.src,force_odd=True,
                                     min_matrix_radius=self.min_matrix_radius)

        self.bounds_template = self._slice_template.compute_bounds(self.src)

        self.mask_template = _create_mask(self.cf_shape,self.bounds_template,
                                         self.src,self.autosize_mask,
                                         self.mask_threshold)

        self.n_units = self._calc_n_units()

        self.activity = np.array(self.dest.activity)
        self.norm_total = np.array(self.dest.activity,dtype=np.float64)
        self.has_norm_total = False

        if initialize_cfs:
            self._create_cfs()

        if self.apply_output_fns_init:
            self.apply_learn_output_fns()

        self.input_buffer = None


    def __getstate__(self):
        """
        Method to support pickling of sparse weights object.
        """

        state_dict = self.__dict__.copy()
        state_dict['triplets'] = state_dict['weights'].getTriplets()
        state_dict['weight_shape'] = (self.src.activity.shape,self.dest.activity.shape)
        del state_dict['weights']
        return state_dict


    def __setstate__(self,state_dict):
        """
        Method to support unpickling of sparse weights object.
        """

        self.__dict__.update(state_dict)
        self.weights = sparse.csarray_float(self.weight_shape[0],self.weight_shape[1])
        rowInds, colInds, values = self.triplets
        self.weights.setTriplets(rowInds,colInds,values)
        del self.triplets
        del self.weight_shape


    def _create_cfs(self):
        """
        Creates the CF objects, initializing the weights one by one
        and adding them to the sparse weights object in chunks.
        """

        vectorized_create_cf = simple_vectorize(self._create_cf)
        self.cfs = vectorized_create_cf(*self._generate_coords())
        self.flatcfs = list(self.cfs.flat)
        self.weights = sparse.csarray_float(self.src.activity.shape,self.dest.activity.shape)

        cf_x,cf_y = self.dest.activity.shape
        src_x,src_y = self.src.activity.shape

        y_array = np.zeros((src_x*src_y*cf_y),dtype=np.int32)
        x_array = np.zeros((src_x*src_y*cf_y),dtype=np.int32)
        val_array = np.zeros((src_x*src_y*cf_y),dtype=np.float32)

        # Iterate over the CFs
        for x in range(cf_x):
            temp_sparse = sparse.csarray_float(self.src.activity.shape,self.dest.activity.shape)
            idx = 0
            for y in range(cf_y):
                cf = self.cfs[x][y]
                label = cf.label + ('-%d' % self.seed if self.seed is not None else '')
                name = "%s_CF (%.5f, %.5f)" % ('' if label is None else label, cf.x,cf.y)
                x1,x2,y1,y2 = cf.input_sheet_slice.tolist()
                if self.same_cf_shape_for_all_cfs:
                    mask_template = self.mask_template
                else:
                    mask_template = _create_mask(self.cf_shape,self.bounds_template,
                                                 self.src,self.autosize_mask,
                                                 self.mask_threshold, name=name)
                weights = self.cfs[x][y]._init_weights(mask_template)
                cn_x,cn_y = weights.shape
                y_val = x * cf_y + y
                for cnx in range(cn_x):
                    val_array[idx:idx+cn_y] = weights[cnx,:]
                    x_val = (x1+cnx) * src_y + y1
                    x_array[idx:idx+cn_y] = range(x_val,x_val+cn_y)
                    y_array[idx:idx+cn_y] = y_val
                    idx += cn_y
            nnz_idx = val_array.nonzero()
            temp_sparse.setTriplets(x_array[nnz_idx],y_array[nnz_idx],val_array[nnz_idx])
            self.weights += temp_sparse
            x_array *= 0; y_array *= 0; val_array *= 0.0
        del temp_sparse
        self.weights.compress()
        self.debug("Sparse projection %r loaded" % self.name)


    def _create_cf(self,x,y):
        """
        Create a ConnectionField at x,y in the src sheet.
        """

        label = self.hash_format.format(name=self.name,
                                        src=self.src.name,
                                        dest=self.dest.name)
        try:
            CF = self.cf_type(template=self._slice_template,
                              projection=self,input_sheet=self.src,x=x,y=y,
                              weights_generator=self.weights_generator,
                              min_matrix_radius=self.min_matrix_radius,
                              label=label)
        except NullCFError:
            if self.allow_null_cfs:
                CF = None
            else:
                raise

        return CF

    def get_sheet_mask(self):
        return np.ones(self.activity.shape, dtype=self.activity.dtype)

    def get_active_units_mask(self):
        return np.ones(self.activity.shape, dtype=self.activity.dtype)


    def activate(self,input_activity):
        """Activate using the specified response_fn and output_fn."""
        if self.input_fns:
            input_activity = input_activity.copy()
        for iaf in self.input_fns:
            iaf(input_activity)
        self.input_buffer = input_activity
        self.activity *=0.0
        self.response_fn(self)
        for of in self.output_fns:
            of(self.activity)


    def learn(self):
        """
        For a SparseCFProjection, learn consists of calling the learning_fn.
        """
        # Learning is performed if the input_buffer has already been set,
        # i.e. there is an input to the Projection.
        if self.input_buffer is not None:
            self.learning_fn(self)


    def apply_learn_output_fns(self,active_units_mask=True):
        """
        Apply the weights_output_fns to each unit.
        """
        for of in self.weights_output_fns: of(self)


    def n_bytes(self):
        """
        Estimates the size on the basis of the number non-zeros in the
        sparse matrix, asssuming indices and values are stored using
        32-bit integers and floats respectively.
        """
        return self.n_conns() * (3 * 4)


    def n_conns(self):
        """
        Returns number of nonzero weights.
        """
        return self.weights.getnnz()