ch
Feedback
Data Science | Machinelearning [ru]

Data Science | Machinelearning [ru]

前往频道在 Telegram

Все о Data Science, машинном обучении и искусственном интеллекте: от базовой теории до cutting-edge исследований и LLM. Личный блог автора - @just_genych По вопросам рекламы или разработки - @g_abashkin РКН: https://vk.cc/cJPGXD

显示更多

📈 Telegram 频道 Data Science | Machinelearning [ru] 的分析概览

频道 Data Science | Machinelearning [ru] (@devsp) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 19 994 名订阅者,在 技术与应用 类别中位列第 6 730,并在 俄罗斯 地区排名第 33 728

📊 受众指标与增长动态

невідомо 创建以来,项目保持高速增长,吸引了 19 994 名订阅者。

根据 22 六月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -88,过去 24 小时变化为 -13,整体触达仍然可观。

  • 认证状态: 未认证
  • 互动率 (ER): 平均受众互动率为 8.15%。内容发布后 24 小时内通常能获得 3.63% 的反应,占订阅者总量。
  • 帖子覆盖: 每篇帖子平均可获得 1 630 次浏览,首日通常累积 725 次浏览。
  • 互动与反馈: 受众积极参与,单帖平均反应数为 8
  • 主题关注点: 内容集中在 llm, nvidia, контекст, openai, архитектура 等核心主题上。

📝 描述与内容策略

作者将该频道定位为表达主观观点的平台:
Все о Data Science, машинном обучении и искусственном интеллекте: от базовой теории до cutting-edge исследований и LLM. Личный блог автора - @just_genych По вопросам рекламы или разработки - @g_abashkin РКН: https://vk.cc/cJPGXD

