[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Помогите с алгоритмом персональн. подбора контента
jetistyum
Имеется некоторый ресурс который подбирает юзеру контент, который должен его заинтересовать, необходимо разработать алгоритм подбора интересующего контента.
Теперь немного понятнее... есть юзер которому предпологается к прочтению некоторая статья... есть кнопка нравится, не нравится... (если не нравится, предлагается след. статья, если нравится, то юзер читает полную версию этой статьи) Нужно разработать обучающий алгоритм позволяющий определять персональные предпочтения юзера на основании прошлых лайков и дизлайков..

У меня есть идея - тегировать каждую статью и понижать, повышать вес тега для юзера на основании лайк-дизлайк, мы будем примерно знать какие тематики нравятся этому юзеру...

It - 100
business - 70
Cars - 68
animals - 30

.....

fishing - 1
agriculture - (-10)


Но каким образом подбирать статьи потом по высшим тегам, в первую очередь

выбирать первый - мы зациклимся на статьях по IT, каким образом их ранжировать, считать ли статью интересной если в ней присутствуют теги business и fishing ... избежать ситуации когда все статьи будут только лишь айтишные (нужно как-то разнообразить выдачу, но не выдавать то что совсем не интересно)

пока писал это, возникла еще идея - подсчитывать общий вес статьи по весам тегов для юзера в этой статьи ...

Есть ли еще какие-то варианты? Буду признателен за помощь! Алгоритм должен быть похож на подбор музыки на last.fm или подбор фильмов на kinobaza.tv, вероятно есть еще какие-то сервисы которые используют подобный алгоритм, но на ум приходят пока только эти.



Спустя 12 минут, 39 секунд (25.08.2011 - 14:31) linker написал(а):
Плохо думается, а потому совет, если ставится лайк на айтишной статье, то если в ней есть бизнес и рыбалка, то повышай вес и этих тегов тоже, таким образом можно будет балансировать, имхо.

Спустя 1 минута, 25 секунд (25.08.2011 - 14:33) jetistyum написал(а):
Да, именно это и имел в виду, повышать веса всех тегов, которые описывают эту статью. Но может у кого-то есть другие идеи.

Спустя 2 минуты, 52 секунды (25.08.2011 - 14:36) linker написал(а):
Да есть ещё идея, чтобы было более честнее, то для тегов в статьях тоже ввести свой вес, т.е. таким образом можно будет понимать какая основная тема у той или иной статьи. Соответственно при лайке повышать вес того или инога тэга для пользователя, основываясь на их весе для статьи.

Спустя 6 минут, 57 секунд (25.08.2011 - 14:43) jetistyum написал(а):
Тоже об этом думал, можно взять порядок тегов за их вес... Но это несколько усложняет рассчет, а любое усложнение будет еще сильнее нагружать сервер.
Кэшировать тут не получится, т.к. вес тега для юзера меняется, соотв. после изменения вес тега нужно пересчитывать вес статей...

Спустя 15 минут, 26 секунд (25.08.2011 - 14:58) linker написал(а):
Зато у статьи вес тега постоянный.
TU - вес тега для пользователя,
P - порядок тэга (отсчёт с 1).

TU = TU + 1/P

Не думаю, что эта формула хоть как-то ощутимо нагрузит сервак.

Спустя 11 минут, 16 секунд (25.08.2011 - 15:09) jetistyum написал(а):
статей, предположим 5-6 тыс.

тегов, предположим 200

в каждой статье, предположим в среднем 3 тега


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

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

к тому же нужно предусмотреть еще вариант когда юзер нажимает dislike, веса тегов понижаются, но статья по-прежнему самая высокая в рейтинге других статей, и снова ему отображается. тоесть нужно предусмотреть еще какую-то историю дизлайков и вносить туда статьи которые не понравились, и блокировать их для выборки последующей. Постоянно или временно.

Спустя 6 минут, 26 секунд (25.08.2011 - 15:16) linker написал(а):
Короче, сколько бы не было статей, но количество тэгов будет гораздо меньше. Т.е. все тэги это T[1..n], т.е. массив тэгов пользователя TU = T[1..n]. Допустим пользователь раз в час нажимает лайк для какой-то статьи, которая содержит тэги T1, T2, T3, соответственно раз в час для каждого из трех тэгов выполняется формула TUn = TUn + 1/Pn. О какой тут высокой нагрузке идёт речь?

Спустя 3 минуты, 51 секунда (25.08.2011 - 15:20) jetistyum написал(а):
речь идет о нагрузке во время выбора новой статьи, которую мы хотим рекомендовать юзеру.

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

Спустя 1 минута, 21 секунда (25.08.2011 - 15:21) linker написал(а):
Зачем пересчитывать, когда эти данные для каждого пользователя можно хранить?

Спустя 3 минуты, 28 секунд (25.08.2011 - 15:24) jetistyum написал(а):
как хранить?

Спустя 4 минуты, 56 секунд (25.08.2011 - 15:29) linker написал(а):
Да как угодно, лишь бы было удобно сортировать по релевантности тэгов.

Спустя 2 часа, 15 минут, 56 секунд (25.08.2011 - 17:45) inpost написал(а):
200 тегов, на каждый тег 10 балов, получаем число 2000,
rand(1,2000) - получаем тег. Если человек пропускает какой-то из тегов, значит этот тег получает -0,5 бала, остальные +(0,5/199) бала.
Если человек читает это описание, тогда +0,5 бала, остальные -(0,5/199) бала.
Итого вероятность нахождения будет расти у того направления, которое читает автор, если в начале самом получить данную статью у него будет примерно 1/200, то повышая от прочитывания нужной темы вероятность становится уже 1/190, а все остальные теги - ниже. Балансировка вероятности будет.

Спустя 1 минута, 48 секунд (25.08.2011 - 17:47) inpost написал(а):
К тому же достаточно не нагружено будет, если у тебя будет 1 таблица, в ней по 1 записи на 1 человека, 1 выборку, 1 запись.

Спустя 4 часа, 58 минут, 34 секунды (25.08.2011 - 22:46) jetistyum написал(а):
linker
Что хранить?
кто-то из нас потерял нить рассуждений. Кэшировать подсчитанные веса статей и хранить нельзя, т.к. он динамически меняется в зависимости от веса тега для юзера...


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


давайте на пальцах...

статьи и их теги


1 статья
охота, рыбалка, лес, озеро

2 статья
рыбалка, море, яхта

3 статья
компьютер, интернет, seo, оптимизация





веса тегов для юзера vasyapupkin

охота - 5
рыбалка - 3
лес - 2
озеро - 8
море - 15
яхта - 20
компьютер - 2
интернет - 3
seo - 0
оптимизация - 0

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

1 статья 5+3+2+8 = 18
2 статья 3+15+20 = 38
3 статья 3+3+0+0 = 6

видим что для него наиболее подходящая статья - 2статья, далее 1 статья и потом уже 3.


можно усложнить алгоритм - ввести коэффициент тега..
только не по формуле TU = TU + 1/P (будет прибавляться одинаковое кол-во баллов всегда при одинаковом кол-ве тегов)
а по
TU = TU * 1/P

1 статья (5*1)+(3*0,5)+(2*0,33)+(8*0,25) = 9,16
2 статья (3*1)+(15*0,5)+(20*0,33) = 17,1
3 статья 2*1+3*0,5+0+0 = 3,5
....
5000 статей .

а мы должны оценить все статьи, чтобы узнать какая самая интересная и рекомендовать ее.


2 мат операции для подсчета веса одного тега для статьи. 3 тега = 6 операций. 5тыс статей = 30 тыс операций.

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


Спустя 15 минут, 4 секунды (25.08.2011 - 23:01) jetistyum написал(а):
inpost
Цитата (inpost @ 25.08.2011 - 17:45)
200 тегов, на каждый тег 10 балов, получаем число 2000,
rand(1,2000) - получаем тег. Если человек пропускает какой-то из тегов, значит этот тег получает -0,5 бала, остальные +(0,5/199) бала.
Если человек читает это описание, тогда +0,5 бала, остальные -(0,5/199) бала.
Итого вероятность нахождения будет расти у того направления, которое читает автор, если в начале самом получить данную статью у него будет примерно 1/200, то повышая от прочитывания нужной темы вероятность становится уже 1/190, а все остальные теги - ниже. Балансировка вероятности будет.


что-то вообще не понял что ты имел в виду.
рандомом получаем тег - не понял. получаем число от 1 до 2000 но каким образом оно принадлежит тегу - не понятно.

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

боюсь просто не понял тебя

Спустя 8 часов, 33 минуты, 53 секунды (26.08.2011 - 07:35) linker написал(а):
...
Все твои кучи операций исключительно лежат на он-лайн пересчёте, я же говорю о том, чтобы сохранять веса тэгов для пользователя. Лайк/анлайк и выборка статей - это разные операции. Пересчёт тэгов должен вестить только на этапе Лайк/анлайк, в выборке - ничего не надо пересчитывать, сюда надо только подставлять ранее сохранённые веса тэгов пользователя. Плюс, пересчёт при Лайк/анлайк ведётся только для тех тэгов, которые есть у статьи.

Спустя 2 часа, 18 минут, 59 секунд (26.08.2011 - 09:54) oberon написал(а):
Если сделать многомерную матрицу для пользователя, где каждое измерение это тэг (координата с его числовым весом). И разместить статьи по этим тэгам (весам). Поиск статьи осуществлять быстро по максимальному тэгу по каждому измерению. Статьи помещаются в матрицу в соответствии с весом тэгов. То есть, пересчитывать не надо. Надо только пересортировывать. Что лучше и менее напряжно для сервака? Зависит от алгоритма.

Спустя 1 минута, 16 секунд (26.08.2011 - 09:55) oberon написал(а):
Кстати, в этом случае нет необходимости хранить данные или кэшировать. Это можно делать в одном многомерном массиве.

Спустя 7 минут, 38 секунд (26.08.2011 - 10:02) linker написал(а):
Цитата (oberon @ 26.08.2011 - 09:54)
Если сделать многомерную матрицу для пользователя, где каждое измерение это тэг (координата с его числовым весом).
Цитата (oberon @ 26.08.2011 - 09:55)
Кстати, в этом случае нет необходимости хранить данные или кэшировать. Это можно делать в одном многомерном массиве.
Но где-то эта матрица-многомерный массив должен храниться для каждого пользователя, либо пересчитывать каждый раз. Из воздуха просто так ничего не берётся.

Спустя 2 минуты, 41 секунда (26.08.2011 - 10:05) oberon написал(а):
Все в памяти. Быстро и прекрасно работает. В ОЗУ все лучше держать и обрабатывать, если есть возможность. Скорость в разы больше, чем при обращению к дискам.

Спустя 59 секунд (26.08.2011 - 10:06) linker написал(а):
oberon
Ты видимо перепутал PHP с другими компилируемыми языками.

Спустя 5 минут, 28 секунд (26.08.2011 - 10:12) oberon написал(а):
Не перепутал smile.gif Загрузить в память можно все и везде. Грузить матрицу можно в память скриптом и обрабатывать ее прямо на странице. Размер не будет слишком большим. Ведь необязательно набивать ее названиями статей. Только ID нужны.

Спустя 1 минута, 49 секунд (26.08.2011 - 10:13) oberon написал(а):
Можно еще загрузить на стороне сервера и не выгружать, пока пользователь не уйдет или не будет бездействовать определенное время. Решить через thread.

Спустя 7 минут, 31 секунда (26.08.2011 - 10:21) linker написал(а):
PHP не поддерживает нити.

Спустя 3 минуты, 56 секунд (26.08.2011 - 10:25) oberon написал(а):
По параметрам можно находить в памяти. Держать как массив и потом при перезагрузке страницы использовать.

Спустя 8 минут, 55 секунд (26.08.2011 - 10:34) linker написал(а):
Память в PHP - это либо кэш (он же мемкэш или иной), либо шаред, но шаред можно поставить только на своём собственном сервере. PHP-скрипт работает по принципу: запустился, отработал, завершился. При завершении всё что скрипт наплодил в памяти - уничтожается.

Спустя 3 минуты, 6 секунд (26.08.2011 - 10:37) oberon написал(а):
Как работает, знаю. Вообще, я привык работать на своих серверах. Как-то люблю, люблю все было мое и под рукой smile.gif Если сервак чужой, тогда проблемы, согласен.

Спустя 2 минуты, 47 секунд (26.08.2011 - 10:40) linker написал(а):
В 90% - это банальный хостинг, где всё уныло.

Спустя 6 часов, 43 минуты, 46 секунд (26.08.2011 - 17:23) jetistyum написал(а):
Цитата (linker @ 25.08.2011 - 23:01)
...
Все твои кучи операций исключительно лежат на он-лайн пересчёте, я же говорю о том, чтобы сохранять веса тэгов для пользователя. Лайк/анлайк и выборка статей - это разные операции. Пересчёт тэгов должен вестить только на этапе Лайк/анлайк, в выборке - ничего не надо пересчитывать, сюда надо только подставлять ранее сохранённые веса тэгов пользователя. Плюс, пересчёт при Лайк/анлайк ведётся только для тех тэгов, которые есть у статьи.

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

oberon

Цитата (oberon @ 26.08.2011 - 07:35)
Если сделать многомерную матрицу для пользователя, где каждое измерение это тэг (координата с его числовым весом). И разместить статьи по этим тэгам (весам). Поиск статьи осуществлять быстро по максимальному тэгу по каждому измерению. Статьи помещаются в матрицу в соответствии с весом тэгов. То есть, пересчитывать не надо. Надо только пересортировывать. Что лучше и менее напряжно для сервака? Зависит от алгоритма.



Что на счет трехмерного массива - тоже не понял.. но интересно было бы рассмотреть и твой подход, oberon не мог бы ты его описать на примере.


Да, что касается размещения проекта - то это на данный момент VPS, так что поставим хоть черта лысого... все в наших силах smile.gif

Спустя 20 часов, 59 минут, 5 секунд (27.08.2011 - 14:23) jetistyum написал(а):
может еще у кого-то будут какие-то идеи? Коллективный разум очень полезная штука smile.gif

Спустя 45 минут (27.08.2011 - 15:08) inpost написал(а):
user | тег1 | тег2 | тег3 | тег4 |  ...
1 | 0 | 10 | 20 | 30 | 40 | 50 | ...2000

rand(0,2000) = 21,
SELECT * WHERE user=1
$ row = fetch_array;
foreach($row as $k->$v)
if($v < $rand)
{
$teg = ($k-1);
break;
}

SELECT * WHERE teg = $row[$teg];

Если он принял одну из тегов, к примеру тег2, то запись становится такой:
user | тег1 | тег2 | тег3 | тег4 | ...
1 | 0 | 9,5 | 20,1 | 30,05 | 40,025 | 50,0125 | ...2000


Итого покрытие тега становится вместо 10-20, в 9,5-20,5 , теперь рендом будет чаще выдавать этот тег, а реже другие. Смысл такого распределения по одному тегу, если больше тегов, то чуть-чуть подправить и менять покрытие обоих тегов.
Теперь достаточно лишь рассчитать % изменения популярности тега, и долю, на которую будут понижаться остальные теги. Тут можно в % указывать даже.

Спустя 2 часа, 10 минут, 13 секунд (27.08.2011 - 17:18) jetistyum написал(а):
inpost
Исходя из твоего алгоритма выборки мы будем повышать каждый раз рейтинг всех тегов кроме тех, которые отклонил юзер (хочу напомнить что статья может содержать несколько тегов, точнее даже должна). тоесть если у нас будет какой-то редкий тег.. предположим "волнистые попугайчики" с одной единственной статьей, то у нас такой тег будет постоянно расти, за счет того что будут показываться статьи с другими тегами, которые юзер не принмает, и далее, у нас появляется еще одна статья про волнистых попугайчиков и сразу попадает в топ выдачи, т.к. за время пока не было статей и не понижался этот тег, вес тега вырос... а юзера это совершенно не интересует.

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

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

Спустя 46 минут, 36 секунд (27.08.2011 - 18:04) inpost написал(а):
jetistyum
Вообще-то каким образом постоянно человеку показывать одну и ту же тему? Надо фиксировать те темы, которые он уже почитал, и не выводить ему снова их.

Спустя 1 день, 14 часов, 54 минуты, 5 секунд (29.08.2011 - 08:58) oberon написал(а):
Пример не покажу. Это надо алгоритм четко разработать, а у меня сейчас со временем туго совсем. Но смысл такой - не трехмерная, а многомерная матрица, где одно измерение=один тэг. А шкала по измерению - его вес. Теперь, имея координаты по весу тэга в статье, размещаем статьи по этой матрице согласно тэгам статьи и весу каждого тэга. Когда пользователю надо подсунуть статьи, то выбираем по матрице статью, которая расположена по наибольшим значениям тэгов в матрице при наибольшем количестве тэгов. Так учитываются и тэги (количество) и их вес сразу в одной выборке. При изменениях весов тэгов в статье матрица пересортировывается, то есть, статья перемещается в матрице на другое место. При этом остальные статьи остаются на месте. Это не сортировка массива. Не надо путать. Кстати, подобный принцип решен в технологии баз OLAP. Там куча измерений и по ним располагаются значения в таблицах. Индексация позволяет быстро сортировать и находить значения. Но здесь индексировать необязательно. Вряд ли будет такое немыслимое количество статей.

Спустя 1 день, 27 минут, 54 секунды (30.08.2011 - 09:26) oberon написал(а):
Для программирования принцип такой: просто вести запись статьи в массиве, где индексы это тэги и диапазон индексов это вес тэга. Правда, для упрощения придется размерность как-то округлять, например, круглые проценты. Пример:
тэг "попугайчики" индекс 1-100
тэг "рыбалка" индекс 101-200
тэг "море" индекс 201-300
тэг "туризм" индекс 301-400
и так далее.
Теперь имеем статью о попугайчиках, живущих на море и промышляющих рыбалкой. Интерес к попугайчикам 20%, к морю 40%, к рыбалке 80%. В таком случае статья помещается в массив на место array[20][240][180]. Остальные индексы по другим всем тэгам принимаются по умолчанию [0]. Таким образом, имеем всегда конкретное размещение с учетом всех величин и весов.
Можно сделать и массивы в массиве (один тэг один массив). Но это, мне кажется, несколько больше будет грузить процессор, потому как каждый массив придется опрашивать отдельно.
Можно увеличить точность размещения статей, увеличив точность тэгов. Сделать диапазон, скажем, не 100 единиц, а 10000 единиц. Тогда можно будет вычислять с точностью до сотой доли процента. Нагрузка в этом случае увеличится несущественно, если все операции производить чисто в памяти без обращения к диску.
Для повторного захода клиента в эти алгоритмы подгружать ранее обработанный массив с диска, который был сохранен один раз, когда пользователь либо ушел, либо не был долго активен.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.