🔴 Сложный ⏱️ 50 минут

Линейная регрессия

📋 Содержание урока

Линейная регрессия

Девять уроков подряд ты разбирался с фундаментом: что такое машинное обучение вообще, чем supervised отличается от unsupervised, что такое переобучение, как честно делить данные на train, validation и test, зачем нужна кросс-валидация, какими метриками измерять качество классификатора, как устроена ROC-кривая и confusion matrix. Это была необходимая, но абстрактная подготовка — правила игры без единого реального игрока на поле. Начиная с этого урока абстракция заканчивается: перед тобой первая настоящая модель машинного обучения, которую ты обучишь, оценишь и научишься интерпретировать от начала до конца.

Хорошая новость в том, что математика этой модели тебе уже знакома. В уроке 249 ты выводил формулы метода наименьших квадратов, доказывал нормальные уравнения и разбирался с коэффициентом детерминации $R^2$ — это был статистический регрессионный анализ, инструмент для объяснения данных и проверки гипотез о связи между переменными. Линейная регрессия как модель машинного обучения использует ровно ту же математику, но меняет постановку задачи: вместо вопроса «насколько статистически значима связь между $x$ и $y$?» ты спрашиваешь «как построить модель, которая как можно точнее предсказывает $y$ по новым, ещё не виденным значениям $x$?». Смещение с объяснения на предсказание — это и есть переход от статистики к машинному обучению, и линейная регрессия — самый прозрачный пример этого перехода, потому что под капотом у неё нет ничего, кроме уже знакомой тебе формулы МНК.

Второе, что тебе уже знакомо, — это градиентный спуск из урока 285. Там ты разбирал его как универсальный алгоритм оптимизации: формулу шага, роль скорости обучения, поведение на выпуклых и невыпуклых функциях потерь. Линейная регрессия — это первая модель курса, где градиентный спуск встречается со своим самым простым и самым наглядным противником: точным аналитическим решением. У линейной регрессии, в отличие от подавляющего большинства моделей, которые ты изучишь дальше — логистической регрессии, нейросетей, градиентного бустинга, — есть формула, которая находит оптимальные веса напрямую, без единой итерации. Это редкий случай, когда можно взять один и тот же датасет, решить задачу обучения двумя принципиально разными способами и увидеть, что они сходятся к одному и тому же ответу.

Весь этот урок построен вокруг одного сквозного примера — предсказания цены квартиры по её площади и числу комнат. Это намеренно приземлённая, но при этом абсолютно реалистичная задача: агентства недвижимости, банки при оценке залога, сервисы вроде ЦИАН и Domclick строят именно такие модели, только с гораздо большим числом признаков. К концу урока ты пройдёшь весь путь: от сырых чисел до обученной модели, от ручного расчёта весов по формуле до вызова model.fit(), от абстрактного коэффициента $w_1$ до содержательного «каждый дополнительный квадратный метр добавляет к цене такую-то сумму».

История

Слово «регрессия» появилось в статистике благодаря Фрэнсису Гальтону — английскому учёному XIX века, двоюродному брату Чарльза Дарвина, который в 1880-х годах изучал наследование роста: измерял рост родителей и их взрослых детей и заметил закономерность, показавшуюся ему поначалу парадоксальной. Дети очень высоких родителей в среднем оказывались чуть ниже своих родителей, а дети очень низких родителей — чуть выше: рост как бы «сползал», регрессировал к среднему значению по популяции. Гальтон назвал этот эффект «регрессией к посредственности» (regression to mediocrity), и хотя современный смысл термина в машинном обучении не имеет прямого отношения к «сползанию к среднему», само слово «регрессия» закрепилось за любой моделью, предсказывающей непрерывную числовую величину, именно с лёгкой руки Гальтона.

Математический аппарат для точного проведения прямой линии через облако точек появился на несколько десятилетий раньше самого Гальтона, и его придумали два человека почти одновременно: французский математик Адриен-Мари Лежандр опубликовал метод наименьших квадратов в 1805 году, а Карл Фридрих Гаусс годом позже заявил, что пользовался этим же методом ещё в 1795 году — для расчёта орбиты астероида Церера по нескольким разрозненным астрономическим наблюдениям. Спор о приоритете между Лежандром и Гауссом так и не получил однозначного решения и до сих пор упоминается в учебниках как классический пример независимого открытия одной и той же идеи. Коллега и последователь Гальтона, Карл Пирсон, довёл идею регрессии и МНК до строгой статистической формы на рубеже XIX и XX веков — именно Пирсон формализовал коэффициент корреляции и заложил основы статистического регрессионного анализа, который ты уже видел в уроке 249.

Целый век после Пирсона линейная регрессия оставалась инструментом статистиков, экономистов и биологов — способом проверить гипотезу о связи между двумя измеримыми величинами. Превращение регрессии в алгоритм машинного обучения произошло во второй половине XX века, когда исследователи вроде Артура Сэмюэла и позже создатели первых статистических пакетов и библиотек начали смотреть на ту же самую формулу МНК не как на способ объяснить прошлые данные, а как на способ построить модель, которая будет предсказывать будущее по новым, ещё не виденным примерам. Сегодня линейная регрессия — это одновременно и старейший, и один из самых часто используемых алгоритмов в арсенале любого специалиста по анализу данных (data science): её вызывают одной строчкой sklearn.linear_model.LinearRegression(), но за этой строчкой стоит математика, которой больше двухсот лет.

Модель линейной регрессии: от точки до гиперплоскости

Интуиция

В уроке 249 ты работал с моделью $\hat y = b_0 + b_1 x$ — прямой линией на плоскости, которая зависит от одного-единственного признака $x$. В реальных задачах предсказание почти никогда не опирается только на один признак: цена квартиры зависит не только от площади, но и от числа комнат, этажа, района, года постройки. Линейная регрессия как ML-модель обобщает ту же самую идею на произвольное число признаков: вместо прямой на плоскости или прямой линии в пространстве ты ищешь гиперплоскость в многомерном пространстве признаков — объект, который при одном признаке превращается в привычную прямую, при двух признаках становится плоскостью, а при большем числе признаков перестаёт визуализироваться, но остаётся всё той же линейной комбинацией.

