| 223 | } |
| 224 | |
| 225 | static void DFS(const TFullModel& model, const THashMap<TFeature, int, TFeatureHash>& featureToIdx, ui32 nodeIdx, TVector<std::pair<int, int>>* pathPtr, THashMap<std::pair<int, int>, double>* sumInteractionsPtr) { |
| 226 | const int split = model.ModelTrees->GetModelTreeData()->GetTreeSplits()[nodeIdx]; |
| 227 | const auto& binFeatures = model.ModelTrees->GetBinFeatures(); |
| 228 | const auto& node = model.ModelTrees->GetModelTreeData()->GetNonSymmetricStepNodes()[nodeIdx]; |
| 229 | |
| 230 | const auto& feature = GetFeature(model, binFeatures[split]); |
| 231 | const int featureIdx = featureToIdx.at(feature); |
| 232 | |
| 233 | const ui32 leftNodeIdx = nodeIdx + node.LeftSubtreeDiff; |
| 234 | const ui32 rightNodeIdx = nodeIdx + node.RightSubtreeDiff; |
| 235 | |
| 236 | int sign = -1; |
| 237 | |
| 238 | if (leftNodeIdx == nodeIdx || rightNodeIdx == nodeIdx) { // terminal |
| 239 | |
| 240 | const auto leafValues = model.ModelTrees->GetModelTreeData()->GetLeafValues(); |
| 241 | const int approxDimension = model.ModelTrees->GetDimensionsCount(); |
| 242 | const int leafValueIndex = model.ModelTrees->GetModelTreeData()->GetNonSymmetricNodeIdToLeafId()[nodeIdx]; |
| 243 | double delta = std::accumulate(leafValues.begin() + leafValueIndex, |
| 244 | leafValues.begin() + leafValueIndex + approxDimension, 0.); |
| 245 | |
| 246 | for (ui32 firstIdx = 0; firstIdx < pathPtr->size(); ++firstIdx) { |
| 247 | for (ui32 secondIdx = firstIdx + 1; secondIdx < pathPtr->size(); ++secondIdx) { |
| 248 | int srcFeature1 = pathPtr->at(firstIdx).first; |
| 249 | int srcFeature2 = pathPtr->at(secondIdx).first; |
| 250 | if (srcFeature2 < srcFeature1) { |
| 251 | DoSwap(srcFeature1, srcFeature2); |
| 252 | } |
| 253 | if (srcFeature1 == srcFeature2) { |
| 254 | continue; |
| 255 | } |
| 256 | int sign = pathPtr->at(firstIdx).second * pathPtr->at(secondIdx).second; |
| 257 | (*sumInteractionsPtr)[std::make_pair(srcFeature1, srcFeature2)] += sign * delta; |
| 258 | } |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | for (const ui32& childIdx: {leftNodeIdx, rightNodeIdx}) { |
| 263 | if (childIdx != nodeIdx) { |
| 264 | pathPtr->push_back({featureIdx, sign}); |
| 265 | DFS(model, featureToIdx, childIdx, pathPtr, sumInteractionsPtr); |
| 266 | sign *= -1; |
| 267 | pathPtr->pop_back(); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | } |
| 272 | |
| 273 | TVector<TFeaturePairInteractionInfo> CalcMostInteractingFeatures(const TFullModel& model, |
| 274 | const THashMap<TFeature, int, TFeatureHash>& featureToIdx, |
no test coverage detected