Как стать автором
Обновить
58.97
Ингосстрах
Строим ИТ в большой страховой

Архитектура проекта автоматического обучения ML-моделей

Уровень сложностиСредний
Время на прочтение11 мин
Количество просмотров2.7K

Хабр, привет! На связи Кравцов Кирилл и Суздалев Руслан из команды моделирования поведенческих сценариев Центра развития искусственного интеллекта СПАО «Ингосстрах»(далее — ЦРИИ). В статье поделимся решением, которое помогает нам быстрее обучать и интегрировать модели в компании.

С ростом компании и ЦРИИ, в частности, у нас появлялось все больше бизнес-заказчиков, которым нужны были ML-модели. Поэтому потребность росла, а ограниченность ресурсов не позволяла быстро обрабатывать задачи бизнеса и многое уходило в беклог.

Чтобы справиться с растущими потребностями, мы разработали несколько ключевых шагов, которые значительно упростили и ускорили процесс создания ML-моделей:

Шаг №1. Разработка моделей классического ML

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

Шаг №2. Выявление ошибок в процессе разработки

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

Шаг №3. Оцифровка алгоритма работы Data Scientist

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

Шаг №4. Написание документации

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

Шаг №5. Подготовка шаблона для запросов на разработку моделей

Мы разработали шаблон, который позволяет бизнес-подразделениям формулировать свои запросы на разработку моделей с помощью AutoML. Это значительно упрощает коммуникацию между бизнесом и командой разработчиков, т.к. теперь можно четко обозначить требования и ожидания от модели.

Шаг №6. Разработка AutoML

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

Сравнение разработки моделей с AutoML и без
Сравнение разработки моделей с AutoML и без

А теперь будем разбираться более детально! Мы разработали модульную архитектуру, которая стала нашим спасательным кругом и представляет собой своего рода «конструктор», позволяющий легко работать с данными, моделями и процессами обучения. Она не только сэкономила нам массу времени, но и открыла новые горизонты для экспериментов, позволяя сосредоточиться на креативных аспектах разработки, а не на рутинных задачах. Давайте остановимся на основных компонентах нашего проекта, как они устроены и как взаимосвязаны между собой.  Начнем на примере кейса как поменялся бизнес-процесс с одним из заказчиков ЦРИИ:

Наглядный пример бизнес-процессов без AutoML и с
Наглядный пример бизнес-процессов без AutoML и с
Результат внедрения AutoML
Результат внедрения AutoML

Основные компоненты архитектуры:

­Model Conveyor
­Model Conveyor

Хранилище данных

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

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

from abc import ABC, abstractmethod
from typing import Dict


class DataSource(ABC):
    """Interface class for data sources providing methods to get and put data."""

    def __init__(self, config: Dict):
        self.config = config

    @abstractmethod
    def get_data(self, path: str) -> Any:
        """Retrieve data from the specified path."""
        pass

    @abstractmethod
    def put_data(self, data: Any, path: str):
        """Store the given data at the specified path."""
        pass

Модели

Обычно у Data Scientist’а есть любимый Jupyter Notebook на все случаи жизни, который он запускает с разными данными, а model factory, по сути, как раз и представляет собой этот самый ноутбук только автоматизированный.

Каждая модель реализована как класс, наследующийся от базового класса MLModel, обеспечивая единый интерфейс и общие атрибуты, в частности, такие методы как train, predict и valid должны быть реализованы в каждой модели. Например, CatBoostGridSearchClassifier включает в себя методы для настройки гиперпараметров.

Основные компоненты:

  • Инициализация: Конструктор класса принимает несколько параметров, таких как target, ids, preprocessor, features, output_channels_schema и т.д. Эти параметры позволяют настроить модель для конкретной задачи и обеспечить гибкость в использовании.    

  •  Схемы ввода и вывода: Свойства input_schema и output_schema определяют, какие столбцы данных используются для входа и выхода модели. Это важно для правильной обработки данных и формирования результатов.

  • Методы предсказания: Метод predict отвечает за создание таблиц с оценками для обученной модели. Он обрабатывает входные данные с помощью предварительного препроцессора и возвращает либо DataFrame с результатами, либо только оценки, в зависимости от параметра return_only_score.

  •   Валидация модели: Метод valid позволяет проверить качество модели на отложенной выборке.

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

from abc import ABC, abstractmethod
from typing import List

class MLModel(ABC):
    """Abstract base class for ML model prediction."""

    def __init__(
        self,
        name: str,
        features: List[str],
        preprocessor,
        id_cols: List[str],
        target_col: str
    ):
        self.name = name
        self.features = features
        self.preprocessor = preprocessor
        self.id_columns = id_cols
        self.target = target_col

    @property
    @abstractmethod
    def input_schema(self):
        """Returns the schema of the input data."""
        pass

    @property
    @abstractmethod
    def output_schema(self):
        """Returns the schema of the output data."""
        pass

    @abstractmethod
    def predict(self, data, return_only_score: bool = False):
        """Makes predictions based on the input data."""
        pass

    @abstractmethod
    def train(self, data):
        """Trains the model using the provided data."""
        pass

