你还在用用户画像和协同过滤做推荐系统吗
周开拓 大数据杂谈

推荐系统的本质是什么?


比如说我们看到手机淘宝首页,往下一拉,就能看到各种各样推荐的商品;比如说百度,它会给我们推荐广告,在某种程度上他的工作方式也很像推荐系统;再比如说今日头条,今日头条从数十万的新闻中选出会被我们看到的数十个新闻,这也是推荐系统。

尽管我们在生活中会已经见过非常多的推荐系统,但是在用机器学习搭建推荐系统之前,我们还是应当先思考一下,推荐系统要解决的到底是个什么样的问题?

推荐系统在本质上是一个信息检索的系统。它和搜索最大的区别是,搜索是主动式的,根据关键词和引擎参数、搜索引擎召回、机器学习排序,决定给你看到的是哪些内容。而我们看到的推荐系统,在大多数情况下是没有主动输入的(有时会有一些简单的反馈动作),是被动出现的。

推荐系统是利用上下文,根据当前用户所处的环境,根据信息的特点来决定给你推荐什么内容和商品。而在我们进一步去想之前,我们要问自己一个问题,就像上节课田老师讲的一样,推荐系统的目标是什么,什么才是一个好的推荐系统,要优化的指标是什么。


推荐系统的指标是什么?


推荐系统是个产品,产品当然是想方设法让用户去喜欢的,或者至少是不讨厌的。因而,我们需要把喜欢和讨厌这两件事情定义出来。同时我们毕竟不是用户肚子里的蛔虫,我们只能用我们可以测量到的数据来描述喜欢和讨厌两件事情。并用这些数据来决定我们做什么和不做什么。

比如说:我是个电商,用户表达对一个推荐商品喜欢的方式是:点击、收藏、加购物车、甚至购买下单、分享到社交平台上等等。用户讨厌一个推荐商品的方式,就是会投诉、会提意见。因而我们要预防一些很可能会让用户讨厌的推荐结果:比如说推荐成人用品和内衣,尤其是在上班时间;比如推荐用户刚刚买过的商品,等等。

我们一定能为一个推荐系统去定义指标,我们可以给这些指标分轻重缓急,看能用什么顺序实现。现在我用的指标可能有点投机取巧,我用的是点击率。而真实的指标考虑的是很多的,仅仅考虑点击率的模型,可能会出现标题党,如果是电商就可能会出现一堆 9 块 9 包邮,这可能不是我们业务想要的。

另外即使只考虑点击率,我们也知道其实我们推荐的是一个列表,列表的质量不完全是由单一的商品决定的,而是整个列表的组合、顺序、多样性所决定的。所以真实的业务中,我们会考虑用更复杂的目标,比如 MAP 来评价一个推荐列表的质量。

但没关系,今天我们就用点击率作为试点,介绍如何用机器学习来搭建推荐系统的完整过程。


推荐系统的 y 和 x


第一步, 我们已经知道机器学习模型需要预测的就是优化目标,点击率;那我们把用户的点击行为需要记录下来。这样一来,对于机器学习来说,我们已经有 y 了

第二步,我们需要定义好 x,也就是特征。

一般来说推荐系统的特征体系由 3 个部分组成:用户特征、内容特征、上下文特征。

用户特征:包括但不限于用户姓名、性别、年龄、注册时间、收货地址、常用区域等用户特征

内容特征:包括但不限于以及商品、内容的标题分词、内容的 TF-IDF、内容来源、内容渠道、内容生产者等等

那么上下文特征, 是代表用户当前时空状态、最近一段时间的行为抽象的特征。比如说用户当前的 GPS 坐标,大家可能觉得奇怪, GPS 坐标怎么用来推荐呢?其实很简单,地球一圈是 4 万公里,GPS 一圈是 360°,一度大概是 100 公开。如果我们把 GPS 坐标保存到小数点后一位,组合起来,这样的特征就是 10*10 公里的格子,这就代表了一个有泛化能力的用户的位置。

位置是一个非常强的特征,如果我们更进一步,做到了 1 公里,显然我们可以相信,在中关村地区,大家的偏好是有共性的,而在金融街,大家的喜好也是有共性的。当大家的数据足够多的时候,落在同一个格子里的人会非常多,GPS 就会成为非常重要的特征。

另外是 IP 地址,比如最近浏览的内容、最近购买的商品,这些都会构成上下文特征。所以我们就是在用户特征、内容特征和上下文特征的基础上,预测用户对当前内容的点击率。


推荐系统的样本构造和数据拼接


一个成熟的推荐系统,它可能有非常复杂的样本构造方法,今天用了比较简单的方法,让问题变得简单。另外,一个成熟的推荐系统,它可能会有多个指标和业务边界条件。

那么接下来:基于已知的 x 和 y,我们要为机器学习构造样本。什么是一条样本?一个样本代表机器学习预测的一个最小粒度的事件。当你把一条内容展现给用户,用户点击或不点击,这就代表了一个最小粒度的事件,就是一条样本。再比如说我们给用户展示了 10 条新闻,用户对应每个新闻点击或者不点击,就是 10 条样本。

在样本采集后,就要考虑数据怎么收集和拼接了。在拼接的时候要注意的是,假如是为了优化点击率,我不光要把用户特征、上下文特征收集起来,我还要把点击率拼回到当时那一条样本请求上去。所以系统一定要有这样的考虑,记录下时间和拼接的 ID ,同时还要考虑刚才说的三类特征是处于实时变化当中的,日志也是实时产生的,而不是后面去拿的,因为这样做很可能会出现问题。 数据一旦出问题,是非常难以 debug 的。给大家举个栗子,有一家公司,BAT 之一,他的推荐系统过去几年 85% 的效果提升来源是把之前有问题的数据给修复了,做对了。


推荐系统的场景思考


样本构造还需要考虑场景的问题,比如说我们会遇到一个问题,屏幕的大小是不一样的,同样展示 10 条新闻,我怎么知道用户有没有看到它。如果没有看到就不应该作为一条样本。这时候就有两种解决方案,第一种解决方案是把用户真正看到的纳入进来,因为前端是你设计的,所以你会知道哪些内容是用户的可见范围内。 当然这会让客户端变得更重一些。

第二种是一个比较简单的方法,把内容的位置作为一个特征。因为我们知道,同样是一屏幕展现 10 行内容,即便是一样的内容,用户也会选择一个他舒服的位置去点,这个可能是偏中上的位置。所以当新闻在第三个位置被点击的时候,这可能是一个容易被点击的位置,但不一定代表这个新闻比其他新闻要好。那我们怎么办?我们就要通过某些手段,把这些偏置吸收掉,所以我们会把位置、屏幕大小等作为特征,通过特征工程的方法来吸收这个偏差,变成无偏的模型。

这时候有些人可能会问,这不是穿越吗?因为在给出预测的时候,是不知道内容最终的位置信息的。但这相当于把偏差的锅由位置来背了,这是机器学习推荐系统中的一个策略。

刚才我们已经构造好特征了,现在给大家讲怎么建模。大家可能会认为,前面的部分是快的,真正做机器学习,做特征工程、模型调参等,这些是慢的。但是今天我们会看到,在成熟的工业界里面,其实前面要花的时间会多很多,后面的内容在成熟的工具下会变得简单。


在先知上完成推荐系统的建模流程


我们会从一个真实的案例出发,虽然我们做了很多的推荐系统的案例,但毕竟不能把客户的数据给大家看,所以我们用了一份公开的数据,这份数据和我们之前讲的场景是相似的。这份数据来自于 Kaggle,叫做 Criteo 点击率预估比赛。


 数据预览


首先我们看数据的样子,第 1 列 col_1 代表的是广告有没有被点击,1 代表被点击,0 代表没有被点击。然后我们看第 2 列到第 14 列,都是数值型的特征,因为这份数据已经被匿名化了,所以我们可能也不知道这些数值代表什么意思,也许是这个用户的 PV,或者标签的权重,不过我们也不需要知道。然后看第 15 列到 40 多列,这些都是离散的特征,这些特征都做了哈希化,都做了匿名处理。


image.png


这个数据有 3000 万行 40 多列,按照我们传统的做法,进行特征工程以及 one-hot 编码后,会有 4000 多万个特征。真实的业务数据中,训练数据体积会更大,往往达到上亿,同时原始特征数量会达到上百,因为为了好的个性化效果,我们会使用诸如 GPS 坐标、手机型号、ip 地址、最近浏览内容等等精细化的特征,并进行非常极致的特征工程,这样的模型在特征工程之后的特征数会达到数亿甚至几百亿。这样规模的机器学习训练,挑战的不仅是算法,更是如何在成本可承受的计算资源上进行训练和实时预估。

