МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ Федеральное государственное бюджетное образовательное учреждение

advertisement
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
Федеральное государственное бюджетное образовательное учреждение
высшего профессионального образования
‹‹КУБАНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ››
(ФГБОУ ВПО ‹‹КубГУ››)
Кафедра вычислительных технологий
РАСПРЕДЕЛЕННАЯ РЕКОМЕНДАТЕЛЬНАЯ СИСТЕМА
И.И.Житков
Краснодар 2014
СОДЕРЖАНИЕ
Введение. ...................................................................................................................... 3
1. Проблема рекомендательных систем. ................................................................... 5
2. Постановка задачич................................................................................................. 8
2.1 Подготовка рабочего места и настройка сервера PredictionIO…….......8
3. Построения списка рекомендаций алгоритмом коллаборативной
фильтрации…………………………………………………………………….……14
3.1 Подготовка данных для обработки……………………….…...…….….14
3.2 Алгоритм рекомендательной системы коллаборативной
фильтрации…………………………………………………………………..15
Заключение. ............................................................................................................... 20
Список используемых источников. ......................................................................... 21
Приложение А. Подготовка данных для обработки .............................................. 22
Приложение Б. Вспомогательные функции для алгоритма рекомендации
коллаборативной фильтрации .................................................................................. 30
2
ВВЕДЕНИЕ
В настоящее время объем информации, доступной человеку стал настолько велик,
что даже используемые сервисы для поиска информации не всегда справляются с
задачами людей. Для осуществления поиска объектов необходимо знать об их
существовании. С ростом объема доступной информации знать обо всем становится
затруднительно. Данную задачу решают рекомендательные системы, которые связывают
между собой объекты и пользователей и ищут для пользователей объекты, вероятно, их
интересующие. Среди них можно выделить 2 наиболее успешных класса:
алгоритмы коллаборативной фильтрации и алгоритмы, основанные на анализе данных о
поведении пользователя (data mining, machine learning, etc).
Алгоритмы коллаборативной фильтрации обладают рядом проблем, наиболее
существенными из которых являются проблема холодного старта, первого рейтинга,
избирательности внимания и долгого времени работы при пересчете данных. Алгоритмы,
основанные на анализе данных о поведении, всегда привязаны к специфике области, к
которой они применяются.
Большинство крупных веб-сайтов рекомендует своим пользователям
различные предложения, например, товары для дальнейшего изучения или
людей, к которым целесообразно обратиться. Рекомендательные механизмы
сортируют огромные объемы данных (целесообразно говорить о «Больших
данных») для выявления потенциальных предпочтений пользователей.
Amazon.com утверждает, что 40% продаж генерируются через механизмы
рекомендаций.
Рекомендательные системы изменили способы взаимодействия веб-сайтов
со своими пользователями. Вместо предоставления статической информации,
когда пользователи ищут и, возможно, покупают продукты, рекомендательные
системы
увеличивают
степень
интерактивности
для
расширения
предоставляемых пользователю возможностей.
3
Рекомендательные системы формируют рекомендации независимо для
каждого конкретного пользователя на основе его прошлых действий, а также на
основе поведения других пользователей.
Цель курсовой работы – освоение принципов обработки данных на
примере сервиса рекомендаций кинофильмов методами коллаборативной
фильтрации.
Прототип рекомендательной системы по разработанному методу для фильмов
протестировать на основе открытых данных MovieLens исследовательской группы
GroupLens.
В ходе выполнения курсовой работы был задействован следующий
инструментарий:
Язык реализации – Python
Версия языка в среде Linux – 2.7
Среда разработки – Canopy
Операционные системы – Ubuntu 13.04
Hadoop 1.2.1 – проект фонда Apache Software Foundation, свободно
распространяемый набор утилит, библиотек и программный каркас для
разработки и выполнения распределённых программ.
PredictionIO Server v0.7.1 – сервер машинного обучения с открытым
исходным
кодом
,
созданный
для
облегчения
разработки
сервисов
персонализации, рекомендации, классификации и т.д.
4
1. Проблема рекомендательных систем.
Рекомендательная система — это программа, которая на основе данных о
пользователе(User), предмете(Item) и оценке предмета для конкретного
пользователя(Rate) дает рекомендации.
Такая система включает в себя весь процесс — от получения информации
до её представления пользователю.
Важен каждый этап. От информации,
которая будет обрабатываться, зависит, какие алгоритмы окажутся более
подходящими. Хорошие алгоритмы дают хорошие, полезные рекомендации.
Критерии оценки результата позволяют выбрать наиболее подходящие
алгоритмы.
Первоначально задача кажется простой, но создать хорошую
систему сложно. Нужно очень бережно подходить к построению системы. Даже
лучшие алгоритмы не всегда дают подходящие результаты.
Типы рекомендательных систем
Существует четыре основных типа рекомендательных систем:
1. Основанные на контенте
2. Коллаборативные
3. Основанные на знаниях
4. Гибридные
Рекомендательные системы, основанные на контенте
Основные шаги в данной системе: проанализировать контент предметов и
составить набор его критериев(жанры, тэги, слова), узнать какие критерии
нравится пользователю, сопоставить эти данные и получить рекомендации.
Критерии объединяют пользователей и предметы в единой системе координат, и
если точка пользователя и предмета рядом, то вероятно предмет понравится
пользователю.
Коллаборативные рекомендательные системы
Это системы, в которых рекомендации пользователю рассчитывается на
5
основе оценок других пользователей. Здесь существует множество алгоритмов,
но
наиболее
популярные
—
User/User(поиск
соседей
по
оценкам),
Item/Item(определение схожести предметов по оценкам пользователей) и
SVD(самообучающийся алгоритм).
Суть этих алгоритмов — нахождение ближайших соседей. Близость двух
пользователей или предметов определяется метриками схожести.
Рекомендательная система, основанная на знаниях
В основном это системы, в которых для получения рекомендаций
используются полученные знания. Пользователи указывают предмету другие
схожие предметы. На основе этих данных создаются рекомендации. Многие
понравившиеся рекомендации этой системы, не смогли найти коллаборативные
алгоритмы. Рекомендательная система, основанная на знаниях, сможет
расширить географию выбора пользователя за счет рекомендаций, которые
оставили предыдущие пользователи.
Гибридные рекомендательные системы
Эти системы объединяют несколько выше представленных алгоритмов в
один. Использование гибридного метода сильно усложнит систему, зато немного
повысит
точность.
Большинство
из
них
используют
рекомендационный подход, совмещающий контентные и
гибридный
коллаборативные
алгоритмы.
Негативный эффект использования рекомендательных систем – «пузырь
фильтров». Веб-сайты используют алгоритмы выборочного угадывания и
рекомендательные алгоритмы, которые определяют, какую информацию
пользователь
хотел
бы
увидеть,
основываясь
на
информации
о
его
месторасположении, прошлых нажатиях и перемещениях мыши и его истории
поиска. В результате веб-сайты показывают только информацию, которая
согласуется с прошлыми точками зрения данного пользователя. Иная
6
информация пользователю не выводится. Яркими примерами являются Google с
персонализированными
результатами
поиска,
а
также
Facebook
с
персонализированной лентой новостей. Соответственно, пользователи получают
намного меньше противоречащей своей точке зрения информации и становятся
интеллектуально изолированными в своём собственном информационном
пузыре.
7
2 Постановка задачи
На основе открытых данных MovieLens исследовательской группы GroupLens
составить список рекомендаций кинофильмов для конкретного пользователя.
Используя программный каркас для разработки и выполнения распределённых
программ, работающих на кластерах Hadoop и сервер машинного обучения
PredictionIO, созданный для облегчения разработки сервисов персонализации,
рекомендации, классификации и т.д.
Подготовить исследовательские данные для обработки;
Написать функции обработки и отправки данных на сервер;
Передать готовые данные серверу обработки PredictionIO;
Если предполагается распределенная обработка, указать это в настройках
PredictionIO;
Написать и подготовить алгоритм, который анализирует данные и выдает
рекомендации пользователю;
Запустить полученную рекомендательную систему и вывести результат.
2.1 Подготовка рабочего места и настройка сервера PredictionIO
Выполнение проекта происходило на ПК Pentium® Dual-Core CPU T4400
(2.20 GHz), ОС Ubuntu 13.04 на языке Python.
Перед тем, как приступить к установке и настройке PredictionIO,
необходимо
выполнить
два
действия,
необходимых
для
правильного
функционирования системы:
1) Проект PredictionIO реализован на языке Java, поэтому для его работы
должна
быть
установленная
среда
JDK,
которая
организует
мультиплатформенность единожды написанной программы.
2) Фреймворк разработан для распределенной работы и требует наличия
доступа для подключения к сетевому протоколу прикладного уровня SSH,
8
который осуществляет удаленное управление и обмен данными с другими
узлами кластера.
Установка начинается с получения копии исходного кода системы с
официального сайта.
Следующим этапом подготовки является настройка сервера PredictionIO
на конкретном ПК (машине) и прописывание адресов, ведущих к необходимым
ресурсам.
Хранение и обработка данных на сервере осуществляется средствами
документо-ориентированной системы управления базами данных (СУБД) с
открытым исходным кодом MongoDB, все операции с которой происходят
независимо от разработчика на стороне сервера PredictionIO.
PredictionIO представляет собой сервер, который получает данные и
строит рекомендации на их основе, предоставляя программисту удобный доступ
к нему средствами API. Работу PredictionIO можно представить как 3 блока:
Приложение(App), Инструмент(Engine) и Алгоритм (Algorithm).
Приложение - база данных. Информация, которая будет обработана, и на
основе которой будут выдаваться рекомендации. Данные являются общими в
пределах одного проекта.
Инструмент - функциональная часть проекта. Для каждого действия в
пределах одного Приложения может быть несколько рабочих инструментов.
Например, один инструмент отвечает за новости для пользователей, а второй за
предложение новых друзей для пользователей. Каждый инструмент должен
иметь собственный алгоритм обработки.
Алгоритм - в PredictionIO имеются встроенные алгоритмы анализа данных
и доступно добавление собственных. Для оптимизации работы сервера на
конкретных входных данных и избежания выдачи неверных рекомендательных
оценок.
9
Рисунок 1 – модель обработки данных
Для запуска сервера PredictionIO нужно запусить MongoDB командой
service mongodb start
После чего, Для активизации всех компонент PredictionIO, нужно выполнить
команду
bin/start-all.sh
10
Рисунок 2 – запуск сервера
Чтобы убедиться, что система готова к выполнению задач, выполняется переход
по локальному адресу
http://localhost:9000/
, который отобразит веб-интерфейс
приложения и предоставит инструменты для дальнейшей работы.
11
Рисунок 3 – вход в панель управления
При первом запуске нужно добавить пользователя, который будет иметь доступ
к административной части приложения.
bin/users
12
Рисунок 4 – добавление пользователя
После выполнения команд, система будет готова к работе.
Рисунок 5 – добавление приложения
13
3
Построения
списка рекомендаций
алгоритмом коллаборативной
фильтрации.
3.1 Подготовка данных для обработки
Каждое приложение имеет свой ключ, по которому будет происходить
авторизация и дальнейшая работа.
Для импорта данных в PredictionIO в файле batch_import.py описаны
функции извлечения из фалов и передачи на сервер информации о фильмах,
пользователях и оценках пользователей для фильмов.
app_data = AppData()
Далее создается объект Client, который будет иметь доступ к данным на сервере
client = predictionio.Client(APP_KEY, 1, API_URL)
Импорт всех user в PredictionIO. Каждый user имеет уникальный uid ключ:
for (k, v) in app_data.get_users().iteritems():
client.create_user(v.uid)
Импорт всех item в PredictionIO. Each item has an unique iid and the itype is
'movie':
for (k, v) in app_data.get_items().iteritems():
client.create_item(v.iid, ("movie",))
Импорт всех rate action в PredictionIO. Каждая оценка имеет ключи uid, iid,
оценка (от 1 до 5) :
for v in app_data.get_rate_actions():
client.identify(v.uid)
14
client.record_action_on_item("rate", v.iid, { "pio_rate": v.rating, "pio_t":
v.t })
Для получения списка рекомендаций в файле movie_rec_app.py задается имя
инструмента, с которым будет работать система.
ENGINE_NAME = 'movie-rec'
Получение n рекомендаций средствами инструмента ENGINE_NAME
try:
self._client.identify(u.uid)
rec = self._client.get_itemrec_topn(n, ENGINE_NAME)
u.rec = rec['iids']
self.display_items(u.rec)
except predictionio.ItemRecNotFoundError:
print "[Info] Recommendation not found"
Алгоритм
3.2
рекомендательной
системы
коллаборативной
фильтрации
На основании заранее подготовленного документа с данными опроса 6000
человек
применить
алгоритм
коллаборативной
фильтрации
и
вывести
рекомендацию конкретному пользователю по его интересам.
Коллаборативные
системы
используют
рекомендации
(оценки),
сделанные другими пользователями. Данная методика имеет рядом проблем:
Проблема нового пользователя.
Чтобы
делать
точные
рекомендации,
система
должна
изучить
предпочтения пользователя на основании данных им оценок.
Проблема новых данных.
15
Новые данные регулярно добавляются в рекомендационные системы.
Коллаборативные системы при выработке рекомендаций руководствуются
только предпочтениями пользователей. Поэтому рекомендационная система не
может рекомендовать товар, пока он не получит достаточное количество
оценок.
Масштабируемость.
Ресурсоемкость и сложность делает затруднительным использование
коллаборативных методик в системах с большим количеством пользователей.
Проблема первой оценки.
Система оценивает степень сходства товаров на основе проставленных
для них оценок, поэтому, когда появляется новый неизвестный элемент, система
никогда его не порекомендует, пока кто-нибудь его не оценит.
Проблема избирательности внимания.
При появлении новых элементов, наблюдается накопление большого
количества оценок для существующих элементов, и отсутствия оценок для
новых/редких кинофильмов. Это ведет к тому, что известные существующие
кинофильмы становятся все более и более популярными, а малоизвестные
новые кинофильмы никогда не предлагаются пользователям.
Алгоритм коллаборативной фильтрации состоит в следующем:
1. Выбрать N кинофильмов, рейтинг которых больше всего похожи на
рейтинги кинофильмов рассматриваемого пользователя. Для этого для
каждого из пользователей нужно вычислить выбранную меру в
отношении рассматриваемого кинофильма, и выбрать N наибольших.
2. Для каждого фильма умножить его оценки на вычисленную величину
меры, таким образом, оценки более «похожих» фильмов будут сильнее
влиять на итоговую позицию фильма.
16
3. Для каждого из фильмов посчитать сумму калиброванных оценок N
наиболее близких фильмов, полученную сумму разделить на сумму мер N
выбранных фильмов. И получить итоговую рекомендацию.
Рисунок 6 – данные пользователя 1
17
Рисунок 7 – данные пользователя 2
Рисунок 8 – рекомендации пользователю 2
18
Замечание.
Импорт и подготовка данных к обработке занимает много времени из-за
большого
количества
связей
между
пользователями(users),
кинофильмами(items) и рейтингами кинофильмов (rate).
В рассмотренном
примере было задействовано 1 миллион рейтингов от 6000 пользователей на
4000 фильмов.
В работе алгоритма применялось Следование принципу: переместить
вычисления проще, чем переместить данные. Поэтому выдача рекомендаций
происходит мгновенно, т.к нет процесса перемещения больших объёмов
данных.
19
ЗАКЛЮЧЕНИЕ
В ходе курсовой работы удалось построить функционирующий сервис,
выполняющий поиск и выдачу рекомендаций кинофильмов на основе
пользовательских
предпочтений
на
основе
открытых
данных
исследовательской группы GroupLens. Не смотря на простоту текущего
алгоритма, система может без особых затруднений быть модифицирована для
выполнения более сложных методов обработки, и для сколь угодно больших
объёмов обрабатываемых данных. Система может быть использована как
основа для приложений, выдающих пользовательские рекомендации, легко
масштабироваться под бесконечное число вычислительных узлов.
20
СПИСОК ИСПОЛЬЗУЕМЫХ ИСТОЧНИКОВ
1.
“Рекомендательные системы: Часть 1. Введение в подходы и алгоритмы”
[электронный ресурс] URL: http://www.ibm.com/developerworks/ru/library/osrecommender1/ [дата обращения: 20 мая 2014]
2.
“How Computers Know What We Want — Before We Do” [электронный
ресурс] URL: http://content.time.com/time/magazine/article/0,9171,1992403,00.html
[дата обращения: 25 мая 2014]
3.
Ricci F..Rokach L., Introduction to Recommender Systems Handbook,
Recommender Systems Handbook// Springer, 2011, pp. 1-35
4.
Melville P., Sindhwani V., Recommender Systems, Encyclopedia of Machine
Learning, 2010, с.135-140
5.
Lemire D., Maclachlan A. Slope One Predictors for Online Rating-Based
Collaborative Filtering//Springer, - 2005, c. 1-12
7.
“PredictionIO Python API Documentation” [электронный ресурс] URL:
http://pythonhosted.org/PredictionIO/ [дата обращения: 2 апреля 2014]
21
ПРИЛОЖЕНИЕ А
«Подготовка данных для обработки»

app_config.py: config data for the app such as App Key.
APP_KEY =
'aBG6YANMMUQrCW3ZjiaKKXhr3s359bs4T3zP7WXmMU1XRhDj5xowZCsHxotyywA
U'
API_URL = 'http://localhost:8000'

appdata.py: data model structure which loads the data from the data set files.
import datetime
from operator import itemgetter, attrgetter
APPDATA_DIRNAME = "ml-100k"
USERS_FILENAME = "u.user"
USERS_FILE_DELIMITER = "|"
ITEMS_FILENAME = "u.item"
ITEMS_FILE_DELIMITER = "|"
RATE_ACTIONS_FILENAME = "u.data"
RATE_ACTIONS_DELIMITER = "\t"
class User:
def __init__(self, uid):
self.uid = uid
self.rec = [] # recommendations, list of iid
def __str__(self):
return "User[uid=%s,rec=%s]" % (self.uid, self.rec)
class Item:
def __init__(self, iid, name):
self.iid = iid
self.name = name
def __str__(self):
return "Item[iid=%s,name=%s]" % (self.iid, self.name)
class RateAction:
def __init__(self, uid, iid, rating, t):
self.uid = uid
self.iid = iid
self.rating = rating
self.t = t
def __str__(self):
22
return "RateAction[uid=%s,iid=%s,rating=%s,t=%s]" % (self.uid, self.iid, self.rating,
self.t)
class AppData:
def __init__(self):
self._users = {} # dict of User obj
self._items = {} # dict of Item obj
self._rate_actions = [] # list of RateAction obj
self._users_file = "%s/%s" % (APPDATA_DIRNAME, USERS_FILENAME)
self._items_file = "%s/%s" % (APPDATA_DIRNAME, ITEMS_FILENAME)
self._rate_actions_file = "%s/%s" % (APPDATA_DIRNAME,
RATE_ACTIONS_FILENAME)
self.__init_users()
self.__init_items()
self.__init_rate_actions()
def __init_users(self):
"""
uid|
"""
print "[Info] Initializing users..."
f = open(self._users_file, 'r')
for line in f:
data = line.rstrip('\r\n').split(USERS_FILE_DELIMITER)
self.add_user(User(data[0]))
f.close()
print "[Info] %s users were initialized." % len(self._users)
def __init_items(self):
"""
iid|name
"""
print "[Info] Initializing items..."
f = open(self._items_file, 'r')
for line in f:
data = line.rstrip('\r\n').split(ITEMS_FILE_DELIMITER)
self.add_item(Item(data[0], data[1]))
f.close()
print "[Info] %s items were initialized." % len(self._items)
def __init_rate_actions(self):
"""
uid|iid|rating|timestamp
"""
print "[Info] Initializing rate actions..."
f = open(self._rate_actions_file, 'r')
23
for line in f:
data = line.rstrip('\r\n').split(RATE_ACTIONS_DELIMITER)
t = datetime.datetime.utcfromtimestamp(int(data[3])).isoformat()
self.add_rate_action(RateAction(data[0], data[1], data[2], t))
f.close()
print "[Info] %s rate actions were initialized." % len(self._rate_actions)
def add_user(self, user):
self._users[user.uid] = user
def add_item(self, item):
self._items[item.iid] = item
def add_rate_action(self, action):
self._rate_actions.append(action)
def get_users(self):
return self._users
def get_items(self):
return self._items
def get_rate_actions(self):
return self._rate_actions
def get_user(self, uid):
"""return single user
"""
if uid in self._users:
return self._users[uid]
else:
return None
def get_item(self, iid):
"""return single item
"""
if iid in self._items:
return self._items[iid]
else:
return None
def get_top_rated_items(self, uid, n):
"""get top n rated iids by this uid
"""
if uid in self._users:
actions = filter(lambda u: u.uid==uid, self._rate_actions)
top = sorted(actions, key=attrgetter('rating'), reverse=True)
topn_iids = map(lambda a: a.iid, top[:n])
return topn_iids
24
else:
return None
def get_top_rate_actions(self, uid, n):
"""get top n rated actions by this uid
"""
if uid in self._users:
actions = filter(lambda u: u.uid==uid, self._rate_actions)
top = sorted(actions, key=attrgetter('rating'), reverse=True)
return top[:n]
else:
return None

batch_import.py: app data batch import script.
from appdata import AppData
import predictionio
import sys
from app_config import APP_KEY, API_URL
def batch_import_task(app_data, client, all_info=False):
print "[Info] Importing users to PredictionIO..."
count = 0
for k, v in app_data.get_users().iteritems():
count += 1
if all_info:
print "[Info] Importing %s..." % v
else:
if (count % 32 == 0):
sys.stdout.write('\r[Info] %s' % count)
sys.stdout.flush()
client.create_user(v.uid)
sys.stdout.write('\r[Info] %s users were imported.\n' % count)
sys.stdout.flush()
print "[Info] Importing items to PredictionIO..."
count = 0
for k, v in app_data.get_items().iteritems():
count += 1
if all_info:
print "[Info] Importing %s..." % v
else:
if (count % 32 == 0):
sys.stdout.write('\r[Info] %s' % count)
25
sys.stdout.flush()
client.create_item(v.iid, ("movie",))
sys.stdout.write('\r[Info] %s items were imported.\n' % count)
sys.stdout.flush()
print "[Info] Importing rate actions to PredictionIO..."
count = 0
for v in app_data.get_rate_actions():
count += 1
if all_info:
print "[Info] Importing %s..." % v
else:
if (count % 32 == 0):
sys.stdout.write('\r[Info] %s' % count)
sys.stdout.flush()
client.identify(v.uid)
client.record_action_on_item("rate", v.iid, { "pio_rate": v.rating, "pio_t": v.t })
sys.stdout.write('\r[Info] %s rate actions were imported.\n' % count)
sys.stdout.flush()
if __name__ == '__main__':
app_data = AppData()
client = predictionio.Client(APP_KEY, 1, API_URL)
batch_import_task(app_data, client)
client.close()

movie_rec_app.py: a simple command line based movie recommendation app.
from appdata import AppData
import predictionio
import sys
from app_config import APP_KEY, API_URL
ENGINE_NAME = 'movie-rec'
class App:
def __init__(self):
self._app_data = AppData()
self._client = predictionio.Client(APP_KEY, 1, API_URL)
26
def run(self):
state = "[Main Menu]"
prompt = "\n"\
"%s\n"\
"%s\n"\
"Please input selection:\n"\
" 0: Quit application.\n"\
" 1: Get Recommendations from PredictionIO.\n"\
" 2: Display user's data." % (state, '-'*len(state))
while True:
print prompt
choice = raw_input().lower()
if choice == '0':
print "\nGood Bye!\n"
break
elif choice == '1':
self.recommend_task(state)
elif choice == '2':
self.display_user_task(state)
else:
print '[Error] \'%s\' is not a valid selection.' % choice
self._client.close()
def recommend_task(self, prev_state):
state = prev_state + " / [Get Recommendations]"
prompt = "\n"\
"%s\n"\
"%s\n"\
"Please enter user id:" % (state, '-'*len(state))
while True:
print prompt
choice = raw_input().lower()
u = self._app_data.get_user(choice)
if u:
n = 10
print "[Info] Getting top %s item recommendations for user %s..." % (n, u.uid)
try:
self._client.identify(u.uid)
rec = self._client.get_itemrec_topn(ENGINE_NAME, n)
u.rec = rec['pio_iids']
self.display_items(u.rec)
except predictionio.ItemRecNotFoundError:
print "[Info] Recommendation not found"
print "[Info] Go back to previous menu..."
27
break
else:
print "[Error] invalid user id %s. Go back to previous menu..." % choice
break
def display_user_task(self, prev_state):
state = prev_state + " / [Display User]"
prompt = "\n"\
"%s\n"\
"%s\n"\
"Please enter user id:" % (state, '-'*len(state))
while True:
print prompt
choice = raw_input().lower()
u = self._app_data.get_user(choice)
if u:
print "[Info] User %s:" % u.uid
n = 10
topn_rate_actions = self._app_data.get_top_rate_actions(u.uid, n)
print "\n[Info] Top %s movies rated by this user:" % n
self.display_rate_actions(topn_rate_actions)
print "\n[Info] Movies recommended to this user:"
self.display_items(u.rec)
self.wait_for_ack()
print "\n[Info] Go back to previous menu..."
break
else:
print "[Error] invalid user id %s. Go back to previous menu..." % choice
break
def display_items(self, iids, all_info=False):
"""print item info for each iid in the list
"""
if iids:
for iid in iids:
item = self._app_data.get_item(iid)
if item:
if all_info:
print "[Info] %s" % item
else:
print "[Info] %s" % item.name
else:
print "[Error] Invalid item id %s" % iid
else:
print "[Info] Empty."
28
def display_rate_actions(self, actions):
"""print iid and rating
"""
if actions:
for a in actions:
item = self._app_data.get_item(a.iid)
if item:
print "[Info] %s, rating = %s" % (item.name, a.rating)
else:
print "[Error] Invalid item id %s" % a.iid
else:
print "[Info] Empty."
def wait_for_ack(self):
prompt = "\nPress enter to continue..."
print prompt
choice = raw_input().lower()
if __name__ == '__main__':
print "\nWelcome To PredictionIO Python-SDK Demo App!"
print "============================================\n"
my_app = App()
my_app.run()
29
ПРИЛОЖЕНИЕ Б
«Вспомогательные функции для алгоритма рекомендации коллаборативной
фильтрации»
class SlopeOne(object):
def __init__(self):
self.uid = {}
self.iid = {}
self.rate = {}
def predict(self, userprefs):
preds, iid = {}, {}
for item, rating in userprefs.iteritems():
for diffitem, diffratings in self.uid.iteritems():
try:
freq = self.iid[diffitem][item]
except KeyError:
continue
preds.setdefault(diffitem, 0.0)
iid.setdefault(diffitem, 0)
preds[diffitem] += freq * (diffratings[item] + rating)
iid[diffitem] += freq
return dict([(item, value / iid[item])
for item, value in preds.iteritems()
if item not in userprefs and iid[item] > 0])
def update(self, userdata):
for ratings in userdata.itervalues():
for item1, rating1 in ratings.iteritems():
self.iid.setdefault(item1, {})
self.uid.setdefault(item1, {})
for item2, rating2 in ratings.iteritems():
self.iid[item1].setdefault(item2, 0)
self.uid[item1].setdefault(item2, 0.0)
self.iid[item1][item2] += 1
self.uid[item1][item2] += rating1 - rating2
for item1, ratings in self.uid.iteritems():
for item2 in ratings:
ratings[item2] /= self.iid[item1][item2]
if __name__ == '__main__':
s = SlopeOne()
s.update(userdata)
30
Download