B24 в vector_tasks.md: мёртвые веса скоринга — диагностика (числа, A/B) и план оживления данными (railway сразу, historical после архива)

This commit is contained in:
2026-09-25 15:10:42 +03:00
parent cdfbf30232
commit ef18f8e28f
+63
View File
@@ -1074,3 +1074,66 @@ mchs_units); admin (РЦУ РЧС) — без фильтра. Тот же ско
ретенция 90 дней.
- Зоны операции уезжают в КОНТУР и видны в штаб-панели CT130:8080 под своим
operation_id; вторая операция не смешивается.
---
## B24 — Мёртвые веса скоринга: анализ зафиксирован, данные решают (2026-09-25)
**Тип:** анализ завершён, РЕШЕНИЕ ЗАФИКСИРОВАНО. НЕ чистить веса «по чутью» — оживлять данными.
### Диагностика (проверено прогонами, A/B-тест)
`BASE_WEIGHTS` (services/scoring_service.py, методика §9) содержит 7 факторов.
Реально на ранжирование зон влияют только 5:
| Фактор | Базовый вес | Подставляется в zone_dict? | Реальный вклад |
|--------|-------------|---------------------------|----------------|
| forest | 0.25 | да (forest_pct из OSM) | 29.4% |
| water | 0.20 | да (water_distance_km из OSM) | 23.5% |
| roads | 0.18 | да (road_density из OSM) | 21.2% |
| settlement | 0.15 | да (settlement_distance_km) | 17.6% |
| historical | 0.12 | **НЕТ** — всегда дефолт 0.5 | 0% (константа) |
| direction | 0.07 | да (direction_match при last_seen_direction) | 8.2% |
| shelter | 0.03 | **НЕТ** — всегда дефолт 0.3 | 0% (константа) |
Третья разновидность мёртвого — **railway**: вес добавляется динамически
(профиль РАС, ×2.5, `apply_profile` → `weights['railway'] = 0.05`), но
`railway_distance_km` никто не вычисляет → вклад в score всегда 0.
При этом critical_warning РАС требует «немедленно проверить ВСЕ ж/д пути».
**A/B-прогон подтверждает**: приоритеты 8 секторов с dead-весами и без них
попарно идентичны (константа historical 0.5 / shelter 0.3 добавляет всем
зонам одинаковую добавку, на разницу оценок не влияет).
### РЕШЕНИЕ (фиксируем)
1. **НЕ удалять веса из BASE_WEIGHTS.** Методика §9 согласована с руководством;
историческая частота — осмысленный фактор, у него нет ДАННЫХ, а не смысла.
Правка весов руками = калибровка «по чутью», запрещена политикой
(«коэффициенты меняются только по явному решению руководства»).
2. **Оживать по мере появления данных:**
- **railway_distance_km** — можно сразу: railway=rail уже есть в локальном
OSM (planet_osm_line, water-эндпоинт выгружает ж/д объекты). Нужна функция
«расстояние до ближайшего ж/д пути в секторе» в osm_local (аналог
settlement/water-кандидатов) + подстановка в zones_dict в rules_analysis.
Тогда railway-фактор для РАС заработает, как обещает critical_warning.
- **shelter_pct** — из локального OSM (доля укрытий в секторе: лес + отдельные
объекты natural=scrub/tree/wetland). Требует выбора методики «укрытие» —
согласовать с руководством, потом код.
- **historical_freq** — ТОЛЬКО после набора архива «прогноз vs факт»
(сейчас 2 записи — данных нет, выдумывать нельзя). Когда закрытых поисков
станет десятки: посчитать места находок вокруг ТНП по секторам и подавать
в скоринг. Это ЗАКРЫВАЕТ калибровку settlement_score из «в планах».
3. **Порядок работы (предложение):**
a) railway из OSM (данные есть, ~1 день) — оживает critical_warning РАС;
b) копить архив закрытых кейсов (каждый поиск — точка);
c) historical_freq по архиву + калибровка весов по фактам (решение руководства);
d) shelter — по согласованной методике.
4. **Тест-страж:** при любых правках скоринга сверять контрольные точки
матрасчёта (README §7) и прогонять A/B (ранжирование до/после) —
приоритеты не должны меняться «молча».
**Не делать:** подстановку «правдоподобных» констант, включение weights без
источника данных, изменение BASE_WEIGHTS без решения руководства.