Как вычисляется шанс того, что теннисист возьмёт следующий гейм? Или что футбольная команда забьёт гол в течение пяти минут? Всё это — не просто угадайка, а работа математической модели, построенной на статистике и обрабатывающей события матча в реальном времени.
В Altenar, разработчике решений для зарубежных операторов спортивных прогнозов, такие модели — часть большой системы. Моя команда работает над реализацией алгоритмов расчёта таких вероятностей.
В этой статье рассказываю, как формулируется гипотеза, как из неё строится модель, почему это важнее, чем «просто посчитать формулу», и как мы выбирали между несколькими .NET-библиотеками по точности и скорости. Всё на примере тенниса. Это один из самых сложных видов спорта для моделирования: стандартные подходы здесь не работают, счёт специфический, а сила игрока выражается не в счёте, а в вероятности взять очко на своей подаче.
Эта статья написана по мотивам моего выступления. Если вам удобнее смотреть полезности, чем читать, то смотрите запись с 14:30.
Где используется оценка вероятности
Привет! Меня зовут Кирилл Панин, я старший .NET разработчик в Altenar.
За 4 года работы с .NET мне приходилось решать различные задачи, связанные с вычислением вероятностей. Особенно это актуально сейчас, в проекте Altenar Data Feed. В спортивной индустрии дата-фиды строятся по единому принципу:
Есть лицензированные провайдеры, с которыми вы можете интегрироваться, чтобы в режиме реального времени получать со спортивных арен поток сигналов — события в матче (например, гол, угловой, удаление, травма), изменения темпа и состояния игры.
Получая поток таких сигналов, мы на своей стороне можем сформировать в фиде актуальную модель игры, и подмешать в нее собственные дополнительные параметры, которые могут формироваться на основе интереса конечных пользователей, экспертной оценки или автоматизированного анализа.
На основе этого математическое ядро — ключевой элемент такой системы, интерпретирует происходящее в матче и преобразует его в набор актуальных вероятностей-коэффициентов.

Но вообще, оценка вероятности исходов событий используется в разных сферах:
В метеопрогнозах оценивается вероятность дождя.
В доставке — вероятность успешного выполнения заказа.
В страховании жизни и здоровья оценивается вероятность наступления страхового случая, чтобы правильно рассчитать стоимость полиса.
Наша команда занимается тем же самым, только в спортивной аналитике: мы вычисляем вероятности на исходы тех или иных событий во время матча. Но как мы извлекаем из статистических данных конкретную вероятность?
Как из статистики получается вероятность: общий алгоритм
Первый шаг — определить ключевую характеристику события. Зная её, мы выдвинем гипотезу, каким может быть значение этой характеристики. И будем отталкиваться от этого предположения, вычисляя вероятности.
Разберем на простом и актуальном примере «привезут ли сегодня мой заказ», как в реальности можно «подбирать» верную гипотезу.

