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

Function CalcShapValuesForDocumentMulti

catboost/libs/fstr/shap_values.cpp:859–1056  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

857}
858
859void CalcShapValuesForDocumentMulti(
860 const TFullModel& model,
861 const TShapPreparedTrees& preparedTrees,
862 const NCB::NModelEvaluation::IQuantizedData* binarizedFeaturesForBlock,
863 const TMaybe<TFixedFeatureParams>& fixedFeatureParams,
864 int featuresCount,
865 TConstArrayRef<NModelEvaluation::TCalcerIndexType> docIndices,
866 size_t documentIdxInBlock,
867 TVector<TVector<double>>* shapValues,
868 ECalcTypeShapValues calcType,
869 size_t documentIdx
870) {
871 const TString lossFunctionName = model.GetLossFunctionName();
872 TMaybe<ELossFunction> lossFunction = Nothing();
873 if (lossFunctionName) {
874 lossFunction = FromString<ELossFunction>(lossFunctionName);
875 }
876 const bool isRMSEWithUncertainty = lossFunction == ELossFunction::RMSEWithUncertainty;
877 const int approxDimension = isRMSEWithUncertainty ? 1 : model.GetDimensionsCount();
878 shapValues->assign(approxDimension, TVector<double>(featuresCount + 1, 0.0));
879 const TModelTrees& forest = *model.ModelTrees;
880 const auto& binFeatureCombinationClass = preparedTrees.BinFeatureCombinationClass;
881 const bool isIndependent = (calcType == ECalcTypeShapValues::Independent);
882 const auto& independentTreeShapParams = preparedTrees.IndependentTreeShapParams;
883 TVector<TVector<TVector<double>>> shapValuesForAllReferences;
884 if (isIndependent) {
885 const size_t referenceCount = independentTreeShapParams->ReferenceLeafIndicesForAllTrees[0].size();
886 const size_t classCount = preparedTrees.CombinationClassFeatures.size();
887 shapValuesForAllReferences.resize(referenceCount);
888 for (size_t referenceIdx = 0; referenceIdx < referenceCount; ++referenceIdx) {
889 shapValuesForAllReferences[referenceIdx].assign(approxDimension, TVector<double>(classCount + 1, 0.0));
890 }
891 }
892 const size_t treeCount = model.GetTreeCount();
893 for (size_t treeIdx = 0; treeIdx < treeCount; ++treeIdx) {
894 const size_t leafCount = (size_t(1) << forest.GetModelTreeData()->GetTreeSizes()[treeIdx]);
895 if (preparedTrees.CalcShapValuesByLeafForAllTrees && model.IsOblivious()) {
896 if (isIndependent) {
897 const auto& binFeatureCombinationClassByDepth =
898 GetBinFeatureCombinationClassByDepth(forest, binFeatureCombinationClass, treeIdx);
899 Y_ASSERT(docIndices[treeIdx] < independentTreeShapParams->ShapValueByDepthBetweenLeavesForAllTrees[treeIdx].size());
900 AddValuesToShapValuesByAllReferences(
901 independentTreeShapParams->ShapValueByDepthBetweenLeavesForAllTrees[treeIdx][docIndices[treeIdx]],
902 independentTreeShapParams->ReferenceLeafIndicesForAllTrees[treeIdx],
903 binFeatureCombinationClassByDepth,
904 &shapValuesForAllReferences
905 );
906 } else {
907 Y_ASSERT(docIndices[treeIdx] < preparedTrees.ShapValuesByLeafForAllTrees[treeIdx].size());
908 AddValuesToShapValues(
909 preparedTrees.ShapValuesByLeafForAllTrees[treeIdx][docIndices[treeIdx]],
910 approxDimension,
911 shapValues
912 );
913 }
914 } else {
915 TVector<TShapValue> shapValuesByLeaf;
916 TVector<TVector<TVector<double>>> shapValueByDepthBetweenLeaves;

Tested by

no test coverage detected