class CFSPRF_Plugin(param.Parameterized): """ Generic large-scale response function based on a simple single-CF function. Applies the single_cf_fn to each CF in turn. For the default single_cf_fn of DotProduct(), does a basic dot product of each CF with the corresponding slice of the input array. This function is likely to be slow to run, but it is easy to extend with any arbitrary single-CF response function. The single_cf_fn must be a function f(X,W) that takes two identically shaped matrices X (the input) and W (the CF weights) and computes a scalar activation value based on those weights. """ single_cf_fn = param.ClassSelector(ResponseFn, default=DotProduct(), doc=""" Accepts a ResponseFn that will be applied to each CF individually.""") def __call__(self, projection, **params): single_cf_fn = self.single_cf_fn for i, cf in enumerate(projection.flatcfs): X = cf.input_sheet_slice.submatrix(projection.src.activity) projection.activity.flat[i] = single_cf_fn(X, cf.weights) projection.activity *= projection.strength
class CFPRF_DotProduct_cython(CFPRF_Plugin): """ Wrapper written to allow transparent non-optimized fallback; equivalent to CFPRF_Plugin(single_cf_fn=DotProduct()). """ single_cf_fn = param.ClassSelector(ResponseFn, DotProduct(),readonly=True) def __init__(self,**params): super(CFPRF_DotProduct_cython,self).__init__(**params)
class CFPRF_ActivityBased(CFPResponseFn): """ Calculate the activity of each unit nonlinearly based on the input activity. The activity is calculated from the input activity, the weights, and a strength that is a function of the input activity. This allows connections to have either an excitatory or inhibitory effect, depending on the activity entering the unit in question. The strength function is a generalized logistic curve (Richards' curve), a flexible function for specifying a nonlinear growth curve:: y = l + ( u /(1 + b exp(-r (x - 2m)) ^ (1 / b)) ) This function has five parameters:: * l: the lower asymptote, i.e. the value at infinity; * u: the upper asymptote minus l, i.e. (u + l) is the value at minus infinity; * m: the time of maximum growth; * r: the growth rate; * b: affects near which asymptote maximum growth occurs. Richards, F.J. 1959 A flexible growth function for empirical use. J. Experimental Botany 10: 290--300, 1959. http://en.wikipedia.org/wiki/Generalised_logistic_curve """ l = param.Number(default=-1.3, doc="Value at infinity") u = param.Number(default=1.2, doc="(u + l) is the value at minus infinity") m = param.Number(default=0.25, doc="Time of maximum growth.") r = param.Number(default=-200, doc="Growth rate, controls the gradient") b = param.Number(default=2, doc="Controls position of maximum growth") single_cf_fn = param.ClassSelector(ResponseFn, default=DotProduct(), doc=""" ResponseFn to apply to each CF individually.""") def __call__(self, iterator, input_activity, activity, strength): single_cf_fn = self.single_cf_fn normalize_factor = max(input_activity.flat) for cf, r, c in iterator(): r1, r2, c1, c2 = cf.input_sheet_slice X = input_activity[r1:r2, c1:c2] avg_activity = sum(X.flat) / len(X.flat) x = avg_activity / normalize_factor strength_fn = self.l + ( self.u / (1 + exp(-self.r * (x - 2 * self.m)))**(1.0 / self.b)) activity[r, c] = single_cf_fn(X, cf.weights) activity[r, c] *= strength_fn
class CFPRF_DotProduct_opt(CFPResponseFn): """ Dot-product response function. Written in C for a manyfold speedup; see CFPRF_DotProduct for an easier-to-read version in Python. The unoptimized Python version is equivalent to this one, but it also works for 1D arrays. """ single_cf_fn = param.ClassSelector(ResponseFn, DotProduct(), readonly=True) def __call__(self, iterator, input_activity, activity, strength, **params): temp_act = activity # pyflakes:ignore (passed to weave C code) irows, icols = input_activity.shape X = input_activity.ravel() # pyflakes:ignore (passed to weave C code) cfs = iterator.flatcfs num_cfs = len(cfs) # pyflakes:ignore (passed to weave C code) mask = iterator.mask.data # pyflakes:ignore (passed to weave C code) cf_type = iterator.cf_type # pyflakes:ignore (passed to weave C code) # Note: no performance hit from array indexing of mask and # temp_act (r11447). code = c_header + """ DECLARE_SLOT_OFFSET(weights,cf_type); DECLARE_SLOT_OFFSET(input_sheet_slice,cf_type); %(cfs_loop_pragma)s for (int r=0; r<num_cfs; ++r) { if(mask[r] == 0.0) { temp_act[r] = 0; } else { PyObject *cf = PyList_GetItem(cfs,r); // CONTIGUOUS_ARRAY_FROM_SLOT_OFFSET(float,weights,cf) <<<<<<<<<<< LOOKUP_FROM_SLOT_OFFSET_UNDECL_DATA(float,weights,cf); char *data = weights_obj->data; int s0 = weights_obj->strides[0]; int s1 = weights_obj->strides[1]; LOOKUP_FROM_SLOT_OFFSET(int,input_sheet_slice,cf); UNPACK_FOUR_TUPLE(int,rr1,rr2,cc1,cc2,input_sheet_slice); double tot = 0.0; npfloat *xj = X+icols*rr1+cc1; // computes the dot product for (int i=rr1; i<rr2; ++i) { npfloat *xi = xj; // float *wi = weights; // for (int j=cc1; j<cc2; ++j) { // tot += *wi * *xi; // ++wi; // ++xi; // } for (int j=cc1; j<cc2; ++j) { tot += *((float *)(data + (i-rr1)*s0 + (j-cc1)*s1)) * *xi; ++xi; } xj += icols; // weights += cc2-cc1; } temp_act[r] = tot*strength; // DECREF_CONTIGUOUS_ARRAY(weights); } } """ % c_decorators inline(code, [ 'mask', 'X', 'strength', 'icols', 'temp_act', 'cfs', 'num_cfs', 'cf_type' ], local_dict=locals(), headers=['<structmember.h>'])
def __init__(self, **params): super(CFPRF_DotProduct, self).__init__(single_cf_fn=DotProduct(), **params)