Search
Write a publication
Pull to refresh
Страховой Дом ВСК
29 лет на рынке страхового бизнеса

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

Level of difficultyMedium
Reading time7 min
Views402

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

Меня зовут Семён Семёнов, я руковожу 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.

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

Tags:
Hubs:
+6
Comments0

Articles

Information

Website
shop.vsk.ru
Registered
Founded
Employees
5,001–10,000 employees
Location
Россия