Небольшой эксперимент для проверки нашего понимания механизмов рекомендаций с использованием научного метода

В этом посте представлен подход к внедрению вашей первой системы рекомендаций и быстрой проверке ее производительности. В нем рассматривается вариант использования, предназначенный для визуальной проверки того, чему модель научилась во время обучения и как она работала во время тестирования. Вариант использования был реализован на Python с pandas и scikit-surprise. Надеюсь, эта статья окажется для вас полезной, если вы сами начинаете работу с системами рекомендаций!

Преамбула

Цель и подход

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

  1. Создайте предсказуемый вариант использования рекомендаций: спроектируйте наборы данных для обучения / тестирования так, чтобы они содержали группы пользователей с одинаковым вкусом.
  2. Обучите механизм рекомендаций.
  3. Протестируйте и убедитесь визуально, что двигатель реагирует в соответствии с ожиданиями, установленными на шаге № 1.

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

Гипотеза проверена

Механизм рекомендаций - это часть искусственного интеллекта. который принимает комбинацию [user_id, product_id] в качестве входа и выводит rating (число). Другими словами: он предсказывает, как конкретному пользователю понравится конкретный продукт. Учитывая эту основную истину, я хотел проверить свое понимание (мою «гипотезу») о том, что механизмы рекомендаций работают следующим образом:

  1. Определите группы пользователей с одинаковым вкусом (т. Е. Которые оценили одни и те же продукты одинаково) во время обучения.
  2. Оцените, как пользователь из «группы того же вкуса» оценил бы продукт, уже оцененный другими пользователями «группы того же вкуса» во время прогнозирования.

Вот пример: скажем, у нас есть 10 пользователей и 2 продукта (P1 и P2). Пользователи с 1 по 5 оценили P1 одинаково, у них одинаковые вкусы, поэтому они принадлежат к одной «группе одинаковых вкусов». Пользователи с 1 по 4 также оценили P2, поэтому разумно использовать эти оценки, чтобы предсказать, как пользователь 5 будет оценивать P2. Используя эту логику, мы можем представить, что пользователи с 6 по 10 могут сформировать другую «группу с одинаковым вкусом» на основе своих оценок P1 и P2 или другого набора продуктов.

Давайте проверим это!

Данные обучения

Разделение на отдельные группы пользователей и введение четких шаблонов «нравится / не нравится» среди этих групп - краеугольный камень варианта использования. Данные, использованные в этой статье, были тщательно созданы с учетом следующих требований:

  • 1000 разные product_id
  • 100 разные user_id
  • Каждый пользователь случайным образом выбирает 100 различных product_id и оценивает их от 0.0 до 10.0 (не обращайте внимания на десятичную шкалу: это теоретический вариант использования, который упрощает визуализацию)

Пользователи сгруппированы в «группы одного вкуса» следующим образом:

  • Первая треть пользователей (категория A, user_id между[1, 33]): рейтинг product_id между [1, 500] высоким ([5.0, 10.0]) и product_id между [501, 1000] низким ([0.0, 5.0]). Это могут быть люди с кошками и product_id между [1, 500] товары для кошек.
  • Вторая треть пользователей (категория B, user_id между[34, 66]): рейтинг product_id между [1, 500] низким ([0.0, 5.0]) и product_id между [501, 1000] высоким ([5.0, 10.0]). Это могут быть люди с собаками и product_id между [501, 1000] товары для собак.
  • Третья треть пользователей (категория C, user_id между[67, 100]): случайным образом оценивают все продукты между [0.0, 10.0] (равномерно распределены). Нет корреляции между product_id и rating (случайный вкус - контрольная группа).

В таблице ниже представлено визуальное представление набора данных, используемого для обучения модели рекомендаций (повернутая [user_id, product_id, rating]). Таблица довольно большая, поэтому показанные строки / столбцы усечены: самый высокий показанный product_id равен 993 (но он достигает 1000), а самый высокий показанный user_id равен 76 (но он достигает 100). NaN означает N или A N, они обозначают продукты, которые не были оценены пользователем.

[product_id, rating] комбинаций для категорий пользователей A и B образуют узнаваемые и противоположные шаблоны «в клетку». Это неверно для категории пользователей C, где нет шаблона (то есть по дизайну). Эти шаблоны являются ключевыми при разработке нашего варианта использования, они упрощают визуальную проверку производительности модели рекомендаций.

Реализация: обучение модели рекомендаций с помощью scikit-Surprise

Мы решили использовать scikit-surprise для реализации механизма рекомендаций по двум причинам: эта библиотека ориентирована исключительно на механизмы рекомендаций и хорошо документирована.

Данные нашего варианта использования были сохранены во фрейме данных pandas (str_ratings_df), первые 5 строк этого фрейма данных показаны ниже. Все это будет использоваться для обучения модели рекомендаций (более подробное объяснение отсутствия очевидного тестового набора данных будет позже).

Код scikit-surprise для обучения модели с использованием обучающего набора:

