def fillVectors(vocab, d, numwords, threshold = 1.0): """Fills the vocabulary with randomly generated vectors.""" numgen = 0 timeout = 1000 while numgen < numwords: vec = RPMutils.genVector(d) unique = True for i in range(numgen): if(RPMutils.similarity(vocab[i][1], vec) > threshold): unique = False if unique: vocab[numgen][1] = vec numgen = numgen + 1 timeout = 1000 timeout = timeout - 1 if timeout == 0: System.out.println("Timeout in fillVectors, using threshold of " + str(threshold+0.1)) return(fillVectors(vocab, d, numwords, threshold+0.1)) return(vocab)
def __init__(self, name, N, d, vocab): NetworkImpl.__init__(self) self.name = name scaleFactor = 0.1 smallN = int(math.ceil(float(N) / d)) tauPSC = 0.007 ef1 = RPMutils.defaultEnsembleFactory() ef1.nodeFactory.tauRef = 0.001 test = ef1.make("hypothesis", 1, d) test.setMode(SimulationMode.DIRECT ) #since this is just a relay ensemble for modularity test.fixMode() test.addDecodedTermination("input", RPMutils.eye(d, 1), 0.0001, False) self.addNode(test) self.exposeTermination(test.getTermination("input"), "hypothesis") combine = ef1.make("combine", 800, 8) # combine.setMode(SimulationMode.DIRECT) #since this is just a relay ensemble for modularity # combine.fixMode() # combine.collectSpikes(True) self.addNode(combine) inputVec = [[0] for x in range(8)] #create a population for each possible answer for i in range(8): ans = ef1.make("ans_" + str(i), smallN, 1) ans.addDecodedTermination("input", [vocab[i]], tauPSC, False) self.addNode(ans) self.addProjection(test.getOrigin("X"), ans.getTermination("input")) inputVec[i] = [scaleFactor] combine.addDecodedTermination("in_" + str(i), inputVec, tauPSC, False) inputVec[i] = [0] self.addProjection(ans.getOrigin("X"), combine.getTermination("in_" + str(i))) self.exposeOrigin(combine.getOrigin("X"), "result") if RPMutils.USE_PROBES: self.simulator.addProbe("combine", "X", True)
def __init__(self, name, N, d): NetworkImpl.__init__(self) self.name = name tauPSC = 0.007 ef = RPMutils.defaultEnsembleFactory() netef = networkensemble.NetworkEnsemble(ef) #create the approximate inverse matrix inv = RPMutils.eye(d, 1) for i in range(d/2): tmp = inv[i+1] inv[i+1] = inv[d-i-1] inv[d-i-1] = tmp #create the two input populations Ainv = netef.make("Ainv", N, tauPSC, [inv], None) self.addNode(Ainv) B = netef.make("B", N, tauPSC, [RPMutils.eye(d, 1)], None) self.addNode(B) #create circular convolution network corr = cconv.Cconv("corr", N, d) self.addNode(corr) self.addProjection(Ainv.getOrigin("X"), corr.getTermination("A")) self.addProjection(B.getOrigin("X"), corr.getTermination("B")) #average result T = average.Average("T", N, d) self.addNode(T) self.addProjection(corr.getOrigin("X"), T.getTermination("input")) if RPMutils.USE_PROBES: self.simulator.addProbe("T", "X", True) self.simulator.addProbe("corr", "X", True) self.simulator.addProbe("Ainv", "X", True) self.simulator.addProbe("B", "X", True) self.exposeOrigin(T.getOrigin("X"), "T") self.exposeTermination(Ainv.getTermination("in_0"), "A") self.exposeTermination(B.getTermination("in_0"), "B") # self.exposeTermination(T.getTermination("lrate"), "lrate")
def getMatrixVocab(self): """Returns all the vocabulary (in vector form) used in this matrix.""" #first figure out all the words that are used #words in this case are attr x val pairs #also add the AxB tags we add to feature descriptions when more than one feature is being used v = [] #list of vocab words for cell in self.matrix[0:8]: for feature in cell: fv = "" #the AxB tag for attr,val in feature: v = v + [attr + " " + val] #add the word for this attr-val pair to the list fv = fv + attr + " " + val + ";" #add this attr-val pair to the AxB tag if len(feature) > 1: #if more than one attribute in feature, add the tag to the word list (if there is #only one attribute in feature then the tag is the same as the attr-val word we #already added, so unnecessary) v = v + [fv] #remove duplicates v.sort() v = [word for i,word in enumerate(v) if i == len(v)-1 or not v[i+1] == word] # print v #turn vocab into vectors vocab = [] for word in v: vec = None prod = None for pair in word.split(";"): if pair: attr,val = pair.split(" ") #the vector for this attr-val pair pairword = RPMutils.normalize(RPMutils.cconv(self.getVocabVal(attr), self.getVocabVal(val))) vec = RPMutils.vecsum(vec, pairword) #the non-tag part (vec should always be None, so vec=pairword) prod = RPMutils.cconv(prod, pairword) #the tag part if ";" in word: vec = prod #then use the tag part vocab = vocab + [RPMutils.normalize(vec)] return vocab
def saveVocab(d, numwords, seed, filename): """Saves the vocabulary to file.""" vocab = genVocab(d, numwords, seed) output = open(filename, "w") for name,val in vocab: if name: output.write(name + " " + RPMutils.floatlist2str(val) + "\n") output.close()
def loadVocab(file): """Loads vocabulary from file.""" input = open(file) vocab = [] for line in input: splitline = line.split(" ", 1) vocab = vocab + [[splitline[0], RPMutils.str2floatlist(splitline[1])]] return(vocab)
def genVocab20(d, seed): """Vocabulary for 20 base words.""" numwords = 20 vocab = [[None,None] for i in range(numwords*2)] PDFTools.setSeed(seed) # for i in range(numwords): # vocab[i][1] = genVector(d) vocab = fillVectors(vocab, d, numwords, RPMutils.VECTOR_SIMILARITY) PDFTools.setSeed(long(time.time())) #attributes vocab[0][0] = "shape" vocab[1][0] = "number" vocab[2][0] = "size" vocab[3][0] = "orientation" vocab[4][0] = "position" #values #vocab[5][0] = "small" #vocab[6][0] = "medium" #vocab[7][0] = "large" vocab[8][0] = "zero" vocab[9][0] = "one" vocab[10][0] = "plusone" vocab[11][0] = "horizontal" vocab[12][0] = "vertical" vocab[13][0] = "oblique" # vocab[14][0] = vocab[15][0] = "circle" vocab[16][0] = "square" vocab[17][0] = "diamond" vocab[18][0] = "triangle" vocab[19][0] = "rubbish" #now the higher level vocabulary vocab[20][0] = "two" vocab[20][1] = RPMutils.normalize(RPMutils.cconv(vocab[9][1], vocab[10][1])) vocab[21][0] = "three" vocab[21][1] = RPMutils.normalize(RPMutils.cconv(vocab[20][1], vocab[10][1])) vocab[22][0] = "four" vocab[22][1] = RPMutils.normalize(RPMutils.cconv(vocab[21][1], vocab[10][1])) output = open(RPMutils.vocabFile(d, numwords, seed), "w") for i in range(len(vocab)): if vocab[i][0] != None: output.write(vocab[i][0] + " " + RPMutils.floatlist2str(vocab[i][1]) + "\n") output.close()
def encodeMatrix(self, matrix): """Converts the matrix into vector form.""" #check if there is more than one feature in the matrix #this is relevant because if there is more than one feature then #we will encode each feature as A + B + AxB, whereas if there is #only one feature we will just use A + B oneFeature = True for cell in matrix: if len(cell) > 1: oneFeature = False result = [] #for each cell in the matrix for cell in matrix: vec = None #the vector representation for this cell #for each feature in the cell for feature in cell: featurevec = None #the vector representation for this feature (the A + B part) prodvec = None #the AxB part of the vector representation of this feature #for each attr in the feature for attr,val in feature: attribute = self.getVocabVal(attr) value = self.getVocabVal(val) pairword = RPMutils.normalize(RPMutils.cconv(attribute,value)) #vector for that attribute-value pair featurevec = RPMutils.vecsum(featurevec, pairword) prodvec = RPMutils.cconv(prodvec,pairword) if oneFeature: if vec != None: System.err.println("oneFeature is true but more than one feature vector is being calculated!") vec = featurevec #ignore the AxB part and vec=featurevec because there is only one feature else: #add this feature (including AxB part) to previous features in the cell vec = RPMutils.vecsum(vec, RPMutils.normalize(RPMutils.vecsum(RPMutils.normalize(prodvec), RPMutils.normalize(featurevec)))) if vec==None: vec = self.getVocabVal("null") result = result + [RPMutils.normalize(vec)] return result
def __init__(self, name, N, d): NetworkImpl.__init__(self) self.name = name tauPSC = 0.007 ef = RPMutils.defaultEnsembleFactory() netef = networkensemble.NetworkEnsemble(ef) #scale input to integrator (adaptive learning rate) # scaler = eprod.Eprod("scaler", N, d, oneDinput=True) # self.addNode(scaler) #new idea, try a constant scale #constant scale on input: 0.4 #constant scale on recurrent connection: 0.8 (forget rate 0.2) #create integrator #we scale the input by 1/stepsize because we want the integrator to reach the target value in stepsize*1s, not 1s int = integrator.Integrator("int", N, d, inputScale=0.4, forgetRate=0.2, stepsize=RPMutils.STEP_SIZE) self.addNode(int) # self.addProjection(scaler.getOrigin("X"), int.getTermination("input")) if RPMutils.USE_PROBES: self.simulator.addProbe("int", "X", True) # self.simulator.addProbe("scaler", "X", True) self.exposeOrigin(int.getOrigin("X"), "X") # self.exposeTermination(scaler.getTermination("A"), "input") # self.exposeTermination(scaler.getTermination("B"), "lrate") self.exposeTermination(int.getTermination("input"), "input")
def testSimilarity(vocab): """Calculates a measure of the vocabulary's similarity.""" #we will count the average proportion of the vocabulary that is more than #threshold similar to each vector in the population threshold = 0.3 vecs = [x[1] for x in vocab] sim = 0.0 for i in range(len(vocab)): count = 0.0 #count the number of vectors that exceed threshold for j in range(len(vocab)): if i != j: if RPMutils.similarity(vecs[i],vecs[j]) > threshold: count += 1.0 count /= len(vocab) sim += count sim /= len(vocab) return sim
def __init__(self, name, N, d, scale=1.0, weights=None, maxinput=1.0, oneDinput=False): #scale is a scale on the output of the multiplication #output = (input1.*input2)*scale #weights are optional matrices applied to each input #output = (C1*input1 .* C2*input2)*scale #maxinput is the maximum expected value of any dimension of the inputs. this is used to #scale the inputs internally so that the length of the vectors in the intermediate populations are not #too small (which results in a lot of noise in the calculations) #oneDinput indicates that the second input is one dimensional, and is just a scale on the #first input rather than an element-wise product NetworkImpl.__init__(self) self.name = name smallN = int(math.ceil(float(N) / d)) #the size of the intermediate populations tauPSC = 0.007 #the maximum value of the vectors represented by the intermediate populations. #the vector is at most [maxinput maxinput], so the length of that is #sqrt(maxinput**2 + maxinput**2) maxlength = math.sqrt(2 * maxinput**2) if weights != None and len(weights) != 2: System.out.println("Warning, other than 2 matrices given to eprod") if weights == None: weights = [RPMutils.eye(d, 1), RPMutils.eye(d, 1)] inputd = len(weights[0][0]) ef = RPMutils.defaultEnsembleFactory() #create input populations in1 = ef.make("in1", 1, inputd) in1.addDecodedTermination("input", RPMutils.eye(inputd, 1), 0.0001, False) self.addNode(in1) in1.setMode(SimulationMode.DIRECT ) #since this is just a relay ensemble for modularity in1.fixMode() in2 = ef.make("in2", 1, inputd) if not oneDinput: in2.addDecodedTermination("input", RPMutils.eye(inputd, 1), 0.0001, False) else: #if it is a 1-D input we just expand it to a full vector of that value so that we #can treat it as an element-wise product in2.addDecodedTermination("input", [[1] for i in range(inputd)], 0.0001, False) self.addNode(in2) in2.setMode(SimulationMode.DIRECT ) #since this is just a relay ensemble for modularity in2.fixMode() #ensemble for intermediate populations multef = NEFEnsembleFactoryImpl() multef.nodeFactory.tauRC = 0.05 multef.nodeFactory.tauRef = 0.002 multef.nodeFactory.maxRate = IndicatorPDF(200, 500) multef.nodeFactory.intercept = IndicatorPDF(-1, 1) multef.encoderFactory = MultiplicationVectorGenerator() multef.beQuiet() result = ef.make("result", 1, d) result.setMode(SimulationMode.DIRECT ) #since this is just a relay ensemble for modularity result.fixMode() self.addNode(result) if RPMutils.SPLIT_DIMENSIONS: resultTerm = [[0] for x in range(d)] zeros = [0 for x in range(inputd)] one = [0 for x in range(inputd)] mpop = [] for e in range(d): #create a 2D population for each input dimension which will combine the components from #one dimension of each of the input populations mpop = multef.make('mpop_' + str(e), smallN, 2) #make two connection that will select one component from each of the input pops #we divide by maxlength to ensure that the maximum length of the 2D vector is 1 #remember that (for some reason) the convention in Nengo is that the input matrices are transpose of what they should be mathematically for i in range(inputd): one[i] = (1.0 / maxlength) * weights[0][e][i] mpop.addDecodedTermination('a', [one, zeros], tauPSC, False) for i in range(inputd): one[i] = (1.0 / maxlength) * weights[1][e][i] mpop.addDecodedTermination('b', [zeros, one], tauPSC, False) one = [0 for x in range(inputd)] #multiply the two selected components together mpop.addDecodedOrigin("output", [PostfixFunction('x0*x1', 2)], "AXON") self.addNode(mpop) self.addProjection(in1.getOrigin('X'), mpop.getTermination('a')) self.addProjection(in2.getOrigin('X'), mpop.getTermination('b')) #combine the 1D results back into one vector resultTerm[e] = [ maxlength**2 * scale ] #undo our maxlength manipulations and apply the scale #we scaled each input by 1/maxlength, then multiplied them together for a total scale of #1/maxlength**2, so to undo we multiply by maxlength**2 result.addDecodedTermination('in_' + str(e), resultTerm, 0.0001, False) resultTerm[e] = [0] self.addProjection(mpop.getOrigin('output'), result.getTermination('in_' + str(e))) else: #do all the multiplication in one population rather than splitting it up by dimension. note that this will #only really work in direct mode. mpop = ef.make("mpop", N, 2 * d) mpop.addDecodedTermination( "a", weights[0] + [[0 for x in range(inputd)] for y in range(d)], tauPSC, False) mpop.addDecodedTermination("b", [[0 for x in range(inputd)] for y in range(d)] + weights[1], tauPSC, False) mpop.addDecodedOrigin("output", [ PostfixFunction("x" + str(i) + "*x" + str(d + i), 2 * d) for i in range(d) ], "AXON") self.addNode(mpop) self.addProjection(in1.getOrigin("X"), mpop.getTermination("a")) self.addProjection(in2.getOrigin("X"), mpop.getTermination("b")) result.addDecodedTermination("input", RPMutils.eye(d, scale), tauPSC, False) self.addProjection(mpop.getOrigin("output"), result.getTermination("input")) self.exposeTermination(in1.getTermination("input"), "A") self.exposeTermination(in2.getTermination("input"), "B") self.exposeOrigin(result.getOrigin("X"), "X")
def __init__(self, N, d, matrix): NetworkImpl.__init__(self) self.name = "SequenceSolver" self.N = N self.d = d ef1 = RPMutils.defaultEnsembleFactory() #load matrix data from file matrixData = self.loadSequenceMatrix(matrix) #the two input signals, A and B, representing the sequence of example pairs Ain = matrixData[0] Bin = matrixData[1] self.addNode(Ain) self.addNode(Bin) #the adaptive learning rate # lrate = matrixData[2] # self.addNode(lrate) #calculate the T for the current A and B calcT = transform.Transform("calcT", N, d) self.addNode(calcT) self.addProjection(Ain.getOrigin("origin"), calcT.getTermination("A")) self.addProjection(Bin.getOrigin("origin"), calcT.getTermination("B")) # self.addProjection(lrate.getOrigin("origin"), calcT.getTermination("lrate")) if RPMutils.USE_CLEANUP: #run T through cleanup memory cleanT = memory.Memory("cleanT", N, d) self.addNode(cleanT) self.addProjection(calcT.getOrigin("T"), cleanT.getTermination("dirty")) #calculate the result of applying T to the second last cell secondLast = matrixData[3] self.addNode(secondLast) calcLast = cconv.Cconv("calcLast", N, d) self.addNode(calcLast) self.addProjection(secondLast.getOrigin("origin"), calcLast.getTermination("A")) if RPMutils.USE_CLEANUP: self.addProjection(cleanT.getOrigin("clean"), calcLast.getTermination("B")) else: self.addProjection(calcT.getOrigin("T"), calcLast.getTermination("B")) if RPMutils.LOAD_RULES: self.removeProjection(calcLast.getTermination("B")) rulesig = matrixData[len(matrixData) - 1] self.addNode(rulesig) self.addProjection(rulesig.getOrigin("origin"), calcLast.getTermination("B")) #compare the result to the possible answers to determine which is most similar if not RPMutils.RUN_WITH_CONTROLLER: testSimilarity = similarity.Similarity("testSimilarity", N, d, matrixData[4:]) self.addNode(testSimilarity) self.addProjection(calcLast.getOrigin("X"), testSimilarity.getTermination("hypothesis")) self.simulator.addProbe("testSimilarity", "result", True) if RPMutils.USE_CLEANUP: Tprobe = self.simulator.addProbe("cleanT", "clean", True) else: Tprobe = self.simulator.addProbe("calcT", "T", True) answerprobe = self.simulator.addProbe("calcLast", "X", True) if RPMutils.USE_CLEANUP and RPMutils.DYNAMIC_MEMORY: self.simulator.addSimulatorListener( memorylistener.MemoryManagementListener( RPMutils.cleanupDataFile(), RPMutils.cleanupFile(d, RPMutils.VOCAB_SIZE))) if RPMutils.RUN_WITH_CONTROLLER: self.simulator.addSimulatorListener( proberecorder.ProbeRecorder( Tprobe, RPMutils.resultFile("sequencesolver"), 0.05)) self.simulator.addSimulatorListener( proberecorder.ProbeRecorder( answerprobe, RPMutils.hypothesisFile("sequencesolver"), 0.05)) self.setMode(RPMutils.SIMULATION_MODE)
def reload(self, matrix): """Reload network with new matrix information.""" N = self.N d = self.d if RPMutils.LOAD_RULES: System.out.println( "Warning, calling reload when LOAD_RULES is True") #reload matrix data matrixData = self.loadSequenceMatrix(matrix) #remove and re-add input signals self.removeProjection(self.getNode("calcT").getTermination("A")) self.removeProjection(self.getNode("calcT").getTermination("B")) # self.removeProjection(self.getNode("calcT").getTermination("lrate")) self.removeNode("sigA") self.removeNode("sigB") # self.removeNode("lrate") Ain = matrixData[0] Bin = matrixData[1] # lrate = matrixData[2] self.addNode(Ain) self.addNode(Bin) # self.addNode(lrate) self.addProjection(Ain.getOrigin("origin"), self.getNode("calcT").getTermination("A")) self.addProjection(Bin.getOrigin("origin"), self.getNode("calcT").getTermination("B")) # self.addProjection(lrate.getOrigin("origin"), self.getNode("calcT").getTermination("lrate")) #remove and re-add secondLast signal self.removeProjection(self.getNode("calcLast").getTermination("A")) self.removeNode("secondLast") secondLast = matrixData[3] self.addNode(secondLast) self.addProjection(secondLast.getOrigin("origin"), self.getNode("calcLast").getTermination("A")) #remove and re-add similarity network if not RPMutils.RUN_WITH_CONTROLLER: self.removeProjection( self.getNode("testSimilarity").getTermination("hypothesis")) probes = RPMutils.findMatchingProbes(self.simulator.getProbes(), "testSimilarity") for probe in probes: self.simulator.removeProbe(probe) self.removeNode("testSimilarity") testSimilarity = similarity.Similarity("testSimilarity", N, d, matrixData[4:]) self.addNode(testSimilarity) self.addProjection( self.getNode("calcLast").getOrigin("X"), testSimilarity.getTermination("hypothesis")) self.simulator.addProbe("testSimilarity", "result", True) if RPMutils.USE_CLEANUP: #call reload on memory network, which will reload cleanup memory probes = RPMutils.findMatchingProbes(self.simulator.getProbes(), "cleaner") for probe in probes: self.simulator.removeProbe(probe) self.getNode("cleanT").reload() #reset all probes self.simulator.resetProbes() self.setMode(RPMutils.SIMULATION_MODE)
def loadSequenceMatrix(self, cell): """Load a matrix in HRR vector format from a file and create corresponding output functions.""" d = len(cell[0]) discontinuities = [ RPMutils.STEP_SIZE, 2 * RPMutils.STEP_SIZE, 3 * RPMutils.STEP_SIZE, 4 * RPMutils.STEP_SIZE, 5 * RPMutils.STEP_SIZE ] values1 = [[0 for x in range(6)] for x in range(d)] values2 = [[0 for x in range(6)] for x in range(d)] # 1.0 2.0 3.0 4.0 #signal A # cell1 cell2 cell4 cell5 cell7 #signal B # cell2 cell3 cell5 cell6 cell8 #values for 0th timestep for i in range(d): values1[i][0] = cell[0][i] for i in range(d): values2[i][0] = cell[1][i] #values for 1st timestep for i in range(d): values1[i][1] = cell[1][i] for i in range(d): values2[i][1] = cell[2][i] #values for 2nd timestep for i in range(d): values1[i][2] = cell[3][i] for i in range(d): values2[i][2] = cell[4][i] #values for 3rd timestep for i in range(d): values1[i][3] = cell[4][i] for i in range(d): values2[i][3] = cell[5][i] #values for 4th timestep for i in range(d): values1[i][4] = cell[6][i] for i in range(d): values2[i][4] = cell[7][i] for i in range(d): values1[i][5] = 0 values2[i][5] = 0 #create signalA f = [] for i in range(d): f = f + [PiecewiseConstantFunction(discontinuities, values1[i])] sigA = FunctionInput("sigA", f, Units.UNK) #create signal B f = [] for i in range(d): f = f + [PiecewiseConstantFunction(discontinuities, values2[i])] sigB = FunctionInput("sigB", f, Units.UNK) #create signal for adaptive learning rate rates = [1.0, 1.0 / 2.0, 1.0 / 3.0, 1.0 / 4.0, 1.0 / 5.0, 0.0] lrate = FunctionInput( "lrate", [PiecewiseConstantFunction(discontinuities, rates)], Units.UNK) #create signal for second last cell f = [] for i in range(d): f = f + [ConstantFunction(1, cell[7][i])] secondLast = FunctionInput("secondLast", f, Units.UNK) #load rule signal from file rulesig = [] if RPMutils.LOAD_RULES: rulefile = open(RPMutils.ruleFile()) lines = rulefile.readlines() rulefile.close() mod, rule = lines[0].split(":") if mod == "sequencesolver": rule = RPMutils.str2floatlist(rule.strip()) else: rule = [0.0 for i in range(self.d)] rulesig = RPMutils.makeInputVectors("rulesig", [rule]) if RPMutils.RUN_WITH_CONTROLLER: return ([sigA, sigB, lrate, secondLast] + rulesig) else: #create signals for answers ans = [] for i in range(8): ans = ans + [cell[8 + i]] return ([sigA, sigB, lrate, secondLast] + ans + rulesig)
def __init__(self, name, N, d, inputScale=1.0, forgetRate = 0.0, stepsize=1.0): NetworkImpl.__init__(self) self.name = name tauPSC = 0.007 intPSC = 0.1 smallN = int(math.ceil((float(N)/d) * 2)) inputWeight = intPSC * 1.0/stepsize * inputScale #weight on input connection #we multiply by intPSC as in standard NEF integrator formulation #we multiply by 1/stepsize so that the integrator will reach its target value #in stepsize rather than the default 1 second #then we multiply by the scale on the input recurWeight = 1-(intPSC * 1.0/stepsize * forgetRate) #weight on recurrent connection ef=RPMutils.defaultEnsembleFactory() netef = networkensemble.NetworkEnsemble(ef) intef = RPMutils.NEFMorePoints() intef.nodeFactory.tauRC = 0.05 intef.nodeFactory.tauRef = 0.002 intef.nodeFactory.maxRate = IndicatorPDF(100, 200) intef.nodeFactory.intercept = IndicatorPDF(-1, 1) intef.beQuiet() input = netef.make("input", N, 0.05, [RPMutils.eye(d, 1)], None) #note we run this in non-direct mode to eliminate the "bumps" self.addNode(input) output = ef.make("output", 1, d) output.setMode(SimulationMode.DIRECT) #since this is just a relay ensemble for modularity output.fixMode() self.addNode(output) if RPMutils.SPLIT_DIMENSIONS: invec = [0 for x in range(d)] resultTerm = [[0] for x in range(d)] for i in range(d): intpop = intef.make("intpop_" + str(i), smallN, 1) invec[i] = inputWeight intpop.addDecodedTermination("input", [invec], tauPSC, False) invec[i] = 0 intpop.addDecodedTermination("feedback", [[recurWeight]], intPSC, False) self.addNode(intpop) self.addProjection(input.getOrigin("X"), intpop.getTermination("input")) self.addProjection(intpop.getOrigin("X"), intpop.getTermination("feedback")) resultTerm[i] = [1] output.addDecodedTermination("in_" + str(i), resultTerm, 0.0001, False) resultTerm[i] = [0] self.addProjection(intpop.getOrigin("X"), output.getTermination("in_" + str(i))) else: #do all the integration in one population rather than dividing it up by dimension. note that #this will only really work in direct mode. intpop = intef.make("intpop", N, d) intpop.addDecodedTermination("input", RPMutils.eye(d,inputWeight), tauPSC, False) intpop.addDecodedTermination("feedback", RPMutils.eye(d,recurWeight), intPSC, False) self.addNode(intpop) self.addProjection(input.getOrigin("X"), intpop.getTermination("input")) self.addProjection(intpop.getOrigin("X"), intpop.getTermination("feedback")) output.addDecodedTermination("in", RPMutils.eye(d,1), 0.0001, False) self.addProjection(intpop.getOrigin("X"), output.getTermination("in")) self.exposeTermination(input.getTermination("in_0"), "input") self.exposeOrigin(output.getOrigin("X"), "X")
def __init__(self, name, N, d): NetworkImpl.__init__(self) self.name = name tauPSC = 0.007 Wr = self.calcWreal(d) Wi = self.calcWimag(d) halfd = int(d / 2) + 1 halfN = int(math.ceil(float(N) * halfd / d)) ef = RPMutils.defaultEnsembleFactory() netef = networkensemble.NetworkEnsemble(ef) #create input populations A = ef.make("A", 1, d) A.addDecodedTermination("input", RPMutils.eye(d, 1), 0.0001, False) A.setMode(SimulationMode.DIRECT ) #since this is just a relay ensemble for modularity A.fixMode() self.addNode(A) B = ef.make("B", 1, d) B.addDecodedTermination("input", RPMutils.eye(d, 1), 0.0001, False) B.setMode(SimulationMode.DIRECT ) #since this is just a relay ensemble for modularity B.fixMode() self.addNode(B) #this is the new method, where we collapse the fft into the eprod #populations to calculate the element-wise product of our vectors so far eprods = [] #note: we scale the output of the eprods by d/2, which we will undo at the #end, to keep the overall length of each dimension around 1 #(the average value of each dimension of a normalized d dimensional vector is 1/sqrt(d), #so 1/sqrt(d)*1/sqrt(d) = 1/d, so when we add the scale the resulting average dimension #should be around d/2d i.e. 1/2) #the 2 is added to give us a bit of a buffer, better to have the dimensions too small #than too large and run into saturation problems multscale = float(d) / 2.0 eprods = eprods + [ eprod.Eprod("eprod0", halfN, halfd, scale=multscale, weights=[Wr, Wr], maxinput=2.0 / math.sqrt(d)) ] eprods = eprods + [ eprod.Eprod("eprod1", halfN, halfd, scale=multscale, weights=[Wi, Wi], maxinput=2.0 / math.sqrt(d)) ] eprods = eprods + [ eprod.Eprod("eprod2", halfN, halfd, scale=multscale, weights=[Wi, Wr], maxinput=2.0 / math.sqrt(d)) ] eprods = eprods + [ eprod.Eprod("eprod3", halfN, halfd, scale=multscale, weights=[Wr, Wi], maxinput=2.0 / math.sqrt(d)) ] for i in range(4): self.addNode(eprods[i]) self.addProjection(A.getOrigin("X"), eprods[i].getTermination("A")) self.addProjection(B.getOrigin("X"), eprods[i].getTermination("B")) #negative identity matrix (for subtraction) negidentity = [[0 for x in range(d)] for x in range(d)] for i in range(d): negidentity[i][i] = -1 #note: all this halfd/expansion stuff is because the fft of a real value #is symmetrical, so we do all our computations on just one half and then #add in the symmetrical other half at the end #matrix for expanding real half-vectors (with negative for subtraction) expand = RPMutils.eye(halfd, 1) negexpand = RPMutils.eye(halfd, -1) #matrix for expanding imaginary half-vectors imagexpand = RPMutils.eye(halfd, 1) midpoint = halfd - 1 - (d + 1) % 2 for i in range(int(math.ceil(d / 2.0) - 1)): expand = expand + [expand[midpoint - i]] negexpand = negexpand + [negexpand[midpoint - i]] imagexpand = imagexpand + [[-x for x in imagexpand[midpoint - i]]] #multiply real components rprod = netef.make("rprod", N, tauPSC, [expand, negexpand], None) self.addNode(rprod) self.addProjection(eprods[0].getOrigin("X"), rprod.getTermination("in_0")) self.addProjection(eprods[1].getOrigin("X"), rprod.getTermination("in_1")) #multiply imaginary components iprod = netef.make("iprod", N, tauPSC, [imagexpand, imagexpand], None) self.addNode(iprod) self.addProjection(eprods[2].getOrigin("X"), iprod.getTermination("in_0")) self.addProjection(eprods[3].getOrigin("X"), iprod.getTermination("in_1")) #now calculate IFFT of Z = (rprod) + (iprod)i #we only need to calculate the real part, since we know the imaginary component is 0 Winvr = self.calcInvWreal(d) Winvi = self.calcInvWimag(d) for i in range(d): for j in range(d): Winvr[i][j] = Winvr[i][j] * (1.0 / multscale) Winvi[i][j] = Winvi[i][j] * (1.0 / multscale) negWinvi = [[0 for x in range(d)] for x in range(d)] for i in range(d): for j in range(d): negWinvi[i][j] = -Winvi[i][j] result = netef.make("result", N, tauPSC, [Winvr, negWinvi], None) self.addNode(result) self.addProjection(rprod.getOrigin("X"), result.getTermination("in_0")) self.addProjection(iprod.getOrigin("X"), result.getTermination("in_1")) if RPMutils.USE_PROBES: self.simulator.addProbe("A", "X", True) self.simulator.addProbe("B", "X", True) self.simulator.addProbe("eprod0", "X", True) self.simulator.addProbe("eprod1", "X", True) self.simulator.addProbe("eprod2", "X", True) self.simulator.addProbe("eprod3", "X", True) self.simulator.addProbe("rprod", "X", True) self.simulator.addProbe("iprod", "X", True) self.simulator.addProbe("result", "X", True) self.exposeTermination(A.getTermination("input"), "A") self.exposeTermination(B.getTermination("input"), "B") self.exposeOrigin(result.getOrigin("X"), "X")
def genVocab50(d, seed): """Vocabulary for 50 base words.""" numwords = 50 vocab = [[None,None] for i in range(numwords*2)] PDFTools.setSeed(seed) # for i in range(numwords): # vocab[i][1] = genVector(d) vocab = fillVectors(vocab, d, numwords, RPMutils.VECTOR_SIMILARITY) PDFTools.setSeed(long(time.time())) #attributes vocab[0][0] = "shape" vocab[1][0] = "number" vocab[2][0] = "linestroke" vocab[3][0] = "angle" vocab[4][0] = "length" vocab[5][0] = "rpos" vocab[6][0] = "hpos" vocab[7][0] = "vpos" vocab[8][0] = "shading" vocab[9][0] = "existence" vocab[10][0] = "linetype" vocab[11][0] = "width" #values #misc vocab[12][0] = "present" vocab[13][0] = "null" vocab[14][0] = "rubbish" #number vocab[15][0] = "zero" vocab[16][0] = "one" vocab[17][0] = "plusone" #angle vocab[18][0] = "0deg" vocab[19][0] = "plus45deg" #shape vocab[20][0] = "circle" vocab[21][0] = "square" vocab[22][0] = "diamond" vocab[23][0] = "dot" vocab[24][0] = "triangle" vocab[25][0] = "cross" vocab[26][0] = "X" vocab[27][0] = "rectangle" #linestroke vocab[28][0] = "normal" vocab[29][0] = "dashed" vocab[30][0] = "bold" #linetype vocab[31][0] = "straight" vocab[32][0] = "curved" vocab[33][0] = "wavy" # vocab[34][0] = #length vocab[35][0] = "short" vocab[36][0] = "longer" #radialpos/horizopos/verticpos vocab[37][0] = "rinner" vocab[38][0] = "hleft" vocab[39][0] = "vbottom" vocab[40][0] = "moveout" vocab[41][0] = "moveright" vocab[42][0] = "moveup" #shading vocab[43][0] = "none" vocab[44][0] = "solid" vocab[45][0] = "lefthatch" vocab[46][0] = "righthatch" vocab[47][0] = "crosshatch" vocab[48][0] = "vertical" vocab[49][0] = "horizontal" #now the higher level vocabulary vocab[50][0] = "two" vocab[50][1] = RPMutils.normalize(RPMutils.cconv(vocab[16][1], vocab[17][1])) vocab[51][0] = "three" vocab[51][1] = RPMutils.normalize(RPMutils.cconv(vocab[50][1], vocab[17][1])) vocab[52][0] = "four" vocab[52][1] = RPMutils.normalize(RPMutils.cconv(vocab[51][1], vocab[17][1])) vocab[55][0] = "45deg" vocab[55][1] = RPMutils.normalize(RPMutils.cconv(vocab[18][1], vocab[19][1])) vocab[56][0] = "90deg" vocab[56][1] = RPMutils.normalize(RPMutils.cconv(vocab[55][1], vocab[19][1])) vocab[57][0] = "135deg" vocab[57][1] = RPMutils.normalize(RPMutils.cconv(vocab[56][1], vocab[19][1])) vocab[58][0] = "180deg" vocab[58][1] = RPMutils.normalize(RPMutils.cconv(vocab[57][1], vocab[19][1])) vocab[59][0] = "225deg" vocab[59][1] = RPMutils.normalize(RPMutils.cconv(vocab[58][1], vocab[19][1])) vocab[60][0] = "270deg" vocab[60][1] = RPMutils.normalize(RPMutils.cconv(vocab[59][1], vocab[19][1])) vocab[61][0] = "315deg" vocab[61][1] = RPMutils.normalize(RPMutils.cconv(vocab[60][1], vocab[19][1])) vocab[65][0] = "rmiddle" vocab[65][1] = RPMutils.normalize(RPMutils.cconv(vocab[37][1], vocab[40][1])) vocab[66][0] = "router" vocab[66][1] = RPMutils.normalize(RPMutils.cconv(vocab[65][1], vocab[40][1])) vocab[67][0] = "hmiddle" vocab[67][1] = RPMutils.normalize(RPMutils.cconv(vocab[38][1], vocab[41][1])) vocab[68][0] = "hright" vocab[68][1] = RPMutils.normalize(RPMutils.cconv(vocab[67][1], vocab[41][1])) vocab[69][0] = "vmiddle" vocab[69][1] = RPMutils.normalize(RPMutils.cconv(vocab[39][1], vocab[42][1])) vocab[70][0] = "vtop" vocab[70][1] = RPMutils.normalize(RPMutils.cconv(vocab[69][1], vocab[42][1])) vocab[71][0] = "medium" vocab[71][1] = RPMutils.normalize(RPMutils.cconv(vocab[35][1], vocab[36][1])) vocab[72][0] = "long" vocab[72][1] = RPMutils.normalize(RPMutils.cconv(vocab[71][1], vocab[36][1])) output = open(RPMutils.vocabFile(d, numwords, seed), "w") for i in range(len(vocab)): if vocab[i][0] != None: output.write(vocab[i][0] + " " + RPMutils.floatlist2str(vocab[i][1]) + "\n") output.close()
def makeNetwork(self, name, N, tauPSC, matrices, outputfuncs): """Create a network ensemble that splits by dimension.""" Main = NetworkImpl() Main.name = name numin = len(matrices) #number of inputs din = [0 for i in range(numin)] #dimension of each input for i in range(numin): din[i] = len(matrices[i][0]) dout = len(matrices[0]) #dimension of output smallN = int(math.ceil(float(N) / dout)) #neurons per population defef = RPMutils.defaultEnsembleFactory() #create input populations (just relay nodes) inputs = [] for i in range(numin): inputs = inputs + [defef.make("in_" + str(i), 1, din[i])] inputs[i].addDecodedTermination("input", RPMutils.eye(din[i], 1), 0.0001, False) Main.exposeTermination(inputs[i].getTermination("input"), "in_" + str(i)) Main.addNode(inputs[i]) inputs[i].setMode(SimulationMode.DIRECT) inputs[i].fixMode() #output population (another relay node) output = defef.make("output", 1, dout) Main.exposeOrigin(output.getOrigin("X"), "X") Main.addNode(output) output.setMode(SimulationMode.DIRECT) output.fixMode() resultTerm = [[0] for x in range(dout)] #create dimension populations for i in range(dout): pop = self.ef.make("mid_" + str(i), smallN, 1) Main.addNode(pop) for j in range(numin): pop.addDecodedTermination("in_" + str(j), [matrices[j][i]], tauPSC, False) Main.addProjection(inputs[j].getOrigin("X"), pop.getTermination("in_" + str(j))) resultTerm[i] = [1] output.addDecodedTermination("in_" + str(i), resultTerm, 0.0001, False) resultTerm[i] = [0] if outputfuncs == None: Main.addProjection(pop.getOrigin("X"), output.getTermination("in_" + str(i))) else: pop.addDecodedOrigin("output", [outputfuncs[i]], "AXON") Main.addProjection(pop.getOrigin("output"), output.getTermination("in_" + str(i))) return Main