Учебное пособие по Scikit-Learn: установка и примеры Scikit-Learn

⚡ Умное резюме

Scikit-learn — это проект с открытым исходным кодом. Python Библиотека, охватывающая предварительную обработку, классификацию, регрессию, кластеризацию и выбор модели, объединена единым согласованным интерфейсом оценщика, что делает весь рабочий процесс машинного обучения коротким, понятным и воспроизводимым — от исходных данных до прогнозов с оценкой.

  • 🔘 Установка: Conda и pip работают, и текущая стабильная версия уже содержит все используемые здесь преобразователи.
  • ☑️ Обработанный набор данных: В качестве основы для всех примеров в этом пошаговом руководстве используется файл переписи взрослого населения Калифорнийского университета в Ирвайне (UCI), содержащий 32 561 строку.
  • Трубопроводы: Функция make_column_transformer масштабирует числовые столбцы и выполняет one-hot кодирование категориальных столбцов в одном объекте.
  • 🧪 Настройка: Метод GridSearchCV выполняет полный обход сетки параметров, в то время как RandomizedSearchCV делает выборки и завершает работу гораздо быстрее.
  • 🇧🇷 Три модели: Результаты логистической регрессии: 0.850891, XGBoost: 0.873157, сеть MLPClassifier: 0.821253.
  • ⚠️ Объяснимость: LIME показывает, какие признаки склонили конкретное предсказание к определенному классу, включая ошибочные.

Учебное пособие по Scikit-learn с пошаговой инструкцией по установке и примерами работы.

Что такое Scikit-learn?

Scikit учиться это открытый исходный код Python библиотека для машинного обучения илиОн поддерживает хорошо зарекомендовавшие себя алгоритмы, такие как KNN, градиентный бустинг, случайный лес и SVM, и построен на основе NumPy и SciPy. Scikit-learn широко используется в соревнованиях Kaggle, а также в ведущих технологических компаниях. Он охватывает предварительную обработку данных, снижение размерности, классификацию, регрессию, кластеризацию и выбор модели.

Библиотека Scikit-learn обладает одной из лучших документаций среди всех библиотек с открытым исходным кодом. Она даже предоставляет интерактивную диаграмму оценки. Выбор подходящего оценщикаЭто пошагово поможет вам определить размер вашего набора данных и составить список алгоритмов, которые стоит попробовать.

На рисунке ниже показан принцип работы библиотеки Scikit-learn.

Как работает Scikit-learn в процессе машинного обучения

Scikit-learn прост в использовании и дает отличные результаты. Однако он обучается на ЦП: работа распараллеливается по ядрам с помощью аргумента n_jobs, а не на графическом процессоре. Запуск алгоритма глубокого обучения с его помощью возможен, но редко бывает оптимальным, особенно если вы уже знаете, как его использовать. TensorFlow.

Как загрузить и установить Scikit-learn

Теперь в этом Python В этом руководстве по Scikit-learn вы узнаете, как скачать и установить Scikit-learn:

Вариант 1: AWS

Scikit-learn можно использовать на AWS. Образ Docker с предустановленным scikit-learn полностью избавляет от необходимости выполнять настройку.

Для установки версии для разработчиков выполните следующую команду. Jupyter:

import sys
!{sys.executable} -m pip install git+git://github.com/scikit-learn/scikit-learn.git

Вариант 2: Mac или Windows используя Анаконду

Чтобы узнать об установке Anaconda, обратитесь к следующему разделу. Как скачать и установить TensorFlow.

На момент написания этого руководства разработчики scikit выпустили версию для разработчиков, в которой были исправлены проблемы, присутствовавшие в текущей версии, поэтому в описании ниже используется именно эта сборка для разработчиков. На современной чистой машине текущая стабильная версия уже содержит все используемые здесь преобразователи, и pip install -U scikit-learn достаточно.

Как установить scikit-learn в среде Conda

Если вы установили scikit-learn через среду conda, выполните следующие действия, чтобы обновить его до версии 0.20.

Шаг 1) Активируйте среду TensorFlow.

source activate hello-tf

Шаг 2) Удалите scikit-learn с помощью команды conda.

conda remove scikit-learn

Шаг 3) Установите версию для разработчиков.

Установите версию scikit-learn для разработчиков вместе с необходимыми библиотеками.

conda install -c anaconda git
pip install Cython
pip install h5py
pip install git+git://github.com/scikit-learn/scikit-learn.git

ПРИМЕЧАНИЕ: Windows пользователям необходимо Microsoft визуальный C++ 14. Вы можете это получить. здесь.

Пример Scikit-Learn с машинным обучением

Это руководство по Scikit разделено на две части:

  1. Машинное обучение с scikit-learn
  2. Как доверить свою модель с LIME

В первой части подробно описывается, как построить конвейер обработки данных, создать модель и настроить гиперпараметры, а во второй части рассматривается интерпретация модели.

Шаг 1) Импортируйте данные

В этом обучающем руководстве по Scikit-learn вы будете использовать набор данных переписи взрослого населения.

В приведенном ниже коде файл считывается непосредственно из репозитория машинного обучения UCI, поэтому ручная загрузка не требуется. Если вас интересуют описательные статистические данные, стоит обратить внимание на инструменты Dive и Overview. См. этот учебник Чтобы узнать больше о погружениях и обзоре.

Импортируйте набор данных с помощью pandas. Обратите внимание, что необходимо преобразовать непрерывные переменные в формат с плавающей запятой.

Этот набор данных включает восемь категориальных переменных, перечисленных в CATE_FEATURES:

  • рабочий класс
  • образование
  • брачный
  • оккупация
  • отношения
  • раса
  • секс
  • родная страна

Он также включает шесть непрерывных переменных, перечисленных в CONTI_FEATURES:

  • возраст
  • фнлвгт
  • образование_номер
  • прирост капитала
  • капитал_убыток
  • часы_неделя

