Банки получают содержание кассовых чеков клиентов по транзакциям, совершенных по собственным картам через Операторов Фискальных Данных с согласия клиента. Данные приходят в сыром текстовом формате, аналогичном тому, что вы получаете в магазине на бумажном носителе информации после каждой вашей покупки. Каждый магазин заносит товары в кассовое ПО в произвольном, полюбившемся ему формате. Чеки некоторых магазинов содержат полное название каждой из товарных позиций, большинство же, видимо, сильно экономят на бумаге и сокращают все названия.
В кассовых чеках не содержатся штрих-коды и другие идентификаторов товаров. К сожалению, исходя из вышеописанных причин, не может существовать единого каталога с категоризацией всех названий товаров из чеков. А ведь наличие такого каталога помогло бы более качественно отображать детализацию покупок клиенту. Дополнительно категоризация товарных позиций может быть использована в качестве дополнительных признаков в моделях, использующих транзакционные переменные.
Весной 2021-го года ВТБ организовывал соревнование на платформе Boosters с целью решения этой задачи.
Описание соревнования
Участникам был предоставлен массив данных, содержащий более семи миллионов неразмеченных чеков и более одного миллиона размеченных чеков. К сожалению, уникальных размеченных товарных позиций было порядка 50 тысяч, заявленный миллион чеков был сгенерирован на основе этой разметки. К счастью, в неразмеченных данных такая тенденция не прослеживалась и в них содержалось примерно 3 миллиона уникальных товарных позиций. В выборке содержались объекты из 90 различных классов.
Товарная позиция |
Цена |
Кол-во |
НДС |
День недели |
Время |
ЙогуртпитEPICAклуб/мар290 |
10 |
1 |
2 |
5 |
11:34 |
Пиво Велкопоповицкий Козел темное ж/б 3,7% 0,45л |
9 |
1 |
6 |
3 |
20:54 |
Энерг. нап. Адреналин Раш 0,25л ж/б (ПепсиКо) |
10 |
1 |
1 |
4 |
14:38 |
Нектар ФрутоНяня Тыквенный с мяк 0,5л |
12 |
1 |
6 |
6 |
17:12 |
Картофель весовой |
8 |
0.43 |
1 |
2 |
11:03 |
В дополнение к названию товарных позиций были доступны мета-признаки: ценовой бакет, количество товара, тип НДС, день недели и время покупки. Опыт подсказывает, что весовые товары сложно купить в целом количестве штук, а схема налогообложения в РФ различна для ряда товаров и услуг, поэтому дополнительные категориальные признаки могут быть полезны для решения задачи.
Организаторы соревнования выбрали метрику weighted f1 score в качестве целевой. Соревнование проходило в формате docker. Время выполнения алгоритма ограничивалось 1.5 часами. Каждый сабмит не должен был превышать 500 мегабайт. Характеристики среды исполнения: 8 vCPU, 46 GB RAM, Nvidia Tesla V100 16 GB.
Подготовка данных
Без преувеличения, текстовые данные кассовых чеков можно смело называть "грязными". Очень часто разделителем является не пробел, а точка, слэш, смена регистра, а иногда и смена языка. Некоторые магазины очень любят сокращения, другие, наоборот, для экономии обрезают часть слов. Некоторые даже экономят на мощности словаря и заменяют все похожие буквы из кириллицы на аналоги из латиницы или цифры: "к" на "k", "с" на "c" или "з" на "3". Также не всегда возможно по названию товара из чека произвести биекцию на товарную позицию, например, "Шоколадный батончик Snickers Лесной орех, 81 г" в каталоге может называться как "Шок. бат".
Алгоритм предобработки данных состоял из следующих этапов:
1. Перевод всех символов в нижний регистр.
2. Замена всех визуально-похожих символов на вариант из кириллицы.
3. Токенизация по группе регулярных выражений.
4. Замена всех последовательностей цифр на "1".
Так, например, строка "Молоко Домик.в деревне 3.2% 0.5л пл/б БЗМЖ/Россия" после предобработки превращалась в "молоко домик в деревне 1% 1л пл/б бзмж россия".
С одной стороны, размер обучающей выборки крайне мал для того, чтобы выучить вектора слов в режиме end-to-end. C другой стороны, доменный контекст в этой задаче сильно отличается от Википедии, Ленты и других популярных датасетов, на которых предобучают векторные представления слов. К счастью, после предобработки данных получалась выборка порядка 2.7 миллионов уникальных строк, что эмпирически можно считать достаточным объем для обучения векторов под специфичный домен. Пример обучения векторов FastText из туториала через CLI-интерфейс:
$./fasttext skipgram -input data/fil9 -output result/fil9 -minn 2 -maxn 5 -dim 300
Модели
Организаторами соревнования был предоставлен бейзлайн на основе логистической регрессии и мешка слов 0.63 F1. Замена логистической регрессии на SVM и добавление символьных нграмм заметно улучшили качество до 0.84 F1. В соревновании на kaggle на аналогичных данных от @dremovd значительно улучшало качество добавление контекста всего чека. В этом соревновании такой подход не зашел, так как чеки были искусственно сгенерированы.
На данный момент SOTA-решением для классификации текстов принято считать BERT-подобные архитектуры. Они показывают отличное качество за счет огромного количества обученных параметров, впитавших контекстные знания из огромных корпусов документов. К сожалению, названия товарных позиций сильно отличаются от текстов новостей и статей википедии. Более того, не существует аналогичных корпусов для домена кассовых чеков, на котором можно было бы обучить BERT. В случаях серьезного доменного отличия эмпирический опыт говорит, что рекуррентные сети справляются с решением задачи лучше.
В итоге выбор архитектуры был сделан в пользу двунаправленной рекуррентной сети с пуллингами и скип-коннекшенами. Представленная ниже архитектура практически полностью дублирует описанную в предыдущей статье.
В первую версию решения были добавлены дропауты и L2 регуляризации, а также подобрано число обучаемых параметров для того, чтобы сеть не переобучалась. Дополнительно был использован Cyclic Learning Rate для лучшей сходимости. В итоге такое решение получило 0.85 F1.
Следующим шагом было ансамблирование моделей. Размеченная выборка была разделена на пять фолдов, выбранная архитектура обучалась на подмножествах из четырех фолдов до тех пор, пока росло качество на оставшемся фолде. Предсказания для тестовой выборки считались как среднее от пяти моделей. Ансамблирование улучшило качество решения до 0.86 F1.
Вектора были необучаемыми параметрами сети ввиду того, что у python-пакета fasttext отсутствует совместимый с pytorch и tensorflow интерфейс для дообучения векторов в end-to-end режиме. FastText при построении векторного представления слова использует нграммы слова, а также особым образом учитывает его начало и конец. Улучшение алгоритма токенизации повысило качество решения до 0.865 F1.
Соревнование проходило в docker-формате, что приводило к необходимости отправки архива с кодом и бинарников в проверяющую систему в рамках каждого сабмита. В системе было установлено ограничение в 500 мегабайт на размер входного файла. Бинарный файл с размерностью векторов 50 едва пролезал через это ограничение.
При использовании параметров по умолчанию библиотека fasttext создает 2 миллион хэшей для хранения векторов нграмм. Их количество можно снизить, уменьшая значение параметра -bucket. В ходе экспериментов выяснилось, что оптимальным размером вектора является 150. Таким образом, при размере словаря 95k и размерности ембеддинга 150 и -butcket=2m бинарный файл весит 1.2 ГБ, а при -bucket=700k — всего 480 МБ. Это бесценное знание помогло увеличить размерность с 50 до 150. Увеличение размера векторного представление слов повысило качество до 0.88+ F1.
Пролог
К сожалению, не всегда удавалось понять четкое различие между классами при помощи естественного интеллекта. В данных было несколько классов с продуктами, скорее всего, различающих по формату магазина: супермаркет, магазин у дома, гипермаркет. Более того, в выборке был выделен класс "другое", в который асессоры относили не только "другие товары", но и сложные объекты из остальных классов. Частичная переразметка этого класса не приводила к росту метрик, так как на тестовой выборке разметка, видимо, была идентичной.
В соревновании не зашли буквенные рекуррентные и сверточные сети, в том числе в качестве дополнительного энкодера. Полагаю, что это следствие обучения на небольшой размеченной выборке. Не зашел подход активного обучения. Видимо, fasttext впитал в себя максимум контекста из неразмеченной выборки.
Материалы
Турнирная таблица
Публичные решения
https://github.com/dremovd/data-fusion-1-baseline
https://github.com/gorodion/GoodsClassifier
https://github.com/aptmess/data_fusion_goodsification
https://github.com/pozdnyakovx/VTB_data_fusion_2021
https://github.com/pskliff/vtb-data-fusion
https://github.com/Irinas5555/Data-Fusion-Contest-Goodsification--18-place-on-public-liderboard-
https://github.com/v-pozdnyakov/data-fusion-contest
Конференция Data Fusion
Комментарии (30)
ya_penek
01.11.2021 16:27+1Банки получают содержание кассовых чеков клиентов по транзакциям, совершенных по собственным картам через Операторов Фискальных Данных с согласия клиента.
А зачем это нужно банкам и клиентам?
И как узнать, не дал ли я когда-нибудь случайно такое согласие? Мне бы не хотелось, чтобы лишние люди знали, что я покупаю.
smirnovevgeny Автор
01.11.2021 19:26Как клиенту, мне удобно просматривать историю покупок в приложении. Зачем нужно банкам расскажу в следующей статье. Согласия должны предоставляться/отключаться в рамках мобильного приложения.
amarao
01.11.2021 16:57+2А как отказаться от согласия на передачу данных чеков банкам?
smirnovevgeny Автор
01.11.2021 20:04Согласия в вашем банке скорее всего предоставляются/отзываются в рамках интерфейса мобильного приложения.
amarao
02.11.2021 13:53+1А если у меня нет мобильного приложения? Мой телефон TA-68 не поддерживается. А я всё равно хочу отказаться от этой фигни. Я подошёл к девочке на респепшене в банке, но она мне сказала, что не понимает о чём речь.
smirnovevgeny Автор
07.11.2021 00:46Убедитесь, что ваш банк получает такие данные.
Воспользуетесь веб-сайтом или позвоните в колл-центр.
amarao
07.11.2021 11:54А как "убедиться"?
smirnovevgeny Автор
07.11.2021 18:41Найти новость в публичном пространстве.
Сделать официальный запрос в банк в письменном виде.
exceL
08.11.2021 20:53К сожалению, от покупателя в данном случае мало что зависит. Да, в интерфейсе некоторых банковских приложений есть галочка разрешающая сбор таких данных, но по факту у большинства ОФД прямые договора с банками, и магазины работая с такими ОФД автоматически дают согласие на передачу данных банкам (передача третьим лицам в обезличенном вроде прописана в оферте), а имея точное время совершения транзакции, и данные чеков из ОФД, легко сопоставить что именно покупал клиент. Снятие же галочки, скорее всего просто отключает подгрузку данных о покупке в приложение банка, но сбор статистики о вас вряд-ли отменит.
kot_martovskiy
01.11.2021 18:53+1В телефон залезли, в ноутбук залезли, теперь оказывается еще и в холодильник лезут. Этак придем-таки к подсчету количества используемого каждым налогоплательщиком бюджетного воздуха. Сначала просто для аналитики, а там и до налога на кислород недалеко.
edo1h
02.11.2021 05:10вы смешиваете государственные структуры и частные компании, у них разные возможности и разные интересы.
и пока непонятно кто хуже )
kot_martovskiy
02.11.2021 07:42То есть уверенности в том, что миром правят корпорации у вас не возникает?
edo1h
02.11.2021 09:35нет, не возникает. тот же цукерберг имел бледный вид в сенате, нет? как и трамп в попытках противостоять продемократическим корпорациям, впрочем.
если же про местные реалии, то имхо в рф государство сейчас гораздо сильнее.
Robottrener
01.11.2021 19:17+1Искажения чека В ОФД от "оригинала" бумажного не может быть. В ОФД поступает наоборот больше информации чем на бумажном чеке. Банк вообще должен получать обезличеные данные. А банки хотят персонализированную рекламу.
smirnovevgeny Автор
01.11.2021 19:23Действительно в ОФД должно поступать больше данных, чем в оригинале чека, но в соревновании эти данные не были доступны) Безусловно банки ищут выгоду и для себя. Банки могут сделать и сервисы для клиентов: автоматический возврат налога, детализированный пирог трат в мобильном приложении или даже поиск лучших предложений в ближайших магазинах.
genek96
02.11.2021 01:18Стало интересно, как банк сопоставляет данные из офд с банковскими транзакциями? На сколько мне известно, вся информация об оплате в офд содержит только суммы оплаты разными способами. Например 100р наличными и 500р картой. Номера транзакции там нет.
Как тогда происходит сопоставление?
smirnovevgeny Автор
02.11.2021 01:21" Для решения задачи команда использовала самообучающийся вероятностный алгоритм, который эффективно находит подходящие пары транзакция-чек." https://www.digitalleague.ru/project/sistema-matchinga-chekov-dlya-nacional-noj-sistemy-platezhnyh-kart
Новость по теме - https://mironline.ru/press-center/press-releases/18-12-2018-takskom-i-bank-tsentr-invest-podklyuchilis-k-servisu-nspk-po-privyazk/
vadimr
07.11.2021 18:09Получатель платежа, сумма и примерное время известны в обеих базах, в чём затруднение? Проблема может быть только с массовой продажей одинаковых товаров, вроде билетов в метро, но тогда и неважно точное соответствие.
edo1h
08.11.2021 07:26получатель платежа тоже примерный.
vadimr
08.11.2021 08:41Это он в выписке примерный, а сам банк точно знает, кому отправляет деньги. А в чеке ИНН.
edo1h
08.11.2021 22:55смотрите, вот типичная цепочка:
банк-эмитент (банк, выпустивший карту) → ПС (visa/mastercard/мир/…) → банк-эквайер (банк, чей терминал стоит на кассе) → мерчант (продавец).да, эквайер точно знает кому отправляет деньги, но в общем случае эквайер и эмитент — два разных
человекабанка.vadimr
08.11.2021 23:13Вы хотите сказать, что банку, в котором открыт карточный счёт, неизвестно назначение платежа с этого счёта??? А как же 115-ФЗ?
Я не знаю реализации этого дела, но мне кажется это невозможным по правовым соображениям. Не могут деньги уходить неустановленному лицу.
Dmitry17
02.11.2021 09:29+1Банки получают содержание кассовых чеков клиентов по транзакциям, совершенных по собственным картам через Операторов Фискальных Данных с согласия клиента.
@smirnovevgeny Евгений, это текст задачи или то, что сейчас происходит на самом деле?
Xo4y_3uMy
02.11.2021 12:01+1Так, например, строка "Молоко Домик.в деревне 3.2% 0.5л пл/б БЗМЖ/Россия" после предобработки превращалась в "молоко домик в деревне 1% 1л пл/б бзмж россия".
Не понял, почему 3.2% превратилось в 1%, а 0,5л в 1л. Странная предобработка. Я понимаю заглавные убрали, пробелы выправили и пр. Но цифры... не понял.
smirnovevgeny Автор
02.11.2021 15:19На категорию товара литраж и жирность никак не влияют, а сокращение алфавита положительно влияет на устойчивость к переобучению.
BigBeaver
Я, наверное глупенький, но можно уточнить, в чем конкретно заключалась задача?
EvgeniyIvanovhabr
На примере Тинькофф банка. У них есть "товарный кэшбэк". За покупки определенных товаров начисляется дополнительный кэшбэк (деньгами в конце отчётного периода на карту). Например, сейчас: Martini – 30%, Colgate – 20%, Coca-Cola – 15%, продукция Danone/Мираторг/Петелинка – 5% и т.п.
Часто встречаются "индивидуальные" предложения по таргентингу заказчика.
Чтобы корректно определить эти товары в чеках разных сетей и нужны подобные алгоритмы. Правда, по моему опыту, часто банк просто не получает данные о чеке. На этот случай в приложении Тинькофф есть возможность добавить его вручную, по QR-коду.
smirnovevgeny Автор
Нужно разработать модель машинного обучения, которая будет по входным данным, например, "Молоко Домик.в деревне 3.2% 0.5л пл/б БЗМЖ/Россия выбирать к какой из 90 заранее заданных категорий относится товарная позиция, например, "Молочные продукты". Предварительно до обучения алгоритма люди размечают набор примеров для каждой из категории. Модель обучается на основе размеченных примеров, а затем применяется на примерах, которые ранее не видела. Качество оценивают по специально отложенным размеченным примерам, на которых модель не обучалась.
SShtole