В прошедшие выходные (14-15 июля) в mail.ru прошел очередной хакатон SmartMailHack. Нам предложили "придумать фичу, которая позволит получить доступ к данным из Почты и более эффективно взаимодействовать с ними".


Описание данных, идеи и решения


Мы получили тестовый ящик с более чем 1500 сообщениями, а также полный доступ к нему через API. Организаторы предоставили большой, развернутый мануал по его использованию (книжка на 547 страниц). С помощью токена и простых JSON-запросов, мы могли получать всю необходимую информацию о почте: письма, имена отправителей, различные характеристики.


Обсудив, что у каждого из нас в почте порядка нескольких тысяч непрочитанных писем из рассылок, мы решили разобраться с этой проблемой. В нашем случае релевантность письма перестала определяться временем его появления в почтовом ящике. И если исходить из того, что будут открыты далеко не все письма — тогда лучше всего показать пользователю только те из них, которые он, вероятно, откроет. А всё остальное можно убрать куда подальше. Так что мы решили сделать сортировку для почты. Сортировать письма предполагалось по категориям, а категории размещать внутри плиток (привет, Trello). Верхний ряд плиток объединял по смыслу письма от разных отправителей. Здесь могут быть "Поездки", "Регистрации", "Переписка с Васей", "События", "Финансы" и так далее, всего около 10 категорий. Вторым рядом шли плитки с самыми крутыми предложениями от компаний. Мы искали самые релевантные промокоды, самые скидочные акции, самые ценные предложения — и показывали их здесь, сгруппированными по компаниям. А дальше шли все остальные письма, распределенные по компаниям-отправителям, а эти отправители, в свою очередь, были раскиданы по категориям ("Еда", "Косметика", "Электроника" и многие другие). Причем категории тоже ранжировались по релевантности писем, и только письма, преодолевшие определенный порог релевантности, показывались внутри. Подкрепив идею словами "Найти нужное и избавиться от лишнего", мы полезли в ML.


Машинное обучение


Мы решили построить три модели:


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


Признаки


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


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


  • tf-idf на коллекции документов
  • эмбеддинги полученные с Word2Vec
  • поведенческие признаки, такие как:
    — количество прочитанных сообщений за последние окна (1, 2, 5 недель назад)
    — число сообщений от данной

Задача классификации


Мы разметили руками 1000 писем для обучения. Оказалось, это не такая медленная и нудная работа как может показаться сперва. Если использовать адреса и заголовки, можно заметно ускорить работу. Например, Lamoda почти всегда присылает письма в категорию "Одежда".


Далее мы обучаем LightGBM на всем множестве признаков и получаем качество 0.913 accuracy и 0.892 f1 меры, что мы определили очень неплохим на уровне бейзлайнов. Это показывает что письма можно классифицировать очень неплохо.


Задача ранжирования


В качестве целевой переменной мы использовали бинарный флаг 0/1 — было ли прочитано письмо пользователем. Далее ранжировали по вероятности предсказываемой моделью, поскольку именно она отражает то, насколько модель уверена в том прочитает человек сообщение или нет.


Здесь мы так же обучили LightGBM на всем множестве признаков и получили качество в районе 0.816 auc-roc.


Кластеризация и выделение новых категорий


Помимо основных категорий у нас есть категория "Другое". Из нее можно выделять новые темы.
Мы обучили стандартный DBSCAN на письмах из этой группы, а дальше выбрали те кластеры в которых было много сообщений (трешолд можно оптимизировать, но он был зафиксирован случайно). На коллекции документов кластера можно натравить, например, тематическое моделирование и получить наиболее релевантную тему для данного кластера и выделить его в отдельную группу. Отвалидировать этот алгоритм времени не хватило.


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





Оставшиеся идеи


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

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