Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

"Построение рекомендательной системы на Python" Василий Лексин (Avito)

1,256 views

Published on

В своём докладе ведущий аналитик Avito Василий Лексин поделится опытом построения рекомендательной системы для всех general категорий. Из рассказа вы узнаете, как создать такую систему с нуля, в том числе: как подготовить данные, обучить модель и сгенерировать рекомендации.
Python Data Science meetup @ Avito 13.08.2016

Published in: Technology

"Построение рекомендательной системы на Python" Василий Лексин (Avito)

  1. 1.   Построение рекомендательной системы на Python Python Data Science meetup @ Avito Лексин Василий 13 августа 2016 г. 0
  2. 2.   План презентации Выгрузка данных Типы данных Выгрузка данных из хранилища Предобработка данных Фильтрация данных Предобработка поисковых запросов Обучение модели Параметры модели и обучение Оценка качества модели 1
  3. 3.   Типы данных Данные по пользователям Профиль интересов по категориям и регион Согласен ли получать рекомендации Данные по объявлениям Микрокатегория Местоположение Действия пользователей Items search, item view Item view phone, item send message Favorites item add 2
  4. 4.   Выгрузка данных из хранилища (SQL) Один месяц click stream Фильтруем офисные IP Фильтруем ботов (ноу хау) Только посление сессии от каждого пользователя От каждой сессии берем максимум случайных событий каждого типа Привязываем действия от неавторизованных пользователей к user_id Отдельно выгружаем поисковые запросы Ns Ne 2 - 1
  5. 5.   Статистика по выгруженным данным 853M событий 13M пользователей 32M объявлений 77M поисковых запросов 4M уникальных текстов запросов 2 - 2
  6. 6.   Постановка задачи рекомендаций Для максимально большого сегмента активных пользователей отобрать по top N объявлений, которые пользователя наиболее вероятно заинтересуют. 3
  7. 7.   Пример поисковых запросов 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
  8. 8.   Пример текстов запросов 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
  9. 9.   Пример лога событий 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
  10. 10.   Нормализация текста In [ ]: In [ ]: from nltk.corpus import stopwords as sw import pymorphy2 import re stopwords= 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
  11. 11.   Параллельная обработка 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
  12. 12.   Биграммы, фильтрация In [2]: In [25]: In [78]: ... ... ... from gensim.models.phrases import Phrases from 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
  13. 13.   Пример нормализованных запросов 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
  14. 14.   Комбинация запроса с микрокатегорией 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
  15. 15.   Признаки пользователя 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
  16. 16.   Фильтрация лога событий In [ ]: import graphlab as gl # Generate bipartite user-item graph g = 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 graph kc = gl.kcore.create(g, kmin=k_value-1, kmax=k_value) # Filtering events training_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
  17. 17.   Factorization Machine - общая идея 9
  18. 18.   Factorization Machine - генеративная модель - пользователь - объявление - global bias term и - weight terms и - side feature vectors и - weight vectors for side features и - latent factors p(i, j) = μ + + + + + ,wi wj a T xi b T yj u T i vj i j μ wi wj xi yj a b ui vj 9 - 1
  19. 19.   Обучение модели 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
  20. 20.   Оценка качества модели In [77]: cutoff precision recall 1 0.022 0.008 2 0.018 0.010 3 0.016 0.012 5 0.014 0.019 10 0.011 0.029 ... prec_rec_data = model_fr.evaluate_precision_recall(validation_data) 10
  21. 21.   Время обучения Один сервер 56 потоков, 256 Гб Сбор данных из хранилища ~1 часа Предобработка данных ~30 минут Обучение модели ~4 часов 11
  22. 22.   Ресурсы 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

×