Пример #1
0
 /**
  * Updates the minimum duty cycles defining normal activity for a column. A column with activity
  * duty cycle below this minimum threshold is boosted.
  *
  * @param c
  */
 public void updateMinDutyCycles(Connections c) {
   if (c.getGlobalInhibition() || c.getInhibitionRadius() > c.getNumInputs()) {
     updateMinDutyCyclesGlobal(c);
   } else {
     updateMinDutyCyclesLocal(c);
   }
 }
Пример #2
0
 /**
  * This method ensures that each column has enough connections to input bits to allow it to become
  * active. Since a column must have at least 'stimulusThreshold' overlaps in order to be
  * considered during the inhibition phase, columns without such minimal number of connections,
  * even if all the input bits they are connected to turn on, have no chance of obtaining the
  * minimum threshold. For such columns, the permanence values are increased until the minimum
  * number of connections are formed.
  *
  * <p>Note: This method services the "sparse" versions of corresponding methods
  *
  * @param c The {@link Connections} memory
  * @param perm permanence values
  */
 public void raisePermanenceToThresholdSparse(Connections c, double[] perm) {
   ArrayUtils.clip(perm, c.getSynPermMin(), c.getSynPermMax());
   while (true) {
     int numConnected = ArrayUtils.valueGreaterCount(c.getSynPermConnected(), perm);
     if (numConnected >= c.getStimulusThreshold()) return;
     ArrayUtils.raiseValuesBy(c.getSynPermBelowStimulusInc(), perm);
   }
 }
Пример #3
0
 /**
  * The average number of columns per input, taking into account the topology of the inputs and
  * columns. This value is used to calculate the inhibition radius. This function supports an
  * arbitrary number of dimensions. If the number of column dimensions does not match the number of
  * input dimensions, we treat the missing, or phantom dimensions as 'ones'.
  *
  * @param c the {@link Connections} (spatial pooler memory)
  * @return
  */
 public double avgColumnsPerInput(Connections c) {
   int[] colDim = Arrays.copyOf(c.getColumnDimensions(), c.getColumnDimensions().length);
   int[] inputDim = Arrays.copyOf(c.getInputDimensions(), c.getInputDimensions().length);
   double[] columnsPerInput =
       ArrayUtils.divide(
           ArrayUtils.toDoubleArray(colDim), ArrayUtils.toDoubleArray(inputDim), 0, 0);
   return ArrayUtils.average(columnsPerInput);
 }
Пример #4
0
  /**
   * This method updates the permanence matrix with a column's new permanence values. The column is
   * identified by its index, which reflects the row in the matrix, and the permanence is given in
   * 'sparse' form, (i.e. an array whose members are associated with specific indexes). It is in
   * charge of implementing 'clipping' - ensuring that the permanence values are always between 0
   * and 1 - and 'trimming' - enforcing sparseness by zeroing out all permanence values below
   * 'synPermTrimThreshold'. Every method wishing to modify the permanence matrix should do so
   * through this method.
   *
   * @param c the {@link Connections} which is the memory model.
   * @param perm An array of permanence values for a column. The array is "sparse", i.e. it contains
   *     an entry for each input bit, even if the permanence value is 0.
   * @param column The column in the permanence, potential and connectivity matrices
   * @param raisePerm a boolean value indicating whether the permanence values
   */
  public void updatePermanencesForColumnSparse(
      Connections c, double[] perm, Column column, int[] maskPotential, boolean raisePerm) {
    if (raisePerm) {
      raisePermanenceToThresholdSparse(c, perm);
    }

    ArrayUtils.lessThanOrEqualXThanSetToY(perm, c.getSynPermTrimThreshold(), 0);
    ArrayUtils.clip(perm, c.getSynPermMin(), c.getSynPermMax());
    column.setProximalPermanencesSparse(c, perm, maskPotential);
  }
Пример #5
0
  /**
   * Returns a randomly generated permanence value for a synapses that is to be initialized in a
   * non-connected state.
   *
   * @return a randomly generated permanence value
   */
  public static double initPermNonConnected(Connections c) {
    double p = c.getSynPermConnected() * c.getRandom().nextDouble();

    // Note from Python implementation on conditioning below:
    // Ensure we don't have too much unnecessary precision. A full 64 bits of
    // precision causes numerical stability issues across platforms and across
    // implementations
    p = ((int) (p * 100000)) / 100000.0d;
    return p;
  }
