| 659 | |
| 660 | template <typename TApproxDefs> |
| 661 | void MapSetApproxes( |
| 662 | const IDerCalcer& error, |
| 663 | const std::variant<TSplitTree, TNonSymmetricTreeStructure>& splitTree, |
| 664 | TVector<TVector<double>>* averageLeafValues, |
| 665 | TVector<double>* sumLeafWeights, |
| 666 | TLearnContext* ctx) { |
| 667 | |
| 668 | using namespace NCatboostDistributed; |
| 669 | using TSum = typename TApproxDefs::TSumType; |
| 670 | using TPairwiseBuckets = typename TApproxDefs::TPairwiseBuckets; |
| 671 | using TBucketUpdater = typename TApproxDefs::TBucketUpdater; |
| 672 | using TDeltaUpdater = typename TApproxDefs::TDeltaUpdater; |
| 673 | |
| 674 | Y_ASSERT(ctx->Params.SystemOptions->IsMaster()); |
| 675 | const int workerCount = TMasterEnvironment::GetRef().RootEnvironment->GetSlaveCount(); |
| 676 | ApplyMapper<TCalcApproxStarter>(workerCount, TMasterEnvironment::GetRef().SharedTrainData, splitTree); |
| 677 | const int gradientIterations = ctx->Params.ObliviousTreeOptions->LeavesEstimationIterations; |
| 678 | const int approxDimension = ctx->LearnProgress->ApproxDimension; |
| 679 | const int leafCount = GetLeafCount(splitTree); |
| 680 | const auto lossFunction = ctx->Params.LossFunctionDescription; |
| 681 | const auto estimationMethod = ctx->Params.ObliviousTreeOptions->LeavesEstimationMethod; |
| 682 | |
| 683 | if (estimationMethod == ELeavesEstimation::Exact) { |
| 684 | UpdateLeavesExact<TDeltaUpdater>(error, leafCount, averageLeafValues, ctx); |
| 685 | } else { |
| 686 | TVector<TSum> buckets(leafCount, TSum(approxDimension, error.GetHessianType())); |
| 687 | const auto leafUpdaterFunc = [&] ( |
| 688 | bool recalcLeafWeights, |
| 689 | const TVector<TVector<double>>& /*approxesPlaceholder*/, |
| 690 | TVector<TVector<double>>* leafValues |
| 691 | ) { |
| 692 | for (auto &bucket : buckets) { |
| 693 | bucket.SetZeroDers(); |
| 694 | } |
| 695 | TPairwiseBuckets pairwiseBuckets; |
| 696 | TApproxDefs::SetPairwiseBucketsSize(leafCount, &pairwiseBuckets); |
| 697 | const auto bucketsFromAllWorkers = ApplyMapper<TBucketUpdater>(workerCount, TMasterEnvironment::GetRef().SharedTrainData); |
| 698 | // reduce across workers |
| 699 | for (const auto& workerBuckets : bucketsFromAllWorkers) { |
| 700 | const auto& singleBuckets = workerBuckets.first; |
| 701 | if (singleBuckets.empty()) { |
| 702 | continue; |
| 703 | } |
| 704 | for (int leafIdx = 0; leafIdx < leafCount; ++leafIdx) { |
| 705 | if (estimationMethod == ELeavesEstimation::Gradient) { |
| 706 | buckets[leafIdx].AddDerWeight( |
| 707 | singleBuckets[leafIdx].SumDer, |
| 708 | singleBuckets[leafIdx].SumWeights, |
| 709 | recalcLeafWeights); |
| 710 | } else { |
| 711 | Y_ASSERT(estimationMethod == ELeavesEstimation::Newton); |
| 712 | buckets[leafIdx].AddDerDer2(singleBuckets[leafIdx].SumDer, singleBuckets[leafIdx].SumDer2); |
| 713 | } |
| 714 | } |
| 715 | TApproxDefs::AddPairwiseBuckets(workerBuckets.second, &pairwiseBuckets); |
| 716 | } |
| 717 | *leafValues = TApproxDefs::CalcLeafValues(buckets, pairwiseBuckets, *ctx); |
| 718 | }; |
nothing calls this directly
no test coverage detected