| 226 | } |
| 227 | |
| 228 | TMetricHolder TCrossEntropyMetric::EvalSingleThread( |
| 229 | TConstArrayRef<TConstArrayRef<double>> approxRef, |
| 230 | TConstArrayRef<TConstArrayRef<double>> approxDeltaRef, |
| 231 | bool isExpApprox, |
| 232 | TConstArrayRef<float> target, |
| 233 | TConstArrayRef<float> weight, |
| 234 | TConstArrayRef<TQueryInfo> /*queriesInfo*/, |
| 235 | int begin, |
| 236 | int end |
| 237 | ) const { |
| 238 | // p * log(1/(1+exp(-f))) + (1-p) * log(1 - 1/(1+exp(-f))) = |
| 239 | // p * log(exp(f) / (exp(f) + 1)) + (1-p) * log(exp(-f)/(1+exp(-f))) = |
| 240 | // p * log(exp(f) / (exp(f) + 1)) + (1-p) * log(1/(exp(f) + 1)) = |
| 241 | // p * (log(val) - log(val + 1)) + (1-p) * (-log(val + 1)) = |
| 242 | // p*log(val) - p*log(val+1) - log(val+1) + p*log(val+1) = |
| 243 | // p*log(val) - log(val+1) |
| 244 | |
| 245 | CB_ENSURE(approxRef.size() == 1, "Metric logloss supports only single-dimensional data"); |
| 246 | |
| 247 | const auto impl = [=] (auto isExpApprox, auto hasDelta, auto hasWeight, auto isLogloss) { |
| 248 | float targetBorder = TargetBorder; |
| 249 | TConstArrayRef<double> approx = approxRef[0]; |
| 250 | TConstArrayRef<double> approxDelta = GetRowRef(approxDeltaRef, /*rowIdx*/0); |
| 251 | int tailBegin; |
| 252 | auto holder = NMixedSimdOps::EvalCrossEntropyVectorized( |
| 253 | isExpApprox, |
| 254 | hasDelta, |
| 255 | hasWeight, |
| 256 | isLogloss, |
| 257 | approx, |
| 258 | approxDelta, |
| 259 | target, |
| 260 | weight, |
| 261 | targetBorder, |
| 262 | begin, |
| 263 | end, |
| 264 | &tailBegin); |
| 265 | for (int i = tailBegin; i < end; ++i) { |
| 266 | const float w = hasWeight ? weight[i] : 1; |
| 267 | const float prob = isLogloss ? target[i] > targetBorder : target[i]; |
| 268 | if (isExpApprox) { |
| 269 | double expApprox = approx[i]; |
| 270 | double nonExpApprox = FastLogf(expApprox); |
| 271 | if (hasDelta) { |
| 272 | expApprox *= approxDelta[i]; |
| 273 | nonExpApprox += FastLogf(approxDelta[i]); |
| 274 | } |
| 275 | holder.Stats[0] += w * (IsFinite(expApprox) ? FastLogf(1 + expApprox) - prob * nonExpApprox : (1 - prob) * nonExpApprox); |
| 276 | } else { |
| 277 | double nonExpApprox = approx[i]; |
| 278 | if (hasDelta) { |
| 279 | nonExpApprox += approxDelta[i]; |
| 280 | } |
| 281 | const double expApprox = exp(nonExpApprox); |
| 282 | holder.Stats[0] += w * (IsFinite(expApprox) ? log(1 + expApprox) - prob * nonExpApprox : (1 - prob) * nonExpApprox); |
| 283 | } |
| 284 | holder.Stats[1] += w; |
| 285 | } |
nothing calls this directly
no test coverage detected