Esempio n. 1
0
int GradientCheckConn::calc_dW() {
   assert(plasticityFlag);
   int status;
   //for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
   //   status = initialize_dW(arborId);
   //   if (status==PV_BREAK) { break; }
   //   assert(status == PV_SUCCESS);
   //}
   for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
      status = update_dW(arborId);
      if (status==PV_BREAK) { break; }
      assert(status == PV_SUCCESS);
   }
   for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
      status = reduce_dW(arborId);
      if (status==PV_BREAK) { break; }
      assert(status == PV_SUCCESS);
   }
   for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
      status = normalize_dW(arborId);
      if (status==PV_BREAK) { break; }
      assert(status == PV_SUCCESS);
   }
   return PV_SUCCESS;
}
Esempio n. 2
0
int MomentumConn::calc_dW() {
   assert(plasticityFlag);
   int status;
   if(timeBatchIdx >= timeBatchPeriod){
      timeBatchIdx = 0;
   }
   else{
      timeBatchIdx++;
   }

   //Clear at time 0, update at time timeBatchPeriod - 1
   bool need_update_w = false;
   bool need_clear_dw = false;
   if(timeBatchIdx == 0){
      need_clear_dw = true;
   }
   if(timeBatchIdx == timeBatchPeriod - 1){
      need_update_w = true;
   }

   for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
      //Clear every batch period
      if(need_clear_dw){
         status = initialize_dW(arborId);
         if (status==PV_BREAK) { break; }
         assert(status == PV_SUCCESS);
      }
   }

   for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
      //Sum up parts every timestep
      status = update_dW(arborId);
      if (status==PV_BREAK) { break; }
      assert(status == PV_SUCCESS);
   }

   for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
      //Reduce only when we need to update
      if(need_update_w){
         status = reduce_dW(arborId);
         if (status==PV_BREAK) { break; }
         assert(status == PV_SUCCESS);
      }
   }

   for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
      //Normalize only when reduced
      if(need_update_w){
         status = normalize_dW(arborId);
         if (status==PV_BREAK) { break; }
         assert(status == PV_SUCCESS);
      }
   }
   return PV_SUCCESS;
}
Esempio n. 3
0
int MomentumConn::allocateDataStructures(){
   HyPerConn::allocateDataStructures();
   if (!plasticityFlag) return PV_SUCCESS;
   int sx = nfp;
   int sy = sx * nxp;
   int sp = sy * nyp;
   int nPatches = getNumDataPatches();

   const int numAxons = numberOfAxonalArborLists();

   //Allocate dw buffer for previous dw
   prev_dwDataStart = (pvwdata_t **) calloc(numAxons, sizeof(pvwdata_t *));
   if( prev_dwDataStart == NULL ) {
      createArborsOutOfMemory();
      assert(false);
   }
   prev_dwDataStart[0] = (pvwdata_t*) calloc(numAxons * nxp * nyp * nfp * nPatches, sizeof(pvwdata_t));
   assert(prev_dwDataStart[0] != NULL);
   for (int arborId = 0; arborId < numAxons; arborId++) {
      prev_dwDataStart[arborId] = (prev_dwDataStart[0] + sp * nPatches * arborId);
      assert(prev_dwDataStart[arborId] != NULL);
   } // loop over arbors

   assert(clones.size() == 0);

   return PV_SUCCESS;
}
Esempio n. 4
0
int MomentumConn::updateWeights(int arborId){
   if(timeBatchIdx != timeBatchPeriod - 1){
      return PV_SUCCESS;
   }
   //Add momentum right before updateWeights
   for(int kArbor = 0; kArbor < this->numberOfAxonalArborLists(); kArbor++){
      applyMomentum(arborId);
   }

   //Saved to prevweights
   assert(prev_dwDataStart);
   std::memcpy(*prev_dwDataStart, *get_dwDataStart(),
         sizeof(pvwdata_t) *
         numberOfAxonalArborLists() * 
         nxp * nyp * nfp *
         getNumDataPatches());


   // add dw to w
   for(int kArbor = 0; kArbor < this->numberOfAxonalArborLists(); kArbor++){
      pvwdata_t * w_data_start = get_wDataStart(kArbor);
      for( long int k=0; k<patchStartIndex(getNumDataPatches()); k++ ) {
         w_data_start[k] += get_dwDataStart(kArbor)[k];
      }
   }
   return PV_BREAK;
}
Esempio n. 5
0
int MomentumConn::checkpointRead(const char * cpDir, double * timeptr) {
   HyPerConn::checkpointRead(cpDir, timeptr);
   if (!plasticityFlag) return PV_SUCCESS;
   clearWeights(prev_dwDataStart, getNumDataPatches(), nxp, nyp, nfp);
   char * path = parent->pathInCheckpoint(cpDir, getName(), "_prev_dW.pvp");
   PVPatch *** patches_arg = sharedWeights ? NULL : get_wPatches();
   double filetime=0.0;
   int status = PV::readWeights(patches_arg, prev_dwDataStart, numberOfAxonalArborLists(), getNumDataPatches(), nxp, nyp, nfp, path, parent->icCommunicator(), &filetime, pre->getLayerLoc());
   if (parent->columnId()==0 && timeptr && *timeptr != filetime) {
      fprintf(stderr, "Warning: \"%s\" checkpoint has timestamp %g instead of the expected value %g.\n", path, filetime, *timeptr);
   }
   free(path);
   return status;
}
Esempio n. 6
0
/**
 * First function to be executed
 * Updates the postsynaptic trace and calls the updateWeights function
 */
