예제 #1
0
  /**
   * Perform global inhibition. Performing global inhibition entails picking the top 'numActive'
   * columns with the highest overlap score in the entire region. At most half of the columns in a
   * local neighborhood are allowed to be active.
   *
   * @param c the {@link Connections} matrix
   * @param overlaps an array containing the overlap score for each column. The overlap score for a
   *     column is defined as the number of synapses in a "connected state" (connected synapses)
   *     that are connected to input bits which are turned on.
   * @param density The fraction of columns to survive inhibition.
   * @return
   */
  public int[] inhibitColumnsGlobal(Connections c, double[] overlaps, double density) {
    int numCols = c.getNumColumns();
    int numActive = (int) (density * numCols);

    Comparator<Pair<Integer, Double>> comparator =
        (p1, p2) -> {
          int p1key = p1.getKey();
          int p2key = p2.getKey();
          double p1val = p1.getValue();
          double p2val = p2.getValue();
          if (Math.abs(p2val - p1val) < 0.000000001) {
            return Math.abs(p2key - p1key) < 0.000000001 ? 0 : p2key > p1key ? 1 : -1;
          } else {
            return p2val > p1val ? 1 : -1;
          }
        };
    int[] inhibit =
        IntStream.range(0, overlaps.length)
            .mapToObj(i -> new Pair<>(i, overlaps[i]))
            .sorted(comparator)
            .mapToInt(Pair<Integer, Double>::getKey)
            .limit(numActive)
            .sorted()
            .toArray();

    return inhibit;
  }
예제 #2
0
  /**
   * Update the boost factors for all columns. The boost factors are used to increase the overlap of
   * inactive columns to improve their chances of becoming active. and hence encourage participation
   * of more columns in the learning process. This is a line defined as: y = mx + b boost =
   * (1-maxBoost)/minDuty * dutyCycle + maxFiringBoost. Intuitively this means that columns that
   * have been active enough have a boost factor of 1, meaning their overlap is not boosted. Columns
   * whose active duty cycle drops too much below that of their neighbors are boosted depending on
   * how infrequently they have been active. The more infrequent, the more they are boosted. The
   * exact boost factor is linearly interpolated between the points (dutyCycle:0,
   * boost:maxFiringBoost) and (dutyCycle:minDuty, boost:1.0).
   *
   * <p>boostFactor ^ maxBoost _ | |\ | \ 1 _ | \ _ _ _ _ _ _ _ | +-------------------->
   * activeDutyCycle | minActiveDutyCycle
   */
  public void updateBoostFactors(Connections c) {
    double[] activeDutyCycles = c.getActiveDutyCycles();
    double[] minActiveDutyCycles = c.getMinActiveDutyCycles();

    // Indexes of values > 0
    int[] mask = ArrayUtils.where(minActiveDutyCycles, ArrayUtils.GREATER_THAN_0);

    double[] boostInterim;
    if (mask.length < 1) {
      boostInterim = c.getBoostFactors();
    } else {
      double[] numerator = new double[c.getNumColumns()];
      Arrays.fill(numerator, 1 - c.getMaxBoost());
      boostInterim = ArrayUtils.divide(numerator, minActiveDutyCycles, 0, 0);
      boostInterim = ArrayUtils.multiply(boostInterim, activeDutyCycles, 0, 0);
      boostInterim = ArrayUtils.d_add(boostInterim, c.getMaxBoost());
    }

    ArrayUtils.setIndexesTo(
        boostInterim,
        ArrayUtils.where(
            activeDutyCycles,
            new Condition.Adapter<Object>() {
              int i = 0;

              @Override
              public boolean eval(double d) {
                return d > minActiveDutyCycles[i++];
              }
            }),
        1.0d);

    c.setBoostFactors(boostInterim);
  }
예제 #3
0
  /**
   * Updates the duty cycles for each column. The OVERLAP duty cycle is a moving average of the
   * number of inputs which overlapped with each column. The ACTIVITY duty cycles is a moving
   * average of the frequency of activation for each column.
   *
   * @param c the {@link Connections} (spatial pooler memory)
   * @param overlaps an array containing the overlap score for each column. The overlap score for a
   *     column is defined as the number of synapses in a "connected state" (connected synapses)
   *     that are connected to input bits which are turned on.
   * @param activeColumns An array containing the indices of the active columns, the sparse set of
   *     columns which survived inhibition
   */
  public void updateDutyCycles(Connections c, int[] overlaps, int[] activeColumns) {
    double[] overlapArray = new double[c.getNumColumns()];
    double[] activeArray = new double[c.getNumColumns()];
    ArrayUtils.greaterThanXThanSetToYInB(overlaps, overlapArray, 0, 1);
    if (activeColumns.length > 0) {
      ArrayUtils.setIndexesTo(activeArray, activeColumns, 1);
    }

    int period = c.getDutyCyclePeriod();
    if (period > c.getIterationNum()) {
      period = c.getIterationNum();
    }

    c.setOverlapDutyCycles(
        updateDutyCyclesHelper(c, c.getOverlapDutyCycles(), overlapArray, period));

    c.setActiveDutyCycles(updateDutyCyclesHelper(c, c.getActiveDutyCycles(), activeArray, period));
  }
