Статьи

Кассандра: как построить наивный байесовский классификатор пользователей на основе поведения

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

В предыдущем посте мы помогали вашей рекламной онлайн-компании отслеживать показатели конверсии рекламы. Но конкуренция высока, и мы должны немного повысить показатели конверсии рекламы, если ваша компания хочет оставаться на вершине. В последнее время возникли подозрения, что объявления часто показываются маловероятным клиентам. Быстрый просмотр журналов подтверждает эту обеспокоенность. Например, был случай, когда один пользователь интернета нажимал почти на каждую рекламу, которую он показывал, при условии, что это было связано с походным снаряжением. Несколько раз он продолжал делать покупки: палатку, фонарь и спальный мешок. Но, несмотря на очевидный интерес пользователей к спортивным товарам на открытом воздухе, в ваших журналах указывалось, что полностью 90% рекламы, которую он показывал, были для женской одежды . Из этих объявлений этот пользователь не нажал ни одной их.

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

Наивные байесовские классификаторы

Помня об этой цели, давайте рассмотрим теорию наивных байесовских классификаторов, чтобы мы могли создать свою собственную. Цель классификатора состоит в том, чтобы определить, к какой группе принадлежит выборка, на основе предоставленных данных. В данном случае наш «образец» — это отдельный пользователь, и на основе свидетельства того, на какую рекламу она нажимает, мы хотим определить, к какой группе она принадлежит: мода или наружная реклама. Чтобы придать математике задачу, рассмотрим следующий вопрос:

Какова вероятность того, что пользователь из группы , граммучитывая тот факт , что этот пользователь нажал на рекламу A, Ви С?

Чтобы поместить это в форму уравнения, мы можем написать:

\ displaystyle P (G | A, B, C)

Эта функция возвращает вероятность, число от 0 до 1, отражающее вероятность того, что этот пользователь входит в определенную группу, исходя из того, что он нажал на эти объявления. Таким образом, цель состоит в том, чтобы оценить это уравнение с каждой группой, а затем найти, какая группа приводит к большему результату. Но как вы оцениваете это уравнение? К счастью для нас, священник 18-го века Томас Байес дал ответ в виде уравнения Байеса:

\ displaystyle P (G | A, B, C, \ cdots) = \ frac {P (G) \ times P (A, B, C, \ cdots | G)} {P (A, B, C, \ cdots )}

Здесь мы превратили одну вероятность в функцию трех отдельных вероятностей:

  • P (G) — вероятность, что при отсутствии каких-либо доказательств того, что пользователь принадлежит к определенной группе, — это называется предшествующим
  • P (A, B, C, \ cdots | G)— вероятность того, что пользователь из группы граммбудет иметь кликали объявления A, В, Си т.д.
  • Р (А, В, С, \ cdots)— вероятность того, что пользователь из любой группы нажмет объявления A, В, Си т.д.

Это выглядит немного запутанно, но потерпите немного, и мы увидим, как это позволяет нам решить нашу проблему классификации. Давайте сначала посмотрим на вероятность P (G). Мы знаем, что и группа моды, и группа на открытом воздухе примерно одинаково сильны, поэтому для простоты мы предполагаем это P (\ textrm {fashion}) = P (\ textrm {outdoors}) = 0,5. Но помните, мы в конечном итоге намереваемся определить группу, которая максимизирует это уравнение. Поскольку P (G) = 0,5в обоих случаях это не влияет на результат и может быть безопасно проигнорировано. Далее Р (А, В, С, \ cdots). Мы могли бы оценить вероятность того, что пользователи нажимают на определенные группы объявлений, но здесь мы снова ищем группу, которая максимизирует вышеприведенное уравнение, и поскольку значениеР (А, В, С, \ cdots)не является функцией рассматриваемой группы, этот компонент остается постоянным во всех группах и также может быть безопасно проигнорирован.

