/** * 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; }
/** * 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); } }
/** * 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)); }
/** * 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); } }
/** * 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); }