Здесь списки заполняются вручную, чтобы у вас было более ясное представление о том, какие столбцы используются. Более быстрый способ составить список категориальных или непрерывных столбцов:

## List Categorical
CATE_FEATURES = df_train.iloc[:,:-1].select_dtypes('object').columns
print(CATE_FEATURES)

## List continuous
CONTI_FEATURES =  df_train._get_numeric_data()
print(CONTI_FEATURES)

Вот код для импорта данных:

# Import dataset
import pandas as pd

## Define path data
COLUMNS = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital',
           'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
           'hours_week', 'native_country', 'label']
### Define continuous list
CONTI_FEATURES  = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week']
### Define categorical list
CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country']

## Prepare the data
features = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital',
           'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
           'hours_week', 'native_country']

PATH = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data"

df_train = pd.read_csv(PATH, skipinitialspace=True, names = COLUMNS, index_col=False)
df_train[CONTI_FEATURES] =df_train[CONTI_FEATURES].astype('float64')
df_train.describe()

Вызов функции describe() для фрейма возвращает сводную статистику по шести непрерывным столбцам:

возраст фнлвгт образование_номер прирост капитала капитал_убыток часы_неделя
считать 32561.000000 3.256100e + 04 32561.000000 32561.000000 32561.000000 32561.000000
значить 38.581647 1.897784e + 05 10.080679 1077.648844 87.303830 40.437456
станд 13.640433 1.055500e + 05 2.572720 7385.292085 402.960219 12.347429
мин 17.000000 1.228500e + 04 1.000000 0.000000 0.000000 1.000000
25% 28.000000 1.178270e + 05 9.000000 0.000000 0.000000 40.000000
50% 37.000000 1.783560e + 05 10.000000 0.000000 0.000000 40.000000
75% 48.000000 2.370510e + 05 12.000000 0.000000 0.000000 45.000000
Макс 90.000000 1.484705e + 06 16.000000 99999.000000 4356.000000 99.000000

Вы можете проверить количество уникальных значений признака native_country. Только одно домохозяйство относится к категории Голландия-Нидерланды. Это домохозяйство не предоставляет никакой информации и вызовет ошибку во время обучения.

df_train.native_country.value_counts()
United-States                 29170
Mexico                          643
?                               583
Philippines                     198
Germany                         137
Canada                          121
Puerto-Rico                     114
El-Salvador                     106
India                           100
Cuba                             95
England                          90
Jamaica                          81
South                            80
China                            75
Italy                            73
Dominican-Republic               70
Vietnam                          67
Guatemala                        64
Japan                            62
Poland                           60
Columbia                         59
Taiwan                           51
Haiti                            44
Iran                             43
Portugal                         37
Nicaragua                        34
Peru                             31
France                           29
Greece                           29
Ecuador                          28
Ireland                          24
Hong                             20
Cambodia                         19
Trinadad&Tobago                  19
Thailand                         18
Laos                             18
Yugoslavia                       16
Outlying-US(Guam-USVI-etc)       14
Honduras                         13
Hungary                          13
Scotland                         12
Holand-Netherlands                1
Name: native_country, dtype: int64

Вы можете исключить эту неинформативную строку из набора данных:

## Drop Netherland, because only one row
df_train = df_train[df_train.native_country != "Holand-Netherlands"]

Далее вы сохраняете положение непрерывных элементов в списке. Он понадобится вам на следующем этапе построения конвейера.

Приведённый ниже код перебирает все имена столбцов в списке CONTI_FEATURES, считывает каждое местоположение (то есть номер столбца) и добавляет его в список с именем conti_features.

## Get the column index of the categorical features
conti_features = []
for i in CONTI_FEATURES:
    position = df_train.columns.get_loc(i)
    conti_features.append(position)
print(conti_features)  
[0, 2, 10, 4, 11, 12]

Следующий блок выполняет ту же работу для категориальных переменных.

## Get the column index of the categorical features
categorical_features = []
for i in CATE_FEATURES:
    position = df_train.columns.get_loc(i)
    categorical_features.append(position)
print(categorical_features)  
[1, 3, 5, 6, 7, 8, 9, 13]

Теперь рассмотрим сам набор данных. Каждая категориальная характеристика представляет собой строку, а модели нельзя передать строковое значение, поэтому набор данных необходимо преобразовать с помощью фиктивных переменных.

df_train.head(5)

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

print(df_train[CATE_FEATURES].nunique(),
      'There are',sum(df_train[CATE_FEATURES].nunique()), 'groups in the whole dataset')
workclass          9
education         16
marital            7
occupation        15
relationship       6
race               5
sex                2
native_country    41
dtype: int64 There are 101 groups in the whole dataset

Весь набор данных содержит 101 группу, как показано выше. Только признак workclass имеет девять групп. Вы можете перечислить названия групп с помощью приведенного ниже кода; функция unique() возвращает уникальные значения каждого категориального признака.

for i in CATE_FEATURES:
    print(df_train[i].unique())
['State-gov' 'Self-emp-not-inc' 'Private' 'Federal-gov' 'Local-gov' '?'
 'Self-emp-inc' 'Without-pay' 'Never-worked']
['Bachelors' 'HS-grad' '11th' 'Masters' '9th' 'Some-college' 'Assoc-acdm'
 'Assoc-voc' '7th-8th' 'Doctorate' 'Prof-school' '5th-6th' '10th'
 '1st-4th' 'Preschool' '12th']
['Never-married' 'Married-civ-spouse' 'Divorced' 'Married-spouse-absent'
 'Separated' 'Married-AF-spouse' 'Widowed']
['Adm-clerical' 'Exec-managerial' 'Handlers-cleaners' 'Prof-specialty'
 'Other-service' 'Sales' 'Craft-repair' 'Transport-moving'
 'Farming-fishing' 'Machine-op-inspct' 'Tech-support' '?'
 'Protective-serv' 'Armed-Forces' 'Priv-house-serv']
['Not-in-family' 'Husband' 'Wife' 'Own-child' 'Unmarried' 'Other-relative']
['White' 'Black' 'Asian-Pac-Islander' 'Amer-Indian-Eskimo' 'Other']
['Male' 'Female']
['United-States' 'Cuba' 'Jamaica' 'India' '?' 'Mexico' 'South'
 'Puerto-Rico' 'Honduras' 'England' 'Canada' 'Germany' 'Iran'
 'Philippines' 'Italy' 'Poland' 'Columbia' 'Cambodia' 'Thailand' 'Ecuador'
 'Laos' 'Taiwan' 'Haiti' 'Portugal' 'Dominican-Republic' 'El-Salvador'
 'France' 'Guatemala' 'China' 'Japan' 'Yugoslavia' 'Peru'
 'Outlying-US(Guam-USVI-etc)' 'Scotland' 'Trinadad&Tobago' 'Greece'
 'Nicaragua' 'Vietnam' 'Hong' 'Ireland' 'Hungary']

Таким образом, обучающий набор данных будет содержать 101 + 6 столбцов: группы, полученные методом one-hot кодирования, плюс шесть непрерывных признаков.

Библиотека Scikit-learn может выполнить преобразование в два этапа:

  1. Преобразуйте строку в идентификатор. State-gov становится ID 1, Self-emp-not-inc — ID 2 и так далее. LabelEncoder сделает это за вас.
  2. Преобразуйте каждый идентификатор в новый столбец. Набор данных содержит 101 идентификатор группы, поэтому будет 101 столбец, охватывающий каждую группу категориальных признаков. Для этой операции Scikit-learn предоставляет OneHotEncoder.

Шаг 2) Создайте набор поездов/тестов.

Теперь, когда набор данных готов, разделите его в соотношении 80/20: 80 процентов для обучающей выборки и 20 процентов для тестовой выборки.

Вы можете использовать функцию train_test_split. Первый аргумент — это датафрейм с признаками, а второй — метка. Размер тестового набора задаётся с помощью параметра test_size.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(df_train[features],
                                                    df_train.label,
                                                    test_size = 0.2,
                                                    random_state=0)
X_train.head(5)
print(X_train.shape, X_test.shape)
(26048, 14) (6512, 14)

Шаг 3) Создайте конвейер

Конвейер обработки данных упрощает подачу в модель согласованных данных. Идея заключается в том, чтобы пропускать необработанные данные через один объект, который выполняет все операции по порядку.

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

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

from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoder
from sklearn.compose import ColumnTransformer, make_column_transformer
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression

Перед передачей данных в логистический классификатор конвейер выполняет две операции:

  1. Стандартизируйте переменную: StandardScaler()
  2. Преобразуйте категориальные функции: OneHotEncoder(sparse=False)

Оба шага выполняются с помощью функции make_column_transformer. На момент написания этого руководства данная функция не входила в выпущенную версию scikit-learn (0.19), поэтому использовалась сборка для разработчиков; она включена во все стабильные релизы, начиная с версии 0.20.

Функция make_column_transformer проста: вы указываете, какие столбцы нужно преобразовать и какое преобразование применить. Для стандартизации непрерывных признаков вы передаете:

  • conti_features, StandardScaler() внутри make_column_transformer
    • conti_features: список непрерывных столбцов
    • StandardScaler: стандартизирует эти столбцы.

Объект OneHotEncoder внутри функции make_column_transformer автоматически кодирует метки.

preprocess = make_column_transformer(
    (conti_features, StandardScaler()),
    ### Need to be numeric not string to specify columns name 
    (categorical_features, OneHotEncoder(sparse=False))
)

Примечание к версии: Два аргумента в блоке выше были изменены. В текущих версиях сначала ожидается преобразователь, а затем столбцы, и редкий Было переименовано разреженный_вывод В scikit-learn 1.2 это было удалено, а в версии 1.4 удалено, поэтому в более новом коде это выглядит так: OneHotEncoder(sparse_output=False).

Вы можете проверить работоспособность конвейера с помощью функции fit_transform. Выходные данные должны иметь форму 26048, 107.

preprocess.fit_transform(X_train).shape
(26048, 107)

Трансформатор данных готов. Вы создаете конвейер с помощью функции make_pipeline, и после преобразования данных передаете их в модель логистической регрессии.

model = make_pipeline(
    preprocess,
    LogisticRegression())

Обучение модели с помощью scikit-learn в этом случае становится тривиальным: достаточно вызвать метод fit в конвейере. Точность можно распечатать с помощью метода score.

model.fit(X_train, y_train)
print("logistic regression score: %f" % model.score(X_test, y_test))
logistic regression score: 0.850891

Наконец, вы можете предсказать классы с помощью функции predict_proba, которая возвращает вероятность каждого класса. Обратите внимание, что сумма двух вероятностей равна единице.

model.predict_proba(X_test)
array([[0.83576663, 0.16423337],
       [0.94582765, 0.05417235],
       [0.64760587, 0.35239413],
       ...,
       [0.99639252, 0.00360748],
       [0.02072181, 0.97927819],
       [0.56781353, 0.43218647]])

Шаг 4) Использование нашего конвейера для поиска по сетке

Настройка гиперпараметров — значений, определяющих структуру модели, — может быть утомительной и сложной задачей.

Один из способов оценить модель — изменить размер обучающего набора данных и измерить производительность, повторив упражнение десять раз, чтобы увидеть разброс результатов. Это требует значительных ручных усилий.

Вместо этого scikit-learn предоставляет функции, которые выполняют настройку параметров и перекрестную проверку за вас.

Перекрестная проверка

