Package topo :: Package learningfn :: Module som
[hide private]
[frames] | no frames]

Source Code for Module topo.learningfn.som

  1  """ 
  2  SOM-based learning functions for CFProjections. 
  3   
  4  $Id: som.py 11316 2010-07-27 17:52:53Z ceball $ 
  5  """ 
  6  __version__ = "$Revision: 11316 $" 
  7   
  8   
  9  from math import ceil 
 10   
 11  import param 
 12   
 13  from topo.base.arrayutil import L2norm, array_argmax 
 14  from topo.base.boundingregion import BoundingBox 
 15  from topo.base.cf import CFPLearningFn 
 16  from topo.base.patterngenerator import PatternGenerator 
 17       
 18  from topo.pattern.basic import Gaussian 
 19   
 20   
 21  ### JABHACKALERT: This class will be removed once the examples no 
 22  ### longer rely upon it 
23 -class CFPLF_SOM(CFPLearningFn):
24 """ 25 An abstract base class of learning functions for Self-Organizing Maps. 26 27 This implementation is obsolete and will be removed soon. 28 Please see examples/cfsom_or.ty for current SOM support. 29 """ 30 __abstract = True 31 32 learning_radius = param.Number(default=0.0,doc= 33 """ 34 The radius of the neighborhood function to be used for 35 learning. Typically, this value will be set by the Sheet or 36 Projection owning this CFPLearningFn, but it can also be set 37 explicitly by the user. 38 """) 39
40 - def __init__(self,**params):
41 self.warning("CFPLF_SOM is deprecated -- see the example in cfsom_or.ty for how to build a SOM")
42
43 - def __call__(self, proj, input_activity, output_activity, learning_rate, **params):
44 raise NotImplementedError
45 46 47 48 ### JABHACKALERT: This class will be removed once the examples no 49 ### longer rely upon it
50 -class CFPLF_HebbianSOM(CFPLF_SOM):
51 """ 52 Hebbian learning rule for CFProjections to Self-Organizing Maps. 53 54 This implementation is obsolete and will be removed soon. 55 Please see examples/cfsom_or.ty for current SOM support. 56 """ 57 58 learning_radius = param.Number(default=0.0) 59 60 crop_radius_multiplier = param.Number(default=3.0,doc= 61 """ 62 Factor by which the radius should be multiplied, 63 when deciding how far from the winner to keep updating the weights. 64 """) 65 66 neighborhood_kernel_generator = param.ClassSelector(PatternGenerator, 67 default=Gaussian(x=0.0,y=0.0,aspect_ratio=1.0), 68 doc="Neighborhood function") 69 70
71 - def __call__(self, iterator, input_activity, output_activity, learning_rate, **params):
72 cfs = iterator.proj.cfs.tolist() # CEBALERT: convert to use flatcfs 73 rows,cols = output_activity.shape 74 75 # This learning function does not need to scale the learning 76 # rate like some do, so it does not use constant_sum_connection_rate() 77 single_connection_learning_rate = learning_rate 78 79 ### JABALERT: The learning_radius is normally set by 80 ### the learn() function of CFSOM, so it doesn't matter 81 ### much that the value accepted here is in matrix and 82 ### not sheet coordinates. It's confusing that anything 83 ### would accept matrix coordinates, but the learning_fn 84 ### doesn't have access to the sheet, so it can't easily 85 ### convert from sheet coords. 86 radius = self.learning_radius 87 crop_radius = max(1.25,radius*self.crop_radius_multiplier) 88 89 # find out the matrix coordinates of the winner 90 # 91 # NOTE: when there are multiple projections, it would be 92 # slightly more efficient to calculate the winner coordinates 93 # within the Sheet, e.g. by moving winner_coords() to CFSOM 94 # and passing in the results here. However, finding the 95 # coordinates does not take much time, and requiring the 96 # winner to be passed in would make it harder to mix and match 97 # Projections and learning rules with different Sheets. 98 wr,wc = array_argmax(output_activity) 99 100 # Optimization: Calculate the bounding box around the winner 101 # in which weights will be changed, to avoid considering those 102 # units below. 103 cmin = int(max(wc-crop_radius,0)) 104 cmax = int(min(wc+crop_radius+1,cols)) # at least 1 between cmin and cmax 105 rmin = int(max(wr-crop_radius,0)) 106 rmax = int(min(wr+crop_radius+1,rows)) 107 108 # generate the neighborhood kernel matrix so that the values 109 # can be read off easily using matrix coordinates. 110 nk_generator = self.neighborhood_kernel_generator 111 radius_int = int(ceil(crop_radius)) 112 rbound = radius_int + 0.5 113 bb = BoundingBox(points=((-rbound,-rbound), (rbound,rbound))) 114 115 # Print parameters designed to match fm2d's output 116 #print "%d rad= %d std= %f alpha= %f" % (topo.sim._time, radius_int, radius, single_connection_learning_rate) 117 118 neighborhood_matrix = nk_generator(bounds=bb,xdensity=1,ydensity=1, 119 size=2*radius) 120 121 for r in range(rmin,rmax): 122 for c in range(cmin,cmax): 123 cwc = c - wc 124 rwr = r - wr 125 lattice_dist = L2norm((cwc,rwr)) 126 if lattice_dist <= crop_radius: 127 cf = cfs[r][c] 128 rate = single_connection_learning_rate * neighborhood_matrix[rwr+radius_int,cwc+radius_int] 129 X = cf.get_input_matrix(input_activity) 130 cf.weights += rate * (X - cf.weights) 131 132 # CEBHACKALERT: see ConnectionField.__init__() 133 cf.weights *= cf.mask
134