Пример #6
0
  /**
   * Initializes the specified {@link Connections} object which contains the memory and structural
   * anatomy this spatial pooler uses to implement its algorithms.
   *
   * @param c a {@link Connections} object
   */
  public void init(Connections c) {
    if (c.getNumActiveColumnsPerInhArea() == 0
        && (c.getLocalAreaDensity() == 0 || c.getLocalAreaDensity() > 0.5)) {
      throw new InvalidSPParamValueException("Inhibition parameters are invalid");
    }

    c.doSpatialPoolerPostInit();
    initMatrices(c);
    connectAndConfigureInputs(c);
  }
Пример #7
0
  /**
   * Maps a column to its input bits. This method encapsulates the topology of the region. It takes
   * the index of the column as an argument and determines what are the indices of the input vector
   * that are located within the column's potential pool. The return value is a list containing the
   * indices of the input bits. The current implementation of the base class only supports a 1
   * dimensional topology of columns with a 1 dimensional topology of inputs. To extend this class
   * to support 2-D topology you will need to override this method. Examples of the expected output
   * of this method: * If the potentialRadius is greater than or equal to the entire input space,
   * (global visibility), then this method returns an array filled with all the indices * If the
   * topology is one dimensional, and the potentialRadius is 5, this method will return an array
   * containing 5 consecutive values centered on the index of the column (wrapping around if
   * necessary). * If the topology is two dimensional (not implemented), and the potentialRadius is
   * 5, the method should return an array containing 25 '1's, where the exact indices are to be
   * determined by the mapping from 1-D index to 2-D position.
   *
   * @param c {@link Connections} the main memory model
   * @param columnIndex The index identifying a column in the permanence, potential and connectivity
   *     matrices.
   * @param wrapAround A boolean value indicating that boundaries should be ignored.
   * @return
   */
  public int[] mapPotential(Connections c, int columnIndex, boolean wrapAround) {
    int index = mapColumn(c, columnIndex);
    TIntArrayList indices =
        getNeighborsND(c, index, c.getInputMatrix(), c.getPotentialRadius(), wrapAround);
    indices.add(index);
    // TODO: See https://github.com/numenta/nupic.core/issues/128
    indices.sort();

    int[] retVal = new int[(int) Math.round(indices.size() * c.getPotentialPct())];
    return ArrayUtils.sample(indices, retVal, c.getRandom());
  }
Пример #8
0
  /**
   * The primary method in charge of learning. Adapts the permanence values of the synapses based on
   * the input vector, and the chosen columns after inhibition round. Permanence values are
   * increased for synapses connected to input bits that are turned on, and decreased for synapses
   * connected to inputs bits that are turned off.
   *
   * @param c the {@link Connections} (spatial pooler memory)
   * @param inputVector a integer array that comprises the input to the spatial pooler. There exists
   *     an entry in the array for every input bit.
   * @param activeColumns an array containing the indices of the columns that survived inhibition.
   */
  public void adaptSynapses(Connections c, int[] inputVector, int[] activeColumns) {
    int[] inputIndices = ArrayUtils.where(inputVector, ArrayUtils.INT_GREATER_THAN_0);

    double[] permChanges = new double[c.getNumInputs()];
    Arrays.fill(permChanges, -1 * c.getSynPermInactiveDec());
    ArrayUtils.setIndexesTo(permChanges, inputIndices, c.getSynPermActiveInc());
    for (int i = 0; i < activeColumns.length; i++) {
      Pool pool = c.getPotentialPools().get(activeColumns[i]);
      double[] perm = pool.getDensePermanences(c);
      int[] indexes = pool.getSparsePotential();
      ArrayUtils.raiseValuesBy(permChanges, perm);
      Column col = c.getColumn(activeColumns[i]);
      updatePermanencesForColumn(c, perm, col, indexes, true);
    }
  }
