среда, 30 ноября 2022 г.

Машинное обучение с библиотеками PyCaret и TROT : регрессия, часть первая

AutoML расшифровывается как автоматизированное машинное обучение, и его основная цель — сократить или полностью исключить роль специалистов по данным в построении моделей машинного обучения. Рассмотрим два варианта реализации решений AutoML : работа с библиотеками PyCaret и TROT. 

Начнем с регрессии и рассмотрим два учебных руководства с сайта библиотеки PyCaret, а также пример из книги "Tolios G. Simplifying Machine Learning with PyCaret: A Low-code Approach for Beginners and Experts".

Пример из книги , поехали!

Импортируем необходимые библиотеки Python : pandas, Matplotlib и Seaborn. Кроме того, мы импортируем все функции PyCaret, связанные с регрессией. Последняя строка указывает, что рисунки Matplotlib будут иметь разрешение 300 DPI

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
from pycaret.datasets import get_data
from pycaret.regression import *
mpl.rcParams['figure.dpi'] = 300

PyCaret включает множество наборов данных, которые можно использовать для тестирования его функций. Мы будем использовать Insurance.csv,  это медицинская страховка с показателями  возраст, пол, индекс массы тела (BMI), курит человек или нет, количество детей и регион США.
Целевая переменная набора данных — это выставленные счета для каждого человека.
Для загрузки данных в DataFrame pandas используем функцию get_data() PyCaret.  Ее вывод после загрузки эквивалентен функции head() pandas, которая печатает первые 5 строк набора данных.

data = get_data('insurance')

agesexbmichildrensmokerregioncharges
019female27.9000yessouthwest16884.92400
118male33.7701nosoutheast1725.55230
228male33.0003nosoutheast4449.46200
333male22.7050nonorthwest21984.47061
432male28.8800nonorthwest3866.85520

Далее используем функцию pandas info() для представления базовой информации о наборе данных : данные содержат 1338 строк, и ни один из столбцов не имеет нулевых значений. Тип данных каждого столбца определяется автоматически.

