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

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

  1. Обзор Scikit-learn

2. Предварительная обработка данных

3. Метрики оценки

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

5. Выбор оценщика

6. Ключевой вынос

1. Обзор Scikit-learn

1.1 Scikit-learn и TensorFlow

Хотя в последние годы Scikit-learn не был так популярен, как развивающийся TensorFlow, у этих двух фреймворков есть свои сильные стороны в разных областях. Scikit-learn в основном используется для традиционных задач машинного обучения, связанных со структурированными табличными данными. Что касается обработки неструктурированных данных, таких как изображение в компьютерном зрении и текст в обработке естественного языка, предпочтение отдается средам глубокого обучения, включая TensorFlow и Pytorch.

Scikit-learn менее гибкий по сравнению с TensorFlow. Scikit-learn предоставляет только API высокого уровня, а TensorFlow предоставляет API низкого уровня (tf.*), API среднего уровня (слои), а также API высокого уровня (tf.keras и оценщики). В Scikit-learn модели предварительно встроены в оценщики, и единственными настраиваемыми параметрами для пользователей являются гиперпараметры. Однако в TensorFlow пользователи могут не только настраивать готовые модели, но и писать модель с нуля (используя операции и тензоры).

Еще одно отличие состоит в том, что Scikit-learn имеет только API-интерфейсы Python, а TensorFlow предоставляет API-интерфейсы для разных языков, таких как Python, C++ и javascript.

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

1.2 Согласованный API Python

Scikit-learn имеет подробную документацию, удобную для новичков. Кроме того, оценщики в Scikit-learn следуют стандартным и согласованным API-интерфейсам Python для подгонки/прогнозирования или подгонки/преобразования.

Однако, согласно Scikit-learn FAQ, не будет поддержки вычислений на GPU, глубокого обучения и обучения с подкреплением.

2. Предварительная обработка данных

Scikit-learn хорошо работает с числовыми данными, которые хранятся в виде массивов numpy, разреженных матриц scipy и фреймов данных pandas. Чтобы передать в оценщики Scikit-learn, категориальные признаки, хранящиеся в виде строк, должны быть предварительно преобразованы в числовые признаки.

Scikit-learn предоставляет широкий спектр API для загрузки и предварительной обработки данных. Что касается подключения нескольких оценщиков, у Scikit-learn есть два решения: Pipeline для последовательного подключения оценщиков и FeatureUnion для параллельного подключения оценщиков. Между тем, объекты Pipeline и FeatureUnion также являются оценщиками. Таким образом, Pipeline и FeatureUnion также могут быть переданы cross-validation методам в качестве оценок.

2.1 Конвейер

Pipeline — это рекомендуемый способ объединения нескольких оценщиков в одну. Pipeline ведет себя аналогично одному преобразователю/классификатору/регрессору, в зависимости от типа последней оценки в цепочке. После применения метода fit к обучающим данным к данным тестирования можно впоследствии применить метод transform или predict. Таким образом, данные тестирования легко преобразовать так же, как данные обучения, и при этом избежать утечки данных тестирования в данные обучения.

Pipeline создается путем передачи списка из (key, value) кортежей. Здесь key — это имя оценщика, определенное пользователями, а value — объект оценщика.

estimators = [('imputer',impute.SimpleImputer(missing_values=nan, strategy='mean')), ('clf', SVC())]
pipe = Pipeline(estimators)

Еще одно преимущество использования Pipeline связано с поиском по сетке гиперпараметров в cross-validation, что будет подробно обсуждаться в следующих сеансах. Поскольку объект Pipeline является оценщиком, легко выполнить совместную оптимизацию гиперпараметров для нескольких объединенных в цепочку оценок. Предположим, у нас есть Pipeline двух оценщиков: за оценщиком 1 следует оценщик 2. У оценщика 1 есть гиперпараметр A, а у оценщика 2 гиперпараметр B. Pipeline позволяет совместную оптимизацию гиперпараметров A и B путем проведения поиска по сетке для различных комбинаций A и значения В.

# define grid search parameters
parameters = {}
parameters['imputer__strategy'] = ['mean','median','most_frequent']
parameters['clf_C'] = [0.1,1,10]
# pass pipeline, grid search parameters into GridSearchCV
CV = GridSearchCV(pipe, parameters, scoring = 'mean_absolute_error', n_jobs= 1)

2.2 Преобразователь столбцов

Когда столбцы набора данных требуют другого преобразования, рекомендуется применять преобразование по столбцам в Scikit-learn, а не в pandas DataFrame. ColumnTransformer является оценкой и может быть передано в cross-validation. Таким образом, ColumnTransformer позволяет применять различные преобразования к столбцам и избегать утечки данных тестирования в данные обучения.

