PredictionValueChange for multiclass
@@ -17,7 +17,7 @@ struct TMxTree {
};
struct TNodeInfo {
- double Value = 0;
+ TVector<double> Values; // [dimension]
double Count = 0;
};
@@ -127,6 +127,7 @@ TVector<double> CalcEffect(
const auto& binFeatures = model.ObliviousTrees->GetBinFeatures();
const auto& leafValues = model.ObliviousTrees->LeafValues;
+ const int approxDimension = model.ObliviousTrees->ApproxDimension;
const int featureCount = featureToIdx.size();
TVector<double> res(featureCount, 0);
@@ -143,8 +144,11 @@ TVector<double> CalcEffect(
if (node.LeftSubtreeDiff == 0 && node.RightSubtreeDiff == 0) { // node is terminal
const int leafValueIndex = model.ObliviousTrees->NonSymmetricNodeIdToLeafId[nodeIdx];
+ TVector<double> values(
+ leafValues.begin() + leafValueIndex,
+ leafValues.begin() + leafValueIndex + approxDimension);
nodeIdxToInfo[nodeIdx] = TNodeInfo{
- leafValues[leafValueIndex],
+ values,
weightedDocCountInLeaf[0][leafValueIndex]
};
} else {
@@ -175,18 +179,22 @@ TVector<double> CalcEffect(
TNodeInfo rightInfo = nodeIdxToInfo[rightNodeIdx];
nodeIdxToInfo.erase(rightNodeIdx);
- const double val1 = leftInfo.Value;
- const double val2 = rightInfo.Value;
-
const double count1 = leftInfo.Count;
const double count2 = rightInfo.Count;
const double sumCount = count1 + count2;
+ TVector<double> parentAvrg;
+ for(int dimension = 0; dimension < approxDimension; dimension++) {
+ const double val1 = leftInfo.Values[dimension];
+ const double val2 = rightInfo.Values[dimension];
+
const double avrg = (val1 * count1 + val2 * count2) / (sumCount ? sumCount : 1);
const double dif = Sqr(val1 - avrg) * count1 + Sqr(val2 - avrg) * count2;
- res[featureIdx] += dif;
- nodeIdxToInfo[parentNodeIdx] = TNodeInfo{avrg, sumCount};
+ res[featureIdx] += dif;
+ parentAvrg.push_back(avrg);
+ }
+ nodeIdxToInfo[parentNodeIdx] = TNodeInfo{parentAvrg, sumCount};
}
}
ConvertToPercents(res);