Конвейер моделей

Конвейер моделей управляет всем процессом: от получения данных из БД до обучения модели и получения предсказаний. Это позволяет настроить последовательность шагов и автоматизировать рутинные задачи.

from abc import ABC, abstractmethod

class ModelConveyor(ABC):
    """Abstract base class for managing training and prediction processes for ML models."""

    @abstractmethod
    def __init__(
        self,
        model_rep: ModelRepository,
        feature_store: DataSource,
        predictions_store: DataSource
    ):
        self.model_rep = model_rep
        self.feature_store = feature_store
        self.predictions_store = predictions_store
        self.model = None
        self.data = None
        self.predictions = None

    @abstractmethod
    def train(self, model: MLModel, query: str):
        """Trains the specified ML model using the provided query to fetch data."""
        pass

    @abstractmethod
    def predict(self, model_name: str, query: str, target_table: str):
        """Makes predictions using the specified model and stores results in the target table."""
        Pass

Несколько примеров конвейеров, которые у нас есть:

  • Базовый конвейер BasicModelConveyor: Этот класс реализует основные функции, такие как обучение модели, валидация и предсказание. Он использует хранилище моделей и источники данных для получения необходимых данных и сохранения результатов. Это позволяет легко управлять жизненным циклом модели;

  • Калиброванный конвейер CalibratedBasicModelConveyor: Этот класс расширяет функциональность базового конвейера, добавляя возможность калибровки модели. Калибровка позволяет улучшить точность предсказаний, особенно в задачах, где важно правильно оценить вероятности;

  • Многофункциональный конвейер MultiPredictConveyor: Этот класс позволяет выполнять предсказания с использованием нескольких моделей одновременно. Это полезно в сценариях, когда необходимо сравнить результаты различных моделей или использовать ансамблирование для повышения точности предсказаний.

Трансформеры

Трансформеры реализуют интерфейс Transformer, который определяет методы fit, transform и inverse_transform, тут по факту sklearn реализации. Это позволяет легко добавлять новые трансформеры и использовать их в конвейере.

Например, RemoveOutliers чистит данные от выбросов.

from sklearn.base import BaseEstimator, TransformerMixin

class Transformer(BaseEstimator, TransformerMixin):
    """
    A custom transformer class that implements the Scikit-Learn BaseEstimator
    and TransformerMixin interfaces.
    """

    def fit(self, data):
        """
        Fit the transformer to the input data.
        """
        return self

    @abstractmethod
    def transform(self, data):
        """
        Transform the input data.
        """
        return data

    def inverse_transform(self, data):
        """
        Reverse the transformation on the input data.
        """
        return data

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

Хранилище моделей

Класс ModelRepository отвечает за хранение и управление моделями. Он позволяет сохранять обученные модели на диск или в S3-хранилище и загружать их при необходимости, что упрощает процесс развертывания.

from abc import ABC, abstractmethod
from typing import Optional, Dict

class ModelRepository(ABC):
    """Abstract base class for managing machine learning models in a repository."""

    def __init__(self, config: Optional[Dict] = None):
        self.config = config

    @abstractmethod
    def get_model(self, model_name: str) -> MLModel:
        """Retrieves a machine learning model by its name."""
        pass

    @abstractmethod
    def put_model(self, model: MLModel):
        """Stores a machine learning model in the repository."""
        pass

Генерация отчетов

После того как модель обучилась нам нужно оценить её качество, для этого после обучения модели автоматически генерируется отчет с её характеристиками такими как: метрики, описание датасета, используемая модель и её гиперпараметры и т.д. Кроме того, такой отчет является отличным артефактом для представления бизнес-заказчику. Также к нему можно всегда вернуться спустя время, и, даже если сотрудник, который обучал модель ушёл, будет легко разобраться, что за модель, на чем обучалась и какое у неё качество.

Пример первых страниц отчета
Пример первых страниц отчета

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

Основные компоненты кода включают классы Report, ReportBlock, и различные конкретные блоки отчетов, такие как ConfusionMatrixBlock, FeatureImportancesBlock и другие.

Описание функциональности классов:

Класс Report: отвечает за создание и управление отчетами. Он принимает список блоков отчётов и применяет их к методам модели.

Метод call: позволяет использовать класс как декоратор для модели, добавляя функциональность отчетов к методам модели. Метод report генерирует документ отчёта, добавляя в него все блоки отчетов.

Класс ReportBlock: это абстрактный базовый класс для всех блоков отчетов. Он определяет общие методы и атрибуты, которые должны быть реализованы в дочерних классах. Каждый блок может добавлять свои данные в документ и сохранять артефакты, связанные с выполнением методов модели.

