"Начиная"

Совместная фильтрация в Pyspark

Введение в совместную фильтрацию и реализацию в Pyspark с использованием алгоритма альтернативных наименьших квадратов (ALS)

Вы когда-нибудь задумывались, как Spotify может размещать список песен каждую неделю в «Discover Weekly», и в итоге вы добавили некоторые из этих песен в свои плейлисты, потому что они вам нравятся? А как насчет тех шоу, которые вам рекомендовал Netflix, потому что вчера вы смотрели конкретное шоу? Почему эти технологические гиганты такие умные? Ответ - система рекомендаций.

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

Что такое совместная фильтрация?

Совместная фильтрация - это математический метод, позволяющий прогнозировать, как пользователи могут оценивать определенный элемент на основе оценок других похожих пользователей. Типичная совместная фильтрация включает 4 разных этапа:

  1. Сбор данных - сбор данных о поведении пользователей и связанных с ними элементах данных.
  2. Обработка данных - Обработка собранных данных
  3. Расчет рекомендаций - расчет переходов на основе обработанных данных
  4. Вывод результатов - извлеките сходство и верните первые N результатов

Явные и неявные отзывы

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

Примером явной обратной связи являются рейтинги, выставленные пользователями, которые Netflix собирает, чтобы давать рекомендации своим клиентам после того, как они оценивают просмотренные фильмы. Неявная обратная связь менее прямолинейна, поскольку основана на взаимодействии пользователей с платформой, начиная от кликов, просмотров, лайков и покупок. Spotify использует неявные отзывы для внедрения своей системы рекомендаций.

Расчет сходства

После того, как данные собраны и обработаны, необходима математическая формула для вычисления подобия. Двумя наиболее распространенными мерами являются:

  1. Евклидово расстояние - предпочтительное расстояние между двумя пользователями. Если расстояние небольшое, сходство между обоими пользователями высокое.
  2. Корреляция Пирсона - если значения косинуса (угла падения) между двумя пользователями совпадают, сходство между обоими пользователями высокое.

Реализация в Pyspark

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

Мы будем использовать набор данных с https://www.last.fm/api/, который содержит 3 файла:

  • user_artist_data.txt 3 столбца: идентификатор пользователя artistid playcount
  • artist_data.txt 2 столбца: artistid artist_name
  • artist_alias.txt 2 столбца: badid, goodid [известные исполнители с неверным написанием и правильный идентификатор исполнителя]

Во-первых, мы настроили Spark следующим образом.

# import libraries
from pyspark import SparkContext
from pyspark.ml.recommendation import ALS
from pyspark.sql import SparkSession ,Row
appName="Collaborative Filtering with PySpark"
# initialize the spark session
spark = SparkSession.builder.appName(appName).getOrCreate()
# get sparkcontext from the sparksession
sc = spark.sparkContext

Затем мы определяем структуры данных и преобразуем устойчивый распределенный фрейм данных (RDD) в фреймы данных.

from pyspark.sql.types import StructType,StructField,IntegerType,StringType,LongType
from pyspark.sql.functions import col
#Define the schema for the datasets
schema_artist = StructType([StructField("artistId",StringType(),True),StructField("artistName",StringType(),True)])
schema_user_artist = StructType([StructField("userId",StringType(),True),StructField("artistId",StringType(),True),StructField("playCount",StringType(),True)])
schema_alias = StructType([StructField("badId",StringType(),True),StructField("goodId",StringType(),True)])
#Convert RDDs into Dataframes
artistRDD = rawArtistData.map(lambda k: k.split("\t"))artist_df = spark.createDataFrame(artistRDD,schema_artist,['artistId','artistName'])
userArtistRDD = rawUserArtistData.map(lambda k: k.split())user_artist_df = spark.createDataFrame(userArtistRDD,['userId','artistId','playCount'])
aliasRDD = rawArtistAlias.map(lambda k: k.split())alias_df = spark.createDataFrame(aliasRDD,['badId', 'goodId'])
#First for convenience, we can create aliases for each dataframes
ua = user_artist_df.alias('ua')
ub = artist_df.alias('ub')

После обработки наборов данных мы можем продолжить обучение нашей модели ALS. Перед этим мы должны разделить наш набор данных на данные для обучения и тестирования, чтобы мы знали, насколько хорошо работает наша модель.

# dataset split into training and testing set
(training, test) = ua.randomSplit([0.8, 0.2])
# training the model
als = ALS(maxIter=5, implicitPrefs=True,userCol="userId", itemCol="artistId", ratingCol="playCount",coldStartStrategy="drop")
model = als.fit(training)
# predict using the testing datatset
predictions = model.transform(test)
predictions.show()

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

Функция ниже принимает в качестве входных данных userId и limit. Для заданного userId он получает список текущих наиболее популярных исполнителей (на основе playcount). Попробуем отобразить для пользователя наиболее понравившихся исполнителей (2062243).

def currentLikes(ua,ub,userId,limit):
 df = ua.join(ub,ua.artistId==ub.artistId)\
 .filter(ua.userId==userId)\
 .sort(ua.playCount.desc())\
 .select(ua.userId,ua.playCount,ub.artistName)\
 .limit(limit)
 return df
# display top 10 liked artists for user 2062243
currentLikes(ua,ub,2062243,10).show(truncate=False)

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

def recommendedArtists(userId,limit):
 test =  model.recommendForAllUsers(limit).filter(col('userId')==userId).select("recommendations").collect()
 topArtists = []
 for item in test[0][0]:
  topArtists.append(item.artistId)
 
schema = StructType([StructField("artistId",IntegerType(),True)])
artists = spark.createDataFrame(topArtists,IntegerType())
final=artists.join(ub,artists.value==ub.artistId).select(ub.artistId,ub.artistName)
return final
# display top 10 recommended artists for user 2062243
recommendedArtists(2062243,10).show(truncate=False)

Резюме

В этой статье мы рассказали, что такое Collaborative Filtering и что это 4 различных этапа. Две категории данных, собираемых для совместной фильтрации, в основном неявная и явная обратная связь, и вычисление сходства с использованием евклидова расстояния или коэффициента Пирсона . Наконец, в Pyspark было представлено краткое пошаговое руководство по реализации совместной фильтрации с использованием встроенного в Spark алгоритма альтернативного метода наименьших квадратов (ALS). Надеюсь, вы, ребята, имеете краткое представление о том, как работает Система рекомендаций, и не удивитесь, увидев хорошие рекомендации для вас в следующий раз, когда вы будете просматривать Интернет и использовать Spotify / Amazon, ура!