All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.numenta.nupic.Parameters Maven / Gradle / Ivy

There is a newer version: 0.6.13
Show newest version
/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2014, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

package org.numenta.nupic;

import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.joda.time.format.DateTimeFormatter;
import org.numenta.nupic.model.Cell;
import org.numenta.nupic.model.Column;
import org.numenta.nupic.model.DistalDendrite;
import org.numenta.nupic.research.ComputeCycle;
import org.numenta.nupic.research.SpatialPooler;
import org.numenta.nupic.research.TemporalMemory;
import org.numenta.nupic.util.ArrayUtils;
import org.numenta.nupic.util.BeanUtil;
import org.numenta.nupic.util.MersenneTwister;
import org.numenta.nupic.util.Tuple;

/**
 * Specifies parameters to be used as a configuration for a given {@link TemporalMemory}
 * or {@link SpatialPooler}
 *
 * @author David Ray
 * @author Kirill Solovyev
 * @see SpatialPooler
 * @see TemporalMemory
 * @see Connections
 * @see ComputeCycle
 */
public class Parameters {
    private static final Map DEFAULTS_ALL;
    private static final Map DEFAULTS_TEMPORAL;
    private static final Map DEFAULTS_SPATIAL;
    private static final Map DEFAULTS_ENCODER;


    static {
        Map defaultParams = new ParametersMap();

        /////////// Universal Parameters ///////////

        defaultParams.put(KEY.SEED, 42);
        defaultParams.put(KEY.RANDOM, new MersenneTwister((int)defaultParams.get(KEY.SEED)));

        /////////// Temporal Memory Parameters ///////////
        Map defaultTemporalParams = new ParametersMap();
        defaultTemporalParams.put(KEY.COLUMN_DIMENSIONS, new int[]{2048});
        defaultTemporalParams.put(KEY.CELLS_PER_COLUMN, 32);
        defaultTemporalParams.put(KEY.ACTIVATION_THRESHOLD, 13);
        defaultTemporalParams.put(KEY.LEARNING_RADIUS, 2048);
        defaultTemporalParams.put(KEY.MIN_THRESHOLD, 10);
        defaultTemporalParams.put(KEY.MAX_NEW_SYNAPSE_COUNT, 20);
        defaultTemporalParams.put(KEY.INITIAL_PERMANENCE, 0.21);
        defaultTemporalParams.put(KEY.CONNECTED_PERMANENCE, 0.5);
        defaultTemporalParams.put(KEY.PERMANENCE_INCREMENT, 0.10);
        defaultTemporalParams.put(KEY.PERMANENCE_DECREMENT, 0.10);
        defaultTemporalParams.put(KEY.TM_VERBOSITY, 0);
        defaultTemporalParams.put(KEY.LEARN, true);
        DEFAULTS_TEMPORAL = Collections.unmodifiableMap(defaultTemporalParams);
        defaultParams.putAll(DEFAULTS_TEMPORAL);

        //////////// Spatial Pooler Parameters ///////////
        Map defaultSpatialParams = new ParametersMap();
        defaultSpatialParams.put(KEY.INPUT_DIMENSIONS, new int[]{64});
        defaultSpatialParams.put(KEY.POTENTIAL_RADIUS, 16);
        defaultSpatialParams.put(KEY.POTENTIAL_PCT, 0.5);
        defaultSpatialParams.put(KEY.GLOBAL_INHIBITIONS, false);
        defaultSpatialParams.put(KEY.INHIBITION_RADIUS, 0);
        defaultSpatialParams.put(KEY.LOCAL_AREA_DENSITY, -1.0);
        defaultSpatialParams.put(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, 10.0);
        defaultSpatialParams.put(KEY.STIMULUS_THRESHOLD, 0.0);
        defaultSpatialParams.put(KEY.SYN_PERM_INACTIVE_DEC, 0.01);
        defaultSpatialParams.put(KEY.SYN_PERM_ACTIVE_INC, 0.1);
        defaultSpatialParams.put(KEY.SYN_PERM_CONNECTED, 0.10);
        defaultSpatialParams.put(KEY.SYN_PERM_BELOW_STIMULUS_INC, 0.01);
        defaultSpatialParams.put(KEY.SYN_PERM_TRIM_THRESHOLD, 0.5);
        defaultSpatialParams.put(KEY.MIN_PCT_OVERLAP_DUTY_CYCLE, 0.001);
        defaultSpatialParams.put(KEY.MIN_PCT_ACTIVE_DUTY_CYCLE, 0.001);
        defaultSpatialParams.put(KEY.DUTY_CYCLE_PERIOD, 1000);
        defaultSpatialParams.put(KEY.MAX_BOOST, 10.0);
        defaultSpatialParams.put(KEY.SP_VERBOSITY, 0);
        defaultSpatialParams.put(KEY.LEARN, true);
        DEFAULTS_SPATIAL = Collections.unmodifiableMap(defaultSpatialParams);
        defaultParams.putAll(DEFAULTS_SPATIAL);
        
        ///////////  Encoder Parameters ///////////
        Map defaultEncoderParams = new ParametersMap();
        defaultEncoderParams.put(KEY.N, 500);
        defaultEncoderParams.put(KEY.W, 21);
        defaultEncoderParams.put(KEY.MIN_VAL, 0.);
        defaultEncoderParams.put(KEY.MAX_VAL, 1000.);
        defaultEncoderParams.put(KEY.RADIUS, 21.);
        defaultEncoderParams.put(KEY.RESOLUTION, 1.);
        defaultEncoderParams.put(KEY.PERIODIC, false);
        defaultEncoderParams.put(KEY.CLIP_INPUT, false);
        defaultEncoderParams.put(KEY.FORCED, false);
        defaultEncoderParams.put(KEY.FIELD_NAME, "UNSET");
        defaultEncoderParams.put(KEY.FIELD_TYPE, "int");
        defaultEncoderParams.put(KEY.ENCODER, "ScalarEncoder");
        defaultEncoderParams.put(KEY.FIELD_ENCODING_MAP, Collections.emptyMap());
        defaultEncoderParams.put(KEY.AUTO_CLASSIFY, Boolean.FALSE);
        DEFAULTS_ENCODER = Collections.unmodifiableMap(defaultEncoderParams);
        defaultParams.putAll(DEFAULTS_ENCODER);

        DEFAULTS_ALL = Collections.unmodifiableMap(defaultParams);
    }

