| 171 | } |
| 172 | |
| 173 | static void InitializeAndCheckMetricData( |
| 174 | const TTrainModelInternalOptions& internalOptions, |
| 175 | const TTrainingDataProviders& data, |
| 176 | const TLearnContext& ctx, |
| 177 | TMetricsData* metricsData) { |
| 178 | |
| 179 | const int approxDimension = ctx.LearnProgress->ApproxDimension; |
| 180 | auto& metrics = metricsData->Metrics; |
| 181 | metrics = CreateMetrics( |
| 182 | ctx.Params.MetricOptions, |
| 183 | ctx.EvalMetricDescriptor, |
| 184 | approxDimension, |
| 185 | ctx.GetHasWeights() |
| 186 | ); |
| 187 | CheckMetrics(metrics, ctx.Params.LossFunctionDescription.Get().GetLossFunction()); |
| 188 | |
| 189 | CB_ENSURE(!metrics.empty(), "Eval metric is not defined"); |
| 190 | |
| 191 | const bool lastTestDatasetHasTargetData = (data.Test.size() > 0) && data.Test.back()->MetaInfo.TargetCount > 0; |
| 192 | |
| 193 | const bool hasTest = data.GetTestSampleCount() > 0; |
| 194 | if (hasTest && metrics[0]->NeedTarget() && !lastTestDatasetHasTargetData) { |
| 195 | CATBOOST_WARNING_LOG << "Warning: Eval metric " << metrics[0]->GetDescription() << |
| 196 | " needs Target data, but test dataset does not have it so it won't be calculated" << Endl; |
| 197 | } |
| 198 | const bool canCalcEvalMetric = hasTest && (!metrics[0]->NeedTarget() || lastTestDatasetHasTargetData); |
| 199 | |
| 200 | if (canCalcEvalMetric) { |
| 201 | EMetricBestValue bestValueType = {}; |
| 202 | float bestPossibleValue = 0; |
| 203 | |
| 204 | metrics.front()->GetBestValue(&bestValueType, &bestPossibleValue); |
| 205 | metricsData->ErrorTracker = BuildErrorTracker(bestValueType, bestPossibleValue, hasTest, ctx); |
| 206 | metricsData->BestModelMinTreesTracker = BuildErrorTracker(bestValueType, bestPossibleValue, hasTest, ctx); |
| 207 | } |
| 208 | |
| 209 | auto& errorTracker = metricsData->ErrorTracker; |
| 210 | metricsData->CalcEvalMetricOnEveryIteration |
| 211 | = canCalcEvalMetric && (internalOptions.ForceCalcEvalMetricOnEveryIteration || errorTracker->IsActive()); |
| 212 | |
| 213 | if (ctx.OutputOptions.GetMetricPeriod() > 1 && errorTracker && errorTracker->IsActive() && hasTest) { |
| 214 | CATBOOST_WARNING_LOG << "Warning: Overfitting detector is active, thus evaluation metric is " << |
| 215 | "calculated on every iteration. 'metric_period' is ignored for evaluation metric." << Endl; |
| 216 | } |
| 217 | |
| 218 | // Use only (last_test, first_metric) for the best iteration and overfitting detection |
| 219 | // In case of changing the order it should be changed in GPU mode also. |
| 220 | metricsData->ErrorTrackerMetricIdx = 0; |
| 221 | |
| 222 | if (internalOptions.OffsetMetricPeriodByInitModelSize) { |
| 223 | metricsData->MetricPeriodOffset = ctx.LearnProgress->GetInitModelTreesSize(); |
| 224 | } else { |
| 225 | metricsData->MetricPeriodOffset = Nothing(); |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | namespace { |
| 230 | struct TLoggingData { |
no test coverage detected