В одном из моих последних проектов мы столкнулись с проблемой прогнозирования с очень ограниченными данными. На сбор каждого набора данных у специалиста уходило несколько часов, и результаты не всегда были успешными.
Поэтому мы искали инструмент для решения этих задач, поскольку искусственный интеллект невозможно было обучить на ограниченном количестве необработанных данных. Таким образом, мы обратились к статистическим подходам, а именно к байесовской статистике с помощью пакета Python PyMC. Я объясню теорию, на которой он основан, и опишу ее на примере обнаружения мошенничества с игральными кубиками.
Байесовская статистика
Байесовская статистика — это раздел статистики, который использует теорему Байеса для обновления наших представлений о вероятности гипотезы по мере поступления новых данных. Теорема Байеса гласит, что вероятность гипотезы (H) с учетом некоторых данных (D) равна вероятности данных с учетом гипотезы (D|H), умноженной на априорную вероятность гипотезы (p(H)), деленную на общую вероятность данных (p(D)). Это позволяет нам обновлять наши представления о гипотезе по мере поступления новых данных, а не полагаться только на имеющиеся данные.
Одним из самых популярных пакетов Python для реализации байесовской статистики является PyMC. PyMC — это мощный пакет, который позволяет пользователям легко определять, подбирать и анализировать байесовские модели. Он включает в себя множество встроенных распределений, таких как нормальное, биномиальное и распределение Пуассона, а также множество выборок, таких как Metropolis-Hastings и No-U-Turn Sampler (NUTS). PyMC также включает в себя множество удобных инструментов для диагностики и визуализации результатов вашей модели.
При использовании PyMC важно помнить, что вы должны думать о проблеме с точки зрения распределения вероятностей, а не с точки зрения точечных оценок.
К этому нужно привыкнуть, но это очень важно для точного моделирования сложных систем. Каждый результат, который вы получаете, имеет вероятность. Поэтому доверительные интервалы являются важной частью любых результатов, полученных с помощью PyMC. Это преимущество по сравнению с нейронными сетями.
В байесовской статистике используются термины априорная вероятность и апостериорная вероятность. Априорная вероятность — это распределение вероятностей до того, как были просмотрены какие-либо данные. По сути, он показывает возможный диапазон исходов для всех предполагаемых параметров, полученных путем простого угадывания. Это обозначается как p(H). Апостериорная вероятность, однако, представляет собой распределение с учетом данных, т. е. (D|H), умноженное на p(H).
Бросание поддельного игрального кубика
В качестве примера мы используем PyMC для моделирования бросков игрального кубика.
Мы хотим выяснить, был ли подделан игральный кубик или его можно использовать. Мы задаем, что вероятность выпадения каждой грани (1-6) моделируется распределением Дирихле с равной вероятностью для хорошего игрального кубика.
Мы также предполагаем, что наблюдаемые данные, являющиеся результатом броска игрального кубика, следуют категориальному распределению с параметром p, то есть предполагаемой вероятностью каждой грани.
В отсутствие каких-либо данных это априорная вероятность. Затем мы проводим анализ модели с помощью выборки Марковской цепи Монте-Карло (MCMC) и используем выборки для вывода вероятностей каждого лица, т. е. апостериорной вероятности. Поддельный кубик дает 6 в 7 из 12 бросков — так что это действительно очевидно.
Вот пример кода:
import numpy as np
import pymc as pm
from matplotlib import pyplot as plt
# Определение игрального кубика и подготовка данных
tampered_dice = [1 / 12, 1 / 12, 1 / 12, 1 / 12, 1 / 12, 7 / 12]
good_dice = [1 / 6] * 6
num_rolls = 10000
x = list(range(0, num_rolls, 1))
for idx, dice in enumerate([tampered_dice, good_dice]):
# генерирование данные о бросках костей
p = np.array(dice)
dice_rolls = np.random.choice(6, size=num_rolls, p=p)
# Определение модели игрального кубика
with pm.Model() as dice_model:
p = pm.Dirichlet("p", a=np.ones(6))
# Определение вероятности
face = pm.Categorical("face", p=p, observed=dice_rolls)
# делаем вывод на основе данных
trace = pm.sample(draws=100, tune=100, chains=2)
# выборочные данные, полученные до и после получения данных
prior_predictive = pm.sample_prior_predictive()
post_pred = pm.sample_posterior_predictive(trace)
# представление предварительных прогнозов
fig, ax = plt.subplots()
ax.hist(prior_predictive.observed_data.face)
plt.xlabel("Die face")
plt.ylabel("Occurences in 10k rolls.")
if idx == 0:
plt.title("Tampered dice")
else:
plt.title("Good dice")
plt.savefig(f"prior_predictive_{idx}.png", dpi=100)
plt.show()
# представление апостериорных прогнозов
trace.extend(post_pred)
fig, ax = plt.subplots()
ax.hist(trace.observed_data.face)
plt.xlabel("Die face")
plt.ylabel("Occurences in 10k rolls.")
if idx == 0:
plt.title("Tampered dice")
else:
plt.title("Good dice")
plt.savefig(f"posterior_predictive_{idx}.png", dpi=100)
plt.show()
# рассчет ожидаемой вероятности выпадения честного игрального кубика
expected_probs = np.ones(6) / 6
# вычисляем разницу между апостериорными и ожидаемыми вероятностями
prob_diff = np.abs(trace.posterior.p - expected_probs)
# рассчет среднго значения и стандартного отклонения разницы
mean_diff = np.mean(prob_diff, axis=0)
std_diff = np.std(prob_diff, axis=0)
# установить порог для разницы
threshold = 0.05
# проверить, превышает ли разница между вычисленными вероятностями и ожидаемыми вероятностями пороговое значение
tampered = mean_diff > threshold
if tampered.any():
print("Dice may have been tampered with.")
else:
print("Dice does not seem to have been tampered with.")
После запуска, программа проверяет, находятся ли грани кубика в пределах 5 % от допустимого отклонения от идеального кубика.
Вероятно, ваш обычный домашний кубик можно считать подделанным с помощью этого кода, потому что грань №1 тяжелее, чем грань №6. В результате чего грань №6 появляется в среднем чаще, чем грань №1. Для априорной вероятности я выбрал 100 розыгрышей. Розыгрыш — это число угадываний, которые программа делает для получения потенциальных параметров модели. Рекомендуется использовать большие значения, например, 1000, чтобы обеспечить достаточную степень детализации распределения вероятностей.
Почему PyMC?
Итак, каковы преимущества и недостатки PyMC?
PyMC — это мощный пакет, который позволяет пользователям легко определять, подбирать и анализировать модели. Он предоставляет множество встроенных распределений и выборок, подходящих для широкого спектра моделей.
PyMC также очень гибок и может работать со сложными моделями. Однако PyMC — это библиотека вероятностного программирования, к которой нужно привыкнуть. Важно понимать концепции распределения вероятностей и байесовской статистики. PyMC может потребовать значительных вычислительных ресурсов, особенно для больших и сложных моделей, и может не подходить для приложений, работающих в режиме реального времени или для больших наборов данных. Тем более, что PyMC построен на языке Python. Байесовские методы являются мощным инструментом для анализа данных, а PyMC позволяет легко реализовать эти методы в Python. Однако PyMC гораздо более громоздкий и не так хорошо документирован, как Tensorflow, но, опять же, Tensorflow является текущим стандартом.
Альтернативами PyMC с другими требованиями и преимуществами являются:
Stan: Написано на C++ и поэтому работает быстрее, чем PyMC, для больших и сложных моделей.
JAGS: Написано на C++
Edward: Построен на основе TensorFlow, что позволяет использовать модели глубокого обучения. Полезно для байесовских задач глубокого обучения.
Соответствующие приложения можно найти в вероятностном прогнозировании, типе прогнозирования, который предоставляет диапазон возможных результатов, а не одну точечную оценку. Некоторые примеры включают прогнозирование погоды, финансовое прогнозирование и наиболее актуальное в настоящее время в Европе прогнозирование энергетики.
Иногда нейронные сети и глубокое обучение дают результаты, которые появляются как по волшебству. Наиболее яркими примерами на данный момент являются ChatGPT и MidJourney. Как они достигают своих результатов, понятно лишь отчасти.
Байесовская статистика требует от нас размышлений о модели, лежащей в основе наблюдаемых данных, и, таким образом, более глубоко понять проблему. Хотя вероятностные подходы не так мощны, как искусственный интеллект, они могут помочь нам подготовить данные и установить требования для ИИ. Более глубокое понимание проблемы часто является ключевым преимуществом.
Заключение
PyMC — это интересный инструмент в вашем наборе инструментов.
Он использует байесовскую статистику для мощного анализа данных, предоставляя специалисту по анализу данных или инженеру возможности для тонкой настройки модели и поиска наилучшего представления для наблюдаемых данных.
PyMC может быть не таким удобным и мощным, как нейронные сети или подходы глубокого обучения в искусственном интеллекте, но он помогает человеку лучше понять поставленную задачу. Кроме того, он дает диапазон результатов с различными вероятностями, а не точечную оценку. Все это делает PyMC интересным инструментом.