Только часть левая P (A, B, C, \ cdots | G), вероятность того, что пользователь из группы G будет нажимать на объявления A, В, Си т.д. Так как эта часть является функцией грамм, мы не можем игнорировать его, так что мы должны как — то вычислить его. И наша цель, опять же, состоит в том, чтобы найти группу, граммкоторая максимизирует эту вероятность. … Но у нас есть проблема. Эта конкретная вероятность, как указано, не может быть вычислена. Это трудно Математически невозможно собрать достаточно информации, чтобы оценить вероятность того, что член группы граммнажмет на какой-либо конкретный набор объявлений. Поэтому мы делаем то, что будет делать любой хороший прикладной математик, когда бьется о такую ​​стену, мы сделаем упрощающее предположение, Если предположить, что рекламные клики полностью независимы друг от друга, мы можем обрабатывать их по отдельности. Таким образом:

P (A, B, C, \ cdots | G) \ приблизительно P (A | G) \ times P (B | G) \ times P (C | G) \ times \ cdots

Здесь каждый кусок, P (A | G), P (B | G), P (C | G)и т.д., на самом деле довольно просто оценить. И хотя это предположение может быть немного наивно — это, в конце концов, причина того, что этот классификатор называется Наивный байесовский классификатор — результирующий классификатор эмпирически был показать на работу достаточно хорошо через широкий спектр применения и даже в некоторых случаях , когда это предположение не только наивно, но на самом деле совершенно неверно.

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

P (G | A, B, C, \ cdots)

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

P (A, B, C, \ cdots | G)

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

P (A | G) \ times P (B | G) \ times P (C | G) \ times \ cdots

,

Построение классификатора с использованием Cassandra

Основываясь на приведенном выше уравнении, для каждого объявления Aи для обеих групп граммнеобходимо сохранить оценки вероятностей P (A | G). Чтобы окончательно определить, к какой группе принадлежит пользователь, мы ждем, пока пользователь совершит покупку. Исходя из того, у какого из наших клиентов он покупает продукт, например, у Zappos vs. REI, легко определить, входит ли этот пользователь в группу моды или наружную группу. В качестве примера рассмотрим пользователя, на которого мы ссылались ранее — человека, который приобрел палатку, фонарь и спальный мешок. Он, очевидно, человек на улице. Более того, поскольку мы можем отслеживать историю кликов каждого пользователя, мы знаем, какие объявления он нажимал в прошлом. И мы можем использовать количество этих объявлений, чтобы оценить вероятность того, что человек на улице нажмет на объявление для походных ботинок —P (\ textrm {HikingBootsAd} | \ textrm {} Открытый),

Вот как мы это делаем, используя Кассандру. Сначала мы создаем таблицу:

CREATE TABLE probability_of_view_given_group ( 
  ad text,
  group text,
  count counter,
  PRIMARY KEY(ad,group) 
);

Затем, когда пользователь совершает новую покупку, мы устанавливаем его группу, моду или на улице, основываясь на клиенте, у которого он приобрел. Затем мы собираем все объявления, на которые нажал этот пользователь, и для каждого объявления мы делаем два обновления. Давайте продемонстрируем это с помощью HikingBootsAd для пользователя выше:

UPDATE probability_of_view_given_group
  SET count=count+1
  WHERE ad='HikingBootsAd'
  AND group='ANY_GROUP';

UPDATE probability_of_view_given_group
  SET count=count+1
  WHERE ad='HikingBootsAd'
  AND group='HikingBootsAd';

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

\ displaystyle P (\ textrm {HikingBootAd} | \ textrm {Outdoor}) \ ок \ frac {N (\ textrm {Наружные покупатели, которые выбирают HikingBootAd})}} {N (\ textrm {Любые покупатели, которые нажимают HikingBootAd})}}

Собираем все вместе

Давайте посмотрим на это в действии. Пользователь только что открыл веб-страницу, принадлежащую одному из ваших рекламных партнеров, и пришло время показывать объявление. Быстрая проверка показывает, что этот пользователь просмотрел три объявления за последние пару дней: LittleBlackDressAd, CuteHighHeelsAd и совсем недавно HikingBootAd. Вот как мы автоматически определяем, в какую группу входит этот пользователь, чтобы мы могли показывать ему рекламу, соответствующую его вкусам:

Сначала мы собираем все доступные данные для рассматриваемой рекламы:

SELECT * FROM probability_of_view_given_group
  WHERE ad='LittleBlackDressAd';

         ad         |   group   | count
--------------------+-----------+-------
 LittleBlackDressAd | ANY_GROUP | 11843 
 LittleBlackDressAd | Outdoors  | 142
 LittleBlackDressAd | Fashion   | 11701

SELECT * FROM probability_of_view_given_group 
  WHERE ad='CuteHighHeelsAd';

       ad        |   group   | count
-----------------+-----------+------- 
 CuteHighHeelsAd | ANY_GROUP | 54127 
 CuteHighHeelsAd | Outdoors  | 53 
 CuteHighHeelsAd | Fashion   | 54074

SELECT * FROM probability_of_view_given_group
  WHERE ad='HikingBootAd';

      ad      |   group   | count
--------------+-----------+-------
 HikingBootAd | ANY_GROUP | 71534
 HikingBootAd | Outdoors  | 63241
 HikingBootAd | Fashion   | 8293

Затем мы вычисляем необходимые вероятности, деля счетчики Outdoors и Fashion на счетчики ANY_GROUP.

P (\ textrm {LittleBlackDressAd} | \ textrm {На открытом воздухе}) = 142/11843 = 0,01199P (\ textrm {LittleBlackDressAd} | \ textrm {Fashion}) = 11701/11843 = 0,98801

P (\ textrm {CuteHighHeelsAd} | \ textrm {На открытом воздухе}) = 53/54127 = 0,00098P (\ textrm {CuteHighHeelsAd} | \ textrm {Fashion}) = 54074/54127 = 0,99902

P (\ textrm {HikingBootAd} | \ textrm {На открытом воздухе}) = 63241/71534 = 0,88407P (\ textrm {HikingBootAd} | \ textrm {Fashion}) = 8293/71534 = 0,11593

Как это часто бывает, когда вы начинаете отслеживать метрики, подобные этой, вы обнаруживаете другие интересные факты как побочный продукт вашей работы. В этом случае мы видим, что HikingBootAd удивительно популярен среди модниц.

Наконец, еще раз напомним, что выбранная нами классификация основана на том, какая группа максимизирует уравнение P (A | G) \ times P (B | G) \ times P (C | G) \ times \ cdots. Поэтому мы применяем это уравнение к обеим группам:

P (\ textrm {LittleBlackDressAd} | \ textrm {Outdoors})\ quad \ times P (\ textrm {CuteHighHeelsAd} | \ textrm {На открытом воздухе})\ quad \ times P (\ textrm {HikingBootAd} | \ textrm {На открытом воздухе})\ quad = 0.01199 \ times 0.00098 \ times 0.88407\ quad = 0.00001

P (\ textrm {LittleBlackDressAd} | \ textrm {Fashion})\ quad \ times P (\ textrm {CuteHighHeelsAd} | \ textrm {Fashion})\ quad \ times P (\ textrm {HikingBootAd} | \ textrm {Fashion})\ quad = 0.98801 \ times 0.99902 \ times 0.11593\ quad = 0.11443

На основании этих расчетов вероятность того, что этот человек принадлежит к группе моды, примерно в 11 000 раз выше, чем к группе наружного отдыха. Основываясь на этой классификации, мы с уверенностью представляем рекламу милого розового дизайнерского кошелька. Оказывается, этот пользователь продолжает покупать кошелек. Поскольку она сделала покупку у одного из наших модных клиентов, мы теперь знаем, что этот пользователь входит в группу модных товаров, и, покорно, мы завершаем цикл анализа, собирая просмотренные объявления и используя их для обновления наших показателей в Cassandra. Обратите внимание, что это включает в себя еще один показатель в пользу того, что HikingBootAd является привлекательным для членов группы моды.

Вывод

Теперь, когда я закончил свой набросок для создания механизма классификации пользователей на основе Cassandra, вы должны выйти и запустить все это в производство? Нет … наверное нет. На самом деле, есть несколько проблем с приложением, так как я создал его здесь. С одной стороны, просто потому, что человек совершает одну покупку на открытом воздухе, это не значит, что он всегда и всегда будет самым типичным человеком на открытом воздухе. Действительно, в нашем примере здесь мы определили конкретную пару туристических ботинок, которые модным людям кажутся модными. Затем, на стороне Кассандры, мы должны сделать несколько запросов, прежде чем показывать каждое отдельное объявление. В то время как Cassandra довольно быстро справляется с операциями чтения, Cassandra лучше всего справляется с задачами быстрой записи, а пример использования, описанный в этом посте, немного сложен для чтения.

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