from abc import ABC, abstractmethod
from typing import Union, List, Optional
import pandas as pd

class ReportBlock(ABC):
    """Abstract base class for report blocks."""

    TYPE: ReportBlockType = ReportBlockType.PRE_EXECUTE

    def __init__(self, methods: Union[str, List[str]]) -> None:
        self.methods = methods

    @abstractmethod
    def add_block(self, document):
        """Adds the block to the document."""
        pass

    @abstractmethod
    def save_artifacts(self, stage: Optional[str] = None, data: Optional[pd.DataFrame] = None, model: MLModel = None):
        """Saves the artifacts."""
        pass

Типы блоков отчетов: ReportBlockType определяет два типа блоков: PRE_EXECUTE (выполняется перед методом) и POST_EXECUTE (выполняется после метода).

class ReportBlockType(Enum):
    """
    Enumeration for the types of report blocks.

    - PRE_EXECUTE: Block to be executed before the decorated method.
    - POST_EXECUTE: Block to be executed after the decorated method.
    """
    PRE_EXECUTE = 0
    POST_EXECUTE = 1

Конкретные блоки отчетов:

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

Списки блоков: CLF_CRM_MODEL_BLOCKS и REG_CRM_MODEL_BLOCKS содержат наборы блоков, которые могут быть использованы для различных типов моделей (например, для моделей классификации и регрессии).

Как может выглядеть последовательность блоков для задачи бинарной классификации:

  • InitDocument: Создает пустой документ.

  • DataPropertiesBlock: отображает основные свойства данных.

  • MetricsBlock: собирает и отображает метрики модели.

  • ConfusionMatrixBlock: создаёт матрицу ошибок.

  • FeaturesImportancesBlock: визуализирует важность признаков.

  • HyperparametersBlock: отображает гиперпараметры модели.

  • TargetDistributionBlock: показывает распределение целевой переменной.

Как работает модуль генерации отчетов:

Создание модели: Создайте класс модели, который будет содержать методы, для которых вы хотите генерировать отчеты.

Применение декоратора: Используйте класс Report как декоратор для вашей модели, передавая ему необходимые блоки отчетов.

@Report(CLF_CRM_MODEL_BLOCKS)
class MyModel(MLMo):
    def train(self, data):
        # Логика обучения модели
        pass

    def validate(self, data):
        # Логика валидации модели
        pass

Генерация отчета:

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

model = MyModel() 
model.train(data) 
model.validate(data) 
report_path = model.report(folder_to_save='reports')

Какие (на наш взгляд) у модуля получились сильные стороны:

  • Модульность: использование блоков отчетов позволяет легко добавлять, удалять или изменять части отчета без изменения основной логики модели.

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

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

  • Гибкость: возможность добавления различных типов блоков (например, для различных метрик или визуализаций) позволяет адаптировать систему отчетов под конкретные нужды.

  • Автоматизация: система автоматически сохраняет артефакты и генерирует отчеты, что экономит время и усилия разработчиков.

Логирование

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

Пример логов
Пример логов

P.S. Созданием паспорта и просмотров логов обучения, конечно же, все не ограничивается – жизненный цикл модели в Ингосстрахе гораздо длиннее: надо смотреть популяции, мониторить качество работы на проде и еще много чего. Но эта тема уже для отдельной статьи. =)

В итоге, пайплайн на обучение и инференсе работают так:

Пайплайн на обучении
Пайплайн на обучении
Пайплайн на инференсе
Пайплайн на инференсе

Ключевые особенности разработанной архитектуры:

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

  •   Интерактивная настройка: в отличие от статических систем, наша архитектура поддерживает динамическое изменение параметров моделей и трансформеров во время обучения. Это позволяет оперативно реагировать на изменения данных или результаты промежуточных этапов, корректируя процесс обучения «на лету». Такая интерактивность дает беспрецедентную гибкость, позволяя исследователям экспериментировать и тонко настраивать модели для достижения оптимальных результатов.

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

Наши планы на будущее:

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

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

Итого мы получаем следующее:

Разработанная архитектура — это не статичный продукт, а постоянно развивающаяся система, которая позволяет эффективно управлять процессами обучения моделей машинного обучения, обеспечивая гибкость, расширяемость и автоматизацию. Ее ключевые преимущества — параллельное обучение, интерактивная настройка и поддержка различных алгоритмов — делают её универсальным решением для широкого спектра задач. Постоянное развитие и совершенствование архитектуры, включающее интеграцию GPU‑кластера, усовершенствование препроцессинга и оптимизацию кода, позволят ей оставаться на переднем крае технологий машинного обучения.

Теги:
Хабы:
+7
Комментарии1

Публикации

Информация

Сайт
www.ingos.ru
Дата регистрации
Дата основания
Численность
5 001–10 000 человек
Местоположение
Россия
Представитель
Eline