Files
blog/docs/maths/baes.md
Rustam 509cc2657a change layout
Математика -> maths
2024-09-24 23:20:54 +03:00

222 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Немного про Байесовскую статистику
## Задача
Представим, что у нас есть монета, честность которой нам неизвестна (если быть
точным, мы не знаем с каким шансом выпадает орёл, с каким — решка). Поэтому мы
бы хотели оценить вероятность $p$ — шанс выпадения орла[^1].
В [классической статистике](https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B0%D1%82%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0)
эта задача бы решалась бы так:
- Монета подбрасывается $n$ раз.
- Из них $m$ — количество выпавших орлов.
- Отношение $\frac{m}{n}$ будет оценкой $p$.
В [Байесовской
статистике](https://ru.wikipedia.org/wiki/%D0%91%D0%B0%D0%B9%D0%B5%D1%81%D0%BE%D0%B2%D1%81%D0%BA%D0%B0%D1%8F_%D1%81%D1%82%D0%B0%D1%82%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0)
подход иной:
1. Обозначим монету как [бернуллевскую случайную
величину](https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%91%D0%B5%D1%80%D0%BD%D1%83%D0%BB%D0%BB%D0%B8)
$\xi$ с параметром $\theta$, у которой $1$ — это выпадение орла, $0$ —
решки.
2. Предполагается априорное распределение $\pi(\theta)$ (т.е. распределение,
которое мы предполагаем, исходя из того, что нам известно о параметре
$\theta$), как правило, это [равномерное
распределение](https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%BF%D1%80%D0%B5%D1%80%D1%8B%D0%B2%D0%BD%D0%BE%D0%B5_%D1%80%D0%B0%D0%B2%D0%BD%D0%BE%D0%BC%D0%B5%D1%80%D0%BD%D0%BE%D0%B5_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5)
$U \left(0,1\right)$.
3. Монета подбрасывается.
4. Распределение $\theta$ уточняется по формуле[^2]:
$$\Large
\pi(\theta | \xi) = \frac{p(\xi|\theta)p(\theta)}
{\int\limits_{\Theta}p(\xi|\theta)p(\theta)d\theta}
$$
5. Повторить пункты 2-4, предполагая $\pi(\theta) = \pi(\theta|\xi)$
Тогда оценкой $\theta$ будет:
$$\Large
\hat \theta = \arg \max_\theta \pi ( \theta | \xi )
$$
Иначе говоря,
[мода](https://ru.wikipedia.org/wiki/%D0%9C%D0%BE%D0%B4%D0%B0_%28%D1%81%D1%82%D0%B0%D1%82%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0%29)
апостериорного распределения.
Мы, в качестве априорного распределения, взяли [Бета-распределения](https://ru.wikipedia.org/wiki/%D0%91%D0%B5%D1%82%D0%B0-%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5) $Beta(2,2)$. В
таком случае, если на $i$-ом шаге мы имеем:
$$\Large
\theta \sim Beta \left( \alpha_i, \beta_i \right)
$$
то апостериорное распределение будет:
$$\Large
Beta \left( \alpha_i, \beta_i \right) =
\begin{cases}
Beta \left( \alpha_i + 1, \beta_i \right), &\xi_i = 1 \\
Beta \left( \alpha_i, \beta_i + 1 \right), &\xi_i = 0 \\
\end{cases}
$$
Тогда не нужно интегрировать на каждом шаге, что существенно упрощает вычисления.
## Решение
Приведем решение на `python`.
### Библиотеки
Сначала нужно импортировать и настроить библиотеки:
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from tqdm import tqdm
plt.rcParams.update({'font.size': 14})
```
### Константы и функции
Обозначим константы:
- `p` — истинная вероятность выпадения орла.
- `NMODEL` — количество бросков монеты.
```python
p = 0.523
NMODEL = 7501
```
Введем функции:
- `beta` — объект для Бета-распределения
- `coin` — функция одиночного броска монеты
```python
from scipy.stats import beta
coin = lambda: np.random.binomial(n=1, p=p)
```
### Моделирование
В качестве априорного распределения тут используется Бета-распределение
$Beta(2,2)$. Это сделано потому, что расчет моды накладывает ограничение, что оба
параметра должны быть строго больше 1.
Мода расчитывается по формуле:
$$\Large
\text{Mode} = \frac{\alpha - 1}{\alpha + \beta - 2}
$$
```python
alphas = np.zeros(NMODEL)
betas = np.zeros(NMODEL)
alphas[0], betas[0] = 2,2
for i in tqdm(range(1, NMODEL)):
A = coin()
if A == 0:
betas[i] = 1
else:
alphas[i] = 1
betas = np.cumsum(betas)
alphas = np.cumsum(alphas)
Es = (alphas - 1) / (alphas + betas - 2)
```
### График
#### Мода
Построим график зависимости моды от количества бросков.
```python
fig, ax = plt.subplots(1, 1, figsize=(10,8), dpi=80)
sns.lineplot(x=np.arange(NMODEL),
y=Es,
ax=ax,
label=r"arg$\max_p \; f(p|\mathbb{X})$", )
sns.lineplot(x=np.arange(NMODEL),
y=p,
ax=ax,
label=r"Истинное $p = {:.3f}$".format(p))
ax.grid()
ax.set(ylabel=r"$E(p|\mathbb{X})$", xlabel=r"$i$");
```
![mode.jpg](assets/baes/mode.jpg)
Гифка
Сделаем гифку на тему. Сначала нужно импортировать библиотеку `imageio` и зададим
шаг `STEP` (так как, потом нужно будет сохранять каждый график в опертивной
памяти, что проблематично при большом `NMODEL`):
```python
import imageio
STEP = NMODEL//150
```
После, создадим список функций плотности вероятности:
```python
pi = []
for i in tqdm(range(0, NMODEL)):
pi.append(beta(alphas[i], betas[i]))
```
И по ним сделаем gif-изображение:
```python
def create_frame(i):
fig, ax = plt.subplots(1, 1, figsize=(10,8), dpi=80)
x = np.linspace(0,1,500)
y = pi[i].pdf(x)
i_max = np.argmax(y)
x_max = x[i_max]
y_max = y[i_max]
ax.grid()
ax.plot(x,y, label=r"$f(p|\mathbb{X})$")
ax.axvline(x = p, color = 'red', label = f"Истинное $p={p}$")
plt.scatter([x_max],
[y_max],
color="green",
marker="o",
label=r"Мода $f(p|\mathbb{X})$")
plt.xlim([0,1])
plt.xlabel('x', fontsize = 14)
plt.ylim([0,100])
plt.ylabel(r'$f(p|\mathbb{X})$', fontsize = 14)
plt.title(r'Распределение p, $i={}$'.format(i+1),
fontsize=14)
ax.legend()
plt.savefig(f'./img/img_{i:04d}.png',
transparent = False,
facecolor = 'white'
)
plt.close()
for i in tqdm(range(0, NMODEL, STEP)):
create_frame(i)
frames = []
for i in tqdm(range(0, NMODEL, STEP)):
image = imageio.v2.imread(f'./img/img_{i:04d}.png')
frames.append(image)
imageio.mimsave('./distributions.gif',
frames,
fps = 30)
```
Результат:
![gif](assets/baes/video.gif)
[^1]: Понятно, что вероятность выпадения решки равна $1 - p$
[^2]: $p(\theta|\xi)$ -- это функция правдоподобия.