深入浅出推荐系统:推荐系统基本架构
Posted 慕阮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入浅出推荐系统:推荐系统基本架构相关的知识,希望对你有一定的参考价值。
提纲
过去八九年在广告、生活服务、电商等领域从事大数据及推荐系统相关工作,近来打算对过去的工作做一个系统性的梳理。一方面帮自己查缺补漏、进行更深入的学习;另一方面也希望能通过博客结交同好,增进交流。
这一博客系列以介绍推荐系统为主,会少量涉及广告系统。本篇文章作为该系列的第一篇,主要对推荐系统、数据框架等进行整体介绍,不涉及过多技术细节问题。
推荐系统简史
在互联网信息爆炸的今天,推荐系统是我们身边一个无法躲避存在。在淘宝上浏览商品,在抖音上刷视频,以及无处不在的小广告…可以说,只要你开始上网冲浪,你就会被推荐系统包围。事实上,大规模推荐系统正是随着信息过载而产生。以新闻场景为例,我们可以将早期的报纸或者杂志看作是一种简易人工推荐系统,它是由编辑来遴选最合适的内容,展现给所有读者。但随着大量用户自主创建内容的产生,依靠有限的人力来筛选推荐并不现实。同时,由于互联网载体的特殊性,不同的人能够看到不同的内容,因此,针对用户进行精准的个性化推荐就成了必需。根据用户以往的兴趣、爱好、行为习惯,为其推荐个性化的视频、商品、广告等,能够极大地增加用户黏性,商品销量和广告转化。
推荐系统在学术上的起源可以追溯到1992年, 美国明尼苏达大学GroupLens研究组推出的GroupLens系统,提出了协同过滤思想。1998年,当贝佐斯发现他们提供了近百万图书时,单纯依靠人力推荐已经不现实了,之后Amazon平台上线了基于物品的协同过滤算法 (ItemCF算法),这一技术机制的革新产生了良好的效果,Amazon销售额号称提高了35%左右,这是推荐算法商业化的一次典范应用。2006年10月,在线DVD租赁公司Netflix举办了一个大奖赛,任务之一要求参赛者在大概包含1亿匿名电影评分数据集上建立一个系统,能够正确预测用户的评分。这一竞赛吸引了大量的研究者加入,极大的促进了推荐系统的发展,提高了推荐系统在学术界和商业界的受关注度。
随着推荐系统的深入发展,目前国内外一般中大型网站都已应用了推荐系统,资讯类如今日头条、小红书;电商类如淘宝、亚马逊、京东等;视频类如抖音、B站、Netflix等;生活服务类如美团、携程等;另外社交类应用也在逐步应用推荐系统进行朋友信息推荐,如微信、Facebook等。不同领域里,推荐的目标并不相同。信息流领域较为关注如留存率、用户满意度、用户时长等指标;电商领域更关注订单量、订单转化率、复购率等;社交领域则比较关注用户活跃度、用户黏性、用户互动比例等;广告领域则更为复杂,在考虑广告点击转化率的同时还要考虑广告竞价策略、预算的限制等。针对不同业务场景,推荐系统的目标设计不尽相同,但有许多通用思路和技术架构可以互相借鉴。
推荐系统本质上是一个过滤系统,是将海量的信息进行逐步过滤,最终为用户(user)在特定场景(context,比如内容上下文是金融财经类,周边环境是夜晚、地铁站附近等)呈现他最可能喜欢的东西(item,比如休闲游戏)。事实上所有的推荐系统都是围绕着用户、场景及物品这三点来做文章。无论是推荐、电商抑或是广告系统,都是在充分利这三点信息的情况下,最大程度地去逼近各自的目标(留存、点击、GMV等)。
推荐系统的架构
由于推荐系统是架构于海量数据之上的,为了保证推荐的实时性和高效性,必须要有一套强有力的技术架构做支撑。其基本结构如下图所示:
我们分数据和计算两部分来介绍系统架构。
数据层
离线数据
离线数据通常是按日存储更新的海量数据,它有两个作用:1、支持模型的离线训练;2、为线上服务提供离线数据(需导入服务友好的数据访问系统);
从用户、场景及item的角度来看,离线数据包括:1、用户相关数据,主要为用户标签数据,包含用户年龄、性别、长短期爱好、常驻地理位置、消费水平等等;2、场景数据:根据不同业务,可能会包含时间、数据来源、访问页面特征、GPS等等,场景数据在线上预估时往往需要实时获取,因此离线场景数据通常仅用来做离线模型训练;3、物品数据,这部分数据基于不同业务有较大差异,以社区消息信息流推荐而言,通常会包括物品id、物品标签、类目属性、发布者相关信息,以及该物品上的用户行为统计性信息,如过去若干天被点赞收藏数量等等;4、交互行为数据,通常是为离线模型准备的样本训练数据,如点击率模型所需要的展现点击数据;多目标模型可能还需要根据业务定制的点赞、收藏、时长等数据。离线作业往往不是一蹴而就,有些离线任务是在为下游离线任务准备中间结果,如文章的分词结果,矩阵分解的中间向量等。它们会作为输入再次在离线任务中流转。
为了获得结构化的上述数据,通常需要线下对数据进行清洗、过滤及存储。如下图所示。
离线处理数据主要使用Hadoop,Spark等技术,数据经过清洗处理后,存入以HDFS为典型代表的离线存储系统,供离线模型读取使用;同时会将其中部分数据导入到Redis、Tair这种线上可实时访问的系统(如用户画标签、物品特征等)用于线上进行实时计算。
离线数据由于对存储要求限制低,可以存储大量精细化特征,从而能支持复杂模型的构建。但是,由于离线的时滞性,使得数据所表达的实时性不强,比如线上用户看了奥运的新闻,接着搜索奥运相关信息,但由于用户的兴趣转瞬即逝,使用前一天的离线数据就无法捕获到当前萌发的兴趣点,也就无法推荐出用户实时感兴趣内容。
因此,近年来随着实时数据处理技术的深入,实时特征及实时模型获得迅猛发展,
近线数据
近线数据,是指时效性较高,但非完全实时化的数据。通常时间间隔在秒级到小时级,因此可以捕获用户及上下文环境近期的变化,包括实时兴趣,地理位置变化等;同时近线数据处理技术的发展也为模型的实时线上更新带来了可能。由于系统可以捕获用户及物品近期特征,因此可以在离线模型基础上,对线上模型进行实时增量更新,以提升模型的时效性。
近线计算从消息队列里订阅数据(如Kafka,MQ,Flume等),对于数据的处理主要使用Storm、Flink、SparkStreaming等技术。其中,SparkStreaming本身还是批处理的方式,是将数据流按照时间单位切分,再通过分布式数据集来进行批量处理,是一种伪实时。相较而言,Storm则是基于单条数据驱动的实时处理系统,而Flink则是基于事件驱动,是面向流的处理系统,因此这二者都是纯实时框架,可达到毫秒级响应。但是,SparkStreaming本身又具有超越其他实时处理系统的高吞吐量、高容错性的优势,因此实时流处理框架的选择要根据业务情况进行取舍,后续的大数据相关博客中我们再进一步详述。
近线数据通常也会存入服务访问友好数据系统,供线上访问。近年来比较火的lambda架构,便是由离线数据计算与近线数据计算共同构成。由离线作业写入存储,再由近线计算增量更新,以完成海量数据的低延迟处理。
实时数据
实时数据主要是指用户在实时访问时拿到的各种数据,如广告系统中广告请求发起时的时间,数据源,页面特征,地理位置等各种因素。这部分数据通常是用于模型的实时预估。推荐模型所依赖的输入特征,不仅取决于用户的离线长期兴趣,也与当前的动态环境有关,实时数据可以提供相关的实时特征。
以信息流推荐系统为例,来看一下实时数据的使用场景。一般来说,实时数据主要来自于实时请求,通过对当下数据的收集及结构化处理,统一装配成业务需要的数据,传入模型,完成模型计算。
请求发起时,系统所收集到的实时数据将会用于模型预估。请求完成后,用户的交互行为会产生新的实时数据。这部分数据会存入系统,最终以近线或离线形式存储下来,用于后续的模型训练,或者是报表展示。
综上,推荐系统所依赖的数据是由离线、近线和实时数据三部分组成。这三部分数据又互相渗透,彼此交互,共同组成推荐系统的数据支持体系。
一个例子
我们以一个例子来看待一个具体的用户行为数据是如何在这个数据系统中流转的。为了更好地展现数据的流转过程,此处不掺入复杂的机器学习算法,仅以用户标签系统来举例说明。假设我们构建的是一个信息流推荐系统,以各类生活化信息为主。今天中午来了一位男用户,他最近买了个大house,准备装修,所以来搜索装修信息。他搜索了“上海 装修”,并查看了装修相关的几篇文章。这样,用户行为记录里便有了如下几条日志:
user_id: a_123; item_id:1100; action: view; ts: 2021-11-30:11:12:30
user_id: a_123; item_id:1111; action: view; ts: 2021-11-30:11:21:11
user_id: a_123; item_id:1111; action: click; ts: 2021-11-30:11:22:13
user_id: a_123; item_id:2221; action: view; ts: 2021-11-30:11:29:22
user_id: a_123; item_id:2221; action: click; ts: 2021-11-30:11:30:02
实际的日志存储更为复杂,通常还会包含如页面特征、点击位置等上下文信息,另外点击日志与展现日志也是分开处理的,为了便于说明,此处进行了简化处理,以kv形式展示,同时仅保留用户id,物品id,行为类型及时间戳。
用户及其所访问的物品,会有其对应的特征数据(一般离线和在线都会存储),如下:
item_id | item_tag | item_class |
---|---|---|
1100 | 上海,装修,欧式 | 生活/装修 |
1111 | 板材,环保 | 电商/装修/板材 |
2221 | 装修,日式,小清新 | 生活/装修 |
事实上,对于物品,除了确定其类目,通过nlp技术提取其关键词外,还可以做更多的处理,提取出更多相关特征,比如:文章主题抽取,知识图谱构建,语义概率模型生成以及用户交互行为类标签,如文章热度、作者被关注度,关联文章id,同类文章等等;从中可以窥探出,数据固然重要,但只有有效地处理和表达数据,才能最大程度地发挥它的价值,这也正是算法的魅力所在。
用户对物品的交互行为,联合物品特征、用户画像等内容,会在离线处理过程中进行规范化继而落盘保存,如下:
user_id | view_item | click | item | item_tag | item_class | user_profile |
---|---|---|---|---|---|---|
a_123 | 1100 | 0 | 1111 | 上海,装修,欧式 | 生活/装修 | 性别:男,地域:上海,爱好:电影:0.9、旅游:0.5 |
a_123 | 1111 | 1 | 1121 | 板材,环保 | 电商/装修/板材 | 性别:男,地域:上海,爱好:电影:0.9、旅游:0.5 |
a_123 | 2221 | 1 | 2221 | 装修,日式,小清新 | 生活/装修 | 性别:男,地域:上海,爱好:电影:0.9、旅游:0.5 |
注意,这里我们加入了该用户的画像,其中电影:0.9是权重系数,表达的是该标签在用户身上的重要程度(一般会根据时间间隔长短和用户行为强度进行计算)。我们将表达用户兴趣的点击文章标签进行处理,将其整合进用户兴趣体系:
user_id | user_profile |
---|---|
a_123 | 性别:男,地域:上海,爱好:电影:0.85、装修/环保:0.8,日式:0.7,旅游:0.3 |
我们可以看到,随着时间的流逝,不同的兴趣权重存在一定程度的增强或减弱。用户画像经过数据交换系统,也会流入Redis,变成实时标签。
此时,我们就对用户有了大概认知,第二天当这个用户再次到来时,就可以基于标签为他推荐“装修”相关的内容了。
这个例子展示了一个用户标签是如何在数据系统里流转,并参与推荐的。对于复杂的机器学习模型乃至深度学习模型来说,虽事殊术异,但其数据处理的框架与思想是完全相类的。只要把握住这个思路,就可以化用到任何推荐业务场景里的任何数据处理模式了。
模型训练
模型训练通常也分成两部分:线下全量训练和线上增量更新。
线下训练
用户多日的行为数据(一般以月为单位,一个月到半年不等)经清洗后,进入模型训练。一般机器学习模型可用spark实现(其本身有强大的机器学习包),深度学习则使用Tensorflow或Pytorch实现。但一般大公司会自研机器学习平台(如阿里的PAI,百度的飞桨等),一般都会提供完善的训练框架,可以支持多种模型的实现和集成,同时可以较方便地支持线上预测部署。
对于召回、排序等不同阶段,需要训练不同的模型,如协同过滤、LR、树模型、深度学习模型等。这些模型可以同时在线上存在(多路召回,或进行AB实验)。
线上更新
离线模型保证了模型的精准性,但由于实时性不强,因此近年来推荐系统一直在往实时化方向演进。实时化包括两方面:特征的实时更新及模型的实时更新,都是通过线上实时增量样本来完成。特征实时更新解决的是如用户线上出现实时兴趣时,为其推荐相关物品的问题,比如用户看了一部侦探电影,那么可以马上为其推荐相关主题(或主演)的电影;实时模型解决的是捕获用户实时行为模式的问题,对于场景商品发生快速变化的情况尤其适用(如电商大促等场景,大量新商品上线的场景),比如热门商品的更新,同好人群最新感兴趣的物品等。
线上推荐
用户端发起一次请求后,线上系统开始运作。海量物品经历召回、粗排序、精排序、重排序这几个环节,最终展现一条(广告)到十几条、几十条信息给用户(信息流推荐)。
从图中可以看出,模型预估虽然是推荐系统中的重中之重,但是真正支撑模型运作起来,需要强大的工程系统。可以说,线上系统是推荐系统中最为复杂的部分,它要承担诸多任务:接收请求,收集实时数据,进行模型预估,将请求结果返回给用户,对于用户反馈进行收集发送给后端,用于实时报表系统及近线数据收集等。
召回阶段是面向全量信息库,检索出用户最可能感兴趣的成百上千条信息。作为线上模型运作的第一步,召回的策略是多种多样的,但核心都是需要保证快速从海量数据中得到一个用户感兴趣的物品集合。想象一下搜索引擎是如何运作“召回”这一步的?用户输入查询词(query),然后搜索引擎去数据库中检索出标题或者内容中带有query的全部记录。推荐场景下没有意向query,推荐引擎该如何做呢?从某种角度讲,没有用户的明确输入,既是好事,也是坏事。好在用户没有限定条件,那么“法无禁止即可行”,算法可以任意发挥想象空间,从各种角度来召回(基于用户历史兴趣、基于用户当下兴趣、基于好友推荐、基于上下文、甚至是基于天气、基于地理位置等等都可以);坏在用户没有表达明确意向,那么召回的结果中可能含有不是特别相关的内容,这个就要靠后续的排序模块来进一步筛选了。
粗排序阶段是将召回的成百上千条信息按照一定指标进行排序(通常包括粗排序和精排序两个阶段),筛选出头部的几条到几十条信息,用于后续展现。粗排序模型主要通过快速排序,将几百上千条的信息进行过滤,剩下几十条给精排序模型,这一阶段的排序要求是要足够快速,精准度要求不高(也有的推荐系统会直接省略这一步)。
精排序模型就是常说的CTR模型,因为早期广告系统强依赖于CTR(点击率)指标,因此预估CTR的高低是排序的重要标准。现如今的无论广告还是信息流排序多考虑综合指标,如广告转化率;信息流的观看时长、点赞收藏率等,因此,多目标排序系统是推荐系统所关注的重要方向。此外,CTR模型从最早的LR(逻辑回归),到树模型(以GBDT为典型代表),再到如今的深度学习模型(如阿里的DIN,MIND等),也在逐渐往精深方向演进。
重排序阶段主要根据实际业务对信息进行重新排序,如广告会考虑竞价因素,信息流会考虑运营、新颖度、惊喜度等因素,此外,还包括对新上线信息的保护机制,以及一些运营逻辑的加入等一系列业务因素,都会在重排序阶段里进行综合考虑。
AB实验
AB实验是广告推荐领域里一个老生常谈的问题。试想对于快消品类,比如宝洁打算新研发一款洗发水,但是不确定柠檬味儿还是香草味儿会更受欢迎,它会怎么做?它可能让一小群用户去同时尝试两种气味的产品,然后告知他们更喜欢哪种;它也可以把这群用户分成两组,每组尝试一种气味的产品,然后比较两组的接受率。显然第一种方案更好,因为它基于同样的用户群,比较更为公平。
推荐系统能否在同一批用户上进行两种不同的实验呢?试想这样一个场景,一个用户近期打算旅游,并通过搜索表达了兴趣,但是当他去看信息流推荐时,一会儿看到的都是旅游相关的信息,一会儿又看到都是游戏相关的信息(可能是基于他既往兴趣);或者更有甚者,对于前端样式的实验,用户一会儿看到的都是图文,一会儿看到的都是视频,用户的感受更多的是惊喜还是惊吓?可以想见,这样的实验会极大程度地削弱用户的把控感,从而带来糟糕的体验。因此,为了保持用户体验的一致性,一般来说AB实验会在同一时段内针对不同用户群进行。
除了上述原因外,这种设计其实也体现了一种哲学思想,即“人不能两次踏进同一条河流”,针对同一用户的两次不同推荐,因为时间、场景、用户心理等发生变化,其实也是不能完全公平比较的。那么对于两批不同用户,在时间等其他因素尽量控制的情况下,只要用户样本量足够,筛选足够随机,其实验效果反倒是较可信的。
AB实验框架最早来自于谷歌的研究,主要针对广告效果而进行的实验分流。通常情况下,一个新模型在上线之初会先选取少量的人群进行AB实验(一般5%-10%),当实验效果足够好且足够稳定,为了保证实验效果并非是由于小样本波动所带来的,之后可以将流量进行扩大观察,直至最后将其部署在全量人群上为止(通常情况下,还会保留一小部分基线实验来进行长期对比观察)。上图展示了一个召回服务层上的分流实验,可以看到,这个服务在同时进行两个实验,分别在实验一中增加了模型四,及实验二中增加了模型五,后续实验效果会与同样流量比例的基础实验进行指标比较。至于如何设计实验分流,以及如何能最大限度地复用现有流量,同时进行多个不同的分层实验,这个问题我们以后再展开讨论。
推荐系统的演进
随着推荐系统所依赖的周边资源逐步发展,推荐系统近十年来也经历了不小的变化。计算架构上,从离线计算到模型和特征的实时在线更新;模型上,则从早期的逻辑回归到如今的大规模深度学习。如今,以图学习和强化学习为方向的研究正引领推荐系统的潮流。技术的价值在于能够为业务而服务,而业务所遇到的瓶颈会反过来推动技术进一步发展,如今,在线旅游、外卖、社群、线下买菜等业务也在逐渐被推荐系统入侵,可以想见,未来随着业务场景的更加多样化,推荐技术也一定会出现新的改变。
参考文献:
【1】超详细:完整的推荐系统架构设计 https://xie.infoq.cn/article/e1db36aecf60b4da29f56eeb4
推荐系统基础-纪要
推荐系统纪要
7天 基础
- 推荐系统相关概念 基本算法
- 推荐算法
- 原生python 实现推荐算法
- lambda架构 5天
- hadoop
- hive hbase
- spark core
- spark sql spark streaming
- 案例 基于电商用户行为
7天 项目
推荐概念
- 信息过滤系统 解决 信息过载 用户需求不明确的问题
- 利用一定的规则将物品排序 展示给需求不明确的用户
- 推荐 搜索区别
- 推荐个性化较强,用户被动的接受,希望能够提供持续的服务
- 搜索个性化弱,用户主动搜索,快速满足用户的需求
- 推荐和 web项目区别
- 构建稳定的信息流通通道
- 推荐 信息过滤系统
- web 对结果有明确预期
- 推荐 结果是概率问题
Lambda 架构介绍
- 离线计算和实时计算共同提供服务的问题
- 离线计算优缺点
- 优点 能够处理的数据量可以很大 比如pb级别
- 缺点 速度比较慢 分钟级别的延迟
- 实时计算
- 优点 响应快 来一条数据处理一条 ms级别响应
- 缺点 处理的数据量小一些
- 离线计算的框架
- hadoop hdfs mapreduce
- spark core , spark sql
- hive
- 实时计算框架
- spark streaming
- storm
- flink
- 消息中间件
- flume 日志采集系统
- kafka 消息队列
- 存储相关
- hbase nosql数据库
- hive sql操作hdfs数据
推荐算法架构
-
召回
-
协同过滤 算相似度 memory base
基于模型的 model base 矩阵分解
-
基于内容
- 分词
- 词权重(提取关键词) tf-idf
- word2Vec 词向量
- 物品向量
-
-
排序
- 逻辑回归
-
策略调整
推荐模型构建流程
-
数据收集
- 显性评分
- 隐性数据
-
特征工程
- 协同过滤:用户-物品 评分矩阵
- 基于内容:分词 tf-idf word2Vec
-
训练模型
- 协同过滤
- kNN
- 矩阵分解 梯度下降 ALS
- 协同过滤
-
评估、模型上线
协同过滤思路介绍
- CF 物以类聚人以群分
- 做协同过滤的话 首先特征工程把 用户-物品的评分矩阵创建出来
- 基于用户的协同过滤
- 给用户A 找到最相似的N个用户
- N个用户消费过哪些物品
- N个用户消费过的物品中-A用户消费过的就是推荐结果
- 基于物品的协同过滤
- 给物品A 找到最相似的N个物品
- A用户消费记录 找到这些物品的相似物品
- 从这些相似物品先去重-A用户消费过的就是推荐结果
相似度计算
- 余弦相似度、皮尔逊相关系数
- 向量的夹角余弦值
- 皮尔逊会对向量的每一个分量做中心化
- 余弦只考虑方向 不考虑向量长度
- 如果评分数据是连续的数值比较适合中余弦、皮尔逊计算相似度
- 杰卡德相似度
- 交集/并集
- 计算评分是0 1 布尔值的相似度
使用不同相似度计算方式实现协同过滤
-
如果 买/没买 点/没点数据 0/1 适合使用杰卡德相似度
- from sklearn.metrics import jaccard_similarity_score
- jaccard_similarity_score(df[‘Item A’],df[‘Item B’])
- from sklearn.metrics.pairwise import pairwise_distances
- user_similar = 1-pairwise_distances(df,metric=‘jaccard’)
-
一般用评分去做协同过滤 推荐使用皮尔逊相关系数
-
评分预测
-
p r e d ( u , i ) = r ^ u i = ∑ v ∈ U s i m ( u , v ) ∗ r v i ∑ v ∈ U ∣ s i m ( u , v ) ∣ pred(u,i)=\\hat{r}_{ui}=\\cfrac{\\sum_{v\\in U}sim(u,v)*r_{vi}}{\\sum_{v\\in U}|sim(u,v)|} pred(u,i)=r^ui=∑v∈U∣sim(u,v)∣∑v∈Usim(u,v)∗rvi
-
-
基于用户和基于物品的协同过滤 严格上说,属于两种算法,实践中可以都做出来,对比效果,选择最靠谱的
协同过滤 基于模型的算法
- 用户-物品矩阵比较稀疏的时候 直接去取物品向量 用户向量计算相似度 不太适合
- 基于模型的方法可以解决用户-物品矩阵比较稀疏的问题
- 矩阵分解
- 把大的矩阵拆成两个小的 用户矩阵 物品矩阵 MXN 大矩阵 M X K K X N K<<M k<<N
- 大矩阵 约等于 用户矩阵 乘 物品矩阵
- 使用als 交替最小二乘法来优化损失 spark ML recommandation 包封装了als
- 优化之后的用户矩阵 取出用户向量
- 优化之后的物品矩阵 取出物品向量
- 用户向量点乘物品向量 得到最终评分的预测
推荐系统的评价
-
准确率 覆盖率
- 准确率
- 学术 rmse mas 点击率预估 精准率
- 工程 A/B test 对比不同的算法 在线上运行对关键指标的影响
- baseline 基准线 热门排行
- 灰度发布
- 准确率
-
EE
- Exploitation & Exploration 探索与利用问题
- Exploitation 利用用户的历史行为 只给他曾经看过的/消费过的相似物品
- Exploration(探测 搜索) 发现用户的新兴趣
- ee问题 实际上是矛盾
-
评估手段
- 离线评估和在线评估结合, 定期做问卷调查
- 在线评估
- 灰度发布 & A/B测试
- 在线评估
- 离线评估和在线评估结合, 定期做问卷调查
推荐系统的冷启动
- 用户冷启动
- 尽可能收集用户信息 构建用户画像(打标签)
- 根据用户的标签可以做人群聚类 用以有用户的行为做推荐
- 更多的使用流行度推荐
- 物品冷启动
- 物品打标签 构建物品画像
- 基于内容的推荐
- 系统冷启动
- 如果应用缺少用户行为数据->基于内容的推荐
- 随着用户行为积累的越来越多->协同过滤
- 基于内容和协同过滤共同工作
基于内容的推荐
- 给物品打标签
- 系统自己提取从业务数据库中提取
- 用户填写
- 中文分词 利用算法计算词的权重
- tf-idf tf term frequency 词频 5/100 *2
- idf 逆文档频率 log 10 文本库篇数/出现关键词的文章篇数
- 1000 10python 1000/10 100 2
- 1000/1000 log(1) = 0
- textrank
- tf-idf tf term frequency 词频 5/100 *2
- 利用标签的文字 转换成词向量
- word2Vec 词->向量
- 用向量来表示语义
- 如果两个词的词向量相似度比较高 认为这两个词的语义相近
- 利用词向量 构建物品的向量
- 一个物品有N个关键词 每一个关键词对应一个词向量
- 求和(权重*词向量)/N
- 利用N个关键词的词向量获取物品向量
- 通过物品向量计算相似度
- 皮尔逊 相关系数 计算物品向量的相似度
基于内容的推荐 基于物品的协同过滤 区别
-
content_base :词向量->物品向量->计算相似度
-
item_based cf :user-item matrix->物品向量->相似度
-
content_base item_based cf 不一样
- 物品向量构建过程有区别
- 基于内容的推荐
- 物品向量 文本(物品描述信息,系统填标签,用户填标签)
- 基于物品的协同过滤
- 用户对物品的评分矩阵 用户的行为数据中来
-
baseline思想来解决协同过滤的问题
-
计算出所有用户对所有物品评分的平均值
-
预测的评分= 在平均值的基础上 + 用户评分偏置 +物品的评分偏置
-
求解所有用户的评分偏置 和 所有物品的得分偏置
-
这个问题可以转换成损失优化的过程
-
-
梯度下降
-
交替最小二乘法
矩阵分解
- SVD 奇异值分解
- 一个大矩阵 分成3个小矩阵 中间的是一个k方阵
- SVD只适用于没有缺失 必须是稠密矩阵
- Funk SVD
- 一个大的 分成两个小矩阵
- LFM 原理
- BiasSVD 矩阵分解+baseline
- SVD++ 矩阵分解+baseline+其它影响(点击,收藏,购买)
基于内容的推荐
- 画像构建 给用户/物品打标签
- 物品画像
- 分类信息
- 标题
- 电影/音乐 主演、歌手
- 用户画像
- 喜好的物品类别 行为偏好
- 基本人口学属性
- 活跃程度
- 风控纬度
- 物品画像
- PGC 应用自己生成
- UGC 用户来生成
- 基于内容推荐的算法流程
- 用户画像/物品画像
- 匹配用户画像 物品画像
- 物品冷启动问题
- 画像->词向量->物品向量->计算物品相似度了
- 从文本描述的角度找相似的物品
- 当用户在浏览A的时候 通过上述套路找到跟物品A相似的一系列物品
基于内容推荐流程
① 建立物品画像
- ①用户打tag ②电影的分类值
- 根据电影的id 把tag和分类值合并起来 求tf-idf
- 根据tf-idf的结果 为每一部电影筛选出 top-n(tf-idf比较大的)个关键词
- 电影id-关键词-关键词权重
② 建立倒排索引
- 通过关键词找到电影
- 遍历 电影id-关键词-关键词权重 数据, 读取每一个关键词,用关键词作为key [(关键词对应的电影id,tfidf)] 作为value 保存到dict当中
③ 用户画像
- 看用户看过那些电影, 到电影的 电影id-关键词-关键词权重 数据中 找到电影所对应的关键词
- 把用户看过的所有的关键词放到一起 统计词频 每个词出现了几次
- 出现次数多的关键词 作为用户的兴趣词,这个兴趣词实际上就是用户画像的关键词
④ 根据用户的兴趣词 找到兴趣词对应的电影 多个兴趣词可能对应一个电影 {电影id:[关键词1权重,关键词2权重]}
- 把每一个部电影对应的关键词权重求和之后 排序 权重比较高的排在前面 推荐给用户
词向量
-
用向量来表示词语 可以表示语义层面的含义
-
如果用word2vec模型创建的词向量, 两个词向量相似度比较高,说明这两个词是近义词
-
词向量作用 把含义相近的判断转换成 向量的相似度计算
-
使用 gensim Word2Vec模块训练词向量模型
import gensim
#准备所有用来训练词向量模型的文本内容
sentences = list(movie_profile["profile"].values)
# 参数1 文本 参数2 window 观察上下文关系的窗口长度
# min_count 训练模型时要保留下的词语出现的频率 iter=20 迭代20词
model = gensim.models.Word2Vec(sentences, window=3, min_count=1, iter=20)
-
通过词向量模型找到topn相似词
model.wv.most_similar(positive=['要找到相似的词的词语'], topn=10)
-
文档向量
from gensim.models.doc2vec import Doc2Vec,TaggedDocument
documents = [TaggedDocument(words, [movie_id]) for movie_id, words in movie_profile["profile"].iteritems()]
# 训练模型并保存 Doc2Vec 通过向量来表示一篇文档 一篇文档就对应一个电影
#向量的相似度 代表了电影额相似程度
model = Doc2Vec(documents, vector_size=100, window=3, min_count=1, workers=4, epochs=20)
words = movie_profile["profile"].loc[6]
inferred_vector = model.infer_vector(words) #传入电影的标签 找到电影文档所对应的向量
# 通过docvecs找到传入的向量最相似的n个向量 每一个向量代表了一个电影
sims = model.docvecs.most_similar([inferred_vector], topn=10)
加油!
感谢!
努力!
以上是关于深入浅出推荐系统:推荐系统基本架构的主要内容,如果未能解决你的问题,请参考以下文章