Архив автора: admin

OnePress Social Locker — лучший cоциальный замок для WordPress

Сейчас я расскажу как поставить на сайт так называемый «социальный замок» и увеличить активность своих пользователей в социальных сетях. Это просто и бесплатно.

Читать

Как правильно садить семена овощей и цветов? Советы эксперта

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

Именно о них мы и поговорим. Читать

ДИЕТА «6-ЛЕПЕСТКОВ»

Diet 6 petals

Сегодня обсудим диету «шесть лепестков», которая переносится довольно легко, весьма эффективна и позволяет избавиться за неделю от 3-5 кг веса.

В основу этой диеты включено несколько монодиет, и авторство принадлежит диетологу из Швеции, Анне Юханссон. Читать

Рекомендование предметов

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

Рекомендование предметов

Найти подходящего критика – это, конечно, неплохо, но в действительности-то я хочу, чтобы мне порекомендовали фильм. Можно было бы посмотреть, какие фильмы понравились человеку с похожими на мои вкусами, и выбрать из них те, что я еще не смотрел. Но при таком подходе можно было бы пропустить много классных фильмов. Или посмотреть фильм, который понравился только ему.

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

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

Можно было бы использовать для ранжирования сами эти суммы, но тогда фильм, который просмотрело больше людей, получил бы преимущество. Чтобы исправить эту несправедливость, необходимо разделить полученную величину на сумму коэффициентов подобия для всех критиков, которые рецензировали фильм (строка «S подоб.» в таблице)
По мере решения этой задачи, можно столкнуться с интересными закономерностями. 
Например, я сделал ранжирование фильмов, которым я ставил оценку. Что это значит? Представьте, что вы поставили всем фильмам 7 баллов. На страницу вашего профиля заходит Ваш друг, чтобы выбрать что посмотреть и натыкается на то, что все фильмы имеют одинаковые оценки. Чтобы этого не возникло, можно ему показывать не просто оценки, а взвешенные(с учетом вкусов друга, а не ваших), т.е. с учетом оценок других критиков.
Привожу скриптик.  Примеры приведены с Евклидовым коэффициентом подобия, исходя из его лаконичности, но так мне больше нравится Пирса.

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, сравнение каждого пользователя со всеми другими, а затем сравнение товаров, которым каждый пользователь выставил оценки, займет недопустимо много времени.

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

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

Итак, создадим табличку, куда будем записывать коэффициенты схожести фильмов между собой.

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. 

Если алгоритм понятен, давайте реализуем его:

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 фильмов, что я лайкнул мне посоветовали посмотреть — «Голова-ластик»
Ну что же…думаю этим и займусь) А вы найдите себе фильм на вечер!)

Автор: Pavel Petropavlov

Подбор предметов

Теперь вы знаете, как искать похожих людей и рекомендовать предметы данному человеку. Но что если нужно узнать, какие предметы похожи друг на друга? В данном случае вы можете определить степень сходства, выявив людей, которым понравился данный товар, и посмотрев, что еще им понравилось. По существу, это тот же метод, которым мы уже пользовались для определения похожести людей, – нужно лишь вместо людей всюду подставить товары. Излогаясь математическим языком — транспонировать)

Подбор схожих предметов

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

Практика Евклида

select
v1.film_id, v2.film_id,
1/(1+(|/sum((v1.vote-v2.vote)^2))),--евклидово не взвешенное расстояние
count(1)--кол-во общих фильмов(вес для ф-ии)
from votes v1
join votes v2 on v1.user_id=v2.user_id
where v1.film_id <> v2.film_id
and v2.film_id=326
group by v1.film_id, v2.film_id
--having count(1)>10
order by 1/(1+(|/sum((v1.vote-v2.vote)^2))) desc, count(1) desc

Для сравнения возьмем фильм «Побег из Шоушенка». Метод Евклида посчитал, что на него больше всего похож фильм «Реал Мадрид». Спросите чем? Отвечу:

select
v1.film_id, v2.film_id,
v1.vote vote1, v2.vote vote2, v1.user_id, v2.user_id
from votes v1
join votes v2 on v1.user_id=v2.user_id
where v1.film_id <> v2.film_id
and v2.film_id=326
and v1.film_id=155080

5 разных людей смотрели оба фильма и поставили не много не мало все 10ки!!! Но конечно, данный алгоритм никак не учитывает жанры, режиссеров или актеров. Однако никто не мешает ввести вам такие дополнительные фильтрующие весовые функции.

Практика Пирсона

select
v1.film_id,
case when ((sum(v1.vote^2)+1)-(sum(v1.vote)^2)/count(1)::float)*((sum(v2.vote^2)+1)-(sum(v2.vote)^2)/count(1)::float) <> 0
then
(sum(v1.vote*v2.vote)-(sum(v1.vote)*sum(v2.vote))/count(1)::float)/(|/((sum(v1.vote^2)+1)-(sum(v1.vote)^2)/count(1)::float)*((sum(v2.vote^2)+1)-(sum(v2.vote)^2)/count(1)::float))
else
0
end,
count(1)--кол-во общих критиков(вес для ф-ии)
from votes v1
join votes v2 on v1.user_id=v2.user_id
where v1.film_id <> v2.film_id
and v2.film_id=326 --фильм для сравнения
group by v1.film_id, v2.film_id
--having count(1)>10
order by
case when ((sum(v1.vote^2)+1)-(sum(v1.vote)^2)/count(1)::float)*((sum(v2.vote^2)+1)-(sum(v2.vote)^2)/count(1)::float) <> 0
then
(sum(v1.vote*v2.vote)-(sum(v1.vote)*sum(v2.vote))/count(1)::float)/(|/((sum(v1.vote^2)+1)-(sum(v1.vote)^2)/count(1)::float)*((sum(v2.vote^2)+1)-(sum(v2.vote)^2)/count(1)::float))
else
0
end
desc,
count(1) desc

Запустив пирсона, получим совсем другой фильм — «Крезанутые». И это всего при 2х общих критиках. В общем советую Вам обратить внимание на закомментированную строку с having, считаю что нужно ее применить для более точного совпадения)

Автор: Pavel Petropavlov