From f98573b7bff0c1972819b4aede5572e1876dc3de Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 10:41:39 +0100
Subject: [PATCH 01/56] Added ignore for IntelliJ IDEA iml files
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 2eff84a4..ebb9b497 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
/build
/doc
.idea/
+*.iml
.gradle
.settings
.classpath
From 87d3d513b76c8d406147d454922410d3a3f03fcd Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 10:46:59 +0100
Subject: [PATCH 02/56] Added slf4j-api
---
build.gradle | 1 +
pom.xml | 7 ++++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/build.gradle b/build.gradle
index 2c5c3d40..13ec7739 100644
--- a/build.gradle
+++ b/build.gradle
@@ -34,6 +34,7 @@ dependencies {
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version:'2.4.4'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version:'2.4.4'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version:'2.4.4'
+ compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.10'
testCompile group: 'junit', name: 'junit', version:'4.11'
}
diff --git a/pom.xml b/pom.xml
index de504514..98e3c343 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,7 +70,12 @@
com.fasterxml.jackson.corejackson-databind2.4.4
-
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.10
+
From 8f80ed963a28d257e4cda942cce5938ac6098616 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 10:49:20 +0100
Subject: [PATCH 03/56] Added logback for tests.
---
build.gradle | 1 +
pom.xml | 6 ++++++
src/test/resources/logback-test.xml | 11 +++++++++++
3 files changed, 18 insertions(+)
create mode 100644 src/test/resources/logback-test.xml
diff --git a/build.gradle b/build.gradle
index 13ec7739..a51edf0c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,6 +36,7 @@ dependencies {
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version:'2.4.4'
compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.10'
testCompile group: 'junit', name: 'junit', version:'4.11'
+ testCompile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2'
}
// create Gradle wrapper with command line `gradle wrapper` in terminal
diff --git a/pom.xml b/pom.xml
index 98e3c343..5a62f768 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,12 @@
slf4j-api1.7.10
+
+ ch.qos.logback
+ logback-classic
+ 1.1.2
+ test
+
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..8a818395
--- /dev/null
+++ b/src/test/resources/logback-test.xml
@@ -0,0 +1,11 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %5p %c{1}:%L - %m%n
+
+
+
+
+
+
+
\ No newline at end of file
From fb0532705c5eff8a9916714db536014724cfd412 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 11:00:35 +0100
Subject: [PATCH 04/56] Replaced verbosity 2 with slf4j trace.
---
.../numenta/nupic/encoders/LogEncoder.java | 126 +++++++++---------
1 file changed, 63 insertions(+), 63 deletions(-)
diff --git a/src/main/java/org/numenta/nupic/encoders/LogEncoder.java b/src/main/java/org/numenta/nupic/encoders/LogEncoder.java
index ec9ca334..31d5ee41 100644
--- a/src/main/java/org/numenta/nupic/encoders/LogEncoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/LogEncoder.java
@@ -35,15 +35,17 @@
import org.numenta.nupic.FieldMetaType;
import org.numenta.nupic.util.MinMax;
import org.numenta.nupic.util.Tuple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* DOCUMENTATION TAKEN DIRECTLY FROM THE PYTHON VERSION:
- *
+ *
* This class wraps the ScalarEncoder class.
* A Log encoder represents a floating point value on a logarithmic scale.
- * valueToEncode = log10(input)
- *
+ * valueToEncode = log10(input)
+ *
* w -- number of bits to set in output
* minval -- minimum input value. must be greater than 0. Lower values are
* reset to this value
@@ -51,7 +53,7 @@
* periodic -- 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.
- *
+ *
* Exactly one of n, radius, resolution must be set. "0" is a special
* value that means "not set".
* n -- number of bits in the representation (must be > w)
@@ -63,29 +65,31 @@
* in the output. In terms of the original input values, this
* means 10^1 (1) and 10^1.1 (1.25) will be distinguishable.
* name -- an optional string which will become part of the description
- * verbosity -- level of debugging output you want the encoder to provide.
* clipInput -- if true, non-periodic inputs smaller than minval or greater
* than maxval will be clipped to minval/maxval
* forced -- (default False), if True, skip some safety checks
*/
public class LogEncoder extends Encoder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LogEncoder.class);
+
private ScalarEncoder encoder;
private double minScaledValue, maxScaledValue;
/**
* Constructs a new {@code LogEncoder}
*/
LogEncoder() {}
-
+
/**
- * Returns a builder for building LogEncoders.
+ * Returns a builder for building LogEncoders.
* This builder may be reused to produce multiple builders
- *
+ *
* @return a {@code LogEncoder.Builder}
*/
public static Encoder.Builder builder() {
return new LogEncoder.Builder();
}
-
+
/**
* w -- number of bits to set in output
* minval -- minimum input value. must be greater than 0. Lower values are
@@ -94,7 +98,7 @@ public static Encoder.Builder builder() {
* periodic -- 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.
- *
+ *
* Exactly one of n, radius, resolution must be set. "0" is a special
* value that means "not set".
* n -- number of bits in the representation (must be > w)
@@ -106,7 +110,6 @@ public static Encoder.Builder builder() {
* in the output. In terms of the original input values, this
* means 10^1 (1) and 10^1.1 (1.25) will be distinguishable.
* name -- an optional string which will become part of the description
- * verbosity -- level of debugging output you want the encoder to provide.
* clipInput -- if true, non-periodic inputs smaller than minval or greater
* than maxval will be clipped to minval/maxval
* forced -- (default False), if True, skip some safety checks
@@ -118,28 +121,28 @@ public void init() {
if (getW() == 0) {
setW(5);
}
-
+
// maxVal defaults to 10000.
if (getMaxVal() == 0.0) {
setMaxVal(10000.);
}
-
+
if (getMinVal() < lowLimit) {
setMinVal(lowLimit);
}
-
+
if (getMinVal() >= getMaxVal()) {
- throw new IllegalStateException("Max val must be larger than min val or the lower limit " +
+ throw new IllegalStateException("Max val must be larger than min val or the lower limit " +
"for this encoder " + String.format("%.7f", lowLimit));
}
-
+
minScaledValue = Math.log10(getMinVal());
maxScaledValue = Math.log10(getMaxVal());
-
+
if(minScaledValue >= maxScaledValue) {
throw new IllegalStateException("Max val must be larger, in log space, than min val.");
}
-
+
// There are three different ways of thinking about the representation. Handle
// each case here.
encoder = ScalarEncoder.builder()
@@ -150,17 +153,16 @@ public void init() {
.n(getN())
.radius(getRadius())
.resolution(getResolution())
- .verbosity(getVerbosity())
.clipInput(clipInput())
.forced(isForced())
.name(getName())
.build();
-
+
setN(encoder.getN());
setResolution(encoder.getResolution());
setRadius(encoder.getRadius());
}
-
+
@Override
public int getWidth() {
@@ -176,7 +178,7 @@ public boolean isDelta() {
public List getDescription() {
return encoder.getDescription();
}
-
+
/**
* {@inheritDoc}
*/
@@ -184,7 +186,7 @@ public List getDescription() {
public List getDecoderOutputFieldTypes() {
return encoder.getDecoderOutputFieldTypes();
}
-
+
/**
* Convert the input, which is in normal space, into log space
* @param input Value in normal space.
@@ -204,23 +206,23 @@ private Double getScaledValue(double input) {
return Math.log10(val);
}
}
-
+
/**
* Returns the bucket indices.
- *
- * @param input
+ *
+ * @param input
*/
@Override
public int[] getBucketIndices(double input) {
Double scaledVal = getScaledValue(input);
-
+
if (scaledVal == null) {
return new int[]{};
} else {
return encoder.getBucketIndices(scaledVal);
}
}
-
+
/**
* Encodes inputData and puts the encoded value into the output array,
* which is a 1-D array of length returned by {@link Connections#getW()}.
@@ -228,23 +230,21 @@ public int[] getBucketIndices(double input) {
* Note: The output array is reused, so clear it before updating it.
* @param inputData Data to encode. This should be validated by the encoder.
* @param output 1-D array of same length returned by {@link Connections#getW()}
- *
+ *
* @return
*/
@Override
public void encodeIntoArray(Double input, int[] output) {
Double scaledVal = getScaledValue(input);
-
+
if (scaledVal == null) {
Arrays.fill(output, 0);
} else {
encoder.encodeIntoArray(scaledVal, output);
-
- if (getVerbosity() >= 2) {
- System.out.print("input: " + input);
- System.out.print(" scaledVal: " + scaledVal);
- System.out.println(" output: " + Arrays.toString(output));
- }
+
+ LOG.trace("input: " + input);
+ LOG.trace(" scaledVal: " + scaledVal);
+ LOG.trace(" output: " + Arrays.toString(output));
}
}
@@ -255,22 +255,22 @@ public void encodeIntoArray(Double input, int[] output) {
public DecodeResult decode(int[] encoded, String parentFieldName) {
// Get the scalar values from the underlying scalar encoder
DecodeResult decodeResult = encoder.decode(encoded, parentFieldName);
-
+
Map fields = decodeResult.getFields();
-
+
if (fields.keySet().size() == 0) {
return decodeResult;
}
-
+
// Convert each range into normal space
RangeList inRanges = (RangeList) fields.values().toArray()[0];
RangeList outRanges = new RangeList(new ArrayList(), "");
for (MinMax minMax : inRanges.getRanges()) {
- MinMax scaledMinMax = new MinMax( Math.pow(10, minMax.min()),
+ MinMax scaledMinMax = new MinMax( Math.pow(10, minMax.min()),
Math.pow(10, minMax.max()));
outRanges.add(scaledMinMax);
}
-
+
// Generate a text description of the ranges
String desc = "";
int numRanges = outRanges.size();
@@ -286,20 +286,20 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
}
}
outRanges.setDescription(desc);
-
+
String fieldName;
if (!parentFieldName.equals("")) {
fieldName = String.format("%s.%s", parentFieldName, getName());
} else {
fieldName = getName();
}
-
+
Map outFields = new HashMap();
outFields.put(fieldName, outRanges);
-
+
List fieldNames = new ArrayList();
fieldNames.add(fieldName);
-
+
return new DecodeResult(outFields, fieldNames);
}
@@ -309,11 +309,11 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
@SuppressWarnings("unchecked")
@Override
public List getBucketValues(Class t) {
- // Need to re-create?
+ // Need to re-create?
if(bucketValues == null) {
List scaledValues = encoder.getBucketValues(t);
bucketValues = new ArrayList();
-
+
for (S scaledValue : scaledValues) {
double value = Math.pow(10, (Double)scaledValue);
((List)bucketValues).add(value);
@@ -321,7 +321,7 @@ public List getBucketValues(Class t) {
}
return (List)bucketValues;
}
-
+
/**
* {@inheritDoc}
*/
@@ -330,10 +330,10 @@ public List getBucketInfo(int[] buckets) {
EncoderResult scaledResult = encoder.getBucketInfo(buckets).get(0);
double scaledValue = (Double)scaledResult.getValue();
double value = Math.pow(10, scaledValue);
-
+
return Arrays.asList(new EncoderResult(value, value, scaledResult.getEncoding()));
}
-
+
/**
* {@inheritDoc}
*/
@@ -342,17 +342,17 @@ public List topDownCompute(int[] encoded) {
EncoderResult scaledResult = encoder.topDownCompute(encoded).get(0);
double scaledValue = (Double)scaledResult.getValue();
double value = Math.pow(10, scaledValue);
-
+
return Arrays.asList(new EncoderResult(value, value, scaledResult.getEncoding()));
}
-
+
/**
* {@inheritDoc}
*/
@Override
public TDoubleList closenessScores(TDoubleList expValues, TDoubleList actValues, boolean fractional) {
TDoubleList retVal = new TDoubleArrayList();
-
+
double expValue, actValue;
if (expValues.get(0) > 0) {
expValue = Math.log10(expValues.get(0));
@@ -364,7 +364,7 @@ public TDoubleList closenessScores(TDoubleList expValues, TDoubleList actValues,
} else {
actValue = minScaledValue;
}
-
+
double closeness;
if (fractional) {
double err = Math.abs(expValue - actValue);
@@ -374,18 +374,18 @@ public TDoubleList closenessScores(TDoubleList expValues, TDoubleList actValues,
} else {
closeness = Math.abs(expValue - actValue);;
}
-
+
retVal.add(closeness);
return retVal;
}
-
+
/**
* Returns a {@link EncoderBuilder} for constructing {@link ScalarEncoder}s
- *
+ *
* The base class architecture is put together in such a way where boilerplate
* initialization can be kept to a minimum for implementing subclasses, while avoiding
* the mistake-proneness of extremely long argument lists.
- *
+ *
* @see ScalarEncoder.Builder#setStuff(int)
*/
public static class Builder extends Encoder.Builder {
@@ -393,20 +393,20 @@ private Builder() {}
@Override
public LogEncoder build() {
- //Must be instantiated so that super class can initialize
+ //Must be instantiated so that super class can initialize
//boilerplate variables.
encoder = new LogEncoder();
-
+
//Call super class here
super.build();
-
+
////////////////////////////////////////////////////////
// Implementing classes would do setting of specific //
// vars here together with any sanity checking //
////////////////////////////////////////////////////////
-
+
((LogEncoder)encoder).init();
-
+
return (LogEncoder)encoder;
}
}
From 35ab0dbd11f458e62d782e44b27490ad3ae87435 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 11:01:46 +0100
Subject: [PATCH 05/56] Replaced verbosity 2 with slf4j trace.
---
.../numenta/nupic/encoders/ScalarEncoder.java | 218 +++++++++---------
1 file changed, 106 insertions(+), 112 deletions(-)
diff --git a/src/main/java/org/numenta/nupic/encoders/ScalarEncoder.java b/src/main/java/org/numenta/nupic/encoders/ScalarEncoder.java
index 6f6bb0ce..77ee65e6 100644
--- a/src/main/java/org/numenta/nupic/encoders/ScalarEncoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/ScalarEncoder.java
@@ -31,6 +31,8 @@
import org.numenta.nupic.util.MinMax;
import org.numenta.nupic.util.SparseObjectMatrix;
import org.numenta.nupic.util.Tuple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -41,7 +43,7 @@
/**
* DOCUMENTATION TAKEN DIRECTLY FROM THE PYTHON VERSION:
- *
+ *
* A scalar encoder encodes a numeric (floating point) value into an array
* of bits. The output is 0's except for a contiguous block of 1's. The
* location of this contiguous block varies continuously with the input value.
@@ -149,25 +151,28 @@
* resolution = radius / w
* n = w * range/radius (periodic)
* n = w * range/radius + 2 * h (non-periodic)
- *
+ *
* @author metaware
*/
public class ScalarEncoder extends Encoder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ScalarEncoder.class);
+
/**
* Constructs a new {@code ScalarEncoder}
*/
ScalarEncoder() {}
-
+
/**
- * Returns a builder for building ScalarEncoders.
+ * Returns a builder for building ScalarEncoders.
* This builder may be reused to produce multiple builders
- *
+ *
* @return a {@code ScalarEncoder.Builder}
*/
public static Encoder.Builder builder() {
return new ScalarEncoder.Builder();
}
-
+
/**
* Returns true if the underlying encoder works on deltas
*/
@@ -175,7 +180,7 @@ public static Encoder.Builder builder() {
public boolean isDelta() {
return false;
}
-
+
/**
* w -- number of bits to set in output
* minval -- minimum input value
@@ -189,7 +194,7 @@ public boolean isDelta() {
* representations
* resolution -- inputs separated by more than, or equal to this distance will have different
* representations
- *
+ *
* name -- an optional string which will become part of the description
*
* clipInput -- if true, non-periodic inputs smaller than minval or greater
@@ -202,29 +207,29 @@ public void init() {
throw new IllegalStateException(
"W must be an odd number (to eliminate centering difficulty)");
}
-
+
setHalfWidth((getW() - 1) / 2);
-
+
// For non-periodic inputs, padding is the number of bits "outside" the range,
// on each side. I.e. the representation of minval is centered on some bit, and
// there are "padding" bits to the left of that centered bit; similarly with
// bits to the right of the center bit of maxval
setPadding(isPeriodic() ? 0 : getHalfWidth());
-
+
if(!Double.isNaN(getMinVal()) && !Double.isNaN(getMinVal())) {
if(getMinVal() >= getMaxVal()) {
throw new IllegalStateException("maxVal must be > minVal");
}
setRangeInternal(getMaxVal() - getMinVal());
}
-
+
// There are three different ways of thinking about the representation. Handle
// each case here.
initEncoder(getW(), getMinVal(), getMaxVal(), getN(), getRadius(), getResolution());
-
+
//nInternal represents the output area excluding the possible padding on each side
setNInternal(getN() - 2 * getPadding());
-
+
if(getName() == null) {
if((getMinVal() % ((int)getMinVal())) > 0 ||
(getMaxVal() % ((int)getMaxVal())) > 0) {
@@ -233,18 +238,18 @@ public void init() {
setName("[" + (int)getMinVal() + ":" + (int)getMaxVal() + "]");
}
}
-
+
//Checks for likely mistakes in encoder settings
if(!isForced()) {
checkReasonableSettings();
}
description.add(new Tuple(2, (name = getName()).equals("None") ? "[" + (int)getMinVal() + ":" + (int)getMaxVal() + "]" : name, 0));
}
-
+
/**
- * There are three different ways of thinking about the representation.
+ * There are three different ways of thinking about the representation.
* Handle each case here.
- *
+ *
* @param c
* @param minVal
* @param maxVal
@@ -260,9 +265,9 @@ public void initEncoder(int w, double minVal, double maxVal, int n, double radiu
}else{
setResolution(getRangeInternal() / getN());
}
-
+
setRadius(getW() * getResolution());
-
+
if(isPeriodic()) {
setRange(getRangeInternal());
}else{
@@ -278,13 +283,13 @@ public void initEncoder(int w, double minVal, double maxVal, int n, double radiu
throw new IllegalStateException(
"One of n, radius, resolution must be specified for a ScalarEncoder");
}
-
+
if(isPeriodic()) {
setRange(getRangeInternal());
}else{
setRange(getRangeInternal() + getResolution());
}
-
+
double nFloat = w * (getRange() / getRadius()) + 2 * getPadding();
setN((int)Math.ceil(nFloat));
}
@@ -294,7 +299,7 @@ public void initEncoder(int w, double minVal, double maxVal, int n, double radiu
* Return the bit offset of the first bit to be set in the encoder output.
* For periodic encoders, this can be a negative number when the encoded output
* wraps around.
- *
+ *
* @param c the memory
* @param input the input data
* @return an encoded array
@@ -305,10 +310,7 @@ public Integer getFirstOnBit(double input) {
}else{
if(input < getMinVal()) {
if(clipInput() && !isPeriodic()) {
- if(getVerbosity() > 0) {
- System.out.println("Clipped input " + getName() +
- "=" + input + " to minval " + getMinVal());
- }
+ LOG.info("Clipped input " + getName() + "=" + input + " to minval " + getMinVal());
input = getMinVal();
}else{
throw new IllegalStateException("input (" + input +") less than range (" +
@@ -316,7 +318,7 @@ public Integer getFirstOnBit(double input) {
}
}
}
-
+
if(isPeriodic()) {
if(input >= getMaxVal()) {
throw new IllegalStateException("input (" + input +") greater than periodic range (" +
@@ -325,10 +327,7 @@ public Integer getFirstOnBit(double input) {
}else{
if(input > getMaxVal()) {
if(clipInput()) {
- if(getVerbosity() > 0) {
- System.out.println("Clipped input " + getName() + "=" + input + " to maxval " + getMaxVal());
- }
-
+ LOG.info("Clipped input " + getName() + "=" + input + " to maxval " + getMaxVal());
input = getMaxVal();
}else{
throw new IllegalStateException("input (" + input +") greater than periodic range (" +
@@ -336,17 +335,17 @@ public Integer getFirstOnBit(double input) {
}
}
}
-
+
int centerbin;
if(isPeriodic()) {
centerbin = ((int)((input - getMinVal()) * getNInternal() / getRange())) + getPadding();
}else{
centerbin = ((int)(((input - getMinVal()) + getResolution()/2) / getResolution())) + getPadding();
}
-
+
return centerbin - getHalfWidth();
}
-
+
/**
* Check if the settings are reasonable for the SpatialPooler to work
* @param c
@@ -357,7 +356,7 @@ public void checkReasonableSettings() {
"Number of bits in the SDR (%d) must be greater than 2, and recommended >= 21 (use forced=True to override)");
}
}
-
+
/**
* {@inheritDoc}
*/
@@ -365,7 +364,7 @@ public void checkReasonableSettings() {
public List getDecoderOutputFieldTypes() {
return Arrays.asList(FieldMetaType.FLOAT);
}
-
+
/**
* Should return the output width, in bits.
*/
@@ -373,23 +372,23 @@ public List getDecoderOutputFieldTypes() {
public int getWidth() {
return getN();
}
-
+
/**
* {@inheritDoc}
* NO-OP
*/
@Override
public int[] getBucketIndices(String input) { return null; }
-
+
/**
* Returns the bucket indices.
- *
- * @param input
+ *
+ * @param input
*/
@Override
public int[] getBucketIndices(double input) {
int minbin = getFirstOnBit(input);
-
+
//For periodic encoders, the bucket index is the index of the center bit
int bucketIdx;
if(isPeriodic()) {
@@ -400,10 +399,10 @@ public int[] getBucketIndices(double input) {
}else{//for non-periodic encoders, the bucket index is the index of the left bit
bucketIdx = minbin;
}
-
+
return new int[] { bucketIdx };
}
-
+
/**
* Encodes inputData and puts the encoded value into the output array,
* which is a 1-D array of length returned by {@link Connections#getW()}.
@@ -411,7 +410,7 @@ public int[] getBucketIndices(double input) {
* Note: The output array is reused, so clear it before updating it.
* @param inputData Data to encode. This should be validated by the encoder.
* @param output 1-D array of same length returned by {@link Connections#getW()}
- *
+ *
* @return
*/
@Override
@@ -420,7 +419,7 @@ public void encodeIntoArray(Double input, int[] output) {
Arrays.fill(output, 0);
return;
}
-
+
Integer bucketVal = getFirstOnBit(input);
if(bucketVal != null) {
int bucketIdx = bucketVal;
@@ -441,26 +440,24 @@ public void encodeIntoArray(Double input, int[] output) {
minbin = 0;
}
}
-
+
ArrayUtils.setIndexesTo(output, ArrayUtils.range(minbin, maxbin + 1), 1);
}
-
- if(getVerbosity() >= 2) {
- System.out.println("");
- System.out.println("input: " + input);
- System.out.println("range: " + getMinVal() + " - " + getMaxVal());
- System.out.println("n:" + getN() + "w:" + getW() + "resolution:" + getResolution() +
+
+ LOG.trace("");
+ LOG.trace("input: " + input);
+ LOG.trace("range: " + getMinVal() + " - " + getMaxVal());
+ LOG.trace("n:" + getN() + "w:" + getW() + "resolution:" + getResolution() +
"radius:" + getRadius() + "periodic:" + isPeriodic());
- System.out.println("output: " + Arrays.toString(output));
- System.out.println("input desc: " + decode(output, ""));
- }
+ LOG.trace("output: " + Arrays.toString(output));
+ LOG.trace("input desc: " + decode(output, ""));
}
/**
* Returns a {@link DecodeResult} which is a tuple of range names
- * and lists of {@link RangeLists} in the first entry, and a list
+ * and lists of {@link RangeLists} in the first entry, and a list
* of descriptions for each range in the second entry.
- *
+ *
* @param encoded the encoded bit vector
* @param parentFieldName the field the vector corresponds with
* @return
@@ -470,11 +467,11 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
// For now, we simply assume any top-down output greater than 0
// is ON. Eventually, we will probably want to incorporate the strength
// of each top-down output.
- if(encoded == null || encoded.length < 1) {
+ if(encoded == null || encoded.length < 1) {
return null;
}
int[] tmpOutput = Arrays.copyOf(encoded, encoded.length);
-
+
// ------------------------------------------------------------------------
// First, assume the input pool is not sampled 100%, and fill in the
// "holes" in the encoded representation (which are likely to be present
@@ -487,7 +484,7 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
Arrays.fill(searchStr, 1);
ArrayUtils.setRangeTo(searchStr, 1, -1, 0);
int subLen = searchStr.length;
-
+
// Does this search string appear in the output?
if(isPeriodic()) {
for(int j = 0;j < getN();j++) {
@@ -505,13 +502,11 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
}
}
}
-
- if(getVerbosity() >= 2) {
- System.out.println("raw output:" + Arrays.toString(
- ArrayUtils.sub(encoded, ArrayUtils.range(0, getN()))));
- System.out.println("filtered output:" + Arrays.toString(tmpOutput));
- }
-
+
+ LOG.trace("raw output:" + Arrays.toString(
+ ArrayUtils.sub(encoded, ArrayUtils.range(0, getN()))));
+ LOG.trace("filtered output:" + Arrays.toString(tmpOutput));
+
// ------------------------------------------------------------------------
// Find each run of 1's.
int[] nz = ArrayUtils.where(tmpOutput, new Condition.Adapter() {
@@ -534,19 +529,19 @@ public boolean eval(int n) {
i += 1;
}
runs.add(new Tuple(2, run[0], run[1]));
-
+
// If we have a periodic encoder, merge the first and last run if they
// both go all the way to the edges
if(isPeriodic() && runs.size() > 1) {
int l = runs.size() - 1;
if(((Integer)runs.get(0).get(0)) == 0 && ((Integer)runs.get(l).get(0)) + ((Integer)runs.get(l).get(1)) == getN()) {
- runs.set(l, new Tuple(2,
- (Integer)runs.get(l).get(0),
+ runs.set(l, new Tuple(2,
+ (Integer)runs.get(l).get(0),
((Integer)runs.get(l).get(1)) + ((Integer)runs.get(0).get(1)) ));
runs = runs.subList(1, runs.size());
}
}
-
+
// ------------------------------------------------------------------------
// Now, for each group of 1's, determine the "left" and "right" edges, where
// the "left" edge is inset by halfwidth and the "right" edge is inset by
@@ -565,7 +560,7 @@ public boolean eval(int n) {
left = start + getHalfWidth();
right = start + runLen - 1 - getHalfWidth();
}
-
+
double inMin, inMax;
// Convert to input space.
if(!isPeriodic()) {
@@ -582,7 +577,7 @@ public boolean eval(int n) {
inMax -= getRange();
}
}
-
+
// Clip low end
if(inMin < getMinVal()) {
inMin = getMinVal();
@@ -590,7 +585,7 @@ public boolean eval(int n) {
if(inMax < getMinVal()) {
inMax = getMinVal();
}
-
+
// If we have a periodic encoder, and the max is past the edge, break into
// 2 separate ranges
if(isPeriodic() && inMax >= getMaxVal()) {
@@ -606,7 +601,7 @@ public boolean eval(int n) {
ranges.add(new MinMax(inMin, inMax));
}
}
-
+
String desc = generateRangeDescription(ranges);
String fieldName;
// Return result
@@ -615,17 +610,17 @@ public boolean eval(int n) {
}else{
fieldName = getName();
}
-
+
RangeList inner = new RangeList(ranges, desc);
Map fieldsDict = new HashMap();
fieldsDict.put(fieldName, inner);
-
+
return new DecodeResult(fieldsDict, Arrays.asList(fieldName));
}
-
+
/**
* Generate description from a text description of the ranges
- *
+ *
* @param ranges A list of {@link MinMax}es.
*/
public String generateRangeDescription(List ranges) {
@@ -643,39 +638,39 @@ public String generateRangeDescription(List ranges) {
}
return desc.toString();
}
-
+
/**
* Return the internal topDownMapping matrix used for handling the
* bucketInfo() and topDownCompute() methods. This is a matrix, one row per
* category (bucket) where each row contains the encoded output for that
* category.
- *
+ *
* @param c the connections memory
* @return the internal topDownMapping
*/
public SparseObjectMatrix getTopDownMapping() {
-
+
if(topDownMapping == null) {
//The input scalar value corresponding to each possible output encoding
if(isPeriodic()) {
setTopDownValues(
- ArrayUtils.arange(getMinVal() + getResolution() / 2.0,
+ ArrayUtils.arange(getMinVal() + getResolution() / 2.0,
getMaxVal(), getResolution()));
}else{
//Number of values is (max-min)/resolutions
setTopDownValues(
- ArrayUtils.arange(getMinVal(), getMaxVal() + getResolution() / 2.0,
+ ArrayUtils.arange(getMinVal(), getMaxVal() + getResolution() / 2.0,
getResolution()));
}
}
-
+
//Each row represents an encoded output pattern
int numCategories = getTopDownValues().length;
SparseObjectMatrix topDownMapping;
setTopDownMapping(
topDownMapping = new SparseObjectMatrix(
new int[] { numCategories }));
-
+
double[] topDownValues = getTopDownValues();
int[] outputSpace = new int[getN()];
double minVal = getMinVal();
@@ -687,13 +682,13 @@ public SparseObjectMatrix getTopDownMapping() {
encodeIntoArray(value, outputSpace);
topDownMapping.set(i, Arrays.copyOf(outputSpace, outputSpace.length));
}
-
+
return topDownMapping;
}
-
+
/**
* {@inheritDoc}
- *
+ *
* @param the input value, in this case a double
* @return a list of one input double
*/
@@ -703,20 +698,20 @@ public TDoubleList getScalars(S d) {
retVal.add((Double)d);
return retVal;
}
-
+
/**
* Returns a list of items, one for each bucket defined by this encoder.
* Each item is the value assigned to that bucket, this is the same as the
* EncoderResult.value that would be returned by getBucketInfo() for that
* bucket and is in the same format as the input that would be passed to
* encode().
- *
+ *
* This call is faster than calling getBucketInfo() on each bucket individually
* if all you need are the bucket values.
*
* @param returnType class type parameter so that this method can return encoder
* specific value types
- *
+ *
* @return list of items, each item representing the bucket value for that
* bucket.
*/
@@ -733,18 +728,18 @@ public List getBucketValues(Class t) {
}
return (List)bucketValues;
}
-
+
/**
* {@inheritDoc}
*/
@Override
public List getBucketInfo(int[] buckets) {
SparseObjectMatrix topDownMapping = getTopDownMapping();
-
+
//The "category" is simply the bucket index
int category = buckets[0];
int[] encoding = topDownMapping.getObject(category);
-
+
//Which input value does this correspond to?
double inputVal;
if(isPeriodic()) {
@@ -752,10 +747,10 @@ public List getBucketInfo(int[] buckets) {
}else{
inputVal = getMinVal() + category * getResolution();
}
-
+
return Arrays.asList(new EncoderResult(inputVal, inputVal, encoding));
}
-
+
/**
* {@inheritDoc}
*/
@@ -763,17 +758,17 @@ public List getBucketInfo(int[] buckets) {
public List topDownCompute(int[] encoded) {
//Get/generate the topDown mapping table
SparseObjectMatrix topDownMapping = getTopDownMapping();
-
+
// See which "category" we match the closest.
int category = ArrayUtils.argmax(rightVecProd(topDownMapping, encoded));
-
- return getBucketInfo(new int[] { category });
+
+ return getBucketInfo(new int[]{category});
}
-
+
/**
* Returns a list of {@link Tuple}s which in this case is a list of
* key value parameter values for this {@code ScalarEncoder}
- *
+ *
* @return a list of {@link Tuple}s
*/
public List dict() {
@@ -784,7 +779,6 @@ public List dict() {
l.add(new Tuple(2, "name", getName()));
l.add(new Tuple(2, "minval", getMinVal()));
l.add(new Tuple(2, "topDownValues", Arrays.toString(getTopDownValues())));
- l.add(new Tuple(2, "verbosity", getVerbosity()));
l.add(new Tuple(2, "clipInput", clipInput()));
l.add(new Tuple(2, "n", getN()));
l.add(new Tuple(2, "padding", getPadding()));
@@ -796,17 +790,17 @@ public List dict() {
l.add(new Tuple(2, "halfwidth", getHalfWidth()));
l.add(new Tuple(2, "resolution", getResolution()));
l.add(new Tuple(2, "rangeInternal", getRangeInternal()));
-
+
return l;
}
/**
* Returns a {@link EncoderBuilder} for constructing {@link ScalarEncoder}s
- *
+ *
* The base class architecture is put together in such a way where boilerplate
* initialization can be kept to a minimum for implementing subclasses, while avoiding
* the mistake-proneness of extremely long argument lists.
- *
+ *
* @see ScalarEncoder.Builder#setStuff(int)
*/
public static class Builder extends Encoder.Builder {
@@ -814,20 +808,20 @@ private Builder() {}
@Override
public ScalarEncoder build() {
- //Must be instantiated so that super class can initialize
+ //Must be instantiated so that super class can initialize
//boilerplate variables.
encoder = new ScalarEncoder();
-
+
//Call super class here
super.build();
-
+
////////////////////////////////////////////////////////
// Implementing classes would do setting of specific //
// vars here together with any sanity checking //
////////////////////////////////////////////////////////
-
+
((ScalarEncoder)encoder).init();
-
+
return (ScalarEncoder)encoder;
}
}
From cd6799944df1507214c5dfe97c94257491235d42 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 11:57:53 +0100
Subject: [PATCH 06/56] #150 - replaced verbosity in Encoder
---
.../org/numenta/nupic/encoders/Encoder.java | 60 +++++++------------
1 file changed, 21 insertions(+), 39 deletions(-)
diff --git a/src/main/java/org/numenta/nupic/encoders/Encoder.java b/src/main/java/org/numenta/nupic/encoders/Encoder.java
index 8e63df24..3a407112 100644
--- a/src/main/java/org/numenta/nupic/encoders/Encoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/Encoder.java
@@ -38,6 +38,8 @@
import org.numenta.nupic.util.MinMax;
import org.numenta.nupic.util.SparseObjectMatrix;
import org.numenta.nupic.util.Tuple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
*
@@ -79,6 +81,9 @@
* @author David Ray
*/
public abstract class Encoder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Encoder.class);
+
/** Value used to represent no data */
public static final double SENTINEL_VALUE_FOR_MISSING_DATA = Double.NaN;
protected List description = new ArrayList<>();
@@ -119,7 +124,6 @@ public abstract class Encoder {
protected int nInternal;
protected double rangeInternal;
protected double range;
- protected int verbosity;
protected boolean encLearningEnabled;
protected List flattenedFieldTypeList;
protected Map> decoderFieldTypes;
@@ -422,22 +426,6 @@ public String getName() {
return name;
}
- /**
- * Sets the verbosity of debug output
- * @param v
- */
- public void setVerbosity(int v) {
- this.verbosity = v;
- }
-
- /**
- * Returns the verbosity setting for an encoder.
- * @return
- */
- public int getVerbosity() {
- return verbosity;
- }
-
/**
* Adds a the specified {@link Encoder} to the list of the specified
* parent's {@code Encoder}s.
@@ -920,7 +908,7 @@ public Tuple encodedBitDescription(int bitOffset, boolean formatted) {
* @param prefix
*/
public void pprintHeader(String prefix) {
- System.out.println(prefix == null ? "" : prefix);
+ LOG.info(prefix == null ? "" : prefix);
List description = getDescription();
description.add(new Tuple(2, "end", getWidth()));
@@ -934,22 +922,22 @@ public void pprintHeader(String prefix) {
StringBuilder pname = new StringBuilder(name);
if(name.length() > width) pname.setLength(width);
- System.out.println(String.format(formatStr, pname));
+ LOG.info(String.format(formatStr, pname));
}
len = getWidth() + (description.size() - 1)*3 - 1;
StringBuilder hyphens = new StringBuilder();
for(int i = 0;i < len;i++) hyphens.append("-");
- System.out.println(new StringBuilder(prefix).append(hyphens));
- }
+ LOG.info(new StringBuilder(prefix).append(hyphens).toString());
+ }
- /**
+ /**
* Pretty-print the encoded output using ascii art.
* @param output
* @param prefix
*/
public void pprint(int[] output, String prefix) {
- System.out.println(prefix == null ? "" : prefix);
+ LOG.info(prefix == null ? "" : prefix);
List description = getDescription();
description.add(new Tuple(2, "end", getWidth()));
@@ -959,17 +947,17 @@ public void pprint(int[] output, String prefix) {
int offset = (int)description.get(i).get(1);
int nextOffset = (int)description.get(i + 1).get(1);
- System.out.println(
- String.format("%s |",
- ArrayUtils.bitsToString(
- ArrayUtils.sub(output, ArrayUtils.range(offset, nextOffset))
- )
- )
- );
- }
- }
+ LOG.info(
+ String.format("%s |",
+ ArrayUtils.bitsToString(
+ ArrayUtils.sub(output, ArrayUtils.range(offset, nextOffset))
+ )
+ )
+ );
+ }
+ }
- /**
+ /**
* Takes an encoded output and does its best to work backwards and generate
* the input that would have generated it.
*
@@ -1265,7 +1253,6 @@ public int getDisplayWidth() {
public static abstract class Builder {
protected int n;
protected int w;
- protected int encVerbosity;
protected double minVal;
protected double maxVal;
protected double radius;
@@ -1284,7 +1271,6 @@ public E build() {
}
encoder.setN(n);
encoder.setW(w);
- encoder.setVerbosity(encVerbosity);
encoder.setMinVal(minVal);
encoder.setMaxVal(maxVal);
encoder.setRadius(radius);
@@ -1305,10 +1291,6 @@ public K w(int w) {
this.w = w;
return (K)this;
}
- public K verbosity(int verbosity) {
- this.encVerbosity = verbosity;
- return (K)this;
- }
public K minVal(double minVal) {
this.minVal = minVal;
return (K)this;
From 5023a4068d0ff7026474feefe1c60b9b8cd9df53 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 11:57:58 +0100
Subject: [PATCH 07/56] #154 - replaced verbosity in SDRCategoryEncoder
---
.../nupic/encoders/SDRCategoryEncoder.java | 23 ++++++++++---------
.../encoders/SDRCategoryEncoderTest.java | 1 -
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/main/java/org/numenta/nupic/encoders/SDRCategoryEncoder.java b/src/main/java/org/numenta/nupic/encoders/SDRCategoryEncoder.java
index 3fcf7381..77b0a356 100644
--- a/src/main/java/org/numenta/nupic/encoders/SDRCategoryEncoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/SDRCategoryEncoder.java
@@ -31,6 +31,8 @@
import org.numenta.nupic.util.MinMax;
import org.numenta.nupic.util.SparseObjectMatrix;
import org.numenta.nupic.util.Tuple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -54,6 +56,9 @@
* @see EncoderResult
*/
public class SDRCategoryEncoder extends Encoder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SDRCategoryEncoder.class);
+
private Random random;
private int thresholdOverlap;
private final SDRByCategoryMap sdrByCategory = new SDRByCategoryMap();
@@ -120,7 +125,7 @@ private SDRCategoryEncoder() {
def __init__(self, n, w, categoryList = None, name="category", verbosity=0,
encoderSeed=1, forced=False):
*/
- private void init(int n, int w, List categoryList, String name, int verbosity,
+ private void init(int n, int w, List categoryList, String name,
int encoderSeed, boolean forced) {
/*Python ref: n is total bits in output
@@ -167,7 +172,6 @@ private void init(int n, int w, List categoryList, String name, int verb
if (this.thresholdOverlap < this.w - 3) {
this.thresholdOverlap = this.w - 3;
}
- this.verbosity = verbosity;
this.description.add(new Tuple(2, name, 0));
this.name = name;
/*
@@ -215,11 +219,8 @@ public void encodeIntoArray(String input, int[] output) {
int[] categoryEncoding = sdrByCategory.getSdr(index);
System.arraycopy(categoryEncoding, 0, output, 0, categoryEncoding.length);
}
- if (verbosity >= 2) {
- System.out.println("input:" + input + ", index:" + index + ", output:" + ArrayUtils.intArrayToString(
- output));
- System.out.println("decoded:" + decodedToStr(decode(output, "")));
- }
+ LOG.trace("input:" + input + ", index:" + index + ", output:" + ArrayUtils.intArrayToString(output));
+ LOG.trace("decoded:" + decodedToStr(decode(output, "")));
}
/**
@@ -287,11 +288,11 @@ public boolean eval(int i) {
}
}
}
- if (verbosity >= 2) {
- System.out.println("Overlaps for decoding:");
+ LOG.trace("Overlaps for decoding:");
+ if (LOG.isTraceEnabled()){
int inx = 0;
for (String category : sdrByCategory.keySet()) {
- System.out.println(overlap[inx] + " " + category);
+ LOG.trace(overlap[inx] + " " + category);
inx++;
}
}
@@ -472,7 +473,7 @@ public SDRCategoryEncoder build() {
throw new IllegalStateException("\"W\" should be set");
}
SDRCategoryEncoder sdrCategoryEncoder = new SDRCategoryEncoder();
- sdrCategoryEncoder.init(n, w, categoryList, name, encVerbosity, encoderSeed, forced);
+ sdrCategoryEncoder.init(n, w, categoryList, name, encoderSeed, forced);
return sdrCategoryEncoder;
diff --git a/src/test/java/org/numenta/nupic/encoders/SDRCategoryEncoderTest.java b/src/test/java/org/numenta/nupic/encoders/SDRCategoryEncoderTest.java
index 79abdd83..aa02c957 100644
--- a/src/test/java/org/numenta/nupic/encoders/SDRCategoryEncoderTest.java
+++ b/src/test/java/org/numenta/nupic/encoders/SDRCategoryEncoderTest.java
@@ -207,7 +207,6 @@ public void testAutoGrow() {
.n(fieldWidth)
.w(bitsOn)
.name("foo")
- .verbosity(2)
.forced(true).build();
int[] encoded = new int[fieldWidth];
Arrays.fill(encoded, 0);
From c28e11fae8b82c2e4ee998c009d5d7cae596d370 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 11:58:27 +0100
Subject: [PATCH 08/56] #151 - replaced verbosity in CategoryEncoder
---
.../nupic/encoders/CategoryEncoder.java | 132 +++++++--------
.../nupic/encoders/CategoryEncoderTest.java | 157 +++++++++---------
2 files changed, 142 insertions(+), 147 deletions(-)
diff --git a/src/main/java/org/numenta/nupic/encoders/CategoryEncoder.java b/src/main/java/org/numenta/nupic/encoders/CategoryEncoder.java
index 4b7edb0c..fdba1c7d 100644
--- a/src/main/java/org/numenta/nupic/encoders/CategoryEncoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/CategoryEncoder.java
@@ -33,6 +33,8 @@
import org.numenta.nupic.util.MinMax;
import org.numenta.nupic.util.SparseObjectMatrix;
import org.numenta.nupic.util.Tuple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -43,14 +45,14 @@
/**
* Encodes a list of discrete categories (described by strings), that aren't
* related to each other, so we never emit a mixture of categories.
- *
+ *
* The value of zero is reserved for "unknown category"
- *
+ *
* Internally we use a ScalarEncoder with a radius of 1, but since we only encode
* integers, we never get mixture outputs.
*
* The SDRCategoryEncoder (not yet implemented in Java) uses a different method to encode categories
- *
+ *
*
* Typical usage is as follows:
*
@@ -61,13 +63,13 @@
* .maxVal(8.0)
* .periodic(false)
* .forced(true);
- *
+ *
* CategoryEncoder encoder = builder.build();
- *
+ *
* Above values are not an example of "sane" values.
- *
+ *
*
- *
+ *
* @author David Ray
* @see ScalarEncoder
* @see Encoder
@@ -75,39 +77,42 @@
* @see Parameters
*/
public class CategoryEncoder extends Encoder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CategoryEncoder.class);
+
protected int ncategories;
-
+
protected TObjectIntMap categoryToIndex = new TObjectIntHashMap();
protected TIntObjectMap indexToCategory = new TIntObjectHashMap();
-
+
protected List categoryList;
-
+
protected int width;
private ScalarEncoder scalarEncoder;
-
+
/**
* Constructs a new {@code CategoryEncoder}
*/
private CategoryEncoder() {
}
-
+
/**
- * Returns a builder for building CategoryEncoders.
+ * Returns a builder for building CategoryEncoders.
* This builder may be reused to produce multiple builders
- *
+ *
* @return a {@code CategoryEncoder.Builder}
*/
public static Encoder.Builder builder() {
return new CategoryEncoder.Builder();
}
-
+
public void init() {
// number of categories includes zero'th category: "unknown"
ncategories = categoryList == null ? 0 : categoryList.size() + 1;
minVal = 0;
maxVal = ncategories - 1;
-
+
scalarEncoder = ScalarEncoder.builder()
.n(this.n)
.w(this.w)
@@ -116,7 +121,7 @@ public void init() {
.maxVal(this.maxVal)
.periodic(this.periodic)
.forced(this.forced).build();
-
+
indexToCategory.put(0, "");
if(categoryList != null && !categoryList.isEmpty()) {
int len = categoryList.size();
@@ -125,26 +130,26 @@ public void init() {
indexToCategory.put(i + 1, categoryList.get(i));
}
}
-
-
+
+
width = n = w * ncategories;
-
+
//TODO this is what the CategoryEncoder was doing before I added the ScalarEncoder delegate.
- //I'm concerned because we're changing n without calling init again on the scalar encoder.
+ //I'm concerned because we're changing n without calling init again on the scalar encoder.
//In other words, if I move the scalarEncoder = ...build() from to here, the test cases fail
//which indicates significant fragility and at some level a violation of encapsulation.
scalarEncoder.n = n;
-
-
-
+
+
+
if(getWidth() != width) {
throw new IllegalStateException(
"Width != w (num bits to represent output item) * #categories");
}
-
+
description.add(new Tuple(2, name, 0));
}
-
+
/**
* {@inheritDoc}
*/
@@ -152,7 +157,7 @@ public void init() {
public TDoubleList getScalars(T d) {
return new TDoubleArrayList(new double[] { categoryToIndex.get(d) });
}
-
+
/**
* {@inheritDoc}
*/
@@ -161,7 +166,7 @@ public int[] getBucketIndices(String input) {
if(input == null) return null;
return scalarEncoder.getBucketIndices(categoryToIndex.get(input));
}
-
+
/**
* {@inheritDoc}
*/
@@ -176,12 +181,9 @@ public void encodeIntoArray(String input, int[] output) {
value = value == categoryToIndex.getNoEntryValue() ? 0 : value;
scalarEncoder.encodeIntoArray(value, output);
}
-
- if(verbosity >= 2) {
- System.out.println(
- String.format("input: %s, val: %s, value: %d, output: %s",
- input, val, value, Arrays.toString(output)));
- }
+
+ LOG.trace("input: {}, val: {}, value: {}, output: {}",
+ input, val, value, Arrays.toString(output));
}
/**
@@ -191,16 +193,16 @@ public void encodeIntoArray(String input, int[] output) {
public DecodeResult decode(int[] encoded, String parentFieldName) {
// Get the scalar values from the underlying scalar encoder
DecodeResult result = scalarEncoder.decode(encoded, parentFieldName);
-
+
if(result.getFields().size() == 0) {
return result;
}
-
+
// Expect only 1 field
if(result.getFields().size() != 1) {
throw new IllegalStateException("Expecting only one field");
}
-
+
//Get the list of categories the scalar values correspond to and
// generate the description from the category name(s).
Map fieldRanges = result.getFields();
@@ -219,7 +221,7 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
minV += 1;
}
}
-
+
//Return result
String fieldName;
if(!parentFieldName.isEmpty()) {
@@ -227,13 +229,13 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
}else{
fieldName = name;
}
-
+
Map retVal = new HashMap();
retVal.put(fieldName, new RangeList(outRanges, desc.toString()));
-
+
return new DecodeResult(retVal, Arrays.asList(new String[] { fieldName }));
}
-
+
/**
* {@inheritDoc}
*/
@@ -241,26 +243,26 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
public TDoubleList closenessScores(TDoubleList expValues, TDoubleList actValues, boolean fractional) {
double expValue = expValues.get(0);
double actValue = actValues.get(0);
-
+
double closeness = expValue == actValue ? 1.0 : 0;
if(!fractional) closeness = 1.0 - closeness;
-
+
return new TDoubleArrayList(new double[]{ closeness });
}
-
+
/**
* Returns a list of items, one for each bucket defined by this encoder.
* Each item is the value assigned to that bucket, this is the same as the
* EncoderResult.value that would be returned by getBucketInfo() for that
* bucket and is in the same format as the input that would be passed to
* encode().
- *
+ *
* This call is faster than calling getBucketInfo() on each bucket individually
* if all you need are the bucket values.
*
* @param returnType class type parameter so that this method can return encoder
* specific value types
- *
+ *
* @return list of items, each item representing the bucket value for that
* bucket.
*/
@@ -275,10 +277,10 @@ public List getBucketValues(Class t) {
((List)bucketValues).add((String)getBucketInfo(new int[] { i }).get(0).getValue());
}
}
-
+
return (List)bucketValues;
}
-
+
/**
* {@inheritDoc}
*/
@@ -286,23 +288,23 @@ public List getBucketValues(Class t) {
public List getBucketInfo(int[] buckets) {
// For the category encoder, the bucket index is the category index
List bucketInfo = scalarEncoder.getBucketInfo(buckets);
-
+
int categoryIndex = (int)Math.round((double)bucketInfo.get(0).getValue());
String category = indexToCategory.get(categoryIndex);
-
+
bucketInfo.set(0, new EncoderResult(category, categoryIndex, bucketInfo.get(0).getEncoding()));
return bucketInfo;
}
-
+
/**
* {@inheritDoc}
*/
@Override
public List topDownCompute(int[] encoded) {
//Get/generate the topDown mapping table
- SparseObjectMatrix topDownMapping = scalarEncoder.getTopDownMapping();
+ SparseObjectMatrix topDownMapping = scalarEncoder.getTopDownMapping();
// See which "category" we match the closest.
- int category = ArrayUtils.argmax(rightVecProd(topDownMapping, encoded));
+ int category = ArrayUtils.argmax(rightVecProd(topDownMapping, encoded));
return getBucketInfo(new int[] { category });
}
@@ -313,30 +315,30 @@ public List getCategoryList() {
public void setCategoryList(List categoryList) {
this.categoryList = categoryList;
}
-
+
/**
* Returns a {@link EncoderBuilder} for constructing {@link CategoryEncoder}s
- *
+ *
* The base class architecture is put together in such a way where boilerplate
* initialization can be kept to a minimum for implementing subclasses, while avoiding
* the mistake-proneness of extremely long argument lists.
- *
+ *
* @see ScalarEncoder.Builder#setStuff(int)
*/
public static class Builder extends Encoder.Builder {
private List categoryList;
-
+
private Builder() {}
@Override
public CategoryEncoder build() {
- //Must be instantiated so that super class can initialize
+ //Must be instantiated so that super class can initialize
//boilerplate variables.
encoder = new CategoryEncoder();
-
+
//Call super class here
super.build();
-
+
////////////////////////////////////////////////////////
// Implementing classes would do setting of specific //
// vars here together with any sanity checking //
@@ -348,16 +350,16 @@ public CategoryEncoder build() {
((CategoryEncoder)encoder).setCategoryList(this.categoryList);
//Call init
((CategoryEncoder)encoder).init();
-
+
return (CategoryEncoder)encoder;
}
-
+
/**
- * Never called - just here as an example of specialization for a specific
+ * Never called - just here as an example of specialization for a specific
* subclass of Encoder.Builder
- *
+ *
* Example specific method!!
- *
+ *
* @param stuff
* @return
*/
diff --git a/src/test/java/org/numenta/nupic/encoders/CategoryEncoderTest.java b/src/test/java/org/numenta/nupic/encoders/CategoryEncoderTest.java
index 008d252a..5a15147d 100644
--- a/src/test/java/org/numenta/nupic/encoders/CategoryEncoderTest.java
+++ b/src/test/java/org/numenta/nupic/encoders/CategoryEncoderTest.java
@@ -25,6 +25,8 @@
import org.numenta.nupic.util.ArrayUtils;
import org.numenta.nupic.util.Condition;
import org.numenta.nupic.util.MinMax;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
@@ -34,9 +36,12 @@
import static org.junit.Assert.assertTrue;
public class CategoryEncoderTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CategoryEncoderTest.class);
+
private CategoryEncoder ce;
private CategoryEncoder.Builder builder;
-
+
private void setUp() {
builder = ((CategoryEncoder.Builder)CategoryEncoder.builder())
.w(3)
@@ -46,7 +51,7 @@ private void setUp() {
.periodic(false)
.forced(true);
}
-
+
private void initCE() {
ce = builder.build();
}
@@ -54,17 +59,17 @@ private void initCE() {
@Test
public void testCategoryEncoder() {
String[] categories = new String[] { "ES", "GB", "US" };
-
+
setUp();
builder.radius(1);
builder.categoryList(Arrays.asList(categories));
initCE();
-
- System.out.println("Testing CategoryEncoder...");
+
+ LOGGER.info("Testing CategoryEncoder...");
// forced: is not recommended, but is used here for readability. see scalar.py
int[] output = ce.encode("US");
assertTrue(Arrays.equals(new int[] { 0,0,0,0,0,0,0,0,0,1,1,1 }, output));
-
+
// Test reverse lookup
DecodeResult decoded = ce.decode(output, "");
assertEquals(decoded.getFields().size(), 1, 0);
@@ -73,29 +78,29 @@ public void testCategoryEncoder() {
MinMax minMax = rangeList.get(0).getRanges().get(0);
assertEquals(minMax.min(), minMax.max(), 0);
assertTrue(minMax.min() == 3 && minMax.max() == 3);
- System.out.println("decodedToStr of " + minMax + "=>" + ce.decodedToStr(decoded));
-
+ LOGGER.info("decodedToStr of " + minMax + "=>" + ce.decodedToStr(decoded));
+
// Test topdown compute
for(String v : categories) {
output = ce.encode(v);
EncoderResult topDown = ce.topDownCompute(output).get(0);
assertEquals(v, topDown.getValue());
assertEquals((int)ce.getScalars(v).get(0), (int)topDown.getScalar().doubleValue());
-
+
int[] bucketIndices = ce.getBucketIndices(v);
- System.out.println("bucket index => " + bucketIndices[0]);
+ LOGGER.info("bucket index => " + bucketIndices[0]);
topDown = ce.getBucketInfo(bucketIndices).get(0);
assertEquals(v, topDown.getValue());
assertEquals((int)ce.getScalars(v).get(0), (int)topDown.getScalar().doubleValue());
assertTrue(Arrays.equals(topDown.getEncoding(), output));
assertEquals(topDown.getValue(), ce.getBucketValues(String.class).get(bucketIndices[0]));
}
-
+
//-------------
// unknown category
output = ce.encode("NA");
assertTrue(Arrays.equals(new int[] { 1,1,1,0,0,0,0,0,0,0,0,0 }, output));
-
+
// Test reverse lookup
decoded = ce.decode(output, "");
assertEquals(decoded.getFields().size(), 1, 0);
@@ -104,21 +109,21 @@ public void testCategoryEncoder() {
minMax = rangeList.get(0).getRanges().get(0);
assertEquals(minMax.min(), minMax.max(), 0);
assertTrue(minMax.min() == 0 && minMax.max() == 0);
- System.out.println("decodedToStr of " + minMax + "=>" + ce.decodedToStr(decoded));
-
+ LOGGER.info("decodedToStr of " + minMax + "=>" + ce.decodedToStr(decoded));
+
EncoderResult topDown = ce.topDownCompute(output).get(0);
assertEquals(topDown.getValue(), "");
assertEquals(topDown.getScalar(), 0);
-
+
//--------------
// ES
output = ce.encode("ES");
assertTrue(Arrays.equals( new int[] {0,0,0,1,1,1,0,0,0,0,0,0 }, output));
-
+
// MISSING VALUE
int[] outputForMissing = ce.encode((String)null);
assertTrue(Arrays.equals( new int[] {0,0,0,0,0,0,0,0,0,0,0,0 }, outputForMissing));
-
+
// Test reverse lookup
decoded = ce.decode(output, "");
assertEquals(decoded.getFields().size(), 1, 0);
@@ -127,17 +132,17 @@ public void testCategoryEncoder() {
minMax = rangeList.get(0).getRanges().get(0);
assertEquals(minMax.min(), minMax.max(), 0);
assertTrue(minMax.min() == 1 && minMax.max() == 1);
- System.out.println("decodedToStr of " + minMax + "=>" + ce.decodedToStr(decoded));
-
+ LOGGER.info("decodedToStr of " + minMax + "=>" + ce.decodedToStr(decoded));
+
// Test topdown compute
topDown = ce.topDownCompute(output).get(0);
assertEquals(topDown.getValue(), "ES");
assertEquals(topDown.getScalar(), (int)ce.getScalars("ES").get(0));
-
+
//----------------
// Multiple categories
Arrays.fill(output, 1);
-
+
// Test reverse lookup
decoded = ce.decode(output, "");
assertEquals(decoded.getFields().size(), 1, 0);
@@ -146,33 +151,31 @@ public void testCategoryEncoder() {
minMax = rangeList.get(0).getRanges().get(0);
assertTrue(minMax.min() != minMax.max());
assertTrue(minMax.min() == 0 && minMax.max() == 3);
- System.out.println("decodedToStr of " + minMax + "=>" + ce.decodedToStr(decoded));
-
-
+ LOGGER.info("decodedToStr of " + minMax + "=>" + ce.decodedToStr(decoded));
+
+
//----------------
// Test with width = 1
categories = new String[] { "cat1", "cat2", "cat3", "cat4", "cat5" };
-
+
setUp();
builder.radius(1);
builder.categoryList(Arrays.asList(categories));
initCE();
-
+
for(String cat : categories) {
output = ce.encode(cat);
topDown = ce.topDownCompute(output).get(0);
- if(ce.getVerbosity() >= 1) {
- System.out.println(cat + "->" + Arrays.toString(output) +
+ LOGGER.debug(cat + "->" + Arrays.toString(output) +
" " + ArrayUtils.where(output, new Condition.Adapter() {
public boolean eval(int i) { return i == 1; }
}));
- System.out.println(" scalarTopDown: " + ce.topDownCompute(output));
- System.out.println(" topDown " + topDown);
- }
+ LOGGER.debug(" scalarTopDown: " + ce.topDownCompute(output));
+ LOGGER.debug(" topDown " + topDown);
assertEquals(topDown.getValue(), cat);
assertEquals(topDown.getScalar(), (int)ce.getScalars(cat).get(0));
}
-
+
//==================
// Test with width = 9, removing some bits in the encoded output
categories = new String[9];
@@ -184,109 +187,99 @@ public void testCategoryEncoder() {
builder.forced(true);
builder.categoryList(Arrays.asList(categories));
initCE();
-
+
for(String cat : categories) {
output = ce.encode(cat);
topDown = ce.topDownCompute(output).get(0);
- if(ce.getVerbosity() >= 1) {
- System.out.println(cat + "->" + Arrays.toString(output) +
- " " + ArrayUtils.where(output, new Condition.Adapter() {
- public boolean eval(int i) { return i == 1; }
- }));
- System.out.println(" scalarTopDown: " + ce.topDownCompute(output));
- System.out.println(" topDown " + topDown);
- }
+ LOGGER.debug(cat + "->" + Arrays.toString(output) +
+ " " + ArrayUtils.where(output, new Condition.Adapter() {
+ public boolean eval(int i) {
+ return i == 1;
+ }
+ }));
+ LOGGER.debug(" scalarTopDown: " + ce.topDownCompute(output));
+ LOGGER.debug(" topDown " + topDown);
assertEquals(topDown.getValue(), cat);
assertEquals(topDown.getScalar(), (int)ce.getScalars(cat).get(0));
-
+
// Get rid of 1 bit on the left
int[] outputNZs = ArrayUtils.where(output, new Condition.Adapter() {
public boolean eval(int i) { return i == 1; }
});
// int[] outputPreserve = Arrays.copyOf(output, output.length);
output[outputNZs[0]] = 0;
-// System.out.println("output = " + Arrays.toString(outputPreserve));
-// System.out.println("outputNZs = " + Arrays.toString(outputNZs));
-// System.out.println("outputDelta = " + Arrays.toString(output));
+// LOGGER.info("output = " + Arrays.toString(outputPreserve));
+// LOGGER.info("outputNZs = " + Arrays.toString(outputNZs));
+// LOGGER.info("outputDelta = " + Arrays.toString(output));
topDown = ce.topDownCompute(output).get(0);
- if(ce.getVerbosity() >= 1) {
- System.out.println("missing 1 bit on left: ->" + Arrays.toString(output) +
+ LOGGER.debug("missing 1 bit on left: ->" + Arrays.toString(output) +
" " + ArrayUtils.where(output, new Condition.Adapter() {
public boolean eval(int i) { return i == 1; }
}));
- System.out.println(" scalarTopDown: " + ce.topDownCompute(output));
- System.out.println(" topDown " + topDown);
- }
+ LOGGER.debug(" scalarTopDown: " + ce.topDownCompute(output));
+ LOGGER.debug(" topDown " + topDown);
assertEquals(topDown.getValue(), cat);
assertEquals(topDown.getScalar(), (int)ce.getScalars(cat).get(0));
-
- // Get rid of 1 bit on the right
+
+ // Get rid of 1 bit on the right
output[outputNZs[0]] = 1;
output[outputNZs[outputNZs.length - 1]] = 0;
topDown = ce.topDownCompute(output).get(0);
- if(ce.getVerbosity() >= 1) {
- System.out.println("missing 1 bit on right: ->" + Arrays.toString(output) +
+ LOGGER.debug("missing 1 bit on right: ->" + Arrays.toString(output) +
" " + ArrayUtils.where(output, new Condition.Adapter() {
public boolean eval(int i) { return i == 1; }
}));
- System.out.println(" scalarTopDown: " + ce.topDownCompute(output));
- System.out.println(" topDown " + topDown);
- }
+ LOGGER.debug(" scalarTopDown: " + ce.topDownCompute(output));
+ LOGGER.debug(" topDown " + topDown);
assertEquals(topDown.getValue(), cat);
assertEquals(topDown.getScalar(), (int)ce.getScalars(cat).get(0));
-
- // Get rid of 4 bits on the left
+
+ // Get rid of 4 bits on the left
Arrays.fill(output, 0);
int[] indexes = ArrayUtils.range(outputNZs[outputNZs.length - 5], outputNZs[outputNZs.length - 1] + 1);
for(int i = 0;i < indexes.length;i++) output[indexes[i]] = 1;
- System.out.println(Arrays.toString(output));
+ LOGGER.info(Arrays.toString(output));
topDown = ce.topDownCompute(output).get(0);
- if(ce.getVerbosity() >= 1) {
- System.out.println("missing 4 bits on left: ->" + Arrays.toString(output) +
+ LOGGER.debug("missing 4 bits on left: ->" + Arrays.toString(output) +
" " + ArrayUtils.where(output, new Condition.Adapter() {
public boolean eval(int i) { return i == 1; }
}));
- System.out.println(" scalarTopDown: " + ce.topDownCompute(output));
- System.out.println(" topDown " + topDown);
- }
+ LOGGER.debug(" scalarTopDown: " + ce.topDownCompute(output));
+ LOGGER.debug(" topDown " + topDown);
assertEquals(topDown.getValue(), cat);
assertEquals(topDown.getScalar(), (int)ce.getScalars(cat).get(0));
-
- // Get rid of 4 bits on the right
+
+ // Get rid of 4 bits on the right
Arrays.fill(output, 0);
indexes = ArrayUtils.range(outputNZs[0], outputNZs[5]);
for(int i = 0;i < indexes.length;i++) output[indexes[i]] = 1;
- System.out.println(Arrays.toString(output));
+ LOGGER.info(Arrays.toString(output));
topDown = ce.topDownCompute(output).get(0);
- if(ce.getVerbosity() >= 1) {
- System.out.println("missing 4 bits on left: ->" + Arrays.toString(output) +
+ LOGGER.debug("missing 4 bits on left: ->" + Arrays.toString(output) +
" " + ArrayUtils.where(output, new Condition.Adapter() {
public boolean eval(int i) { return i == 1; }
}));
- System.out.println(" scalarTopDown: " + ce.topDownCompute(output));
- System.out.println(" topDown " + topDown);
- }
+ LOGGER.debug(" scalarTopDown: " + ce.topDownCompute(output));
+ LOGGER.debug(" topDown " + topDown);
assertEquals(topDown.getValue(), cat);
assertEquals(topDown.getScalar(), (int)ce.getScalars(cat).get(0));
}
-
+
int[] output1 = ce.encode("cat1");
int[] output2 = ce.encode("cat9");
output = ArrayUtils.or(output1, output2);
topDown = ce.topDownCompute(output).get(0);
- if(ce.getVerbosity() >= 1) {
- System.out.println("cat1 + cat9 ->" + Arrays.toString(output) +
+ LOGGER.debug("cat1 + cat9 ->" + Arrays.toString(output) +
" " + ArrayUtils.where(output, new Condition.Adapter() {
public boolean eval(int i) { return i == 1; }
}));
- System.out.println(" scalarTopDown: " + ce.topDownCompute(output));
- System.out.println(" topDown " + topDown);
- }
-
+ LOGGER.debug(" scalarTopDown: " + ce.topDownCompute(output));
+ LOGGER.debug(" topDown " + topDown);
+
assertTrue(topDown.getScalar().equals((int)ce.getScalars("cat1").get(0)) ||
topDown.getScalar().equals((int)ce.getScalars("cat9").get(0)));
-
- System.out.println("passed"); //Just because they did it in the Python version :-)
+
+ LOGGER.info("passed"); //Just because they did it in the Python version :-)
}
}
From 4b195e49ea54e2a82a5c5bd59377288d1cf4eab8 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 11:58:39 +0100
Subject: [PATCH 09/56] #150 - replaced verbosity in other encoders
---
.../numenta/nupic/encoders/MultiEncoder.java | 87 +++++++++----------
.../nupic/encoders/PassThroughEncoder.java | 58 +++++++------
.../RandomDistributedScalarEncoder.java | 82 +++++++++--------
3 files changed, 112 insertions(+), 115 deletions(-)
diff --git a/src/main/java/org/numenta/nupic/encoders/MultiEncoder.java b/src/main/java/org/numenta/nupic/encoders/MultiEncoder.java
index 61cc79ab..0807534a 100644
--- a/src/main/java/org/numenta/nupic/encoders/MultiEncoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/MultiEncoder.java
@@ -38,29 +38,29 @@
* A MultiEncoder encodes a dictionary or object with
* multiple components. A MultiEncode contains a number
* of sub-encoders, each of which encodes a separate component.
- *
+ *
* @see Encoder
* @see EncoderResult
* @see Parameters
- *
+ *
* @author wlmiller
*/
public class MultiEncoder extends Encoder
- *
+ *
* @author Anubhav Chaturvedi
*/
public static class Builder
@@ -671,7 +668,6 @@ public static class Builder
private Builder() {
this.n(400);
this.w(21);
- this.verbosity(0);
seed = 42;
maxBuckets = 1000;
maxOverlap = 2;
From 0e4024fbd6d5fa64148d3ba9f3daabdf2d82e455 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Sun, 1 Feb 2015 12:07:46 +0100
Subject: [PATCH 10/56] Standardized LOGGER naming.
---
.../org/numenta/nupic/encoders/Encoder.java | 12 +++++-----
.../numenta/nupic/encoders/ScalarEncoder.java | 24 +++++++++----------
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/src/main/java/org/numenta/nupic/encoders/Encoder.java b/src/main/java/org/numenta/nupic/encoders/Encoder.java
index 3a407112..5046d32a 100644
--- a/src/main/java/org/numenta/nupic/encoders/Encoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/Encoder.java
@@ -82,7 +82,7 @@
*/
public abstract class Encoder {
- private static final Logger LOG = LoggerFactory.getLogger(Encoder.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(Encoder.class);
/** Value used to represent no data */
public static final double SENTINEL_VALUE_FOR_MISSING_DATA = Double.NaN;
@@ -908,7 +908,7 @@ public Tuple encodedBitDescription(int bitOffset, boolean formatted) {
* @param prefix
*/
public void pprintHeader(String prefix) {
- LOG.info(prefix == null ? "" : prefix);
+ LOGGER.info(prefix == null ? "" : prefix);
List description = getDescription();
description.add(new Tuple(2, "end", getWidth()));
@@ -922,13 +922,13 @@ public void pprintHeader(String prefix) {
StringBuilder pname = new StringBuilder(name);
if(name.length() > width) pname.setLength(width);
- LOG.info(String.format(formatStr, pname));
+ LOGGER.info(String.format(formatStr, pname));
}
len = getWidth() + (description.size() - 1)*3 - 1;
StringBuilder hyphens = new StringBuilder();
for(int i = 0;i < len;i++) hyphens.append("-");
- LOG.info(new StringBuilder(prefix).append(hyphens).toString());
+ LOGGER.info(new StringBuilder(prefix).append(hyphens).toString());
}
/**
@@ -937,7 +937,7 @@ public void pprintHeader(String prefix) {
* @param prefix
*/
public void pprint(int[] output, String prefix) {
- LOG.info(prefix == null ? "" : prefix);
+ LOGGER.info(prefix == null ? "" : prefix);
List description = getDescription();
description.add(new Tuple(2, "end", getWidth()));
@@ -947,7 +947,7 @@ public void pprint(int[] output, String prefix) {
int offset = (int)description.get(i).get(1);
int nextOffset = (int)description.get(i + 1).get(1);
- LOG.info(
+ LOGGER.info(
String.format("%s |",
ArrayUtils.bitsToString(
ArrayUtils.sub(output, ArrayUtils.range(offset, nextOffset))
diff --git a/src/main/java/org/numenta/nupic/encoders/ScalarEncoder.java b/src/main/java/org/numenta/nupic/encoders/ScalarEncoder.java
index 77ee65e6..94397cdb 100644
--- a/src/main/java/org/numenta/nupic/encoders/ScalarEncoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/ScalarEncoder.java
@@ -156,7 +156,7 @@
*/
public class ScalarEncoder extends Encoder {
- private static final Logger LOG = LoggerFactory.getLogger(ScalarEncoder.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ScalarEncoder.class);
/**
* Constructs a new {@code ScalarEncoder}
@@ -310,7 +310,7 @@ public Integer getFirstOnBit(double input) {
}else{
if(input < getMinVal()) {
if(clipInput() && !isPeriodic()) {
- LOG.info("Clipped input " + getName() + "=" + input + " to minval " + getMinVal());
+ LOGGER.info("Clipped input " + getName() + "=" + input + " to minval " + getMinVal());
input = getMinVal();
}else{
throw new IllegalStateException("input (" + input +") less than range (" +
@@ -327,7 +327,7 @@ public Integer getFirstOnBit(double input) {
}else{
if(input > getMaxVal()) {
if(clipInput()) {
- LOG.info("Clipped input " + getName() + "=" + input + " to maxval " + getMaxVal());
+ LOGGER.info("Clipped input " + getName() + "=" + input + " to maxval " + getMaxVal());
input = getMaxVal();
}else{
throw new IllegalStateException("input (" + input +") greater than periodic range (" +
@@ -444,13 +444,13 @@ public void encodeIntoArray(Double input, int[] output) {
ArrayUtils.setIndexesTo(output, ArrayUtils.range(minbin, maxbin + 1), 1);
}
- LOG.trace("");
- LOG.trace("input: " + input);
- LOG.trace("range: " + getMinVal() + " - " + getMaxVal());
- LOG.trace("n:" + getN() + "w:" + getW() + "resolution:" + getResolution() +
+ LOGGER.trace("");
+ LOGGER.trace("input: " + input);
+ LOGGER.trace("range: " + getMinVal() + " - " + getMaxVal());
+ LOGGER.trace("n:" + getN() + "w:" + getW() + "resolution:" + getResolution() +
"radius:" + getRadius() + "periodic:" + isPeriodic());
- LOG.trace("output: " + Arrays.toString(output));
- LOG.trace("input desc: " + decode(output, ""));
+ LOGGER.trace("output: " + Arrays.toString(output));
+ LOGGER.trace("input desc: " + decode(output, ""));
}
/**
@@ -503,9 +503,9 @@ public DecodeResult decode(int[] encoded, String parentFieldName) {
}
}
- LOG.trace("raw output:" + Arrays.toString(
- ArrayUtils.sub(encoded, ArrayUtils.range(0, getN()))));
- LOG.trace("filtered output:" + Arrays.toString(tmpOutput));
+ LOGGER.trace("raw output:" + Arrays.toString(
+ ArrayUtils.sub(encoded, ArrayUtils.range(0, getN()))));
+ LOGGER.trace("filtered output:" + Arrays.toString(tmpOutput));
// ------------------------------------------------------------------------
// Find each run of 1's.
From 1c162bf74896522e1b5dfd1cbc48d0672cfb3088 Mon Sep 17 00:00:00 2001
From: Sean Connolly
Date: Wed, 4 Feb 2015 21:43:32 +0100
Subject: [PATCH 11/56] Switched use of verbosity to SLF4J
---
.../nupic/encoders/AdaptiveScalarEncoder.java | 45 ++++++++++---------
1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/src/main/java/org/numenta/nupic/encoders/AdaptiveScalarEncoder.java b/src/main/java/org/numenta/nupic/encoders/AdaptiveScalarEncoder.java
index 6bbf5fe2..a00cf8be 100644
--- a/src/main/java/org/numenta/nupic/encoders/AdaptiveScalarEncoder.java
+++ b/src/main/java/org/numenta/nupic/encoders/AdaptiveScalarEncoder.java
@@ -1,31 +1,36 @@
package org.numenta.nupic.encoders;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AdaptiveScalarEncoder extends ScalarEncoder {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AdaptiveScalarEncoder.class);
+
/*
* This is an implementation of the scalar encoder that adapts the min and
* max of the scalar encoder dynamically. This is essential to the streaming
* model of the online prediction framework.
- *
+ *
* Initialization of an adapive encoder using resolution or radius is not
* supported; it must be intitialized with n. This n is kept constant while
* the min and max of the encoder changes.
- *
+ *
* The adaptive encoder must be have periodic set to false.
- *
+ *
* The adaptive encoder may be initialized with a minval and maxval or with
* `None` for each of these. In the latter case, the min and max are set as
* the 1st and 99th percentile over a window of the past 100 records.
- *
+ *
* *Note:** the sliding window may record duplicates of the values in the
* dataset, and therefore does not reflect the statistical distribution of
* the input data and may not be used to calculate the median, mean etc.
*/
-
+
public int recordNum = 0;
public boolean learningEnabled = true;
public Double[] slidingWindow = new Double[0];
@@ -34,7 +39,7 @@ public class AdaptiveScalarEncoder extends ScalarEncoder {
/*
* (non-Javadoc)
- *
+ *
* @see org.numenta.nupic.encoders.ScalarEncoder#init()
*/
@Override
@@ -42,10 +47,10 @@ public void init() {
this.setPeriodic(false);
super.init();
}
-
+
/*
* (non-Javadoc)
- *
+ *
* @see org.numenta.nupic.encoders.ScalarEncoder#initEncoder(int, double,
* double, int, double, double)
*/
@@ -71,7 +76,7 @@ public AdaptiveScalarEncoder() {
/**
* Returns a builder for building AdaptiveScalarEncoder. This builder may be
* reused to produce multiple builders
- *
+ *
* @return a {@code AdaptiveScalarEncoder.Builder}
*/
public static AdaptiveScalarEncoder.Builder adaptiveBuilder() {
@@ -129,7 +134,7 @@ private void setMinAndMax(Double input, boolean learn) {
slidingWindow = deleteItem(slidingWindow, 0);
}
slidingWindow = appendItem(slidingWindow, input);
-
+
if (this.minVal == this.maxVal) {
this.minVal = input;
this.maxVal = input + 1;
@@ -140,20 +145,16 @@ private void setMinAndMax(Double input, boolean learn) {
double minOverWindow = sorted[0];
double maxOverWindow = sorted[sorted.length - 1];
if (minOverWindow < this.minVal) {
- if (this.verbosity >= 2) {
- System.out.println(String.format("Input %s=%d smaller than minval %d. Adjusting minval to %d",
- this.name, input, this.minVal, minOverWindow));
- this.minVal = minOverWindow;
- setEncoderParams();
- }
+ LOGGER.trace("Input {}={} smaller than minVal {}. Adjusting minVal to {}",
+ this.name, input, this.minVal, minOverWindow);
+ this.minVal = minOverWindow;
+ setEncoderParams();
}
if (maxOverWindow > this.maxVal) {
- if (this.verbosity >= 2) {
- System.out.println(String.format("Input %s=%d greater than maxval %d. Adjusting maxval to %d",
- this.name, input, this.minVal, minOverWindow));
- this.maxVal = maxOverWindow;
- setEncoderParams();
- }
+ LOGGER.trace("Input {}={} greater than maxVal {}. Adjusting maxVal to {}",
+ this.name, input, this.minVal, minOverWindow);
+ this.maxVal = maxOverWindow;
+ setEncoderParams();
}
}
}
From edb81ae8b073e7e9a5a47b60401cf36f911dabae Mon Sep 17 00:00:00 2001
From: David Ray
Date: Wed, 4 Feb 2015 14:43:49 -0600
Subject: [PATCH 12/56] add joda time library
---
libs/joda-time-2.5.jar | Bin 0 -> 588001 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 libs/joda-time-2.5.jar
diff --git a/libs/joda-time-2.5.jar b/libs/joda-time-2.5.jar
new file mode 100644
index 0000000000000000000000000000000000000000..4fe151d0fa6c5840cfd98e2488629456d99eadc8
GIT binary patch
literal 588001
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