| 1241 | } |
| 1242 | |
| 1243 | void 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, |
no test coverage detected