    /**
     * Constant values representing configuration parameters for the {@link TemporalMemory}
     */
    public static enum KEY {
        /////////// Universal Parameters ///////////
        /**
         * Total number of columns
         */
        COLUMN_DIMENSIONS("columnDimensions", int[].class),
        /**
         * Total number of cells per column
         */
        CELLS_PER_COLUMN("cellsPerColumn", Integer.class, 1, null),
        /**
         * Learning variable
         */
        LEARN("learn", Boolean.class),
        /**
         * Random Number Generator
         */
        RANDOM("random", Random.class),
        /**
         * Seed for random number generator
         */
        SEED("seed", Integer.class),

        /////////// Temporal Memory Parameters ///////////
        /**
         * If the number of active connected synapses on a segment
         * is at least this threshold, the segment is said to be active.
         */
        ACTIVATION_THRESHOLD("activationThreshold", Integer.class, 0, null),
        /**
         * Radius around cell from which it can
         * sample to form distal {@link DistalDendrite} connections.
         */
        LEARNING_RADIUS("learningRadius", Integer.class, 0, null),
        /**
         * If the number of synapses active on a segment is at least this
         * threshold, it is selected as the best matching
         * cell in a bursting column.
         */
        MIN_THRESHOLD("minThreshold", Integer.class, 0, null),
        /**
         * The maximum number of synapses added to a segment during learning.
         */
        MAX_NEW_SYNAPSE_COUNT("maxNewSynapseCount", Integer.class),
        /**
         * Initial permanence of a new synapse
         */
        INITIAL_PERMANENCE("initialPermanence", Double.class, 0.0, 1.0),
        /**
         * If the permanence value for a synapse
         * is greater than this value, it is said
         * to be connected.
         */
        CONNECTED_PERMANENCE("connectedPermanence", Double.class, 0.0, 1.0),
        /**
         * Amount by which permanence of synapses
         * are incremented during learning.
         */
        PERMANENCE_INCREMENT("permanenceIncrement", Double.class, 0.0, 1.0),
        /**
         * Amount by which permanences of synapses
         * are decremented during learning.
         */
        PERMANENCE_DECREMENT("permanenceDecrement", Double.class, 0.0, 1.0),
        TM_VERBOSITY("tmVerbosity", Integer.class, 0, 10),