Пример #9
0
  /**
   * Initializes the permanences of a column. The method returns a 1-D array the size of the input,
   * where each entry in the array represents the initial permanence value between the input bit at
   * the particular index in the array, and the column represented by the 'index' parameter.
   *
   * @param c the {@link Connections} which is the memory model
   * @param potentialPool An array specifying the potential pool of the column. Permanence values
   *     will only be generated for input bits corresponding to indices for which the mask value is
   *     1. WARNING: potentialPool is sparse, not an array of "1's"
   * @param index the index of the column being initialized
   * @param connectedPct A value between 0 or 1 specifying the percent of the input bits that will
   *     start off in a connected state.
   * @return
   */
  public double[] initPermanence(
      Connections c, int[] potentialPool, int index, double connectedPct) {
    double[] perm = new double[c.getNumInputs()];
    for (int idx : potentialPool) {
      if (c.random.nextDouble() <= connectedPct) {
        perm[idx] = initPermConnected(c);
      } else {
        perm[idx] = initPermNonConnected(c);
      }

      perm[idx] = perm[idx] < c.getSynPermTrimThreshold() ? 0 : perm[idx];
    }
    c.getColumn(index).setProximalPermanences(c, perm);
    return perm;
  }
Пример #10
0
  /**
   * The range of connectedSynapses per column, averaged for each dimension. This value is used to
   * calculate the inhibition radius. This variation of the function supports arbitrary column
   * dimensions.
   *
   * @param c the {@link Connections} (spatial pooler memory)
   * @param columnIndex the current column for which to avg.
   * @return
   */
  public double avgConnectedSpanForColumnND(Connections c, int columnIndex) {
    int[] dimensions = c.getInputDimensions();
    int[] connected = c.getColumn(columnIndex).getProximalDendrite().getConnectedSynapsesSparse(c);
    if (connected == null || connected.length == 0) return 0;

    int[] maxCoord = new int[c.getInputDimensions().length];
    int[] minCoord = new int[c.getInputDimensions().length];
    Arrays.fill(maxCoord, -1);
    Arrays.fill(minCoord, ArrayUtils.max(dimensions));
    SparseMatrix<?> inputMatrix = c.getInputMatrix();
    for (int i = 0; i < connected.length; i++) {
      maxCoord = ArrayUtils.maxBetween(maxCoord, inputMatrix.computeCoordinates(connected[i]));
      minCoord = ArrayUtils.minBetween(minCoord, inputMatrix.computeCoordinates(connected[i]));
    }
    return ArrayUtils.average(ArrayUtils.add(ArrayUtils.subtract(maxCoord, minCoord), 1));
  }
Пример #11
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;
  }
Пример #12
0
 /**
  * Returns a dense array representing the potential pool bits with the connected bits set to 1.
  *
  * <p>Note: Only called from tests for now...
  *
  * @param c
  * @return
  */
 public int[] getDenseConnections(Connections c) {
   int[] retVal = new int[c.getNumInputs()];
   for (int inputIndex : synapseConnections.toArray()) {
     retVal[inputIndex] = 1;
   }
   return retVal;
 }
Пример #13
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();
   }
 }
Пример #14
0
 /**
  * Returns a dense array representing the potential pool permanences
  *
  * <p>Note: Only called from tests for now...
  *
  * @param c
  * @return
  */
 public double[] getDensePermanences(Connections c) {
   double[] retVal = new double[c.getNumInputs()];
   int[] keys = synapsesBySourceIndex.keys();
   for (int inputIndex : keys) {
     retVal[inputIndex] = synapsesBySourceIndex.get(inputIndex).getPermanence();
   }
   return retVal;
 }
Пример #15
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();
  }
Пример #16
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);
 }
Пример #17
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));
  }
Пример #18
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);
  }
Пример #19
0
 /**
  * Updates this {@code Pool}'s store of permanences for the specified {@link Synapse}
  *
  * @param c the connections memory
  * @param s the synapse who's permanence is recorded
  * @param permanence the permanence value to record
  */
 public void updatePool(Connections c, Synapse s, double permanence) {
   int inputIndex = s.getInputIndex();
   if (synapsesBySourceIndex.get(inputIndex) == null) {
     synapsesBySourceIndex.put(inputIndex, s);
   }
   if (permanence > c.getSynPermConnected()) {
     synapseConnections.add(inputIndex);
   } else {
     synapseConnections.remove(inputIndex);
   }
 }
Пример #20
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);
  }
Пример #21
0
  /**
   * This method increases the permanence values of synapses of columns whose activity level has
   * been too low. Such columns are identified by having an overlap duty cycle that drops too much
   * below those of their peers. The permanence values for such columns are increased.
   *
   * @param c
   */
  public void bumpUpWeakColumns(final Connections c) {
    int[] weakColumns =
        ArrayUtils.where(
            c.getMemory().get1DIndexes(),
            new Condition.Adapter<Integer>() {
              @Override
              public boolean eval(int i) {
                return c.getOverlapDutyCycles()[i] < c.getMinOverlapDutyCycles()[i];
              }
            });

    for (int i = 0; i < weakColumns.length; i++) {
      Pool pool = c.getPotentialPools().get(weakColumns[i]);
      double[] perm = pool.getSparsePermanences();
      ArrayUtils.raiseValuesBy(c.getSynPermBelowStimulusInc(), perm);
      int[] indexes = pool.getSparsePotential();
      Column col = c.getColumn(weakColumns[i]);
      updatePermanencesForColumnSparse(c, perm, col, indexes, true);
    }
  }
Пример #22
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));
  }
Пример #23
0
 /**
  * Updates the minimum duty cycles in a global fashion. Sets the minimum duty cycles for the
  * overlap and activation of all columns to be a percent of the maximum in the region, specified
  * by {@link Connections#getMinOverlapDutyCycles()} and minPctActiveDutyCycle respectively.
  * Functionality it is equivalent to {@link #updateMinDutyCyclesLocal(Connections)}, but this
  * function exploits the globalness of the computation to perform it in a straightforward, and
  * more efficient manner.
  *
  * @param c
  */
 public void updateMinDutyCyclesGlobal(Connections c) {
   Arrays.fill(
       c.getMinOverlapDutyCycles(),
       c.getMinPctOverlapDutyCycles() * ArrayUtils.max(c.getOverlapDutyCycles()));
   Arrays.fill(
       c.getMinActiveDutyCycles(),
       c.getMinPctActiveDutyCycles() * ArrayUtils.max(c.getActiveDutyCycles()));
 }
Пример #24
0
  /**
   * This is the primary public method of the SpatialPooler class. This function takes a input
   * vector and outputs the indices of the active columns. If 'learn' is set to True, this method
   * also updates the permanences of the columns.
   *
   * @param inputVector An array of 0's and 1's that comprises the input to the spatial pooler. The
   *     array will be treated as a one dimensional array, therefore the dimensions of the array do
   *     not have to match the exact dimensions specified in the class constructor. In fact, even a
   *     list would suffice. The number of input bits in the vector must, however, match the number
   *     of bits specified by the call to the constructor. Therefore there must be a '0' or '1' in
   *     the array for every input bit.
   * @param activeArray An array whose size is equal to the number of columns. Before the function
   *     returns this array will be populated with 1's at the indices of the active columns, and 0's
   *     everywhere else.
   * @param learn A boolean value indicating whether learning should be performed. Learning entails
   *     updating the permanence values of the synapses, and hence modifying the 'state' of the
   *     model. Setting learning to 'off' freezes the SP and has many uses. For example, you might
   *     want to feed in various inputs and examine the resulting SDR's.
   */
  public void compute(Connections c, int[] inputVector, int[] activeArray, boolean learn) {
    if (inputVector.length != c.getNumInputs()) {
      throw new InvalidSPParamValueException(
          "Input array must be same size as the defined number of inputs: From Params: "
              + c.getNumInputs()
              + ", From Input Vector: "
              + inputVector.length);
    }

    updateBookeepingVars(c, learn);
    int[] overlaps = c.setOverlaps(calculateOverlap(c, inputVector));

    double[] boostedOverlaps;
    if (learn) {
      boostedOverlaps = ArrayUtils.multiply(c.getBoostFactors(), overlaps);
    } else {
      boostedOverlaps = ArrayUtils.toDoubleArray(overlaps);
    }

    int[] activeColumns = inhibitColumns(c, c.setBoostedOverlaps(boostedOverlaps));

    if (learn) {
      adaptSynapses(c, inputVector, activeColumns);
      updateDutyCycles(c, overlaps, activeColumns);
      bumpUpWeakColumns(c);
      updateBoostFactors(c);
      if (isUpdateRound(c)) {
        updateInhibitionRadius(c);
        updateMinDutyCycles(c);
      }
    }

    Arrays.fill(activeArray, 0);
    if (activeColumns.length > 0) {
      ArrayUtils.setIndexesTo(activeArray, activeColumns, 1);
    }
  }
Пример #25
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);
  }
