协同滤波和它的子孙们

2022年Q4,在项目里接触了一些跟召回相关的工作,但坦白讲做的比较匆忙。整好最近在家带娃,空余时间比较系统地学习了一下,这篇小作文做个总结。 本文总结的算法都有一个共同的发端,就是大名鼎鼎的协同滤波(collaborative filtering,CF)算法。这个协同只看字面也看不出个所以然,维基百科的解释如下 协同过滤(collaborative filtering)是一种在推荐系统中广泛使用的技术。 该技术通过分析用户或者事物之间的相似性(“协同”),来预测用户可能感兴趣的内容并将此内容推荐给用户。 经典CF 最早的CF算法是user CF。这种算法包含两个主要步骤 对于当前用户,在所有用户中寻找与他最相似的一些用户 用相似用户对item的评价来作为当前用户对item的评价 我做的几个召回渠道也是基于CF的。如果把这个技术用在召回里,就是对于当前user,返回在与之相似的用户中受欢迎的item。这里面用户相似度的评价方式比较重要,例如通过计算两个用户交互过item的Jaccard距离来作为相似度。这种做法在用户集合很大时计算复杂度相当高。在早期的系统里,item的数量可能远远少于用户的数量,并且用户的相似度会随着用户行为的变化而变化。所以有人提出在item与item之间直接计算相似度,这种相似度相对稳定,离线计算好一个相似度关系表之后在线可以直接使用,这样就可以避免相似用户计算这个耗时的步骤,这种做法称为item CF。 矩阵分解 Matrix Factorization 上面的经典CF算法实际是个间接推荐的方法,人们发现可以从用户和item的交互历史中得到用户和item的关系,从而进行直接推荐。基本的思路是将user-item交互矩阵近似为user矩阵和item矩阵的乘积。具体来说,若用户数为N,item数为M,则交互矩阵为N*M,希望把它近似为N*K和M*K两个矩阵的乘积。K可以远小于N和M,这样相似度的计算复杂度将比jaccard大大降低。实际上也就是获得了K维的user和item的embedding。交互矩阵通常是0,1矩阵(称为implicit feedback data),上面的操作实际上要让有交互的user和item embedding之间的点积接近1,没有交互的embedding点积远离1。 以下图为例,我们获得了4个用户和5部电影的交互矩阵,右边是矩阵分解之后的结果。左边4*2的矩阵为用户矩阵,在一个二维空间对用户进行表征,上面5*2的矩阵是电影矩阵,在同一个二维空间对电影进行表征。右边的大矩阵是这两个矩阵相乘的结果,和左侧0,1矩阵是比较接近但不完全一致的(毕竟降维了)。对于一个user未交互过的item,我们可以拿user的embedding和item embedding做点积来预测用户发生交互的概率。 {: .align-center style=“width:80%”} Matrix Factorization示意图 {: .align-caption style=“text-align:center;font-size:smaller”} 这个算法实际上优化的是下面这个目标 $$ \min_{U \in \mathbb R^{m \times d},\ V \in \mathbb R^{n \times d}} |A - U V^T|_F^2. $$ 学过数值分析的话会知道矩阵分解有一些经典算法,例如SVD。但这个交互矩阵A实在是太稀疏且太大了,经典算法比较难处理,因此实用的损失函数是这样 $$ \min_{U \in \mathbb R^{m \times d},\ V \in \mathbb R^{n \times d}} \sum_{(i, j) \in \text{obs}} (A_{ij} - \langle U_{i}, V_{j} \rangle)^2 + w_0 \sum_{(i, j) \not \in \text{obs}} (\langle U_i, V_j\rangle)^2....

December 23, 2022 · 1 min · Yuanhao

也聊一下ChatGPT

最近ChatGPT火了,而且火出圈了。好多不是做技术的朋友都开始关注甚至转发相关文章。从广为流传的一些例子看,ChatGPT确实做出了让大家眼前一亮的效果。聊天机器人搞了这么些年,也终于有了一个让大家都比较认可的产品。 {: .align-center style=“width:80%”} ChatGPT的结果令人惊艳 {: .align-caption style=“text-align:center;font-size:smaller”} 小迷思 前几天几个小伙伴聊天,说起ChatGPT和OpenAI,纷纷感叹为什么国内没有这样的创新公司和突破性产品涌现。几个大厂的研究院,比如阿里达摩院、字节AI Lab虽然成果也很多,但跟deepmind、OpenAI比起来差距还是很大。其实ChatGPT背后的东西并不是有多难,但为什么做出来的是他们? 今天在知乎上发现也有类似的问题,还挺火的。不少回答都从大环境的角度分析,有说我们还穷的,有说国内资源和人才不匹配的。这些固然对,但作为个体我们也可以从自己身上找找原因。前几天看到一个做AI架构的大佬在朋友圈感叹,18年就在某大厂实现了500块GPU并行训练transformer,但大家都不知道这东西能干嘛。所以有的时候并不全是资源不到位的问题。我不禁想起了马老师“因为相信,所以看见”的观点,我感觉就是差在这个境界上。从学校毕业五年多了,我感觉这也是自己目前比较大的一个问题,我们有把事情做好的能力,但却缺少真正相信且原意长期坚持的东西。 ChatGPT背后的技术 还是聊回技术。ChatGPT还没有公开的论文,根据OpenAI的博客,基本上使用的技术和他们在今年早些时候公布的InstructGPT差不多。 We trained this model using Reinforcement Learning from Human Feedback (RLHF), using the same methods as InstructGPT, but with slight differences in the data collection setup. {: .align-center style=“width:80%”} ChatGPT训练流程 {: .align-caption style=“text-align:center;font-size:smaller”} 上面是ChatGPT博客上的训练流程图,下面是早先InstructGPT论文里的训练流程图,嗯,可以说是一模一样,比较大的差别是基础语言模型从GPT3升级到了GPT3.5。 {: .align-center style=“width:80%”} InstructGPT训练流程 {: .align-caption style=“text-align:center;font-size:smaller”} InstructGPT的介绍还有图例,更容易讲清楚ChatGPT是如何训练的。这个模型的训练分为3个步骤: 从预训练语言模型出发,用标注者产生的数据fine tune一个根据提示(prompt)生成答案的模型,这一步称为SFT 用上一步训练的模型生成大量的答案,每一个prompt都生成多组,并让标注者对这些答案进行排序。用这样获得的数据训练一个奖励模型(Reward Model,RM)。这个模型会作为后续强化学习环节的世界模型。 强化学习训练。这一步有点左右互搏的意思,用RM模型作为世界模型,SFT之后的生成模型做agent,进行训练,让生成模型尽可能地在RM模型那里拿到高分。这一步使用的算法也来自OpenAI,为2017年发布的PPO算法。 {: .align-center style=“width:80%”} 强化学习基本流程 {: .align-caption style=“text-align:center;font-size:smaller”} 我对强化学习并不熟悉,只是稍微看了下PPO的介绍,这个算法的目标函数可以用下面的公式来概括,这个目标函数包含了三个部分,第一部分是标准的强化学习目标,即在reward model那得高分;第二部分是PPO的创新点,即KL惩罚,目的是让强化学习的每一步都不要更新太多(新模型和老模型的KL散度要小);第三部分是针对语言模型精调新加的,为了防止语言模型在精调的时候退化,他们在精调时把语言模型loss也加了进来。三个部分通过两个超参数β和γ进行调节。...