Перекрестная проверка означает, что во время обучения обучающий набор данных разбивается n раз на фолды, и модель оценивается n раз. Если значение перекрестной проверки установлено равным 10, модель обучается и оценивается десять раз. В каждом раунде классификатор обучается на девяти случайно выбранных фолдах, а десятый фолд используется для оценки.

Поиск по сетке

Каждый классификатор имеет гиперпараметры для настройки. Вы можете пробовать значения по одному или задать сетку параметров. В документации scikit-learn перечислены все параметры, которые принимает логистический классификатор. Для ускорения обучения в этом примере настраивается только параметр C, который управляет регуляризацией. Он должен быть положительным, и небольшое значение дает больший вес регуляризатору.

Вы используете объект GridSearchCV, который принимает словарь гиперпараметров для настройки. Перечислите каждый гиперпараметр, а затем значения, которые вы хотите попробовать. Для настройки C вы пишете:

  • 'logisticregression__C': [0.001, 0.01, 0.1, 1.0] — перед именем параметра стоит имя классификатора в нижнем регистре и два символа подчеркивания.

Модель будет пробовать четыре различных значения: 0.001, 0.01, 0.1 и 1. Она обучается с использованием 10 фолдов, то есть cv=10.

from sklearn.model_selection import GridSearchCV
# Construct the parameter grid
param_grid = {
    'logisticregression__C': [0.001, 0.01,0.1, 1.0],
    }

Теперь вы можете обучить модель, используя GridSearchCV с параметрами grid и cv.

# Train the model
grid_clf = GridSearchCV(model,
                        param_grid,
                        cv=10,
                        iid=False)
grid_clf.fit(X_train, y_train)

Выход:

GridSearchCV(cv=10, error_score='raise-deprecating',
       estimator=Pipeline(memory=None,
     steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None,
         transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,...ty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False))]),
       fit_params=None, iid=False, n_jobs=1,
       param_grid={'logisticregression__C': [0.001, 0.01, 0.1, 1.0]},
       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
       scoring=None, verbose=0)

Примечание к версии: н.о.р. Аргумент, видимый в этом выводе, был объявлен устаревшим в scikit-learn 0.22 и удален в версии 0.24, поэтому его следует просто удалить из вызова GridSearchCV в текущих релизах.

Для выбора оптимальных параметров используйте функцию best_params_.

grid_clf.best_params_

Выход:

{'logisticregression__C': 1.0}

После обучения модели с четырьмя различными значениями регуляризации оптимальный параметр дает следующее:

print("best logistic regression from grid search: %f" % grid_clf.best_estimator_.score(X_test, y_test))

лучшая логистическая регрессия из поиска по сетке: 0.850891

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

grid_clf.best_estimator_.predict_proba(X_test)
array([[0.83576677, 0.16423323],
       [0.9458291 , 0.0541709 ],
       [0.64760416, 0.35239584],
       ...,
       [0.99639224, 0.00360776],
       [0.02072033, 0.97927967],
       [0.56782222, 0.43217778]])

Модель XGBoost с scikit-learn

Теперь попробуйте один из самых мощных классификаторов на рынке. XGBoost — это улучшенная версия случайного леса, использующая градиентный бустинг. Его теоретические основы выходят за рамки данной статьи. Python Это руководство по Scikit, но имейте в виду, что XGBoost выиграл множество соревнований на Kaggle. На наборе данных среднего размера он может показать результаты, сравнимые с алгоритмами глубокого обучения, или даже лучше.

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

В данном случае лучшим вариантом является RandomizedSearchCV. GridSearchCV замедляется при больших размерах сетки, поскольку пространство поиска увеличивается с добавлением каждого параметра. RandomizedSearchCV же выбирает значения каждого гиперпараметра случайным образом на каждой итерации, поэтому 1,000 итераций оценивают 1,000 комбинаций. В остальном он работает во многом так же, как GridSearchCV.

Вам необходимо импортировать xgboost. Если библиотека не установлена, выполните команду pip3 install xgboost или установите её из репозитория. Jupyter блокнот со следующим содержимым:

use import sys
!{sys.executable} -m pip install xgboost

Затем импортируйте классификатор и два вспомогательных инструмента поиска:

import xgboost
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import StratifiedKFold

Следующий шаг в этом Scikit Python В этом руководстве показано, как указать параметры для настройки. В официальной документации XGBoost перечислены все эти параметры. Для простоты изложения в данном случае... Python В руководстве по Sklearn вы выбираете только два гиперпараметра с двумя значениями каждый, потому что обучение XGBoost занимает много времени, и каждая дополнительная точка сетки увеличивает время ожидания.

params = {
        'xgbclassifier__gamma': [0.5, 1],
        'xgbclassifier__max_depth': [3, 4]
        }

Затем вы создаете новый конвейер с классификатором XGBoost и 600 оценщиками. Параметр n_estimators можно настроить, и его высокое значение может привести к переобучению. Вы можете попробовать другие значения, но имейте в виду, что это может занять несколько часов. Все остальные параметры сохраняют свои значения по умолчанию.

model_xgb = make_pipeline(
    preprocess,
    xgboost.XGBClassifier(
                          n_estimators=600,
                          objective='binary:logistic',
                          silent=True,
                          nthread=1)
)

Вы можете улучшить перекрестную проверку с помощью стратифицированной K-складчатой ​​перекрестной проверки. Здесь используются только три складки для ускорения вычислений, но с некоторым ухудшением качества; для лучших результатов увеличьте их количество до 5 или 10 на вашем компьютере. Модель обучается в течение четырех итераций.

skf = StratifiedKFold(n_splits=3,
                      shuffle = True,
                      random_state = 1001)

random_search = RandomizedSearchCV(model_xgb,
                                   param_distributions=params,
                                   n_iter=4,
                                   scoring='accuracy',
                                   n_jobs=4,
                                   cv=skf.split(X_train, y_train),
                                   verbose=3,
                                   random_state=1001)