2.3 Вменение отсутствующих значений

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

2.4 Предварительная обработка данных

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

2.4.1 Стандартизация

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

estimators = [('scaler',preprocessing.StandardScaler()),                    ('clf',SVC())]
pipe = Pipeline(estimators)

Для масштабирования наборов данных с большим количеством выбросов StandardScalar работает плохо. В этом случае вместо этого рекомендуется использоватьRobustScaler.

2.4.2 Преобразование в распределение Гаусса

Scikit-learn предоставляет API-интерфейсы QuantileTransformer и PowerTransformer для сопоставления входных данных с распределением Гаусса. Это полезно для моделирования проблем, связанных с гетероскедастичностью (непостоянной дисперсией) и других ситуаций, когда требуется нормальность.

2.4.3 Нормализация

Normalizer API изменяет масштаб отдельной выборки, чтобы иметь единичную норму. Normalizer отличается от StandardScalar. StandardScalar масштабирует разные функции и гарантирует, что разные функции имеют одинаковый масштаб, а Normalizer масштабирует разные вектора выборки, чтобы иметь единичную норму. Другой способ понять разницу между этими двумя преобразователями заключается в том, что StandardScalar работает со столбцами, а Normalizer — со строками.

2.4.4 Кодирование категориальных функций

Для кодирования категориальных строковых признаков в целочисленные коды можно использовать OrdinalEncoder и OneHotEncoder. По умолчанию OrdinalEncoder интерпретирует категории по порядку. Чтобы избежать этой проблемы, следует использовать OneHotEncoder. Хотя OneHotEncoder кодирует категориальные признаки в более длинные представления, используя 0 и 1, он интерпретирует порядок категориальных признаков как произвольный. Большинство оценщиков хорошо работают с OneHotEncoders, но древовидные модели хорошо работают с OrdinalEncoder.

3. Метрики оценки

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

3.1 Показатели оценки и целевые функции

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

3.2 Показатели оценки, оканчивающиеся на _score, _loss и _error

Scikit-learn имеет три типа показателей оценки: API, оканчивающиеся на _score, _loss и _error. Существует два сценария использования показателей оценки, в которых показатели оценки используются по-разному.

Первый сценарий заключается в применении показателей оценки к конкретной модели для измерения производительности модели. В этом первом сценарии для показателей оценки _score более высокие возвращаемые значения лучше, чем более низкие возвращаемые значения. Однако для _error и _loss более низкие возвращаемые значения лучше, чем более высокие возвращаемые значения.

Второй сценарий — передать метрику оценки как параметр scoring в cross-validation функции. Цель передачи параметра scoring — служить эталоном для выбора моделей с наилучшей производительностью. В Scikit-learn все объекты счетчика следуют соглашению, согласно которому более высокие возвращаемые значения лучше, чем более низкие возвращаемые значения. Это соглашение соответствует использованию _score, но противоречит _loss и _error. Чтобы решить эту проблему, при передаче метрик оценки _loss и _error в качестве параметров scoring требуется преобразование:

scoring = make_scorer(metrics.mean_absolute_error, greater_is_better=False)

3.3. Как использовать несколько показателей оценки

Методы GridSearchCV, RandomizedSearchCV и cross_validation Scikit-learn cross-validation позволяют передавать несколько показателей оценки в качестве параметра scoring. Есть два способа передать несколько показателей оценки в параметр scoring.

В виде списка строковых метрик:

scoring = ['neg_mean_absolute_error','r2']

Второй способ — использовать dict, отображающий настроенное имя в функцию подсчета очков, здесь значения dict могут быть созданы с использованием make_scorer или предопределенных строк метрик:

scoring = {'neg_mean_absolute_error':make_scorer(metrics.mean_absolute_error, greater_is_better=False),
 'R2': 'r2'}

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

4.1 Данные проверки

Некоторые модели имеют гиперпараметры, которые присваиваются модели пользователями, а не изучаются во время обучения. Оптимизация гиперпараметров требует оценки моделей с несколькими различными настройками значений гиперпараметров. Чтобы оценить модели и избежать утечки тестовых данных в модели, распространенным решением является использование train_test_split() для отделения части данных обучения в качестве данных проверки. Таким образом, данные обучения используются для обучения модели, а данные проверки используются для оценки различных гиперпараметров и выбора оптимизированного гиперпараметра.

Перекрестная проверка в 4,2 тысячи раз