December 10, 2022 · 1 min · Yuanhao

大教堂与集市-part1

《The Cathedral & the Bazaar》 By:Eric Steven Raymond, 1997 基础版本:https://github.com/crazyangelo/Cathedral-and-Bazaar 基础版译注:原始版本為 1999 年 5 月 5 日,由謝志昌所翻譯;英文最新版為 2002 年 8 月 2 日的 3.0 版,由於內容更動處不少,因此逐一更新;翻譯以語句通順達意為主要考量,難免與英文版的字詞有所不同,為求盡善盡美,以 CC 授權釋出,希望各方同好自由修改散佈。 本版译注:将繁体字改成简体,并修正了一些词汇表达 第一章 教堂与市集 Linux 打破了许多软件发展的传统,这个世界级的操作系统在五年前(1991 年)仅仅靠着如丝般的网际网路,神奇地联合了散布在全世界数以千计兼职的玩家们来发展它,谁曾料到会发生这样的事情呢? 我当然也没料到,Linux 出现在我电脑萤幕是在 1993 年初,当时我埋首于 UNIX 及开放性原始码的软件发展已有十年,1980 年代中期,我是 GNU 专案首批的贡献者之一,我写过许多开放性原始码的软件放到网路上供人使用,也曾独立或协同发展好几个程序(nethack,Emacs 的 VC 和 GUD 功能,xlife,…等等),这些程序到今天仍广泛地为人所用,我想我知道这是怎么办到的。 GNU 是自由软件基金会(Free Software Fundation)的一个专案,目标是发展出 UNIX 上所有程序的自由版本,Emacs 是自由软件基会发展出来的一支程序,可做文字编辑器,提供写程序的整合发展环境,用来读电子邮件,新闻群组,甚至浏览网页。更详细的资讯请参考 http://www.gnu.org。 ―― 译注。 Linux 扭转了许多我认为我已知道的观念。多年来我一直宣扬使用小工具集、快速原型发展及程序进化的 UNIX 福音。但我也相信对于有一定复杂度的程序必需使用集中和有经验的方法来开发,我相信最重要的软件(操作系统以及庞大的工具程序如 Emacs)必须如建造一座教堂般,由个别的高手或一小群专家在光辉的孤立中小心翼翼地精雕细琢,时机未到之前,不会释出测试版。 Linus Torvald[^2] 的软件发展风格(尽早并经常发表新版本,授权每一件作者可以委托的事,不拒绝几乎到混乱程度的程序)的出现如同一个惊奇,没有令人肃然起敬的教堂,甚至 Linux 的同好们似乎组成了一个有不同流程和不同方式的大市集(Linux 的档案服务站台就是它适切的象征,每个人都服从着自由的规则),以这个风格发展出来的 Linux 既一致又稳定,表面上看来真是一连串的奇迹。...

December 9, 2022 · 3 min · Yuanhao

大教堂与集市-part2