Метод случайного поиска готов, так что вы можете обучать модель.

#grid_xgb = GridSearchCV(model_xgb, params, cv=10, iid=False)
random_search.fit(X_train, y_train)
Fitting 3 folds for each of 4 candidates, totalling 12 fits
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8759645283888057, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8729701715996775, total= 1.0min
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=0.5, score=0.8706519235199263, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5 ............
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8735460094437406, total= 1.3min
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8722791661868018, total=  57.7s
[CV] xgbclassifier__max_depth=3, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8753886905447426, total= 1.0min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8697304768486523, total= 1.3min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=0.5, score=0.8740066797189912, total= 1.4min
[CV] xgbclassifier__max_depth=4, xgbclassifier__gamma=1 ..............
[CV]  xgbclassifier__max_depth=3, xgbclassifier__gamma=1, score=0.8707671043538355, total= 1.0min
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8729701715996775, total= 1.2min
[Parallel(n_jobs=4)]: Done  10 out of  12 | elapsed:  3.6min remaining:   43.5s
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8736611770125533, total= 1.2min
[CV]  xgbclassifier__max_depth=4, xgbclassifier__gamma=1, score=0.8692697535130154, total= 1.2min
[Parallel(n_jobs=4)]: Done  12 out of  12 | elapsed:  3.6min finished
/Users/Thomas/anaconda3/envs/hello-tf/lib/python3.6/site-packages/sklearn/model_selection/_search.py:737: DeprecationWarning: The default of the `iid` parameter will change from True to False in version 0.22 and will be removed in 0.24. This will change numeric results when test-set sizes are unequal. DeprecationWarning)
RandomizedSearchCV(cv=<generator object _BaseKFold.split at 0x1101eb830>,
          error_score='raise-deprecating',
          estimator=Pipeline(memory=None,
     steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None,
         transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,...
       reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
       silent=True, subsample=1))]),
          fit_params=None, iid='warn', n_iter=4, n_jobs=4,
          param_distributions={'xgbclassifier__gamma': [0.5, 1], 'xgbclassifier__max_depth': [3, 4]},
          pre_dispatch='2*n_jobs', random_state=1001, refit=True,
          return_train_score='warn', scoring='accuracy', verbose=3)

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

print("лучших parameter", random_search.best_params_)
print("best logistic regression from grid search: %f" % random_search.best_estimator_.score(X_test, y_test))
лучших parameter {'xgbclassifier__max_depth': 3, 'xgbclassifier__gamma': 0.5}
best logistic regression from grid search: 0.873157
random_search.best_estimator_.predict(X_test)
array(['<=50K', '<=50K', '<=50K', ..., '<=50K', '>50K', '<=50K'],      dtype=object)

Создайте DNN с помощью MLPClassifier в scikit-learn

Наконец, вы можете обучить нейронную сеть с помощью самого scikit-learn. Метод тот же, что и для любого другого классификатора, а в качестве оценщика используется MLPClassifier.

from sklearn.neural_network import MLPClassifier

Приведенная ниже сеть определяется следующим образом:

  • Адам решатель
  • Функция активации ReLU
  • Альфа = 0.0001
  • Размер партии: 150
  • Два скрытых слоя по 200 и 100 нейронов соответственно
model_dnn = make_pipeline(
    preprocess,
    MLPClassifier(solver='adam',
                  alpha=0.0001,
                  activation='relu',
                    batch_size=150,
                    hidden_layer_sizes=(200, 100),
                    random_state=1))

Вы можете изменить количество слоев, чтобы улучшить модель.

model_dnn.fit(X_train, y_train)
  print("DNN regression score: %f" % model_dnn.score(X_test, y_test))

Оценка регрессии DNN: 0.821253

LIME: Доверяйте своей модели

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

Три исследователя разработали инструмент, демонстрирующий, как компьютер приходит к прогнозу. Их статья называется... «Почему я должен вам доверять?», а опубликованный ими алгоритм называется «Локальные интерпретируемые модельно-независимые объяснения» (LIME).

Рассмотрим пример. Иногда вы не знаете, можно ли доверять прогнозу, полученному с помощью машинного обучения. Врач не может принять диагноз только потому, что его поставил компьютер, и вам необходимо знать, насколько надежна модель, прежде чем внедрять ее в производство.

Представьте, что вы можете увидеть, почему тот или иной классификатор сделал тот или иной прогноз, даже для таких сложных моделей, как нейронные сети, случайные леса или SVM с произвольным ядром. Доверять прогнозу становится гораздо проще, когда причины, лежащие в его основе, видны, и так же легко решить, когда модели не следует доверять. LIME показывает, какие признаки повлияли на решение классификатора.

Подготовка данных

Для запуска LIME с определенными параметрами необходимо внести несколько изменений. PythonСначала установите Lime в терминале с помощью команды `pip install lime`.

Lime использует объект LimeTabularExplainer для локального приближения модели. Для работы этого объекта требуется:

  • набор данных в NumPy формат
  • Название функций: Feature_names
  • Название классов: class_names
  • Индекс столбца категориальных признаков: categorical_features
  • Название группы для каждого категориального признака: categorical_names

Создайте набор поездов на основе NumPy.

Вы можете очень легко скопировать и преобразовать df_train из pandas в NumPy.

df_train.head(5)
# Create numpy data
df_lime = df_train
df_lime.head(3)

Получить имя класса

Доступ к метке осуществляется через функцию unique(). Вы должны увидеть:

  • '<= 50 КБ'
  • '> 50K'
# Get the class name
class_names = df_lime.label.unique()
class_names
array(['<=50K', '>50K'], dtype=object)

Проиндексируйте столбцы с категориальными признаками.

