Мы продолжаем рассказ про нашу систему «Светофор 3.0», которая позволяет прогнозировать качество прямых поставок и экономить время на приемке товара. О том, как это работает и зачем нужно компании, вы можете прочитать в нашем предыдущем посте, а сегодня мы раскрываем техническую сторону вопроса — об алгоритме ML и его развитии, о схеме передачи данных и некоторых нюансах интеграции «Светофора 3.0» со складской системой.

ML-архитектура

«Светофор 3.0» — это система, которая определяет, насколько прямым поставкам можно доверять, и в одних случаях рекомендует принять товары доверительно, а в других — пересчитать. (Что это дает — читайте здесь). Прогнозирование степени доверия к поставке происходит на основе алгоритма деревьев решений с бустингом.

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

Кроме того, CatBoost прекрасно обрабатывает исключения, которые встречаются в датасете (NaN, неожиданные «нули» и т. д.). На Хабре можно найти множество детализированных обзоров применения и настройки алгоритма. Мы ничего кардинально нового с точки зрения машинного обучения не использовали и взяли CatBoost «as is», выполнив стандартную настройку гиперпараметров.

Интеграция с Navision WMS

Но при этом перед командой стояла задача свести к минимуму изменения в бизнес-процессах. У нас очень много магазинов, и поэтому обучение вместе с функциональной поддержкой требует огромного количества ресурсов. Именно поэтому мы старались максимально оградить сотрудников магазина от внедрения новых инструментов. Алгоритм «Светофора 3.0» было решено внедрить в текущий рабочий процесс и не менять ничего в инструменте, с которым работают сотрудники склада — то есть со складской системой WMS Navision.

Система содержит информацию о поставках за пол года, а также сопутствующую информацию — в частности, ID поставщика, ID магазина, даты приемки, номера заказов, номера поставок, артикулы товаров, флаги доверительной приемки и т. д. Именно эти данные мы использовали для обучения модели CatBoost — всего 1519 поставщиков и 68 275 артикулов (и это только прямые поставки в магазины).

Этап интеграции с Navision WMS был важным и трудоемким. Для этого нам пришлось провести ряд работ с самой Navision WMS. В частности, потребовалось добавить дополнительные поля значений, чтобы размещать в них результаты проверки поставки в «Светофоре 3.0». 

Схема движения данных

Чтобы наш «Светофор 3.0» заработал, пришлось реализовать интеграцию и наладить передачу данных из WMS Navision в основное хранилище данных GreenPlum. В GreenPLum хранятся данные за большой период, поэтому ML модель забирает оттуда исторические данные для переобучения.

Технически это выглядит следующим образом: когда поставщик доставляет свои паллеты на склад магазина, сотрудник вводит данные о поставке в Navision. Через Kafka мы в онлайн-режиме получаем от Navision сообщение о поставке, которое обрабатывается и сохраняется в базе данных Postgres, а затем передается в модуль Predict в Kubernetes. Модуль Predict обращается к модели CatBoost и генерирует признак доверительной приемки на основе отклика модели. К сообщению прикрепляется признак доверительной приемки (1 — доверительно, 0 — отправить на пересчет). 

После этого сообщение уходит обратно в Navision (также с помощью Kafka), и уже меньше чем через минуту сотрудник склада видит значение признака доверительной приемки и принимает решение о том, стоит ли пересчитывать товар в поставке с учетом рекомендации «Светофора 3.0» или нет. 

Для того чтобы наладить обмен данными между Navision WMS и нашей ML-моделью, пришлось завести в учетной системе специальный аккаунт, поработать с логикой расчета убытков (система по умолчанию считает средний убыток, а нужен был суммарный). Кроме этого, новый поток инфообмена выявил пару косяков при настройке сетевых соединений — так, на некоторых серверах пришлось поправить DNS, немного покопаться в настройках GreenPlum и протестировать двустороннюю передачу данных со всеми магазинами (оказалось, что один из них выпал из обоймы и по умолчанию не хотел общаться со «Светофором 3.0»). Все эти вопросы решились достаточно быстро, а каких-то крупных проблем при настройке обмена сообщениями через Kafka мы не встретили.

Схема движения данных
Схема движения данных

Свобода воли и рандомный пересчет

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

Иногда модель предлагает пересчитать товар в поставке на случайной основе. Это необходимо, чтобы расширить датасет и увеличить стабильность модели. При том, что точность прогноза может составлять до 98-99%, нам необходимы дополнительные данные для того, чтобы модель не оторвалась от реальности. Для этого специально пересчитывается порядка 5% поставок из тех, которые «Светофор 3.0» маркирует как доверительные. Какие именно — выбирается случайным образом.

Если же сотрудник склада принял решение о ручном пересчете поставки, то он дополняет запись в Navision данными о количестве пересчитанных товаров и поясняет, почему он принял такое решение. Эта запись отправляется в специальную витрину в Postgres и в дальнейшем используется для тренировки моделей, которые хранятся в S3 на Yandex Cloud.     

Заключение

В таком виде наш «Светофор 3.0» уже работает во всех магазинах «Леруа Мерлен Восток». Команда планомерно работает с теми филиалами, которые чаще всего меняют решения системы, и уточняет, почему это происходит. Мы продолжаем развитие продукта, а доказанная на практике успешность применения подобных ML-моделей в логистических процессах стала стартом для еще одного проекта, который помог нам оптимизировать затраты на складскую обработку товаров.

Кстати, расскажите, а что вы думаете про применение ML для подобных задач? Если у вас есть релевантный опыт, поделитесь своим мнением в комментариях.

Комментарии (0)