private IDictionary <string, float[]> GetPredictions(ILearner <TSample> learner) { var predictions = new ConcurrentDictionary <string, float[]>(); var sampleCount = _positiveSamples.Length + _negativeSamples.Length; var samplesProcessed = 0; foreach (var config in learner.AllPossibleConfigurations()) { if (config.IndexOfAny(new[] { '>', '?', ':', '\r', '\n' }) > 0) { throw new FormatException("Learner configuration cannot contain any of '>', '?', ':', or a line break."); } predictions.TryAdd(config, new float[sampleCount]); } Parallel.ForEach(_positiveSamples.Concat(_negativeSamples), s => { var localLearner = learner; localLearner.SetSample(s.Sample); foreach (var config in learner.AllPossibleConfigurations()) { localLearner = localLearner.WithConfiguration(config); predictions[config][s.Index] = learner.Classify(); } if (_cancellation.IsCancellationRequested) { return; } if (_progress != null) { if (Monitor.TryEnter(_progress)) { try { samplesProcessed++; _progress.Report(Tuple.Create("Running learner \"" + learner.UniqueId + "\"", samplesProcessed * 100 / sampleCount)); } finally { Monitor.Exit(_progress); } } } }); return(predictions); }
private LayerHolder OptimizeCoefficients(ILearner <TSample> learner, float[] outputs) { var positiveWeights = _positiveSamples.Select(s => s.Weight).ToArray(); var negativeWeights = _negativeSamples.Select(s => s.Weight).ToArray(); var positiveCorrect = new bool[_positiveSamples.Length]; var negativeCorrect = new bool[_negativeSamples.Length]; #if DEBUG var perfect = true; foreach (var s in _positiveSamples.Concat(_negativeSamples)) { learner.SetSample(s.Sample); // ReSharper disable CompareOfFloatsByEqualityOperator if (learner.Classify() != outputs[s.Index]) { throw new Exception(); } perfect &= s.Actual == outputs[s.Index]; // ReSharper restore CompareOfFloatsByEqualityOperator } #endif //Find best bias point, adding one sample at a time to the predicted target set and updating the cost. //Note that -cost is the cost of the inverse of the current hypothesis i.e. "all samples are in the target". var bestThres = float.PositiveInfinity; var bestCost = float.PositiveInfinity; var bestPos = float.PositiveInfinity; var bestNeg = float.NegativeInfinity; var threshold = float.NegativeInfinity; while (threshold < float.PositiveInfinity) { { var i = 0; foreach (var s in _positiveSamples) { positiveCorrect[i++] = outputs[s.Index] > threshold; } i = 0; foreach (var s in _negativeSamples) { negativeCorrect[i++] = outputs[s.Index] <= threshold; } } double sumWeightsPosCorrect = 0; double sumWeightsPosIncorrect = 0; double sumWeightsNegCorrect = 0; double sumWeightsNegIncorrect = 0; SumWeights(positiveWeights, positiveCorrect, ref sumWeightsPosCorrect, ref sumWeightsPosIncorrect); SumWeights(negativeWeights, negativeCorrect, ref sumWeightsNegCorrect, ref sumWeightsNegIncorrect); var coefPos = (float)Math.Log(sumWeightsPosCorrect / sumWeightsNegIncorrect) / 2; var coefNeg = (float)Math.Log(sumWeightsNegCorrect / sumWeightsPosIncorrect) / -2; coefPos = float.IsNaN(coefPos) ? 0 : coefPos; coefNeg = float.IsNaN(coefNeg) ? 0 : coefNeg; var loss = (float)(sumWeightsPosCorrect * Math.Exp(-coefPos) + sumWeightsNegIncorrect * Math.Exp(coefPos)); loss += (float)(sumWeightsNegCorrect * Math.Exp(coefNeg) + sumWeightsPosIncorrect * Math.Exp(-coefNeg)); #if DEBUG if (!ApproxEqual((float)(sumWeightsNegCorrect + sumWeightsNegIncorrect + sumWeightsPosCorrect + sumWeightsPosIncorrect), 1)) { // ReSharper disable once EmptyStatement ; } if (!perfect && (float.IsInfinity(coefNeg) || float.IsInfinity(coefPos))) { throw new Exception("Unexpected coefficients"); } //float calcLoss = 0; //calcLoss += getLoss(coefPos, coefNeg, positiveSamples.Select(s => s.confidence).Zip(positiveCorrect, (s, c) => new Tuple<float, bool>(s, c)), 1f); //calcLoss += getLoss(coefNeg, coefPos, negativeSamples.Select(s => s.confidence).Zip(negativeCorrect, (s, c) => new Tuple<float, bool>(s, c)), -1f); #endif if (!float.IsNaN(loss) && loss < bestCost) { bestCost = loss; bestPos = coefPos; bestNeg = coefNeg; bestThres = threshold; } var next = outputs.Aggregate(float.PositiveInfinity, (min, i) => (i > threshold && i < min) ? i : min); threshold = next; } return(new LayerHolder(bestCost, new Layer <TSample>(learner, bestPos, bestNeg, bestThres), outputs)); }
internal float Classify(TSample s) { _learner.SetSample(s); return(_learner.Classify() > Threshold ? CoefPos : CoefNeg); }