예제 #4
0
 /**
  * Updates the minimum duty cycles. The minimum duty cycles are determined locally. Each column's
  * minimum duty cycles are set to be a percent of the maximum duty cycles in the column's
  * neighborhood. Unlike {@link #updateMinDutyCyclesGlobal(Connections)}, here the values can be
  * quite different for different columns.
  *
  * @param c
  */
 public void updateMinDutyCyclesLocal(Connections c) {
   int len = c.getNumColumns();
   for (int i = 0; i < len; i++) {
     int[] maskNeighbors =
         getNeighborsND(c, i, c.getMemory(), c.getInhibitionRadius(), true).toArray();
     c.getMinOverlapDutyCycles()[i] =
         ArrayUtils.max(ArrayUtils.sub(c.getOverlapDutyCycles(), maskNeighbors))
             * c.getMinPctOverlapDutyCycles();
     c.getMinActiveDutyCycles()[i] =
         ArrayUtils.max(ArrayUtils.sub(c.getActiveDutyCycles(), maskNeighbors))
             * c.getMinPctActiveDutyCycles();
   }
 }
예제 #5
0
 /**
  * Performs inhibition. This method calculates the necessary values needed to actually perform
  * inhibition and then delegates the task of picking the active columns to helper functions.
  *
  * @param c the {@link Connections} matrix
  * @param overlaps an array containing the overlap score for each column. The overlap score for a
  *     column is defined as the number of synapses in a "connected state" (connected synapses)
  *     that are connected to input bits which are turned on.
  * @param density The fraction of columns to survive inhibition. This value is only an intended
  *     target. Since the surviving columns are picked in a local fashion, the exact fraction of
  *     surviving columns is likely to vary.
  * @return indices of the winning columns
  */
 public int[] inhibitColumnsLocal(Connections c, double[] overlaps, double density) {
   int numCols = c.getNumColumns();
   int[] activeColumns = new int[numCols];
   double addToWinners = ArrayUtils.max(overlaps) / 1000.0;
   for (int i = 0; i < numCols; i++) {
     TIntArrayList maskNeighbors =
         getNeighborsND(c, i, c.getMemory(), c.getInhibitionRadius(), false);
     double[] overlapSlice = ArrayUtils.sub(overlaps, maskNeighbors.toArray());
     int numActive = (int) (0.5 + density * (maskNeighbors.size() + 1));
     int numBigger = ArrayUtils.valueGreaterCount(overlaps[i], overlapSlice);
     if (numBigger < numActive) {
       activeColumns[i] = 1;
       overlaps[i] += addToWinners;
     }
   }
   return ArrayUtils.where(activeColumns, ArrayUtils.INT_GREATER_THAN_0);
 }
예제 #6
0
  /**
   * Update the inhibition radius. The inhibition radius is a measure of the square (or hypersquare)
   * of columns that each a column is "connected to" on average. Since columns are are not connected
   * to each other directly, we determine this quantity by first figuring out how many *inputs* a
   * column is connected to, and then multiplying it by the total number of columns that exist for
   * each input. For multiple dimension the aforementioned calculations are averaged over all
   * dimensions of inputs and columns. This value is meaningless if global inhibition is enabled.
   *
   * @param c the {@link Connections} (spatial pooler memory)
   */
  public void updateInhibitionRadius(Connections c) {
    if (c.getGlobalInhibition()) {
      c.setInhibitionRadius(ArrayUtils.max(c.getColumnDimensions()));
      return;
    }

    TDoubleArrayList avgCollected = new TDoubleArrayList();
    int len = c.getNumColumns();
    for (int i = 0; i < len; i++) {
      avgCollected.add(avgConnectedSpanForColumnND(c, i));
    }
    double avgConnectedSpan = ArrayUtils.average(avgCollected.toArray());
    double diameter = avgConnectedSpan * avgColumnsPerInput(c);
    double radius = (diameter - 1) / 2.0d;
    radius = Math.max(1, radius);
    c.setInhibitionRadius((int) Math.round(radius));
  }
