Библиотека OutboxML от Страхового Дома ВСК

от автора

Хабр, привет!

Меня зовут Семён Семёнов, я руковожу Data Science и Machine Learning в Страховом Доме ВСК. В этой статье расскажу, как мы создали систему автоматического обучения и развёртывания моделей машинного обучения с открытым исходным кодом.

Первый вопрос, который может задать себе читатель, знакомый с темой современного машинного обучения: «почему бы не взять одну из десятков (если не сотен) открытых AutoML-библиотек?»

Ответ прост: мы не стремились создать ещё один «стандартный» проект AutoML. Наша цель — сфокусироваться на вещах, которые редко встречаются в готовых решениях:

  • развёртывание системы,

  • мониторинг в реальном времени,

  • удобное написание собственных моделей внутри AutoML-каркаса,

  • конфигурация всех компонентов через простые скрипты и файлов конфигурации.

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

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

Концептуально система состоит из основных компонентов:

  • ядра, включающего в себя логику машинного обучения при взаимодействии с другими компонентами,

  • докер компонентов базы данных (PostgreSQL),

  • трекинга экспериментов (MLFlow),

  • визуализации метрик (Grafana),

  • веб-сервисов (FastAPI) и вспомогательных компонентов.

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

Стандартный цикл работы библиотеки состоит из следующих этапов: на вход подаётся файл с данными в формате csv, далее запускается процесс автоматического машинного обучения, результаты которого сохраняются в MLflow, выводятся в консоль и в интерфейс в виде графиков. В случае необходимости запускается дальнейший автоматический процесс загрузки в базу данных с использованием мониторинга результатов в Grafana. При этом саму модель можно развернуть с помощью веб-сервиса на основе FastAPI.

Цикл работ отображён на схеме ниже:

В статье рассматривается простое использование библиотеки для создания базовой модели в трёх вариациях:

  1. Целиком коробочный запуск с использованием файла конфигурации;

  2. С собственным препроцессором данных;

  3. С использованием собственных моделей.

В качестве датасета используются данные эффективности энергии.
Датасет используется для моделирования эффективности отопительной нагрузки и холодильной нагрузки зданий (то есть энергоэффективности) в зависимости от параметров здания. Датасет состоит из 767 строк и десяти колонок, восемь из которых используются как фичи в модели и две (Heating Load и Cooling Load) – в качестве таргета.

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

1. Клонируем проект, переходим на ветку v.0.8.0;

2. Заходим в папку outboxml/app, запускаем create-folder.bat (Windows) или create-folder.sh (Linux);

3. Запускаем docker compose up -d;

4. Для загрузки артефактов в MLFlow, открываем MinIO по адресу http://localhost:9001 (login: minio, password: Strong#Pass#2022), нажимаем «Create Bucket» с именем «mlflow» и меняем настройку Access Policy на public.

Инфраструктура для работы развёрнута. Теперь переходим в JupyterLab, открывая первый пример по адресу: http://localhost:8889/lab/tree/work/examples/energy_efficiency/1.energy\_efficiency\_basic.ipynb

В основе библиотеки лежат файлы конфигурации. Для примера нам нужно использовать два файла – файл конфигурации предподготовки модели и файл AutoML. Отложим описание конфига AutoML и сфокусируемся на конфиге модели. Для базовой версии примера используем следующий файл конфигурации energy_efficiency/configs/config-energy-efficiency-basic.json

