def make(learn_type='hPES', nperd=20, learn_rate=5e-5, supervision_ratio=0.5, oja=False): net = nef.Network('Learn Digits') # creates a network in Nengo input = net.add(Input('input')) # create the input node pre = net.make('pre', IND * nperd, IND, radius=4.5) post = net.make('post', OUTD * nperd, OUTD, radius=2.5) # Create error population # Established learning connection between input and output populations if learn_type == 'PES': pes.make(net, preName='pre', postName='post', errName='error', N_err=OUTD * nperd, rate=learn_rate, oja=oja) elif learn_type == 'hPES': hpes.make(net, preName='pre', postName='post', errName='error', N_err=OUTD * nperd, rate=learn_rate, supervisionRatio=supervision_ratio) # Connect parts of network net.connect(input.getOrigin('label'), 'error') net.connect(input.getOrigin('input'), pre) net.connect('post', 'error', weight=-1) # Create a gate for turning learning on and off gating.make(net,name='Gate', gated='error', neurons=40, pstc=0.01) # Have the 'learning switch position' file drive the gate net.connect(input.getOrigin('learnswitch'), 'Gate') return net
def make(self): import nef import nef.templates.learned_termination as pes import nef.templates.hpes_termination as hpes import nef.templates.gate as gating if self.net is not None: return self.net random.seed(self.seed) net = nef.Network('Learn Network', seed=random.randrange(0x7fffffff)) net.make('pre', self.nperd * self.in_d, self.in_d) net.make('post', self.nperd * self.out_d, self.out_d) net.make_fourier_input('input', dimensions=self.in_d, base=0.25, high=40) net.connect('input', 'pre') if self.learn_type == 'PES': pes.make(net, preName='pre', postName='post', errName='error', N_err=self.nperd * self.out_d, rate=self.learn_rate, oja=self.oja) elif self.learn_type == 'hPES': hpes.make(net, preName='pre', postName='post', errName='error', N_err=self.nperd * self.out_d, rate=self.learn_rate, supervisionRatio=self.supervision_ratio) elif self.learn_type == 'control': net.connect('pre', 'post', func=self.func, origin_name='pre_00') net.make('error', 1, self.out_d, mode='direct') # Unused net.connect('pre', 'error', func=self.func) net.connect('post', 'error', weight=-1) start = 'test' if self.testtype == 'full' else 'train' net.make_input('switch', LearnBuilder.get_learning_times( self.train, self.test, start)) gating.make(net, name='Gate', gated='error', neurons=50, pstc=0.01) net.connect('switch', 'Gate') # Calculate actual error net.make('actual', 1, self.in_d, mode='direct') net.connect('input', 'actual') net.make('actual error', 1, self.out_d, mode='direct') net.connect('actual', 'actual error', func=self.func) net.connect('post', 'actual error', weight=-1) self.net = net return self.net
# Create input and output populations. net.make('pre', N, D) net.make('post', N, D) # Create a random white noise input function with # .1 base freq, max freq 10 rad/s, RMS of .5, and random number seed 12 net.make_fourier_input('input', base=0.1, high=10, power=0.5, seed=12) net.connect('input', 'pre') # Create a modulated connection between the 'pre' and 'post' ensembles. learning.make( net, errName='error', N_err=100, preName='pre', postName='post', rate=5e-4) # Set the modulatory signal. net.connect('pre', 'error') net.connect('post', 'error', weight=-1) # Add a gate to turn learning on and off. net.make_input('switch', [0]) gating.make(net, name='Gate', gated='error', neurons=40, pstc=0.01) net.connect('switch', 'Gate') # Add another non-gated error population running in direct mode. net.make('actual error', 1, 1, mode='direct') net.connect('pre', 'actual error') net.connect('post', 'actual error', weight=-1) net.add_to_nengo()
def make_learnable_cleanup(D=16, cleanup_neurons=1000, num_vecs=4, threshold=(-0.9, 0.9), max_rate=(100, 200), radius=1.0, cleanup_pstc=0.001, neurons_per_dim=50, clean_learning=False, trial_length=100, learning_noise=0.6, testing_noise=0.3, user_control_learning=False, user_control_bias=False, learning_rate=5e-6, schedule_func=None, neural_input=False, learning_bias=0.0, testing_bias=0.0, **kwargs): """ Construct a cleanup memory that initially has no vocabulary, and learns its vocabulary from the vectors it receives as input. Also constructs an experiment node that tests the cleanup. Should probably separate that part out eventually. :param variable_bias: For using different thresholds during learning and testing. Implemented by a decoded-to-nondecoded connection from an ensemble to the cleanup population. :type variable_bias: boolean or tuple. If a tuple, first value will be used as threshold during learning, second will be used as threshold during testing. If True, user controls threshold (only works with a GUI). If False, threshold is fixed at whatever is determined by t_hi and t_lo. """ print cleanup_neurons logger = logging.getLogger("make_learnable_cleanup") net = nef.Network('learn_cleanup', seed=2) vocab = hrr.Vocabulary(D) func_str = "def tr(self, x, dimensions=%d, pstc=0.02):\n self.results = x\n self.trial_error.append(self.correct_vector - self.results)" % D exec func_str in locals() ExperimentController.termination_results = tr controller = ExperimentController( 'EC', vocab, num_vecs, clean_learning, learning_noise, testing_noise, learning_bias, testing_bias, trial_length, schedule_func=schedule_func, user_control_learning=user_control_learning) net.add(controller) logger.info("Adding cleanup") net.make('cleanup', neurons=cleanup_neurons, dimensions=D, radius=radius, intercept=threshold, max_rate=max_rate, tau_ref=0.004) if user_control_bias: logger.info("Adding bias controlled by user") make_bias(net, 'bias', 'cleanup', bias=1.0, neurons=1, pstc=cleanup_pstc, direct=True) net.make_input('bias_input', [0]) net.connect('bias_input', 'bias') else: logger.info("Adding bias controlled by EC") make_bias(net, 'bias', 'cleanup', bias=1.0, neurons=1, pstc=cleanup_pstc, direct=True) net.connect(controller.getOrigin('bias'), 'bias') logger.info("Adding output") net.make('output', neurons=neurons_per_dim * D, dimensions=D, mode='default') logger.info("Adding input") if neural_input: net.make_array('input', neurons=neurons_per_dim, length=D, dimensions=1, mode='default') else: net.make('input', neurons=1, dimensions=D, mode='direct') net.connect(controller.getOrigin('input_vecs'), 'input') net.connect('input', 'cleanup', pstc=cleanup_pstc) logger.info("Adding error population and learning") learning.make(net, errName='error', N_err=neurons_per_dim * D, preName='cleanup', postName='output', rate=learning_rate) net.connect(controller.getOrigin('learning_vecs'), 'error', pstc=0.01) logger.info("Adding learning gate") gating.make(net, name='Gate', gated='error', neurons=40, pstc=0.01) net.connect('output', controller.getTermination('results')) if user_control_learning: logger.info("Adding learning-control switch") net.make_input('switch', [1.0]) net.connect('switch', controller.getTermination('learning_on')) net.connect(controller.getOrigin('learning_control'), 'Gate') logger.info("Adding network to nengo") net.add_to_nengo() #if show_stats: # encoders = net.get('cleanup').getEncoders() # sims=[[] for name in names] # hrrs = [vocab.parse(name) for name in names] # for enc in encoders: # h = hrr.HRR(data=enc) # for v, s in zip(hrrs,sims): # s.append(v.compare(h)) # sims.append(s) # for v,s, in zip(hrrs,sims): # print "lo" # print len(filter(lambda x: x > t_lo, s)) # print "hi" # print len(filter(lambda x: x > t_hi, s)) # print sims return net
N, 2, quick=True, intercept=(-1, 0), encoders=[[1]]) thalamus.addDecodedTermination('bg', [[-3, 0], [0, -3]], 0.01, False) net.network.addProjection(bg.getOrigin('output'), thalamus.getTermination('bg')) def xBiased(x): return [x[0] + 1] # Add gating signals to control memory acquisition and motor output gating.make(net, name='Gate1', gated='Channel', neurons=100, pstc=0.01) gating.make(net, name='Gate2', gated='Motor', neurons=100, pstc=0.01) net.connect(thalamus, 'Gate1', index_pre=0, func=xBiased) net.connect(thalamus, 'Gate2', index_pre=1, func=xBiased) inputs = {} ZERO = [0] * D inputs[0.0] = ZERO inputs[0.1] = vocab.parse('STATEMENT+RED*CIRCLE').v inputs[0.5] = ZERO inputs[0.6] = vocab.parse('STATEMENT+BLUE*SQUARE').v inputs[1.0] = ZERO inputs[1.2] = vocab.parse('QUESTION+RED').v inputs[1.4] = vocab.parse('QUESTION+SQUARE').v inputs[1.6] = ZERO inputs[1.8] = vocab.parse('QUESTION+RED').v
.1, 8,.4,i, 0) for i in range(D)], Units.UNK) #Create a white noise input function .1 base freq, #max freq 8 rad/s, and RMS of .4; i makes one for #each dimension; 0 is the seed net.add(input) #Add the input node to the network net.connect(input,A) # Create a modulated connection between the 'pre' and 'post' ensembles. learning.make(net,errName='error', N_err=100, preName='pre', postName='post', rate=5e-7) #Make an error population with 100 neurons, and a learning #rate of 5e-7 # Set the modulatory signal to compute the desired function def square(x): return [xx*xx for xx in x] net.connect('pre', 'error', func=square) net.connect('post', 'error', weight=-1) # Add a gate to turn learning on and off. net.make_input('switch',[0]) #Create a controllable input function with #a starting value of 0 and 0 in the two #dimensions gating.make(net,name='Gate', gated='error', neurons=40, pstc=0.01) #Make a gate population with 40 neurons, and a postsynaptic #time constant of 10ms net.connect('switch', 'Gate') net.add_to_nengo()
# Create a modulated connection between the 'pre' and 'post' ensembles. learning.make( net, errName='error', N_err=100, preName='pre', postName='post', rate=5e-7) #Make an error population with 100 neurons, and a learning #rate of 5e-7 # Set the modulatory signal to compute the desired function def product(x): product = 1.0 for xx in x: product *= xx return product net.connect('pre', 'error', func=product) net.connect('post', 'error', weight=-1) # Add a gate to turn learning on and off. net.make_input('switch', [0]) #Create a controllable input function with #a starting value of 0 and 0 in the two #dimensions gating.make( net, name='Gate', gated='error', neurons=40, pstc=0.01) #Make a gate population with 40 neurons, and a postsynaptic #time constant of 10ms net.connect('switch', 'Gate') net.add_to_nengo()
bgtemplate.make(net,name='Basal Ganglia',dimensions=2,pstc=0.01) bg = net.network.getNode('Basal Ganglia') bg_rule.make(net,bg,index=0,dimensions=D,pattern='STATEMENT',pstc=0.01,use_single_input=True) bg_rule.make(net,bg,index=1,dimensions=D,pattern='QUESTION',pstc=0.01,use_single_input=True) net.network.addProjection(visual.getOrigin('X'), bg.getTermination('rule_00')) net.network.addProjection(visual.getOrigin('X'), bg.getTermination('rule_01')) # Create the thalamus network to process the output from the basal ganglia thalamus = net.make_array('Thalamus', N, 2, quick=True, intercept=(-1, 0), encoders=[[1]]) thalamus.addDecodedTermination('bg',[[-3, 0], [0, -3]],0.01,False) net.network.addProjection(bg.getOrigin('output'), thalamus.getTermination('bg')) def xBiased(x): return [x[0]+1] # Add gating signals to control memory acquisition and motor output gating.make(net,name='Gate1', gated='Channel', neurons=100 ,pstc=0.01) gating.make(net,name='Gate2', gated='Motor', neurons=100 ,pstc=0.01) net.connect(thalamus, 'Gate1', index_pre=0, func=xBiased) net.connect(thalamus, 'Gate2', index_pre=1, func=xBiased) # Automatic inputs class Input(nef.SimpleNode): def __init__(self,name): self.zero=[0]*D nef.SimpleNode.__init__(self,name) self.v1=vocab.parse('STATEMENT+RED*CIRCLE').v self.v2=vocab.parse('STATEMENT+BLUE*SQUARE').v self.v3=vocab.parse('QUESTION+RED').v self.v4=vocab.parse('QUESTION+SQUARE').v def origin_x(self): t=self.t_start
# Create a modulated connection between the 'pre' and 'post' ensembles. learning.make(net, errName='error', N_err=100, preName='pre', postName='post', rate=5e-7) # Set the modulatory signal. net.connect('pre', 'error') net.connect('post', 'error', weight=-1) # Add a gate to turn learning on and off. net.make_input('switch', [0]) gating.make(net, name='Gate', gated='error', neurons=100, pstc=0.01) net.connect('switch', 'Gate') # Add another non-gated error population running in direct mode. actual = net.make('actual error', 1, 1, mode='direct') net.connect('pre', 'actual error') net.connect('post', 'actual error', weight=-1) def square(x): return x[0] * x[0] # Make an origin on pre that computes the square, to generate # a different error signal net.connect('pre', None, func=square, create_projection=False)
def make_learnable_cleanup(D=16, cleanup_neurons = 1000, num_vecs = 4, threshold=(-0.9,0.9), max_rate=(100,200), radius=1.0, cleanup_pstc=0.001, neurons_per_dim=50, clean_learning=False, trial_length=100, learning_noise=0.6, testing_noise=0.3, user_control_learning=False, user_control_bias=False, learning_rate=5e-6, schedule_func=None, neural_input=False, learning_bias=0.0, testing_bias=0.0, **kwargs): """ Construct a cleanup memory that initially has no vocabulary, and learns its vocabulary from the vectors it receives as input. Also constructs an experiment node that tests the cleanup. Should probably separate that part out eventually. :param variable_bias: For using different thresholds during learning and testing. Implemented by a decoded-to-nondecoded connection from an ensemble to the cleanup population. :type variable_bias: boolean or tuple. If a tuple, first value will be used as threshold during learning, second will be used as threshold during testing. If True, user controls threshold (only works with a GUI). If False, threshold is fixed at whatever is determined by t_hi and t_lo. """ print cleanup_neurons logger = logging.getLogger("make_learnable_cleanup") net = nef.Network('learn_cleanup', seed=2) vocab=hrr.Vocabulary(D) func_str = "def tr(self, x, dimensions=%d, pstc=0.02):\n self.results = x\n self.trial_error.append(self.correct_vector - self.results)" % D exec func_str in locals() ExperimentController.termination_results = tr controller = ExperimentController('EC', vocab, num_vecs, clean_learning, learning_noise, testing_noise, learning_bias, testing_bias, trial_length, schedule_func=schedule_func, user_control_learning=user_control_learning) net.add(controller) logger.info("Adding cleanup") net.make('cleanup', neurons=cleanup_neurons, dimensions=D, radius=radius, intercept=threshold, max_rate=max_rate, tau_ref=0.004) if user_control_bias: logger.info("Adding bias controlled by user") make_bias(net, 'bias', 'cleanup', bias=1.0, neurons=1, pstc=cleanup_pstc, direct=True) net.make_input('bias_input', [0]) net.connect('bias_input', 'bias') else: logger.info("Adding bias controlled by EC") make_bias(net, 'bias', 'cleanup', bias=1.0, neurons=1, pstc=cleanup_pstc, direct=True) net.connect(controller.getOrigin('bias'), 'bias') logger.info("Adding output") net.make('output', neurons=neurons_per_dim * D, dimensions=D, mode='default') logger.info("Adding input") if neural_input: net.make_array('input', neurons=neurons_per_dim, length=D, dimensions=1, mode='default') else: net.make('input', neurons=1, dimensions=D, mode='direct') net.connect( controller.getOrigin('input_vecs'), 'input') net.connect('input', 'cleanup', pstc=cleanup_pstc) logger.info("Adding error population and learning") learning.make(net, errName = 'error', N_err = neurons_per_dim * D, preName='cleanup', postName='output', rate=learning_rate) net.connect( controller.getOrigin('learning_vecs'), 'error', pstc=0.01) logger.info("Adding learning gate") gating.make(net, name='Gate', gated='error', neurons=40, pstc=0.01) net.connect('output', controller.getTermination('results')) if user_control_learning: logger.info("Adding learning-control switch") net.make_input('switch', [1.0]) net.connect('switch', controller.getTermination('learning_on')) net.connect( controller.getOrigin('learning_control'), 'Gate') logger.info("Adding network to nengo") net.add_to_nengo() #if show_stats: # encoders = net.get('cleanup').getEncoders() # sims=[[] for name in names] # hrrs = [vocab.parse(name) for name in names] # for enc in encoders: # h = hrr.HRR(data=enc) # for v, s in zip(hrrs,sims): # s.append(v.compare(h)) # sims.append(s) # for v,s, in zip(hrrs,sims): # print "lo" # print len(filter(lambda x: x > t_lo, s)) # print "hi" # print len(filter(lambda x: x > t_hi, s)) # print sims return net
# Create a white noise input function .1 base freq, max # freq 10 rad/s, and RMS of .4; 0 is a seed net.connect("input", "pre") # Create a modulated connection between the 'pre' and 'post' ensembles. learning.make( net, errName="error", N_err=100, preName="pre", postName="post", rate=5e-7 ) # Make an error population with 100 neurons, and a learning # rate of 5e-7 # Set the modulatory signal to compute the desired function def square(x): return [xx * xx for xx in x] net.connect("pre", "error", func=square) net.connect("post", "error", weight=-1) # Add a gate to turn learning on and off. net.make_input("switch", [0]) # Create a controllable input function with # a starting value of 0 and 0 in the two # dimensions gating.make( net, name="Gate", gated="error", neurons=40, pstc=0.01 ) # Make a gate population with 40 neurons, and a postsynaptic # time constant of 10ms net.connect("switch", "Gate") net.add_to_nengo()