推荐系统入门——没在学校学到的那些事

2019/11/24

希望能讲一些推荐算法行业内的同学都知道,而如果对这个行业没有什么了解的同学基本没有什么思路和信源能获取到的信息。也希望自己能借这个机会做一次总结。主要涉及推荐系统整体架构,模型的实时更新以及如何获取最新的一些信息。

毕竟我现在心里想的都是这一件事儿:早知道现在这些东西,在学校期间就应该多看点paper;也希望大家看完这篇文章之后,能够在在校期间做一点除了刷代码题之外的准备工作。毕竟可能更有趣一点,以及可以更早的修炼内功。

推荐系统整体架构

推荐系统整体架构,在我看来可能业界和学校之间区别最大的一个模块。在校期间或者是一些做一些数据竞赛的项目时,我们通常面对的是一份已经成型的数据集,然后我们只需要对这个数据集做一些处理,做一些特征工程,根据目标训练一个模型,调调参数然后就可以在测试集上进行拟合了。我们能控制到的变量基本只有模型,且数据量一般都不大,无论我们使用什么样的模型训练,只要等待的时间长一点,总能跑出结果的。所以我们关注的核心点在于模型。模型结构,模型效果,模型的更新方法(听起来这三者是计算机的同学更擅长的),以及模型的数学性质(听起来是搞统计数学的人更喜欢做的)。

但是在生产环境下,除了模型之外,我个人觉得以下几个点会同等甚至更加重要。以至于很多公司上线某一个排序系统的时候,都是先搞对这几件事情,模型可以使用一个逻辑回归先跑着。等这几件事情搞对了,再做进一步的优化。

  • 样本怎么来?
  • 怎么样可以对新增的数据做更实时的反馈?
  • 怎样保证在有限延迟的情况下返回预估结果?

这三个点对于一个熟悉“模型”的同学来说,重要性可能依次递减。但对于一个线上系统来说,这些都是非常关键的。

样本怎么来?

样本是模型的基础,样本搞不对搞不明白,最终训练好的模型肯定会有问题。这一点无论是对于已经构建好的数据集,还是从无到有构建数据集的时候都非常重要。

其实这个问题的答案说起来会非常简单:

我们先保存一份feature,通常是一些用户行为日志;然后再保存一份label,通常是一些用户行为。把这两个信息通过某种方式拼接在一起在一起,就是最终的数据集了。

当然这个问题有很多细节,比如我下面列举的这些问题:

  • 用户行为的特征通常要什么时候记录?是用户一天结束之后保存用户行为特征,还是在什么时候?
    • 比如模型中现在有一个计数类的特征,代表这个用户一天点击了某一个栏目多少次。因为计数是不断在实时更新的,在把这个特征纳入模型的时候,计数应该截止到什么时候为止呢?
  • 用户的行为那么多,怎么可以有效的转化为模型真正需要的label?
    • 比如我在今日头条这个App一天点击了了那么多,到底哪些才是真正的有用的label?怎么样做选择和定义?
  • 假设feature和label我都已经有比较好的数据集了,我什么时候才能够把它们拼接在一起?这里面有两个问题。
    • 多久拼接一次?是一天拼一次还是一周拼一次?
    • 如果一个用户一天之内可能有多个feature或者多个label,怎么保证拼接的时候是没有重复的?

受限于雇主,我不能把这些问题讲的过于清楚,大家可以自行思考一下这些问题。但我能说的是,对于数据集的构建也许各个公司的做法不太一样,但总体上这些问题行业是用一套通用的解决办法的。所以这总体是一个有解的问题。

在我看来,这些属于对于从零到有搭建系统的时候很关键,日常工作干活来说很重要。比如你现在想在原有的数据集上加一个特征,这些东西你就必须得清楚。但总体上来说,想明白了很关键,但也不怕晚。属于手熟了之后就可以做的事情,不怎么需要前置知识。

怎么样可以对新增的数据做更实时的反馈?

怎么评价一个推荐系统的好坏?或者说日常我们这些搞推荐系统的人怎么来评判一个推荐系统是否是足够优秀的?其中一个很重要的指标就是反馈的实时性,而这也对推荐系统提出了一些要求:

比方说,作为一个二十六岁的男生,我的兴趣爱好很广泛。我看到了一个漂亮小姐姐的图片,于是就给她点了赞。那在我接下来的几次刷新中,我就不想看到什么机器学习、量子力学、宇宙简史,就希望系统能给我多出几个漂亮的小姐姐;如果没出,那我可能就要关掉app,使用头条搜索操作一番了。