Ключевым для примера является описание модели.

  "models_configs": [     {       "name": "heating", // Название модели       "column_target": "Heating Load", // Название колонки-таргета       "wrapper": "catboost", // Выбор «коробочной» модели, в нашем случае catboost       "relative_features": [], // Выбор фичей-отношений, в нашем случае остаётся пустым       "features": [        // Список фичей для модели, в нашем случае все фичи численные         {           "name": "Relative Compactness",  // Название колонки-фичи           "default": 0, // Значение  по умолчание           "replace": {"_TYPE_": "_NUM_"} // Тип фичи, численная фича         },         {           "name": "Roof Area",           "default": 0,           "replace": {"_TYPE_": "_NUM_"}         }       ]     }   ] 

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

from outboxml.automl_manager import AutoMLManager  config_name = './configs/config-energy-efficiency-basic.json' auto_ml_config = './configs/automl-energy-efficiency-automl.json'  auto_ml = AutoMLManager(auto_ml_config=auto_ml_config,models_config=config_name) auto_ml.update_models()

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

После довольно продолжительного (из-за подбора гиперпараметров) запуска мы получаем информацию о завершении процесса.

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

auto_ml.get_result()['heating'].metrics

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

Далее, рассмотрим возможности улучшения процесса.

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

Откроем вторую тетрадку: http://localhost:8889/lab/tree/work/examples/energy_efficiency/2.energy_efficiency_extractor.ipynb

Для преобразования фичей и таргета используется класс Extractor.

class EnergyEfficiencyExtractor(Extractor):     def __init__(self,                  path_to_file: str                  ):         self.__path_to_file = path_to_file         super().__init__()      def extract_dataset(self) -> pd.DataFrame:         data = pd.read_csv(self.__path_to_file)  # Читаем файл на прямую, данная функциональность «переписывает» файл из конфига.         data['EEI'] = (data['Heating Load'] + data['Cooling Load'])/data['Surface Area']         # Считаем Индекс энергетической эффективности или Energy Efficiency Index (EEI) в качестве нового таргета          data['Wall_Roof_Ratio'] = data['Wall Area'] / data['Roof Area']         #Посчитаем отношение площади стен к площади крыши          data['Compactness_Height'] = data['Relative Compactness'] * data['Overall Height']      # Посчитаем комбинированный эффект компактности и высоты         final_features = ['Wall_Roof_Ratio',  'Compactness_Height','Glazing Area Distribution','Orientation', 'EEI']         return data[final_features]  

Для расчёта собственной метрики используем класс BaseMetric, считаем MAPE в качестве метрики:

class EnergyEfficiencyMetrics(BaseMetric):     def __init__(self):         pass     def calculate_metric(self, result1: dict, result2: dict = None) -> dict:         y_true = result1['EEI'].y         y_pred = result1['EEI'].y_pred         return {'MAPE': np.mean(np.abs((y_true - y_pred) / y_true)) * 100}

Так как мы изменили ряд фичей и таргет модели, нам необходимо изменить часть конфига модели. Конфиг после изменений находится по адресу: energy_efficiency/configs/config-energy-efficiency-extractor.json.

  "models_configs": [     {       "name": "EEI", // Название новой модели       "column_target": "EEI",  // Название нового таргета, созданного в extractor       "wrapper": "catboost",        "relative_features": [],       "features": [                 {           "name": "Wall_Roof_Ratio",           "default": 0,           "replace": {"_TYPE_": "_NUM_"}         },         {           "name": "Compactness_Height",           "default": 0,           "replace": {"_TYPE_": "_NUM_"}         },         {           "name": "Glazing Area Distribution",           "default": 0,           "replace": {"_TYPE_": "_NUM_"}         },         {           "name": "Orientation",            "default": 0,           "replace": {"_TYPE_": "_NUM_"},           "encoding" : "WoE_cat_to_num" // Интерпретируем Orientation в качестве категориальной и преобразуем её с помощью WoE         }       ]     }   ]

Далее мы можем визуализировать результаты с помощью ResultExport.plots. Функция предоставляет возможность визуализировать как стандартные графики «из коробки», так и передавать свою собственную функцию для отрисовки результатов.

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

В тетрадке показаны три типа графиков. Ниже приведём визуализацию с собственной функцией с помощью метода:

ResultExport(ds_manager=auto_ml).plots('EEI', user_plot_func = plot_info)

Наконец, предположим, что мы хотим использовать ещё более сложную версию процесса, включающую в себя целиком настраиваемую модель и множество других параметров, Например, используем регрессию гауссовского процесса в качестве модели и настроим тип репорта с результатами для отправки по email или сохранения на диск. http://localhost:8889/lab/tree/work/examples/energy_efficiency/3.energy_efficiency_custom.ipynb

Мы используем модель регрессии гауссовского процесса и передаём модель как параметр.

from sklearn.gaussian_process import GaussianProcessRegressor from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C kernel = C(1.0, (1e-3, 1e3)) * RBF(length_scale=1.0) model_energy_efficiency = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=10) models_dict={'EEI':model_energy_efficiency}

Вызываем AutoMLManager с параметро models_dict=models_dict

Далее загружаем результат запуска в виде отчёта с настроенным внутренним форматированием. Мы можем отправить этот отчёт по электронной почте, либо сохранить как HTML файл. В результате запуска кода — auto_ml.review(email=EnergyEfficiencyEMail(config), send_mail=False) — сохраняется отчёт по адресу /home/jovyan/work/results/automl_report.html

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

В статье были показаны базовые возможности использования библиотеки. В следующих статьях мы планируем продемонстрировать более сложную логику, показывая полный цикл AutoML, использование Grafana, MLFlow и FastAPI, проработку дата дрифта, A/B тестирования и другие аспекты библиотеки.

Присоединяйтесь к нашему проекту на GitHub https://github.com/SVSemyonov/outboxml и в Telegram https://t.me/outboxml.

Будем рады услышать конструктивную критику и найти единомышленников для дальнейшего усовершенствования библиотеки!


ссылка на оригинал статьи https://habr.com/ru/articles/942110/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *