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

Например, telegram-бот, в котором игроку предлагается выбирать из двух логотипов компаний тот, что ему больше нравятся. Из результатов сложить “народный” рейтинг логотипов и оценить меру оригинальности вкусов каждого игрока. Или даже та же логика, но сравнивать будем не логотипы, а книги.

А ещё это может быть базовая механика решения проблемы “холодного старта” рекомендательных систем. У тебя может быть очень крутая база данных, лучшие в мире алгоритмы, но до тех пор, пока ты не знаешь о новом пользователе ничего, твои рекомендации будут так себе. Обычно для решения задачи рекомендации хорошей книги или фильма пользователя просят рассказать что-то о себе. Например, через систему списков или чекбоксов указать какой-то набор “хороших” (или “плохих”) сущностей, от которых можно дальше как-то плясать. Кажется, предложенная выше игра будет веселее, чем просто выбор хорошего из списка: есть динамика, выбор более конкретный, можно указать больше сущностей.

Давайте посмотрим, что из этого может выйти?

Итак, простая игра в telegram. Почему там? Ну почему нет? Фронт как фронт, господин Дуров решил за меня большое количество проблем, можно там же просто закинуть ссылку знакомым и он точно откроется. И библиотеки, в которых реализованы все необходимые мне функции. Просто думай, садись и пиши.

Давайте подумаем, что бы нам хотелось максимизировать в такой игре, за что игрока нужно поощрить? Понятно, за активность: чем больше играешь, тем больше ценности ты приносишь. При этом хорошо, если активность конструктивная: это реально игра, выбор лучшего, а не просто тыканье кнопок. Если при этом игрок вносит разнообразие, вообще отлично. Если игрок считает, что Пеп Гвардиола - лучший тренер на свете, а Gillette - лучшие в мире бритвы, он, конечно, молодец, но назвать эти идеи свежими достаточно сложно. Как это технически реализовываем?

Первым делом напрашивается штраф за рандом. Я даже уже начал писать функцию, которая считает статистику нажатий первой и второй кнопки, но быстро понял, что это не то, что нужно. Если объекты выбираются случайным образом, статистика нажатий нормального человека будет близкой к 50 / 50. То есть мы накажем невиновных. Как лучше? Если человек выбирает тот или иной объект случайным образом, селектрейт (количество выборов объекта, делённое на число участий объекта в сравнениях) каждого объекта будет одинаковым (и, так как объекты мы сравниваем попарно, близок к 50%). Чем дальше наши действия от случайных, тем выше разброс значений селектрейта. Значит дисперсия этих значений и есть мера ранлдомности. Чем дисперсия ниже, тем больший штраф назначаем игроку.
Вот так например, различается разнообразие селекрейтов у лидера и антилидера по данному показателю. Что такое "ящик с усами" можно прочитать, например, здесь.
Вроде работает так, как я хотел.

Основной метрикой, конечно, должна быть мера оригинальности. Тут помогает опыт настольных игр, там такую метрику придумали достаточно давно. Например, в таких играх как Ellias или Dixit. Ты не оригинален, когда
  • все делают так, как предлагаешь ты (логично)
  • никто не делает так, как предлагаешь ты (иначе можно творить всякую жесть)
Как это оцифровать? Да это просто разница между селектрейтом игрока и селектрейтом “по больнице”. Окрестности 0% и 100% в этой разнице принудительно зануляем и вуаля.

Такая мера оригинальности решает ещё одну проблему: проблему очень трудолюбивого игрока. Представьте себе, что большинство участников поиграло полчаса и ушло из игры. А какой-то очень трудолюбивый человек сыграл, допустим, в 100 раз больше среднего. Скорее всего, он будет на первом месте. Но, может и нет. Почему? Потому что его мера оригинальности будет низкой: разницы между его ответами и всеми ответами будет крайне низкой! В какой-то момент такому игроку будет математически невыгодно дальше играть. Если к этому моменту он не занимает первого места, то лучшая стратегия для него будет приглашение новых игроков!

