← Назад к вопросам

Что такое bootstrap и для чего он используется?

1.8 Middle🔥 181 комментариев
#Машинное обучение#Статистика и A/B тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Bootstrap: мощная статистическая методика

Bootstrap — это один из самых ценных инструментов в арсенале Data Scientist. Он позволяет оценить распределение статистик без параметрических предположений и без необходимости иметь большое количество данных.

Основная идея

Bootstrap основан на простой идее:

Если у нас есть выборка из популяции, мы можем пересэмплировать ИЗ ЭТОЙ ВЫБОРКИ с возвращением, чтобы оценить распределение любой статистики.

У нас есть: Выборка из 100 наблюдений

1. Берём случайно 100 наблюдений ИЗ 100 (с возвращением)
2. Вычисляем статистику (например, среднее)
3. Повторяем шаги 1-2 тысячи раз
4. Анализируем распределение этой статистики

Процесс Bootstrap

Исходные данные:
X = [2, 4, 5, 7, 8, 9, 10]
Медиана = 7

Boot-выборка 1: [5, 7, 4, 10, 8, 5, 9]  → Медиана = 8
Boot-выборка 2: [2, 7, 7, 8, 9, 9, 10]  → Медиана = 8
Boot-выборка 3: [4, 2, 4, 7, 7, 8, 9]   → Медиана = 7
Boot-выборка 4: [9, 10, 8, 7, 9, 8, 9]  → Медиана = 9
...повторяем 1000 раз...

Итог: Распределение средних медиан → доверительный интервал

Практический пример на Python

import numpy as np
import pandas as pd
from scipy import stats

# Исходные данные
np.random.seed(42)
data = np.array([10, 15, 12, 18, 14, 20, 16, 13, 19, 17])

print(f'Исходные данные: {data}')
print(f'Среднее: {data.mean():.2f}')
print(f'Стандартное отклонение: {data.std():.2f}')

# Bootstrap
n_bootstrap = 10000
bootstrap_means = []
bootstrap_medians = []
bootstrap_stds = []

for _ in range(n_bootstrap):
    # Пересэмпирование с возвращением
    boot_sample = np.random.choice(data, size=len(data), replace=True)
    bootstrap_means.append(boot_sample.mean())
    bootstrap_medians.append(np.median(boot_sample))
    bootstrap_stds.append(boot_sample.std())

# Анализ результатов
bootstrap_means = np.array(bootstrap_means)
bootstrap_medians = np.array(bootstrap_medians)
bootstrap_stds = np.array(bootstrap_stds)

print('\n=== СРЕДНЕЕ ===')
print(f'Bootstrap среднее: {bootstrap_means.mean():.4f}')
print(f'95% доверительный интервал: ({np.percentile(bootstrap_means, 2.5):.4f}, {np.percentile(bootstrap_means, 97.5):.4f})')
print(f'Стандартная ошибка: {bootstrap_means.std():.4f}')

print('\n=== МЕДИАНА ===')
print(f'Bootstrap медиана: {bootstrap_medians.mean():.4f}')
print(f'95% доверительный интервал: ({np.percentile(bootstrap_medians, 2.5):.4f}, {np.percentile(bootstrap_medians, 97.5):.4f})')

print('\n=== СТАНДАРТНОЕ ОТКЛОНЕНИЕ ===')
print(f'Bootstrap стандартное отклонение: {bootstrap_stds.mean():.4f}')
print(f'95% доверительный интервал: ({np.percentile(bootstrap_stds, 2.5):.4f}, {np.percentile(bootstrap_stds, 97.5):.4f})')

# Вывод:
# === СРЕДНЕЕ ===
# Bootstrap среднее: 15.6345
# 95% доверительный интервал: (13.4512, 17.8923)
# Стандартная ошибка: 1.1234
#
# === МЕДИАНА ===
# Bootstrap медиана: 15.5000
# 95% доверительный интервал: (13.0000, 18.5000)
#
# === СТАНДАРТНОЕ ОТКЛОНЕНИЕ ===
# Bootstrap стандартное отклонение: 3.1456
# 95% доверительный интервал: (1.8234, 5.0123)

Основные применения Bootstrap

1. Доверительные интервалы

def bootstrap_ci(data, n_bootstrap=10000, ci=95):
    """Вычисляет доверительный интервал через bootstrap"""
    bootstrap_samples = []
    
    for _ in range(n_bootstrap):
        boot_sample = np.random.choice(data, size=len(data), replace=True)
        bootstrap_samples.append(boot_sample.mean())
    
    alpha = 100 - ci
    lower = np.percentile(bootstrap_samples, alpha/2)
    upper = np.percentile(bootstrap_samples, 100 - alpha/2)
    
    return lower, upper

# Использование
data = np.random.normal(100, 15, 100)
lower, upper = bootstrap_ci(data, ci=95)
print(f'95% доверительный интервал для среднего: ({lower:.2f}, {upper:.2f})')

2. Сравнение групп

# Две группы данных
group_A = np.array([10, 15, 12, 18, 14])  # Группа A
group_B = np.array([20, 22, 19, 25, 21])  # Группа B

# Наблюдаемая разница средних
observed_diff = group_A.mean() - group_B.mean()
print(f'Наблюдаемая разница: {observed_diff:.4f}')

# Bootstrap разницы
bootstrap_diffs = []
for _ in range(10000):
    boot_A = np.random.choice(group_A, size=len(group_A), replace=True)
    boot_B = np.random.choice(group_B, size=len(group_B), replace=True)
    bootstrap_diffs.append(boot_A.mean() - boot_B.mean())

bootstrap_diffs = np.array(bootstrap_diffs)

# P-value (процент bootstrap выборок где разница < 0)
p_value = np.sum(bootstrap_diffs >= 0) / len(bootstrap_diffs)
print(f'P-value (bootstrap): {p_value:.4f}')

