Skip to content

Feed

亿级用户相似度计算:Faiss与Spark的实践探索

在系列前作中,我们已经探讨了如何利用ALS算法为海量用户及其兴趣标签构建向量表征(Embeddings)(详见《机器学习实践:ALS的矩阵分解》),并进一步研究了如何让这些向量模型具备动态适应线上数据更新的能力

手握这些用户画像向量,一个新的工程挑战摆在了面前:如何在两亿级别的用户海洋中,为每一位用户精准且高效地“捞”出与其兴趣图谱最为契合的Top-K“知己”?这对于个性化推荐系统(例如“猜你认识”或关联内容推荐)而言,无疑是核心一环。

面对如此庞大的用户基数,传统的“两两握手”式比较方法,在计算资源和时间成本上显然力不从心。本文将聚焦于一种结合Faiss与Spark的分布式解决方案,旨在攻克这一大规模用户相似度计算的难题

漫漫长路:那些年我们踩过的“坑”

在抵达“光明顶”之前,咱们也曾在崎岖小路上摸索过。

机器学习实践:ALS的矩阵分解-Part II

在之前「机器学习实践:ALS的矩阵分解」中,我们通过ALS矩阵分解,对用户兴趣标签进行向量化,得到了接近word2vec的效果。

但是遗留了一个重要的问题,矩阵分解模型是对user_iditem_id进行建模的,只有把对全量的id的数据都喂给模型,才能获得id向量。这个id向量是静态的,一次性的,但在推荐系统使用时,建模数据每天变化,user_iditem_id集合也是不断变化的,导致ALS直接使用并不方便,两方面的挑战:

  • 如果只关心item的向量,可以对user集合进行了10%的抽样,但如果需要user集合的向量,就需要对全量数据分解,训练时间就会大大增加。
  • 行为数据每天更新,每次训练ALS学出来的向量都会与旧数据完全不同,没有连续性。

这个挑战类似于GNN之于node2vec的改进,也就是 inductive(不使用node_id)和 transductive(使用node_id)的区别。

那么,这篇讨论的问题是,ALS算法能不能改造成inductive的? 也就是能否满足下面两点性质,

机器学习实践:ALS的矩阵分解

交替最小二乘法(Alternating Least Squares, ALS)是一个比较古早的推荐系统算法了,发表在18年之前,本来已经完全可以不管了,因为用神经网络(Neural Network)做物品的embedding的效果已经很好了。

但是,NN开销确实比较大,一来训练速度限制样本不能太多,二来内存限制物品数量不能太多(虽然严格意义上,通过更猛的框架分布式,PS之类可以解决,但也更麻烦)。因此,又把ALS算法给捡起来了,它的效果上虽然只能达到NN的80%左右,但是优势是,

  • 用户和物品数量几乎无上限(只要不超过整型最大21亿,微博月活用户能全量分解)
  • 训练速度非常快(因为没有反向传播/SGD)
  • 可以分布式(Spark MLlib的明星算法)

粗看下来,几乎是弥补了神经网络的劣势,因此有了这篇实践,看看有什么坑,摸摸上限在哪里。

机器学习笔记:LLM的中文分词

在word2vec时代,基本上就是先jieba.cut,把中文切成token。后面再接w2v或者fasttext。但是第一次接触transformer的工具时,发现并不需要预先进行jieba.cut,因此速度也加快了不少。借此机会想再研究下,到底是为什么能跳过

1、理论部分

从早期NLP时代过来的人知道,英文一般是word based,词表会很大,动辄几十万都未必够,需要限制vocab的大小;但这么做就会损失长尾信息1,就像用户画像中的id类标签或者app编码遇到的问题一样。中文理论上可以直接character based切分成单字,这样词表大小就是有限的汉字数了,但模型需要在内部学习词组的含义,对模型要求更高。

机器学习实践:Hive使用虚拟环境

之前受限于hive机器上安装的python版本,只能使用py2.7默认环境,也没法安装包,导致很多复杂逻辑没法放到集群上跑。工作中需要用到scipy,redis等工具,也要使用py3.7以上的新功能。

尝试1

曾经将单独的包打包成zip后缀,打包后可以直接import进来,但是发现并不是所有的包都能跑通。一些依赖底层c库或者系统的,就会报错,比如numpy,scipy。成功的案例是redis和pymysql,见曾经的方案

尝试2

venv打包后的python并没有包含需要的全部库,venv.zip/bin/python无法运行。

尝试3

今天参考了几篇文献后,发现可以借助conda,由conda封装后,依赖的各种库都可以原封不动的使用,打的zip包可以无缝在各个linux系统中使用

1、新方案

创建conda环境

机器学习笔记:GBDT的并行化训练

@作者: 机器学习算法 @迪吉老农

最近使用 GBDT 时,想通过分布式进行训练,尝试了一些框架,但原理不太了解。有些东西与同事讨论后,也还不甚明了,于是专心看了一下文档,在此记录一下。

1、分布式原理

常用分布式训练方式,应该是参数服务器。worker把sample的统计结果推送到单台参数服务器机器上,参数服务器汇总后,再推送到worker端。有点类似于单reducer的方式。

相比于参数服务器的中心化方案,这里提到的都是 去中心化 方案。

微博大数据第三期:GPU占用程序试验

@作者: 机器学习算法 @迪吉老农, 代码地址: forge_load

1. 背景需求

最近组内的GPU利用率一直被警告,说是利用率过低。其实GPU这件事和CPU还是有区别的。

第一个问题是内存限制。CPU的话,可以平行的跑很多程序,这样利用率就上去了。但GPU很大程度上受限于内存。如果内存只能装2个进程,再想运行更多的程序也没有办法。

第二个问题是,CPU一般可以通过复制进程来提高利用率,每个进程占用一个CPU核,就可以按任意的比例提高总体利用率。但是GPU的训练任务跑起来的时候,经常一个程序就100%占用了。如果用这种方式占用空闲GPU,别的正常的程序就只能等待了。

不过既然上面要求了,我们也得做。就考虑两个方面的要求,

  • 占用尽可能小的内存。
  • 控制单进程的GPU资源占用比例。