РАЗРАБОТКА РЕКОМЕНДАТЕЛЬНОЙ СИСТЕМЫ ФИЛЬМОВ НА ОСНОВЕ СРЕДСТВ КЛАСТЕРНОЙ ОБРАБОТКИ ДАННЫХ

DEVELOPMENT OF THE FILM RECOMMENDATION SYSTEM BASED ON CLUSTER DATA PROCESSING

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

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

Большинство интернет-продуктов, которые мы используем сегодня, работают на рекомендательных системах. Youtube, Netflix, Amazon, Pinterest, и длинный список других интернет-продуктов, все они полагаются на рекомендательные системы, чтобы фильтровать миллионы контента и давать персональные рекомендации своим пользователям. 

В основе создания проекта будет использоваться среда распределенной обработки данных ApacheSpark, главной особенностью которой являются кластерные вычисления в памяти, которые увеличивают скорость обработки приложения, а также библиотека SparkMLlib, которая предоставляет общие алгоритмы машинного обучения. SparkMLlib содержит библиотеку алгоритмов MLlib ALS, которая будет использована в разработке рекомендательной системы фильмов.

В качестве основной среды разработки будет использоваться программное обеспечение IntelliJ IDEA, Плагин Scala(язык программирования),Maven(в качестве системы сборки) и библиотеки ApacheSpark.

Разработка программной реализации состоит из следующих шагов:

  • Загрузить пример данных в формате DAT
  • Разобрать данные во входном формате для алгоритма ALS.
  • Разделить данные на две части: одну для построения модели и одну для тестирования модели.
  • Запустить алгоритм ALS, чтобы построить/обучить модель матрицы продукта пользователя.
  • Сделать прогнозы с данными обучения и наблюдать за результатами.
  • Протестировать модель с тестовыми данными.

Загрузим данные с сайта MovieLens, который содержат 1 000 209 анонимных оценок примерно 3900 фильмов  6040 пользователями MovieLens, которые присоединились к MovieLens в 2000 году.

 Все рейтинги содержатся в файле "ratings.dat" и находятся в следующем формате:

USERID :: MovieID :: Рейтинг :: Отметка, здесь:

  • USERID - Идентификаторы пользователей
  • Диапазон MovieID от 1 до 3952
  • Рейтинги составляются по 5-звездочной шкале
  • Временная метка представлена ​​в секундах
  • У каждого пользователя должно быть не менее 20 оценок

Присвоим ссылку на данные, указанные в качестве входных данных функции main, переменной  movieLensHomeDir:valmovieLensHomeDir = args(0)Инициализируем объект SparkSession для создания новой сессии для взаимодействия с базовой функциональностью Spark, которая  позволяет программировать Spark с помощью API DataFrame и Dataset.

valsparkSession = SparkSession

      .builder()

      .appName("spark-read-csv")

      .master("local[*]")

      .getOrCreate();

Cоздадим классы case для строк рейтингов и фильмов, которые используются для неизменяемых данных. Метод applycase классов case не требуют объявления экземпляра т.к. case-классы  делает это автоматически. Классы case являются val константами.case class Rating(userId: Int, movieId: Int, rating: Float, timestamp: Long)case class Movie(movieId: Int, movieName: String, rating: Float)

Создадим метод parseRating, который принимает строку и разделяет её, где имеется символ "::". Метод создает массив из этих разделенных элементов и возвращает объект Rating.

defparseRating(str: String): Rating = {valfields = str.split("::")   returnRating(fields(0).toInt, fields(1).toInt, fields(2).toFloat, fields(3).toLong)}

Загрузим пакеты, которые содержат неявные методы для преобразования общих объектов Scala в DataFrames: importsparkSession.implicits.

Загружаем личный рейтинг в переменную myRating в виде DataFrame. Для этого обращаемся к нашей сессии sparkSession.  Метод  read() используется для загрузки Dataset.  Метод TextFile загружает текстовый файл "personalRatings.txt" и возвращает Dataset строку. Метод Map() является методом класса RDD и является преобразователем т.е. один тип данных в другой. Метод map() в качестве входного параметра принимает функцию parseRating.

valmyRating: DataFrame = sparkSession.read.textFile(movieLensHomeDir + "personalRatings.txt") .map(parseRating).toDF()

Загружаем рейтинги пользователей в виде DataFrame :

val ratings = sparkSession
  .read.textFile(movieLensHomeDir + "ratings.dat")
  .map(parseRating)
  .toDF()Разбиваем данные на обучение (50%) и тестирование (50%).
Метод randomSplit() случайно разбивает набор данных:valArray(training, test) = ratingWithMyRats.randomSplit(Array(0.5, 0.5)

Инициализируем новый объект ALS() и поместим его в переменную als. С помощью метода setMaxIter() укажем максимальное количество итераций. Укажем параметр регуляризации равным 0.01 методом setRegParam(). Методом setUserCol() укажем наименование столбца с id пользователями. С помощью методаsetItemCol() укажем наименование столбца с id фильмами, с помощью метода setRatingCol() наименование столбца с id рейтингами:

valals = newALS()

.setMaxIter(3)

.setRegParam(0.01)

.setUserCol("userId")

.setItemCol("movieId")

.setRatingCol("rating").

Произведем обучение модели методом ALS.fit(), используя в качестве входных данные предназначенные  для обучения, которые находятся в переменной   training: valmodel = als.fit(training)

Рассчитаем прогнозы пользователей, используя тестовый набор данных, находящихся в переменной test. Метод transform() - это алгоритм, который преобразует один DataFrame в другой DataFrame. В нашем случае превращение DataFrame с  даннными в DataFrame с предсказаниями: valpredictions = model.transform(test)

Рассчитаем личные прогнозы используя свой рейтинг, который находится в myRating:

valmyPredictions = model.transform(myRating).na.drop

Преобразуем наши рекомендации в формат DataFrame  методом map().

valmyMovies = myPredictions.map(r => Movie(r.getInt(1), movies(r.getInt(1)), r.getFloat(2))).toDF
myMovies.show(100)

Произвёдем оценку модели по формуле  среднеквадратической ошибки. Инициализируем оценщик для регрессии  RegressionEvaluator и присвоим его переменной evaluator.  Методом etMetricName устанавливаем метрику типа rmse, которая соответствует формуле среднеквадратической ошибки.  Метрика rmseчасто используемая мера различий между значениями (выборка и значения совокупности), прогнозируемыми моделью или оценщиком, и реально наблюдаемыми значениями. Методом setLabelCol() устанавливаем столбец rating в качестве метки и методом setPredictionCol() устанавливаем столбец prediction в качестве прогнозов.

val evaluator = new RegressionEvaluator()
  .setMetricName("rmse")
  .setLabelCol("rating")
  .setPredictionCol("prediction")Получим результаты по формуле RMSE. Метод evaluate()  класса RegressionEvaluator измеряет, насколько хорошо подобранная модель справляется с данными по результатам испытаний.  В качестве входных параметров функция ожидает данные прогнозов.valrmse = evaluator.evaluate(predictions)Получим личные рекомендации исходя из таблицы личного рейтинга и выведем топ 5 рекомендаций имеющих наивысший предсказанный рейтинг(рис.2)valmyMovies = myPredictions.map(r =>Movie(r.getInt(1), movies(r.getInt(1)), r.getFloat(2))).toDF
 import org.apache.spark.sql.functions._
myMovies.orderBy(desc("rating")).show(5)

Рисунок 2. Топ 5 рекомендаций

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

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

Cписок литературы:

  1. А. Гомзин, А. Коршунов Системы рекомендаций: обзор современных подходов. Препринт. Москва: Труды Института системного программирования РАН. 2012. 20 С.
  2. P. Melville, V. Sindhwani Recommender systems. Encyclopedia of Machine Learning. 2010.
  3. Y. Koren Collaborative Filtering with Temporal Dynamics. KDD’09. 2009
  4. X. Su, T.M. Khoshgoftaar Survey of Collaborative Filtering Techniques. Advances in Artificial Intelligence. 2009.