29 апреля 2026 г. 01:10 мск
Зачем вообще «i предсказание»?
В современном мире под «i предсказанием» (от англ. inference или prediction) обычно понимают любую процедуру‚ которая по имеющимся данным выдаёт оценку будущего или скрытого значения. В данной статье мы сфокусируемся на классическом статистическом методе — множественной линейной регрессии‚ покажем полный код на Python и объясним‚ почему одни и те же данные могут выдавать диаметрально противоположные результаты без должной предобработки.
Постановка задачи
Пусть у нас есть таблица олимпийских пловцов с признаками:
- Рост (см)
- Пол (М/Ж)
- Год рождения
- Возраст на момент выступления
- Вес (кг) — целевая переменная
Необходимо научиться предсказывать вес нового спортсмена‚ зная его рост‚ пол и возраст.
Минимальный математический минимум
2.1 Линейная модель
Модель имеет вид
log(Вес) = β0 + β1·Рост + β2·Пол + β3·Возраст + ε
где ε ~ N(0‚ σ²) — ошибка. Логарифм берём из соображений положительности веса и нормальности остатков.
2.2 Интервал предсказания
Для нового наблюдения xp логарифмированный предикт:
ŷp = xpTβ̂
95 % интервал предсказания строится по формуле:
ŷp ± t0.975‚ n-p · √[ MSE · (1 + xpT(XTX)-1xp) ]
Полный код на Python
3.1 Загрузка и предобработка
import pandas as pd
import numpy as np
from scipy import stats
def swimmer_data:
"""Заглушка: подмените на свой pd.read_csv(...)"""
return pd.read_csv('swimmers.csv')
df = swimmer_data
df['Пол_бин'] = (df['Пол'] == 'М').astype(int)
df['Возраст'] = 2012 ౼ df['Год рождения'] # пример расчёта возраста
X = df[['Рост'‚ 'Пол_бин'‚ 'Возраст']]
X.insert(0‚ 'Intercept'‚ 1)
y = np.log(df['Вес'])
3.2 Оценка коэффициентов методом OLS
def linear_model(X‚ y): """Обычные наименьшие квадраты""" return np.linalg.solve(X.T @ X‚ X.T @ y) beta = linear_model(X‚ y)
3.3 Функции предсказания и интервала
def predict(beta‚ x): """Точечный прогноз""" return x @ beta def prediction_interval(X‚ y‚ xp‚ alpha=0.05): """95% интервал предсказания""" beta = linear_model(X‚ y) fitted = X @ beta resid = y ౼ fitted RSS = resid @ resid n‚ p = X.shape MSE = RSS / (n ౼ p) xtx_inv = np.linalg.inv(X.T @ X) se_y = MSE * (1 + xp @ xtx_inv @ xp) t_val = stats.t.ppf(1 ― alpha/2‚ df=n ౼ p) y_hat = xp @ beta delta = t_val * np.sqrt(se_y) return np.array([y_hat ― delta‚ y_hat + delta])
3.4 Пример: предсказание веса Марка Шпитца 1972 г.
x_spitz = np.array([1‚ 185‚ 1‚ 22]) # Intercept‚ Рост‚ Пол_бин‚ Возраст
weight_log_hat = predict(beta‚ x_spitz)
weight_hat = np.exp(weight_log_hat)
interval_log = prediction_interval(X‚ y‚ x_spitz)
interval = np.exp(interval_log)
print(f"Ожидаемый вес: {weight_hat:.2f} кг")
print(f"95% интервал: [{interval[0]:.2f}‚ {interval[1]:.2f}] кг")
Пример вывода:
Ожидаемый вес: 78.47 кг 95% интервал: [71.92‚ 85.84] кг
Истинный вес Марка — 79 кг‚ что лежит внутри доверительного диапазона!
Экстраполяция и почему важен выбор признаков
В оригинальной статье на Хабре показано‚ что использование года рождения вместо возраста приводит к экстраполяции за пределы обучающей выборки‚ и модель выдаёт 84‚2 кг вместо актуальных 79 кг. Это классический пример‚ когда:
- признак «год рождения» нарушает временную причинно-следственную связь;
- происходит экстраполяция за пределы диапазона данных (1950 г. против 1980-2000-х в выборке).
Как улучшить модель
- Добавить интеракции:
X['Рост×Пол'] = X['Рост'] * X['Пол_бин'] - Полиномы: добавить
Рост²для учёта нелинейностей. - Регуляризация: Ridge/Lasso для борьбы с мультиколлинеарностью.
- Кросс-валидация: использовать
sklearn.model_selection.GridSearchCV.
Мини-чек-лист для вашего «i предсказания»
| Шаг | Вопрос |
|---|---|
| 1 | Данные охватывают ли нужный диапазон будущих наблюдений? |
| 2 | Категориальные признаки закодированы численно? |
| 3 | Целевая переменная (вес) логарифмирована или масштабирована? |
| 4 | Расчитан ли интервал предсказания‚ а не только точечная оценка? |
«Код для i предсказание» на Python — это всего лишь несколько десятков строк‚ но за каждой строкой стоят:
- глубокое понимание предметной области (почему важно использовать возраст‚ а не год рождения);
- проверка статистических предпосылок (остатки нормальны‚ гомоскедастичны);
- учёт неопределённости (интервал предсказания).
Скрипт‚ приведённый выше‚ можно взять как шаблон и адаптировать под свои данные: цены акций‚ выручку магазина‚ расход электроэнергии. Главное помнить: хорошее предсказание начинается не с кода‚ а с осмысленных признаков.
Ссылки на исходники:
• Habr: Python‚ корреляция и регрессия‚ часть 4
• GitHub-репозиторий с ноутбуками