用户流失当然是推荐系统最不愿意见到的。那怎么办呢?这时候流式计算就派上用场了。如果你从来没听过流式计算这个词,那先自行搜索一下,熟悉一下这些概念以及背后的名词吧。在我看来,大规模流式场景可能是在学校,或者是科研场景下最难模拟到的一个场景。

假设线上有一个还不差的模型,我们用这个模型给出了预估结果,得到了用户的一些反馈,并且在系统中已经转化成了流式的样本(流式的样本怎么产生呢?)。通常的做法就是对模型进行增量更新,或者进一步的,在线学习。核心思想就是每次不用全部样本训练,而只是用新生成的这一部分样本数据去更新老的模型。同样地,我再列举几个问题:

  • 如果使用在线学习的方式更新模型,会遇到什么样的问题?
  • 常见的FTRL,AdaGrad又是怎么去解决这个问题的,它们各自的优缺点又是什么?

在我看来,这一部分知识是需要一定量的理论积淀的,优化方法相关有一些比较经典的论文,是可以在学校期间可以推导推导学习一下的。

同样的,这背后的工程框架也是需要了解的,比如:

  • 流式计算框架,现在最流行的Flink和Spark Streaming,他们之间有什么异同点,和批处理任务怎么结合?
  • 流式更新算法怎么样在分布式场景下使用?Parameter Server是个什么东西?用来干什么?

怎样保证在有限延迟的情况返回预估结果?

这个问题其实是一个工程和效果的trade-off,怎么可以在大规模候选集下选出系统最好的推荐结果。

目前比较通用的做法是把系统分成两个阶段,这方面比较详细的介绍当属YouTube的这篇论文——《Deep Neural Networks for YouTube Recommendations》。这篇论文把系统分成了召回(candidate generation)和排序(ranking)两个阶段,两个阶段的目标不同,问题的定义和模型也各不相同。里面还有很多非常经典的细节处理,比如模型结构,embedding的运用,连续值特征怎么加入模型等等。

这是一篇比较经典的文章,建议大家如果对推荐系统感兴趣请务必阅读。我在文章底部的原文链接里附了这篇文章的原文,我这里就不想详细展开了。

借由此,我想跟大家大致说一下工业界一般关注的paper怎么选取怎么读。如果大家空闲时间比较多,还是要多读一些这样的paper。当然我也是在摸索过程中,只是分享给大家一些我现在了解到的情况。这块的知识科普还要感谢我的敬伍老哥,从他身上真的学到很多。

  • 大公司的paper基本是必读的,其中Google(YouTube)的基本上就是行业标杆了。比如Google去年发了一篇用强化学习做推荐的文章(Top-K Off-Policy Correction for a REINFORCE Recommender System),据说取得了YouTube两年内的最大涨幅,我司一下子就洋溢着强化学习的氛围了。其他的比如阿里,Facebook都有一些不错的论文,但最优先的还是Google。据说Google的论文是模型或者系统被更先进的取代了之后才会把自己的东西发出来让大家学习一下,即便是这样仍然是最有价值的,不得不让人感慨这家公司的水实在太深了。
  • 学术界的论文质量好坏看引用量,大部分还是关注思路和idea。因为前面说的众多的原因,学术界关注的点和工业界生产环境有很大的不同。比如做实验的时候可以随便蒙特卡洛,但生产环境根本没这个机会。所以核心还是借鉴一下模型结构和一些思路。
  • 单篇精读的论文固然很好,但有时候可能会囿于细节,不太好继续深入。快速的了解某一个领域的框架相对来说还是重要且必要的。比较常用的方法就是翻知乎博客(中文好理解,但质量高的不太好找),或者是看一些Survey(英文,但质量通常有保障)。比如想了解Meta Learning,就可以通过搜索Meta Learning Survey找到比较权威的学术Survey。

最后我来总结一下这篇文章。我提出了三个在学校期间可能对于业界不太了解的三个点,样本是怎么生成的?怎么对新增数据做更实时的反馈?以及最后的有限延迟的情况下返回预估结果。针对第一个问题,我提出了几个需要思考的问题;后两个我都列出了一些参考文献。最后我还提到了一些怎么选取paper的一些思路。

如果大家在学校空闲的时间做到了这些,希望将来可以少像我现在这样,慨叹早知道这些东西就好了,就可以多读一些paper;以及现在知道这些的我,其实也是在为未来整理思路和方向,也要更加努力呀。

wechat follow