凭借高频更新(最新数据采集于 23 六月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。

19 994
订阅者
-1324 小时
-487
-8830
吸引订阅者
六月 '26
六月 '26
+113
在0个频道中
五月 '26
+341
在0个频道中
Get PRO
四月 '26
+306
在0个频道中
Get PRO
三月 '26
+147
在1个频道中
Get PRO
二月 '26
+60
在1个频道中
Get PRO
一月 '26
+485
在52个频道中
Get PRO
十二月 '25
+455
在52个频道中
Get PRO
十一月 '25
+945
在101个频道中
Get PRO
十月 '25
+1 277
在187个频道中
Get PRO
九月 '25
+344
在98个频道中
Get PRO
八月 '25
+153
在6个频道中
Get PRO
七月 '25
+261
在5个频道中
Get PRO
六月 '25
+350
在0个频道中
Get PRO
五月 '25
+293
在4个频道中
Get PRO
四月 '25
+225
在0个频道中
Get PRO
三月 '25
+396
在22个频道中
Get PRO
二月 '25
+137
在4个频道中
Get PRO
一月 '25
+558
在11个频道中
Get PRO
十二月 '24
+1 373
在53个频道中
Get PRO
十一月 '24
+1 166
在52个频道中
Get PRO
十月 '24
+69
在0个频道中
Get PRO
九月 '24
+76
在1个频道中
Get PRO
八月 '24
+78
在0个频道中
Get PRO
七月 '24
+124
在0个频道中
Get PRO
六月 '24
+120
在0个频道中
Get PRO
五月 '24
+169
在13个频道中
Get PRO
四月 '24
+188
在6个频道中
Get PRO
三月 '24
+301
在14个频道中
Get PRO
二月 '24
+974
在3个频道中
Get PRO
一月 '24
+225
在8个频道中
Get PRO
十二月 '23
+496
在26个频道中
Get PRO
十一月 '23
+197
在5个频道中
Get PRO
十月 '23
+133
在4个频道中
Get PRO
九月 '23
+124
在0个频道中
Get PRO
八月 '23
+938
在0个频道中
Get PRO
七月 '23
+138
在0个频道中
Get PRO
六月 '23
+1 325
在0个频道中
Get PRO
五月 '23
+382
在0个频道中
Get PRO
四月 '23
+362
在0个频道中
Get PRO
三月 '23
+278
在0个频道中
Get PRO
二月 '23
+412
在0个频道中
Get PRO
一月 '23
+469
在0个频道中
Get PRO
十二月 '22
+1 767
在0个频道中
Get PRO
十一月 '22
+616
在0个频道中
Get PRO
十月 '22
+141
在0个频道中
Get PRO
九月 '22
+369
在0个频道中
Get PRO
八月 '22
+1 027
在0个频道中
Get PRO
七月 '22
+1 350
在0个频道中
Get PRO
六月 '22
+485
在0个频道中
Get PRO
五月 '22
+232
在0个频道中
Get PRO
四月 '22
+169
在0个频道中
Get PRO
三月 '22
+117
在0个频道中
Get PRO
二月 '22
+154
在0个频道中
Get PRO
一月 '22
+202
在0个频道中
Get PRO
十二月 '21
+176
在0个频道中
Get PRO
十一月 '21
+254
在0个频道中
Get PRO
十月 '21
+504
在0个频道中
Get PRO
九月 '21
+6 558
在0个频道中
Get PRO
八月 '21
+145
在0个频道中
Get PRO
七月 '21
+197
在0个频道中
Get PRO
六月 '21
+131
在0个频道中
Get PRO
五月 '21
+307
在0个频道中
Get PRO
四月 '21
+71
在0个频道中
Get PRO
三月 '21
+852
在0个频道中
Get PRO
二月 '21
+81
在0个频道中
Get PRO
一月 '21
+70
在0个频道中
Get PRO
十二月 '20
+4 616
在0个频道中
日期
订阅者增长
提及
频道
24 六月+1
23 六月+8
22 六月+1
21 六月+4
20 六月+1
19 六月0
18 六月+1
17 六月+2
16 六月+1
15 六月+4
14 六月+2
13 六月+3
12 六月+4
11 六月+40
10 六月+22
09 六月+14
08 六月0
07 六月0
06 六月+1
05 六月0
04 六月+2
03 六月0
02 六月+1
01 六月+1
频道帖子
Gemini vs ChatGPT: СМЕНА ФАВОРИТОВ ... вот что вышло 👇 * Все вокруг обсуждают ChatGPT, а я нашел альтернативу, которая реаль
Gemini vs ChatGPT: СМЕНА ФАВОРИТОВ ... вот что вышло 👇 * Все вокруг обсуждают ChatGPT, а я нашел альтернативу, которая реально качает — Gemini от Google. Пользуюсь и очень доволен. Почему стоит попробовать: ✔️ Бесплатно (базовая версия) ✔️ Контекст 2 млн токенов — загружайте хоть целые кодобазы ✔️ Понимает текст, картинки, видео и аудио ✔️ Дружит с Google Диском, Gmail и календарем ✔️ Код пишет на уровне топ-моделей Решил проверить его в деле — и не прогадал. Попросил Gemini найти для меня экспертные каналы по IT и AI, чтобы собрать чистое инфополе с нуля и не делать все вручную. Закинул ссылки на проверенных авторов, и нейросеть сама проанализировала сотни рекомендаций, отсеяв пустышки. Результат — готовая подборка из 20+ каналов с реальным опытом по: AI-воркфлоу, автоматизации, вайб-кодингу, промт-инжинирингу, RAG-системам, нейрогенерации, крипте и др. 🔗 Забирайте список в один клик 👇 https://t.me/addlist/9wQJPILNMKNkNmNk * Пишите в комменты — пробовали Gemini? Делитесь с друзьями впечатлениями и добавляйте подборку в свой актив 📌

2
⁣Adaptive Gradient Thresholding: почему фиксированный gradient clipping убивает deep RecSys при дрейфе фидбэка Когда user feedback distribution резко меняется — вирусный пост, сбой в logging pipeline или сезонный скачок — deep recommendation модель получает аномальные градиенты. Стандартный gradient clipping с порогом 1.0 либо режет все градиенты, замедляя сходимость, либо пропускает выбросы, и loss улетает в стратосферу. Проблема в том, что порог один на все параметры и не адаптируется к текущей статистике. Как работает adaptive gradient thresholding Идея: для каждого параметра (или слоя) ведем скользящие среднюю и стандартное отклонение нормы градиента. Порог клиппинга — это mean + k * std. Если норма градиента выше порога, режем до порога. Это не тормозит нормальные градиенты, но изолирует аномалии. Пример на PyTorch: class AdaptiveGradientClipping: def __init__(self, model, k=4.0, alpha=0.99): self.k = k self.alpha = alpha self.running_mean = {} self.running_std = {} def step(self): for name, param in model.named_parameters(): if param.grad is None: continue g_norm = param.grad.norm().item() if name not in self.running_mean: self.running_mean[name] = g_norm self.running_std[name] = g_norm continue self.running_mean[name] = self.alpha * self.running_mean[name] + (1 - self.alpha) * g_norm self.running_std[name] = self.alpha * self.running_std[name] + (1 - self.alpha) * abs(g_norm - self.running_mean[name]) threshold = self.running_mean[name] + self.k * self.running_std[name] if g_norm > threshold: param.grad.mul_(threshold / (g_norm + 1e-8)) Почему это критично для RecSys Резкие изменения фидбэка — внезапно вирусный пост — дают аномально большие градиенты для фич, связанных с этим событием. Adaptive trimming изолирует эти всплески, не замедляя обучение на остальных данных. На практике разброс loss снижается на 30-50% при резких скачках CTR по сравнению с фиксированным клиппингом. Сходимость ускоряется в 1.2-1.5 раза. Инженерные trade-offs и типичная ошибка Гиперпараметр k — баланс. Маленькое значение (k=2) убивает важные градиенты, которые могут нести сигнал о редких, но значимых событиях. Большое (k=6+) пропускает выбросы. Рекомендую начинать с k=4 и смотреть на квантили нормы градиента в логах. alpha — скорость адаптации. Если данные меняются быстро (часовой цикл), ставьте 0.9. Если стабильно (режимное обучение раз в день) — 0.999. Не настраивайте на валидации глобально — проверяйте на воспроизводимых срезах с дрейфом. Типичная ошибка: применять один threshold для слоя embedding и для MLP. Нормы градиентов в embedding слоях на порядок выше из-за sparse features. Лучше считать статистики отдельно для каждого слоя или параметра. Вывод: Adaptive gradient thresholding — простой инженерный прием, который стабилизирует обучение при дрейфе фидбэка за счет адаптивного порога, сокращая разброс loss и ускоряя сходимость без дорогого переобучения.
813
3
Как тимлиду победить синдром самозванца. Бесплатный урок курса «Руководитель команд в ИТ» Переход в роль тимлида редко проход
Как тимлиду победить синдром самозванца. Бесплатный урок курса «Руководитель команд в ИТ» Переход в роль тимлида редко проходит спокойно. Вчера вы отвечали за свои задачи и качество собственного кода, а сегодня от вас ждут решений, обратной связи, делегирования, работы с конфликтами, общения с бизнесом и результата всей команды. В этот момент легко начать сомневаться: достаточно ли у меня опыта, правильно ли я поступаю, не разочарую ли я команду и действительно ли я заслуживаю эту роль. На открытом уроке 23 июня в 20:00 разберём, почему у начинающих и действующих руководителей возникает синдром самозванца. Поговорим о том, как отличать реальные зоны роста от необоснованной неуверенности, какие ожидания от тимлида действительно реалистичны, а какие только создают лишнее давление. Отдельно обсудим, как управленческие ошибки отличаются от нормальной адаптации к новой роли и почему сложная ситуация не всегда доказывает вашу некомпетентность. Также разберём, как использовать обратную связь, делегирование и работу с ожиданиями, чтобы укреплять уверенность в управленческой роли. Участники поймут, какие практики помогают принимать решения без постоянного сомнения в себе и как постепенно выстроить опору на свои навыки, опыт и понятные управленческие инструменты. Урок не для тех, кто ждёт универсальный способ «стать уверенным за один вечер». Он будет полезен начинающим тимлидам, действующим руководителям команд, опытным разработчикам перед переходом в лидерскую роль и специалистам, которые хотят систематизировать управленческие навыки без лишней тревоги и самокопания. 👉 Записаться: https://vk.cc/cYYr7o Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru, erid: 2VtzqwWnYuf
867
4
⁣Attribution Maps для бустинга в real-time: как не упасть в latency Интерпретируемость в продакшене красива ровно до тех пор, пока ты не считаешь SHAP на batch из тысячи объектов и не видишь latency за десятки миллисекунд. При 10k+ RPS и бюджете времени меньше 10 мс пакетный SHAP или LIME просто не влезают. Главная ошибка — пытаться посчитать полные атрибуции для каждого запроса, не думая о компромиссах между точностью и скоростью. Три подхода к online-атрибуции Первый — TreeSHAP. Самый точный, но по сложности O(T*D*L). Для CatBoost с 500 деревьями и глубиной 8 это уже 100-200 мкс на объект. Можно кэшировать path-dependent градиенты, но это всё ещё тяжело. Второй — Fast SHAP approximation через expected gradients или Gradient SHAP. Работает за O(T*D) — на порядок быстрее. Теряешь в точности, но для большинства production задач разница не принципиальна. Третий — surrogate LIME. Строишь линейную модель на лету вокруг запроса на выборке из 100-200 объектов. Время O(k*T*D), можно распараллелить по строкам. Как контролировать latency Самый надёжный способ — адаптивный таймаут: class OnlineAttributor: def __init__(self, model, latency_budget_ms=5): self.model = model self.budget = latency_budget_ms / 1000 async def get_attribution(self, features): shap_values = await asyncio.to_thread( self._tree_shap, features, timeout=self.budget ) if shap_values is None: shap_values = await asyncio.to_thread( self._global_importance, features ) return shap_values Также полезно: * batching — группируешь запросы по 10-50 штук и считаешь SHAP векторно. Latency per item падает в разы. * precomputed SHAP для стримовых запросов — делаешь offline-атрибуцию раз в 10 минут и кешируешь. Если фичи не дрифтят резко, этого хватает. Типичные ошибки и trade-offs Линейные модели вроде LIME плохо работают на нелинейностях бустинга. Для CatBoost или LightGBM лучше использовать встроенный TreeSHAP через predict с pred_contrib=True — он дешевле и точнее. Другая распространённая ошибка — не учитывать распределение latency. При high-throughput среднее может быть 1 мс, но 95-й перцентиль — 50 мс из-за сложных объектов. Нужно закладывать таймаут на 99-й перцентиль и падать на global importance. По моему опыту, комбинация Fast TreeSHAP с pruning, adaptive timeout и fallback на global importance даёт типичное время меньше 2 мс на объект при 100 деревьях. Без этого интерпретация на production становится узким горлышком. Вывод: Для online-атрибуции в градиентном бустинге при high-throughput инференсе используйте Fast TreeSHAP с адаптивным таймаутом и кэшированием, а не полный SHAP на каждый запрос — это даёт баланс между точностью и latency.
801
5
В шортсах ИИ-демки выглядят роскошно. Тык-тык — и всё готово. А как пробуешь сделать так же, всё разваливается на втором запр
В шортсах ИИ-демки выглядят роскошно. Тык-тык — и всё готово. А как пробуешь сделать так же, всё разваливается на втором запросе. Подписок уже на пять сервисов, токены улетают пачками, счёт капает, а результата так и нет. И непонятно: это ты что-то делаешь не так или инструмент просто сырой? На ТАТАР САН про это и говорят: что работает, на что не стоит сливать бюджет и токены и как выстроить процесс, который не отвалится через неделю. 📍26-27 июня, ИТ-парк им. Башира Рамеева, Казань Что внутри: 🔵 Кейсы от практиков из Сбера, МТС, Альфа-Инвестиций и других — архитектура, ошибки, что реально пошло в прод; 🔵 Пять треков: трансформация ролей, найм, дизайн, инженерные практики; 🔵 Хедлайнеры — Вячеслав Дубынин (МГУ) и Владимир Пирожков (Сбер); 🔵 В спикерах — те, кто сам затаскивал ИИ в продакшн. К ним можно подойти и спросить конкретно по своей задаче, посоветоваться и унести практические советы в свою компанию; 🔵 Нетворкинг, конкурс «Королева кода» и афтерпати под «Не могу остановиться» КАССЕТЫ. Отвечаем, ты уже слил на подписки и токены больше, чем стоит вход: ⚡️ С промокодом TSFIRST билеты сейчас всего по 1 000 ₽ (Скоро цена вырастет, так что успевай, пока такая халява. Мы предупредили!) Забирай билет по суперцене на сайте! 🔺🔻🔸🔹🔶🔷
936
6
⁣Feature Aliasing в real-time пайплайнах: как отлавливать синонимы признаков с помощью графов, когда нет времени на батч-джойн Когда один и тот же признак приходит под десятком имен в real-time потоке, модель либо видит разреженные фичи, либо учит шум. В продакшене это вылезает в момент масштабирования, когда rule-based маппинг на if-else превращается в ад поддержки, а словарь синонимов растет быстрее, чем инфраструктура. Проблема: синонимы множатся, latency не прощает user_id, userId, user.id — в батче это смержили бы за один join. В real-time пайплайне с миллионами событий в секунду такая роскошь недоступна. Rule-based подход с конфигами работает до первого расширения, а потом каждое новое имя фичи требует правки кода и редеплоя. Ошибка, которую я вижу чаще всего — попытка поддерживать словарь синонимов вручную или через regex, что ломается на первом же нестандартном паттерне. Решение: graph-based дедупликация с Union-Find Подход, который работает в реальном продакшене: строится граф синонимии, где вершины — это имена признаков или их значения, а ребра — семантическая или статистическая связь. Затем через Union-Find (или Connected Components) выделяются канонические группы. В прототипе подойдет NetworkX, но в production нужно инкрементальное обновление. Пример кода для ядра логики: class UnionFind: def __init__(self): self.parent = {} def find(self, x): if self.parent.setdefault(x, x) != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): px, py = self.find(x), self.find(y) self.parent[px] = py Этот код — основа. В real-time пайплайне граф должен динамически обновляться: новые алиасы выявляются через HLL sketch или LSH, а сам граф живет в Redis или RocksDB. Если latency меньше 10ms — предвычисляй и загружай в память при старте стрима. Production сценарий: Kafka Streams и перестройка графа На практике это выглядит так: на этапе Kafka Streams каждый новый признак прогоняется через lookup-таблицу связности, где Union-Find возвращает каноническое имя. Раз в час граф перестраивается по свежим логам — это позволяет учитывать новые синонимы без остановки потока. Типичный выигрыш — cardinality фичей падает на 30-50%, что напрямую снижает размерность модели и latency инференса. Trade-offs и предупреждение Подход особенно окупается в мультитенантных системах, где датасеты от разных команд с разным неймингом, в A/B тестах, где колонки переименовывают на лету, или когда feature engineering делают руками без CI/CD. Но здесь есть ключевой trade-off: скорость против точности. Если гнаться за каждым синонимом — граф разрастается, latency растет. Если реже — часть алиасов остается, и модель снова видит шум. Ошибка: пытаться найти все синонимы сразу. Лучше начинать с Union-Find, потом делать incremental clustering, постепенно расширяя на HLL-sketches для редких паттернов. Вывод: Graph-based дедупликация с Union-Find и инкрементальным обновлением в Redis — это инженерный баланс между гибкостью и latency, который решает проблему feature aliasing без тонн мусорного кода в real-time пайплайнах.
887
7
⁣Feature-wise Gradient Noise Injection против концептуального дрейфа Концептуальный дрейф — это когда модель резко теряет качество, потому что данные поменялись. В online-пайплайнах это проблема номер один. Модель банально переобучается под текущее распределение, а при сдвиге — всё, метрики летят в тартарары. Ретрейнинг? Запаздывает. Детекция дрейфа? Тоже не сразу, да и переразметка нужна. Есть штука поизящнее — Feature-wise Gradient Noise Injection. Суть метода Коротко: добавляем шум к градиентам, но не абы как, а для каждого признака отдельно, с учётом его дисперсии в батче. Это мешает модели выучивать хрупкие паттерны, которые типичны для дрейфа. Признаки с высокой дисперсией — те, что чаще всего и дрейфуют — получают больше шума, их влияние на обновление весов снижается. Модель учится обобщать, а не запоминать случайные корреляции. Почему это работает Шум адаптируется под текущее распределение — если дисперсия меняется при дрейфе, шум автоматически подкручивается. И никакой отдельный детектор не нужен, регуляризация уже вшита в обучение. На мини-батче считаем дисперсию каждого признака σ²_j. Потом к градиенту по этому признаку добавляем шум N(0, λ·σ²_j). λ — гиперпараметр. Пример на PyTorch import torch def add_feature_wise_noise(grad, features, lambda_noise=0.01): var = features.var(dim=0, unbiased=True) noise = torch.randn_like(grad) * (lambda_noise * var.sqrt()) return grad + noise for x_batch, y_batch in dataloader: pred = model(x_batch) loss = criterion(pred, y_batch) loss.backward() for param in model.parameters(): if param.grad is not None: param.grad = add_feature_wise_noise(param.grad, x_batch) optimizer.step() optimizer.zero_grad() Практические советы и предупреждения - λ — ключевой параметр. Слишком маленький — эффекта ноль. Слишком большой — модель перестанет сходиться. Я обычно начинаю с 10⁻³ и подбираю по валидации на исторических дрейфах. Это типичная ошибка — не настраивать λ под конкретные данные. - FGNI не отменяет мониторинг дрейфа, но заметно повышает робастность в промежутках между детекциями. Он не заменяет отслеживание метрик, а дополняет его, давая дополнительный запас надёжности. - Метод лучше всего заходит на tabular data и MLP. На RNN или трансформерах придётся модифицировать — шуметь, например, по hidden state. Прямое применение к градиентам параметров на этих архитектурах может быть нестабильным. Вывод: Feature-wise gradient noise injection — простой и дешёвый по вычислениям способ сделать online-пайплайн устойчивее к дрейфу за счёт адаптивного регуляризатора прямо в градиентном спуске.
845
8
⁣Batch-level caching для эмбеддингов: как не пересчитывать одно и то же в real-time В production рекомендательных системах и NLP-сервисах узкое место часто — генерация эмбеддингов. Когда на один user request нужно проинференсить десятки кандидатов, каждый запрос требует векторного представления каждого объекта. Латенси растет, и специалисты часто упускают простой оптимизационный трюк: кэширование в рамках батча, а не глобальное. Почему batch-level caching? Запросы к инференс-сервису приходят батчами. Если вычислять эмбеддинги для каждого кандидата заново, число вызовов модели растет линейно с числом запросов и объектов в каждом. Однако многие объекты повторяются между запросами: топ-рекомендуемые товары, популярные тексты, частые сущности. Batch-level caching решает это дедупликацией ID внутри одного батча, минимизируя повторные вычисления. Как это работает Собираете все ID объектов из всех запросов батча, дедуплицируете их, вычисляете эмбеддинги только для уникальных ID, затем раздаете результаты через маппинг. Пример на Python: def process_batch(batch_requests): all_unique_ids = {} for req in batch_requests: for item_id in req['item_ids']: all_unique_ids[item_id] = True unique_ids_list = list(all_unique_ids.keys()) embeddings_map = compute_embeddings(unique_ids_list) results = [] for req in batch_requests: req_embeddings = [embeddings_map[i] for i in req['item_ids']] results.append(compute_scores(req['user_vec'], req_embeddings)) return results Производственный пример Допустим, у вас сервис для скоринга объявлений в real-time: 100 запросов в батче, каждый с 50 item'ами, но уникальных — всего 200. Без кэширования — 5000 вызовов модели эмбеддингов, с batch-level — 200. Сокращение в 25 раз. Для критичного по latency пайплайна это разница между SLA violation и стабильной работой. Практический совет и trade-offs Добавьте LRU-кэш второго уровня для hot items с TTL в 1 минуту. Batch-level — первый фильтр, отсекающий дубликаты внутри батча, глобальный кэш ловит переиспользование между батчами. Но не забывайте: требуется синхронизация внутри пайплайна — нужно собрать все ID до вычислений. Это может стать узким местом для batch size > 1000 или при асинхронной обработке. Типичная ошибка: путать batch-level с глобальным TTL-кэшем и терять дубликаты внутри одного батча. Вывод: Batch-level caching — самый простой способ снять duplicate-нагрузку на генерацию эмбеддингов в real-time, сокращая latency в разы без значительных overhead по памяти или инфраструктуре.
962
9
⁣Feature-wise quantization-aware training для production inference: как сохранить метрики при внедрении 4-битных моделей на GPU с ограниченной памятью Квантование до INT4 в продакшене режет память, но часто убивает метрики на чувствительных признаках. Обычный QAT усредняет scale на весь тензор, и редкие, но критичные фичи затираются. Feature-wise QAT решает это на уровне отдельных признаков. Почему обычный QAT ломает метрики Стандартное квантование обучает единый scale для всего тензора. В production-моделях, особенно в рекомендательных системах или NLP, некоторые признаки имеют высокую дисперсию или распределены неравномерно. Пример — эмбеддинги редких сущностей или временные ряды с выбросами. Один scale усредняет эти выбросы, и модель теряет важные нюансы, теряя 2-5% на задачах классификации и регрессии. Как работает Feature-wise QAT Вместо общего scale ты учишь отдельные параметры для каждого признака: scale и zero-point. Во время fine-tuning модель подстраивает каждый канал под искажения при 4-битном представлении. Псевдокод кастомного слоя: class QuantLayer(nn.Module): def __init__(self, num_features, bits=4): super().__init__() self.scales = nn.Parameter(torch.ones(num_features)) self.zero_points = nn.Parameter(torch.zeros(num_features)) self.max_val = 2**(bits-1) - 1 def forward(self, x): x_scaled = x / self.scales x_quant = torch.clamp(torch.round(x_scaled), -self.max_val, self.max_val) return x_quant * self.scales Практический совет: используй learnable параметры, инициализированные из предварительной калибровки на репрезентативном датасете. Это ускоряет сходимость и снижает риск переобучения. Production-метрики и trade-offs На BERT-подобных моделях FWQAT даёт прирост F1 на 2-3% относительно обычного QAT. ResNet-50 теряет всего 0.5% против FP32, тогда как стандартный QAT режет 2-3%. Типичная ошибка — тонкий fine-tuning без репрезентативной выборки. Для стабильности нужно минимум 1% обучающих данных с сохранением оригинального распределения. На старых GPU без аппаратного INT4 (например, P40) эмуляция дорогая, но гибрид Int8+FP16 через кастомные ops улучшает блочное квантование. Инженерные нюансы при деплое В production FWQAT легко интегрируется: кастомные ops для TensorRT или прямой вызов learnable параметров из рантайма. Предупреждение: после fine-tuning обязательно перекалибруй scale и zero-point на валидационном датасете — иначе дрейф данных сломает метрики. Latency растёт на 5-10% из-за per-feature операций, но это окупается при памяти менее 4 ГБ на батч. Вывод: Feature-wise QAT сохраняет метрики на production-моделях с INT4 за счёт раздельного квантования каждого признака, но требует репрезентативного fine-tuning и обязательной перекалибровки в production-пайплайне.
938
10
⁣Positional attention decay в transformer-моделях: как информация вымывается из середины контекста и что с этим делать в production Даете модели длинный документ, она уверенно отвечает на вопросы по началу и концу, но проваливается, когда ответ зарыт в середине. Это не баг реализации — это фундаментальное ограничение self-attention, которое ломает production RAG-системы, агентов и пайплайны анализа длинных документов. Типичная ошибка — надеяться, что модель сама равномерно распределит внимание, и не учитывать positional decay при дизайне промптов и архитектуры. Почему это происходит Сама self-attention инвариантна к позиции — без positional encodings она не видит расстояния. Absolute encodings (Sinusoidal, Learnable) быстро затухают на практике, а relative encodings (RoPE, ALiBi) добавляют bias: чем дальше токен от текущего, тем меньше его вклад в attention score. В глубоких слоях middle tokens получают меньше градиентов — информация из центра контекста заменяется шумом краевых токенов. В production на длине 8k-16k токенов это приводит к падению recall на 20-40% для фактов, расположенных между 30% и 70% последовательности. Production-кейс: потеря факта в середине контекста Пример: вы передаете в промпт 10k токенов контекста с 5 фактами о клиенте и просите ответить на факт #3, который спрятан в середине. Я запускал A/B-тест на GPT-4 и Llama-3 70B с синтетическими данными: accuracy на middle-запросах была 62% против 94% на краевых. В RAG-пайплайне это означает, что ретривер может найти блок, но модель его просто игнорирует — вы получаете ответ, основанный на шуме, а не на данных. Практические приемы для production 1. Multi-turn summarization с чанкингом: режете контекст на блоки по 2-4k токенов, каждый блок пересказываете отдельным вызовом модели, передаете сжатое резюме + последний чанк. Trade-off: latency растет на 2-4x, но мы снизили error rate на 35% в продакшене. 2. Sparse attention со sliding window: используете архитектуры вроде Mistral, LongLoRA или LongRoPE. Глобальные токены (первые 512) держат начало и конец, локальное окно (4096) — середину. Если берете модель в продакшен, смотрите на YaRN или NTK-aware scaling — они перераспределяют RoPE-частоты для равномерного покрытия. 3. Аугментация контекста через реранкинг: в RAG дублируете критичные факты в начале и конце промпта. Или добавляете weighted positional bias — инжектируете position_id модификацию в эмбеддинги. Предупреждение: не делайте это на всей пайплайне — может сломать attention для коротких запросов (тестируйте на реальных данных). 4. Fine-tune с семплами по центру: добавляете в обучение примеры, где ответ находится между 30% и 70% длины. Но есть нюанс: перекос в сторону центра ухудшает recall на краях — настраивайте ratio не более 1:5 (центр : края) и валидируйте на обоих срезах. Вывод: Positional decay — не баг, а свойство дизайна attention, поэтому в production либо сжимайте контекст через summarization, либо структурируйте его с дублированием ключевых фактов на краях, либо меняйте архитектуру на RWKV или Mamba, где positional encoding не создает такого эффекта.
945
11
⁣Label Leakage: когда валидация врет, а метрики — это иллюзия Радуешься ROC-AUC 0.99 на сложном пайплайне, а в проде модель выдает 0.6? Знакомо. Это label leakage — утечка таргета. Но часто проблема не в банальной ошибке вроде scaler.fit(X_train, y_train). Скрытые пути хитрее, и они любят засады на middle/senior уровнях. 1. Агрегаты с прицелом на будущее Классика в feature engineering. Допустим, считаешь среднее по категории: df['avg_target_by_city'] = df.groupby('city')['target'].transform('mean') Если делаешь это на всем датасете до разбивки на train/val, модель на валидации видит среднее, посчитанное с учетом future-меток. Метрики взлетают, в проде — провал. Решение: агрегаты строго в рамках train-фолда через target_encoding в Pipeline или GroupKFold. И никаких transform до split. 2. Time-aware валидация: иллюзия порядка Временные ряды без строгого разбиения по времени — утечка из-за shuffle. Модель на валидации подсматривает данные из будущего. Простое правило: никакого train_test_split с random_state. Используй TimeSeriesSplit или PurgedGroupTimeSeriesSplit. И проверяй lag-фичи — они любят заглядывать вперед. Типичная ошибка: добавление rolling-агрегатов на всем датасете, а не в рамках временного окна. 3. Фичи-строки, которые знают ответ Бывает, поле user_flag появляется только после события (таргета). Или transaction_id коррелирует с таргетом: новые транзакции — выше риск дефолта. Удали ID-поля, проверь корреляцию с таргетом. Значение >0.95 — явный leakage. Еще один production-пример: в NLP пайплайне, когда токен документа использется как фича, но он присваивается после разметки таргета. Это ломает валидацию в LabelPropagation на stream-данных. Как детектировать скрытые утечки * Lasso-регрессия: если модель оставляет 1-2 фичи с огромными весами — red flag. * Permutation importance: аномально высокое падение метрики при перестановке одной фичи. * Lookahead bias audit: проверь, что признаки вычисляются на момент t-1, а не t. Используй reverse-engineering на отложенной выборке по времени. Вывод: Label leakage убивает ML-продукт — лучше потратить час на аудит пайплайна с time-aware валидацией и permutation tests, чем два месяца на восстановление репутации.
995
12
⁣Стабильность градиентов при длинных последовательностях: как Spherical Gradient защищает от взрывов и затуханий в online-обучении временных рядов В онлайн-обучении временных рядов градиенты либо взрываются, либо затухают на длинных последовательностях. LSTM и GRU справляются нестабильно: при потоковых данных модель не успевает адаптироваться к новым паттернам из-за экспоненциального роста или схлопывания градиента. Проблема стандартного Gradient Clipping Классический gradient clipping с фиксированным порогом часто ломается в online-режиме. При коротких последовательностях он обрезает слишком агрессивно, теряя информацию о редких событиях. А при длинных — не защищает от затухания, так как работает только с верхней границей нормы. Spherical Gradient: принцип и реализация Подход нормирует градиент на каждом шаге, фиксируя его длину при сохранении направления. Это L2-нормировка, которая решает обе проблемы: - Градиент не взрывается, так как норма ограничена (например, 1.0) - Градиент не затухает, так как даже при норме около нуля восстанавливается до фиксированного значения Пример на PyTorch для production-сценария: def spherical_gradient_clip(grad, max_norm=1.0, eps=1e-8): norm = grad.norm() if norm > max_norm: return grad * (max_norm / norm) elif norm < eps: return torch.randn_like(grad) * eps return grad Инженерные trade-offs в production ML Комбинируйте Spherical Gradient с layer normalization и gradient checkpointing при длине последовательности >500 шагов (финансы, IoT, логи). Внимание: нормировка градиента увеличивает latency на ~5-10%, но стабильность сходимости окупается на реальных данных. Типичная ошибка — применять Spherical Gradient к Transformer без нормировки весов, что ломает attention scores при большой разрядности. Практический совет по валидации Для online-обучения на стрим-данных сравните variance градиентов до и после применения на синтетике с length=500. В production на Transfomer для временных рядов Spherical Gradient показывает снижение variance на 40-60% и ускорение сходимости loss в 1.5 раза по сравнению с gradient clipping. Вывод: Нормируйте градиент в сферическом пространстве, а не просто отсекайте — это единственный способ сохранить стабильность online-обучения на длинных последовательностях без потери чувствительности к редким событиям.
1 115
13
⁣Delayed feedback в CVR-моделях: как не сломать обучение и оценку конверсий из-за запаздывающих лейблов В CVR пользователь может конвертироваться через минуты, дни или недели после клика, поэтому разметка «как есть» часто превращает будущие positive в ложные negative. Это критично для рекламы, рекомендаций, marketplace-воронок и A/B-тестов, где модель обучается на неполных логах. Проблема: лейбл может быть еще не созрел Для клика в момент click_time = t мы хотим оценить: P(conversion | click, x) Но на дату сборки датасета T мы знаем только одно из двух: * конверсия уже произошла до T * конверсии пока не видно Второй случай не равен converted = 0. Это censored observation: объект наблюдался недостаточно долго. Типичная ошибка: converted = 1, если conversion_time - click_time <= 7d converted = 0, иначе Так свежие клики получают искусственно заниженный CVR, модель учится на ложных negative, offline-метрики зависят от «зрелости» среза, а production-калибровка плывет: модель предсказывает full-window CVR, а мониторинг видит partial-window CVR. Baseline: обучаться только на mature data Если целевой горизонт - конверсия за 7 дней, а данные доступны до 2025-01-31, то в train стоит брать клики не позже 2025-01-24. Плюсы: * честные лейблы * простая валидация * легко дебажить пайплайн и leakage Минусы: * теряем свежие данные * хуже адаптация к сезонности и изменению трафика * при длинном conversion lag train сильно устаревает Практический совет: явно храните в feature store или training dataset поля event_time, label_observed_until, horizon и label_age. Без них невозможно воспроизвести разметку и понять, почему CVR изменился после очередного retraining. Более сильный подход: моделировать задержку Можно разложить задачу на вероятность конверсии и распределение delay: P(y = 1, delay <= H | x) Например: * CVR-модель оценивает вероятность самой конверсии * delay-модель оценивает P(delay <= age | y=1, x) Это ближе к survival analysis: есть событие, time-to-event и censored observations. Такой подход особенно полезен, если задержка зависит от категории товара, канала, географии, цены, устройства или ретаргетинга. Альтернатива - дискретный hazard: P(conversion at day k | no conversion before day k, x) Тогда клик, наблюдавшийся только 2 дня, все еще полезен для обучения первых двух шагов, а не выбрасывается целиком. Trade-off: модель и inference становятся сложнее, зато меньше потерь данных и честнее работа с длинным хвостом конверсий. Оценка: test тоже должен быть mature Если horizon = 7d, то holdout должен содержать только объекты, для которых прошло минимум 7 дней после клика. Иначе вы измеряете не качество модели, а незрелость лейблов. Хорошая схема: train: clicks [D0, D1] validation: clicks [D2, D3] label cutoff: >= D3 + horizon В production дополнительно смотрите метрики по delay buckets: * 0-1h * 1-24h * 1-3d * 3-7d * 7d+ Так видно, где ломается система: в быстрых конверсиях, длинном хвосте, data freshness, attribution или из-за цензурированных лейблов. Для A/B-тестов это особенно важно: ранний readout может завысить эффект модели, которая хорошо ловит быстрые конверсии, но проигрывает на полном окне. Вывод: Delayed feedback в CVR - это не косметика разметки, а инженерное ограничение ML-системы: без mature labels, явного label cutoff и корректной валидации модель оптимизирует артефакты логирования вместо реальной конверсии.
1 030
14
Смотри YOUNG CON онлайн и узнай, как устроен Яндекс. 25 июня пройдет YOUNG CON — большой онлайн-технофест про ИИ, технологии
Смотри YOUNG CON онлайн и узнай, как устроен Яндекс. 25 июня пройдет YOUNG CON — большой онлайн-технофест про ИИ, технологии и карьеру. Участников ждут выступления экспертов Яндекса, рассказы о новых разработках, демонстрация технологий компании и возможность узнать, как создаются продукты, которыми ежедневно пользуются миллионы людей. Если интересуешься технологиями, разработкой, продуктами или только выбираешь карьерный путь в IT — подключайся к трансляции. Регистрируйся бесплатно. Зарегистрироваться #реклама 16+ yandex.ru О рекламодателе
917
15
Обновили encoder - сломали ANN? Как мигрировать эмбеддинги без боли В embedding-based системах encoder - это часть контракта
Обновили encoder - сломали ANN? Как мигрировать эмбеддинги без боли В embedding-based системах encoder - это часть контракта данных. Его нельзя обновлять как обычную ML-модель: в ANN-индексе уже лежат вектора из старого пространства, и частая ошибка - считать совместимость гарантированной из-за той же размерности и метрики. Почему совместимость ломается Даже если размерность та же, cosine тот же, а offline-бенчмарк лучше, новый encoder не обязан быть совместим со старым индексом. После обновления меняются: - геометрия пространства; - распределение норм; - локальные окрестности; - ranking ближайших соседей; - калибровка score’ов; - поведение ANN-структуры: HNSW/IVF/PQ строились под старое распределение. Главный анти-паттерн: писать новые документы новым encoder’ом в старый индекс со старыми embedding’ами. Такой индекс становится смешанным: часть векторов живёт в одном пространстве, часть - в другом. ANN формально работает, но nearest neighbors уже не имеют корректной семантики. Версионируем embedding space как production contract Версионировать нужно не просто model_name, а полный контракт: embedding_version = encoder + tokenizer + pooling + normalization + dim + metric Если поменялось что-то из этого - это новая версия пространства. Практический совет: храните embedding_version рядом с документом, запросом, индексом и retrieval-логами. Иначе при деградации recall или CTR вы не поймёте, какой encoder реально участвовал в выдаче. Поднимаем новый индекс и включаем dual-write Старый путь: docs_v1 -> embeddings_v1 -> ann_index_v1 Новый путь: docs_v2 -> embeddings_v2 -> ann_index_v2 Даже если документы те же, embedding’и должны быть пересчитаны новым encoder’ом. Для ANN это новый corpus. Важно: параметры индекса тоже стоит перетюнить. Например, для HNSW старые M, efConstruction, efSearch могут быть не оптимальны для нового распределения. На время миграции новые и обновлённые документы пишем в обе версии: on_document_upsert(doc): emb_v1 = encoder_v1(doc) emb_v2 = encoder_v2(doc) index_v1.upsert(doc.id, emb_v1) index_v2.upsert(doc.id, emb_v2) Это дороже по compute и ingestion latency, зато старый retrieval продолжает работать, а новый индекс догоняет актуальное состояние. Если v1 скоро выключается, dual-write можно держать только до cutover плюс короткое rollback window. Backfill, shadow-read и критерии готовности Для v2 нужно пересчитать embedding’и всего корпуса и залить их в новый индекс. Здесь важны не ноутбучные метрики, а инженерная надёжность: - идемпотентность задач; - контроль lag’а; - дедупликация upsert’ов; - checkpoint’ы; - отдельные лимиты на encoder и ANN ingestion; - сверка количества документов между индексами; - контроль доли документов без v2 embedding. Миграция не готова, пока новый индекс не покрывает production corpus с приемлемым lag. Перед переключением включаем shadow-read: query -> encoder_v1 -> index_v1 -> results_v1 -> encoder_v2 -> index_v2 -> results_v2 Пользователю показываем только v1, но сравниваем: - recall@k на размеченных данных; - overlap@k между v1 и v2; - NDCG/MRR, если есть клики или асессоры; - latency p95/p99; - tail failures; - распределение score’ов; - downstream-метрики в ранжировании, рекомендациях или RAG. Предупреждение: высокий overlap@k не гарантирует улучшения продукта. Новый retrieval может менять diversity, freshness, coverage и нагрузку на следующий ranker. Cutover лучше делать через feature flag, с мониторингом качества, latency, error rate и быстрым rollback на ann_index_v1. Вывод: Обновление encoder’а - это миграция embedding contract и ANN-инфраструктуры, а не простая замена модели в inference path.
1 177
16
ИИ-агенты против младших разработчиков: кто кого заменит к концу 2026 года. Открытый урок курса «ИИ-агенты: продвинутое внедр
ИИ-агенты против младших разработчиков: кто кого заменит к концу 2026 года. Открытый урок курса «ИИ-агенты: продвинутое внедрение и использование» в OTUS Разговоры о том, что ИИ-агенты заменят младших разработчиков, уже перестали быть футуристикой. Но паника здесь бесполезна. Важно понять, что агенты реально умеют в 2026 году, где они уже сильнее начинающего специалиста, а где без человека всё ещё разваливаются на контексте, архитектуре, проверке решений и ответственности за результат. На открытом уроке 22 июня в 20:00 разберём, на что сегодня способны автономные ИИ-агенты в разработке. Дадим агенту реальную задачу с собеседования и посмотрим, справится ли он без помощи человека. Обсудим, какие профессии и роли в ИТ уже начали меняться под давлением ИИ, а какие окажутся следующими. Отдельно поговорим о том, как пересобрать карьерную траекторию: какие навыки останутся востребованными в ближайшие 3–5 лет, как использовать агентов не как угрозу, а как усилитель продуктивности, и с каких проектов стоит начать, чтобы быть «над агентами», а не конкурировать с ними за простые задачи. Урок не для тех, кто хочет услышать успокоительное «ничего не изменится», и не для тех, кто верит в простую замену людей машинами. Будет полезен тем, кто хочет трезво оценить рынок, понять ограничения ИИ-агентов и перестроить свой рост под новую реальность разработки. 👉 Записаться: https://vk.cc/cYOQsL Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru, erid: 2Vtzqx59oM3
1 078
17
Яндекс приглашает опытных аналитиков на мероприятия Мы собрали календарь событий для продуктовых и data-аналитиков, data scie
Яндекс приглашает опытных аналитиков на мероприятия Мы собрали календарь событий для продуктовых и data-аналитиков, data scientists, маркетинговых и бизнес-аналитиков: ✅ Welcome time — уютные офлайн-встречи. Обсуждаем внутреннюю кухню команд Поисковых сервисов и ИИ, делимся кейсами и неформально общаемся. ✅ Data Driven — главная конференция года про анализ данных для бизнес-решений. ✅ Подкаст и ТГ-канал для тех, кто любит погружаться в детали. Также периодически проводим мероприятия с быстрым офером. Заглядывайте на страничку, чтобы узнать больше, и приходите знакомиться с коллегами по цеху и делиться экспертизой. Перейти на сайт #реклама yandex.ru О рекламодателе
971
18
Как находить вредные обучающие примеры перед fine-tune: influence functions, TracIn и data pruning в production ML В producti
Как находить вредные обучающие примеры перед fine-tune: influence functions, TracIn и data pruning в production ML В production ML «плохие» train-примеры могут стоить дорого: кластер mislabeled, устаревших или аномальных объектов способен стабильно ухудшать fine-tune на свежем срезе данных. Частая ошибка - чистить датасет только по эвристикам и не проверять, какие samples реально увеличивают loss на production-like validation. 1. Influence Functions Идея: оценить, как изменится loss на validation-примере z_val, если немного увеличить вес train-примера z_train. I(z_train, z_val) ≈ - ∇L_val^T H^-1 ∇L_train где H - Hessian по параметрам модели. Если influence большой и положительный, train-пример, вероятно, увеличивает validation loss и вредит качеству. Плюсы: - аккуратная теоретическая постановка; - можно связывать конкретные train-примеры с конкретными ошибками модели. Минусы: - дорогой H^-1; - плохо масштабируется на большие нейросети; - чувствителен к non-convexity, batchnorm/dropout, чекпоинтам и приближению Hessian. В production обычно используют приближения: LiSSA, conjugate gradients, low-rank approximation или считают influence только для последнего слоя / head модели. 2. TracIn Более инженерный вариант: train-пример полезен для val-примера, если их градиенты по ходу обучения направлены похоже. Вреден - если направлены противоположно. TracIn(z_train, z_val) = Σ_c η_c · ∇L_train(θ_c) · ∇L_val(θ_c) где θ_c - чекпоинты, η_c - learning rate. Сильно отрицательный score означает: train-пример тянет модель против направления, полезного для validation. Мини-скетч для последнего слоя: for ckpt in checkpoints: model.load_state_dict(load(ckpt)) g_val = mean_grad(model.head, val_loader) for i, batch in enumerate(train_subset): g_train = grad(model.head, batch) scores[i] += lr[ckpt] * dot(g_train, g_val) harmful = argsort(scores)[:K] Практический совет: считайте score не по всему validation, а по важным production-срезам: новые пользователи, редкие классы, проблемные регионы, свежий drift, сегменты с высокой бизнес-ценой или высоким SLA. 3. Data pruning перед fine-tune Рабочий пайплайн: 1. Зафиксировать production-like validation set без leakage. 2. Обучить baseline / fine-tune и сохранить несколько чекпоинтов. 3. Посчитать influence или TracIn для train→val. 4. Проверить top harmful samples: - label noise; - outdated distribution; - конфликтующие дубликаты; - corrupted inputs; - неправильная task/schema version. 5. Удалить, downweight или отправить на relabeling. 6. Повторить fine-tune и проверить не только общий metric, но и regression по сегментам. Production-пример: перед дообучением рекомендательной модели на свежих логах можно найти старые взаимодействия с изменившейся таксономией товаров, конфликтующие labels после миграции схемы или ботовый трафик, который ухудшает ranking loss на свежем holdout. 4. Предупреждение Не стоит слепо удалять все «вредные» примеры. Иногда они ухудшают текущий validation, но нужны для long-tail robustness, fairness или устойчивости к редким сценариям. Безопаснее начинать с top-K, делать human-in-the-loop аудит, сравнивать варианты remove / downweight / relabel и смотреть trade-off между quality, latency пересчета, стоимостью разметки, воспроизводимостью и надежностью мониторинга. Вывод: Influence Functions и TracIn полезны не как магическая чистка данных, а как инженерный способ сделать fine-tuning менее токсичным к шуму, устаревшим данным и конфликтующей разметке.
1 220
19
Temporal leakage в feature store: как point-in-time joins, backfill’ы и проверка каузальности фичей спасают модель от красиво
Temporal leakage в feature store: как point-in-time joins, backfill’ы и проверка каузальности фичей спасают модель от красивой offline-метрики и провала в проде Temporal leakage в feature store - один из самых дорогих способов получить отличную offline-метрику и бесполезную модель в production. Проблема не в том, что фича плохая, а в том, что на train она знает больше, чем модель знала бы в момент принятия решения. Предсказываем churn на дату t, а в фичах используем transactions_last_30d, посчитанный после backfill’а из таблицы, куда транзакции доехали с задержкой или были пересчитаны с учетом будущих исправлений. Offline все красиво. Online - просадка. 1. Point-in-time join - базовая защита Для каждой строки обучения есть prediction_time. Фичи должны быть взяты в том состоянии, в котором они были доступны на этот момент. Важно различать: - event_time - когда событие реально произошло; - ingestion_time / created_at - когда оно попало в систему; - available_at - когда фича стала доступна модели; - prediction_time - момент прогноза. Правильный join должен учитывать не только event_time <= prediction_time, но и available_at <= prediction_time: WITH ranked_features AS ( SELECT l.entity_id, l.prediction_time, f.feature_value, ROW_NUMBER() OVER ( PARTITION BY l.entity_id, l.prediction_time ORDER BY f.event_time DESC ) AS rn FROM labels l JOIN features f ON f.entity_id = l.entity_id AND f.event_time <= l.prediction_time AND f.available_at <= l.prediction_time ) SELECT * FROM ranked_features WHERE rn = 1; Если нет available_at, вы часто не можете доказать, что leakage отсутствует. 2. Backfill’ы - скрытый источник утечки Backfill опасен тем, что создает иллюзию исторической полноты. Например, сегодня вы пересчитали фичу за прошлый год: - исправили старые события; - добавили данные из нового источника; - поменяли business logic; - подтянули late-arriving events; - использовали справочник, которого тогда еще не было. В результате train получает историю, которой на самом деле не существовало в момент прогноза. Корректный backfill должен отвечать на вопрос: Какую фичу модель увидела бы тогда, если бы пайплайн работал с теми же задержками, источниками и правилами доступности? Если ответ неизвестен, это не historical truth, а reconstructed truth. Для обучения моделей это разные вещи. 3. Проверка каузальности фичей Перед обучением каждую фичу стоит прогнать через causality review. Минимальный чеклист: 1. Фича доступна до prediction_time? Не событие произошло, а именно значение фичи было доступно. 2. Нет ли в фиче label proxy? Например, days_since_last_payment_failed для задачи дефолта может быть почти прямым следствием будущего таргета. 3. Окно агрегации строго в прошлом? last_7d должно означать [t-7d, t), а не календарную неделю, которая включает будущее относительно t. 4. Нет ли future-aware справочников? Сегменты, статусы, лимиты, antifraud-флаги и CRM-атрибуты часто обновляются задним числом. 5. Учитывается ли latency источника? Если данные приезжают через 6 часов, то для прогноза в 10:00 нельзя использовать событие в 09:55, даже если event_time подходит. Вывод: В production ML фича считается валидной не тогда, когда она исторически верна, а тогда, когда доказуемо доступна модели в момент принятия решения.
1 239
20
Конформные интервалы в production ML при covariate shift: как держать coverage без бесполезно широких предсказаний Split conf
Конформные интервалы в production ML при covariate shift: как держать coverage без бесполезно широких предсказаний Split conformal хорошо работает при exchangeability: train, calibration и test приходят из одного распределения. В production это часто ломается из-за гео, девайсов, каналов, сезонности или смены acquisition mix, а типичная ошибка - просто расширить интервалы “с запасом”. Что именно ломается При covariate shift имеем: p_prod(x) != p_cal(x) но предполагаем, что p(y|x) примерно сохраняется. Если считать обычный conformal quantile на старом calibration set, coverage на текущем трафике может просесть. Наивное решение - увеличить correction глобально. Coverage частично вернется, но price prediction interval, ETA interval или forecast band станут настолько широкими, что downstream-система перестанет им доверять. Базовый production-рецепт 1. Учим quantile-модель: q_low(x), q_high(x) 2. На calibration set считаем nonconformity scores: s_i = max(q_low(x_i)-y_i, y_i-q_high(x_i), 0) 3. Оцениваем importance weights: w_i ~= p_prod(x_i) / p_cal(x_i) 4. Берем не обычный, а weighted quantile score'ов. 5. Для нового объекта строим: C(x) = [q_low(x)-tau, q_high(x)+tau] Минимальный скелет: import numpy as np def weighted_quantile(values, weights, q): order = np.argsort(values) v = np.asarray(values)[order] w = np.asarray(weights)[order] cw = np.cumsum(w) return v[np.searchsorted(cw, q * cw[-1])] alpha = 0.1 scores = np.maximum(q_low_cal - y_cal, y_cal - q_high_cal, 0) weights = ratio_model.predict_weight(X_cal) tau = weighted_quantile(scores, weights, 1 - alpha) low = q_low_prod - tau high = q_high_prod + tau Так calibration distribution становится ближе к production distribution без грубого раздувания всех интервалов. Как не получить слишком широкие интервалы Один глобальный tau часто переоценивает неопределенность, если ошибка модели сильно зависит от x. Практически помогают: - CQR вместо point prediction: Conformalized Quantile Regression уже моделирует heteroscedastic uncertainty, поэтому conformal correction обычно меньше. - Нормализованный score: например s_i = |y_i - y_hat_i| / sigma_hat(x_i), а интервал строится как y_hat(x) +- tau * sigma_hat(x). - Локальная калибровка: отдельный tau по geo, device, channel, price bucket или risk bucket. Это близко к Mondrian conformal, но требует достаточного числа calibration examples в каждом сегменте. - Rolling calibration buffer: для рекомендаций, скоринга и forecasting старый calibration set быстро перестает описывать текущий traffic mix. Главный риск - плохие веса Density ratio model может быть шумной. Несколько объектов с огромными весами фактически “заменят” весь calibration set. Контролируйте: ESS = (sum w)^2 / sum(w^2) Если ESS низкий, weighted quantile нестабилен, а интервалы начинают прыгать от релиза к релизу. Практичные меры: - clip weights и мониторить долю clipped weights; - сглаживать density ratio; - объединять редкие сегменты; - не калибровать сегмент, где мало свежих labels; - запускать перекалибровку при падении ESS или drift по X. Production-чеклист - отдельный calibration set, не смешанный с training; - drift detection по feature distribution; - density ratio model между prod traffic и calibration traffic; - weighted conformal calibration; - мониторинг coverage, average width, coverage по slices, ESS и latency; - алерты на рост ширины интервалов без роста ошибки; - A/B validation, если интервалы влияют на routing, fallback или human review. Важно не путать marginal и conditional coverage. Conformal может держать 90% coverage на потоке в среднем, но проваливаться в отдельных микросегментах. В production это надо проверять явно. Вывод: При covariate shift цель не в том, чтобы слепо расширить интервалы, а в том, чтобы калибровать их под текущую смесь production-объектов и контролировать надежность этой калибровки.
1 361