MCPcopy Create free account
hub / github.com/catboost/catboost / CalcShapValuesInternalForFeature

Function CalcShapValuesInternalForFeature

catboost/libs/fstr/shap_values.cpp:1243–1385  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1241}
1242
1243void CalcShapValuesInternalForFeature(
1244 const TShapPreparedTrees& preparedTrees,
1245 const TFullModel& model,
1246 int /*logPeriod*/,
1247 ui32 start,
1248 ui32 end,
1249 ui32 featuresCount,
1250 const NCB::TObjectsDataProvider& objectsData,
1251 TVector<TVector<TVector<double>>>* shapValues, // [docIdx][featureIdx][dim]
1252 NPar::ILocalExecutor* localExecutor,
1253 ECalcTypeShapValues calcType
1254) {
1255
1256 CB_ENSURE(start <= end && end <= objectsData.GetObjectCount());
1257 const TModelTrees& forest = *model.ModelTrees;
1258 shapValues->clear();
1259 const ui32 documentCount = end - start;
1260 shapValues->resize(documentCount);
1261
1262 THolder<IFeaturesBlockIterator> featuresBlockIterator
1263 = CreateFeaturesBlockIterator(model, objectsData, start, end);
1264
1265 const ui32 documentBlockSize = NModelEvaluation::FORMULA_EVALUATION_BLOCK_SIZE;
1266 TVector<NModelEvaluation::TCalcerIndexType> indices(documentBlockSize * forest.GetTreeCount());
1267
1268 for (ui32 startIdx = 0; startIdx < documentCount; startIdx += documentBlockSize) {
1269 NPar::ILocalExecutor::TExecRangeParams blockParams(startIdx, startIdx + Min(documentBlockSize, documentCount - startIdx));
1270 featuresBlockIterator->NextBlock(blockParams.LastId - blockParams.FirstId);
1271 auto binarizedFeaturesForBlock = MakeQuantizedFeaturesForEvaluator(model, *featuresBlockIterator, blockParams.FirstId, blockParams.LastId);
1272
1273 model.GetCurrentEvaluator()->CalcLeafIndexes(
1274 binarizedFeaturesForBlock.Get(),
1275 0, forest.GetTreeCount(),
1276 MakeArrayRef(indices.data(), binarizedFeaturesForBlock->GetObjectsCount() * forest.GetTreeCount())
1277 );
1278
1279 localExecutor->ExecRange([&](ui32 documentIdx) {
1280 TVector<TVector<double>> &docShapValues = (*shapValues)[documentIdx];
1281 docShapValues.assign(featuresCount, TVector<double>(forest.GetDimensionsCount() + 1, 0.0));
1282 auto docIndices = MakeArrayRef(indices.data() + forest.GetTreeCount() * (documentIdx - startIdx), forest.GetTreeCount());
1283 for (size_t treeIdx = 0; treeIdx < forest.GetTreeCount(); ++treeIdx) {
1284 if (preparedTrees.CalcShapValuesByLeafForAllTrees && model.IsOblivious()) {
1285 for (const TShapValue& shapValue : preparedTrees.ShapValuesByLeafForAllTrees[treeIdx][docIndices[treeIdx]]) {
1286 for (int dimension = 0; dimension < (int)forest.GetDimensionsCount(); ++dimension) {
1287 docShapValues[shapValue.Feature][dimension] += shapValue.Value[dimension];
1288 }
1289 }
1290 } else {
1291 TVector<TShapValue> shapValuesByLeaf;
1292 switch (calcType) {
1293 case ECalcTypeShapValues::Approximate:
1294 if (model.IsOblivious()) {
1295 CalcObliviousApproximateShapValuesForLeaf(
1296 forest,
1297 preparedTrees.BinFeatureCombinationClass,
1298 preparedTrees.CombinationClassFeatures,
1299 docIndices[treeIdx],
1300 treeIdx,

Tested by

no test coverage detected