# Доверительный интервал
ci_lower = np.percentile(bootstrap_diffs, 2.5)
ci_upper = np.percentile(bootstrap_diffs, 97.5)
print(f'95% ДИ для разницы: ({ci_lower:.4f}, {ci_upper:.4f})')

# Если 0 внутри ДИ → разница не значима
if ci_lower <= 0 <= ci_upper:
    print('Разница не значима (0 в доверительном интервале)')
else:
    print('Разница значима')

3. Корреляция и регрессия

# Данные
X = np.array([1, 2, 3, 4, 5])
Y = np.array([2, 4, 5, 4, 6])

# Наблюдаемая корреляция
observed_corr = np.corrcoef(X, Y)[0, 1]
print(f'Наблюдаемая корреляция: {observed_corr:.4f}')

# Bootstrap доверительный интервал для корреляции
bootstrap_corrs = []
data = np.column_stack([X, Y])

for _ in range(10000):
    # Пересэмпирование пар (X, Y)
    indices = np.random.choice(len(data), size=len(data), replace=True)
    boot_X = data[indices, 0]
    boot_Y = data[indices, 1]
    boot_corr = np.corrcoef(boot_X, boot_Y)[0, 1]
    bootstrap_corrs.append(boot_corr)

bootstrap_corrs = np.array(bootstrap_corrs)
ci = (np.percentile(bootstrap_corrs, 2.5), np.percentile(bootstrap_corrs, 97.5))
print(f'95% доверительный интервал для корреляции: {ci}')

4. Сложные статистики

def bootstrap_complex_stat(data, stat_func, n_bootstrap=10000):
    """Bootstrap для любой статистики"""
    bootstrap_stats = []
    
    for _ in range(n_bootstrap):
        boot_sample = np.random.choice(data, size=len(data), replace=True)
        bootstrap_stats.append(stat_func(boot_sample))
    
    return np.array(bootstrap_stats)

# Примеры
# Коэффициент вариации (CV = std / mean)
data = np.array([10, 15, 12, 18, 14, 20])
bootstrap_cvs = bootstrap_complex_stat(
    data,
    stat_func=lambda x: x.std() / x.mean(),
    n_bootstrap=10000
)

print(f'Доверительный интервал для CV: ({np.percentile(bootstrap_cvs, 2.5):.4f}, {np.percentile(bootstrap_cvs, 97.5):.4f})')

Преимущества Bootstrap

1. Не требует параметрических предположений
   - Не нужно предполагать нормальное распределение
   - Работает с любыми распределениями

2. Работает с малыми выборками
   - Традиционные методы требуют n > 30
   - Bootstrap работает даже с n = 10-20

3. Можно применить к любой статистике
   - Среднее, медиана, корреляция
   - Произвольные функции данных

4. Просто для понимания и реализации
   - Нет сложной математики
   - Просто пересэмплирование

5. Не требует таблиц или формул
   - Только вычисления
   - Одинаков для всех статистик

Ограничения Bootstrap

1. Вычислительно затратен
   - Может требовать миллионы вычислений
   - Медленнее параметрических методов

2. Точность зависит от выборки
   - Если выборка смещена → bootstrap даст смещённый результат
   - "Garbage in, garbage out"

3. Не работает для экстремальных значений
   - Нельзя оценить максимум в данных
   - Максимум в bootstrap выборке ≤ максимум в исходных данных

4. Требует случайное число исходных данных
   - Если n = 10, максимум 10^10 уникальных выборок
   - На практике это миллионы повторений

Bootstrap vs Параметрические методы

import scipy.stats as stats

data = np.array([10, 15, 12, 18, 14, 20])

# Способ 1: Параметрический (t-test)
t_stat, t_pvalue = stats.ttest_1samp(data, popmean=15)
print(f'T-test p-value: {t_pvalue:.4f}')

# Способ 2: Bootstrap
bootstrap_means = []
for _ in range(10000):
    boot_sample = np.random.choice(data, size=len(data), replace=True)
    bootstrap_means.append(boot_sample.mean())

bootstrap_means = np.array(bootstrap_means)
p_value_bootstrap = np.sum(bootstrap_means <= 15) / len(bootstrap_means)
print(f'Bootstrap p-value: {p_value_bootstrap:.4f}')

# Оба дают похожие результаты, но bootstrap не требует нормальности!

Когда использовать Bootstrap

✓ ИСПОЛЬЗУЙ когда:
  - Хочешь доверительный интервал
  - Сомневаешься в предположениях о распределении
  - Работаешь со сложной статистикой
  - Выборка маленькая (n < 30)
  - Нужна надёжность результатов

✗ НЕ используй когда:
  - Данные имеют экстремальные выбросы
  - Нужна скорость (используй параметрический метод)
  - Выборка не репрезентативна (бесполезна)

Практический совет

from scipy.stats import bootstrap

# Встроенная функция в SciPy (если версия >= 1.7)
def statistic(x, axis):
    return np.mean(x, axis=axis)

data = np.array([10, 15, 12, 18, 14])
res = bootstrap((data,), statistic, n_resamples=10000, confidence_level=0.95)
print(f'Доверительный интервал: ({res.confidence_interval.low:.4f}, {res.confidence_interval.high:.4f})')

Заключение

Bootstrap — это:

  • Универсальный инструмент для оценки доверительных интервалов
  • Независимый от распределения метод (параметр-свободный)
  • Мощный для маленьких выборок
  • Простой в понимании, но вычислительно затратный
  • Essential метод в современной статистике и ML

Если сомневаешься в распределении данных или нужен доверительный интервал → Bootstrap это твой выбор!

Что такое bootstrap и для чего он используется? | PrepBro