from surprise import Reader, Dataset, SVD
# Put the training data in the right format
reader = Reader(rating_scale = (0.0, 10.0))
data = Dataset.load_from_df(str_ratings_df, reader)
trainset = data.build_full_trainset()
# Singular Values Decomposition algorithm
# gives good results according to the 
# scientific / engineering community
model = SVD(n_epochs = 20, n_factors = 50, verbose = True)
model.fit(trainset)

Вуаля! Наш объект model обучен, и теперь мы можем попросить его прогнозировать оценки пользователей!

Оценка эффективности

Задавать правильные вопросы

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

  1. Выучил шаблоны «проверки» для каждой категории пользователей.
  2. Делает разумные рейтинговые прогнозы при представлении комбинаций [user_id, product_id], невидимых во время обучения.

Это делается в 3 этапа:

  1. Найдите все [user_id, product_id] комбинации, в которых product_id не был оценен user_id, но был оценен другими пользователями в группе user_id.
  2. Для каждой допустимой [user_id, product_id] комбинации используйте модель рекомендаций, чтобы получить predicted_rating.
  3. Постройте [product_id, predicted_rating] комбинации для каждой категории пользователей (A, B, C), убедитесь, что схема обучения действительно изучена и используется для прогнозирования оценок.

Чтобы сделать прогноз с помощью модели scikit-surpise:

predicted_rating = model.predict(str(user_id), str(product_id))

Примечание: логически модель не должна предсказывать рейтинги для всех возможных [user_id, product_id] комбинаций. В частности: модель не должна предсказывать рейтинги для следующих случаев:

  • Неизвестно user_id или product_id: значение, не включенное в данные обучения: модель не знает, что нравится этому пользователю или кому нравится этот продукт.
  • Неизвестная [user_id, product_id] связь: данные обучения не включали оценку для этого product_id от одного из пользователей этой user_id группы.

Полученные результаты

Фрейм данных ниже - это небольшая выдержка из наших прогнозов. Обратите внимание на флаг was_impossible: я подозреваю, что он будет установлен на TRUE, если мы зададим один из этих «невозможных вопросов», как описано выше. Все наши флаги были FALSE, поскольку мы тщательно отбирали «возможные» вопросы во время эксперимента.

Наконец, как и было обещано, наша визуальная проверка: вот визуальные представления [product_id, predicted_ratings] сопоставлений. Совершенно очевидно, что модель выучила противоположные шаблоны «проверки» из обучающих данных для категорий A и B, в то время как она не нашла шаблон для категории пользователей C. Визуально наши ожидания оправдались.

Мы также можем посмотреть средние значения фактического и прогнозируемого рейтинга для каждого продукта и для каждой категории пользователей. Наличие четкой линейной зависимости между avg_rating avg_predicted_rating (с наклоном, близким к 1) для категорий A и B показывает, что модель усвоила связь между user_id и rating. Для группы пользователей C не было модели рейтинга, которую нужно было изучить (поскольку эта группа была разработана с учетом непредсказуемого вкуса). Для этой группы пользователей почти нет связи между avg_rating и avg_predicted_rating.

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

Что я буду делать дальше?

Первый

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

Второй

Я хотел бы найти лучший способ решить этот простой вариант использования. Как упоминалось ранее, все, что мы делали, - это визуально проверяли, «что все имеет смысл». Требуются дополнительные усилия, чтобы перейти отсюда к ситуации, когда у нас есть «хорошая модель». Для этой новой цели наличие числовой метрики производительности становится обязательным условием для поиска кандидатов на улучшение и эффективного прогресса. Возможный подход к получению базовой метрики (которая должна быть минимизирована) заключается в следующем:

  1. Разделите необработанные данные между наборами данных для обучения и тестирования.
  2. Тренируйтесь на тренировочном наборе - Дух: D.
  3. Прогнозируйте рейтинги, используя [user_id, product_id] комбинаций из набора данных тестирования.
  4. Вычислите среднее или сумму абсолютных значений нормализованных ошибок (A NE или SNE) между прогнозируемыми и фактическими оценками. Под нормализованным мы понимаем деление на потенциальную максимальную ошибку при определенном значении рейтинга. Примеры: a) для фактического рейтинга 0.0 или 10 максимальное абсолютное значение ошибки прогнозирования равно 10 - нормализовать ошибку, используя коэффициент 1/10. б) для фактического рейтинга 5 максимальное абсолютное значение ошибки прогнозирования составляет 5 - нормализовать ошибку, используя коэффициент 1/5. Это необходимо для того, чтобы ошибки на краях учитывались так же, как и в центре диапазона прогнозирования.

Затем ANE или SNE можно минимизировать, чтобы найти оптимальный набор гиперпараметров для модели рекомендаций и / или выбрать лучший алгоритм (в этом посте мы оценивали только SVD, есть и другие варианты). Примечание: ошибки нормализации - это значение со знаком, поэтому я бы также рекомендовал следить за стандартным отклонением нормализованных ошибок или их плотностью во время процесса оптимизации. (Является ли меньшее количество ошибок в среднем, но большее распространение - реальным улучшением)?