На момент написания статьи этот показатель для самого оригинального и неоригинального игроки выглядят так:
Ну а дальше всё - дело техники. Рейтинг конкретного игрока - это сумма двух факторов, взвешенная на количество игр. А рейтинг самих сущностей - это обычный рейтинг Эло.

Что в итоге получается?
Я постараюсь учесть хабрэффект и обновлять данные в этой статье, но могу не успевать. Самое оперативное - в самих ботах, и у меня в телеграме. А ещё я там про игры и книжки рассказываю.
На момент написания статьи "народный рейтинг" логотипов выглядит так:

Самое время начинать шутить о том, какая именно компания "заказала" это исследование или своё место в рейтинге.
Кластеры логотипов (чем темнее, тем больше они похожи друг на друга):
картинка
Лучший друзья по близости логотипов
таблица
Да, пришло время раскрыть карты. Эта игра не для того, чтобы улучшить рекомендации кинопоиска. Я хочу продать её в тиндер.
С логотипами как-то получилось. Но у них есть важное преимущество: для того, чтобы оценить логотип, достаточно просто на него посмотреть.
Если мы захотим сделать аналогичную игру по книгам или фильмам, мы напираемся на новую проблему: люди могу не читать определённые книги или не смотреть определённые фильмы. Искать “точки соприкосновения” между игроками значительно сложнее. Что делать с этим? Я придумал две вещи.
Первая, очевидная. Это кнопка “Пропустить”. Если игрок встречается с чем-то для себя незнакомым, нажимает кнопку и нет проблем.
Топ книг, которых пропускали чаще всего
таблица
намекает на то, что это правильная логика.
В идеале это ещё и должно влиять на рандом: объекты, которые данный игрок уже пропускал, должны показываться ему реже, чем обычно.
Вторая вещь - это категории. Если взять в среднем по популяции, то вероятность найти человека, который читал Честертона крайне мала. Если мы берём тех людей, которые хотят оценить книги в категории “Детективы”, то эта вероятность сильно выше.
Кстати, на реальных данных доля пропусков Честертона - около 40%.
Аналогичные лидерборды:
Топ-10 лучший логотипов
таблица
Топ-10 лучших игроков
таблица
Кластеры логотипов (чем темнее, тем больше они похожи друг на друга)
картинка
Лучший друзья по близости логотипов
таблица

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

Дальше расскажу чуть-чуть про технические подробности.
Обе игры есть на гитхабе.
  • логотипы
  • книги

Первым я сделал книги. Использовал классический telebot. С логотипами перешёл на aiogram и почувствовал себя человеком. Telebot может просто перестать отвечать без какого-либо предупреждения. Грешил на сервер, но нет, библиотека такая.

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

В самом коде ничего особенного. Подружить telebot в Postgres оказалось удивительно легко.
Вся логика в функциях или внутри SQL-запросов, логика текстовых команд - самая что ни на есть типичная для ботов. Хорошо, что нет книг “Продолжить” и “Пропустить”.
Считал, что безликие id никому неинтересны и хотел выводить таблицу с никами игроков. Словил шикарный баг на проде, когда узнал, что далеко не у всех в телеграме есть текстовые ники.
Визуализации таблиц заставляют меня страдать. К сожалению, сделать лучше для таблиц произвольного размера и содержания без установки браузера на виртуальной машине (с последующим рендерингом html) у меня не получилось.

Какие я вижу тут следующие шаги?
  • рекомендации по числу боёв, через какое количество сравнений что-то произойдёт
  • кнопка “Пропустить” должна влиять на дальнейший рандом
  • ранги или категории игроков, достижения, какие-то плюшки, например, в идеале лучшие получают право добавлять свои айтемы в игру
  • сюжет какой-нибудь
  • сочетание разных типов сравнений между собой
(c) 2022. Kotelok, Roman Tsaregorodtsev