← Назад к вопросам
Что такое 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 это твой выбор!