第五章 有多少眼球驯服了复杂度 可以很明显地观察到市集模式极大地加速了除错与程序演化。另一件可以清楚明白的是,在微观上,开发者与测试者的每天活动中,市集模式如何与为何可以达到这样的成果。在本章(初版完成三年后,依据开发者多次亲身体验过的洞察力),我们将仔细的检查它的实际机制。非技术性倾向的读者可以略过这一章,直接跳到下一章去。 一个关键点是,为何没有源代码意识的使用者所报告的错不会太有用。没有源代码意识的使用者倾向报告表面上的问题,他们把自己的使用环境视为理所当然,所以他们会忽视重要的背景资料,报告错误时很少会包括可信赖的过程。 这里的问题是测试者与开发者对问题的视角不同,测试者由外向内看,开发者由内向外看。在封闭源代码的体系中,两者只会固守自己的角度谈论事情,因而对另一方深深的失望。 开源的体系则打破这条界线,使测试者与开发者可以站在同样的角度来讨论事情,这有高效多了。实践中,这将有巨大的差异,一者是只报告表象的症状,一者是以开发者那种以源代码为基础的角度来看问题。 大部分的时候,大多数的bug是可以由描述开发层级的特征来除错的,即使是不完整的描述。当一个 beta 测试者告诉你在那一行代码有边界的问题时,或告诉你在 X、Y 跟 Z 的情形下,有个变量有问题,指出有问题的代码通常就足够找出问题并修正它。 因此,对于 beta 测试者与核心开发者来说,有源代码意识的人对于双方都可以强化沟通与合作。换句话说,核心开发者的时间被节省了,即使是在有很多共同开发者的情形下。 另一个开源方式的特征是节省开发者的时间,而这是典型开源项目的沟通结构。上面我使用了「核心开发者」(core developer)这个字来区别项目核心(project core,通常很小;一个开发者是常见的,一到三个开发者则是很典型的)与项目圈(project halo)的 beta 测试者跟贡献者(通常有数百个)。 传统软件开发组织的根本问题是「Brooks法则」︰在落后的项目,增加越多程序员会使得项目更落后。一般的状况下,「Brooks法则」的预测是,随着开发者的人数增加,复杂度与沟通成本随着人数的平方上升,而完成的工作却只成线性上升。 「Brooks法则」依据的经验是,bug会在由不同的人编写的代码的接口上大量出现,而沟通损耗会随着项目参与人数的升高而升高。因此,问题的规模会随着开发者间的沟通路径而呈现平方上升。(精确的说,是 N x (N-1)/2,N 是开发者的数目。) 「Brooks法则」的分析建立在一个隐藏的假设基础上︰项目的沟通结构必须是完全图(complete graph),每个人都可以跟每个人沟通。但是在开源的项目中,开发者在有效平行分割的子项目中彼此很少互动;程序更改与bug报告是透过核心团体来处理的,只有在这样的小团体中,「Brooks法则」的分析才成立1。 还有其它原因让源代码层级的bug报告变得有效率。事实是一个错误常常会有许多可能的症状,取决于使用的的使用状况与使用环境。这些错误是一些复杂与微妙的bug(像是内存管理错误或视窗的随意中断),也是最难被发现或靠静态分析来捕捉的,这在长期的开发中造成最多的问题。 当一个测试者发出一个尝试性的源代码层级的多症状bug报告(例如,我看来在第 1250 行代码有个窗口在做讯号处理,或你在哪里把那个缓存清空),可能会给开发者一个关键的线索来发现半打的症状,这些开发者通常因为太靠近底层代码而无法发现这样的问题。在这种案例中,很难找出可从外部看见的不正确动作是从哪个bug引起的,甚至是不可能的 ―― 但是透过经常发布,就不需要知道了。其他的合作者会迅速找出bug是否已被修正。在很多案例中,导致不正常动作的源代码层级bug将被移除,甚至在还没有被报告之前就被移除。 复杂的多症状错误,通常有很多从表面症状来的方式可以找出真正的bug。这种能让测试者与开发者找出问题的方式,可能与开发环境有关,也可能会随着时间而有无法预期的变化。实际上,当测试者或开发者追踪一个症状时,都是在程序空间的一个集合中「半随机」(semi-random)取样。bug越微妙复杂,越难找出相关的样本。 对于简单与容易复现的bug,重点在于「半」(semi)而非在「随机」(random);debug技巧、对程序与架构的熟练都是关键。但对于复杂的bug来说,重点就是「随机」(random),这时人多比人少好 ―― 即使这些少数人是平均技巧较高的。 如果从表面的症状找出bug的难度大,像是一些无法从表面症状预测的,上述的结果会进一步增强。单一的开发者可能会以一个困难的方式来做第一次尝试,但其实也可以从简单的方式达到同样的结果。另一方面,假如很多人随着频繁的版本一起测试,可能就会有一个人可以用最简单的方式找到bug,节省了大量的时间。项目管理者将会发现,随着新版本发布,许多人一起用各种复杂方法追踪同一个bug的时代将会过去,尤其是在众人浪费太多时间之前2。 第六章 今花非昨花? 由 Linus 行为的研究中,我们得到了一个能解释他为什么成功的理论,所以我想要在我的新项目(当然不如 Linux 内核程序复杂和雄心勃勃)中来测试这个理论。 但我做的第一件事情是大力重组和简化 popclient 的程序,Carl Harris 的实现非常扎实,可是却像许多的 C 程序员一样,含括了一种不必要的复杂,他以代码为主,数据结构为辅,因此代码看起来漂亮,但数据结构却很特殊,甚至可以说是丑陋的(至少以这位老资格 Lisp 高手的高标准而言)。 然而,我重写程序除了改良原来代码和数据结构的设计外,还有其他目的,就是把它发展到我可以完全了解,否则负责修补你不懂的程序是一件很无趣的事。 项目进行的第一个月,我简单地依循着 Carl 原来基本设计的用意,第一个重大的改变是我加入 IMAP 协议的支持,我重构原来处理协议的程序,改成一个较为通用的驱动程序再加上三个驱动它的方法表(即 POP2,POP3 和 IMAP)。这个改变阐释了一个广义的原则,特别在像 C 这种先天上未提供动态类型的程序语言,程序员们最好谨记在心︰ 格言9︰聪明的数据结构配上笨拙的代码要比相反的组合好。3 Brooks 在《人月神话》的第九章中也说︰「光给我看你的代码,而不给我看它用的数据结构,我会一头雾水。给我看你程序的数据结构,我通常不需要再看你的代码,因为已经够明白了4。」...

December 9, 2022 · 2 min · Yuanhao

大教堂与集市-part3