int STDP3Conn::updateState(double time, double dt)
{
   update_timer->start();

   int status=0;
   if (stdpFlag) {

      //const int axonId = 0;       // assume only one for now
      for(int axonId = 0; axonId<numberOfAxonalArborLists(); axonId++) {
         status=updateWeights(axonId);
      }
   }
   update_timer->stop();

   //const int axonId = 0;       // assume only one for now
   //return updateWeights(axonId);
   return status;
}
Esempio n. 7
0
int VaryingHyPerConn::allocateDataStructures() {
   HyPerConn::allocateDataStructures();
   // initialize all dW's to one.
   int syPatch = yPatchStride();
   for(int kAxon = 0; kAxon < numberOfAxonalArborLists(); kAxon++){
      for(int kPatch = 0; kPatch < getNumDataPatches(); kPatch++){
         PVPatch * W = getWeights(kPatch, kAxon);
         int nkPatch = fPatchSize() * W->nx;
         float * dWdata = get_dwData(kAxon, kPatch);
         for(int kyPatch = 0; kyPatch < W->ny; kyPatch++){
            for(int kPatch = 0; kPatch < nkPatch; kPatch++){
               dWdata[kPatch] = 1.0f;
            }
            dWdata += syPatch;
         }
      }
   }

   return PV_SUCCESS;
}
Esempio n. 8
0
int MomentumConn::allocateDataStructures(){
   int status = HyPerConn::allocateDataStructures();
   if (status==PV_POSTPONE) { return status; }
   if (!plasticityFlag) return status;
   int sx = nfp;
   int sy = sx * nxp;
   int sp = sy * nyp;
   int nPatches = getNumDataPatches();

   const int numAxons = numberOfAxonalArborLists();

   //Allocate dw buffer for previous dw
   prev_dwDataStart = (pvwdata_t **) pvCalloc(numAxons, sizeof(pvwdata_t *));
   prev_dwDataStart[0] = (pvwdata_t*) pvCalloc(numAxons * nxp * nyp * nfp * nPatches, sizeof(pvwdata_t));
   for (int arborId = 0; arborId < numAxons; arborId++) {
      prev_dwDataStart[arborId] = (prev_dwDataStart[0] + sp * nPatches * arborId);
      assert(prev_dwDataStart[arborId] != NULL);
   } // loop over arbors

   //assert(clones.size() == 0);

   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. 10
0
//Connections update first
int GradientCheckConn::updateState(double time, double dt){
   int status = PV_SUCCESS;
   int weightIdx = parent->getCurrentStep() - parent->getInitialStep() - 2;
   std::cout << "weightIdx " << weightIdx << "\n";
   int numPatch = nxp * nyp * nfp;
   int numData = getNumDataPatches();
   int arborIdx = weightIdx / (numPatch * numData);
   int dataIdx = (weightIdx / numPatch) % numData;
   int patchIdx = weightIdx % numPatch;

   if(firstRun){
      initialize_dW(0);
      firstRun = false;
      return PV_SUCCESS;
   }
   
   //Grab cost from previous timestep
   if(secondRun){
      //First run does regular updateState to calculate dw buffer
      for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) {
         status = calc_dW();        // Calculate changes in weights
         if (status==PV_BREAK) { break; }
         assert(status == PV_SUCCESS);
      }
      //for (int arborID = 0; arborID < numberOfAxonalArborLists(); arborID++) {
      //   if(sharedWeights){
      //      status = reduceKernels(arborID); // combine partial changes in each column
      //      if (status == PV_BREAK) {
      //         break;
      //      }
      //      assert(status == PV_SUCCESS);
      //   }
      //}
      //No update weights
      origCost = getCost();
      secondRun = false;
   }

   //Does not update after first run
   //Check if we are in bounds for non-shared weights
   if(!sharedWeights){
      PVPatch* weights = getWeights(dataIdx, arborIdx);
      //Calculate x and y of patchIdx and compare it to offset
      int xPatchIdx = kxPos(patchIdx, nxp, nyp, nfp);
      int yPatchIdx = kyPos(patchIdx, nxp, nyp, nfp);
      int xOffsetIdx = kxPos(weights->offset, nxp, nyp, nfp);
      int yOffsetIdx = kyPos(weights->offset, nxp, nyp, nfp);

      //If index is oob, skip
      if(xPatchIdx < xOffsetIdx || xPatchIdx >= xOffsetIdx + weights->nx ||
         yPatchIdx < yOffsetIdx || yPatchIdx >= yOffsetIdx + weights->ny){
         return PV_SUCCESS;
      }
   }

   //Calculate difference in numerical method and backprop method
   if(prevIdx != -1){
      currCost = getCost();
      //Check for accuracy
      float numGradient = (currCost - origCost)/epsilon;
      float backpropGradient = get_dwDataStart()[0][prevIdx] / dWMax;
      std::cout << "Numerical gradient: " << numGradient << "  Backprop gradient: " << backpropGradient << "\n";

      //if(fabs(numGradient + backpropGradient) >= .1){
      //   std::cout << "Numerical gradient: " << numGradient << "  Backprop gradient: " << backpropGradient << "\n";
      //   exit(-1);

      //}
   }

   //Restore weight
   if(prevIdx != -1){
      std::cout << "Restoring weight " << prevIdx << " to " << prevWeightVal << "\n";
      get_wDataStart()[0][prevIdx] = prevWeightVal;
   }

   //Set next weight if not the end
   if(weightIdx < numberOfAxonalArborLists() * numData * numPatch){
      prevWeightVal = get_wDataStart()[0][weightIdx];
      prevIdx = weightIdx;
      get_wDataStart()[0][weightIdx] += epsilon;
      std::cout << "Setting weight " << weightIdx << " to " << prevWeightVal + epsilon << "\n";
   }
   else{
      std::cout << "END\n";
   }

   return status;
}
Esempio n. 11
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;
}