| 206 | |
| 207 | |
| 208 | void TCoxError::CalcFirstDerRange( |
| 209 | int start, |
| 210 | int count, |
| 211 | const double* approxes, |
| 212 | const double* approxesDeltas, |
| 213 | const float* targets, |
| 214 | const float* /*weights*/, |
| 215 | double* firstDers |
| 216 | ) const { |
| 217 | const TVector<int> labelOrder = ArgSort(start, count, targets); |
| 218 | |
| 219 | const auto getApprox = [=] (int i) { |
| 220 | return approxes[i] + (approxesDeltas == nullptr ? 0 : approxesDeltas[i]); |
| 221 | }; |
| 222 | |
| 223 | double maxApprox = getApprox(0); |
| 224 | for (auto i : xrange(start, start + count)) { |
| 225 | const auto approx = getApprox(i); |
| 226 | if (approx > maxApprox) { |
| 227 | maxApprox = approx; |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | double expPSum = CalcCoxApproxSum(start, count, maxApprox, approxes, approxesDeltas); |
| 232 | |
| 233 | double rk = 0; |
| 234 | double lastExpP = 0.0; |
| 235 | double accumulatedSum = 0; |
| 236 | for (auto i : xrange(start, start + count)) { |
| 237 | const int ind = labelOrder[i]; |
| 238 | const double p = getApprox(ind) - maxApprox; |
| 239 | |
| 240 | const double expP = std::exp(p); |
| 241 | const double y = targets[ind]; |
| 242 | accumulatedSum += lastExpP; |
| 243 | |
| 244 | if (y > 0) { |
| 245 | expPSum -= accumulatedSum; |
| 246 | accumulatedSum = 0; |
| 247 | rk += 1.0 / expPSum; |
| 248 | } |
| 249 | |
| 250 | const double grad = static_cast<double>(y > 0) - expP * rk; |
| 251 | firstDers[ind] = grad; |
| 252 | |
| 253 | lastExpP = expP; |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | namespace { |
| 258 | template <int Capacity> |
no test coverage detected