public static void Run() { var ex = new Example(2, new double[] { 1, 3, 2 }); // WithClass test if (ex.WithClass(5).Class != 5 || !ex.WithClass(5).Features.SequenceEqual(new double[] { 1, 3, 2 })) throw new Exception("WithClass failed"); // ZScore test var examples = new Example[] { new Example(1, new double[] { 1, 7 }), new Example(3, new double[] { 5, 5 }), new Example(1, new double[] { 3, 3 }), }.AsIArray(); IArrayView<double> means, sds; var zscored = examples.ZScored(out means, out sds); if (!means.SequenceEqual(new double[] { 3, 5 })) throw new Exception("Bad means"); if (!sds.SequenceEqual(new double[] { 2, 2 })) throw new Exception("Bad standard deviations"); foreach (int i in examples.Indices()) foreach (int j in examples[0].Features.Indices()) if (zscored[i].Features[j] != (examples[i].Features[j] - means[j]) / sds[j]) throw new Exception("Bad zscore value"); }
/// <summary> /// Classifies the example /// </summary> protected override int PredictHelper(Example example, out double confidence) { if (this.neighborhood.Count == 0) throw new Exception("Cannot make a prediction without at least 1 training example"); // find K nearest neighbors var kNearest = this.neighborhood .Select(e => new { Class = e.Class, Distance = e.Features.SquaredDistanceTo(example.Features) }) .OrderBy(cd => cd.Distance) .Take(this.K); // vote var voteMap = new Dictionary<int, double>(); foreach (var nearest in kNearest) { if (!voteMap.ContainsKey(nearest.Class)) voteMap[nearest.Class] = 0; voteMap[nearest.Class] += this.WeightedVoting ? (1.0 / nearest.Distance) : 1.0; } // predict double bestVote = double.NegativeInfinity; int bestClass = 0; foreach (var pair in voteMap) if (pair.Value > bestVote) { bestVote = pair.Value; bestClass = pair.Key; } confidence = bestVote / voteMap.Values.Sum(); return bestClass; }
/// <summary> /// Computes the classifier's binary prediction /// </summary> protected override int PredictBinary(Example binaryExample, out double confidence) { double innerProductSum = 0, weightedSum = this.perceptronWeights[0] * this.Kernel.Evaluate(innerProductSum); /* * Use the recurrence (v_i+1 . ex) = (v_i . ex) + y_i (x_i . ex) to * compute the remaining predictions. */ for (int i = 1; i < this.mistakes.Count; i++) { innerProductSum += this.mistakes[i].Class * this.mistakes[i].Features.InnerProduct(binaryExample.Features); weightedSum += this.perceptronWeights[i] * this.Kernel.Evaluate(innerProductSum); } // the confidence represents where we are in [-cr, cr] confidence = (Math.Abs(weightedSum) + this.confidenceRange) / (2 * this.confidenceRange); // rare corner case: just return the most common mistake if (weightedSum == 0.0) { int negCount = this.mistakes.Count(e => e.Class == this.NegativeExampleValue), posCount = this.mistakes.Count(e => e.Class == this.PositiveExampleValue); return negCount > posCount ? this.NegativeExampleValue : this.PositiveExampleValue; } return Math.Sign(weightedSum); }
/// <summary> /// Classifies the example /// </summary> protected override int PredictBinary(Example binaryExample, out double confidence) { int feature = this.Feature < binaryExample.Features.Count ? this.Feature : 0; confidence = 1.0; return ((binaryExample.Features[feature] < this.cutPoint) == this.negativesBelowCutPoint) ? this.NegativeExampleValue : this.PositiveExampleValue; }
/// <summary> /// Predicts the binary class of the binary example using the weighted vote of each weak learner /// </summary> protected override int PredictBinary(Example binaryExample, out double confidence) { confidence = 1.0; double weightedVote = 0; for (int i = 0; i < this.weakLearners.Length; i++) weightedVote += this.alphas[i] * this.weakLearners[i].Predict(binaryExample.WithFeatures(this.weakLearnerFeatures[i])); if (weightedVote == 0) return this.NegativeExampleValue; return Math.Sign(weightedVote); }
/// <summary> /// Classifies the example /// </summary> protected override int PredictBinary(Example binaryExample, out double confidence) { return this.stump.Predict(ConvertToAverageExample(binaryExample), out confidence); }
private static Example ConvertToAverageExample(Example example) { return new Example(example.Class, example.Features.Select(Math.Abs).Average().Enumerate()); }
protected override int PredictHelper(Example example, out double confidence) { return(this.classifier.Predict(example, out confidence)); }
/// <summary> /// Throws an execption is the classifier has not been trained, then calls PredictHelper. /// </summary> public int Predict(Example example, out double confidence) { if (!this.IsTrained) throw new Exception("Classifier is not yet trained!"); return this.PredictHelper(example, out confidence); }
/// <summary> /// As <code>classifier.IsPositive(classifier, example.Class)</code> /// </summary> public static bool IsPositive(this IBinaryClassifier classifier, Example example) { return classifier.IsPositive(example.Class); }
/// <summary> /// TrainMore, but with a single example /// </summary> public static void TrainMore(this IOnlineClassifier classifier, Example labeledExample) { classifier.TrainMore(labeledExample.NCopies(1)); }
private void DoTrainingStep(Example binaryExample, double weight) { // if current classifies correctly, increase the weight of // the current perceptron if (Math.Sign(this.Kernel.Evaluate(this.currentPerceptron, binaryExample.Features)) == binaryExample.Class) this.perceptronWeights[this.perceptronWeights.Count - 1] += weight; // create a new perceptron else { // save the mistake this.mistakes.Add(binaryExample); // add a new weight this.perceptronWeights.Add(weight); // Update the current perceptron: v_k+1 = v_k + y_i * x_i for (int a = 0; a < binaryExample.Features.Count; a++) this.currentPerceptron[a] += binaryExample.Class * binaryExample.Features[a]; } this.confidenceRange += weight; }
/// <summary> /// Classify as NegativeExampleValue or PositiveExampleValue /// </summary> protected abstract int PredictBinary(Example binaryExample, out double confidence);
/// <summary> /// Called by Predict /// </summary> protected abstract int PredictHelper(Example example, out double confidence);
/// <summary> /// Calls PredictBinary, and then converts the prediction back to a regular class value. /// </summary> protected override int PredictHelper(Example example, out double confidence) { int binaryClass = this.PredictBinary(example, out confidence); return(this.classMap.Where(p => p.Value == binaryClass).First().Key); }
protected override int PredictHelper(Example example, out double confidence) { return this.classifier.Predict(example, out confidence); }
/// <summary> /// Predict without the confidence parameter /// </summary> public static int Predict(this IClassifier classifier, Example example) { double ignored; return classifier.Predict(example, out ignored); }
/// <summary> /// Calls PredictBinary, and then converts the prediction back to a regular class value. /// </summary> protected override int PredictHelper(Example example, out double confidence) { int binaryClass = this.PredictBinary(example, out confidence); return this.classMap.Where(p => p.Value == binaryClass).First().Key; }
/// <summary> /// As <code>classifier.IsNegative(classifier, example.Class)</code> /// </summary> public static bool IsNegative(this IBinaryClassifier classifier, Example example) { return(classifier.IsNegative(example.Class)); }
/// <summary> /// Predict without the confidence parameter /// </summary> public static int Predict(this IClassifier classifier, Example example) { double ignored; return(classifier.Predict(example, out ignored)); }
/// <summary> /// Returns an example whose class is the binary equivalent of the given example's class and /// whose features are the same as the given example's features /// </summary> protected Example ConvertToBinaryExample(Example nonBinaryExample) { if (!this.classMap.ContainsKey(nonBinaryExample.Class)) { switch (this.classMap.Count) { case 0: this.classMap[nonBinaryExample.Class] = this.NegativeExampleValue; break; case 1: this.classMap[nonBinaryExample.Class] = this.classMap.Values.First() == this.NegativeExampleValue ? this.PositiveExampleValue : this.NegativeExampleValue; break; default: throw new Exception("Class " + nonBinaryExample.Class + " not found!"); } } return nonBinaryExample.WithClass(this.classMap[nonBinaryExample.Class]); }