Ключевая смена оптики по сравнению с уроком 249 — терминологическая, но важная. В статистике коэффициенты $b_0, b_1, \ldots$ называют оценками параметров модели, полученными по выборке. В машинном обучении те же самые числа называют весами модели (weights) и обозначают буквой $w$: $w_0$ — это вес при фиктивном признаке, всегда равном единице (bias, свободный член, смещение), а $w_1, \ldots, w_n$ — веса при $n$ настоящих признаках. За этой заменой обозначений стоит смена постановки задачи: веса — это параметры, которые модель обучает по тренировочным данным, чтобы затем применять их к новым объектам, которых при обучении не было. Именно термины «веса» и «обучение весов» ты будешь использовать во всех последующих уроках курса — у логистической регрессии, у нейросетей, у градиентного бустинга — и линейная регрессия вводит эту терминологию в её самом прозрачном виде.

Формула

Модель линейной регрессии. Для объекта с признаками $x_1, x_2, \ldots, x_n$ предсказание модели — линейная комбинация этих признаков с весами плюс свободный член:

$$\hat y = w_0 + w_1 x_1 + w_2 x_2 + \cdots + w_n x_n$$

В матричной форме, добавляя к вектору признаков фиктивную единицу $x_0=1$, это записывается компактно как скалярное произведение вектора весов $\mathbf{w} = (w_0, w_1, \ldots, w_n)$ и вектора признаков $\mathbf{x} = (1, x_1, \ldots, x_n)$:

$$\hat y = \mathbf{w}^{\mathsf T}\mathbf{x}$$

Обучение модели — это подбор такого вектора весов $\mathbf{w}$, который минимизирует среднеквадратичную ошибку предсказаний на тренировочной выборке из $m$ объектов:

$$L(\mathbf{w}) = \frac{1}{m}\sum_{i=1}^{m}\left(\hat y_i - y_i\right)^2 = \frac{1}{m}\sum_{i=1}^{m}\left(\mathbf{w}^{\mathsf T}\mathbf{x}_i - y_i\right)^2$$

Примеры

Пример 1: сквозной набор данных этого урока — одна переменная. Возьми пять квартир с известной площадью (в квадратных метрах) и ценой (в миллионах рублей) — эти данные будут использоваться на протяжении всего урока:

Квартира Площадь, м² Цена, млн руб
1 30 3.5
2 45 5.0
3 60 6.2
4 75 7.8
5 90 9.0

Здесь один признак $x_1 = $ площадь, и модель имеет вид $\hat y = w_0 + w_1 x_1$ — та же самая форма, что и в уроке 249, только $b_0, b_1$ теперь называются $w_0, w_1$. Уже на глаз видно, что зависимость почти линейна: каждые дополнительные 15 м² добавляют к цене примерно 1.3–1.6 млн рублей.

Пример 2: та же задача с двумя признаками. Добавь к каждой квартире число комнат и ещё одну, шестую квартиру с необычным сочетанием признаков — небольшая площадь, но всего одна комната (просторная студия), что позволит увидеть, как модель распутывает вклад каждого признака по отдельности:

Квартира Площадь, м² Комнаты Цена, млн руб
1 30 1 3.5
2 45 2 5.0
3 60 2 6.2
4 75 3 7.8
5 90 3 9.0
6 50 1 5.3

Теперь модель имеет вид $\hat y = w_0 + w_1 \cdot \text{площадь} + w_2 \cdot \text{комнаты}$ — гиперплоскость в трёхмерном пространстве (площадь, комнаты, цена), которую уже невозможно нарисовать на плоском листе бумаги так же просто, как прямую линию, но которая считается и интерпретируется ровно по той же логике.

Пример 3: масштабирование модели на произвольное число признаков. В реальном сервисе оценки недвижимости признаков будет не два, а несколько десятков: площадь, число комнат, этаж, этажность дома, год постройки, расстояние до метро, наличие балкона, район, материал стен и так далее. Форма модели не меняется ни на йоту — $\hat y = w_0 + w_1 x_1 + \cdots + w_n x_n$, просто $n$ растёт с 1–2 до 30–50. Это свойство и делает линейную регрессию удобной отправной точкой: одна и та же формула, один и тот же способ обучения работают что для игрушечного примера из пяти квартир, что для промышленного датасета из сотен тысяч объявлений с десятками признаков.

Почему это важно

Понимание модели как линейной комбинации обучаемых весов, а не как «формулы прямой линии», — это фундамент, на котором строится весь остаток курса моделей машинного обучения. Логистическая регрессия из урока 313 использует ровно ту же линейную комбинацию $\mathbf{w}^{\mathsf T}\mathbf{x}$, только пропускает её через дополнительную функцию активации. Нейросеть — это, по сути, множество слоёв таких линейных комбинаций, соединённых нелинейностями. Освоив идею весов как параметров, которые модель подбирает под данные, а не как коэффициенты заранее известной физической формулы, ты получаешь словарь понятий, применимый практически ко всем моделям машинного обучения, которые встретятся дальше в курсе.

Два пути обучения: нормальные уравнения против градиентного спуска

Интуиция

У линейной регрессии, в отличие от большинства моделей машинного обучения, есть счастливая особенность: функция потерь $L(\mathbf{w})$ — квадратичная и выпуклая по весам, а значит, у неё есть единственный глобальный минимум, который можно найти напрямую, решив систему линейных уравнений, — без единого шага итеративной оптимизации. Это и есть аналитическое решение, знакомое тебе по уроку 249 под именем нормальных уравнений. Но у аналитического решения есть цена: оно требует обращения матрицы размера $(n+1)\times(n+1)$, а вычислительная сложность обращения матрицы растёт кубически с числом признаков и умножается на размер выборки при построении самой матрицы $\mathbf{X}^{\mathsf T}\mathbf{X}$. Для датасета из пяти квартир с двумя признаками это доли секунды; для датасета из миллиона объявлений с полутысячей признаков — уже серьёзная вычислительная и памятезатратная задача, а если признаков больше, чем объектов, или среди признаков есть линейно зависимые, матрица $\mathbf{X}^{\mathsf T}\mathbf{X}$ может оказаться необратимой.

Здесь на сцену выходит градиентный спуск из урока 285 — универсальный итеративный алгоритм, которому не нужно обращать никакую матрицу. Вместо того чтобы решить задачу за один шаг, градиентный спуск постепенно, маленькими шагами в сторону антиградиента функции потерь, приближается к тому же самому минимуму, который нормальные уравнения находят мгновенно. Для линейной регрессии оба пути гарантированно ведут к одному и тому же результату, потому что функция потерь выпуклая и у неё нет других локальных минимумов, кроме глобального, — это тот самый частный случай, о котором шла речь в уроке 285 при разборе поведения градиентного спуска на выпуклых функциях.

