Как мы освободили операторов от классификации текстов диалогов на 1000+ классов. nlp.. nlp. nlp обработка текста.. nlp. nlp обработка текста. автоматизация.. nlp. nlp обработка текста. автоматизация. глубокое обучение.. nlp. nlp обработка текста. автоматизация. глубокое обучение. иерархическая классификация.. nlp. nlp обработка текста. автоматизация. глубокое обучение. иерархическая классификация. лаборатория машинного обучения.. nlp. nlp обработка текста. автоматизация. глубокое обучение. иерархическая классификация. лаборатория машинного обучения. машинное обучениe.

Всем привет! Меня зовут Наумов Герман, я работаю в Лаборатории машинного обучения Альфа-Банка, и я расскажу, как мы автоматизировали внутренние процессы, упростили работу операторов чата с физическими лицами. Задача не особо простая и тюнингом гиперпараметров как на Kaggle не решается. Но решается.

Как мы освободили операторов от классификации текстов диалогов на 1000+ классов - 1

Небольшое вступление

Когда клиент обращается в чат или звонит на горячую линию, его встречает чат-бот (или войс-бот, голосовой помощник). Если бот не может решить проблему, клиента переключают на оператора. После завершения разговора оператор заполняет специальную форму, где отвечает на несколько вопросов:

  • По какому продукту обращался клиент (например, Дебетовая карта).

  • По какому подпродукту обращался клиент (например, платежный стикер).

  • Какая была тема обращения (блокировка/разблокировка).

  • Какая была подтема обращения (блокировка по причине утери).

  • Канал, где произошла проблема (сайт банка).

  • Статус решения вопроса (например, «Вопрос решён»).

 Задачу с этой формой мы и решали, о чём и пойдёт речь в статье.

Хотя форма состоит всего из 6 вопросов, но на данный момент у нас 20 Продуктов (классов). И в них:

  • 140 подпродуктов,

  • 120 тем,

  • 630 подтем,

  • 35 каналов,

  • 18 статусов,

  • 1000+ (сочетаний) продукт x тема x подтема.

Каждый продукт, подпродукт, тема, подтема связаны иерархией, которая представлена на картинке:

Как мы освободили операторов от классификации текстов диалогов на 1000+ классов - 2

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

Примечание. Класс — это возможные варианты и подварианты продуктов, например, ипотека, дебетовая карта, кредитная карта, счёт, детская карта. Всё, что продукт, это всё класс.

И заполнение отчёта, где так много классов, занимает у оператора в среднем 30 секунд (например, ему надо мысленно пройтись по этой иерархии). Соответственно, в течение 30 секунд оператор не может приступить к решению нового запроса от клиента. Клиенты ждут, они недовольны, даже если оператора нет минуту. Ну вы сами в курсе — минутное ожидание может казаться вечностью.

С этой проблемой бизнес пришёл в виде запроса (бизнес-задачи):

Необходимо автоматизировать процесс заполнения отчета об обращении физического лица в чат.

Задача в том, чтобы освободить оператора от заполнения отчёта. 

Если мы придумаем эффективное решение, то:

  • Облегчим работу оператора.

  • Снизим Average Handling Time — среднее время сессии с оператором (a.k.a AHT).

  • Повысим качество заполнения отчёта (классификации). Уровень экспертизы у операторов разный и отчёты от опытных операторов яснее, по ним бизнес может быстрее разобраться с проблемой. И не стоит забывать о снижении производительности к концу рабочего дня/недели.

С наскока не получилось: «тут вам не Kaggle»

Задача поступила, мы приступили к работе.

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

Для первой итерации решили остановиться на следующем эвристическом алгоритме:

Сообщения хранятся в БД и помечены тегами (метаданные, id, время и т.п.). Но в единый диалог они не собраны. Берём все сообщения за час (или день), в которых получатель или отправитель — это уникальный клиент, сортируем по времени, склеиваем, отмечаем фразы клиента и оператора.

То есть составляем обучающую выборку.

Вполне очевидным и довольно «дешёвым» вариантом является переиспользование уже существующих данных — ответы операторов на формы за последние месяцы.

И вот у нас есть диалоги и соответствующая диалогу разметка (формы) от операторов. Осталось обучить безлайны и выбрать лучшее решение. И вот мы уже тестируем несколько моделей на основе рекуррентных нейронных сетей и пару трансформер – based моделей

Делюсь результатами лучшей модели за время экспериментов:

Таргет

Точность на тесте, %

Продукт

75

Тема

67

Подтема

47

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

Перепроверим

Провалидируем качество нашей обучающей выборки.

