Source code for imagen.transferfn

"""
TransferFns: accept and modify a 2d array
"""

import numpy
import copy
import param


[docs]class TransferFn(param.Parameterized): """ Function object to modify a matrix in place, e.g. for normalization. Used for transforming an array of intermediate results into a final version, by cropping it, normalizing it, squaring it, etc. Objects in this class must support being called as a function with one matrix argument, and are expected to change that matrix in place. """ __abstract = True init_keys = param.List(default=[], constant=True, doc=""" List of item key labels for metadata that that must be supplied to the initialize method before the TransferFn may be used.""") # CEBALERT: can we have this here - is there a more appropriate # term for it, general to output functions? JAB: Please do rename it! norm_value = param.Parameter(default=None)
[docs] def initialize(self, **kwargs): """ Transfer functions may need additional information before the supplied numpy array can be modified in place. For instance, transfer functions may have state which needs to be allocated in memory with a certain size. In other cases, the transfer function may need to know about the coordinate system associated with the input data. """ if not set(kwargs.keys()).issuperset(self.init_keys): raise Exception("TransferFn needs to be initialized with %s" % ','.join(repr(el) for el in self.init_keys))
def __call__(self,x): raise NotImplementedError
[docs]class TransferFnWithState(TransferFn): """ Abstract base class for TransferFns that need to maintain a self.plastic parameter. These TransferFns typically maintain some form of internal history or other state from previous calls, which can be disabled by override_plasticity_state(). """ plastic = param.Boolean(default=True, doc=""" Whether or not to update the internal state on each call. Allows plasticity to be temporarily turned off (e.g for analysis purposes).""") __abstract = True def __init__(self,**params): super(TransferFnWithState,self).__init__(**params) self._plasticity_setting_stack = []
[docs] def override_plasticity_state(self, new_plasticity_state): """ Temporarily disable plasticity of internal state. This function should be implemented by all subclasses so that after a call, the output should always be the same for any given input pattern, and no call should have any effect that persists after restore_plasticity_state() is called. By default, simply saves a copy of the 'plastic' parameter to an internal stack (so that it can be restored by restore_plasticity_state()), and then sets the plastic parameter to the given value (True or False). """ self._plasticity_setting_stack.append(self.plastic) self.plastic=new_plasticity_state
[docs] def restore_plasticity_state(self): """ Re-enable plasticity of internal state after an override_plasticity_state call. This function should be implemented by all subclasses to remove the effect of the most recent override_plasticity_state call, i.e. to reenable changes to the internal state, without any lasting effect from the time during which plasticity was disabled. By default, simply restores the last saved value of the 'plastic' parameter. """ self.plastic = self._plasticity_setting_stack.pop()
[docs] def state_push(self): """ Save the current state onto a stack, to be restored with state_pop. Subclasses must implement state_push and state_pop to store state across invocations. The behaviour should be such that after state_pop, the state is restored to what it was at the time when state_push was called. """ pass
[docs] def state_pop(self): """ Restore the state saved by the most recent state_push call. """ pass
[docs]class IdentityTF(TransferFn): """ Identity function, returning its argument as-is. For speed, calling this function object is sometimes optimized away entirely. To make this feasible, it is not allowable to derive other classes from this object, modify it to have different behavior, add side effects, or anything of that nature. """ def __call__(self,x,sum=None): pass
[docs]class Scale(TransferFn): """ Multiply the input array by some constant factor. """ scale = param.Number(default=1.0, doc=""" The multiplicative factor that scales the input values.""") def __call__(self, x): x *= self.scale
[docs]class Threshold(TransferFn): """ Forces all values below a threshold to zero, and leaves others unchanged. """ threshold = param.Number(default=0.25, doc=""" Decision point for determining values to clip.""") def __call__(self,x): numpy.minimum(x,self.threshold,x)
[docs]class BinaryThreshold(TransferFn): """ Forces all values below a threshold to zero, and above it to 1.0. """ threshold = param.Number(default=0.25, doc=""" Decision point for determining binary value.""") def __call__(self,x): above_threshold = x>=self.threshold x *= 0.0 x += above_threshold
[docs]class DivisiveNormalizeL1(TransferFn): """ TransferFn that divides an array by its L1 norm. This operation ensures that the sum of the absolute values of the array is equal to the specified norm_value, rescaling each value to make this true. The array is unchanged if the sum of absolute values is zero. For arrays of non-negative values where at least one is non-zero, this operation is equivalent to a divisive sum normalization. """ norm_value = param.Number(default=1.0) def __call__(self,x): """L1-normalize the input array, if it has a nonzero sum.""" current_sum = 1.0*numpy.sum(abs(x.ravel())) if current_sum != 0: factor = (self.norm_value/current_sum) x *= factor
[docs]class DivisiveNormalizeL2(TransferFn): """ TransferFn to divide an array by its Euclidean length (aka its L2 norm). For a given array interpreted as a flattened vector, keeps the Euclidean length of the vector at a specified norm_value. """ norm_value = param.Number(default=1.0) def __call__(self,x): xr = x.ravel() tot = 1.0*numpy.sqrt(numpy.dot(xr,xr)) if tot != 0: factor = (self.norm_value/tot) x *= factor
[docs]class DivisiveNormalizeLinf(TransferFn): """ TransferFn to divide an array by its L-infinity norm (i.e. the maximum absolute value of its elements). For a given array interpreted as a flattened vector, scales the elements divisively so that the maximum absolute value is the specified norm_value. The L-infinity norm is also known as the divisive infinity norm and Chebyshev norm. """ norm_value = param.Number(default=1.0) def __call__(self,x): tot = 1.0*(numpy.abs(x)).max() if tot != 0: factor = (self.norm_value/tot) x *= factor
[docs]def norm(v,p=2): """ Returns the Lp norm of v, where p is an arbitrary number defaulting to 2. """ return (numpy.abs(v)**p).sum()**(1.0/p)
[docs]class DivisiveNormalizeLp(TransferFn): """ TransferFn to divide an array by its Lp-Norm, where p is specified. For a parameter p and a given array interpreted as a flattened vector, keeps the Lp-norm of the vector at a specified norm_value. Faster versions are provided separately for the typical L1-norm and L2-norm cases. Defaults to be the same as an L2-norm, i.e., DivisiveNormalizeL2. """ p = param.Number(default=2) norm_value = param.Number(default=1.0) def __call__(self,x): tot = 1.0*norm(x.ravel(),self.p) if tot != 0: factor = (self.norm_value/tot) x *=factor
[docs]class Hysteresis(TransferFnWithState): """ Smoothly interpolates a matrix between simulation time steps, with exponential falloff. """ time_constant = param.Number(default=0.3,doc=""" Controls the time scale of the interpolation.""") def __init__(self,**params): super(Hysteresis,self).__init__(**params) self.first_call = True self.__current_state_stack=[] self.old_a = 0 def __call__(self,x): if self.first_call is True: self.old_a = x.copy() * 0.0 self.first_call = False new_a = x.copy() self.old_a = self.old_a + (new_a - self.old_a)*self.time_constant x*=0 x += self.old_a def reset(self): self.old_a *= 0 def state_push(self): self.__current_state_stack.append((copy.copy(self.old_a), copy.copy(self.first_call))) super(Hysteresis,self).state_push() def state_pop(self): self.old_a,self.first_call = self.__current_state_stack.pop() super(Hysteresis,self).state_pop()

ImaGen

Table Of Contents

This Page