Формула

Нормальные уравнения (аналитическое решение). Собери все признаки объектов обучающей выборки в матрицу $\mathbf{X}$ размера $m \times (n+1)$ (включая столбец единиц для $w_0$) и все целевые значения — в вектор $\mathbf{y}$ размера $m$. Оптимальный вектор весов находится напрямую:

$$\hat{\mathbf{w}} = (\mathbf{X}^{\mathsf T}\mathbf{X})^{-1}\mathbf{X}^{\mathsf T}\mathbf{y}$$

Градиентный спуск. Начиная со случайного (или нулевого) вектора весов $\mathbf{w}^{(0)}$, повторяй обновление до сходимости:

$$\mathbf{w}^{(t+1)} = \mathbf{w}^{(t)} - \eta \nabla L(\mathbf{w}^{(t)}), \qquad \nabla L(\mathbf{w}) = \frac{2}{m}\mathbf{X}^{\mathsf T}(\mathbf{X}\mathbf{w} - \mathbf{y})$$

где $\eta$ — скорость обучения (learning rate) из урока 285.

Примеры

Пример 1: нормальные уравнения на одномерном сквозном примере. Возьми данные из первой таблицы (площадь → цена). $\bar x = (30+45+60+75+90)/5=60$, $\bar y = (3.5+5.0+6.2+7.8+9.0)/5=6.3$. Отклонения от среднего по $x$: $-30,-15,0,15,30$; по $y$: $-2.8,-1.3,-0.1,1.5,2.7$. Сумма произведений отклонений: $(-30)(-2.8)+(-15)(-1.3)+0+15\cdot1.5+30\cdot2.7 = 84+19.5+0+22.5+81=207$. Сумма квадратов отклонений по $x$: $900+225+0+225+900=2250$. Отсюда

$$w_1 = \frac{207}{2250} \approx 0{,}092, \qquad w_0 = 6{,}3 - 0{,}092\cdot60 \approx 0{,}78$$

Модель: $\hat y = 0{,}78 + 0{,}092\cdot\text{площадь}$. Проверка на крайних точках: при площади 30 м² модель даёт $0{,}78+2{,}76=3{,}54$ млн (реально 3.5), при 90 м² — $0{,}78+8{,}28=9{,}06$ млн (реально 9.0). Отклонения на уровне десятков тысяч рублей — модель почти идеально описывает эти пять квартир.

Пример 2: три шага градиентного спуска на той же задаче. Начни с $w_0=0, w_1=0$ и скорости обучения $\eta = 0{,}0001$ (маленькая скорость нужна из-за разных масштабов признака и цели — об этом отдельно в разделе про частые ошибки). При $\mathbf{w}=(0,0)$ предсказания все равны нулю, а градиент по $w_1$ пропорционален $-\sum x_i(y_i-\hat y_i)$, что задаёт направление роста. После первой итерации веса сдвигаются в сторону положительных значений — модель начинает «понимать», что цена растёт вместе с площадью. Повторяя обновление сотни раз с постепенным уменьшением ошибки на каждом шаге (в точности как в примерах урока 285 с иллюстрацией «маленький шаг — долгий путь, подходящий шаг — быстрая сходимость»), веса постепенно приближаются к тем самым $w_0\approx0{,}78,\ w_1\approx0{,}092$, которые нормальные уравнения нашли за одно вычисление. Итоговая точка совпадает — потому что оба метода минимизируют одну и ту же выпуклую функцию потерь, а различаются только маршрутом к минимуму.

Пример 3: когда аналитика перестаёт быть практичной. Представь не пять квартир, а базу ЦИАН из 500 000 объявлений с 40 признаками (район, этаж, год постройки, расстояние до метро и так далее, после кодирования категориальных признаков в числовые). Матрица $\mathbf{X}^{\mathsf T}\mathbf{X}$ здесь имеет размер $41\times41$ — сама по себе некрупная, но её вычисление требует перемножения матриц размера $500\,000\times41$, и, что важнее, при сильно скоррелированных признаках (например, «площадь» и «число комнат» коррелируют почти всегда) матрица может оказаться почти вырожденной — её обращение станет численно неустойчивым. В таких случаях градиентный спуск (или его практичные модификации вроде стохастического градиентного спуска, где на каждом шаге используется не вся выборка, а случайное подмножество) — единственный практически разумный путь: он не требует обращения матрицы вообще и устойчиво сходится, даже когда признаки скоррелированы.

Почему это важно

Выбор между нормальными уравнениями и градиентным спуском — это первое в курсе столкновение с фундаментальным компромиссом машинного обучения между точностью и масштабируемостью. На маленьких и средних датасетах с небольшим числом признаков аналитическое решение — это буквально одна строчка numpy.linalg.solve(), без гиперпараметров, без риска расходимости, без вопроса «а точно ли я сошёлся к минимуму?». На больших датасетах с сотнями и тысячами признаков — а тем более при переходе к моделям, у которых аналитического решения вообще не существует (то же самое случится в следующем уроке при добавлении регуляризации и позже при логистической регрессии) — градиентный спуск и его модификации становятся единственным реалистичным инструментом. Именно поэтому урок 285 стоит раньше линейной регрессии в программе курса: без понимания механики градиентного спуска невозможно осмысленно обучать почти ни одну модель, которая встретится дальше.

Интерпретация весов модели

Интуиция

Самое ценное практическое свойство линейной регрессии по сравнению с многими другими моделями машинного обучения — прозрачность. Обучив модель, ты получаешь не чёрный ящик, а набор чисел, каждое из которых имеет прямой содержательный смысл: вес $w_i$ показывает, насколько в среднем меняется предсказание $\hat y$, если признак $x_i$ увеличить на единицу, а все остальные признаки при этом оставить без изменений. Эта оговорка «при прочих равных» — не формальность, а ключевая часть интерпретации: она означает, что вес $w_i$ изолирует эффект ровно одного признака от эффектов всех остальных признаков, включённых в модель.

Формула

Интерпретация веса $w_i$. Частная производная предсказания по $i$-му признаку равна самому весу:

