Все курсы > Вводный курс > Занятие 13
Работая с линейной регрессией в Scikit-learn, мы обучили нашу модель предсказывать обхват шеи по росту человека. Посмотрим на этот процесс еще раз.
Вначале, мы брали данные наших наблюдений (рост людей X и обхват шеи y) и строили модель (подбирали веса w). Затем, зная рост и веса модели, делали прогноз (ŷ). Качество модели мы оценивали по отклонению прогноза (ŷi) от реальных значений (yi).
В этом подходе все хорошо, кроме одного. Для обучения и проверки качества модели мы использовали одни и те же данные. Приведу хрестоматийную аналогию, чтобы объяснить почему так делать не стоит.
Пример студентов во время сессии

Как известно, от сессии до сессии живут студенты весело. Однако в какой-то момент сессия все-таки наступает, и перед учащимися встает вопрос подготовки к экзаменам. У них по большому счету есть два варианта:
- Первый вариант. Взять вопросы к экзамену у преподавателя, подготовить билеты и вызубрить их. Преимуществом такого подхода будут относительно небольшие трудозатраты. Нужно выучить только то, что написано в билетах. Недостатком будет то, что любой вопрос вне выученного конспекта поставит экзаменуемого в тупик.
- Второй вариант. Выучить сам предмет без привязки к билетам. Да, на вопросы билета человек может отвечать менее бодро, зато у него будет целостная картина того материала, который он, как надеются преподаватели, учил весь семестр.
Так вот при обучении модели у нас есть точно такой же выбор.
Обучающая и тестовая выборки
Если мы будем оценивать качество модели (например, с помощью корня из средней суммы расстояний, RMSE) на тех же данных, на которых обучали модель, то будем по большому счету заучивать билеты. Когда же нам встретятся новые данные, наш прогноз уже не будет таким замечательным.
Логичнее разделить данные на обучающую (training data) и тестовую (test data) выборки с тем, чтобы модель «знала предмет в целом» и не «проваливала экзамен из-за неожиданных вопросов преподавателя», т.е. не показывала низкого RMSE при встрече с новыми данными (новыми X и y).
Да, во втором случае мы скорее всего несколько снизим качество модели, потому что обучающая и тестовая выборки будут отличаться. Выигрышем же будет то, что в целом наша модель сможет делать более точные предсказания.
Проблема переобучения
С точки зрения данных проблему «заучивания билетов» еще называют переобучением модели (model overfitting). Когда мы учим и проверяем модель на одних и тех же данных, то по сути просим модель запомнить каждую единицу наших данных.
Также существует проблема недообучения (underfitting).
Если бы мы строили не линейную модель, а, например, полиномиальную (она выражена кривой), то нормально обученная модель отличалась бы от недообученной и переобученной следующим образом.

Разделение на обучающую и тестовую выборки в Scikit-learn
Вначале откроем ноутбук к этому занятию⧉
Вновь возьмем данные роста и обхвата шея. Только теперь не просто разделим данные на рост (X) и обхват шеи (y), но и каждый компонент в свою очередь разделим на две части, обучающую и тестовую.

Обучать мы будем на X_train и y_train, а делать прогноз и проверять качество модели на X_test и y_test. Вначале возьмем и подготовим наши данные.
1 2 3 4 5 6 7 8 9 10 11 12 |
# возьмем данные роста (X) и обхвата шеи (y) X = [1.48, 1.49, 1.49, 1.50, 1.51, 1.52, 1.52, 1.53, 1.53, 1.54, 1.55, 1.56, 1.57, 1.57, 1.58, 1.58, 1.59, 1.60, 1.61, 1.62, 1.63, 1.64, 1.65, 1.65, 1.66, 1.67, 1.67, 1.68, 1.68, 1.69, 1.70, 1.70, 1.71, 1.71, 1.71, 1.74, 1.75, 1.76, 1.77, 1.77, 1.78] y = [29.1, 30.0, 30.1, 30.2, 30.4, 30.6, 30.8, 30.9, 31.0, 30.6, 30.7, 30.9, 31.0, 31.2, 31.3, 32.0, 31.4, 31.9, 32.4, 32.8, 32.8, 33.3, 33.6, 33.0, 33.9, 33.8, 35.0, 34.5, 34.7, 34.6, 34.2, 34.8, 35.5, 36.0, 36.2, 36.3, 36.6, 36.8, 36.8, 37.0, 38.5] # импортируем библиотеку Numpy import numpy as np # преобразуем наш список X сначала в одномерный массив Numpy, а затем добавим второе измерение X = np.array(X).reshape(-1, 1) # список y достаточно преобразовать в одномерный массив Numpy y = np.array(y) |
Теперь произведем разделение с помощью функции train_test_split из библиотеки Scikit-learn.
1 2 3 4 5 6 7 8 9 |
# из модуля model_selection библиотеки sklearn импортируем функцию train_test_split from sklearn.model_selection import train_test_split # разбиваем данные на четыре части # названия переменных могут быть любыми, но обычно используют именно их # также задаем размер тестовой выборки (30%) и точку отсчета для воспроизводимости X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 42) |
Выведем результат.
1 2 |
# выведем исходный размер массива признаков (X) X.shape |
1 |
(41, 1) |
1 2 |
# теперь посмотрим, что сделала функция train_test_split print(X_train.shape, X_test.shape) |
1 |
(28, 1) (13, 1) |
Далее мы снова построим нашу модель, но уже с учетом вышеописанного разделения на train и test (для простоты часто говорят именно так).
1 2 3 4 5 6 7 8 9 10 |
# из набора линейных моделей библиотеки sklearn импортируем линейную регрессию from sklearn.linear_model import LinearRegression # создадим объект этого класса и запишем в переменную model model = LinearRegression() # обучим нашу модель # т.е. найдем те самые веса или наклон и сдвиг прямой с помощью функции потерь # только теперь используем только обучающую выборку model.fit(X_train, y_train) |
Выведем коэффициенты (веса):
1 2 |
# выведем наклон и сдвиг с помощью атрибутов coef_ и intercept_ соответственно print(model.coef_, model.intercept_) |
1 |
[26.37316095] -9.809957964460885 |
Сделаем прогноз, но уже на тестовой выборке.
1 2 3 4 5 |
# на основе значений роста (Х) предскажем значения обхвата шеи y_pred = model.predict(X_test) # выведем первые пять значений с помощью диапазона индексов print(y_pred[:5]) |
1 |
[33.9694892 31.59590472 30.54097828 34.23322081 30.01351506] |
Посмотрим на результат, т.е. рассчитаем RMSE, снова по тестовой выборке.
1 2 3 4 5 6 |
# импортируем модуль метрик from sklearn import metrics # выведем корень среднеквадратической ошибки # в этот раз сравним тестовые и прогнозные значения окружности шеи print('Root Mean Squared Error (RMSE):', np.sqrt(metrics.mean_squared_error(y_test, y_pred))) |
1 |
Root Mean Squared Error (RMSE): 0.5604831734149255 |
Результат несколько хуже, чем в прошлый раз (0,56 против 0,47), зато мы можем быть уверены, что модель готова к работе на всех данных, а не только на обучающих. Студент готов к самым неожиданным вопросам экзаменатора.
К сожалению, даже такое разделение имеет свои недостатки. Если тестовая выборка сильно отличается от обучающей, то оценка качества модели все равно будет некорректной. О том как преодолеть этот и некоторые другие недостатки мы поговорим в другой раз.
Вопросы и упражнения для закрепления
На какие четыре компонента разбивает данные функция train_test_split?
Посмотреть правильный ответ
Ответ: данные независимых переменных (признаков) и данные зависимой (целевой) переменной разбиваются каждые на обучающую и тестовую выборки. Получается четыре набора данных.
На каких данных мы строим прогноз и проверяем качество модели?
Посмотреть правильный ответ
Ответ: на тестовой выборке. Это позволяет избежать переобучения.
Дополнительные упражнения⧉ вы найдете в конце ноутбука.
Большое повторение
Итак, мы прошли два подготовительных раздела. Что мы узнали?
- В первую очередь, мы узнали, что такое модель машинного обучения, и чем она отличается от жестко прописанной компьютерной программы.
- Научились работать в программе Google Colab и освоили основы программирования на Питоне.
- Кроме того, мы изучили наборы данных, списки и словари.
- Добавив условия и циклы, мы начали писать первые программы.
- Все это заложило основу для анализа данных на Питоне.
- Во втором разделе, имея достаточно технических навыков, мы начали изучать данные с точки зрения их содержания. В частности, занимались описательной статистикой и статистическим выводом.
- Узнав о взаимосвязи переменных, мы начали строить первые модели.
- Затем мы изучили как компьютер подбирает веса и как можно представить данные в форме вектора или матрицы для удобства вычислений.
- Наконец, мы посмотрели, почему не стоит обучать и тестировать модели на одних и тех же данных.
Поздравляю!
Вы готовы к настоящей практической работе по построению моделей. В следующем, третьем, разделе мы изучим классические модели машинного обучения: регрессию, классификацию и кластеризацию. В последнем, четвертом, разделе, мы начнем решать существенно более сложные прикладные задачи.
Желаю успехов в дальнейшем обучении!