Хотя train_test_split() позволяет избежать утечки тестовых данных в модель, разделение проверочных данных уменьшает объем доступных обучающих данных. Для решения этой проблемы решением является процедура под названием cross-validation. Вместо разделения обучающих данных на обучающие и проверочные данные обучающие данные делятся на k частей в cross-validation. Каждая часть по очереди служит проверочными данными, а оставшиеся (k-1) части служат обучающими данными. k-fold cross-validation требует k циклов вычислений, а результирующая метрика оценки представляет собой среднее значение значений, вычисленных в k циклах. Таким образом, k-fold cross-validation позволяет избежать траты обучающих данных ценой более дорогих вычислений.

4.3. Два API для вычисления показателей с перекрестной проверкой

У Scikit-learn есть два API для вычисления метрик с перекрестной проверкой на модели с заданным набором гиперпараметров: cross_val_score и cross_validation. Самый простой способ — вызвать вспомогательную функцию cross_val_score для оценщика и набора данных. В отличие от cross_val_score, который допускает только одну метрику оценки, cross_validation позволяет оценивать модель с использованием нескольких метрик.

API cross_val_score:

sklearn.model_selection.cross_val_score(estimator, X, y=None, groups=None, scoring=None, cv=None, n_jobs=None, verbose=0, fit_params=None, pre_dispatch='2*n_jobs', error_score=nan)

API cross_validation:

sklearn.model_selection.cross_validate(estimator, X, y=None, groups=None, scoring=None, cv=None, n_jobs=None, verbose=0, fit_params=None, pre_dispatch='2*n_jobs', return_train_score=False, return_estimator=False, error_score=nan)

4.4 Итераторы перекрестной проверки

Помимо использования API cross_val_score и cross_validation, еще одним способом применения процедуры cross-validation является использование итераторов перекрестной проверки. Эти cross-validation итераторы генерируют разбиение набора данных в соответствии с заданной cross-validation стратегией, и сгенерированные разбиения набора данных можно вручную перебирать для различных операций.

Пример использования итератора cross-validation:

X = ["a", "b", "c", "d"]
kf = KFold(n_splits=2)
for train, test in kf.split(X):
     print("%s %s" % (train, test))

4.5 Оптимизация гиперпараметров

Учитывая, что cross-validation помогает оценить производительность модели, не тратя впустую доступные обучающие данные, можно и рекомендуется оптимизировать гиперпараметры с помощью cross-validation. У Scikit-learn есть два API для оптимизации гиперпараметров: GridSearchCV и RandomizedSearchCV. В отличие от cross_val_score и cross_validation, которые генерируют оценку cross-validation модели с определенной настройкой гиперпараметра, GridSearchCV и RandomizedSearchCV сравнивают оценку cross-validation модели с несколькими заданными настройками гиперпараметра, чтобы найти гиперпараметр оптимизации.

GridSearchCV реализует исчерпывающий поиск по заданным настройкам параметров, а API:

sklearn.model_selection.GridSearchCV(estimator, param_grid, scoring=None, n_jobs=None, iid='deprecated', refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', error_score=nan, return_train_score=False)

RandomizedSearchCV реализует рандомизированный поиск по параметрам путем выборки из распределения по возможным значениям параметров, а API:

sklearn.model_selection.RandomizedSearchCV(estimator, param_distributions, n_iter=10, scoring=None, n_jobs=None, iid='deprecated', refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', random_state=None, error_score=nan, return_train_score=False)

5. Выбор оценщика

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

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

6. Ключевой вынос

Я знаю, что это был длинный пост. Но прежде чем вы уйдете, я хотел бы резюмировать ключевой вывод. Потратив недели на чтение документации Scikit-learn и опробовав различные оценщики Scikit-learn, я обнаружил, что сила Scikit-learn заключается в доступности Pipeline вместе с cross-validation. Поскольку Scikit-learn предоставляет только оценщики высокого уровня, настраиваемые параметры, оставленные пользователям, — это гиперпараметры. Чтобы пользователи могли настраивать гиперпараметры, Scikit-learn хорошо поддерживает cross-validation. Pipeline позволяет улучшить cross-validation, так как он связывает оценщики предварительной обработки с окончательным оценщиком, чтобы добиться полного разделения данных обучения и данных проверки. Таким образом, Pipeline предотвращает утечку данных во время cross-validation и позволяет искать гиперпараметры по нескольким оценщикам. Таким образом, я нахожу Pipeline вместе с cross-validation мощным.

Я надеюсь, что вы найдете этот пост полезным в своем журнале для изучения машинного обучения и Scikit-learn. Если вам интересно прочитать мой обзор обучения TensorFlow 2.0 и кодированию модели Python с помощью Scikit-learn и TensorFlow 2.0, следите за обновлениями, я скоро буду обновлять новые сообщения!

[1] https://scikit-learn.org/stable/tutorial/machine_learning_map/index.html