第九章 由 Fetchmail 学到的一些经验 在我们回头讨论一般软件工程的议题前,由 fetchmail 得来的一些特殊教训值得深思。 Fetchmail 配置文件(rc file)的语法包括可有可无的关键字,这些如「噪音」般的字眼会被语法分析程序忽略,这些字的加入,使得配置文件的语法和英文很接近,和传统中简洁的「关键字 ―― 设定值」配对表示法(把噪音字去掉就可以得到)比较起来,要来得容易阅读。 这个教训开始于某一个夜晚的实验,我注意到配置文件中的宣告语法可以组成一个迷你的祈使语言。(这也是为什么我把原来 popclient 中的关键字 server 改成 poll)。 对我而言,如果把这个祈使语言弄得更像英文,那会让 fetchmail 更易于使用,虽然我现在信服如 Emacs、HTML 及许多数据库引擎制定出来的模范语言,在正常情况下我也不那么迷英文的语法。 传统的程序员喜欢非常精确而简洁的配置语法,不希望有任何冗余在其中,这是因为早期的电脑计算资源昂贵而遗留下来的观念,他们认为语法分析的过程要节约计算资源,并要尽可能的简单。英文的语句大约有百分之五十的冗余,所以不利于做为配置语法。 但这并非我在正常的情况下不用英文语法的原因,我在此提及是为了推翻像英文的语法不适合作配置语法的论点,当中央处理器和内存都变得便宜时,配置语法的简洁已不再是我们的目标,现在的情况是︰一个电脑语言中符合人性易于使用的重要性已超过节约电脑的计算资源。 然而还是有好几个地方要小心,其中之一是语法分析过程变得比较复杂的代价 ―― 你不会想把这个特点(使用像英文的配置语法)变成程序错误的来源及使用者的疑惑处。另一个是当我们要订出一个像英文的语言时,通常需要做些修改,表面上看起来修改过后的语法可重组出自然语言,但可能也会因修改过以致于和传统的配置语法一样,令人感到疑惑。(我们可以在许多所谓的第四代程序语言和商业用的数据库查询语言看到这个现象) Fetchmail 的控制语法看起来免除了这个问题,因为我严格地限制控制语法的范围,它不是一个以通用为目的的语言,它简单并不很复杂,所以在极小的英文子集和真正的控制语言之间的相混处很少,我认为这里还有一个更广义的教训︰ 格言16︰当你设计的语言没有一处是 Turing-complete,你可以采用比较平易的语法。 另有一个教训是关于含糊的保密性,有一些 fetchmail 的使用者要我修改程序,以把经保密处理的凭证储存于配置文件内,这样一来,偷窥者就没办法看到真正的密码了。 我并没有这么做,因为这个做法并不能达到真正的安全,能拿到读取你配置文件权限的人,也能以你的身份执行 fetchmail ―― 如果你的密码经保密处理存在配置文件中,他们可以由 fetchmail 中取得解码程序来得到你真正的密码。 如果我把程序改成可以在 fetchmail 的配置文件中储存保密的密码,那会给认为这并不难的人们对保密性的错误观念。一般的守则应该是: 格言17︰一个保密系统是否安全依存于它隐藏的秘密,注意不要有「虚拟秘密」。1 第十章 市集模式必要的条件 早先看过这篇文章的书评家和试读者都提出同样的问题,那就是以市集模式发展软件,获得成功的先决条件为何?包括项目领导人的资格,代码到什么样的程度,才对社群发布并开始成立协同发展团队。 相当明显的,任何人无法以市集模式建立软件基础2,但是可以用市集模式来测试,debug,改进软件,在一个项目的起始点很难运用市集模式,Linus 没试过,我也没有。项目初始的协同发展团队需要有一些东西可以测试,可以执行。 当你开始召募项目团队时,你必须能提出大致合理的保证,你的程序不需要运作得很好,它可以暴力,有错,不完整,及注释贫乏,只要它可以使潜在的协同开发者相信,这个程序在可预见的未来大有可为。 Linux 和 fetchmail 公开发布时都具有强健及吸引人的设计,许多人认为这和我所报告的市集模式有所不同,并以为这样的设计很重要,甚至进一步做出一个他们的结论 ―― 高度的设计直觉和聪明是一个项目领导人不可或缺的特质。 但是 Linus 的设计由 UNIX 而来,我的设计由原先的 popclient 而来(虽然它后来改变甚大,比例上说来还超过 Linux),所以市集模式项目的领导人或协调者真的需要格外的设计技巧?或者能提升别人的设计技巧呢? 我想对于项目协调者是否能做出耀眼的设计并不重要,最重要的是协调者是否能认知别人在设计上的好点子。 Linux 和 fetchmail 都证明了这件事,Linus 这位仁兄如同之前所讨论的,他并不是伟大的创新设计师,但他展现了另一种卓越的技巧,即认同别人好的设计点子,且将这些好的设计整合到 Linux 的核心中。而我之前描述过 fetchmail 最有力的设计(藉 SMTP 转发邮件)也来自他人。...

December 9, 2022 · 3 min · Yuanhao

推荐系统金字塔