        /////////// Spatial Pooler Parameters ///////////
        INPUT_DIMENSIONS("inputDimensions", int[].class),
        POTENTIAL_RADIUS("potentialRadius", Integer.class),
        POTENTIAL_PCT("potentialPct", Double.class), //TODO add range here?
        GLOBAL_INHIBITIONS("globalInhibition", Boolean.class),
        INHIBITION_RADIUS("inhibitionRadius", Integer.class, 0, null),
        LOCAL_AREA_DENSITY("localAreaDensity", Double.class), //TODO add range here?
        NUM_ACTIVE_COLUMNS_PER_INH_AREA("numActiveColumnsPerInhArea", Double.class),//TODO add range here?
        STIMULUS_THRESHOLD("stimulusThreshold", Double.class), //TODO add range here?
        SYN_PERM_INACTIVE_DEC("synPermInactiveDec", Double.class, 0.0, 1.0),
        SYN_PERM_ACTIVE_INC("synPermActiveInc", Double.class, 0.0, 1.0),
        SYN_PERM_CONNECTED("synPermConnected", Double.class, 0.0, 1.0),
        SYN_PERM_BELOW_STIMULUS_INC("synPermBelowStimulusInc", Double.class, 0.0, 1.0),
        SYN_PERM_TRIM_THRESHOLD("synPermTrimThreshold", Double.class, 0.0, 1.0),
        MIN_PCT_OVERLAP_DUTY_CYCLE("minPctOverlapDutyCycles", Double.class),//TODO add range here?
        MIN_PCT_ACTIVE_DUTY_CYCLE("minPctActiveDutyCycles", Double.class),//TODO add range here?
        DUTY_CYCLE_PERIOD("dutyCyclePeriod", Integer.class),//TODO add range here?
        MAX_BOOST("maxBoost", Double.class), //TODO add range here?
        SP_VERBOSITY("spVerbosity", Integer.class, 0, 10),
        
        ///////////// SpatialPooler / Network Parameter(s) /////////////
        /** Number of cycles to send through the SP before forwarding data to the rest of the network. */
        SP_PRIMER_DELAY("sp_primer_delay", Integer.class),
        
        ///////////// Encoder Parameters //////////////
        /** number of bits in the representation (must be >= w) */
        N("n", Integer.class),
        /** 
         * The number of bits that are set to encode a single value - the
         * "width" of the output signal
         */
        W("w", Integer.class),
        /** The minimum value of the input signal.  */
        MIN_VAL("minVal", Double.class),
        /** The maximum value of the input signal. */
        MAX_VAL("maxVal", Double.class),
        /**
         * inputs separated by more than, or equal to this distance will have non-overlapping
         * representations
         */
        RADIUS("radius", Double.class),
        /** inputs separated by more than, or equal to this distance will have different representations */
        RESOLUTION("resolution", Double.class),
        /**
         * If true, then the input value "wraps around" such that minval = maxval
         * For a periodic value, the input must be strictly less than maxval,
         * otherwise maxval is a true upper bound.
         */
        PERIODIC("periodic", Boolean.class),
        /** 
         * if true, non-periodic inputs smaller than minval or greater
         * than maxval will be clipped to minval/maxval 
         */
        CLIP_INPUT("clipInput", Boolean.class),
        /** 
         * If true, skip some safety checks (for compatibility reasons), default false 
         * Mostly having to do with being able to set the window size < 21 
         */
        FORCED("forced", Boolean.class),
        /** Name of the field being encoded */
        FIELD_NAME("fieldName", String.class),
        /** Primitive type of the field, used to auto-configure the type of encoder */
        FIELD_TYPE("fieldType", String.class),
        /** Encoder name */
        ENCODER("encoderType", String.class),
        /** Designates holder for the Multi Encoding Map */
        FIELD_ENCODING_MAP("fieldEncodings", Map.class),
        CATEGORY_LIST("categoryList", List.class),
        