Способ №1 — отдаём экспертам (самым опытным операторам) подвыборку для бинарной перепроверки и просим ответить, правильно ли разметил оператор или нет.

Таргет

Точность, %

Продукт

78

Тема

68

Подтема

64

Способ 2 — скроем разметку от оператора, попросим экспертов разметить заново и замерим согласованность.

Таргет

Согласованность, %

Продукт

65

Тема

52

Подтема

41

Какие выводы из этого можно сделать?

  • Модель не так уж и плоха — качество примерно совпадает с разметкой оператора.

  • Разница между бинарной перепроверкой и полной переразметкой велика. Скорее всего, это произошло, потому что согласиться с чем-то проще, чем размечать с нуля. Ещё одной причиной может быть наличие схожих классов: при перепроверке контроллер согласится с предоставленной разметкой, а при переразметке может уже выбрать какой-то схожий класс.

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

  • Отсутствие логирования изменений классификатора ведёт к наличию неактуальных данных (изменилось > 20 % тематик).

Что мы сделали, чтобы всё получилось?

Меняем подход к сбору данных.

Использование диалога с момента инициации его клиентом до закрытия оператором вместо time-based фильтрации сообщений.

Организуем процесс переразметки обучающей выборки

Решили не использовать эксельки, где было много опечаток, макросов, постоянно ехавших полей, и развернули платформу разметки. На ранних этапах использовали Label Studio, а затем перешли на собственное решение.

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

Размечали с перекрытием и считали, что разметка правильная, если хотя бы два оператора проставили одинаковые классы на всех уровнях. Ещё вели аналитику по точности, согласованности и переразмечали несогласованные кейсы.

Процесс разметки выглядел вот так:

Как мы освободили операторов от классификации текстов диалогов на 1000+ классов - 3

И вот, спустя 6 месяцев, у нас 50 000+ примеров при согласованности в 65–80%. Всё это руками 3–6 экспертов. Проблем с актуальностью некоторых тематик у нас теперь нет. Если и появляется новая тема/подтема, мы переразмечаем кейсы со старой тематикой.

Перейдем к модельной части

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

Как мы освободили операторов от классификации текстов диалогов на 1000+ классов - 4

Некоторые важные детали:

  • Использовали символы разграничители для фраз клиентов и операторов.

  • Шеринг весов, регуляризация, layer-wise learning rate, learning rate warmup помогают с переобучением. Об этих и других методах мои коллеги подробно рассказывали на курсе «NLP in practice». 

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

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

Таргет

Точность, %

Продукт

92

Подпродукт

89

Тема

86

Подтема

77

Канал

97

Статус

85

Вот теперь хорошо.

Внедряем модель в production

Как мы освободили операторов от классификации текстов диалогов на 1000+ классов - 5

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

Ведь мониторинг показал, что качество предсказания подпродукта сильно просело…Хмм.

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

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

  • Вопросы по открытым продуктам клиента. В таких обращениях клиент очень редко уточняет, по какому именно продукту у него вопрос. Он просто спрашивает: «Подскажите условия по моему вкладу». Даже оператор не в силах понять, что конкретно имел в виду клиент: «Альфа-Вклад Максимальный» или «Альфа-Вклад новые деньги». Для этого он смотрит, какие вклады есть у этого клиента.

В процессе предсказания мы точно не знаем, к какой категории относится обращение, поэтому договорились на следующее упрощение — замаскируем те продукты, которых у клиента нет. И теперь модели предстоит сделать выбор из 2-3 классов вместо 15.

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

Реализовав это, получаем такой буст в качестве:

Как мы освободили операторов от классификации текстов диалогов на 1000+ классов - 6

Итоговый процесс теперь выглядит так:

Как мы освободили операторов от классификации текстов диалогов на 1000+ классов - 7

Результаты в цифрах.

Таргет

Точность оператора

Точность модели

Продукт

88

94

Подпродукт

78

81

Тема

77

87

Подтема

66

79

Канал

83

97

Статус решения

69

88

Итоги

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

После внедрения модели Average Handling Time снизили на 30 секунд, а 80% операторов освобождены от обязательного заполнения классификатора. А сейчас и все 90% (не убираем оставшиеся 10%, чтобы была возможность майнить данные с новыми классами).

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

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

Красота.


А чтобы не пропускать анонсы наших статей и других новостей из мира DS – обязательно переходите в Телеграмм-канал «Нескучный Data Science» 

Подписывайтесь на Телеграм-канал Alfa Digital — там мы постим новости, опросы, видео с митапов, краткие выжимки из статей, иногда шутим.

Автор: GermanNaumov

Источник

Rambler's Top100