Sklearn RFE, конвейер и перекрестная проверка

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

Я нашел пример того, как использовать RFECV для автоматического выбора идеального количества функций, и он выглядит примерно так:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.feature_selection import RFECV


rfecv = RFECV(estimator=RandomForestClassifier(random_state=101), step=1, cv=StratifiedKFold(10), scoring='accuracy')
rfecv.fit(X, target)
print(np.where(rfecv.support_ == False)[0])

что я нахожу довольно простым.

Однако я проверял, как сделать то же самое с помощью объекта RFE, но для включения перекрестной проверки я нашел только решения, связанные с использованием конвейеров, например:

X, y = make_regression(n_samples=1000, n_features=10, n_informative=5, random_state=1)
# create pipeline
rfe = RFE(estimator=DecisionTreeRegressor(), n_features_to_select=5)
model = DecisionTreeRegressor()
pipeline = Pipeline(steps=[('s',rfe),('m',model)])
# evaluate model
cv = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)
n_scores = cross_val_score(pipeline, X, y, scoring='neg_mean_absolute_error', cv=cv, n_jobs=-1, error_score='raise')

# report performance
print(f'MAE: {mean(n_scores):.3f}')

Я не уверен, что именно здесь происходит. Конвейер используется для постановки в очередь алгоритма RFE и второго DecisionTreeRegressor (модели). Если я не ошибаюсь, идея состоит в том, что для каждой итерации перекрестной проверки выполняется RFE, выбирается желаемое количество лучших функций, а затем запускается вторая модель, используя только эти функции. Но как и когда RFE передал информацию о том, какие функции были выбраны, в DecisionTreeRegressor? Это вообще произошло, или в коде отсутствует эта часть?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
1 735
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну, во-первых, давайте отметим, что RFECV и RFE выполняют в вашем скрипте две отдельные задачи: первая выбирает оптимальное количество функций, а вторая выбирает пять наиболее важных функций (или наилучшую комбинацию из 5 функций). , учитывая их важность для DecisionTreeRegressor).

Вернемся к вашему вопросу: «Когда RFE передал информацию о том, какие функции были выбраны, в дерево решений?» Стоит отметить, что RFE явно не сообщает дереву решений, какие функции выбраны. Проще говоря, он берет матрицу в качестве входных данных (обучающий набор) и преобразует ее в матрицу из N столбцов на основе параметра n_features_to_select=N. Эта матрица (то есть преобразованный обучающий набор) передается в качестве входных данных в дерево решений вместе с целевой переменной, которая возвращает подобранную модель, которую можно использовать для прогнозирования невидимых случаев.

Давайте погрузимся в пример для классификации:

""" Import dependencies and load data """
import numpy as np
import pandas as pd

from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import RFE
from sklearn.metrics import precision_score
from sklearn.tree import DecisionTreeClassifier

X, y = load_breast_cancer(return_X_y=True)
rfe = RFE(estimator=DecisionTreeClassifier(), n_features_to_select=2)

Теперь мы загрузили набор данных breast_cancer и создали экземпляр объекта RFE (я использовал DecisionTreeClassifier, но можно использовать и другие алгоритмы).

Чтобы увидеть, как обучающие данные обрабатываются в конвейере, давайте начнем с ручного примера, который показывает, как конвейер будет работать, если его разложить на «основные шаги»:

from sklearn.model_selection import train_test_split

def test_and_train(X, y, random_state):
    # For simplicity, let's use 80%-20% splitting
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=random_state)

    # Fit and transform the training data by applying Recursive Feature Elimination
    X_train_transformed = rfe.fit_transform(X_train, y_train)
    # Transform the testing data to select the same features
    X_test_transformed = rfe.transform(X_test)  

    print(X_train[0:3])
    print(X_train_transformed[0:3])
    print(X_test_transformed[0:3])

    # Train on the transformed trained data
    fitted_model = DecisionTreeClassifier().fit(X_train_transformed, y_train)

    # Predict on the transformed testing data
    y_pred = fitted_model.predict(X_test_transformed)

    print('True labels: ', y_test)
    print('Predicted labels:', y_pred)

    return y_test, y_pred

precisions = list() # to store the precision scores (can be replaced by any other evaluation measure)

y_test, y_pred = test_and_train(X, y, 42)
precisions.append(precision_score(y_test, y_pred))

