Как мы научили Adesk предсказывать статьи банковских операций

👋 На связи инженерная команда сервиса финансового учета для малого бизнеса Adesk. У нас есть очень важная задача: сделать так, чтобы новые пользователи максимально быстро погружались в продукт. На одном из этапов клиенту нужно распределить свои банковские операции по статьям, чтобы получить актуальную аналитику по своему бизнесу. Сегодня мы расскажем, как разработали алгоритм, который умеет предсказывать статьи и очень упрощает пользователям работу с сервисом.

В закладки

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

С чего все начиналось, шаг первый

Сначала мы разработали простой микросервис, который показывает пользователю нераспределенные операции (без статьи) одну за другой, а человек должен выбирать подходящую статью. Это достаточно удобно: просто кликаешь на нужную статью, потом тебе «прилетает» следующая, и так пока они не закончатся. Мы назвали этот сервис Matchmaker.

Шаг второй

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

Вторая версия Matchmaker

Шаг третий

Текущая версия Matchmaker'а уже неплохо работала и помогала пользователям. Однако, мы решили пойти дальше и подключили тяжелую артиллерию — разработали умный предиктор (предсказатель) статей, который использует TF-IDF модель, основанную на размеченных пользователями данных.

Теперь Matchmaker научился сам определять, какая статья соответствует этой операции и может давать пользователям подсказки. Более того, он обучается и становится точнее с каждой новой размеченной операцией.

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

Поиск похожих операций стал гораздо эффективнее и умнее

Как это работает

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

В основе языковой модели предиктора лежит метрика TF-IDF (от англ. TF — term frequency, IDF — inverse document frequency) — статистическая мера, используемая для оценки важности слова в контексте документа, являющегося частью коллекции документов или корпуса. Вес некоторого слова пропорционален частоте употребления этого слова в документе и обратно пропорционален частоте употребления слова во всех документах коллекции.

В контексте предметной области документом будем называть совокупность описаний всех операций с одной статьей, а корпусом — коллекцию документов по всем известным статьям.

Расчет метрики

Итоговая метрика состоит из двух компонентов. Компонент TF (term frequency — частота слова) — отношение числа вхождений некоторого слова к общему числу слов документа. Таким образом, оценивается важность слова в пределах отдельного документа. Рассчитывается по формуле:

Здесь nt — это число вхождений слова t в документе d, а в знаменателе — общее число слов в данном документе.

Компонент IDF (inverse document frequency — обратная частота документа) — величина, обратная частоте, с которой некоторое слово встречается в документах коллекции. Учёт IDF уменьшает вес широкоупотребительных слов. Рассчитывается по формуле:

где числитель — число документов в корпусе, а знаменатель — число документов из коллекции D, в которых встречается t

Итоговая метрика вычисляется как произведение этих компонентов. Больший вес в TF-IDF получат слова с высокой частотой в пределах конкретного документа и с низкой частотой употреблений в других документах.

Построение модели

Модель предиктора представляется в виде двух матриц: матрицы частотности слов и матрицы весов слов по статьям. Матрица частотности каждой статье сопоставляет частоты слов во всех описаниях операций с данной статьей:

Матрица весов каждому слову сопоставляет набор статей, ранжированный метрикой TF-IDF этого слова в каждой из статей:

Для построения начальной модели отбираются все размеченные операции и группируются по статьям, производится предобработка описаний операций: токенизация (разбиение на слова), удаление стоп-слов и стемминг (выделение основ слов). Получившиеся в результате токены подсчитываются и заносятся в матрицу частотности. Затем, на основе построенной матрицы частотности заполняется матрица весов: для каждого токена в каждой группе вычисляется метрика TF-IDF и получившийся вес заносится в матрицу.

Инкрементальное дополнение модели

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

Разделение моделей по пользователям

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

Процесс предсказания статей

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

К примеру, рассмотрим операцию с описанием "Перечисление заработной платы за март. НДС не облагается":

  • После предобработки получим набор токенов [перечисл, заработ, плат, март, НДС, облаг].
  • По каждому токену получаем статистику из матрицы весов:
    перечисл: { банковские переводы: 1.2345, вывод денег из бизнеса: 0.9876, заработная плата: 0.8371 }
    заработ: { заработная плата: 1.0572 }
    плат: { оплата счетов: 0.8234, заработная плата: 0.9143 }
    НДС: { налоги и пошлины: 1.5432 }
    облаг: { налоги и пошлины: 1.0213 }

  • Формируем сводную статистику: { заработная плата: 2.8086, налоги и пошлины: 2.5645‬, банковские переводы: 1.2345, вывод денег из бизнеса: 0.9876, оплата счетов: 0.8234 }
  • Три статьи с наибольшим весом выбираются в качестве наиболее подходящих. Получаем итоговое предсказание: [ заработная плата, налоги и пошлины, банковские переводы ].

Технические детали

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

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

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

Надеемся, было интересно. Удачи!

{ "author_name": "ADESK / Управленческий учёт", "author_type": "self", "tags": [], "comments": 0, "likes": 13, "favorites": 7, "is_advertisement": false, "subsite_label": "unknown", "id": 131830, "is_wide": true, "is_ugc": true, "date": "Thu, 04 Jun 2020 08:05:42 +0300", "is_special": false }
Объявление на vc.ru
0
Комментариев нет
Популярные
По порядку

Комментарии