$$\frac{\partial \hat y}{\partial x_i} = w_i$$

Содержательно: при увеличении признака $x_i$ на одну единицу измерения и неизменных значениях всех остальных признаков предсказание модели изменяется на $w_i$ единиц измерения целевой переменной. Свободный член $w_0$ — это предсказание модели в гипотетической точке, где все признаки равны нулю (что не всегда имеет содержательный смысл, если ноль лежит далеко за пределами реальных значений признаков в данных).

Примеры

Пример 1: интерпретация весов на многомерном сквозном примере. Обучив модель на данных из шести квартир (второй таблицы) с признаками «площадь» и «комнаты», получи коэффициенты (посчитанные инструментом на этой выборке) $w_1 \approx 0{,}081$ млн руб/м² и $w_2 \approx 0{,}35$ млн руб/комнату при $w_0 \approx 0{,}42$. Интерпретация: при фиксированном числе комнат каждый дополнительный квадратный метр площади в среднем добавляет к цене квартиры около 81 тысячи рублей; при фиксированной площади каждая дополнительная комната добавляет около 350 тысяч рублей. Обрати внимание на слово «фиксированном» — это ровно тот смысл, который несёт оговорка «при прочих равных»: модель не говорит, сколько в среднем стоит комната сама по себе (просторная студия с одной комнатой и тесная двушка отличаются по цене совсем не так, как $0{,}35$ млн), она говорит, что происходит с ценой, если добавить комнату, не меняя площадь квартиры.

Пример 2: как мультиколлинеарность искажает интерпретацию. Если бы шестая квартира из таблицы не была добавлена, а все квартиры в выборке имели строго пропорциональную зависимость числа комнат от площади (скажем, ровно одна комната на каждые 30 м²), модель не смогла бы разделить эффект площади и эффект числа комнат — они менялись бы всегда синхронно, и МНК мог бы с равным успехом приписать весь эффект либо признаку «площадь», либо признаку «комнаты», либо разделить его между ними почти произвольным образом, оставляя сумму вкладов почти неизменной. Это и есть на практике эффект сильной мультиколлинеарности: веса становятся нестабильными и плохо интерпретируемыми, хотя само предсказание $\hat y$ при этом может оставаться вполне точным. Шестая квартира в примере (маленькая площадь, но всего одна комната) содержательно «разрывает» эту синхронность и позволяет модели различить вклад каждого признака отдельно.

Пример 3: сравнение важности признаков через стандартизацию. Сырые веса $w_1=0{,}081$ и $w_2=0{,}35$ нельзя напрямую сравнивать между собой, чтобы понять, какой признак «важнее», — площадь измеряется в квадратных метрах с разбросом в десятки единиц, а число комнат — в штуках с разбросом в единицы, и более крупный по модулю вес вовсе не означает более сильное влияние на цену. Чтобы честно сравнить вклад признаков, их предварительно стандартизируют — вычитают среднее и делят на стандартное отклонение, приводя все признаки к одному масштабу (среднее 0, дисперсия 1), — и только после этого сравнивают полученные веса по абсолютной величине: больший по модулю вес при стандартизированном признаке означает более сильное влияние этого признака на предсказание при заданном разбросе значений в данных.

Почему это важно

Интерпретируемость весов — главная причина, по которой линейная регрессия остаётся востребованной моделью даже в эпоху нейросетей и градиентного бустинга, особенно там, где объяснение решения модели важно не меньше, чем само предсказание: банк, отклоняющий заявку на кредит, обязан по закону объяснить причину отказа; риелтор должен уметь сказать клиенту, за что именно он платит дополнительные деньги. Умение грамотно интерпретировать вес — с оговоркой «при прочих равных» и с пониманием эффекта мультиколлинеарности — отличает специалиста, который реально понимает свою модель, от того, кто просто читает число из атрибута model.coef_, не задумываясь, что оно означает.

Предпосылки модели на практике и коэффициент детерминации

Интуиция

В уроке 249 ты уже разбирал классические предпосылки линейной регрессии — линейность, независимость ошибок, гомоскедастичность, нормальность остатков — в контексте статистических выводов и доверительных интервалов. В практическом машинном обучении из этого длинного списка обычно выделяют три предпосылки, которые критичны не столько для статистической строгости, сколько для того, чтобы модель вообще давала осмысленные и стабильные предсказания и интерпретируемые веса: линейность связи между признаками и целью, независимость ошибок друг от друга и отсутствие сильной мультиколлинеарности между признаками. А для оценки того, насколько хорошо модель в принципе справляется с задачей, используется уже знакомый тебе по уроку 249 коэффициент детерминации $R^2$ — только теперь он считается не столько для статистических выводов о значимости, сколько как одна из базовых метрик качества регрессии наравне с MAE и RMSE, к которым ты вернёшься в следующих уроках.

Формула

Три практические предпосылки.

  1. Линейность. Истинная зависимость между признаками и целевой переменной приближённо линейна; если реальная связь, например, квадратичная или экспоненциальная, линейная модель систематически ошибается на определённых участках диапазона признаков, что видно на графике остатков.
  2. Независимость ошибок. Ошибки модели $e_i = y_i - \hat y_i$ не должны быть систематически связаны друг с другом (актуально прежде всего для временных рядов, где соседние по времени ошибки часто коррелируют).
  3. Отсутствие сильной мультиколлинеарности. Признаки не должны быть почти линейно зависимы друг от друга; степень мультиколлинеарности измеряется, например, фактором инфляции дисперсии (VIF) для каждого признака.

Коэффициент детерминации (как в уроке 249):

$$R^2 = 1 - \frac{\sum_i (y_i-\hat y_i)^2}{\sum_i (y_i-\bar y)^2} = 1 - \frac{SSE}{SST}$$

Примеры

Пример 1: $R^2$ на одномерном сквозном примере. Используя модель $\hat y=0{,}78+0{,}092x$ из раздела про обучение, посчитай остатки для всех пяти квартир: при $x=30$ остаток $-0{,}04$, при $x=45$ остаток $0{,}08$, при $x=60$ остаток $-0{,}10$, при $x=75$ остаток $0{,}12$, при $x=90$ остаток $-0{,}06$. Сумма квадратов остатков $SSE = 0{,}0016+0{,}0064+0{,}01+0{,}0144+0{,}0036=0{,}036$. Сумма квадратов отклонений $y$ от среднего $SST=2{,}8^2+1{,}3^2+0{,}1^2+1{,}5^2+2{,}7^2=19{,}08$. Отсюда $R^2 = 1 - 0{,}036/19{,}08 \approx 0{,}998$ — модель объясняет 99.8% разброса цен, что для реального рынка недвижимости с одним признаком — редкий и почти идеальный результат (реальные датасеты почти никогда не бывают настолько чистыми).

