做广告业务 1 年多时间了,但是平时的工作主要和广告工程有关,核心的广告算法由 AI 部门支持,对我们而言可以说是「黑盒般」的存在,只需要对训练好的模型进行调用即可。
图片来自 Pexels
近期,我打算系统性地学习下广告中的搜索和推荐算法,当然更多是从工程的视角去弄清楚:算法的基本原理、以及面对线上海量数据时算法是如何解决性能问题的?整个过程,我会将有价值的技术点输出成系列文章。
这篇文章属于推荐系统的入门篇,本文暂不考虑线上环境的海量数据,目的是先了解清楚推荐系统的基本构成。
走进推荐系统的世界
“啤酒与尿布” 的故事相信很多人都听过,年轻爸爸去超市购买尿布时,经常会买点啤酒犒劳自己。
“啤酒与尿布”的故事
这个故事背后的理论依据就是 “推荐算法”,因为尿布和啤酒经常出现在同一个购物车中,那么向购买尿布的年轻爸爸推荐啤酒确实有一定道理。
推荐系统到底解决的是什么问题?
推荐系统从 20 世纪 90 年代就被提出来了,但是真正进入大众视野以及在各大互联网公司中流行起来,还是最近几年的事情。
随着移动互联网的发展,越来越多的信息开始在互联网上传播,产生了严重的信息过载。
因此,如何从众多信息中找到用户感兴趣的信息,这个便是推荐系统的价值。精准推荐解决了用户痛点,提升了用户体验,最终便能留住用户。
推荐系统的分阶段过滤流程
推荐系统的应用场景
头条、京东、网易云音乐中的推荐功能
哪里有海量信息,哪里就有推荐系统,我们每天最常用的 APP 都涉及到推荐功能:
-
资讯类:今日头条、腾讯新闻等。
-
电商类:淘宝、京东、拼多多、亚马逊等。
-
娱乐类:抖音、快手、爱奇艺等。
-
生活服务类:美团、大众点评、携程等。
-
社交类:微信、陌陌、脉脉等。
推荐系统的应用场景通常分为以下两类:
-
基于用户维度的推荐:根据用户的历史行为和兴趣进行推荐,比如淘宝首页的猜你喜欢、抖音的首页推荐等。
-
基于物品维度的推荐:根据用户当前浏览的标的物进行推荐,比如打开京东 APP 的商品详情页,会推荐和主商品相关的商品给你。
搜索、推荐、广告三者的异同
搜索和推荐是 AI 算法最常见的两个应用场景,在技术上有相通的地方。
这里提到广告,主要考虑很多没做过广告业务的同学不清楚为什么广告和搜索、推荐会有关系,所以做下解释:
-
搜索:有明确的搜索意图,搜索出来的结果和用户的搜索词相关。
-
推荐:不具有目的性,依赖用户的历史行为和画像数据进行个性化推荐。
-
广告:借助搜索和推荐技术实现广告的精准投放,可以将广告理解成搜索推荐的一种应用场景,技术方案更复杂,涉及到智能预算控制、广告竞价等。
推荐系统的整体架构
推荐系统的整体架构
上面是推荐系统的整体架构图,自下而上分成了多层,各层的主要作用如下:
-
数据源:推荐算法所依赖的各种数据源,包括物品数据、用户数据、行为日志、其他可利用的业务数据、甚至公司外部的数据。
-
计算平台:负责对底层的各种异构数据进行清洗、加工,离线计算和实时计算。
-
数据存储层:存储计算平台处理后的数据,根据需要可落地到不同的存储系统中,比如 Redis 中可以存储用户特征和用户画像数据,ES 中可以用来索引物品数据,Faiss 中可以存储用户或者物品的 embedding 向量等。
-
召回层:包括各种推荐策略或者算法,比如经典的协同过滤,基于内容的召回,基于向量的召回,用于托底的热门推荐等。为了应对线上高并发的流量,召回结果通常会预计算好,建立好倒排索引后存入缓存中。
-
融合过滤层:触发多路召回,由于召回层的每个召回源都会返回一个候选集,因此这一层需要进行融合和过滤。
-
排序层:利用机器学习或者深度学习模型,以及更丰富的特征进行重排序,筛选出更小、更精准的推荐集合返回给上层业务。
从数据存储层到召回层、再到融合过滤层和排序层,候选集逐层减少,但是精准性要求越来越高,因此也带来了计算复杂度的逐层增加,这个便是推荐系统的最大挑战。
特征计算由于数据量大,通常采用大数据的离线和实时处理技术,像 Spark、Flink 等,然后将计算结果保存在 Redis 或者其他存储系统中(比如 HBase、MongoDB 或者 ES),供召回和排序模块使用。
召回算法的作用是:从海量数据中快速获取一批候选数据,要求是快和尽可能的准。
这一层通常有丰富的策略和算法,用来确保多样性,为了更好的推荐效果,某些算法也会做成近实时的。
排序算法的作用是:对多路召回的候选集进行精细化排序。它会利用物品、用户以及它们之间的交叉特征,然后通过复杂的机器学习或者深度学习模型进行打分排序,这一层的特点是计算复杂但是结果更精准。
图解经典的协同过滤算法
了解了推荐系统的整体架构和技术方案后,下面带大家深入一下算法细节。这里选择图解的是推荐系统中的明星算法:协同过滤(Collaborative Filtering,CF)。
对于工程同学来说,可能觉得 AI 算法晦涩难懂,门槛太高,确实很多深度学习算法的确是这样,但是协同过滤却是一个简单同时效果很好的算法,只要你有初中数学的基础就能看懂。
协同过滤是什么?
协同过滤算法的核心就是「找相似」,它基于用户的历史行为(浏览、收藏、评论等),去发现用户对物品的喜好,并对喜好进行度量和打分,最终筛选出推荐集合。
它又包括两个分支:
①基于用户的协同过滤:User-CF,核心是找相似的人。
基于用户的协同过滤示例
②基于物品的协同过滤:Item-CF,核心是找相似的物品。
比如下图中,物品 a 和物品 b 同时被用户 A,B,C 购买了,那么物品 a 和 物品 b 被认为是相似的,因为它们的共现次数很高。
基于物品的协同过滤示例
如何找相似?
前面讲到,协同过滤的核心就是找相似,User-CF 是找用户之间的相似,Item-CF 是找物品之间的相似,那到底如何衡量两个用户或者物品之间的相似性呢?
除了余弦距离,衡量相似性的方法还有很多种,比如:欧式距离、皮尔逊相关系数、Jaccard 相似系数等等,这里不做展开,只是计算公式上的差异而已。
Item-CF 的算法流程
清楚了相似性的定义后,下面以 Item-CF 为例,详细说下这个算法到底是如何选出推荐物品的?
第一步:整理物品的共现矩阵
所谓共现,即:两个物品被同一个用户喜欢了。比如物品 a 和 b,由于他们同时被用户 A、B、C 喜欢,所以 a 和 b 的共现次数是 3,采用这种统计方法就可以快速构建出共现矩阵。
第二步:计算物品的相似度矩阵
其中,N(u) 表示喜欢物品 u 的用户数,N(v) 表示喜欢物品 v 的用户数,两者的交集表示同时喜欢物品 u 和物品 v 的用户数。很显然,如果两个物品同时被很多人喜欢,那么这两个物品越相似。
第三步:推荐物品
其中,Puj 表示用户 u 对物品 j 的感兴趣程度,值越大,越值得被推荐。N(u) 表示用户 u 感兴趣的物品集合,S(j,N) 表示和物品 j 最相似的前 N 个物品,Wij 表示物品 i 和物品 j 的相似度,Rui 表示用户 u 对物品 i 的兴趣度。
上面的公式有点抽象,直接看例子更容易理解,假设我要给用户 E 推荐物品,前面我们已经知道用户 E 喜欢物品 b 和物品 c,喜欢程度假设分别为 0.6 和 0.4。
因为物品 b 和物品 c 已经被用户 E 喜欢过了,所以不再重复推荐。最终对比用户 E 对物品 a 和物品 d 的感兴趣程度,因为 0.682>0.3,因此选择推荐物品 a。
从 0 到 1 搭建一个推荐系统
有了上面的理论基础后,我们就可以用 Python 快速实现出一个推荐系统。
选择数据集
这里采用的是推荐领域非常经典的 MovieLens 数据集,它是一个关于电影评分的数据集,官网上提供了多个不同大小的版本,下面以 ml-1m 数据集(大约 100 万条用户评分记录)为例。
下载解压后,文件夹中包含:ratings.dat、movies.dat、users.dat,3 个文件,共 6040 个用户,3900 部电影,1000209 条评分记录。各个文件的格式都是一样的,每行表示一条记录,字段之间采用 :: 进行分割。
以 ratings.dat 为例,每一行包括 4 个属性:UserID, MovieID, Rating, Timestamp。
读取原始数据
程序主要使用数据集中的 ratings.dat 这个文件,通过解析该文件,抽取出 user_id、movie_id、rating,3 个字段,最终构造出算法依赖的数据,并保存在变量 dataset 中。
构造物品的相似度矩阵
基于相似度矩阵推荐物品
调用推荐系统
下面选择 UserId=1 这个用户,看下程序的执行结果。由于推荐程序输出的是 movieId 列表,为了更直观的了解推荐结果,这里转换成电影的标题进行输出。
线上推荐系统的挑战
通过上面的介绍,大家对推荐系统的基本构成应该有了一个初步认识,但是真正运用到线上真实环境时,还会遇到很多算法和工程上的挑战,绝对不是几十行 Python 代码可以搞定的。
主要总结如下几点:
-
上面的示例使用了标准化的数据集,而线上环境的数据是非标准化的,因此涉及到海量数据的收集、清洗和加工,最终构造出模型可使用的数据集。
-
复杂且繁琐的特征工程,都说算法模型的上限由数据和特征决定。对于线上环境,需要从业务角度选择出可用的特征,然后对数据进行清洗、标准化、归一化、离散化,并通过实验效果进一步验证特征的有效性。
-
算法复杂度如何降低?比如上面介绍的 Item-CF 算法,时间和空间复杂度都是 O(N×N),而线上环境的数据都是千万甚至上亿级别的,如果不做算法优化,可能几天都跑不出数据,或者内存中根本放不下如此大的矩阵数据。
-
实时性如何满足?因为用户的兴趣随着他们最新的行为在实时变化的,如果模型只是基于历史数据进行推荐,可能结果不够精准。
因此,如何满足实时性要求,以及对于新加入的物品或者用户该如何推荐,都是要解决的问题。
-
算法效果和性能的权衡。从算法角度追求多样性和准确性,从工程角度追求性能,这两者之间必须找到一个平衡点。
-
推荐系统的稳定性和效果追踪。需要有一套完善的数据监控和应用监控体系,同时有 ABTest 平台进行灰度实验,进行效果对比。
写在最后
作者:骆俊武
编辑:陶家龙
出处:转载自公众号 IT 人的职场进阶
精彩文章推荐:
一次代码评审,差点过不了试用期!
张一鸣:给产品技术人才的建议
文章评论