Esempio n. 1
0
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;
}
Esempio n. 3
0
/**
 *  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;
}
Esempio n. 4
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;
}