data.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1338 entries, 0 to 1337
Data columns (total 7 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   age       1338 non-null   int64  
 1   sex       1338 non-null   object 
 2   bmi       1338 non-null   float64
 3   children  1338 non-null   int64  
 4   smoker    1338 non-null   object 
 5   region    1338 non-null   object 
 6   charges   1338 non-null   float64
dtypes: float64(2), int64(2), object(3)
memory usage: 73.3+ KB


Исследовательский анализ данных (EDA)

EDA — это метод, который помогает нам понять свойства набора данных с помощью
описательной статистике и визуализацию. Это важная часть каждого проекта машинного обучения, так как мы должны понять набор данных, прежде чем его использовать.
Распределение числовых переменных можно визуализировать с помощью гистограммы, которую можно легко создается с помощью функции pandas hist(). Очевидно, что
некоторые переменные имеют правостороннее распределение, что может вызвать
проблемы с регрессионными моделями.

numeric = ['age', 'bmi', 'children', 'charges']
data[numeric].hist(bins=20, figsize = (12,8))



Использование столбчатых диаграмм — стандартный способ отображения
категориальных переменных. Это легко, используя функции pandas value_counts() и
plot(). 

В этом примере используем функцию subplots(), первые два параметра
задают количество строк и столбцов сетки. Функция subplots() возвращает два объекта,
первый — это Figure, подложка, на которой будут размещены поля с
графиками, второй — объект (или массив объектов) Axes, через который
можно получить полных доступ к настройке внешнего вида отображаемых элементов.

categorical = ['smoker', 'sex', 'region']
color = ['C0', 'C1', 'C2', 'C3']
fig, axes = plt.subplots(2, 2, figsize = (12,10))
#Отключаем вывод четвертого графика
axes[1,1].set_axis_off()
# axes.flatten () сгладит ax из группы осей n * m в группу осей 1 * nm
for ax, col in zip(axes.flatten(), categorical) :
    data[col].value_counts().plot(kind = 'bar', ax = ax, color = color)
    ax.set_xlabel(col)



Как мы видим, переменная курильщик имеет неравномерное распределение, 
только 20% люди курят. С другой стороны, переменные пол и регион одинаково
распределены.

Функция Seaborn histplot() позволяет визуализировать взаимосвязь между числовыми
и категориальные переменные с помощью цвета. Гистограмма целевой функции 
(страховых расходов) окрашена по разному для курильщиков, пола и регионов.
Очевидно, что у курильщики расходы значительно больше. Это ожидаемо,
поскольку риски для здоровья, связанные с курением, хорошо известны.

fig, axes = plt.subplots(2, 2, figsize=(12,8))
axes[1,1].set_axis_off()
for ax, col in zip(axes.flatten(), categorical):
    sns.histplot(data, x='charges', hue=col, multiple='stack', ax=ax)






Диаграммы рассеяния — это тип визуализации, который помогает понять взаимосвязь
между числовыми переменными. Функция steamplot() Seaborn создает матрицу диаграмм рассеяния для всех пар числовых переменных в заданном наборе данных. На диагонали располагаются  графики распределения в виде гистограмм или KDE. Цвет используем для выделения различий между курящими и некурящими. 
 Анализируя этот график можно сделать некоторые выводы : начисления коррелируют с возрастом, чем старше, тем больше расходов на поддержания здоровья, при этом у некурящих все равно эта тенденция ниже; у людей с избыточным весом нет более высоких расходов, если они не курят.

cols = ['age', 'bmi', 'charges', 'smoker']
sns.pairplot(data[cols], hue='smoker')
plt.tight_layout()    


После предварительного анализа данных переходим к инициализация среды PyCaret.


Инициализация среды PyCaret

reg = setup(data=data, target='charges', train_size = 0.8, session_id = 7402,
numeric_features = numeric[:-1], categorical_features = categorical,
transformation = True, normalize = True, transform_target = True,fold_shuffle=True)

Функция setup() инициализирует среду в pycaret и создает конвейер преобразования для подготовки данных для моделирования и развертывания. setup() необходимо вызывать

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

параметра: DataFrame pandas и имя целевого столбца. Все остальные параметры

являются необязательными и используются для настройки конвейера предварительной обработки.


Разберем параметры, заданные в примере :


data - типа DataFrame Pandas


Набор данных с формой (n_samples, n_features), где n_samples — количество выборок, а n_features — количество признаков. Если данные не являются DataFrame pandas, они преобразуются в DataFrame с использованием имен столбцов по умолчанию.


target: int, str или последовательность, по умолчанию = -1


Если int или str, соответственно индекс или имя целевого столбца в данных. Значение

по умолчанию выбирает последний столбец в наборе данных. Если

последовательность, она должна иметь форму (n_samples). Цель может быть либо

бинарной, либо мультиклассовой.


train_size: с плавающей запятой, по умолчанию = 0,7


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

быть между 0,0 и 1,0.


session_id: целое, по умолчанию = None


Предоставляет начальное значение внутреннему генератору случайных чисел,

эквивалентно «random_state» в scikit-learn. Если None, генерируется псевдослучайное

число. Используется для последующей воспроизводимости всего эксперимента.


numeric_features: list of str, по умолчанию = None


Список имен столбцов с числовыми признаками, задаются, если не согласны с

автоматическим определение типов 


categorical_features: list of str, по умолчанию = None


Список имен столбцов с категориальными признаками, задаются, если не согласны с

автоматическим определение типов 


ordinal_features: dict, по умолчанию = нет

Категориальные признаки должны кодироваться порядково.

Например, категориальный признак со значениями «низкий», «средний», «высокий»,

где низкий < средний < высокий, может быть передан как

ordinal_features = {'column_name' : ['low', 'medium', 'high']} .


Помимо этих, есть date_features для дат и text_features для строк, а также

ignore_features - список столбцов, которые надо игнорировать и keep_features - список

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


transformation: bool, по умолчанию = False

Если установлено значение True, применяется степенное преобразование,

чтобы сделать данные более похожими на нормальное распределение. Тип преобразования определяется параметром transform_method.


transform_target: bool, по умолчанию = False

Если установлено значение True, целевая переменная преобразуется с

использованием метода, определенного в параметре transform_target_method.

Целевое преобразование применяется отдельно от преобразования признаков.


normalize: bool, по умолчанию = False

Если установлено значение True, он преобразует объекты, масштабируя их до

заданного диапазона. Тип масштабирования определяется параметром

normalize_method. normalize_method: str, по умолчанию = ‘zscore’

Определяет метод масштабирования. По умолчанию метод нормализации установлен

на «zscore». Стандартный zscore рассчитывается как z = (x - u) / s. Игнорируется,

если для нормализации не установлено значение True. Другие варианты: - minmax: масштабируйте каждую функцию в диапазоне [0, 1],

- maxabs: масштабируйте каждую функцию в диапазоне [-1, 1],


- robust: масштабирует и переводит каждый признак в соответствии

с межквартильным диапазоном. Когда набор данных содержит выбросы,

часто дает лучшие результаты.


fold_shuffle: bool, по умолчанию = False


Управляет параметром перемешивания CV. Применимо, только если fold_strategy

имеет значение «kfold» или «stratifiedkfold». Игнорируется, если fold_strategy

является настраиваемым объектом.


fold_strategy: str or sklearn CV generator object,, по умолчанию = ‘kfold’

Выбор стратегии перекрестной проверки. Возможные значения: ‘kfold’ ‘groupkfold’ ‘timeseries’ собственный объект генератора CV, совместимый с scikit-learn. Для groupkfold имя столбца должно быть передано в параметре fold_groups.

Пример: setup(fold_strategy="groupkfold", fold_groups="COLUMN_NAME")


Получается, что раз fold_strategy по умолчанию ‘kfold’, то fold_shuffle должен быть

по умолчанию True, однако это не так и приходиться задавать его явно, иначе будет

ошибка


max_encoding_ohe: целое число, по умолчанию = 25

Категориальные столбцы с max_encoding_ohe или менее уникальными значениями

кодируются с использованием OneHotEncoding. Если больше, используется

оценщик encoding_method. Обратите внимание, что столбцы с ровно двумя

классами всегда кодируются по порядку. Установите значение ниже 0,

чтобы всегда использовать OneHotEncoding. encoding_method: оценка кодировщиков категорий, по умолчанию = None

Средство оценки кодировщиков категорий для кодирования категориальных столбцов

с более чем max_encoding_ohe уникальными значениями. Если нет,

используется category_encoders.leave_one_out.LeaveOneOutEncoder.


Подробнее о параметрах настройки

https://pycaret.readthedocs.io/en/latest/api/regression.html


После запуска функции setup() распечатывается таблица с ее параметрами

и настройками. 


Печать предварительно обработанных элементов


get_config('X').head().T


01234
age-1.462763-1.535749-0.807782-0.445654-0.517962
bmi-0.4089710.5439530.426243-1.350171-0.240519
children-1.0538840.2039601.414612-1.053884-1.053884
sex_female1.0000000.0000000.0000000.0000000.000000
smoker_no0.0000001.0000001.0000001.0000001.000000
region_northeast0.0000000.0000000.0000000.0000000.000000
region_northwest0.0000000.0000000.0000001.0000001.000000
region_southeast0.0000001.0000001.0000000.0000000.000000
region_southwest1.0000000.0000000.0000000.0000000.000000


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

числовые признаки имеют разные значения из-за нормализация/преобразование

и категориальные признаки были преобразованы к нескольким двоичным переменным

из-за  применения one-hot encoding.


Сравнение моделей регрессии


best = compare_models(sort='RMSE')



ModelMAEMSERMSER2RMSLEMAPETT (Sec)
rfRandom Forest Regressor2314.040722718644.07234715.86630.84060.41490.20830.1720
gbrGradient Boosting Regressor2248.689523025672.30304723.38790.83870.38310.18000.0430
lightgbmLight Gradient Boosting Machine2472.468223306959.38774766.99660.83720.41160.20640.2010
adaAdaBoost Regressor3240.712723938991.45954847.01550.83160.48040.42660.0210
catboostCatBoost Regressor2508.491925307119.97274953.35310.82280.40440.19710.5440
etExtra Trees Regressor2418.787126054884.66125056.11860.81580.44110.22610.1450
xgboostExtreme Gradient Boosting2832.307432979184.80005568.33250.77440.44650.25360.0670
dtDecision Tree Regressor3169.959244888037.81426676.81150.67050.53510.35500.0100
ompOrthogonal Matching Pursuit5637.700558885229.96097602.75040.58880.68360.68730.0100
ridgeRidge Regression4053.793160899553.20007749.93660.57140.43880.26930.0110
brBayesian Ridge4060.231861248984.34827772.25830.56880.43880.26910.0100
larLeast Angle Regression4068.572361713577.60007801.88190.56540.43880.26880.0110
lrLinear Regression4068.589961714293.20007801.92420.56540.43880.26880.8460
knnK Neighbors Regressor4557.127171071863.64168351.89910.50910.53200.31220.0130
huberHuber Regressor4225.863580592753.42468895.49470.43210.45420.20760.0140
parPassive Aggressive Regressor6234.6940132789408.978910197.7140-0.06150.61540.59270.0100
enElastic Net8222.1528160880655.200012599.0370-0.11780.90730.96940.0110
llarLasso Least Angle Regression8248.0973161187188.000012610.6184-0.11980.91000.97670.0100
lassoLasso Regression8248.0973161187188.000012610.6184-0.11980.91000.97670.0100



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

процесс, обучая все доступные модели и отображая таблицу с результатами. Первый

столбец содержит имя модели регрессии, а остальные являются различными

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

используется для оценки эффективности регрессионной модели, но мы сосредоточимся на среднеквадратичной ошибке (RMSE), поэтому  результаты отсортированы на ее

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

У меня по этому показателю лучшая модель rf (Random Forest Regressor) co значением

4715.8663, в книге это Gradient Boosting Regressor со значением RMSE 4750.1089.

Так как работаем по книге, не будем от нее отходить и также для дальнейшего

рассмотрения выберем gbr, тем более что у этой модели лучший показатель MAPE,

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


Далее мы можем обучить модель с помощью функции create_model(). Функция, которая использует k-кратную перекрестную проверку для оценки точности модели. Набор

данных разбивается на k подвыборок, одна из которых сохраняется для проверки,

а остальные используются для обучения модели. Этот процесс повторяется k раз,

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



model = create_model('gbr', fold = 10)


MAEMSERMSER2RMSLEMAPE
01577.801111712642.18693422.37380.89570.39400.1563
11778.354213278923.71693644.02580.89750.30280.1778
22454.444524687957.84244968.69780.88070.38930.1730
32764.935134137006.09985842.68830.81540.38570.1847
41823.542613710743.40093702.80210.89270.35370.1706
52146.737721985576.72614688.87800.84030.41660.1849
62683.986431434415.15735606.64030.76520.37800.1930
72245.522619903097.82454461.28880.83720.34220.1745
82535.346328168373.30105307.38860.80310.45060.2017
92476.224531237986.77395589.09530.75940.41790.1839
Mean2248.689523025672.30304723.38790.83870.38310.1800
SD386.61787819241.0112845.74190.04990.04010.0120



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

tune_model() можно использовать для применения настройки гиперпараметров к

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

производится случайная выборка возможных комбинаций. 

Словарь с нашими гиперпараметрами  был передан в параметр функции custom_grid.

Мы видим, что после настройки модели RMSE значение уменьшилось до 4585.6787.

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

значение параметра n_iter. Каждая регрессионная модель имеет свой набор

гиперпараметров, которые можно настроить, поэтому придется проработать его

документации для их выбора. В для Gradient Boosting документация по регрессии

scikit-learn : ttps://scikit-learn.org/stable/modules/generated/

sklearn.ensemble.GradientBoostingRegressor.html


params = {'learning_rate': [0.01, 0.02, 0.05], 'max_depth': [1,2, 3, 4, 5, 6, 7, 8], 'subsample': [0.4, 0.5, 0.6, 0.7, 0.8], 'n_estimators' : [100, 200, 300, 400, 500, 600]} tuned_model = tune_model(model, optimize = 'RMSE', fold = 10, custom_grid = params, n_iter = 100)

MAEMSERMSER2RMSLEMAPE
01603.821812188586.86743491.21570.89140.39660.1645
11728.306413112545.58463621.12490.89880.30000.1749
22309.441123388076.15924836.12200.88700.37750.1603
32676.344334715313.42005891.97020.81220.37680.1742
41579.945511948234.32113456.62180.90650.34980.1588
52050.634720786022.23144559.16900.84900.40580.1761
62601.879130444354.71215517.64030.77260.37330.1911
72208.341519712289.84044439.85250.83870.34870.1857
82440.907227343035.94895229.05690.80890.44550.1986
92106.444523174724.11454814.01330.82150.43000.1709
Mean2130.606621681318.32004585.67870.84870.38040.1755
SD374.67237394738.2223808.00340.04320.04010.0124

 Функция predict_model() делает прогнозы на набор тестовых данных, что позволяет нам оценить производительность модели на данных, которые не использовался для
обучения модели. Как мы видим, значение RMSE в тестовом наборе данных равно
4046.7334,что говорит о том, что модель имеет отличные характеристики


cols = ['age', 'bmi', 'children', 'sex_female', 'smoker_no','charges','Label']
predictions = predict_model(tuned_model)
predictions[cols].head()

ModelMAEMSERMSER2RMSLEMAPE
0Gradient Boosting Regressor1884.414216376051.25214046.73340.89490.33300.1759
agebmichildrensex_femalesmoker_nochargesLabel
00.558673-2.0238420.2039600.01.08627.5410169060.098274
1-0.880372-0.739121-1.0538840.01.03070.8085943666.289899
21.055905-0.017651-1.0538840.01.010231.50000012260.610769
31.1975410.522682-1.0538840.00.043921.18359444518.272396
40.273279-0.6195990.9341731.00.022478.59960924167.086587

Функция plot_model() позволяет нам легко создавать различные полезные графики для нашей модели. В этом случае мы создали график важности признаков, чтобы визуализировать влияние, которое каждая функция оказывает на прогнозирование целевой переменной. По-видимому, наиболее важными характеристиками являются возраст каждого человека и то, курит он или нет. Это подтверждает EDA Insights, где мы пришли к выводу, что эти функции действительно являются наиболее важными. Эту функцию также можно использовать для построения кривой проверки, кривой обучения и различные другие полезные графики о модели регрессии.

plot_model(tuned_model, 'feature', scale = 4)



Теперь мы используем функцию plot_model() для создания графика ошибки предсказания, визуализирующего разница между целевыми значениями набора данных и прогнозами нашей модели. Как мы видим, предсказания модели довольно точны, потому что линия наилучшего соответствия значительно близка к линии тождества, где все предсказания теоретически верны. Кроме того, метрика R2 также указывает на то, что модель является точной, имея значение 0,895. 

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


Комментариев нет:

Отправить комментарий