本文同样适合没有技术背景的朋友阅读 遥想若干年前,今日头条和后来的抖音横空出世的时候,到处都可以看到关于他们推荐算法的讨论,个性化推荐对业务的重要性也被捧上了天。最近一年多,也算是亲身参与了一些推荐相关的项目,在实操之后,对这件事情也有一些自己的理解。 开门见山,我认为好的推荐系统,或者说个性化系统有三层特点,从底向上分别是: 有丰富的让用户感兴趣的物料 用户能够发现并表达兴趣 用户表达兴趣后能推荐高相关性的物料 就像一作金字塔。 1 首先是【有丰富的让用户感兴趣的物料】,这实际上是所有推荐系统的基础:物料要丰富且高质量。物料就是要推荐的东西,电商应用里是商品,内容应用里视频、图文,社区应用是达人,各不相同。如果物料不丰富,那实际上没有推荐的必要,小卖部一般没有导购,有啥东西一目了然。物料如果质量不高,那后面的工作也很难做,用户很难在这种系统中留存下来,也就会导致推荐系统的另一个重要燃料用户行为数据的不足。这块一般和算法没什么关系,但实际确是重中之重。大的生态系统治理其实更像经济学问题,解决的是供给和需求的关系。 {: .align-center style=“width:80%”} 京东平台在2015年就有两千多万件商品了,为推荐提供了舞台 {: .align-caption style=“text-align:center;font-size:smaller”} 2 接下来是【用户能够发现并表达兴趣】,这层开始跟算法有了一些关系,但更多还是通过产品和工程来解决。换比较专业的说法就是怎么做冷启动和试探。最理想的方法是把冷启动转变成热启动,例如说一个头条老用户来看抖音,好了,你在头条喜欢看啥我先给你看啥,大概率会比随机给你看点东西好。所以字节的产品矩阵在这方面就可以发挥很大的作用。但一般公司没这条件,那就只好尽量去挖可以用的先验信号,比如用户的地点、安装的app,甚至去爬其他的社交网络平台。 如果这条路走不通,那就只好试探了,产品没做好的话大概率是自身生态里什么热门就给你试探什么,这里总归是要碰点壁的。所以大部分产品上来会让你选一下你感兴趣的话题或者分类,作为用户,这时候可以直接点告诉他们,让这些系统更好地为自己服务。 {: .align-center style=“width:50%”} 常见的兴趣选择界面,让用户直接表达兴趣,顺利留存下来 {: .align-caption style=“text-align:center;font-size:smaller”} 还有些重要的用户表达兴趣的渠道,例如搜索。当一个系统的物料特别丰富,例如淘宝,什么东西都有,此时就很难试探,因为这个试探空间太大了。但好在买东西通常有目的性的,通常电商平台有50%的成交是搜索贡献的,用户会通过搜索功能来告诉平台自己想要什么。 所以一个好产品一定要打通各种用户表达兴趣的渠道,尽量避免瞎猜。 3 最后才是【用户表达兴趣后能推荐高相关性的物料】,也就是常说的推荐算法解决的问题。作为塔尖,它似乎吸引了最多的目光。举刚才搜索的例子,用户搜索“杯子”,ta已经表达了兴趣,你如果给他展示一堆碗,那肯定无法促成消费。 这方面算法很多,比较常见的比如各种协同滤波(买了杯子的人还会买啥?)以及现在流行的各种序列建模(每个月都买米这个月应该也会买米)等等。当系统往大了发展,我感觉工程的重要性又会超过算法:这么多的用户行为怎么存?这么多的训练数据怎么跑?虽然每年新结构、新网络层出不穷,但实际上常用的还是那几个经典的。以Criteo数据集为例,多年下来各种模型迭代导致的auc提升不到3个百分点(但不是说3%不重要,以大公司的体量还是很可观的)。但实际上推荐系统的发展早已不是这个数据集可以追踪的了,因为各个大公司特征、用户的规模早就不是这样了。 {: .align-center style=“width:80%”} Criteo数据集近年来的auc指标 {: .align-caption style=“text-align:center;font-size:smaller”} 前不久Tik Tok放出了他们推荐系统的论文,大量篇幅是在讲基础设施pipeline,模型部分这是个多年前的DeepFM。 小结 我感觉三个层次大致对应了【生意】-【产品】-【技术】,在这个互联网纷纷裁员的寒冬回过头看,确实这三个层次都出现了不同程度的停滞。不过一个时代过去总会有一个新的时代来临,技术应该是这三个里面停滞现象比较低的,相信在不久的将来就会有新的增长点。 以上就是我的一些想法,欢迎大家讨论。

November 16, 2022 · 1 min · Yuanhao

现在的开源深度学习模型真的太强了

为了迎接宝宝的诞生,前段时间收集了一些中英文故事,做了一个讲故事小程序。 在收集故事的过程中遇到不少问题,比较典型的情况是只有音频,或者只有文字,或者没有配图。在深度学习模型日新月异的2022,我决定尝试用最新的开源模型来解决一下这些问题。 [TOC] 插图生成(text2img) 这是目前大火的领域,每天各种营销号都有大量文章狂轰滥炸。不论是生成梵高画作还是生成性感waifu,似乎AI画师现在已经无所不能。 但我实际使用下来感觉要让AI直接给故事画插图还是蛮困难的。我使用的是最近红的发紫、大名鼎鼎的Stable Diffusion,短短几个月已经发展到第四版了。我的做法也比较简单,直接把故事标题嵌入在一段prompt里面,例如a story illustration for children of the story about The crow and the water bottle 。这个prompt模板是参考了一些prompt编写指南结合尝试之后得到。 在尝试的过程中发现几个比较明显的现象 通过art by xxx控制风格非常灵敏,试了梵高和莫奈,得到图片的风格都很强 细节效果都比较差,不管是脸还是手,只要有这种部位的图都不太能用 AI产生的图片有时给人感觉阴森森的,给小朋友做故事书插画估计真会吓死宝宝 下面是几个我生成出来的例子 这个乌鸦喝水的图是我比较满意的,两个东西都画的比较正常,水瓶子里还有点石头,估计是模型训练时有见过这个phrase和相应图片,直接给记住了。 这个图不知所云,没看到有奶牛,青蛙也怪怪的。 这张丑小鸭算是平均水平,虽然鸭头有点怪,但是在可以接受的范围内。 后来我又调研了下,有的朋友为了给故事生成插图做得还是比较fancy的。例如这个小姐姐的repo,大家感兴趣可以看一下,也是开源模型攒的pipeline。 更多生成图片的例子,可以参考这个故事集。 语音转文字(ASR) 虽然各种有声故事大大减轻了讲故事的负担,但给婴儿或者胎儿讲故事最好还是由爸爸妈妈亲自来。毕竟这个时期故事内容肯定是听不懂的,更重要的是让宝宝听到父母的声音。为了能亲自讲故事,我需要把之前找到的一些故事音频(主要是英文的)转换成文本。 经过一番调研,目前比较好的ASR模型是最近openAI开源的来源于论文《Robust Speech Recognition via Large-Scale Weak Supervision》的Whisper。 这个模型是个transformer seq2seq model,从插图来看multi task这块比较复杂。 待转写的故事听起来都比较清晰,我直接搞了个base.en单语模型试了一下。跑出来的效果简直惊艳,几乎没有错误的单词,甚至连时态都识别得很准确。唯一美中不足的是有些文章转写出来没有标点符号,也几乎没法识别出段落,给阅读带来一些障碍。为了解决这个问题,我又找了个punctuation restore模型后处理了一下。现代化的语言模型做这个事情简直是易如反掌,效果也相当好。 大家可以看这个故事集里面的内容,都是ASR转写出来的。 文字转语音(TTS) 亲自讲故事虽好,但英语内容不是所有家长都能驾驭的。对于只有文本的英语故事,我也希望能生成相对应的音频。 目前开源模型里面SOTA水平的应该是来自Facebook(Model Card里是叫fastspeech2,但正文里又写是S^2,微软也有一个叫fastspeech的模型,我还没搞懂他们之间关系)的FastSpeech2,这个模型是用faiseq来实现的,但也在huggingface的hub上托管。 样例代码有点bug,按照讨论区的指导可以跑通。给一段文字的话生成很快,但句与句之间有点黏连太紧,听感不佳。我稍微做了点小后处理,让文章听起来自然了一些。大家可以参考这个故事集的内容。 在做TTS和扫论文的过程中隐约感觉TTS是一个很有意思的领域,后面有时间可以多学习一下。 总之,经过这些有趣尝试,我基本上解决了我遇到的内容问题。虽然这些模型都还有一些问题,但确实已经可以很大得提升生产力。原来需要特别专业团队才能做的事情现在只要几行代码就可以搞定。内容类、工具类产品的玩法也更多了,可以用这些模型和人相互激发促进来产生更多有趣的创意。 本文就先写到这,如果你也需要经常给宝宝讲故事,欢迎使用这个简单的小程序!后面我还会写一两篇关于这个小程序工程和算法方面的心得,如果你感兴趣,欢迎关注公众号,及时获取更新。