Например, для доставки это может быть ожидаемое количество заказов в день у курьера. В этом случае гипотеза может звучать так: «Курьер доставляет в среднем 6 заказов в день».
Далее проверяем эту гипотезу на соответствие статистическим данным. То есть сравнивая количество заказов в день с историей заказов, например, за год, мы сможем понять, соответствует ли наша гипотеза реальности. Добавляем дополнительные параметры: вес груза, расстояние, транспорт. Сопоставляем с нашей гипотезой.
Если гипотеза подтверждается, по ней можно вычислить вероятности интересующих нас событий — например, доставит ли курьер ещё 2 заказа до конца смены.
Если нет — корректируем гипотезу (например, меняем 6 на 4) и проверяем снова.
Важно понимать: выбор гипотезы — это не менее важная задача, чем вычисления, потому что сложность и точность всего алгоритма зависят от изначального предположения.
Вероятность событий в спорте
Вернемся к тому, что считаем мы в своей компании: вероятности спортивных событий — победа команды, очки в тайме и т.д.
В спорте гипотеза это как правило характеристика силы команды. Дальше везде буду писать про «силу команды», но на самом деле это та самая числовая характеристика, относительно которой будем строить гипотезу.
Для разных видов спорта сила команды определяется по-разному. Например, в футболе сила команды — это ожидаемое количество голов. То, сколько команда в среднем забивает за матч. Зная силы команд-соперников, мы можем оценить вероятность победы. Если у обеих команд одинаковое ожидаемое количество голов — допустим, по 2 — то вероятность победы у них равна, и вероятность ничьей при этом оказывается наибольшей.
Если во время матча мы получаем новую информацию — например, кто-то удалили с поля и команды играют в неравных составах, мы пересчитываем силу команд. Например, теперь у команды, играющей в большинстве, ожидается 4 гола, а у другой — 1.
Соответственно, изменяется и расклад по вероятностям: шансы на победу у домашней команды значительно возрастают.
Cила игроков в теннисе
Есть виды спорта, в которых сила команд не является такой очевидной характеристикой, как в футболе.
Например, в теннисе, сила команды характеризуется вероятностью выиграть очко в розыгрыше на своей подаче. Это не только сложно понять, но и сложно посчитать. Расскажу про наш опыт решения такой задачи и с какими трудностями нам пришлось столкнуться в процессе.
У нас была математическая модель, описывающая теннисный матч.
x— искомая сила команд (игроков)P— известные параметры матча (например, счёт).b— статистика по матчу, с которой мы сверяем результат.F— функции, которые по x и P моделируют ожидаемую статистику.
Перед нами встала задача найти способ решения системы уравнений с помощью .NET.
Но этот способ должен учитывать ряд особенностей:
Нет аналитического решения.
Из-за сложной структуры функции f эта система не имеет аналитического (точного) решения, которое можно выразить в виде формулы и получить решение за конечное число операций. Поэтому нам нужно использовать численные методы, чтобы получить приближённое решение с заданной точностью. На этом этапе у нас уже было представление о том, какие численные методы под задачу могут подойти.Непостоянное количество уравнений.
Количество уравнений в системе зависит от доступных в момент расчёта статистических данных. В одном случае мы имеем, скажем, два параметра — значит, два уравнения. В другом — шесть параметров, и система становится больше. Нужен метод, который гибко работает при разном числе уравнений.Строгие требования к качеству решения.
Конкретные критерии оценки решения я опишу чуть ниже, но уже на этом этапе понятно, что метод должен обеспечивать высокую точность и быстрое выполнение.
Свой метод или готовая библиотека
И вот мы начали искать способ решить задачу. Первый вопрос, который встал перед нами — реализовать численный метод самостоятельно или использовать готовую библиотечную реализацию.
У каждого подхода есть свои плюсы и минусы.
Собственное решение
Теоретически можно кастомизировать алгоритм под конкретную задачу.
Требуется значительное время на разработку и отладку
Есть вероятность допустить ошибку в реализации
Не факт, что оптимизация даст заметный прирост производительности
Готовое библиотечное решение
Можно быстро получить работающий результат
Математический алгоритм, скорее всего, реализован корректно
Может быть трудно адаптировать библиотеку под задачу из-за недостаточной документации
Настройка и интеграция могут занять время
Какой путь выбрать — зависит от специфики задачи. Если удаётся найти подходящую библиотеку, это предпочтительный вариант. Мы приняли решение: сначала ищем библиотечное решение. Если ни одно не подойдёт, будем реализовывать метод самостоятельно.
Обзор .NET-библиотек для численных методов
Прошерстив интернет в поисках популярных и актуальных библиотек, реализующих нужные нам численные методы, мы отобрали четыре варианта, которые подошли под нашу задачу.
Math.NET Numerics — библиотека с широкой функциональностью, предназначенная как для повседневных задач, так и для более серьёзных вычислений. Чаще всего используется для численных методов, компьютерной алгебры и цифровой обработки сигналов. Поддерживает векторы, матрицы, комплексные числа, вероятностные распределения и т.д.
Extreme Numerics (Numerics.NET) — коммерческая библиотека для построения научных, инженерных и финансовых приложений. Предлагает набор инструментов для статистики, анализа данных, регрессий и работы с многомерными структурами. Отличается высокой скоростью.
ALGLIB for C# (.NET) — библиотека с поддержкой пяти языков программирования, включая C#. Предоставляет инструменты для линейной алгебры, оптимизации, интерполяции, статистики и обработки данных. Активно развивается, есть форум поддержки. Официального GitHub-репозитория не найдено, но дистрибутив доступен на сайте разработчика.
Accord.NET — открытая библиотека, ориентированная на машинное обучение, анализ данных, статистику и теорию вероятности. Часто используется при построении систем распознавания, классификации и принятия решений. Имеет открытый исходный код и большое сообщество.
Как библиотеки интегрируются в код
Прежде чем сравнивать библиотеки по точности и скорости, давайте разберёмся, как они вообще работают с нашей системой уравнений — как они принимают её на вход и что мы должны передать.
Возьмем для примера ALGLIB, но стоит отметить, что у всех рассмотренных библиотек подход примерно одинаковый.
Использование библиотеки обычно происходит в три этапа:
Подготовка модели → Запуск вычислений → Получение результатов
public (double[], alglib.minlmreport) Calculate(
alglib.minlmstate modelState,
alglib.ndimensional_fvec systemEquations)
{
// Вычисление
alglib.minlmoptimize(modelState, systemEquations);
// Получение искомых значений и отчета
alglib.minlmresults(
modelState,
out var solution,
out var calculationReport);
return (solution, calculationReport);
}
public delegate void alglib.ndimensional_fvec(
double[] arguments,
double[] functions);Ключевой интерес для нас представляет этап вычислений. Здесь мы передаём в модель делегат — systemEquations. Это делегат внутреннего типа библиотеки, который в себе содержит всю логику вычисления функций из системы уравнений, то есть реализацию математической функции f(x, P).
Таким же способом работают и остальные библиотеки: мы формируем модель, передаём в неё описание нашей системы, запускаем решение и получаем выходные данные.
Это позволяет сравнивать их между собой уже по фиксированному набору критериев, не беспокоясь о принципиальных отличиях в структуре.
Критерии выбора: точность и скорость
После того как мы определились с набором библиотек, следующим шагом стало — сформулировать критерии оценки, по которым мы могли бы выбрать наилучшее решение. Эти критерии напрямую исходят из бизнес-требований к системе.
В нашей системе вероятности считаются для множества событий, и все они так или иначе зависят от силы команд. Соответственно, даже небольшие изменения значений силы могут существенно повлиять на расчитанные вероятности.
Это означает, что при вычислении силы коман�� мы должны быть максимально точны.
Кроме того, система должна работать в реальном времени, прямо во время матча. К примеру, если произошло событие — гол, удаление игрока или замена — мы сразу пересчитываем силу команд и связанные с ней вероятности. От этого зависит, насколько актуальные данные получает пользователь.
Следующим шагом мы попытались формализовать эти критерии — выразить их в числах, чтобы можно было применять их при тестах и сравнении.
Критерий №1: точность (относительная погрешность)
Чтобы понять, правильно ли библиотека рассчитывает силу команд, нужно было сравнить результат её вычислений с теми данными, в корректности которых мы уверены. Такие данные у нас были — они собраны на основе реальных матчей и охватывают широкий спектр ситуаций на поле.
На их основе были составлены тест-кейсы: каждый из них содержит входные параметры и эталонное решение, полученное вручную, с максимальной кастомизацией под конкретный матч и ситуацию. Это решение считается максимально точным.
Условие, которое должна удовлетворять библиотека: относительная погрешность результатов не должна превышать 10% по сравнению с эталонным решением.
Критерий №2: скорость (время выполнения)
Со скоростью всё проще: чем быстрее — тем лучше.
Но есть чёткая верхняя граница, обусловленная ограничениями системы и пользовательским ожиданием. Для той машины, на которой мы проводили тесты, время расчёта не должно превышать 1 секунду.
Сравнение методов
Мы примерно представляли какие численные методы нам подойдут. Все библиотечные реализации этих методов мы прогнали на одном наиболее стандартном тесте. Получили список методов, которые сошлись с результатом с допустимой погрешностью.
Библиотека – Метод | Относительная погрешность, % |
Accord – Бройден | 2.06 |
alglib.net – Бройден* | 6.96 |
alglib.net – Л-М** | 2.88 |
Numerics.Net – Пауэлл*** | 2.89 |
Math.Net – Бройден | 2.85 |
Это реализации алгоритмов Левенберга – Марквардта, Бройдена и Пауэлла
Далее мы прогнали эти методы по всем тестам и получили среднюю относительную погрешность.
Библиотека – Метод | Средняя | Максимальная относительная погрешность, % |
Accord – Бройден | 8.75 | – |
alglib.net – Бройден | 14.8 | 30.28 |
alglib.net – Л-М | 3.43 | 3.96 |
Numerics.Net – Пауэлл | 3.16 | 3.76 |
Math.Net – Бройден | 8.88 | – |
Тут мы смело отбросили один из методов библиотеки alglib, так как его средняя погрешность превысила допустимую.
Но на самом деле нам важна не столько средняя погрешность, сколько максимальная. И тут выясняется что пара методов Бройдена не могут найти решение для нескольких случаев.
Так у нас осталось только два метода, которые вычисляют с приемлемой точностью.
Оптимизация и финальный выбор
Для оставшихся двух методов мы написали бенчмарки — на том же наборе тестовых данных.
Библиотека – Метод | Время выполнения, мс | Время выполнения библиотечного кода, % |
alglib.net – Л-М | 1135 | 5.75 |
Numerics.Net – Пауэлл | 1033 | 9.96 |
В процессе замеров выяснилось, что оба метода выполняются медленнее одной секунды. То есть, несмотря на то, что они проходили по точности, но по скорости всё ещё не проходили.
На этом этапе мы начали думать, что делать дальше. Все основные численные методы уже были рассмотрены, но ни один из них полностью не соответствовал как требованиям по точности, так и требованиям по производительности.
Мы решили попробовать оптимизировать выполнение — чтобы добиться нужной скорости хотя бы для тех методов, которые дают необходимую точность.
В ходе анализа производительности мы наткнулись на интересное наблюдение:
медленно работал вовсе не библиотечный код. Основную часть времени занимало вызов и выполнение делегата, передаваемого в качестве системы уравнений.
Это означало, что именно наша реализация делегата systemEquations была «узким местом».
После оптимизации — переписав код, упрощая вычисления и устраняя лишние операции — нам удалось значительно сократить общее время выполнения и уложиться в требуемый лимит.
Библиотека – Метод | Время выполнения, мс | Время выполнения библиотечного кода, % |
alglib.net – Л-М | 569 | 11.47 |
Numerics.Net – Пауэлл | 504 | 20.41 |
Изначально мы планировали использовать Numerics.Net, так как она показала хорошие результаты. Однако позже выяснилось, что библиотека требует онлайн-проверку лицензионного ключа, а это противоречит правилам информационной безопасности в нашей компании.
В итоге финальный выбор пал на alglib.net — она показала достаточную точность, приемлемую производительность после оптимизации и соответствовала всем внутренним ограничениям проекта.
Выводы и рекомендации
В ходе нашей работы над задачей оценки вероятностей мы пришли к нескольким важным выводам, основанным как на теоретических, так и на практических аспектах:
Постановка задачи зачастую сложнее, чем её решение.
Одним из главных вызовов является формулировка гипотезы, на основе которой мы потом сможем считать вероятность. Это не всегда тривиально. Гипотеза должна быть не только пригодна для вычислений, но и сопровождаться доступом к статистическим данным, необходимым для её подтверждения.Реализовывать алгоритм вручную или использовать библиотеку?
Оптимальный подход — сначала попробовать использовать готовую библиотеку. Это экономит время и снижает риски ошибок. Только если не удаётся найти подходящую реализацию, стоит переходить к самостоятельной разработке. В нашем случае нам удалось найти подходящее библиотечное решение, но это бывает не всегда.Критерии выбора библиотеки могут быть неочевидны сразу.
Помимо точности и скорости, в нашем случае к критериям добавился фактор безопасности — способ интеграции с учётом политики ИБ. Это показатель того, что в реальных условиях появляются дополнительные ограничения, которые влияют на выбор инструмента.Не существует универсального способа оценки вероятностей.
Каждая задача уникальна. Иногда достаточно одного уравнения, которое можно решить аналитически. В других случаях — требуется система линейных ��ли нелинейных уравнений, которая решается численно.Поэтому важно придерживаться универсального подхода: выдвигаем гипотезу → проверяем её достоверность → рассчитываем вероятность на её основе.
Так можно будет построить устойчивый и надёжный алгоритм оценки вероятности практически для любого события — будь то прогноз погоды, успех доставки или счёт в матче по теннису.
