int VaryingHyPerConn::updateWeights(int axonId) { int syPatch = yPatchStride(); for( int kPatch = 0; kPatch < getNumDataPatches(); kPatch++) { PVPatch * W = getWeights(kPatch, axonId); int nkPatch = fPatchSize() * W->nx; pvwdata_t * Wdata = get_wData(axonId, kPatch); // W->data; pvdata_t * dWdata = get_dwData(axonId, kPatch); for(int kyPatch = 0; kyPatch < W->ny; kyPatch++) { for(int kPatch = 0; kPatch < nkPatch; kPatch++) { Wdata[kPatch] += dWdata[kPatch]; } dWdata += syPatch; } } return PV_SUCCESS; }
int LCALIFLateralKernelConn::allocateDataStructures() { int status = HyPerConn::allocateDataStructures(); // Neurons don't inhibit themselves, only their neighbors; set self-interaction weights to mmzero. assert(nxp % 2 == 1 && nyp % 2 == 1 && getNumDataPatches()==nfp); for (int k=0; k<getNumDataPatches(); k++) { int n = kIndex((nxp-1)/2, (nyp-1)/2, k, nxp, nyp, nfp); get_wDataHead(0, k)[n] = 0.0f; } integratedSpikeCountCube = pvcube_new(pre->getLayerLoc(), pre->getNumExtended()); integratedSpikeCount = integratedSpikeCountCube->data; for (int k=0; k<pre->getNumExtended(); k++) { integratedSpikeCount[k] = integrationTimeConstant*getTargetRateKHz(); // Spike counts initialized to equilibrium value } mpi_datatype = Communicator::newDatatypes(pre->getLayerLoc()); if (mpi_datatype==NULL) { fprintf(stderr, "LCALIFLateralKernelConn \"%s\" error creating mpi_datatype\n", name); abort(); } // Compute the number of times each patch contributes to dw, for proper averaging. int num_arbors = numberOfAxonalArborLists(); interiorCounts = (float **) calloc(num_arbors, sizeof(float *)); if (interiorCounts==NULL) { fprintf(stderr, "LCALIFLateralKernelConn::initialize \"%s\" error: unable to allocate memory for interiorCounts pointer\n", name); } interiorCounts[0] = (float *) calloc(getNumDataPatches()*nxp*nyp*nfp, sizeof(float)); if (interiorCounts[0]==NULL) { fprintf(stderr, "LCALIFLateralKernelConn::initialize \"%s\" error: unable to allocate memory for interiorCounts\n", name); } for (int arbor=1; arbor<num_arbors; arbor++) { interiorCounts[arbor] = interiorCounts[0]+arbor*getNumDataPatches()*nxp*nyp*nfp; } const PVLayerLoc * preloc = pre->getLayerLoc(); int nxpre = preloc->nx; int nypre = preloc->ny; int nfpre = preloc->nf; int nExt = pre->getNumExtended(); int sya = getPostExtStrides()->sy; int nxglob = preloc->nxGlobal; int nyglob = preloc->nyGlobal; int kx0 = preloc->kx0; int ky0 = preloc->ky0; for (int arbor=0; arbor<numberOfAxonalArborLists(); arbor++) { for(int kExt=0; kExt<nExt;kExt++) { int xglob = kxPos(kExt, nxpre + preloc->halo.lt + preloc->halo.rt, nypre + preloc->halo.dn + preloc->halo.up, nfpre) + kx0 - preloc->halo.lt; int yglob = kyPos(kExt, nypre + preloc->halo.lt + preloc->halo.rt, nypre + preloc->halo.dn + preloc->halo.up, nfpre) + ky0 - preloc->halo.up; if (xglob < 0 || xglob >= nxglob || yglob < 0 || yglob >= nyglob) { continue; } PVPatch * weights = getWeights(kExt,arbor); int offset = (int) getAPostOffset(kExt, arbor); int ny = weights->ny; int nk = weights->nx * nfp; int interiorCountOffset = get_wData(arbor, kExt)-get_wDataStart(arbor); int lineoffsetw = 0; int lineoffseta = 0; for( int y=0; y<ny; y++ ) { for( int k=0; k<nk; k++ ) { int postactindex = offset+lineoffseta+k; if (postactindex != kExt) { // Neurons don't inhibit themselves interiorCounts[arbor][interiorCountOffset + lineoffsetw + k]++; } } lineoffsetw += syp; lineoffseta += sya; } } } int bufsize = numberOfAxonalArborLists() * getNumDataPatches() * nxp * nyp * nfp; // TODO-CER-2014.3.26 - Ensure that reduction is done when not using MPI #ifdef PV_USE_MPI MPI_Allreduce(MPI_IN_PLACE, interiorCounts[0], bufsize, MPI_FLOAT, MPI_SUM, parent->icCommunicator()->communicator()); #endif return status; }
/** * STDP online implementation * (see more at: Pfister et al. 2008) * */ int STDP3Conn::updateWeights(int axonId) { // Steps: // 1. Update post_tr // 2. Update pre_tr // 3. Update w_ij const float dt = parent->getDeltaTime(); const float decayLTP = exp(-dt / tauLTP); const float decayLTD = exp(-dt / tauLTD); const float decayY = exp(-dt / tauY); const int nkpre = pre->getNumExtended(); assert(nkpre == getNumWeightPatches()); const pvdata_t * preLayerData = pre->getLayerData(); const pvdata_t * aPost = post->getLayerData(); pvdata_t aPre; //PVPatch * w; pvdata_t * post_tr_m; pvdata_t * post2_tr_m; pvdata_t * pre_tr_m; // Presynaptic trace matrix pvwdata_t * W; int nk, ny; const int nkPost = post_tr->numItems; post_tr_m = post_tr->data; // Postsynaptic trace matrix post2_tr_m = post2_tr->data; // Postsynaptic trace matrix // 1. Updates the postsynaptic traces for (int kPost = 0; kPost < nkPost; kPost++) { //post_tr_m[kPost] = (decayLTD * post_tr_m[kPost] + aPost[kPost]) > 1? 1 : (decayLTD * post_tr_m[kPost] + aPost[kPost]); post_tr_m[kPost] = decayLTD * post_tr_m[kPost] + aPost[kPost]; post2_tr_m[kPost] = decayY * post2_tr_m[kPost] + aPost[kPost]; } // this stride is in extended space for post-synaptic activity and STDP decrement variable const int postStrideY = post->getLayerLoc()->nf * (post->getLayerLoc()->nx + post->getLayerLoc()->halo.lt + post->getLayerLoc()->halo.rt); //FIXME: In the first iteration post is -70!! for (int kPre = 0; kPre < nkpre; kPre++) { aPre = preLayerData[kPre]; PVPatch * w = getWeights(kPre, axonId); //Get weights in form of a patch (nx,ny,nf), TODO: what's the role of the offset? size_t postOffset = getAPostOffset(kPre, axonId); //Gets start index for postsynaptic vectors given presynaptic neuron kPre aPost = &post->getLayerData()[postOffset]; //Gets postsynaptic activity post_tr_m = &(post_tr->data[postOffset]); // STDP decrement variable post2_tr_m = &(post_tr->data[postOffset]); // STDP y decrement variable //pre_tr_m = get_dwData(axonId, kPre); // STDP increment variable pre_tr_m = &(pre_tr->data[kPre]); W = get_wData(axonId, kPre); // w->data; nk = nfp * w->nx; // one line in x at a time ny = w->ny; // 2. Updates the presynaptic trace //pre_tr_m[0] = (decayLTP * pre_tr_m[0] + aPre) > 1? 1 : (decayLTP * pre_tr_m[0] + aPre); pre_tr_m[0] = decayLTP * pre_tr_m[0] + aPre; //3. Update weights for (int y = 0; y < ny; y++) { for (int k = 0; k < nk; k++) { // The next statement allows some synapses to "die". if (W[k] < WEIGHT_MIN_VALUE) continue; W[k] += dWMax * (-ampLTD*aPre * post_tr_m[k] + ampLTP * aPost[k] * (pre_tr_m[0]*post2_tr_m[k])); W[k] = W[k] < wMin ? wMin : W[k]; W[k] = W[k] > wMax ? wMax : W[k]; } // advance pointers in y W += syp; //FIXME: W += nk //pre_tr_m += syp; //FIXME: pre_tr_m += syp; // postActivity and post trace are extended layer aPost += postStrideY; //TODO: is this really in the extended space? post_tr_m += postStrideY; post2_tr_m += postStrideY; } } if(synscalingFlag){ //int kxPre, kyPre, kPre; const int numPostPatch = nxpPost * nypPost * nfpPost; // Post-synaptic weights are never shrunken float sumW = 0; //int kxPost, kyPost, kfPost; const int xScale = post->getXScale() - pre->getXScale(); const int yScale = post->getYScale() - pre->getYScale(); const double powXScale = pow(2.0f, (double) xScale); const double powYScale = pow(2.0f, (double) yScale); nxpPost = (int) (nxp * powXScale); nypPost = (int) (nyp * powYScale); nfpPost = pre->clayer->loc.nf; for(int axonID=0;axonID<numberOfAxonalArborLists();axonID++) { // loop through post-synaptic neurons (non-extended indices) for (int kPost = 0; kPost < post_tr->numItems; kPost++) { pvwdata_t ** postData = wPostDataStartp[axonID] + numPostPatch*kPost + 0; for (int kp = 0; kp < numPostPatch; kp++) { sumW += *(postData[kp]); } for (int kp = 0; kp < numPostPatch; kp++) { *(postData[kp]) = ((*postData[kp])/sumW)*synscaling_v; } //printf("%f ",sumW); sumW = 0; } //printf("\n"); } } return 0; }
int InhibSTDPConn::updateWeights(int arborID) { // Steps: // 2. Update pre_stdp_tr[arborID] // 3. Update w_ij const float dt = parent->getDeltaTime(); const float decayLTP = exp(-dt / tauLTP); //Extended Pre const int nkPre = pre->getNumExtended(); assert(nkPre == getNumWeightPatches()); //Restricted Post const pvdata_t * aPost = post->getLayerData(getDelay(arborID)); pvdata_t * post_stdp_tr_m; // Postsynaptic trace matrix; i.e. data of post_stdp_tr struct pvdata_t * post_oja_tr_m; // Postsynaptic mean trace matrix pvdata_t * ampLTD_m; // local ampLTD //Extended Pre const pvdata_t * preLayerData = pre->getLayerData(getDelay(arborID)); pvdata_t aPre; pvdata_t * pre_stdp_tr_m; // Presynaptic trace matrix pvwdata_t * W; // Weight matrix pointer //Restricted post vals const int postNx = post->getLayerLoc()->nx; const int postNy = post->getLayerLoc()->ny; const int postNf = post->getLayerLoc()->nf; const PVHalo * postHalo = &post->getLayerLoc()->halo; //stride in restricted space const int postStrideYRes = postNf * postNx; int nk, ny; #ifdef SPLIT_PRE_POST //Separate LTD and LTP calculations to take advantage of sparsity //Loop over postsynaptic neurons for post before pre (tau'') const int numPostPatch = nxpPost * nypPost * nfpPost; // Number of pre-neurons in post receptive field. Postsynaptic weights are never shrunken //Update all pre traces (all traces decay every time step) for (int kPreExt = 0; kPreExt < nkPre; kPreExt++) // Loop over all presynaptic neurons { aPre = preLayerData[kPreExt]; // Spiking activity pre_stdp_tr_m = &(pre_stdp_tr[arborID]->data[kPreExt]); // PreTrace for given presynaptic neuron kPreExt *pre_stdp_tr_m = decayLTP * ((*pre_stdp_tr_m) + aPre); //If spiked, minimum is 1. If no spike, minimum is 0. } pvwdata_t * startAdd = this->get_wDataStart(arborID); // Address of first neuron in pre layer //Loop through postsynaptic neurons (non-extended indices) for (int kPost = 0; kPost < post->getNumNeurons(); kPost++) { //Neuron indices //Post in extended space if (aPost[kPost] == 0) { //No LTP if post does not spike continue; } pvdata_t ** postData = getPostWeightsp(arborID,kPost); // Pointer array full of addresses pointing to the weights for all of the preNeurons connected to the given postNeuron's receptive field for (int kPrePatch=0; kPrePatch < numPostPatch; kPrePatch++) { // Loop through all pre-neurons connected to given post-neuron float * kPreAdd = postData[kPrePatch]; // Address of preNeuron in receptive field of postNeuron assert(kPreAdd != NULL); int kPreExt = (kPreAdd-startAdd) / (this->xPatchSize()*this->yPatchSize()*this->fPatchSize()); // Grab index based on patch size assert(kPreExt < nkPre); // Pre in extended space pre_stdp_tr_m = &(pre_stdp_tr[arborID]->data[kPreExt]); // PreTrace for given presynaptic neuron kPreExt // See STDP_LCA_Equations.pdf in documentation for description of feed-forward inhibitory weight adaptation equations. TODO: That file does not exist. //STDP Equation (*postData[kPrePatch]) -= dWMax * ampLTP * aPost[kPost] * (*pre_stdp_tr_m); (*postData[kPrePatch]) = (*postData[kPrePatch]) < wMin ? wMin : (*postData[kPrePatch]); // Stop weights from going all the way to 0 } } // Pre-synaptic neurons for Pre Before Post (tau') for (int kPreExt = 0; kPreExt < nkPre; kPreExt++) // Loop over all presynaptic neurons { //Pre in extended space aPre = preLayerData[kPreExt]; // Spiking activity if (aPre == 0) { //No LTD if pre does not spike continue; } size_t postOffsetExt = getAPostOffset(kPreExt, arborID); // Gets start index for postsynaptic vectors for given presynaptic neuron and axon // size_t postOffsetRes = postOffsetExt - (postNb * (postNx + 2*postNb) + postNb); size_t postOffsetRes = kIndexRestricted(postOffsetExt, postNx, postNy, postNf, postNb); //Post in restricted space post_stdp_tr_m = &(post_stdp_tr->data[postOffsetRes]); // Reference to STDP post trace (local) ampLTD_m = &(ampLTD[postOffsetRes]); // Points to local address W = get_wData(arborID, kPreExt); // Pointer to data of given axon & presynaptic neuron // Get weights in form of a patch (nx,ny,nf) // nk and ny are the number of neurons connected to the given presynaptic neuron in the x*nfp and y // if each of the presynaptic neurons connects to all postsynaptic than nk*ny = nkPost TODO: Is this true? Rui says yes. PVPatch * w = getWeights(kPreExt, arborID); // Get weights in form of a patch (nx,ny,nf), TODO: what's the role of the offset? nk = nfp * w->nx; // one line in x at a time ny = w->ny; // 3. Update weights for (int y = 0; y < ny; y++) { for (int kPatchLoc = 0; kPatchLoc < nk; kPatchLoc++) { //loop over all postsynaptic neurons connected to given presynaptic neuron //STDP Equation W[kPatchLoc] += dWMax * ampLTD_m[kPatchLoc] * aPre * post_stdp_tr_m[kPatchLoc]; W[kPatchLoc] = W[kPatchLoc] < wMin ? wMin : W[kPatchLoc]; // Stop weights from going all the way to 0 } // advance pointers in y W += syp; // postActivity and post trace are extended layer post_stdp_tr_m += postStrideYRes; ampLTD_m += postStrideYRes; } } #else // this stride is in extended space for post-synaptic activity and STDP decrement variable const int postStrideYExt = postNf * (postNx + postHalo->lt + postHalo->rt); for (int kPreExt = 0; kPreExt < nkPre; kPreExt++) // Loop over all presynaptic neurons { size_t postOffsetExt = getAPostOffset(kPreExt, arborID); // Gets start index for postsynaptic vectors for given presynaptic neuron and axon // size_t postOffsetRes = postOffsetExt - (postNb * (postNx + 2*postNb) + postNb); size_t postOffsetRes = kIndexRestricted(postOffsetExt, postNx, postNy, postNf, postHalo->lt, postHalo->rt, postHalo->dn, postHalo->up); //Post in extended space aPost = &post->getLayerData()[postOffsetExt]; // Gets address of postsynaptic activity //Post in restricted space post_stdp_tr_m = &(post_stdp_tr->data[postOffsetRes]); // Reference to STDP post trace (local) ampLTD_m = &(ampLTD[postOffsetRes]); // Points to local address //Pre in extended space aPre = preLayerData[kPreExt]; // Spiking activity pre_stdp_tr_m = &(pre_stdp_tr[arborID]->data[kPreExt]); // PreTrace for given presynaptic neuron kPre W = get_wData(arborID, kPreExt); // Pointer to data of given axon & presynaptic neuron // Get weights in form of a patch (nx,ny,nf) // nk and ny are the number of neurons connected to the given presynaptic neuron in the x*nfp and y // if each of the presynaptic neurons connects to all postsynaptic than nk*ny = nkPost TODO: Is this true? Rui says yes. PVPatch * w = getWeights(kPreExt, arborID); // Get weights in form of a patch (nx,ny,nf), TODO: what's the role of the offset? nk = nfp * w->nx; // one line in x at a time ny = w->ny; // 2. Updates the presynaptic trace *pre_stdp_tr_m = decayLTP * ((*pre_stdp_tr_m) + aPre); //If spiked, minimum is 1. If no spike, minimum is 0. // 3. Update weights for (int y = 0; y < ny; y++) { for (int kPatchLoc = 0; kPatchLoc < nk; kPatchLoc++) { //loop over all postsynaptic neurons connected to given presynaptic neuron // See STDP_LCA_Equations.pdf in documentation for description of feed-forward inhibitory weight adaptation equations. TODO: That file does not exist. //STDP Equation W[kPatchLoc] += dWMax * (ampLTD_m[kPatchLoc] * aPre * post_stdp_tr_m[kPatchLoc] - ampLTP * aPost[kPatchLoc] * (*pre_stdp_tr_m)); W[kPatchLoc] = W[kPatchLoc] < wMin ? wMin : W[kPatchLoc]; // Stop weights from going all the way to 0 } // advance pointers in y W += syp; // postActivity and post trace are extended layer aPost += postStrideYExt; //TODO: is this really in the extended space? post_stdp_tr_m += postStrideYRes; post_oja_tr_m += postStrideYRes; ampLTD_m += postStrideYRes; } } #endif return 0; }