October 17, 2022 · 1 min · Yuanhao

文本生成专题2:常见的摘要生成方法

按照第一篇的计划,这篇文章梳理一下常见的摘要生成方法。大部分方法并不复杂,更多的内容其实包含在seq2seq框架、语言模型、self/cross attention这些模块里。 [TOC] 抽取式摘要 所谓抽取式摘要,有点像之前写过的关键词抽取,就是把原文里重要的部分抽出来作为摘要。 前Transformer时代的方法 有好多基于统计的抽取式摘要生成方法,例如jieba里都集成的TextRank。这方面资料很多,大家搜搜就有。 Transformers-based方法 比较典型的工作是BERTSum,其结构如下图。相比原始BERT,几个主要的变化是 在每个句子前面增加[CLS]token,后续用他们对应的隐向量作为句子表征; 把BERT原有的token type改变成了0/1相间的形式; 在得到句子表征后,又增加了一个称为Summarization Layers的Transformer/LSTM模块,用户在句子表征间做交互。 最后对于每句话输出一个应该包含进摘要的概率,最终结果由得分top3句子产生。 来看一下BERTSum的表现,如下图,总体还是不错的。可以发现加上所谓的Summarization Layers模块并没有很明显的提升,预训练语言模型大部分时候确实很强,光魔改结构往往收效不大。这篇文章的结构我感觉很工整,句子前加[CLS]的操作给人一种细腻的感觉。 生成式摘要 生成式摘要的大体框架很久都没有变过了,大概就是下面这张图。左边是一个encoder,用来编码原文,右边是个decoder,用来生成摘要。 前Transformer时代的方法 在RNN之后,Transformer出来之前,主要的改进是加入各种各样的attention,原文间,摘要间,原文和摘要间等等。大家可以看出来上面那张图已经是有attention的了。 我个人认为前Transformers时代最特别的一个问题是OOV。有不少工作是针对这个问题展开的,其中比较有名的是Google的Pointer Generator。对比和上图的区别可以发现,对于next token的预测,概率分布里出现了"2-0"这个从原文copy出来的词(也是不属于词典的词,是没有copy mechanism之前不可能被生成的词)。真的是要感谢subword tokenizer的广泛使用,让大家省去了很多类似的dirty work。 目前主流的方法 目前的encoder-decoder transformer早已把各种attention玩到登封造极的程度,原文、生成结果间相互的联系已经大大加强。这几年的提升很多都是来自于非结构方面,例如BART用一种新颖的预训练方法来提高,GPT用超大语言模型来提高等。摘要生成逐渐成为了一个跟随语言模型水涨船高的领域(调参调结构当然也有用,但至少大的提升我认为是这样)。 近期刷榜方法 如果大家有关心今年的ACL,会发现摘要相关的论文很多,前段时间还看到丕子老师发微博感叹。不仅数量多,今年在CNN/Dailymail数据集上还有个不小的涨幅,在本文的最后一起来看下是什么神奇的方法。 近几年的刷榜方法我认为可以总结为更加充分地挖掘数据集提供的信号,同时在模型上结合生成模型和判别模型。 我们先从一篇直白的论文Abstractive Summarization with Combination of Pre-trained Sequence-to-Sequence and Saliency Models讲起。这篇论文把原文和摘要中都出现的token认为是重要token,用这个作为监督信号,训练了一个重要性模型(saliency models)。然后尝试了多种组合方式来在解码器上使用重要性模型产生的辅助信号。 这里解释一下里面出现的几种方式: SE,Selective Encoding:用重要性得分来控制编码器输出 SA,Selective Attention:用重要性得分来控制解码器cross attention SEG, Sentence Extraction then Generation:相当于精简原文输入 CIT, Conditional Summarization Model with Important Tokens:把重要的Token选出来跟原文一起输入编码器 来看一下各种方式的表现,只是单独增加一个siliency model训练任务(MT)就提高了1个点的R1,CIT表现也不错,提升接近两个点。 有了上面这篇文章作为基础,我们来看下目前的SOTA,BRIO: Bringing Order to Abstractive Summarization,他们组其实工作是一脉相承的,感兴趣可以看下他们之前的论文GSum: A General Framework for Guided Neural Abstractive Summarization和SimCLS: A Simple Framework for Contrastive Learning of Abstractive Summarization。...

July 3, 2022 · 1 min · Yuanhao

文本生成专题1:基础知识