예제 #7
0
  /**
   * Removes the set of columns who have never been active from the set of active columns selected
   * in the inhibition round. Such columns cannot represent learned pattern and are therefore
   * meaningless if only inference is required. This should not be done when using a random,
   * unlearned SP since you would end up with no active columns.
   *
   * @param activeColumns An array containing the indices of the active columns
   * @return a list of columns with a chance of activation
   */
  public int[] stripUnlearnedColumns(Connections c, int[] activeColumns) {
    TIntHashSet active = new TIntHashSet(activeColumns);
    TIntHashSet aboveZero = new TIntHashSet();
    int numCols = c.getNumColumns();
    double[] colDutyCycles = c.getActiveDutyCycles();
    for (int i = 0; i < numCols; i++) {
      if (colDutyCycles[i] <= 0) {
        aboveZero.add(i);
      }
    }
    active.removeAll(aboveZero);
    TIntArrayList l = new TIntArrayList(active);
    l.sort();
    // return l;

    return Arrays.stream(activeColumns).filter(i -> c.getActiveDutyCycles()[i] > 0).toArray();
  }
예제 #8
0
  /**
   * Step two of pooler initialization kept separate from initialization of static members so that
   * they may be set at a different point in the initialization (as sometimes needed by tests).
   *
   * <p>This step prepares the proximal dendritic synapse pools with their initial permanence values
   * and connected inputs.
   *
   * @param c the {@link Connections} memory
   */
  public void connectAndConfigureInputs(Connections c) {
    // Initialize the set of permanence values for each column. Ensure that
    // each column is connected to enough input bits to allow it to be
    // activated.
    int numColumns = c.getNumColumns();
    for (int i = 0; i < numColumns; i++) {
      int[] potential = mapPotential(c, i, true);
      Column column = c.getColumn(i);
      c.getPotentialPools().set(i, column.createPotentialPool(c, potential));
      double[] perm = initPermanence(c, potential, i, c.getInitConnectedPct());
      updatePermanencesForColumn(c, perm, column, potential, true);
    }

    // The inhibition radius determines the size of a column's local
    // neighborhood.  A cortical column must overcome the overlap score of
    // columns in its neighborhood in order to become active. This radius is
    // updated every learning round. It grows and shrinks with the average
    // number of connected synapses per column.
    updateInhibitionRadius(c);
  }
예제 #9
0
  /**
   * Performs inhibition. This method calculates the necessary values needed to actually perform
   * inhibition and then delegates the task of picking the active columns to helper functions.
   *
   * @param c the {@link Connections} matrix
   * @param overlaps an array containing the overlap score for each column. The overlap score for a
   *     column is defined as the number of synapses in a "connected state" (connected synapses)
   *     that are connected to input bits which are turned on.
   * @return
   */
  public int[] inhibitColumns(Connections c, double[] overlaps) {
    overlaps = Arrays.copyOf(overlaps, overlaps.length);

    double density;
    double inhibitionArea;
    if ((density = c.getLocalAreaDensity()) <= 0) {
      inhibitionArea = Math.pow(2 * c.getInhibitionRadius() + 1, c.getColumnDimensions().length);
      inhibitionArea = Math.min(c.getNumColumns(), inhibitionArea);
      density = c.getNumActiveColumnsPerInhArea() / inhibitionArea;
      density = Math.min(density, 0.5);
    }

    // Add our fixed little bit of random noise to the scores to help break ties.
    // ArrayUtils.d_add(overlaps, c.getTieBreaker());

    if (c.getGlobalInhibition()
        || c.getInhibitionRadius() > ArrayUtils.max(c.getColumnDimensions())) {
      return inhibitColumnsGlobal(c, overlaps, density);
    }

    return inhibitColumnsLocal(c, overlaps, density);
  }
예제 #10
0
 /**
  * This function determines each column's overlap with the current input vector. The overlap of a
  * column is the number of synapses for that column that are connected (permanence value is
  * greater than '_synPermConnected') to input bits which are turned on. Overlap values that are
  * lower than the 'stimulusThreshold' are ignored. The implementation takes advantage of the
  * SpraseBinaryMatrix class to perform this calculation efficiently.
  *
  * @param c the {@link Connections} memory encapsulation
  * @param inputVector an input array of 0's and 1's that comprises the input to the spatial
  *     pooler.
  * @return
  */
 public int[] calculateOverlap(Connections c, int[] inputVector) {
   int[] overlaps = new int[c.getNumColumns()];
   c.getConnectedCounts().rightVecSumAtNZ(inputVector, overlaps, c.getStimulusThreshold());
   return overlaps;
 }