public void AdjustTreeOutputs(IChannel ch, RegressionTree tree, DocumentPartitioning partitioning, ScoreTracker trainingScores) { double shrinkage = LearningRate * Shrinkage; var scores = trainingScores.Scores; var weights = trainingScores.Dataset.SampleWeights; // Following equation 18, and line 2c of algorithm 1 in the source paper. for (int l = 0; l < tree.NumLeaves; ++l) { Double num = 0; Double denom = 0; if (_index1 == 0) { // The index == 1 Poisson case. foreach (int i in partitioning.DocumentsInLeaf(l)) { var s = scores[i]; var w = weights == null ? 1 : weights[i]; num += w * _labels[i]; denom += w * Math.Exp(s); } } else { // The index in (1,2] case. foreach (int i in partitioning.DocumentsInLeaf(l)) { var s = scores[i]; var w = weights == null ? 1 : weights[i]; num += w * _labels[i] * Math.Exp(_index1 * s); denom += w * Math.Exp(_index2 * s); } } var step = shrinkage * (Math.Log(num) - Math.Log(denom)); if (num == 0 && denom == 0) { step = 0; } // If we do not clamp, it is entirely possible for num to be 0 (with 0 labels), which // means that we will have negative infinities in the leaf nodes. This has a number of // bad negative effects we'd prefer to avoid. Nonetheless, we do give up a substantial // amount of "gain" for those examples. if (step < -_maxClamp) { step = -_maxClamp; } else if (step > _maxClamp) { step = _maxClamp; } tree.SetOutput(l, step); } }