大家好,好久不见,疫情封控在家两个月写文章都不利索了😂。 在这段时间我反思了一下之前写的东西,基本是最近用了什么、看到什么就写什么,感觉系统性比较差。后面我打算少写一些零散话题,多总结一些更有体系的内容。第一个小专题我想总结一下我最近关注比较多的领域,文本生成。文本生成领域很广泛,我主要会聚焦在文本摘要(Text Summarization)和数据驱动生成(Data2Text)。 这篇文章是专题第一篇,将介绍以下的内容: [TOC] 除了第二部分外都比较像科普文,没有相关技术背景的朋友也可以看懂。 问题定义和数据集 摘要 摘要这个问题比较好理解,就是把长的文章,例如学术论文、新闻等等缩写成更短的文本,并且保留重要的信息。 摘要领域常见的典型数据集CNN/DailyMail, arXiv, Pubmed, XSUM等。其中CNN/DailyMail的原始文本是大约几百个词的新闻,摘要(ground truth)是人写的,大概五六十个词。中间两个都是来自学术论文的数据集,原始文本比新闻长不少。学术论文通常都需要作者提供摘要,一般一百来个词,天然适合拿来做摘要的数据集。X-SUM是里面摘要长度最短的数据集,基本是一句话的长度。还有一些数据集,大家可以参考papwerswithcode。 数据驱动生成 数据驱动生成则是给定一些结构化的数据,例如餐馆信息、实体间的关系等,生成一段自然语言。 这个领域典型的数据集有WebNLG和E2E。WebNLG的每条样本会提供一系列用三元组描述的实体及关系,以及一段陈述三元组表达事实的自然语言文本作为标签。 E2E数据集则提供了成对的餐馆结构化信息和自然语言描述。自然语言描述相比于WebNLG数据集更简短一些。更多数据集大家参考这个页面。 常用的评价指标 除了数据集,要理解一个技术的发展水平,另一个很重要的方面是理解评价指标。评价机器生成的文本,最常用的指标是ROUGE和BLEU。 ROUGE 摘要里最常用的指标是ROUGE,它的全称是Recall-Oriented Understudy for Gisting Evaluation,是在2004年的论文ROUGE: A Package for Automatic Evaluation of Summaries里提出的。从名字可以看出来它比较关注recall。它有很多形式,在论文里比较常看到的有ROUGE-N(N=1,2,3…)和ROUGE-L两种。 对于ROUGE-N,计算方式就是生成结果和参考文本中都出现的ngram占参考文本ngram的比例。ROUGE-L比较麻烦,需要考虑最长公共子串,但相比于预设ngram大小的ROUGE-N有一定的优势。单句的ROUGE-L是最长子串长度除以参考句的长度,举一个论文里的例子 S1. police killed the gunman S2. police kill the gunman S3. the gunman kill police 假设S1是参考句,那S2和S3的ROUGE-2都是1/3(匹配上了the gunman),但S2的ROUGE-L是3/4比S3的2/4大,实际情况确实是S2更好一些。 可以看出ROUGE,特别是ROUGE-N是比较考察和参考文本用词的一致性的,理论上不是个语义上的评价,这也和后面会写到的一些trick有直接的关联。 ROUGE指标的python实现可以参考这个repo,看代码应该是是最清楚的。 BLEU 在Data2Text领域常用的指标是BLEU,全称是bilingual evaluation understudy,从名字也能看出来,最开始是在机器翻译的评价里被广泛使用。BLEU像是一个precision指标,基本是在算生成结果和参考文本都出现的词和参考文本长度的比值。主要考虑的问题是多次匹配,例如 candidate:ha ha ha reference: only saying ha is not good candidate只有一种词,且在标签中出现了,但若BLEU是100分,显然是不合理的。因为ha在reference中只出现一次,所以只能匹配一次,所以BLEU是1/3。 另一个要解决的问题是防止candidate过短而导致的高分。因为precision的分母是自己ngram的数目,只输出有把握的词是可以提高分数的。这里引入了一个叫brevity penalty的参数。这个参数的计算公式如下:...

May 25, 2022 · 2 min · Yuanhao

面向Meta全公司工程师的AI优化平台解析

