| 3225 | } |
| 3226 | |
| 3227 | TMetricHolder TQuerySoftMaxMetric::EvalSingleQuery( |
| 3228 | int start, |
| 3229 | int count, |
| 3230 | TConstArrayRef<double> approxesRef, |
| 3231 | TConstArrayRef<TConstArrayRef<double>> approxDeltaRef, |
| 3232 | bool isExpApprox, |
| 3233 | TConstArrayRef<float> targets, |
| 3234 | TConstArrayRef<float> weights, |
| 3235 | TArrayRef<double> softmax |
| 3236 | ) const { |
| 3237 | Y_ASSERT(!isExpApprox); |
| 3238 | const auto impl = [=, this] (auto hasDelta, auto hasWeight) { |
| 3239 | TConstArrayRef<double> approx = approxesRef; |
| 3240 | TConstArrayRef<double> approxDelta = GetRowRef(approxDeltaRef, /*rowIdx*/0); |
| 3241 | double sumWeightedTargets = 0; |
| 3242 | for (int dim : xrange(count)) { |
| 3243 | if (targets[start + dim] > 0) { |
| 3244 | const double weight = hasWeight ? weights[start + dim] : 1; |
| 3245 | sumWeightedTargets += weight * targets[start + dim]; |
| 3246 | } |
| 3247 | } |
| 3248 | TMetricHolder error(2); |
| 3249 | if (sumWeightedTargets <= 0) { |
| 3250 | return error; |
| 3251 | } |
| 3252 | error.Stats[1] = sumWeightedTargets; |
| 3253 | |
| 3254 | for (int dim : xrange(count)) { |
| 3255 | const double delta = hasDelta ? approxDelta[start + dim] : 0; |
| 3256 | softmax[dim] = Beta * (approx[start + dim] + delta); |
| 3257 | } |
| 3258 | double maxApprox = -std::numeric_limits<double>::max(); |
| 3259 | for (int dim : xrange(count)) { |
| 3260 | if (!hasWeight || weights[start + dim] > 0) { |
| 3261 | maxApprox = Max(maxApprox, softmax[dim]); |
| 3262 | } |
| 3263 | } |
| 3264 | for (int dim : xrange(count)) { |
| 3265 | softmax[dim] -= maxApprox; |
| 3266 | } |
| 3267 | FastExpWithInfInplace(softmax.data(), count); |
| 3268 | double sumExpApprox = 0; |
| 3269 | for (int dim : xrange(count)) { |
| 3270 | const double weight = hasWeight ? weights[start + dim] : 1; |
| 3271 | if (weight > 0) { |
| 3272 | softmax[dim] *= weight; |
| 3273 | sumExpApprox += softmax[dim]; |
| 3274 | } |
| 3275 | } |
| 3276 | for (int dim : xrange(count)) { |
| 3277 | if (targets[start + dim] > 0) { |
| 3278 | const double weight = hasWeight ? weights[start + dim] : 1; |
| 3279 | if (weight > 0) { |
| 3280 | error.Stats[0] -= weight * targets[start + dim] * log(softmax[dim] / sumExpApprox); |
| 3281 | } |
| 3282 | } |
| 3283 | } |
| 3284 | return error; |
nothing calls this directly
no test coverage detected