        // Network Layer indicator for auto classifier generation
        AUTO_CLASSIFY("hasClassifiers", Boolean.class),
        
        
        // How many bits to use if encoding the respective date fields.
        // e.g. Tuple(bits to use:int, radius:double)
        DATEFIELD_SEASON("season", Tuple.class), 
        DATEFIELD_DOFW("dayOfWeek", Tuple.class),
        DATEFIELD_WKEND("weekend", Tuple.class),
        DATEFIELD_HOLIDAY("holiday", Tuple.class),
        DATEFIELD_TOFD("timeOfDay", Tuple.class),
        DATEFIELD_CUSTOM("customDays", Tuple.class), // e.g. Tuple(bits:int, List:"mon,tue,fri")
        DATEFIELD_PATTERN("formatPattern", String.class),
        DATEFIELD_FORMATTER("dateFormatter", DateTimeFormatter.class);
        

        private static final Map fieldMap = new HashMap<>();

        static {
            for (KEY key : KEY.values()) {
                fieldMap.put(key.getFieldName(), key);
            }
        }

        public static KEY getKeyByFieldName(String fieldName) {
            return fieldMap.get(fieldName);
        }

        final private String fieldName;
        final private Class fieldType;
        final private Number min;
        final private Number max;

        /**
         * Constructs a new KEY
         *
         * @param fieldName
         * @param fieldType
         */
        private KEY(String fieldName, Class fieldType) {
            this(fieldName, fieldType, null, null);
        }

        /**
         * Constructs a new KEY with range check
         *
         * @param fieldName
         * @param fieldType
         * @param min
         * @param max
         */
        private KEY(String fieldName, Class fieldType, Number min, Number max) {
            this.fieldName = fieldName;
            this.fieldType = fieldType;
            this.min = min;
            this.max = max;
        }

        public Class getFieldType() {
            return fieldType;
        }

        public String getFieldName() {
            return fieldName;
        }

        public Number getMin() {
            return min;
        }

        public Number getMax() {
            return max;
        }

        public boolean checkRange(Number value) {
            if (value == null) {
                throw new IllegalArgumentException("checkRange argument can not be null");
            }
            return (min == null && max == null) ||
                   (min != null && max == null && min.doubleValue() <= value.doubleValue()) ||
                   (max != null && min == null && value.doubleValue() < value.doubleValue()) ||
                   (min != null && min.doubleValue() <= value.doubleValue() && max != null && value.doubleValue() < max.doubleValue());
        }

    }

    /**
     * Save guard decorator around params map
     */
    private static class ParametersMap extends EnumMap {
        /**
         * Default serialvers
         */
        private static final long serialVersionUID = 1L;

        ParametersMap() {
            super(Parameters.KEY.class);
        }

        @Override public Object put(KEY key, Object value) {
            if (value != null) {
                if (!key.getFieldType().isInstance(value)) {
                    throw new IllegalArgumentException(
                            "Can not set Parameters Property '" + key.getFieldName() + "' because of type mismatch. The required type is " + key.getFieldType());
                }
                if (value instanceof Number && !key.checkRange((Number)value)) {
                    throw new IllegalArgumentException(
                            "Can not set Parameters Property '" + key.getFieldName() + "' because of value '" + value + "' not in range. Range[" + key.getMin() + "-" + key.getMax() + "]");
                }
            }
            return super.put(key, value);
        }
    }

    /**
     * Map of parameters to their values
     */
    private final Map paramMap = Collections.synchronizedMap(new ParametersMap());

    //TODO apply from container to parameters
    
    /**
     * Returns the size of the internal parameter storage.
     * @return
     */
    public int size() {
        return paramMap.size();
    }

    /**
     * Factory method. Return global {@link Parameters} object with default values
     *
     * @return {@link Parameters} object
     */
    public static Parameters getAllDefaultParameters() {
        return getParameters(DEFAULTS_ALL);
    }

    /**
     * Factory method. Return temporal {@link Parameters} object with default values
     *
     * @return {@link Parameters} object
     */
    public static Parameters getTemporalDefaultParameters() {
        return getParameters(DEFAULTS_TEMPORAL);
    }


