public void TestSingleValueWithMultipleIteration() { var classifier = new CLAClassifier <double>(); ClassificationExperiment <Double> retVal = null; for (int recordNum = 0; recordNum < 10; recordNum++) { retVal = compute(classifier, recordNum, new int[] { 1, 5 }, 0, 10); } checkValue(retVal, 0, 10.0, 1); }
public void TestWithDiffertBucketIndexWithMultipleIteration() { var classifier = new CLAClassifier <double>(); ClassificationExperiment <Double> retVal = null; for (int recordNum = 0; recordNum < 20; recordNum++) { int bucketIndex = recordNum % 2; retVal = compute(classifier, recordNum, new int[] { 1, 5 }, bucketIndex, 10); } checkValue(retVal, 0, 10.0, 0.5); }
public void TestComputeWithMissingValue() { var classifier = new CLAClassifier <double>(new List <int> { 1 }, 0.1, 0.1); Dictionary <string, object> classification = new Dictionary <string, object>(); classification.Add("bucketIdx", null); classification.Add("actValue", null); ClassificationExperiment <double> result = classifier.Compute(0, classification, new int[] { 1, 5, 9 }, true, true); Assert.AreEqual(1, result.getActualValueCount()); Assert.AreEqual(-1, result.getActualValue(0)); }
public void TestCompute() { var classifier = new CLAClassifier <double>(new List <int> { 1 }, 0.1, 0.1); Dictionary <string, object> classification = new Dictionary <string, object>(); classification.Add("bucketIdx", 4); classification.Add("actValue", 34.7); ClassificationExperiment <double> result = classifier.Compute(0, classification, new int[] { 1, 5, 9 }, true, true); //it is first time and so it wont learn and that's why value count will be one Assert.AreEqual(1, result.getActualValueCount()); Assert.AreEqual(34.7, result.getActualValue(0), 0.01); }
public void testComputeComplex() { var classifier = new CLAClassifier <double>(new List <int> { 1 }, 0.1, 0.1); int recordNum = 0; Dictionary <string, object> classification = new Dictionary <string, object>(); classification.Add("bucketIdx", 4); classification.Add("actValue", 34.7); ClassificationExperiment <double> result = classifier.Compute(recordNum, classification, new int[] { 1, 5, 9 }, true, true); recordNum += 1; classification["bucketIdx"] = 5; classification["actValue"] = 41.7; result = classifier.Compute(recordNum, classification, new int[] { 0, 6, 9, 11 }, true, true); recordNum += 1; classification["bucketIdx"] = 5; classification["actValue"] = 44.9; result = classifier.Compute(recordNum, classification, new int[] { 6, 9 }, true, true); recordNum += 1; classification["bucketIdx"] = 4; classification["actValue"] = 42.9; result = classifier.Compute(recordNum, classification, new int[] { 1, 5, 9 }, true, true); recordNum += 1; classification["bucketIdx"] = 4; classification["actValue"] = 34.7; result = classifier.Compute(recordNum, classification, new int[] { 1, 5, 9 }, true, true); Assert.AreEqual(35.520000457763672, result.getActualValue(4), 0.00001); Assert.AreEqual(42.020000457763672, result.getActualValue(5), 0.00001); Assert.AreEqual(6, result.getStatCount(1)); Assert.AreEqual(0.0, result.getStat(1, 0), 0.00001); Assert.AreEqual(0.0, result.getStat(1, 1), 0.00001); Assert.AreEqual(0.0, result.getStat(1, 2), 0.00001); Assert.AreEqual(0.0, result.getStat(1, 3), 0.00001); Assert.AreEqual(0.12300123, result.getStat(1, 4), 0.00001); Assert.AreEqual(0.87699877, result.getStat(1, 5), 0.00001); }
public void TestSingleValue() { var classifier = new CLAClassifier <double>(new List <int> { 0 }, 0.001, 0.3); ClassificationExperiment <double> retVal = null; for (int recordNum = 0; recordNum < 10; recordNum++) { retVal = compute(classifier, recordNum, new int[] { 1, 5 }, 0, 10); } Assert.AreEqual(10.0, retVal.getActualValue(0), .00001); Assert.AreEqual(1.0, retVal.getStat(0, 0), .00001); }
public void TestComputeWithTwoIteration() { var classifier = new CLAClassifier <double>(new List <int> { 1 }, 0.1, 0.1); Dictionary <string, object> classification = new Dictionary <string, object>(); classification.Add("bucketIdx", 4); classification.Add("actValue", 34.7); classifier.Compute(0, classification, new int[] { 1, 5, 9 }, true, true); //It is second iteration and so it will learn and that's why value count will be more than one ClassificationExperiment <double> result = classifier.Compute(1, classification, new int[] { 1, 5, 9 }, true, true); Assert.AreEqual(5, result.getActualValueCount()); Assert.AreEqual(34.7, result.getActualValue(4), 0.01); }
public void testOverlapPattern() { var classifier = new CLAClassifier <double>(); ClassificationExperiment <Double> result = compute(classifier, 0, new int[] { 1, 5 }, 9, 9); result = compute(classifier, 1, new int[] { 1, 5 }, 9, 9); result = compute(classifier, 1, new int[] { 1, 5 }, 9, 9); result = compute(classifier, 2, new int[] { 3, 5 }, 2, 2); // Since overlap - should be previous with 100% checkValue(result, 9, 9.0, 1.0); result = compute(classifier, 3, new int[] { 3, 5 }, 2, 2); // Second example: now new value should be more probable than old Assert.IsTrue(result.getStat(1, 2) > result.getStat(1, 9)); }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(ClassificationExperiment obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
/// <summary> /// Method computes the result after the data is provided by the temporal memory and encoder /// </summary> /// <param name="recordNum">Record number of this input pattern. /// Record numbers should normally increase sequentially by 1 each time unless there are missing records in the dataset. /// Knowing this information insures that we don't get confused by missing records.</param> /// <param name="classification">{@link Map} of the classification information: /// bucketIdx: index of the encoder bucket</param> /// <param name="patternNZ">list of the active indices from the output below</param> /// <param name="learn">if true, learn this sample</param> /// <param name="infer">if true, perform inference</param> /// <returns>ClassificationExperiment Object</returns> public ClassificationExperiment <T> Compute(int recordNum, Dictionary <string, object> classification, int[] patternNZ, bool learn, bool infer) { if (classification == null) { throw new ArgumentNullException(nameof(classification)); } if (patternNZ == null) { throw new ArgumentNullException(nameof(patternNZ)); } ClassificationExperiment <T> retVal = new ClassificationExperiment <T>(); List <T> actualValues = (List <T>) this.actualValues; // Save the offset between recordNum and learnIteration if this is the first // compute if (recordNumMinusLearnIteration == -1) { recordNumMinusLearnIteration = recordNum - learnIteration; } // Update the learn iteration learnIteration = recordNum - recordNumMinusLearnIteration; if (patternNZHistory.Any(x => x.Item1 == learnIteration)) { patternNZHistory.Add(Tuple.Create(learnIteration, patternNZ)); } //------------------------------------------------------------- // For each active bit in the activationPattern, get the classification // votes // // Return value dict. For buckets which we don't have an actual value // for yet, just plug in any valid actual value. It doesn't matter what // we use because that bucket won't have non-zero likelihood anyways. if (infer) { // If doing 0-step prediction, we shouldn't use any knowledge // of the classification input during inference. object defaultValue = default(T); if (steps[0] == 0) { defaultValue = 0; } else { defaultValue = classification["actValue"]; if (defaultValue == null) { if (IsNumericType(default(T))) { defaultValue = ConversionExtensions.Convert <T>(-1); } } } T[] actValues = new T[this.actualValues.Count]; for (int i = 0; i < actualValues.Count; i++) { if (IsNumericType(default(T))) { actValues[i] = (T)(actualValues[i].Equals(ConversionExtensions.Convert <T>(-1)) ? ConversionExtensions.Convert <T>(defaultValue) : actualValues[i]); } else { actValues[i] = (T)(actualValues[i].Equals(default(T)) ? defaultValue : actualValues[i]); } } retVal.setActualValues(actValues); // For each n-step prediction... foreach (int nSteps in steps) { // Accumulate bucket index votes and actValues into these arrays double[] sumVotes = new double[maxBucketIdx + 1]; double[] bitVotes = new double[maxBucketIdx + 1]; foreach (var bit in patternNZ) { var key = Tuple.Create(bit, nSteps); BitHistory history = null; activeBitHistory.TryGetValue(key, out history); if (history == null) { continue; } history.Infer(bitVotes); sumVotes = ArrayUtils.AddOffset(sumVotes, bitVotes); } // Return the votes for each bucket, normalized double total = sumVotes.Sum(); if (total > 0) { sumVotes = ArrayUtils.Divide(sumVotes, total); } else { // If all buckets have zero probability then simply make all of the // buckets equally likely. There is no actual prediction for this // timestep so any of the possible predictions are just as good. if (sumVotes.Length > 0) { double val = 1.0 / sumVotes.Length; for (int i = 0; i < sumVotes.Length; i++) { sumVotes[i] = val; } } } retVal.setStats(nSteps, sumVotes); } } // ------------------------------------------------------------------------ // Learning: // For each active bit in the activationPattern, store the classification // info. If the bucketIdx is None, we can't learn. This can happen when the // field is missing in a specific record. if (learn && classification["bucketIdx"] != null) { // Get classification info int bucketIdx = (int)classification["bucketIdx"]; object actValue = null; if (classification["actValue"] == null) { if (IsNumericType(default(T))) { actValue = ConversionExtensions.Convert <T>(-1); } } else { actValue = ConversionExtensions.Convert <T>(classification["actValue"]); } // Update maxBucketIndex maxBucketIdx = (int)Math.Max(maxBucketIdx, bucketIdx); // Update rolling average of actual values if it's a scalar. If it's // not, it must be a category, in which case each bucket only ever // sees one category so we don't need a running average. while (maxBucketIdx > actualValues.Count - 1) { actualValues.Add(IsNumericType(default(T)) ? ConversionExtensions.Convert <T>(-1) : default(T)); } if (actualValues[bucketIdx].Equals(IsNumericType(default(T)) ? ConversionExtensions.Convert <T>(-1) : default(T))) { actualValues[bucketIdx] = (T)actValue; } else { if (IsNumericType(actValue)) { double val = ((1.0 - actValueAlpha) * Convert.ToDouble(actualValues[bucketIdx], enusFormatProvider)) + (actValueAlpha * (Convert.ToDouble(actValue, enusFormatProvider))); actualValues[bucketIdx] = ConversionExtensions.Convert <T>(val); } else { actualValues[bucketIdx] = (T)actValue; } } // Train each pattern that we have in our history that aligns with the // steps we have in steps int nSteps = -1; int iteration = 0; int[] learnPatternNZ = null; foreach (var n in steps) { nSteps = n; // Do we have the pattern that should be assigned to this classification // in our pattern history? If not, skip it bool found = false; foreach (var t in patternNZHistory) { iteration = t.Item1; learnPatternNZ = t.Item2; if (iteration == learnIteration - nSteps) { found = true; break; } iteration++; } if (!found) { continue; } // Store classification info for each active bit from the pattern // that we got nSteps time steps ago. foreach (int bit in learnPatternNZ) { // Get the history structure for this bit and step var key = Tuple.Create(bit, nSteps); BitHistory history = null; activeBitHistory.TryGetValue(key, out history); if (history == null) { history = new BitHistory(alpha); activeBitHistory.Add(key, history); } history.store(learnIteration, bucketIdx); } } } return(retVal); }
/// <summary> /// general method for checking expected probability and value /// </summary> /// <typeparam name="T"></typeparam> /// <param name="retVal">Result of compute method</param> /// <param name="index">value of particular bucket index</param> /// <param name="value">expected value</param> /// <param name="probability">expected probability</param> public void checkValue <T>(ClassificationExperiment <T> retVal, int index, Object value, double probability) { Assert.AreEqual(retVal.getActualValue(index), value); Assert.AreEqual(probability, retVal.getStat(1, index), 0.01); }