Построение эффективной системы электронного маркетинга. EMW 2012
"Построение рекомендательной системы на Python" Василий...
-
Upload
avitotech -
Category
Technology
-
view
384 -
download
3
Transcript of "Построение рекомендательной системы на Python" Василий...
Построение рекомендательнойсистемы на PythonPython Data Science meetup @ Avito
Лексин Василий
13 августа 2016 г.
0
План презентацииВыгрузка данных
Типы данных
Выгрузка данных из хранилища
Предобработка данных
Фильтрация данных
Предобработка поисковых запросов
Обучение модели
Параметры модели и обучение
Оценка качества модели
1
Типы данныхДанные по пользователям
Профиль интересов по категориям и регион
Согласен ли получать рекомендации
Данные по объявлениям
Микрокатегория
Местоположение
Действия пользователей
Items search, item view
Item view phone, item send message
Favorites item add
2
Выгрузка данных изхранилища (SQL)
Один месяц click stream
Фильтруем офисные IP
Фильтруем ботов (ноу хау)
Только посление сессии от каждого пользователя
От каждой сессии берем максимум случайных событий
каждого типа
Привязываем действия от неавторизованных
пользователей к user_id
Отдельно выгружаем поисковые запросы
Ns
Ne
2 - 1
Статистика по выгруженнымданным
853M событий
13M пользователей
32M объявлений
77M поисковых запросов
4M уникальных текстов запросов
2 - 2
Постановка задачирекомендацийДля максимально большого сегментаактивных пользователей отобрать по top Nобъявлений, которые пользователя наиболеевероятно заинтересуют.
3
Пример поисковых запросовIn [73]:
Out[73]: ext_user_id microcat_id location_id searchquery_id
110046 -6474078695648370021 2744 3960 NaN
528990 3115636 2679 1344 9955361
770905 90352811 1776 3953 8285511
1081196 79333327 3718 2142 2608148
473135 29970120 5779 1344 NaN
3099378 -5360608040238233550 5250 3856 NaN
665866 24882994 259 1261 NaN
1368309 3202041 3718 2885 NaN
1659277 89384896 1989 3953 12435410
1841537 13939317 66 1261 NaN
import pandas as pd df_queries.sample(10)
4
Пример текстов запросовIn [81]:
Out[81]: searchquery_id query
128240 59238250342 кожаный кошклек
139772 234299750143 batyka
18635 4411625 медсестра
202708 1040250002 кукла новая испания
149424 234267250442 детские вещи емле
214063 233309500285 зимний комбинезон мальчикучика 86-92
51753 5599527 tally weijl
6267 6729157 туфли 39
69994 133827 плащ пиджак
39963 1008632 doctor e
df_searchquery.sample(10)
4 - 1
Пример лога событийIn [87]:
Out[87]: ext_user_id ext_item_id
0 269878 778223165
1 269878 820358781
2 269878 804777863
3 93940783 602550035
4 93940783 793828222
5 93940783 811076220
6 93940783 651115689
7 93940783 211688068
8 93940783 807188069
9 93940783 762847248
df_data.sample(10)
4 - 2
Нормализация текстаIn [ ]:
In [ ]:
from nltk.corpus import stopwords as swimport pymorphy2import restopwords= set(sw.words("russian"))
morph = pymorphy2.MorphAnalyzer()token_pattern = re.compile(r'\b[\w\.\/]+\b')tokenize = lambda doc: token_pattern.findall(doc) badlist = set(['отличный', 'идеальный', 'состояние', 'продажа', 'продавать', 'обменять', 'москва', 'продать', 'хороший', 'продаваться', 'супер']) def get_tokens(line): cur_line = tokenize(line) normalized_tokens = [morph.parse(x)[0].normal_form for x in cur_line] filtered_tokens = [token for token in normalized_tokens if not token in badlist and not token in stopwords] return filtered_tokens
5
Параллельная обработкаIn [1]:
In [24]:
. . .
from multiprocessing import Pool
pool = Pool()df_searchquery['norm_query'] = pool.map(get_tokens, df_searchquery['query'].values)pool.terminate()
5 - 1
Биграммы, фильтрацияIn [2]:
In [25]:
In [78]:
. . .
. . .
. . .
from gensim.models.phrases import Phrasesfrom gensim.corpora import Dictionary
bigram_transformer = Phrases(df_searchquery['norm_query'].values)df_searchquery['norm_query'] = [bigram_transformer[q] for q in df_searchquery['norm_query']]
id2word = Dictionary(df_searchquery['norm_query'].values)id2word.filter_extremes(no_below=5) df_searchquery['norm_query'] = [[w for w in q if w in id2word.token2id] for q in df_searchquery['norm_query']]
6
Пример нормализованных запросовIn [88]:
Out[88]: searchquery_id query norm_query
11363 40583250271 куртка на осень стильная [куртка, осень, стильный]
30231 8776934 памперсы меррис [памперс]
89102 6296057 stig []
102222 13296939 пакетом 2-3 [пакет, 2_3]
33406 5522081 casadei балетки [casadei, балетки]
194946 234467250136 комбенизон reima ноаые [комбенизон, reima, ноаый]
42300 2691799 пастельное белье детское [пастельный_бельё, детский]
108060 136389 ecco демисезон [ecco, демисезон]
82151 5960365 кукла германия [кукла, германия]
92853 69941250025 на мальчика размер 80 [мальчик, размер, 80]
df_searchquery.sample(10)
6 - 1
Комбинация запроса смикрокатегорией
In [89]:
Out[89]: ext_user_id microcat_id location_id searchquery_id norm_query
2768669 79821794 2744 1403 NaN [2744:]
2716176 -3322596449809766062 3718 406 NaN [3718:]
2349895 930812 847 2187 NaN [847:]
3180239 -4757589830893039331 6232 4111 NaN [6232:]
2122630 46977773 6670 4499 NaN [6670:]
2023443 48879590 5250 2643 NaN [5250:]
1492290 87985326 7188 2885 NaN [7188:]
2452980 -8482002081938376691 5428 3960 2.339135e+11
[5428:lps,5428:петшоп,5428:литло_петь,5428:...
1795200 1431139 3718 3976 5.659923e+06 [3718:крокс_crocs]
951770 3471714 7382 3953 5.589893e+06 [7382:шуба_мутон]
df_queries.sample(10)
6 - 2
Признаки пользователяIn [90]:
Out[90]: ext_user_id norm_query location_id
723827 56908675 [7382:, 478:, 3718:, 1675:, 149:] [2430]
7962 -9019847421690666119[2744:сумка, 1860:, 5250:, 2744:женский,2744:...
[230]
1020309 95760508 [2744:стрип, 2744:] [992]
297934 -1603932776056930038 [5250:] [4181]
494505 11949033 [2868:, 4488:, 6875:, 4243:, 3478:, 5938:] [926]
150433 -5371442050781010156 [4814:] [3610]
552456 19578840 [6797:, 5513:] [3953]
223287 -3517260670980945043 [2744:] [2885]
811247 76406847 [259:bugaboo] [2885]
843402 80272837 [259:] [642, 44]
df_user_query.sample(10)
7
Фильтрация лога событийIn [ ]: import graphlab as gl
# Generate bipartite user-item graphg = gl.SGraph()g = g.add_edges(training_data, src_field='ext_user_id', dst_field='ext_item_id') k_value = 10 # Compute the N-core decomposition of the graphkc = gl.kcore.create(g, kmin=k_value-1, kmax=k_value) # Filtering eventstraining_filtered = g.get_neighborhood(kc.core_id.filter_by( k_value, 'core_id')['__id'], radius=0) training_filtered = gl.SFrame(training_filtered.edges).rename({ '__src_id': 'ext_user_id', '__dst_id': 'ext_item_id'})
8
Factorization Machine - общая идея
9
Factorization Machine - генеративнаямодель
- пользователь
- объявление
- global bias term
и - weight terms
и - side feature vectors
и - weight vectors for side features
и - latent factors
p(i, j) = μ + + + + + ,wi wj aTxi bTyj uTi vj
i
j
μ
wi wj
xi yj
a b
ui vj
9 - 1
Обучение моделиIn [67]:
. . .
(training_data, validation_data) = gl.recommender.util.random_split_by_user( gl.SFrame(df_data)) train_settings = dict( regularization=1e-07, linear_regularization=1e-07, side_data_factorization=True, num_factors=100, num_sampled_negative_examples=4, max_iterations=25) model_fr = gl.ranking_factorization_recommender.create( training_filtered, user_id = 'ext_user_id', item_id = 'ext_item_id', user_data=transformed_user_data, **train_settings)
9 - 2
Оценка качества моделиIn [77]:
cutoff precision recall1 0.022 0.0082 0.018 0.0103 0.016 0.0125 0.014 0.019
10 0.011 0.029
. . .
prec_rec_data = model_fr.evaluate_precision_recall(validation_data)
10
Время обученияОдин сервер 56 потоков, 256 Гб
Сбор данных из хранилища ~1 часа
Предобработка данных ~30 минут
Обучение модели ~4 часов
11
РесурсыPython: http://www.python.org/ (http://www.python.org/)
IPython: http://ipython.org/ (http://ipython.org/)
Pandas: http://pandas.pydata.org/ (http://pandas.pydata.org/)
Gensim: https://radimrehurek.com/gensim/
(https://radimrehurek.com/gensim/)
GraphLab Create: https://turi.com/products/create/
(https://turi.com/products/create/)
12