Используйте изученный ранее метод, чтобы получить название каждой группы. Закодируйте метку с помощью LabelEncoder и повторите операцию для каждого категориального признака.

## 
import sklearn.preprocessing as preprocessing
categorical_names = {}
for feature in CATE_FEATURES:
    le = preprocessing.LabelEncoder()
    le.fit(df_lime[feature])
    df_lime[feature] = le.transform(df_lime[feature])
    categorical_names[feature] = le.classes_
print(categorical_names)    
{'workclass': array(['?', 'Federal-gov', 'Local-gov', 'Never-worked', 'Private',
       'Self-emp-inc', 'Self-emp-not-inc', 'State-gov', 'Without-pay'],
      dtype=object), 'education': array(['10th', '11th', '12th', '1st-4th', '5th-6th', '7th-8th', '9th',
       'Assoc-acdm', 'Assoc-voc', 'Bachelors', 'Doctorate', 'HS-grad',
       'Masters', 'Preschool', 'Prof-school', 'Some-college'],
      dtype=object), 'marital': array(['Divorced', 'Married-AF-spouse', 'Married-civ-spouse',
       'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed'],
      dtype=object), 'occupation': array(['?', 'Adm-clerical', 'Armed-Forces', 'Craft-repair',
       'Exec-managerial', 'Farming-fishing', 'Handlers-cleaners',
       'Machine-op-inspct', 'Other-service', 'Priv-house-serv',
       'Prof-specialty', 'Protective-serv', 'Sales', 'Tech-support',
       'Transport-moving'], dtype=object), 'relationship': array(['Husband', 'Not-in-family', 'Other-relative', 'Own-child',
       'Unmarried', 'Wife'], dtype=object), 'race': array(['Amer-Indian-Eskimo', 'Asian-Pac-Islander', 'Black', 'Other',
       'White'], dtype=object), 'sex': array(['Female', 'Male'], dtype=object), 'native_country': array(['?', 'Cambodia', 'Canada', 'China', 'Columbia', 'Cuba',
       'Dominican-Republic', 'Ecuador', 'El-Salvador', 'England',
       'France', 'Germany', 'Greece', 'Guatemala', 'Haiti', 'Honduras',
       'Hong', 'Hungary', 'India', 'Iran', 'Ireland', 'Italy', 'Jamaica',
       'Japan', 'Laos', 'Mexico', 'Nicaragua',
       'Outlying-US(Guam-USVI-etc)', 'Peru', 'Philippines', 'Poland',
       'Portugal', 'Puerto-Rico', 'Scotland', 'South', 'Taiwan',
       'Thailand', 'Trinadad&Tobago', 'United-States', 'Vietnam',
       'Yugoslavia'], dtype=object)}

df_lime.dtypes
age               float64
workclass           int64
fnlwgt            float64
education           int64
education_num     float64
marital             int64
occupation          int64
relationship        int64
race                int64
sex                 int64
capital_gain      float64
capital_loss      float64
hours_week        float64
native_country      int64
label              object
dtype: object

Теперь, когда набор данных готов, вы можете создать различные наборы данных, показанные в примерах Scikit-learn ниже. Преобразование данных происходит вне конвейера, чтобы избежать ошибок с LIME: обучающий набор, передаваемый в LimeTabularExplainer, должен представлять собой массив NumPy без строк, а описанный выше метод уже создал такой массив.

from sklearn.model_selection import train_test_split
X_train_lime, X_test_lime, y_train_lime, y_test_lime = train_test_split(df_lime[features],
                                                    df_lime.label,
                                                    test_size = 0.2,
                                                    random_state=0)
X_train_lime.head(5)

Вы можете создать конвейер обработки данных с оптимальными параметрами, найденными с помощью XGBoost.

model_xgb = make_pipeline(
    preprocess,
    xgboost.XGBClassifier(max_depth = 3,
                          gamma = 0.5,
                          n_estimators=600,
                          objective='binary:logistic',
                          silent=True,
                          nthread=1))

model_xgb.fit(X_train_lime, y_train_lime)
/Users/Thomas/anaconda3/envs/hello-tf/lib/python3.6/site-packages/sklearn/preprocessing/_encoders.py:351: FutureWarning: The handling of integer data will change in version 0.22. Currently, the categories are determined based on the range [0, max(values)], while in the future they will be determined based on the unique values.
If you want the future behavior and silence this warning, you can specify "categories='auto'."In case you used a LabelEncoder before this OneHotEncoder to convert the categories to integers, then you can now use the OneHotEncoder directly.
  warnings.warn(msg, FutureWarning)