Пример #26
0
  /**
   * This method ensures that each column has enough connections to input bits to allow it to become
   * active. Since a column must have at least 'stimulusThreshold' overlaps in order to be
   * considered during the inhibition phase, columns without such minimal number of connections,
   * even if all the input bits they are connected to turn on, have no chance of obtaining the
   * minimum threshold. For such columns, the permanence values are increased until the minimum
   * number of connections are formed.
   *
   * @param c the {@link Connections} memory
   * @param perm the permanence values
   * @param maskPotential
   */
  public void raisePermanenceToThreshold(Connections c, double[] perm, int[] maskPotential) {
    if (maskPotential.length < c.getStimulusThreshold()) {
      throw new IllegalStateException(
          "This is likely due to a "
              + "value of stimulusThreshold that is too large relative "
              + "to the input size. [len(mask) < self._stimulusThreshold]");
    }

    ArrayUtils.clip(perm, c.getSynPermMin(), c.getSynPermMax());
    while (true) {
      int numConnected =
          ArrayUtils.valueGreaterCountAtIndex(c.getSynPermConnected(), perm, maskPotential);
      if (numConnected >= c.getStimulusThreshold()) return;
      ArrayUtils.raiseValuesBy(c.getSynPermBelowStimulusInc(), perm, maskPotential);
    }
  }
Пример #27
0
 /**
  * Maps a column to its respective input index, keeping to the topology of the region. It takes
  * the index of the column as an argument and determines what is the index of the flattened input
  * vector that is to be the center of the column's potential pool. It distributes the columns over
  * the inputs uniformly. The return value is an integer representing the index of the input bit.
  * Examples of the expected output of this method: * If the topology is one dimensional, and the
  * column index is 0, this method will return the input index 0. If the column index is 1, and
  * there are 3 columns over 7 inputs, this method will return the input index 3. * If the topology
  * is two dimensional, with column dimensions [3, 5] and input dimensions [7, 11], and the column
  * index is 3, the method returns input index 8.
  *
  * @param columnIndex The index identifying a column in the permanence, potential and connectivity
  *     matrices.
  * @return A boolean value indicating that boundaries should be ignored.
  */
 public int mapColumn(Connections c, int columnIndex) {
   int[] columnCoords = c.getMemory().computeCoordinates(columnIndex);
   double[] colCoords = ArrayUtils.toDoubleArray(columnCoords);
   double[] ratios =
       ArrayUtils.divide(colCoords, ArrayUtils.toDoubleArray(c.getColumnDimensions()), 0, 0);
   double[] inputCoords =
       ArrayUtils.multiply(ArrayUtils.toDoubleArray(c.getInputDimensions()), ratios, 0, 0);
   inputCoords =
       ArrayUtils.d_add(
           inputCoords,
           ArrayUtils.multiply(
               ArrayUtils.divide(
                   ArrayUtils.toDoubleArray(c.getInputDimensions()),
                   ArrayUtils.toDoubleArray(c.getColumnDimensions()),
                   0,
                   0),
               0.5));
   int[] inputCoordInts =
       ArrayUtils.clip(ArrayUtils.toIntArray(inputCoords), c.getInputDimensions(), -1);
   return c.getInputMatrix().computeIndex(inputCoordInts);
 }
Пример #28
0
 /**
  * Updates counter instance variables each cycle.
  *
  * @param c the {@link Connections} memory encapsulation
  * @param learn a boolean value indicating whether learning should be performed. Learning entails
  *     updating the permanence values of the synapses, and hence modifying the 'state' of the
  *     model. setting learning to 'off' might be useful for indicating separate training vs.
  *     testing sets.
  */
 public void updateBookeepingVars(Connections c, boolean learn) {
   c.spIterationNum += 1;
   if (learn) c.spIterationLearnNum += 1;
 }
Пример #29
0
 /**
  * Returns true if enough rounds have passed to warrant updates of duty cycles
  *
  * @param c the {@link Connections} memory encapsulation
  * @return
  */
 public boolean isUpdateRound(Connections c) {
   return c.getIterationNum() % c.getUpdatePeriod() == 0;
 }
Пример #30
0
 /**
  * Return the overlap to connected counts ratio for a given column
  *
  * @param c
  * @param overlaps
  * @return
  */
 public double[] calculateOverlapPct(Connections c, int[] overlaps) {
   return ArrayUtils.divide(overlaps, c.getConnectedCounts().getTrueCounts());
 }