Пример 2: проверка линейности через график остатков. Если бы вместо квартир ты работал с датасетом, где цена растёт с площадью не линейно, а резко ускоряется для больших элитных квартир (нелинейный эффект премиум-сегмента), график остатков — предсказания по горизонтали, остатки по вертикали — показал бы не случайное облако вокруг нуля, а систематическую дугу: для маленьких и средних квартир модель немного завышает цену, для очень больших — сильно занижает. Такая закономерная форма остатков, а не разброс вокруг нуля, — прямой сигнал, что линейная модель не годится в исходном виде и нужно либо добавить нелинейные признаки (урок 311 про полиномиальную регрессию), либо преобразовать целевую переменную.

Пример 3: мультиколлинеарность площади и числа комнат на практике. В реальных датасетах недвижимости площадь и число комнат почти всегда сильно коррелируют — VIF для этой пары признаков нередко превышает 5–10, что считается тревожным порогом. При этом сам $R^2$ модели и качество предсказаний могут оставаться высокими: мультиколлинеарность портит именно интерпретируемость и стабильность отдельных весов (как в примере из предыдущего раздела), а не точность прогноза как такового. На практике эту проблему решают либо удалением одного из скоррелированных признаков, либо переходом к регуляризованной регрессии — Ridge и Lasso, которым посвящён урок 312.

Почему это важно

Три предпосылки и $R^2$ — это не теоретическая формальность, а практический чек-лист, который стоит пройти перед тем, как доверять обученной модели. Высокий $R^2$ на тренировочных данных ничего не говорит о том, нарушена ли линейность (модель может «подогнаться» под нелинейные данные не лучшим образом, но всё равно показать приемлемый $R^2$), и ничего не говорит о том, насколько стабильны и интерпретируемы полученные веса при наличии мультиколлинеарности. Именно сочетание всех этих проверок — графика остатков, VIF, $R^2$ на отдельной тестовой выборке — отличает осмысленно обученную модель от модели, которая просто «завелась» без единой проверки.

Полный практический пример: от сырых данных до обученной модели через sklearn

Интуиция

Весь материал этого урока сходится в одном практическом навыке — умении провести полный цикл обучения модели: от таблицы с сырыми данными до готовой, проверенной и интерпретируемой модели. В индустрии этот цикл выполняется не вручную по формулам, а через sklearn.linear_model.LinearRegression — класс, который под капотом решает те самые нормальные уравнения (а для больших разреженных данных использует численно устойчивые методы вроде сингулярного разложения вместо прямого обращения матрицы).

Формула

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
import numpy as np

model = LinearRegression()
model.fit(X_train, y_train)          # обучение — поиск весов
y_pred = model.predict(X_test)        # предсказание на новых данных
r2 = r2_score(y_test, y_pred)         # оценка качества

Примеры

Пример 1: базовая одномерная модель. Воспроизведи ручной расчёт из раздела про обучение уже через sklearn:

import numpy as np
from sklearn.linear_model import LinearRegression

X = np.array([[30], [45], [60], [75], [90]])   # площадь, м²
y = np.array([3.5, 5.0, 6.2, 7.8, 9.0])         # цена, млн руб

model = LinearRegression()
model.fit(X, y)

print(f"w1 (площадь): {model.coef_[0]:.3f}")   # ≈ 0.092
print(f"w0 (intercept): {model.intercept_:.3f}") # ≈ 0.780

Коэффициенты совпадают (с точностью до округления) с теми, что были получены вручную через формулы МНК, — это ожидаемо, потому что LinearRegression по умолчанию решает ту же самую задачу минимизации суммы квадратов остатков.

Пример 2: множественная регрессия и интерпретация coef_. Расширь модель до двух признаков — площади и числа комнат — на данных из шести квартир:

X = np.array([[30, 1], [45, 2], [60, 2], [75, 3], [90, 3], [50, 1]])
y = np.array([3.5, 5.0, 6.2, 7.8, 9.0, 5.3])

model = LinearRegression()
model.fit(X, y)

print(f"Вес площади:  {model.coef_[0]:.3f} млн руб/м²")
print(f"Вес комнат:   {model.coef_[1]:.3f} млн руб/комнату")
print(f"Intercept:    {model.intercept_:.3f} млн руб")

model.coef_ — это массив из двух чисел, ровно $w_1$ и $w_2$ из раздела про интерпретацию весов, а model.intercept_ — это $w_0$. Дальше эти числа читаются точно так, как было разобрано выше: при фиксированном числе комнат каждый лишний метр площади добавляет к цене значение coef_[0], при фиксированной площади каждая лишняя комната добавляет coef_[1].

Пример 3: полный цикл с разделением на train/test и предсказанием новой квартиры. На практике модель никогда не оценивают на тех же данных, на которых обучали, — используют разбиение из урока 305:

from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score

# представим более крупный датасет из 200 квартир с площадью и комнатами
X_train, X_test, y_train, y_test = train_test_split(
    X_all, y_all, test_size=0.2, random_state=42
)

model = LinearRegression()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)
print(f"R² на тесте: {r2_score(y_test, y_pred):.3f}")

# предсказание для новой квартиры: 65 м², 2 комнаты
new_flat = np.array([[65, 2]])
predicted_price = model.predict(new_flat)
print(f"Предсказанная цена: {predicted_price[0]:.2f} млн руб")

Этот код — законченный ML-проект в миниатюре: данные разделены на train и test так, чтобы оценка $R^2$ была честной проверкой на объектах, которые модель не видела при обучении, а финальный вызов model.predict() на новой квартире — именно то практическое применение, ради которого вся модель обучалась.

Почему это важно

Умение написать эти несколько строк кода — не самоцель, а проверка того, что все понятия урока действительно усвоены и связаны друг с другом: model.fit() внутри себя решает задачу минимизации из раздела про модель, либо через нормальные уравнения, либо через итеративный численный метод из раздела про обучение; model.coef_ — это в точности веса, которые интерпретируются с оговоркой «при прочих равных» из раздела про интерпретацию; r2_score на отдельной тестовой выборке — это честная проверка предпосылок и качества модели, а не самообман высоким $R^2$ на тренировочных данных. Именно так выглядит реальная работа специалиста по машинному обучению: перевод математического понимания в несколько строк рабочего кода, который можно встроить в настоящий продукт.

Практика: 30 заданий

Базовые задания (1–10)

Задание 1: Запиши формулу модели линейной регрессии с тремя признаками $x_1, x_2, x_3$ и объясни, что означает каждый из символов $w_0, w_1, w_2, w_3$.


Задание 2: По данным о четырёх квартирах: площадь $x$: 20, 40, 60, 80 (м²), цена $y$: 2.5, 4.5, 6.5, 8.5 (млн руб), найди $w_1$ и $w_0$ через формулы МНК.


Задание 3: Используя модель из задания 2, предскажи цену квартиры площадью 55 м².


Задание 4: Модель предсказывает зарплату по стажу работы: $\hat y = 30 + 2{,}5x$ (тыс. руб., $x$ — годы стажа). Объясни содержательно, что означают числа 30 и 2.5.


Задание 5: В чём принципиальное отличие нормальных уравнений от градиентного спуска с точки зрения числа шагов, необходимых для нахождения решения?


Задание 6: Почему для линейной регрессии градиентный спуск и нормальные уравнения гарантированно сходятся к одному и тому же результату?


Задание 7: Модель обучена на признаках «площадь» и «число комнат» и даёт веса $w_1=0{,}08$ (площадь), $w_2=0{,}3$ (комнаты). Что произойдёт с предсказанной ценой, если добавить одну комнату, не меняя площадь квартиры?


Задание 8: Назови три предпосылки линейной регрессии, важные на практике, о которых говорилось в уроке.


Задание 9: Для модели $SST=100$, $SSE=15$ найди $R^2$ и объясни его смысл.


Задание 10: Какой метод sklearn используется для создания и обучения модели линейной регрессии, и какие два метода вызываются для обучения и предсказания?


Продвинутые задания (11–20)

Задание 11: По шести наблюдениям известны суммарные статистики: $n=6$, $\sum x_i=180$, $\sum y_i=39$, $\sum x_iy_i=1300$, $\sum x_i^2=6300$. Найди $w_1$ и $w_0$, используя формулы через суммы.


Задание 12: Объясни, почему при слишком большой скорости обучения $\eta$ в градиентном спуске для линейной регрессии веса могут не сойтись, а начать расходиться (сравни с уроком 285).


Задание 13: Датасет содержит признаки «площадь в квадратных метрах» (от 20 до 200) и «число санузлов» (от 1 до 3). Почему обучение градиентным спуском без предварительного масштабирования признаков может сходиться очень медленно?


Задание 14: Модель без стандартизации даёт веса $w_{\text{площадь}}=0{,}08$ и $w_{\text{комнаты}}=0{,}3$. Можно ли на основании этих двух чисел сделать вывод, что число комнат сильнее влияет на цену, чем площадь? Обоснуй ответ.


Задание 15: Объясни, почему обычный $R^2$ линейной регрессии никогда не уменьшается при добавлении в модель любого нового признака, даже статистически бесполезного (вспомни аналогичный вывод из урока 249).


Задание 16: Датасет имеет 60 объектов и 55 признаков, среди которых много почти линейно зависимых друг от друга (сильная мультиколлинеарность). Почему в этой ситуации нормальные уравнения могут давать численно нестабильный результат?


Задание 17: Предложи два практических способа поправить проблему из задания 16, опираясь на материал этого урока и его связь со следующими уроками курса.


Задание 18: Модель предсказывает время доставки заказа по расстоянию (км) и числу товаров в заказе: $\hat y = 15 + 3x_1 + 2x_2$ (минуты). Заказ на расстояние 8 км с 4 товарами доставлен фактически за 55 минут. Найди предсказание модели и остаток.


Задание 19: Обученная на тренировочных данных модель показывает $R^2=0{,}92$ на train и $R^2=0{,}40$ на test. Что это говорит о модели, и какая тема из фундамента курса (уроки 304–305) здесь напрямую применима?


Задание 20: Почему при построении графика остатков по оси Y откладывают именно остатки $y_i-\hat y_i$, а не сами предсказания $\hat y_i$?


Задания-челленджи (21–30)

Задание 21: По данным $x$: 10, 20, 30, 40, 50 и $y$: 12, 25, 33, 48, 55 найди $w_1$, $w_0$ и $R^2$.


Задание 22: Докажи в общих чертах, что линия регрессии, полученная методом наименьших квадратов, всегда проходит через точку $(\bar x, \bar y)$ (используй первое нормальное уравнение).


Задание 23: Две модели предсказывают цену дома: модель А использует только площадь и даёт $SSE_A=800$, модель Б добавляет к площади ещё пять признаков и даёт $SSE_Б=650$ при одинаковом $SST=3000$. Посчитай $R^2$ обеих моделей и объясни, почему одного этого сравнения недостаточно, чтобы предпочесть модель Б.


Задание 24: Модель для оценки квартир получает признак «этаж» как число от 1 до 25 и признак «наличие лифта» как 0/1. Объясни, почему такая смесь разных по своей природе шкал не мешает линейной регрессии математически, но может мешать корректной интерпретации и сходимости градиентного спуска.


Задание 25: Смоделируй ситуацию: обучена модель $\hat y = 2 + 0{,}5x_1 - 0{,}3x_2$, где $x_1$ — площадь кухни (м²), $x_2$ — расстояние до ближайшей свалки бытовых отходов (км). Интерпретируй оба веса и объясни знак каждого из них содержательно.


Задание 26: Выведи в общих чертах, почему нормальные уравнения в матричной форме $\hat{\mathbf w}=(\mathbf X^{\mathsf T}\mathbf X)^{-1}\mathbf X^{\mathsf T}\mathbf y$ получаются из приравнивания градиента функции потерь к нулевому вектору.


Задание 27: Реши, какой из двух подходов — нормальные уравнения или градиентный спуск — предпочтителен для датасета из 50 объектов и 3 признаков, и отдельно — для датасета из 10 миллионов объектов и 200 признаков, обосновывая выбор вычислительными соображениями из урока.


Задание 28: Банк использует линейную регрессию для одобрения максимальной суммы кредита по признакам «доход» и «стаж работы». Объясни, почему интерпретируемость весов этой модели может быть не просто удобством, а требованием закона или регулятора.


Задание 29: Сравни модель линейной регрессии, обученную на пяти квартирах из первого примера этого урока (только площадь), с гипотетической моделью, обученной на тех же пяти квартирах, но с добавлением признака «этаж», значения которого случайны и не связаны с ценой. Что произойдёт с $R^2$ на train и почему это не повод включать признак «этаж» в финальную модель?


Задание 30: Спроектируй полный практический процесс построения модели предсказания цены квартиры для реального сервиса: перечисли по порядку основные шаги от сырых данных до модели, готовой к использованию, используя понятия этого и предыдущих уроков курса (305–309).


Частые ошибки

Ошибка 1. Обучают модель без предварительного масштабирования признаков разного порядка величины и удивляются, что градиентный спуск либо расходится, либо сходится крайне медленно.

Как выглядит: признак «площадь» варьируется в диапазоне 20–200, признак «число комнат» — в диапазоне 1–5, обучение градиентным спуском с одной общей скоростью $\eta$ либо не сходится вовсе, либо требует тысяч лишних итераций.

Почему возникает: градиент по весу «крупного» признака систематически больше градиента по весу «мелкого» признака, и единая скорость обучения не подходит для обоих направлений одновременно.

Как правильно: перед градиентным спуском стандартизировать или нормализовать признаки (привести к сопоставимому масштабу); для нормальных уравнений эта проблема не критична, но масштабирование всё равно облегчает интерпретацию и сравнение весов.

Ошибка 2. Интерпретируют вес $w_i$ как «полный эффект» признака на цену, забывая оговорку «при прочих равных».

Как выглядит: «вес при числе комнат 0.35 — значит, каждая комната стоит 350 тысяч рублей сама по себе», без учёта того, что комнаты почти всегда идут рука об руку с ростом площади.

Почему возникает: естественное желание читать коэффициент как простую «цену» признака, без учёта того, что вес показывает изолированный эффект при фиксированных остальных признаках, а не полный совместный эффект.

Как правильно: формулировать интерпретацию явно через «при неизменных остальных признаках» и отдельно проверять степень мультиколлинеарности, прежде чем делать содержательные выводы из значения конкретного веса.

Ошибка 3. Оценивают качество модели по $R^2$, посчитанному на тех же данных, на которых модель обучалась.

Как выглядит: «наша модель показывает $R^2=0{,}95$» — без упоминания, что это тренировочная выборка.

Почему возникает: $R^2$ на train легко посчитать сразу после model.fit(), и высокое число создаёт ложное ощущение готовой модели.

Как правильно: всегда оценивать $R^2$ (и другие метрики) на отдельной тестовой выборке, которую модель не видела при обучении, — только такая оценка честно отражает способность модели обобщаться на новые данные (урок 305).

Ошибка 4. Используют линейную регрессию для данных с явно нелинейной зависимостью, ориентируясь только на приемлемое значение $R^2$, без проверки графика остатков.

Как выглядит: обучают модель на данных, где цена растёт нелинейно (например, ускоренно для элитной недвижимости), получают $R^2=0{,}7$ и считают его достаточным без дальнейшего анализа.

Почему возникает: $R^2$ — агрегированное число, которое не показывает, в какой части диапазона признаков модель систематически ошибается.

Как правильно: строить график остатков против предсказаний и проверять его на закономерные, неслучайные узоры (дуги, воронки) — признак нарушенной линейности, требующий полиномиальных признаков (урок 311) или иного преобразования.

Ошибка 5. Игнорируют сильную мультиколлинеарность между признаками и делают выводы о важности признаков на основании нестабильных, «случайно» распределившихся между коррелированными признаками весов.

Как выглядит: «вес при площади почти нулевой, значит, площадь не важна для цены» — при том, что площадь сильно коррелирует с числом комнат, которое «забрало» на себя почти весь совместный эффект.

Почему возникает: не проверяют VIF или корреляционную матрицу признаков перед интерпретацией весов.

Как правильно: перед содержательными выводами о важности отдельных признаков проверять мультиколлинеарность и, при необходимости, использовать регуляризацию (урок 312) или удалять избыточные признаки.

Ошибка 6. Забывают, что коэффициент $R^2$ измеряет долю объяснённой дисперсии, а не абсолютную точность предсказания в единицах измерения цели.

Как выглядит: «$R^2=0{,}9$ — значит, модель ошибается в среднем всего на 10%» — подмена одной метрики другой.

Почему возникает: оба числа лежат в интуитивно похожем диапазоне (доли или проценты), что провоцирует смешение смыслов.

Как правильно: для оценки типичной величины ошибки в понятных единицах (например, в миллионах рублей) использовать отдельные метрики — MAE или RMSE, которые разбираются в последующих уроках метрик регрессии, а $R^2$ использовать именно как долю объяснённой дисперсии.

Главное запомнить

  • Линейная регрессия — первая полноценная модель машинного обучения курса: $\hat y = w_0+w_1x_1+\cdots+w_nx_n$, где веса $w_i$ — параметры, которые модель обучает по тренировочным данным, а не заранее заданные статистические оценки.

  • Обучение модели — минимизация среднеквадратичной ошибки предсказаний, той же функции потерь МНК, которую ты выводил в уроке 249, только теперь применяемой к новым, не виденным при обучении объектам.

  • Есть два способа найти оптимальные веса: нормальные уравнения $\hat{\mathbf w}=(\mathbf X^{\mathsf T}\mathbf X)^{-1}\mathbf X^{\mathsf T}\mathbf y$ дают точное решение за один шаг и хороши для небольших датасетов, а градиентный спуск из урока 285 приближается к тому же решению итеративно и лучше масштабируется на большие данные и много признаков.

  • Для линейной регрессии оба способа обучения гарантированно сходятся к одному и тому же результату, потому что функция потерь выпуклая и у неё единственный глобальный минимум.

  • Вес $w_i$ интерпретируется как изменение предсказания при увеличении признака $x_i$ на единицу и неизменных остальных признаках — оговорка «при прочих равных» критична и требует проверки на мультиколлинеарность.

  • Три практические предпосылки модели — линейность связи, независимость ошибок, отсутствие сильной мультиколлинеарности между признаками — стоит проверять до того, как доверять весам и предсказаниям.

  • Коэффициент детерминации $R^2$ (тот же, что в уроке 249) показывает долю объяснённой моделью дисперсии целевой переменной и остаётся одной из базовых метрик качества регрессии, но никогда не уменьшается при добавлении новых признаков, что делает его ненадёжным для сравнения моделей с разным числом признаков без дополнительных поправок.

  • sklearn.linear_model.LinearRegression реализует полный цикл: .fit() находит веса, .predict() строит предсказания для новых объектов, model.coef_ и model.intercept_ дают доступ к обученным весам для интерпретации.

  • Качество модели нужно оценивать на отдельной тестовой выборке (урок 305), а не на тех же данных, на которых происходило обучение, — иначе высокий $R^2$ может маскировать переобучение (урок 304).