开发这样一个规模的可以并行运行的系统的挑战更加大,即使 BAT 这样的大公司也会养一个百人的团队,只为了做好机器学习模型训练和预估的工程实现。下面我们会看到利用第四范式的先知平台去做这件事情,会大大降低我们开发和运维一个在线机器学习系统的成本,让我们更加聚焦在业务本身。下面我们会看到在先知平台上对这份数据的建模会非常简单。


 数据拆分


首先我们把这份数据拆成了训练集和测试集,以 9:1 的方式。当然这可能是不太合适的拆分方法,因为真正训练一个机器学习模型,它的拆分是按照时间排序后再拆的,就是用前面的时间来训练模型,然后用这个模型来预测点击。这样训练和测试在时间上是正交的,那么模型如果在这种实验设计下有好的效果,这个效果就会有时间平移性,上线后就会有好的效果。当然,为什么我们在这里没有使用按照时间排序拆分的方式,是因为参考了一篇论文的做法(https://arxiv.org/abs/1703.04247),这样同样的做法结果可比。在真实的业务中,不建议大家按照这种方式来处理数据。


 特征工程、模型选择和评估


然后就是做特征工程了,一般来说大家可能觉得很难,但只需要告诉电脑哪个是 Label,其他的直接默认配置就好了。但天下没有免费的午餐,特征简单处理,我们要有更强的模型,所以我们用了线性分型分类器。


image.png


一般来说,推荐系统中会有离散特征和连续特征,当我们用逻辑回归这种宽的离散线性模型的时候,我就会遇到一个很大的问题,就是我需要对特征进行分段,这样才能学到连续特征的非线性结构。比如说用户年龄对点击率的影响,它并不是线性上升的,它可能会上升到 30 岁,然后就下降了,甚至有更复杂的模式,这些是非线性的特性。所以我们可以用机器对连续的特征做自动搜索分段,这样的预处理效率就大大提高了。线性分形分类器就是做的这样的事情,基本上我花了不到 5 分钟,就跑出了 0.796 的 AUC。


image.png


AUC 代表了一个模型对样本的排序能力。如果这是一个完美的排序,点击率高的 100% 排到了点击率低的前面,那 AUC 就是 1。如果是随机瞎排,那 AUC 就是 0.5。所以 AUC 越接近于 1,就代表了整体的排序能力越强。现在的 AUC 是 0.796,比论文的 0.801 稍微差一点,我只做了这么点就到了这个成绩,我觉得还是可以的。

当然这里进一步说一下,评估上线的时候,不能只是看 AUC。例如说,我要看的是 User AUC,或者每一刷的 AUC,因为模型的排序能力,一部分来自于对每个用户个性化的识别能力,另一部分来自于对用户本身的识别能力。比如说有些用户就是什么都爱点,什么都点,而有些用户基本只看标题不点开。我们把这样的人分开,对个性化推荐是有帮助的。所以我最终应该看的是,在每一个用户身上的 AUC,甚至是每一次展现的 AUC,当然先知也提供了工具,就不多赘述了。特征组合

但我还是想让这个模型更好,怎么办呢?在做推荐系统的时候,特征工程最重要的处理方法是特征组合。比如说有两个特征,一个是性别,另一个是新闻的色情等级。我们可能会注意到,男同志比较喜欢火爆的新闻,女同志可能正好相反。我把色情等级作为一个特征,可能两边的喜好不同导致最终这个特征整体对点击率的影响和一个随机数一样,它就不是好的特征,没有预测能力。

但如果我把这些特征组合起来,我就对这些空间有更细致的分割能力,我就会做出很好的效果。性别、用户 ID 和新闻色情等级组合起来,是新闻推荐非常有用的特征。进一步说,假如我们有 100 个特征,那么特征两两组合的空间,就是 一万个,这是个很大的工作量。

传统的手段是,通过业务经验和实验去筛选好的组合。但是工具可以帮我们做得更快更好,先知的 FeatureGo 功能,可以通过一系列的配置和优化目标设定,自动搜索出好的特征组合,大大节省我们的工作时间,让人的工作由机器来完成。然后我就跑了 FeatureGo,找到了 18 和 28,33 和 34 这些组合特征就不错。而如果计算资源足够,那你还可以搜索 3 阶的特征,这是由人来做非常难的事情。


image.png


在用机器完成自动特征组合后,调参其实也可以自动化的。我们知道机器学习就像炼丹,炼丹就是调参,调参就是在参数空间里,根据我们的经验去搜索一下,看什么参数是好的。我们也有好的工具,可以自动搜索到好的参数。当把这些设定好之后,我就去睡觉了。第二天醒来后发现,这个模型的 AUC 达到了 0.802,已经超过了论文的效果。由于这篇论文还是今年比较有名的论文,我还是很满意的。



image.png


 模型上线


设计好模型后,一般是用 Restful API 的模式服务的。比方说根据这个 API,就可以给不同的内容进行打分,打分后根据倒排后的结果,响应推荐的内容。

image.png

推荐系统相关组件


当然,一个完整的推荐系统,不仅仅需要机器学习排序,还需要相应的组件。比方说我要有物料库,把商品的特征维护起来,这需要一个高性能的缓存和数据库,能够增删查改,能够进行特征的初步生成。我还需要一个日志系统,日志系统通过唯一性的标识,把实时的请求和后续的反馈 Label 记录并拼接起来。我还需要一个自学习的系统,机器学习的模型每天都是要更新的,如果拿 7 天前学到的模型去推今天的商品,那岂不是用前朝的剑斩本朝的官,效果一定不好,所以我们还需要自学习,或者是增量的在线学习,来保证模型捕捉到最新的用户偏好和市场情况。

然后我们还需要后续的预测,比方说我的内容有好几十万,我并不是拿好几十万给机器学习去预估,我会用启发式的方法,比如说 CF、热度、Tag 匹配等召回策略先生成候选集,然后才进入到机器学习排序。召回策略同样使得我们有更大的能力去影响机器学习排序的结果,比如我们可以过滤掉一些我们明知道不好的内容或者增加我们认为好的内容的权重或出现比例。在机器学习排序后,我们也需要对结果进行去重、多样化和随机化,最后才做成一个好的推荐系统。

今天和大家介绍的是,我们如何利用机器学习去搭建一个推荐系统的排序环节。总结起来是这么几个点:第一个是如何使用机器学习来剖析一个问题,我们用了推荐系统的例子。第二个是我们如何构造一个推荐系统的样本、数据并进行建模,当我们有一个非常好的机器学习工具的时候,我们可以把精力聚焦在业务上,在怎么找到好的数据上,以及在怎么定义好的目标和规划上。第三我们描述了机器学习系统是如何和其他系统发挥作用的,机器学习就像发动机,汽车当然需要发动机,但只有发动机车是跑不起来的,你还需要周边的配件,这是系统化的工程。在这方面我们已经做了一些工作,我们既有发动机,也就是先知平台,大家可以在这里试用 https://prophet.4paradigm.com,我们也有整车,就是整个推荐系统的解决方案。我们很高兴和大家分享这样的技术和能力,谢谢大家。


答疑环节


Q1: 针对制造业,有哪些已经比较好的案例可以帮助客户改进运营,质量或生产的。Kaggle 上有没有案例可以参考学习?

周开拓: 制造业,有很多的问题都很适合机器学习去解决。比如说所有的制造业企业成本很大一部分来自于库存和物流。是否可以利用企业的大量数据,来预测到分地区、分时间的销量。如果你预测的准,就可以大大降低企业的成本,优化他们的运营。我忘了 kaggle 哪个具体的比赛了,但是你在 kaggle 上搜索 inventory 应该可以找到。

Q2: 推荐系统,都有哪些方案解决冷启动问题,百万级用户的推荐系统,一般用什么样的框架

周开拓: 推荐系统冷启动是个很大的话题,可能这里只能给大家一些简单的例子。冷启动分为用户的冷启动和整个推荐系统的冷启动,整个推荐系统的冷启动就是在搭建推荐系统之前,我能否已经收集了一些用户行为的数据,如果有的话,可以构造一些弱一点的模型,比如说用 CF、SVD、热度这样的方法对内容做一些初步的排序和筛选,同时配合一些简单的基于 query 的策略,比如最新、最热、最多评价等等先构造一个差一点但是比随机强很多的推荐列表。如果数据基础更好,也可以用其他场景的数据来构造 label、样本来进行建模。而用户的冷启动,归根结底就是在用户进入产品之后,尽快有效地获取他的信息,一方面可以通过产品的手段来实现,一方面可以通过第三方数据合作的方式来实现,比如说这个人如果是微博注册的话,如果你能够收集到一些公开的微博数据,就会对冷启动很有帮助。关于架构的话,刚才已经介绍很多了,您可以参考。

Q3: 讲解中提到对连续特征分段,比如用户年龄对点击率的影响,是否可以详细解释下呢,技术原理和方法?

周开拓: 就是如果年龄是一个你可以取到的特征,那么我们这个模型就应该能描述年龄对于点击率的影响。如果你直接把年龄作为特征,那么对于线性模型来说只能够学习到线性的关系。所以你会把年龄分段,就是你认为年龄 =18 岁有 w1 的影响,年龄 =19 岁有 w2 的影响,以此类推。而分段怎么分,会决定你的这个特征是否能够有很好的预测能力。这通过我们的线性分形分类器可以得到很好的解决。

Q4: 样本采集过后是怎么来发现有问题的数据呢?另外数据修复的措施有些什么呢?

周开拓: 那首先看是什么问题,先看看问题的原因是什么?比如说举个栗子,你发现点击率突然异常地高,那你应该想想是日志系统挂掉了,还是因为有爬虫在攻击你们的产品。你找到问题产生的原因以后,再想想这个问题对你的推荐系统影响的程度,因为问题很多,不是每个都能够马上解决。有时候,数据根本无法修复,这是本身业务形态导致的数据系统性偏差,你可以用模型或者构造更精妙的特征的方法来解决他。

Q5: 老师刚才讲到因为修复了数据问题而提升了 85% 的准确性,请问数据都是有那些问题需要我们注意?

周开拓: 数据首先要注意的就是,用于训练和预测的是两条数据流,这两条数据流是不是一致的,因为只要是人开发的系统,即使你自己重新写两遍,因为上下游依赖的种种东西,它就可能不一致,就可能出毛病。这是最重要的,一致性的问题是最重要的。另外你用于训练的数据,是否符合他要预测的场景的那个时空状态下采集到的状态情况?我们见过一些客户自己做推荐系统,用了错误的方法,采集了错误的数据,尽管线下训练效果很好,线上实施的结果却远远低于预期。这是最大的风险之一。

Q6: 特征组合的方式是什么?怎么拼接在一起?

周开拓: 特征组合其实很简单,比如一个特征叫做身高,分高矮,一个特征区分穷富,还有一个特征叫做帅和不帅。那么高富帅就是一个组合特征,他对人的描述能力就强于之前任何一个单独的特征。

Q7: 在时间非常重要的情况下如何判断一个模型是不是过拟合了?

周开拓: 过拟合其实很容易判断,首先你的实验设计在时间上一定要是正交的,就是你用 1-7 号的数据训练的话,要用 8 号的数据做验证。那么如果验证集上的表现差,而训练集上的表现好,那可能是不是就是穿越了。另外你会对验证指标,比如 auc 比如 logloss 有一些经验性的判断,当一个模型的指标值大大超过你的经验的时候,风险就比较大。

Q8: 请问你这边机器自动调参是怎么实现的呢?

周开拓: 机器调参和人本质没什么区别,就是快很多而已。通过设定搜索的参数空间范围,以及启发式的搜索方式来找到在空间里优的参数组合。

Q9: 请问在线学习用的是什么算法?用的是跟离线训练一样的特征吗?auc 能达到多少?一直在训练的模型最后会过拟合吗?

周开拓: 在线学习的主要好处是快,而不是准。当然有一些特征因为工程的原因,在线不好收集到,就没法用了。AUC 取决于具体问题。一直在训练的模型可能出现的问题就是新增的增量样本对于模型的影响越来越小,学不动了,这时可以考虑做一些措施。


作者介绍

周开拓,第四范式互联网业务负责人。毕业于北京大学数学系,曾在传统媒介、制造业、电商等不同领域从事机器学习算法应用。在加入第四范式前负责淘宝网的推荐算法策略。对如何在现实的商业环境中用机器学习算法驱动业务富有经验。


CIO之家 www.ciozj.com 公众号:imciow
关联的文档
也许您喜欢