Pipeline(memory=None,
     steps=[('columntransformer', ColumnTransformer(n_jobs=1, remainder='drop', transformer_weights=None,
         transformers=[('standardscaler', StandardScaler(copy=True, with_mean=True, with_std=True), [0, 2, 10, 4, 11, 12]), ('onehotencoder', OneHotEncoder(categorical_features=None, categories=None,...
       reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
       silent=True, subsample=1))])

Вы получаете предупреждение. В нем объясняется, что вам не нужно создавать кодировщик меток перед запуском конвейера. Если вы не используете LIME, то подойдет метод из первой части этого руководства по машинному обучению с использованием Scikit-learn. В противном случае, придерживайтесь следующего подхода: сначала создайте закодированный набор данных, а затем примените one-hot кодировщик внутри конвейера.

print("best logistic regression from grid search: %f" % model_xgb.score(X_test_lime, y_test_lime))
best logistic regression from grid search: 0.873157
model_xgb.predict_proba(X_test_lime)
array([[7.9646105e-01, 2.0353897e-01],
       [9.5173013e-01, 4.8269872e-02],
       [7.9344827e-01, 2.0655173e-01],
       ...,
       [9.9031430e-01, 9.6856682e-03],
       [6.4581633e-04, 9.9935418e-01],
       [9.7104281e-01, 2.8957171e-02]], dtype=float32)

Прежде чем использовать LIME, создайте массив NumPy, содержащий признаки строк, неправильно классифицированных. Этот список можно использовать позже, чтобы понять, что ввело классификатор в заблуждение.

temp = pd.concat([X_test_lime, y_test_lime], axis= 1)
temp['predicted'] = model_xgb.predict(X_test_lime)
temp['wrong']=  temp['label'] != temp['predicted']
temp = temp.query('wrong==True').drop('wrong', axis=1)
temp= temp.sort_values(by=['label'])
temp.shape

(826, 16)

Затем создайте лямбда-функцию, которая будет извлекать предсказание из модели для новых данных. Она вам скоро понадобится.

predict_fn = lambda x: model_xgb.predict_proba(x).astype(float)
X_test_lime.dtypes
age               float64
workclass           int64
fnlwgt            float64
education           int64
education_num     float64
marital             int64
occupation          int64
relationship        int64
race                int64
sex                 int64
capital_gain      float64
capital_loss      float64
hours_week        float64
native_country      int64
dtype: object
predict_fn(X_test_lime)
array([[7.96461046e-01, 2.03538969e-01],
       [9.51730132e-01, 4.82698716e-02],
       [7.93448269e-01, 2.06551731e-01],
       ...,
       [9.90314305e-01, 9.68566816e-03],
       [6.45816326e-04, 9.99354184e-01],
       [9.71042812e-01, 2.89571714e-02]])

Вы преобразуете DataFrame pandas в массив NumPy.

X_train_lime = X_train_lime.values
X_test_lime = X_test_lime.values
X_test_lime
array([[4.00000e+01, 5.00000e+00, 1.93524e+05, ..., 0.00000e+00,
        4.00000e+01, 3.80000e+01],
       [2.70000e+01, 4.00000e+00, 2.16481e+05, ..., 0.00000e+00,
        4.00000e+01, 3.80000e+01],
       [2.50000e+01, 4.00000e+00, 2.56263e+05, ..., 0.00000e+00,
        4.00000e+01, 3.80000e+01],
       ...,
       [2.80000e+01, 6.00000e+00, 2.11032e+05, ..., 0.00000e+00,
        4.00000e+01, 2.50000e+01],
       [4.40000e+01, 4.00000e+00, 1.67005e+05, ..., 0.00000e+00,
        6.00000e+01, 3.80000e+01],
       [5.30000e+01, 4.00000e+00, 2.57940e+05, ..., 0.00000e+00,
        4.00000e+01, 3.80000e+01]])
model_xgb.predict_proba(X_test_lime)
array([[7.9646105e-01, 2.0353897e-01],
       [9.5173013e-01, 4.8269872e-02],
       [7.9344827e-01, 2.0655173e-01],
       ...,
       [9.9031430e-01, 9.6856682e-03],
       [6.4581633e-04, 9.9935418e-01],
       [9.7104281e-01, 2.8957171e-02]], dtype=float32)
print(features,
      class_names,
      categorical_features,
      categorical_names)
['age', 'workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country'] ['<=50K' '>50K'] [1, 3, 5, 6, 7, 8, 9, 13] {'workclass': array(['?', 'Federal-gov', 'Local-gov', 'Never-worked', 'Private',
       'Self-emp-inc', 'Self-emp-not-inc', 'State-gov', 'Without-pay'],
      dtype=object), 'education': array(['10th', '11th', '12th', '1st-4th', '5th-6th', '7th-8th', '9th',
       'Assoc-acdm', 'Assoc-voc', 'Bachelors', 'Doctorate', 'HS-grad',
       'Masters', 'Preschool', 'Prof-school', 'Some-college'],
      dtype=object), 'marital': array(['Divorced', 'Married-AF-spouse', 'Married-civ-spouse',
       'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed'],
      dtype=object), 'occupation': array(['?', 'Adm-clerical', 'Armed-Forces', 'Craft-repair',
       'Exec-managerial', 'Farming-fishing', 'Handlers-cleaners',
       'Machine-op-inspct', 'Other-service', 'Priv-house-serv',
       'Prof-specialty', 'Protective-serv', 'Sales', 'Tech-support',
       'Transport-moving'], dtype=object), 'relationship': array(['Husband', 'Not-in-family', 'Other-relative', 'Own-child',
       'Unmarried', 'Wife'], dtype=object), 'race': array(['Amer-Indian-Eskimo', 'Asian-Pac-Islander', 'Black', 'Other',
       'White'], dtype=object), 'sex': array(['Female', 'Male'], dtype=object), 'native_country': array(['?', 'Cambodia', 'Canada', 'China', 'Columbia', 'Cuba',
       'Dominican-Republic', 'Ecuador', 'El-Salvador', 'England',
       'France', 'Germany', 'Greece', 'Guatemala', 'Haiti', 'Honduras',
       'Hong', 'Hungary', 'India', 'Iran', 'Ireland', 'Italy', 'Jamaica',
       'Japan', 'Laos', 'Mexico', 'Nicaragua',
       'Outlying-US(Guam-USVI-etc)', 'Peru', 'Philippines', 'Poland',
       'Portugal', 'Puerto-Rico', 'Scotland', 'South', 'Taiwan',
       'Thailand', 'Trinadad&Tobago', 'United-States', 'Vietnam',
       'Yugoslavia'], dtype=object)}
import lime
import lime.lime_tabular
### Train should be label encoded not one hot encoded
explainer = lime.lime_tabular.LimeTabularExplainer(X_train_lime ,
                                                   feature_names = features,
                                                   class_names=class_names,
                                                   categorical_features=categorical_features, 
                                                   categorical_names=categorical_names,
                                                   kernel_width=3)

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

import numpy as np
np.random.seed(1)
i = 100
print(y_test_lime.iloc[i])
>50K
X_test_lime[i]
array([4.20000e+01, 4.00000e+00, 1.76286e+05, 7.00000e+00, 1.20000e+01,
       2.00000e+00, 4.00000e+00, 0.00000e+00, 4.00000e+00, 1.00000e+00,
       0.00000e+00, 0.00000e+00, 4.00000e+01, 3.80000e+01])

Вы можете использовать функцию explain_instance с модулем explain_instance, чтобы изучить логику работы модели. Диаграмма, которую она отображает, показана ниже.

exp = explainer.explain_instance(X_test_lime[i], predict_fn, num_features=6)
exp.show_in_notebook(show_all=False)

Диаграмма LIME, показывающая вклад различных признаков в правильно предсказанное домохозяйство.

Классификатор правильно предсказал ситуацию с этим домохозяйством: доход действительно превышает 50 тысяч.

Первое, что следует отметить, это то, что классификатор не очень уверен в себе. Он предсказывает доход свыше 50 тысяч с вероятностью 64%, и эти 64% обусловлены приростом капитала и семейным положением. Синий цвет отрицательно влияет на положительный класс, а оранжевая линия — положительно.

Классификатор проявляет нерешительность, поскольку прирост капитала этого домохозяйства равен нулю, в то время как прирост капитала обычно является хорошим показателем богатства. Кроме того, домохозяйство работает менее 40 часов в неделю. Возраст, профессия и пол оказывают положительное влияние.

Если бы человек был холост, классификатор предсказал бы доход ниже 50 тысяч (0.64 – 0.18 = 0.46).

Теперь попробуйте другую семью, которая была классифицирована неправильно. Пояснительная таблица для нее приведена после кода.

temp.head(3)
temp.iloc[1,:-2]
age                  58
workclass             4
fnlwgt            68624
education            11
education_num         9
marital               2
occupation            4
relationship          0
race                  4
sex                   1
capital_gain          0
capital_loss          0
hours_week           45
native_country       38
Name: 20931, dtype: object
i = 1
print('This observation is', temp.iloc[i,-2:])
This observation is label        <=50K
predicted     >50K
Name: 20931, dtype: object
exp = explainer.explain_instance(temp.iloc[1,:-2], predict_fn, num_features=6)
exp.show_in_notebook(show_all=False)

Диаграмма с пояснениями LIME для домохозяйства, в котором классификатор указан неверно.

Классификатор предсказал доход ниже 50 тысяч, что неверно. Это необычное домохозяйство: у него нет ни прироста капитала, ни убытка от продажи активов, человек разведен, ему около 60 лет, и он образован, то есть education_num > 12. Следуя общей закономерности, классификатор отнес доход домохозяйства к категории ниже 50 тысяч.

Поэкспериментируйте с LIME сами, и вы заметите множество грубых ошибок со стороны классификатора. В репозитории GitHub автора библиотеки содержится дополнительная документация по классификации изображений и текста.

Справочник команд Scikit-learn

Ниже приведён список полезных команд, применимых к scikit-learn версии 0.20 и более поздних.

Сложность задачи Функция или класс
Создайте обучающий/тестовый набор данных. train_test_split
Построить трубопровод
Выберите столбцы и примените преобразование. make_column_transformer
Тип преобразования
Стандартизируй StandardScaler
Масштабирование по принципу «минимум-максимум» MinMaxScaler
Нормализовать нормализ
Заполнение пропущенных значений SimpleImputer
Преобразование категориального OneHotEncoder
Сопоставьте и преобразуйте данные fit_transform
Сделать трубопровод make_pipeline
Базовая модель
Логистическая регрессия Логистическая регрессия
XGBoost XGBКлассификатор
Нейронная сеть MLPКлассификатор
Поиск по сетке GridSearchCV
Рандомизированный поиск Рандомизированный поискрезюме

Часто задаваемые вопросы (FAQ)

Установите текущую стабильную версию с помощью pip install -U scikit-learn или conda install -c conda-forge scikit-learn. Сборка для разработчиков, использованная в описанных выше шагах, была необходима только в 2018 году, когда make_column_transformer не был выпущен; теперь он входит в каждую стабильную версию.

Функция fit обучается таким параметрам, как среднее значение столбца и стандартное отклонение. Функция transform применяет их к данным. Функция fit_transform выполняет обе операции за один вызов и должна затрагивать только обучающий набор данных, никогда не затрагивая тестовый набор.

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

Он автоматически дополняет знакомые формы: блоки ColumnTransformer, сетки параметров и имена с двойным подчеркиванием, которые ожидает GridSearchCV. RevОбратите внимание на любые факторы, зависящие от версии, поскольку в предлагаемых вариантах часто воспроизводятся более старые имена аргументов, например, sparse, вместо sparse_output.

Не совсем. Автоматизированные инструменты поиска быстрее исследуют сетку и отсеивают слабые варианты, но вы все равно выбираете пространство поиска, метрику оценки и схему перекрестной проверки. Эти решения важнее, чем сам алгоритм поиска.

Нет. Обучение выполняется на ЦП и распараллеливается по ядрам с помощью n_jobs. Экспериментальный слой Array API позволяет ограниченному набору оценщиков принимать массивы GPU, но TensorFlow И аналогичные фреймворки по-прежнему остаются вариантом с использованием графического процессора.

Да. Вызовите set_output(transform=”pandas”) для трансформера или всего конвейера, и результат сохранит имена столбцов вместо возврата пустого списка. NumPy массив, что значительно упрощает анализ выходных данных ColumnTransformer.

Передайте параметр class_weight=”balanced” оценщикам, которые его принимают, выполните передискретизацию с помощью сопутствующей библиотеки, такой как imbalanced-learn, и оцените результат с помощью точности, полноты или показателя F1, а не просто правильности.

Подведем итог этой публикации следующим образом: