В прошлом посте мы с Вами разобрались, как ранжировать людей по вкусам и говорить кто на нас похож больше всех. Теперь займемся связанной задачей - рекомендацией фильмов!
Чтобы разрешить эти проблемы, необходимо ранжировать сами фильмы, вычислив взвешенную сумму оценок критиков. Берем каждого из отобранных критиков и умножаем его оценку подобия со мной на оценку, которую он выставил каждому фильму. Вот пример из книжки, надеюсь будет понятно)
Смысл в том, чтобы мнение критика с похожими на мои вкусами вносило больший вклад в общую оценку, чем мнение критика, не похожего на меня. В строке «Итого» приведены суммы вычисленных таким образом величин.
Рекомендование предметов
Найти подходящего критика – это, конечно, неплохо, но в действительности-то я хочу, чтобы мне порекомендовали фильм. Можно было бы посмотреть, какие фильмы понравились человеку с похожими на мои вкусами, и выбрать из них те, что я еще не смотрел. Но при таком подходе можно было бы пропустить много классных фильмов. Или посмотреть фильм, который понравился только ему.Чтобы разрешить эти проблемы, необходимо ранжировать сами фильмы, вычислив взвешенную сумму оценок критиков. Берем каждого из отобранных критиков и умножаем его оценку подобия со мной на оценку, которую он выставил каждому фильму. Вот пример из книжки, надеюсь будет понятно)
Смысл в том, чтобы мнение критика с похожими на мои вкусами вносило больший вклад в общую оценку, чем мнение критика, не похожего на меня. В строке «Итого» приведены суммы вычисленных таким образом величин.
Можно было бы использовать для ранжирования сами эти суммы, но тогда фильм, который просмотрело больше людей, получил бы преимущество. Чтобы исправить эту несправедливость, необходимо разделить полученную величину на сумму коэффициентов подобия для всех критиков, которые рецензировали фильм (строка «S подоб.» в таблице)
По мере решения этой задачи, можно столкнуться с интересными закономерностями.
Например, я сделал ранжирование фильмов, которым я ставил оценку. Что это значит? Представьте, что вы поставили всем фильмам 7 баллов. На страницу вашего профиля заходит Ваш друг, чтобы выбрать что посмотреть и натыкается на то, что все фильмы имеют одинаковые оценки. Чтобы этого не возникло, можно ему показывать не просто оценки, а взвешенные(с учетом вкусов друга, а не ваших), т.е. с учетом оценок других критиков.
Привожу скриптик. Примеры приведены с Евклидовым коэффициентом подобия, исходя из его лаконичности, но так мне больше нравится Пирса.
Таким образом фильмы с одинаковыми оценками(которые поставил я), стали взвешенными и выстроились в порядке, которые по идее мне понравились чуточку больше)))
Ну что же - это уже, как минимум не плохо) Но и основная задача, рекомендации фильмов, решается не сложнее).
Вот и все!) Что нам нужно знать об этой ф-ии. Ну во первых мы ввели ограничение на минимальное кол-во голосов за фильм в 10, чтобы не вышло так, что кому-то понравился фильм, у вас с этим критиком коэффициент близкий у 1 и соответственно фильм имеет хороший вес.
И теперь про отличие этой цифры от той, что выставлена на самом сайте kinopoisk.ru. А отличие простое: там просто средне арифметическая по голосам и кол-ву голосовавших, а эта чисто ваша, рассчитанная исходя из сходства вкусов Вас и тех кто голосовал. Поэтому при таком подходе, у разных людей у одного и того же фильма будут разные оценки, иногда абсолютно разные!)))
select v1.film_id, count(1),--количество людей тоже ставивших голоса фильму кроме меня evkl.sum_koef -- сумма подобия людей(со мной) голосовавших за этот фильм from votes v1 join votes v2 on v1.film_id=v2.film_id join ( select sum(evkl.vote*evkl.koef)/sum(evkl.koef) sum_koef, evkl.film_id from( select v1.user_id, v1.vote, v1.film_id, 1/(1+(|/sum((v1.vote-v2.vote)^2))) koef--евклидово не взвешенное расстояние from votes v1 join votes v2 on v1.film_id=v2.film_id where v1.user_id <> v2.user_id and v2.user_id=4722023 -- мой id group by v1.user_id, v1.film_id, v1.vote ) evkl group by evkl.film_id ) evkl on v1.film_id=evkl.film_id where v1.user_id <> v2.user_id and v2.user_id=4722023 -- мой id group by v1.film_id, evkl.sum_koef order by evkl.sum_koef desc
Таким образом фильмы с одинаковыми оценками(которые поставил я), стали взвешенными и выстроились в порядке, которые по идее мне понравились чуточку больше)))
Ну что же - это уже, как минимум не плохо) Но и основная задача, рекомендации фильмов, решается не сложнее).
select v1.film_id, sum(v1.vote*evkl.koef)/sum(evkl.koef) from votes v1 join ( select v1.user_id, 1/(1+(|/sum((v1.vote-v2.vote)^2))) koef--евклидово не взвешенное расстояние from votes v1 join votes v2 on v1.film_id=v2.film_id where v1.user_id <> v2.user_id and v2.user_id=4722023 group by v1.user_id order by v1.user_id ) evkl on evkl.user_id=v1.user_id --фильтруем, чтобы за фильм голосовало не менее 10 человек join ( select film_id, count(1) from votes group by film_id having count(1)>10 ) flms on flms.film_id=v1.film_id group by v1.film_id order by sum(v1.vote*evkl.koef)/sum(evkl.koef)
Вот и все!) Что нам нужно знать об этой ф-ии. Ну во первых мы ввели ограничение на минимальное кол-во голосов за фильм в 10, чтобы не вышло так, что кому-то понравился фильм, у вас с этим критиком коэффициент близкий у 1 и соответственно фильм имеет хороший вес.
И теперь про отличие этой цифры от той, что выставлена на самом сайте kinopoisk.ru. А отличие простое: там просто средне арифметическая по голосам и кол-ву голосовавших, а эта чисто ваша, рассчитанная исходя из сходства вкусов Вас и тех кто голосовал. Поэтому при таком подходе, у разных людей у одного и того же фильма будут разные оценки, иногда абсолютно разные!)))
Фильтрация по схожести образцов
Мы реализовали механизм рекомендования таким образом, что для создания набора данных необходимы оценки, выставленные каждым пользователем. Для нескольких тысяч людей или предметов это, возможно, и будет работать, но на таком большом сайте, как kinopoisk.ru, сравнение каждого пользователя со всеми другими, а затем сравнение товаров, которым каждый пользователь выставил оценки, займет недопустимо много времени.
Техника, которую мы применяли до сих пор, называется коллаборативной фильтрацией по схожести пользователей. Альтернатива известна под названием «коллаборативная фильтрация по схожести образцов». Когда набор данных очень велик, коллаборативная фильтрация по схожести образцов может давать лучшие результаты, причем многие вычисления можно выполнить заранее, поэтому пользователь получит рекомендации быстрее.
Процедура фильтрации по схожести образцов во многом основана на уже рассмотренном материале. Основная идея заключается в том, чтобы для каждого образца заранее вычислить большинство похожих на него, при помощи запроса выше. Тогда для выработки рекомендаций пользователю достаточно будет найти те образцы, которым он выставил наивысшие оценки, и создать взвешенный список образцов, максимально похожих на эти. Отметим одно существенное отличие: хотя на первом шаге необходимо исследовать все данные, результаты сравнения образцов изменяются не так часто, как результаты сравнения пользователей. Это означает, что не нужно постоянно пересчитывать для каждого образца список похожих на него; это можно делать, когда нагрузка на сайт невелика, или вообще на отдельном компьютере.
Итак, создадим табличку, куда будем записывать коэффициенты схожести фильмов между собой.
Туда при помощи запроса и конструкции INSERT INTO запишем данные фильмов, которые мы оценили уже на сайте.
Техника, которую мы применяли до сих пор, называется коллаборативной фильтрацией по схожести пользователей. Альтернатива известна под названием «коллаборативная фильтрация по схожести образцов». Когда набор данных очень велик, коллаборативная фильтрация по схожести образцов может давать лучшие результаты, причем многие вычисления можно выполнить заранее, поэтому пользователь получит рекомендации быстрее.
Процедура фильтрации по схожести образцов во многом основана на уже рассмотренном материале. Основная идея заключается в том, чтобы для каждого образца заранее вычислить большинство похожих на него, при помощи запроса выше. Тогда для выработки рекомендаций пользователю достаточно будет найти те образцы, которым он выставил наивысшие оценки, и создать взвешенный список образцов, максимально похожих на эти. Отметим одно существенное отличие: хотя на первом шаге необходимо исследовать все данные, результаты сравнения образцов изменяются не так часто, как результаты сравнения пользователей. Это означает, что не нужно постоянно пересчитывать для каждого образца список похожих на него; это можно делать, когда нагрузка на сайт невелика, или вообще на отдельном компьютере.
Итак, создадим табличку, куда будем записывать коэффициенты схожести фильмов между собой.
CREATE TABLE movies_similarity ( id serial NOT NULL, film_id1 integer NOT NULL, film_id2 integer NOT NULL, pirson_koef double precision NOT NULL, CONSTRAINT movies_similarity_pk PRIMARY KEY (id) )
Туда при помощи запроса и конструкции INSERT INTO запишем данные фильмов, которые мы оценили уже на сайте.
Выдача рекомендаций
Теперь вы готовы выдавать рекомендации, пользуясь словарем данных о схожести образцов без обращения ко всему набору данных. Необходимо получить список всех образцов, которым пользователь выставлял оценки, найти похожие и взвесить их с учетом коэффициентов подобия. Давайте разберем пример:
В каждой строке указан фильм, который я смотрел, и оценка, которую я ему выставил. Для каждого фильма, который я не смотрел, имеется столбец, где показано, насколько он похож на виденные мной фильмы. Например, коэффициент подобия между фильмами «Superman» и «The Night Listener» равен 0,103. В столбцах с названиями, начинающимися с О.x, показана моя оценка, умноженная на коэффициент подобия; поскольку я поставил фильму «Superman» оценку 4,0, то, умножая число на пересечении строки «Superman» и столбца «Night» на 4,0, получаем: 4,0 × 0,103 = 0,412.
В строке «Итого» просуммированы коэффициенты подобия и значения в столбцах «О.x» для каждого фильма. Чтобы предсказать мою оценку фильма, достаточно разделить итог для колонки «О.x» на суммарный коэффициент подобия. Так, для фильма «The Night Listener» прогноз моей оценки равен 1,378/0,433 = 3,183.
Если алгоритм понятен, давайте реализуем его:
В общем из тех 14 фильмов, что я лайкнул мне посоветовали посмотреть - "Голова-ластик"
Ну что же...думаю этим и займусь) А вы найдите себе фильм на вечер!)
select ms.film_id1, case when sum(ms.pirson_koef)<>0 then sum(v.vote*ms.pirson_koef)/sum(ms.pirson_koef) else 0 end from votes v join movies_similarity ms on ms.film_id2=v.film_id where v.user_id=4722023 group by ms.film_id1 order by case when sum(ms.pirson_koef)<>0 then sum(v.vote*ms.pirson_koef)/sum(ms.pirson_koef) else 0 end desc
В общем из тех 14 фильмов, что я лайкнул мне посоветовали посмотреть - "Голова-ластик"
Ну что же...думаю этим и займусь) А вы найдите себе фильм на вечер!)
Комментариев нет:
Отправить комментарий