    /**
     * Factory method. Return spatial {@link Parameters} object with default values
     *
     * @return {@link Parameters} object
     */
    public static Parameters getSpatialDefaultParameters() {
        return getParameters(DEFAULTS_SPATIAL);
    }

    /**
     * Factory method. Return Encoder {@link Parameters} object with default values
     * @return
     */
    public static Parameters getEncoderDefaultParameters() {
        return getParameters(DEFAULTS_ENCODER);
    }
    /**
     * Called internally to populate a {@link Parameters} object with the keys
     * and values specified in the passed in map.
     *
     * @return {@link Parameters} object
     */
    private static Parameters getParameters(Map map) {
        Parameters result = new Parameters();
        for (KEY key : map.keySet()) {
            result.setParameterByKey(key, map.get(key));
        }
        return result;
    }


    /**
     * Constructs a new {@code Parameters} object.
     * It is private. Only allow instantiation with Factory methods.
     * This way we will never have erroneous Parameters with missing attributes
     */
    private Parameters() {
    }

    /**
     * Sets the fields specified by this {@code Parameters} on the specified
     * {@link Connections} object.
     *
     * @param cn
     */
    public void apply(Object cn) {
        BeanUtil beanUtil = BeanUtil.getInstance();
        Set presentKeys = paramMap.keySet();
        synchronized (paramMap) {
            for (KEY key : presentKeys) {
                beanUtil.setSimpleProperty(cn, key.fieldName, getParameterByKey(key));
            }
        }
    }
    
    /**
     * Copies the specified parameters into this {@code Parameters}
     * object over writing the intersecting keys and values.
     * @param p     the Parameters to perform a union with.
     * @return      this Parameters object combined with the specified
     *              Parameters object.
     */
    public Parameters union(Parameters p) {
        for(KEY k : p.paramMap.keySet()) {
            setParameterByKey(k, p.getParameterByKey(k));
        }
        return this;
    }
    
    /**
     * Returns a Set view of the keys in this {@code Parameter}s 
     * object
     * @return
     */
    public Set keys() {
        Set retVal = paramMap.keySet();
        return retVal;
    }
    
    /**
     * Returns a separate instance of the specified {@code Parameters} object.
     * @return      a unique instance.
     */
    public Parameters copy() {
        return new Parameters().union(this);
    }
    
    /**
     * Returns an empty instance of {@code Parameters};
     * @return
     */
    public static Parameters empty() {
        return new Parameters();
    }

    /**
     * Set parameter by Key{@link KEY}
     *
     * @param key
     * @param value
     */
    public void setParameterByKey(KEY key, Object value) {
        paramMap.put(key, value);
    }

    /**
     * Get parameter by Key{@link KEY}
     *
     * @param key
     * @return
     */
    public Object getParameterByKey(KEY key) {
        return paramMap.get(key);
    }

    /**
     * @param key IMPORTANT! This is a nuclear option, should be used with care. 
     * Will knockout key's parameter from map and compromise integrity
     */
    public void clearParameter(KEY key) {
        paramMap.remove(key);
    }

    /**
     * Convenience method to log difference this {@code Parameters} and specified
     * {@link Connections} object.
     *
     * @param cn
     * @return true if find it different
     */
    public boolean logDiff(Object cn) {
        if (cn == null) {
            throw new IllegalArgumentException("cn Object is required and can not be null");
        }
        boolean result = false;
        BeanUtil beanUtil = BeanUtil.getInstance();
        BeanUtil.PropertyInfo[] properties = beanUtil.getPropertiesInfoForBean(cn.getClass());
        for (int i = 0; i < properties.length; i++) {
            BeanUtil.PropertyInfo property = properties[i];
            String fieldName = property.getName();
            KEY propKey = KEY.getKeyByFieldName(property.getName());
            if (propKey != null) {
                Object paramValue = this.getParameterByKey(propKey);
                Object cnValue = beanUtil.getSimpleProperty(cn, fieldName);
                if ((paramValue != null && !paramValue.equals(cnValue)) || (paramValue == null && cnValue != null)) {
                    result = true;
                    System.out.println(
                            "Property:" + fieldName + " is different - CN:" + cnValue + " | PARAM:" + paramValue);
                }
            }
        }
        return result;
    }

