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