原作者:Igor Markov, Norm Zhou 人工智能是使现代软件系统和产品尽良好运行的一个重要部分,从改善用户体验到使计算基础设施更有效率都能看见AI的影子。无论是减少延迟,提高视频流的质量,还是精简界面以满足特定人的需求,今天的人工智能往往比人类精心构建的启发式策略更有效。但是,为了在我们的产品中更有效地利用人工智能,我们需要解决几个挑战:系统必须适应没有机器学习背景的软件工程师;它必须提供机制,为许多不同的产品目标进行优化,这可能不同于封闭形式的机器学习损失函数;它必须区分数据中的因果关系;它必须有效地扩展,以训练、托管和监测大量的人工智能模型。 为了满足Meta公司的这些需求,我们建立了一个端到端的人工智能平台,名为Looper,具有易于使用的优化、个性化和反馈收集的API。Looper支持整个机器学习的生命周期,从模型训练、部署和推理一直到产品的评估和调整。与其围绕人工智能模型重建我们现有的产品,Looper使我们能够升级它们,使用人工智能进行个性化优化。Looper平台目前承载了700个AI模型,每秒产生400万个AI输出。 让智能策略为应用程序所用 Meta的不同服务每天有数十亿人在使用,每个人都有不同的兴趣和偏好。Looper使我们能够以前所未有的规模定制其中的许多 “开箱即用 “的服务,而不需要复杂的专业代码。 让使用产品的人在用户界面菜单上有几十个选择,会使产品失去吸引力,无论它提供多少价值。但不同的人对菜单的偏好是不同的。同样,适时地将可能被用户浏览的内容预取到移动设备上,可能会极大地改善我们产品的用户体验,但要做到这一点而不使设备的硬件资源不堪重负,需要准确地预测什么会是最感兴趣的。 为了以可扩展的方式支持实时智能策略,Looper提供了几个功能。 Looper的目标是为具有适度数据规模和模型复杂性的用例提供易用性和快速部署模型。 它支持各种模型类型,托管和训练众多模型和决策策略。 它通过使用监督学习或强化学习,支持广泛的机器学习任务(分类、估计、价值和序列预测、排序、planning)。结合模型管理基础设施,我们的自动化工具(AutoML)选择模型和超参数以平衡模型质量、大小、推理时间等。Looper涵盖了从数据源到产品影响的范围,通过因果实验进行评估和优化。 它是一个声明式的人工智能系统,这意味着产品工程师只需要声明他们想要的功能,系统就会根据声明来填充软件的实现。在内部,Looper依赖于我们的策略蓝图抽象,它将特征、标签、模型和决策策略的配置合二为一,并维护这种联合配置的多个版本。这支持更全面的优化,捕捉不同版本之间的兼容性,并实现智能策略的整个生命周期的免编码管理。蓝图能够使用强大的实验优化系统对黑盒产品指标进行垂直优化。 其他人工智能平台通常以批处理模式进行离线推理,而Looper则是实时操作。 许多人工智能系统使用统一的数据工作,如像素或文本,但不同的产品往往有非常不同的元数据,往往来自不同的来源。此外,元数据的模式变化很快,需要定期在新数据上重新训练人工智能模型。 A/B测试,以评估许多不同类型的模型和决策规则,包括那些由上下文bandit使用的模型,以模拟一个或多个目标的预测的不确定性;或强化学习,以优化长期、累积的目标。 与传统的端到端人工智能系统不同,Looper使Meta公司的工程师和其他人能够跟踪一个模型在软件栈中的实际使用情况,并对建模框架的所有方面进行实验–从指标选择到策略优化的所有过程。为了做到这一点,Looper将常见的端到端定义扩展到软件层,这样,模型架构、特征选择参数可以在模型质量和计算资源之间进行多目标权衡优化。为了优化长期的产品目标,工程师可以调整在做实时决策时对不同输入的重视程度。我们的平台使得使用应用于整个管道的AutoML技术来优化这些和其他参数成为可能。 用于部署智能策略的Looper平台 与用于视觉、语音和自然语言处理的重量级人工智能模型不同的是,Looper使用的是可以重新训练并在共享基础设施上快速大量部署的模型,这些模型有利于离线推理和批量处理。我们的平台将用户互动和系统互动的元数据解释为监督学习的标签或强化学习的奖励。 Looper追求的是快速上线、稳健部署和低能耗的多种智能策略的维护,其中的积极影响是直接在应用方面进行测量和优化。应用程序代码与平台代码分离,Looper利用现有的水平AI平台,如PyTorch和Ax,为机器学习任务提供可互换的模型。 为了使智能策略获得成功,我们需要一种方法来评估它们,并在结果不够好时加以改进。这种评估是基于产品指标进行的。在某些情况下,每个决策都可以被检查,因此,好的和差的决策可以作为智能策略学习的例子(通过监督学习)。然而,有些产品指标追踪的是长期目标(如每日活跃用户),无法追踪到具体的决策。这两种情况都可以由Looper来处理,而使用实时数据则尤为重要。访问Meta的监控基础设施有助于发现不可预见的副作用。在我们的平台上,产品开发者定义决策空间,允许平台自动选择模型类型和超参数设置。在不影响用户的情况下,对模型进行训练和评估,并对其进行改进,直至可以部署。在产品使用前,新训练的模型会被关起来(部署在影子流量上)–这种模型在记录的特征和观测值的抽样子集上进行评估,并计算出离线质量指标(例如回归任务的MSE)。这有助于避免在部署较新的模型时降低模型质量。 智能策略的应用和影响 我们的垂直机器学习平台承载了来自水平平台的中等规模的模型,以便改善软件系统的各个方面。这些模型的部署只需很少的工程努力,并且不需要特定模型的基础设施来维护。Looper目前被Meta公司的90多个产品团队使用,这些团队部署了690个模型,每秒进行400万次预测。 应用案例可分为五类,按频率递减排列: 个性化体验是根据用户的参与历史而定制的。例如,一个产品可能只向那些可能使用它的人突出显示与购物有关的内容(但这种内容所有用户都可以通过菜单访问)。 排名对项目进行排序,以提高用户的效用,例如,为浏览者提供个性化的候选项目。 根据预测的使用可能性,预取/预计算数据/资源(4.1节)。 通知/提示可以只发送给认为有帮助的用户。 值估计预测回归任务,例如,数据查询的延迟或内存使用。 下图按资源类别对活跃的Looper用例的资源消耗(Y轴上的服务器数量)进行了比较。 各个产品团队的人工智能专业知识各不相同,从初学者到经验丰富的人工智能工程师都有。而使用Looper平台的团队中只有15%为人工智能工程师。对于没有生产人工智能经验的团队来说,一个易于使用的人工智能平台往往是采用的决定性因素,而人工智能的投资在证明有用后继续进行。我们的平台在高级服务背后处理关于软件升级、日志、监控等问题,并释放出巨大的生产力改进。对于有经验的人工智能工程师来说,智能策略平台通过自动化重复性的耗时工作来提高生产力:编写数据库查询,实施数据管道,设置监控和警报。与专精型的系统相比,它可以帮助产品开发人员推出更多的AI用例。无论之前是否有人工智能经验,成功的平台采用者在短短几天内就配置了最初的机器学习模型,迅速开始收集训练数据,然后在短短几个月内完善他们的模型并推出新产品。 让工程师和产品开发人员更容易实现规模化的人工智能 将产品决策的自我优化智能策略嵌入到软件系统中,从而提高用户体验,优化资源利用,并支持新的功能,这其中存在巨大的机会。我们的人工智能平台Looper解决了产品驱动的端到端机器学习系统的复杂性,促进了智能策略的大规模部署。它在数据可用性、简易配置、明智地使用可用资源、减少工程努力和确保产品影响方面提供了直接、切实的好处。平台采用者尤其被通过因果推理和资源开销测量对产品影响评估的广泛支持所吸引。 Looper使软件工程师更容易获得智能策略,并使产品团队能够以自我服务的方式建立、部署和改进人工智能驱动的能力,而无需人工智能专业知识。我们将继续开发这个平台,以便我们能够以新的方式利用人工智能来改善Meta的产品和服务。

April 24, 2022 · 1 min · Yuanhao