    //TODO I'm not sure we need maintain implicit setters below. Kinda contradict unified access with KEYs

    /**
     * Returns the seeded random number generator.
     *
     * @param r the generator to use.
     */
    public void setRandom(Random r) {
        paramMap.put(KEY.RANDOM, r);
    }

    /**
     * Sets the number of {@link Column}.
     *
     * @param columnDimensions
     */
    public void setColumnDimensions(int[] columnDimensions) {
        paramMap.put(KEY.COLUMN_DIMENSIONS, columnDimensions);
    }

    /**
     * Sets the number of {@link Cell}s per {@link Column}
     *
     * @param cellsPerColumn
     */
    public void setCellsPerColumn(int cellsPerColumn) {
        paramMap.put(KEY.CELLS_PER_COLUMN, cellsPerColumn);
    }

    /**
     * Sets the activation threshold.
     * 

* If the number of active connected synapses on a segment * is at least this threshold, the segment is said to be active. * * @param activationThreshold */ public void setActivationThreshold(int activationThreshold) { paramMap.put(KEY.ACTIVATION_THRESHOLD, activationThreshold); } /** * Radius around cell from which it can * sample to form distal dendrite connections. * * @param learningRadius */ public void setLearningRadius(int learningRadius) { paramMap.put(KEY.LEARNING_RADIUS, learningRadius); } /** * If the number of synapses active on a segment is at least this * threshold, it is selected as the best matching * cell in a bursting column. * * @param minThreshold */ public void setMinThreshold(int minThreshold) { paramMap.put(KEY.MIN_THRESHOLD, minThreshold); } /** * The maximum number of synapses added to a segment during learning. * * @param maxNewSynapseCount */ public void setMaxNewSynapseCount(int maxNewSynapseCount) { paramMap.put(KEY.MAX_NEW_SYNAPSE_COUNT, maxNewSynapseCount); } /** * Seed for random number generator * * @param seed */ public void setSeed(int seed) { paramMap.put(KEY.SEED, seed); } /** * Initial permanence of a new synapse * * @param */ public void setInitialPermanence(double initialPermanence) { paramMap.put(KEY.INITIAL_PERMANENCE, initialPermanence); } /** * If the permanence value for a synapse * is greater than this value, it is said * to be connected. * * @param connectedPermanence */ public void setConnectedPermanence(double connectedPermanence) { paramMap.put(KEY.CONNECTED_PERMANENCE, connectedPermanence); } /** * Amount by which permanences of synapses * are incremented during learning. * * @param permanenceIncrement */ public void setPermanenceIncrement(double permanenceIncrement) { paramMap.put(KEY.PERMANENCE_INCREMENT, permanenceIncrement); } /** * Amount by which permanences of synapses * are decremented during learning. * * @param permanenceDecrement */ public void setPermanenceDecrement(double permanenceDecrement) { paramMap.put(KEY.PERMANENCE_DECREMENT, permanenceDecrement); } ////////////////////////////// SPACIAL POOLER PARAMS ////////////////////////////////// /** * A list representing the dimensions of the input * vector. Format is [height, width, depth, ...], where * each value represents the size of the dimension. For a * topology of one dimension with 100 inputs use 100, or * [100]. For a two dimensional topology of 10x5 use * [10,5]. * * @param inputDimensions */ public void setInputDimensions(int[] inputDimensions) { paramMap.put(KEY.INPUT_DIMENSIONS, inputDimensions); } /** * This parameter determines the extent of the input * that each column can potentially be connected to. * This can be thought of as the input bits that * are visible to each column, or a 'receptiveField' of * the field of vision. A large enough value will result * in 'global coverage', meaning that each column * can potentially be connected to every input bit. This * parameter defines a square (or hyper square) area: a * column will have a max square potential pool with * sides of length 2 * potentialRadius + 1. * * @param potentialRadius */ public void setPotentialRadius(int potentialRadius) { paramMap.put(KEY.POTENTIAL_RADIUS, potentialRadius); } /** * The inhibition radius determines the size of a column's local * neighborhood. of a column. A cortical column must overcome the overlap * score of columns in his neighborhood in order to become actives. This * radius is updated every learning round. It grows and shrinks with the * average number of connected synapses per column. * * @param inhibitionRadius the local group size */ public void setInhibitionRadius(int inhibitionRadius) { paramMap.put(KEY.INHIBITION_RADIUS, inhibitionRadius); } /** * The percent of the inputs, within a column's * potential radius, that a column can be connected to. * If set to 1, the column will be connected to every * input within its potential radius. This parameter is * used to give each column a unique potential pool when * a large potentialRadius causes overlap between the * columns. At initialization time we choose * ((2*potentialRadius + 1)^(# inputDimensions) * * potentialPct) input bits to comprise the column's * potential pool. * * @param potentialPct */ public void setPotentialPct(double potentialPct) { paramMap.put(KEY.POTENTIAL_PCT, potentialPct); } /** * If true, then during inhibition phase the winning * columns are selected as the most active columns from * the region as a whole. Otherwise, the winning columns * are selected with respect to their local * neighborhoods. Using global inhibition boosts * performance x60. * * @param globalInhibition */ public void setGlobalInhibition(boolean globalInhibition) { paramMap.put(KEY.GLOBAL_INHIBITIONS, globalInhibition); } /** * The desired density of active columns within a local * inhibition area (the size of which is set by the * internally calculated inhibitionRadius, which is in * turn determined from the average size of the * connected potential pools of all columns). The * inhibition logic will insure that at most N columns * remain ON within a local inhibition area, where N = * localAreaDensity * (total number of columns in * inhibition area). * * @param localAreaDensity */ public void setLocalAreaDensity(double localAreaDensity) { paramMap.put(KEY.LOCAL_AREA_DENSITY, localAreaDensity); } /** * An alternate way to control the density of the active * columns. If numActivePerInhArea is specified then * localAreaDensity must be less than 0, and vice versa. * When using numActivePerInhArea, the inhibition logic * will insure that at most 'numActivePerInhArea' * columns remain ON within a local inhibition area (the * size of which is set by the internally calculated * inhibitionRadius, which is in turn determined from * the average size of the connected receptive fields of * all columns). When using this method, as columns * learn and grow their effective receptive fields, the * inhibitionRadius will grow, and hence the net density * of the active columns will *decrease*. This is in * contrast to the localAreaDensity method, which keeps * the density of active columns the same regardless of * the size of their receptive fields. * * @param numActiveColumnsPerInhArea */ public void setNumActiveColumnsPerInhArea(double numActiveColumnsPerInhArea) { paramMap.put(KEY.NUM_ACTIVE_COLUMNS_PER_INH_AREA, numActiveColumnsPerInhArea); } /** * This is a number specifying the minimum number of * synapses that must be on in order for a columns to * turn ON. The purpose of this is to prevent noise * input from activating columns. Specified as a percent * of a fully grown synapse. * * @param stimulusThreshold */ public void setStimulusThreshold(double stimulusThreshold) { paramMap.put(KEY.STIMULUS_THRESHOLD, stimulusThreshold); } /** * The amount by which an inactive synapse is * decremented in each round. Specified as a percent of * a fully grown synapse. * * @param synPermInactiveDec */ public void setSynPermInactiveDec(double synPermInactiveDec) { paramMap.put(KEY.SYN_PERM_INACTIVE_DEC, synPermInactiveDec); } /** * The amount by which an active synapse is incremented * in each round. Specified as a percent of a * fully grown synapse. * * @param synPermActiveInc */ public void setSynPermActiveInc(double synPermActiveInc) { paramMap.put(KEY.SYN_PERM_ACTIVE_INC, synPermActiveInc); } /** * The default connected threshold. Any synapse whose * permanence value is above the connected threshold is * a "connected synapse", meaning it can contribute to * the cell's firing. * * @param synPermConnected */ public void setSynPermConnected(double synPermConnected) { paramMap.put(KEY.SYN_PERM_CONNECTED, synPermConnected); } /** * Sets the increment of synapse permanences below the stimulus * threshold * * @param synPermBelowStimulusInc */ public void setSynPermBelowStimulusInc(double synPermBelowStimulusInc) { paramMap.put(KEY.SYN_PERM_BELOW_STIMULUS_INC, synPermBelowStimulusInc); } /** * @param synPermTrimThreshold */ public void setSynPermTrimThreshold(double synPermTrimThreshold) { paramMap.put(KEY.SYN_PERM_TRIM_THRESHOLD, synPermTrimThreshold); } /** * A number between 0 and 1.0, used to set a floor on * how often a column should have at least * stimulusThreshold active inputs. Periodically, each * column looks at the overlap duty cycle of * all other columns within its inhibition radius and * sets its own internal minimal acceptable duty cycle * to: minPctDutyCycleBeforeInh * max(other columns' * duty cycles). * On each iteration, any column whose overlap duty * cycle falls below this computed value will get * all of its permanence values boosted up by * synPermActiveInc. Raising all permanences in response * to a sub-par duty cycle before inhibition allows a * cell to search for new inputs when either its * previously learned inputs are no longer ever active, * or when the vast majority of them have been * "hijacked" by other columns. * * @param minPctOverlapDutyCycles */ public void setMinPctOverlapDutyCycle(double minPctOverlapDutyCycles) { paramMap.put(KEY.MIN_PCT_OVERLAP_DUTY_CYCLE, minPctOverlapDutyCycles); } /** * A number between 0 and 1.0, used to set a floor on * how often a column should be activate. * Periodically, each column looks at the activity duty * cycle of all other columns within its inhibition * radius and sets its own internal minimal acceptable * duty cycle to: * minPctDutyCycleAfterInh * * max(other columns' duty cycles). * On each iteration, any column whose duty cycle after * inhibition falls below this computed value will get * its internal boost factor increased. * * @param minPctActiveDutyCycles */ public void setMinPctActiveDutyCycle(double minPctActiveDutyCycles) { paramMap.put(KEY.MIN_PCT_ACTIVE_DUTY_CYCLE, minPctActiveDutyCycles); } /** * The period used to calculate duty cycles. Higher * values make it take longer to respond to changes in * boost or synPerConnectedCell. Shorter values make it * more unstable and likely to oscillate. * * @param dutyCyclePeriod */ public void setDutyCyclePeriod(int dutyCyclePeriod) { paramMap.put(KEY.DUTY_CYCLE_PERIOD, dutyCyclePeriod); } /** * The maximum overlap boost factor. Each column's * overlap gets multiplied by a boost factor * before it gets considered for inhibition. * The actual boost factor for a column is number * between 1.0 and maxBoost. A boost factor of 1.0 is * used if the duty cycle is >= minOverlapDutyCycle, * maxBoost is used if the duty cycle is 0, and any duty * cycle in between is linearly extrapolated from these * 2 end points. * * @param maxBoost */ public void setMaxBoost(double maxBoost) { paramMap.put(KEY.MAX_BOOST, maxBoost); } /** * spVerbosity level: 0, 1, 2, or 3 * * @param spVerbosity */ public void setSpVerbosity(int spVerbosity) { paramMap.put(KEY.SP_VERBOSITY, spVerbosity); } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder result = new StringBuilder("{\n"); StringBuilder spatialInfo = new StringBuilder(); StringBuilder temporalInfo = new StringBuilder(); StringBuilder otherInfo = new StringBuilder(); this.paramMap.keySet(); for (KEY key : paramMap.keySet()) { if (DEFAULTS_SPATIAL.containsKey(key)) { buildParamStr(spatialInfo, key); } else if (DEFAULTS_TEMPORAL.containsKey(key)) { buildParamStr(temporalInfo, key); } else { buildParamStr(otherInfo, key); } } if (spatialInfo.length() > 0) { result.append("\tSpatial: {\n").append(spatialInfo).append("\t}\n"); } if (temporalInfo.length() > 0) { result.append("\tTemporal: {\n").append(temporalInfo).append("\t}\n"); } if (otherInfo.length() > 0) { result.append("\tOther: {\n").append(otherInfo).append("\t}\n"); } return result.append("}").toString(); } private void buildParamStr(StringBuilder spatialInfo, KEY key) { Object value = getParameterByKey(key); if (value instanceof int[]) { value = ArrayUtils.intArrayToString(value); } spatialInfo.append("\t\t").append(key.getFieldName()).append(":").append(value).append("\n"); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy