На этом шаге мы рассмотрим пример применения взаимодействий и полиномов.
В качестве более реального примера, иллюстрирующего применение взаимодействий и полиномов, давайте еще раз обратимся к набору данных Boston Housing. Мы уже использовали полиномиальные признаки этого набора данных. Теперь давайте посмотрим, как были получены эти признаки и выясним, насколько они могут помочь нам улучшить прогноз. Сначала мы загрузим данные и отмасштабируем их с помощью MinMaxScaler, чтобы все признаки принимали значения в диапазоне между 0 и 1:
[In 27]: from sklearn.datasets import load_boston from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler boston = load_boston() X_train, X_test, y_train, y_test = train_test_split ( boston.data, boston.target, random_state=0) # масштабируем данные scaler = MinMaxScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test)
Теперь, мы выделим полиномиальные признаки и взаимодействия вплоть до 2-й степени:
[In 28]: poly = PolynomialFeatures(degree=2).fit(X_train_scaled) X_train_poly = poly.transform(X_train_scaled) X_test_poly = poly.transform(X_test_scaled) print("форма обучающего массива X: {}".format(X_train.shape)) print("форма обучающего массива X полиномы и взаим: {}".format(X_train_poly.shape)) форма обучающего массива X: (379, 13) форма обучающего массива X полиномы и взаим: (379, 105)
Набор данных первоначально содержал 13 признаков, которые в ходе преобразований превратились в 105 новых признаков. Эти новые признаки представляют собой все возможные взаимодействия между двумя различными исходными характеристиками, а также квадраты исходных характеристик. В данном случае degree=2 означает, что мы рассматриваем признаки, которые являются произведением не более двух исходных характеристик. Точное соответствие между входными и выходными признаками можно найти с помощью метода get_feature_names():
[In 29]: print("Имена полиномиальных признаков:\n{}".format(poly.get_feature_names())) Имена полиномиальных признаков: ['1', 'x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11', 'x12', 'x0^2', 'x0 x1', 'x0 x2', 'x0 x3', 'x0 x4', 'x0 x5', 'x0 x6', 'x0 x7', 'x0 x8', 'x0 x9', 'x0 x10', 'x0 x11', 'x0 x12', 'x1^2', 'x1 x2', 'x1 x3', 'x1 x4', 'x1 x5', 'x1 x6', 'x1 x7', 'x1 x8', 'x1 x9', 'x1 x10', 'x1 x11', 'x1 x12', 'x2^2', 'x2 x3', 'x2 x4', 'x2 x5', 'x2 x6', 'x2 x7', 'x2 x8', 'x2 x9', 'x2 x10', 'x2 x11', 'x2 x12', 'x3^2', 'x3 x4', 'x3 x5', 'x3 x6', 'x3 x7', 'x3 x8', 'x3 x9', 'x3 x10', 'x3 x11', 'x3 x12', 'x4^2', 'x4 x5', 'x4 x6', 'x4 x7', 'x4 x8', 'x4 x9', 'x4 x10', 'x4 x11', 'x4 x12', 'x5^2', 'x5 x6', 'x5 x7', 'x5 x8', 'x5 x9', 'x5 x10', 'x5 x11', 'x5 x12', 'x6^2', 'x6 x7', 'x6 x8', 'x6 x9', 'x6 x10', 'x6 x11', 'x6 x12', 'x7^2', 'x7 x8', 'x7 x9', 'x7 x10', 'x7 x11', 'x7 x12', 'x8^2', 'x8 x9', 'x8 x10', 'x8 x11', 'x8 x12', 'x9^2', 'x9 x10', 'x9 x11', 'x9 x12', 'x10^2', 'x10 x11', 'x10 x12', 'x11^2', 'x11 x12', 'x12^2']
В данном случае первый новый признак является признаком-константой "1". Следующие 13 признаков являются исходными признаками (от "x0" до "x12"). Затем следует квадрат первого признака ("х0^2"), после него приводятся произведения первого и остальных признаков.
Давайте вычислим правильность прогнозов, применив модель Ridge к данным, включающим взаимодействия, и данным без взаимодействий:
[In 30]: from sklearn.linear_model import Ridge ridge = Ridge().fit(X_train_scaled, y_train) print("Правильность на тестовом наборе без взаимодействий: {:.3f}".format( ridge.score(X_test_scaled, y_test))) ridge = Ridge().fit(X_train_poly, y_train) print("Правильность на тестовом наборе с взаимодействиями: {:.3f}".format( ridge.score(X_test_poly, y_test))) Правильность на тестовом наборе без взаимодействий: 0.621 Правильность на тестовом наборе с взаимодействиями: 0.753
Очевидно, что в случае с гребневой регрессией взаимодействия и полиномиальные признаки позволяют улучшить правильность модели. Впрочем, применение более сложной модели типа случайного леса дает немного другой результат:
[In 31]: from sklearn.ensemble import RandomForestRegressor rf = RandomForestRegressor(n_estimators=100).fit(X_train_scaled, y_train) print(("Правильность на тестовом наборе без взаимодействий: {:.3f}".format( rf.score(X_test_scaled, y_test))) rf = RandomForestRegressor(n_estimators=100).fit(X_train_poly, y_train) print(("Правильность на тестовом наборе с взаимодействиями: {:.3f}".format( rf.score(X_test_poly, y_test))) Правильность на тестовом наборе без взаимодействий: 0.818 Правильность на тестовом наборе с взаимодействиями: 0.759
Видно, что даже без дополнительных признаков случайный лес дает более высокую правильность прогнозов, чем гребневая регрессия. Включение взаимодействий и полиномов на самом деле немного уменьшает правильность прогнозов.
На следующем шаге мы рассмотрим одномерные нелинейные преобразования.