Связь с темами курса

Этот урок напрямую опирается на урок 249 «Регрессионный анализ»: формула модели, метод наименьших квадратов, нормальные уравнения и коэффициент детерминации $R^2$ — это буквально та же математика, только теперь применённая не для статистического объяснения данных, а для построения предсказательной ML-модели. Всё, что было строго выведено в уроке 249 — вывод формул через частные производные, свойство прохождения линии регрессии через точку средних, тождество $R^2=r_{xy}^2$ для простой регрессии, предпосылки классической линейной модели, — используется в этом уроке как готовый инструмент, без повторного вывода.

Урок также напрямую продолжает урок 285 «Градиентный спуск»: там ты разобрал универсальный алгоритм итеративной оптимизации на абстрактных примерах, а линейная регрессия дала тебе первую модель, где можно сравнить градиентный спуск с точным аналитическим решением и увидеть, что оба метода сходятся к одному и тому же ответу. Это сравнение — не просто иллюстрация: в следующих уроках курса (логистическая регрессия, а тем более нейросети) аналитического решения уже не будет вовсе, и градиентный спуск останется единственным доступным способом обучения, поэтому важно закрепить понимание того, что именно он ищет и почему это работает.

Следующий урок 311 «Полиномиальная регрессия» берёт ту же самую модель и ту же самую функцию потерь и снимает предпосылку линейности связи, о которой шла речь в разделе про предпосылки этого урока, — добавляя в модель степени признаков ($x^2, x^3, \ldots$) как новые «признаки» той же самой линейной по весам формулы. А урок 312 «Регуляризация (Ridge, Lasso)» напрямую отвечает на проблему мультиколлинеарности, разобранную в разделе про интерпретацию весов, — модифицируя саму функцию потерь так, чтобы веса оставались стабильными даже при сильно скоррелированных признаках.

Интересные факты

  • Формула нормальных уравнений линейной регрессии, придуманная Лежандром и Гауссом для расчёта орбиты астероида в начале XIX века, без единого изменения используется сегодня внутри sklearn.linear_model.LinearRegression — под капотом библиотеки, обученной специалистами Google, Microsoft и тысяч других компаний, работает математика возрастом больше двухсот лет.

  • Слово «регрессия» из названия целого семейства алгоритмов машинного обучения — от простой линейной регрессии до градиентного бустинга для регрессии — исторически не имеет прямого отношения к «предсказанию»: Гальтон придумал его для совсем другого явления, «сползания» роста детей к среднему по популяции, и лишь по историческому совпадению термин закрепился за задачей предсказания непрерывных величин вообще.

  • Линейная регрессия остаётся стандартным «базовым уровнем» (baseline) практически в любом ML-соревновании и коммерческом проекте: перед тем как обучать сложную модель вроде градиентного бустинга или нейросети, специалисты почти всегда сначала обучают линейную регрессию — просто чтобы понять, какого качества можно добиться самым простым и быстрым способом, прежде чем усложнять модель.

  • Несмотря на почтенный возраст, линейная регрессия математически эквивалентна простейшей нейронной сети без скрытых слоёв и без нелинейной функции активации на выходе — она же используется как «строительный блок» внутри гораздо более сложных архитектур, включая последний слой многих глубоких сетей для задач регрессии.

Лайфхаки

  • Прежде чем обучать что-либо сложнее линейной регрессии, всегда обучи саму линейную регрессию в качестве базового уровня (baseline) — если сложная модель не превосходит её заметно, скорее всего, дело не в недостаточной сложности модели, а в качестве данных или признаков.

  • Если веса модели выглядят подозрительно большими, нестабильными или меняют знак при малейшем изменении датасета — первым делом проверь мультиколлинеарность признаков через корреляционную матрицу или VIF, а не спеши подозревать саму модель или её реализацию.

  • Всегда смотри на график остатков после обучения, даже если $R^2$ выглядит хорошим, — закономерный, неслучайный узор в остатках говорит о систематической проблеме модели, которую одно агрегированное число $R^2$ может полностью скрыть.

  • При работе с признаками разного масштаба используй StandardScaler из sklearn перед градиентным спуском (или перед регуляризованными версиями регрессии из следующего урока) — это не изменит итоговое качество модели при нормальных уравнениях, но заметно ускорит и стабилизирует сходимость градиентного спуска.

  • Держи в голове, что интерпретация веса «при прочих равных» — не только математический нюанс, но и практическая проверка на здравый смысл: если содержательный смысл знака или величины веса кажется странным (как в задании 25 про расстояние до свалки), почти всегда стоит перепроверить единицы измерения признака и направление шкалы, прежде чем доверять модели.

Ты только что прошёл полный путь от абстрактной формулы МНК из урока 249 и универсального алгоритма оптимизации из урока 285 до первой настоящей, обученной и интерпретированной модели машинного обучения. Всё, что раньше было математикой на бумаге, теперь умещается в несколько строк sklearn-кода, которые ты можешь запустить на реальных данных прямо сегодня. Это фундамент, на котором будет держаться весь остаток курса моделей: полиномиальная регрессия в следующем уроке всего лишь добавит новых признаков к той же самой формуле, регуляризация — модифицирует функцию потерь, а логистическая регрессия — обернёт эту же линейную комбинацию в новую функцию активации. Ты уже знаешь главное: как модель обучается, как её интерпретировать и как проверить, что ей можно доверять.

Понял тему? Закрепи в боте! 🚀

Попрактикуйся на задачах и получи персональные рекомендации от AI

💪 Начать тренировку
💬 Есть вопрос? Спроси бота!