y_test, y_pred = test_and_train(X, y, 84)
precisions.append(precision_score(y_test, y_pred))

y_test, y_pred = test_and_train(X, y, 168)
precisions.append(precision_score(y_test, y_pred))

print('Average precision:', np.mean(precisions))
"""
Average precision: 0.92
"""

В приведенном выше скрипте мы создали функцию, которая с учетом набора данных X и целевой переменной y

  1. Создает набор для обучения и тестирования, следуя правилу разделения 80%-20%.
  2. Преобразует их с помощью RFE (т. е. выбирает две лучшие функции, как указано в предыдущем фрагменте кода). При вызове fit_transform на RFE он запускает рекурсивное устранение признаков и сохраняет информацию о выбранных признаках в состоянии своего объекта. Чтобы узнать, какие функции выбраны, звоните rfe.support_. Примечание. В тестовом наборе выполняется только преобразование, поэтому функции в rfe.support_ используются для фильтрации других функций из тестового набора.
  3. Соответствует модели и возвращает кортеж (y_test, y_pred).

y_test и y_pred можно использовать для анализа производительности модели, например, ее точности. Точность сохраняется в массиве, и процедура повторяется 3 раза. Наконец, мы печатаем среднюю точность.

Мы смоделировали процедуру перекрестной проверки, разделив исходные данные 3 раза в соответствующих наборах для обучения и тестирования, подогнали модель, вычислили и усреднили ее производительность (то есть точность) по трем кратностям. Этот процесс можно упростить с помощью проверки RepeatedKFold:

from sklearn.model_selection import RepeatedKFold

precisions = list()
rkf = RepeatedKFold(n_splits=2, n_repeats=3, random_state=1)

for train_index, test_index in rkf.split(X, y):
    # print("TRAIN:", train_index, "TEST:", test_index)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    
    X_train_transformed = rfe.fit_transform(X_train, y_train)
    X_test_transformed = rfe.transform(X_test)
    
    fitted_model = DecisionTreeClassifier().fit(X_train_transformed, y_train)
    y_pred = fitted_model.predict(X_test_transformed)

    precisions.append(precision_score(y_test, y_pred))

print('Average precision:', np.mean(precisions))
"""
Average precision: 0.93
"""

и даже дальше с Pipeline:

from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score

rkf = RepeatedKFold(n_splits=2, n_repeats=3, random_state=1)
pipeline = Pipeline(steps=[('s',rfe),('m',DecisionTreeClassifier())])
precisions = cross_val_score(pipeline, X, y, scoring='precision', cv=rkf)

print('Average precision:', np.mean(precisions))
"""
Average precision: 0.93
"""

Таким образом, когда исходные данные передаются в конвейер, последний:

  1. разбивает его на данные обучения и тестирования;
  2. вызывает RFE.fit_transform() данные обучения;
  3. применяет RFE.transform() к данным тестирования, чтобы они состояли из одних и тех же функций;
  4. вызывает estimator.fit() данные обучения, чтобы подогнать (т. е. обучить) модель;
  5. вызывает estimator.predict() данные тестирования, чтобы предсказать их.
  6. сравнивает прогнозы с фактическими значениями и сохраняет результаты производительности (тот, который вы передали параметру scoring) внутри.
  7. Повторяет шаги 1–6 для каждого разделения в процедуре перекрестной проверки.

В конце процедуры кто-то может получить доступ к результатам производительности и усреднить их по складкам.

Вау, большое спасибо, вы действительно не могли бы быть более исчерпывающим, чем это! Я полностью пропустил часть, где конвейер использует fit_transform для обучающих данных... теперь, когда вы объяснили эту часть, все стало понятно. Грэйзи Милле!

Carlo 16.12.2020 13:28

@s.dallapalma Пожалуйста, не могли бы вы помочь мне с этим вопросом? stackoverflow.com/questions/71279499/…

user140259 03.03.2022 14:28

«Мы смоделировали процедуру перекрестной проверки, разделив исходные данные 3 раза в соответствующем наборе для обучения и тестирования». Мне кажется, что исходные данные разделяются два раза, и каждый повторяется 3 раза, что дает в общей сложности 6 результатов. .

user140259 03.03.2022 14:59

Другие вопросы по теме