斯坦福-CS224U-自然语言理解笔记-全-
斯坦福 CS224U 自然语言理解笔记(全)
1:引言与自然语言理解的演进(第一部分)🚀



在本节课中,我们将要学习自然语言理解领域的概览,回顾其发展历程,并探讨当前研究的关键驱动力与核心概念。
欢迎来到自然语言理解课程。当前是进行自然语言理解研究的一个奇特、美妙,或许也令人担忧的时刻。我今天的首要目标是让我们沉浸于这个时刻,思考我们如何走到今天,以及现在进行研究是怎样的体验。这将为我们思考课程内容以及如何让你们以自己选择的方式参与当前人工智能的诸多方面奠定良好基础。这是一个尤其具有影响力的时刻。本课程以项目为导向,我相信我们可以引导你们所有人达到能够做出有意义贡献的水平,以令人兴奋且具有影响力的方式参与到这个持续发展的时刻中,这是本课程的根本目标。
现在,让我们思考当前时刻。这对我来说总是一个反思的时刻。我于2012年开始教授这门课程,现在看来那似乎是很久以前了,但在我的个人经历中感觉并不遥远。然而,就课程内容而言,2012年确实感觉像是很久以前。在2012年的第一天,我有一张幻灯片看起来是这样的。我说,这是进行自然语言理解研究的一个激动人心的时刻。我注意到,在经历了很长一段人们主要关注句法等内容的时期后,该领域重新引起了广泛兴趣。当时普遍认为自然语言理解即将取得突破并产生巨大影响,这与商业事务相关,并且斯坦福毕业生的就业市场非常火爆。这种说法的很大一部分源于当时我们正处于Siri刚刚推出、Watson在《危险边缘》节目中获胜的时刻,我们拥有所有这些家用设备,所有科技巨头都在这个新兴的自然语言理解领域展开竞争。
让我们快进到2022年。我当时确实觉得应该更新那张幻灯片,将其表述为“这是有史以来最激动人心的时刻”,而不仅仅是“一个激动人心的时刻”。但我强调了相同的事情:我们再次感受到该领域重新引起了兴趣,尽管现在这种兴趣已经极度强化;行业兴趣也是如此,此时的行业兴趣让2012年的情况看起来微不足道。系统变得非常令人印象深刻,但我在此仍然坚持认为,它们很快会暴露出弱点,自然语言理解的核心问题远未解决,因此重大突破仍在未来。我要说的是,即使自2022年以来,我们也感觉到加速,一些我们过去关注的问题感觉不那么紧迫了。我不会说它们已经解决,但随着模型变得更好,我们在这些问题上取得了很大进展。但对我来说,这意味着未来有更多令人兴奋的事情,我们可以处理甚至更雄心勃勃的问题。你们会看到,我已经尝试彻底改革这门课程,对我们可能承担的问题类型抱有更大的雄心。
但我们确实生活在这类事物的黄金时代。即使在2022年,我也不确定我会预测什么,更不用说2012年了,我们会拥有像DALL-E 2这样令人难以置信的模型,它可以将文本转换成这些令人惊叹的图像;语言模型,它们或多或少将成为我们本季度的明星;还有可以从自然语言生成代码的模型;当然,正如我们此刻所见,与网络搜索相关的整个行业正在围绕自然语言理解技术重塑。因此,当我们在2012年开始这门课程时,这感觉像是自然语言处理领域的一个小众领域,而现在感觉整个自然语言处理领域,甚至在某些方面是整个人工智能领域,都聚焦于这些自然语言理解问题,这对我们来说是令人兴奋的。


这里还有另一个反思的时刻。多年来,在这门课程中,我们使用简单的例子来突出现有模型的弱点。一个经典的例子就是这个问题:“哪些美国州不与任何美国州接壤?”这里的想法是,这是一个简单的问题,但由于其中的否定词“不”,它可能对我们的语言技术来说很难。
1980年有一个著名的系统叫做Chat-80,它是一个符号系统,代表了自然语言处理研究的第一个主要阶段。你们可以在这里看到该系统的一个片段。Chat-80是一个令人难以置信的系统,因为它可以回答诸如“哪个与地中海接壤的国家与一个被人口超过印度的国家接壤的国家接壤?”这样的问题。我在这里给出了答案:土耳其,至少根据1980年代的地理知识。但如果你问Chat-80一个简单的问题,比如“哪些美国州不与任何美国州接壤?”,它只会说“我不明白”。它是一个表达能力极强的系统,但也很僵化,正如你们从第一个问题所看到的,它可以非常深入地处理某些事情,但对于超出其能力范围的事情,它会完全失败。
那是1980年代。让我们快进到2009年左右,这门课程启动的时候,Wolfram Alpha出现了。这被认为是一种革命性的语言技术。该网站仍然存在,令我惊讶的是,如果你搜索“哪些美国州不与任何美国州接壤?”,它仍然会给出以下行为:它只是给你一个美国州的列表,这表明它没有能力理解所提出的问题。
那是2009年。所以我们从1980年走到了2009年。好吧,让我们看看2020年。这是OpenAI的第一个模型Ada:“哪些美国州不与任何美国州接壤?”答案是“没有”,然后它开始胡言乱语:“美国边境不是州边境。”它这样持续了很长时间。但关于Babbage模型,这仍然是2020年。“哪些美国州不与任何美国州接壤?美国州的名字是什么?”然后它真的开始偏离主题,同样持续了很长时间。那是Babbage模型。如果你看到这个输出,至少对我来说,可能会动摇我对这是一种可行方法的信心。但团队坚持了下来。
我想,2021年,这是Curie模型:“哪些美国州不与任何美国州接壤?”它有一个问题,它开始列举东西,但它确实说了“阿拉斯加、夏威夷和波多黎各”,这是一个比第一个答案更有趣、更令人印象深刻的答案。它仍然在理解如何回应方面有些问题,但看起来我们看到了一些信号。
DaVinci-instruct-beta,这是2022年。我认为重要的是,这是第一个名字中带有“instruct”的模型,我们稍后会讨论这一点。“哪些美国州不与任何美国州接壤?”“阿拉斯加和夏威夷。”从2020年到2022年,我们看到了这种惊人的飞跃,使得之前的一切都相形见绌。最后是text-davinci-003,这是当时最新的最佳模型之一(至少在两个月前):“哪些美国州不与任何美国州接壤?”“阿拉斯加和夏威夷是仅有的两个不与任何其他美国州接壤的美国州。”确实是一个非常令人印象深刻的答案。如果你们思考一下我给出的这段简短历史,这是该领域正在发生的事情的一个缩影:很长一段时间没有太大进展,伴随着一些炒作,而现在在最近几年,这种快速进步正在发生。
你们知道,这只是一个例子,但这样的例子成倍增加,我们可以量化这一点。这是另一个令人印象深刻的案例:我问DaVinci-002模型:“斯坦福大学成立于哪一年?它何时招收了第一批学生?现任校长是谁?它的吉祥物是什么?”这确实是一个复杂的问题。它在所有方面都给出了流畅且事实正确的答案。这是DaVinci-003模型,它在几周前还是最佳模型,它给出了完全相同的答案,非常令人印象深刻。
在本课程中,你们会在网站上看到,我们建议课程开始时阅读的一篇经典论文是Hector Levesque的《论我们的最佳行为》。这篇文章的核心思想,本质上借鉴了Terry Winograd和Terry Winograd的图式,即我们应该提出一些例子来测试模型是否深刻理解,特别是要超越对训练数据统计信息等的简单记忆,真正探究它们是否理解世界是什么样的。Levesque和Winograd的技术是提出非常不可能的问题,而人类对此有非常自然的答案,例如Levesque提出的问题之一是:“鳄鱼能跑障碍赛吗?”也许这是你们从未想过的问题,但你们在这个群体中可能有一个相当一致的答案。“鳄鱼能跑障碍赛吗?”在这里,我问了另一个Levesque的问题:“职业棒球运动员被允许在他们的帽子上粘小翅膀吗?”你们可以思考一下。DaVinci-002模型当时说:“没有规则禁止这样做,但这并不常见。”当时这对我来说似乎是一个非常好的答案。然而,当DaVinci-003引擎出现时,这开始让我担心了:“不,职业棒球运动员不允许在他们的帽子上粘小翅膀。美国职业棒球大联盟对球员制服和帽子的外观有严格规定,任何对帽子的修改都是不允许的。”好吧,我以为我对这个感觉良好,但现在我自己甚至都不知道答案是什么了。职业棒球运动员被允许在他们的帽子上粘小翅膀吗?我们有两个非常自信但相互矛盾的答案,来自两个关系非常密切的模型。我希望这开始让我们有点担心,但仍然令人印象深刻。你们可以查一下。是的,我有几个案例,这肯定是我们进行的一个有趣实验。让我稍后展示我得到的回复。
不过,我想,如果你们看过电影《银翼杀手》,这开始感觉像是为了弄清楚我们正在交互的代理是人类还是人工智能,我们需要非常复杂的面试技巧。图灵测试早已被遗忘,现在我们进入了试图通过对我们与它们交互的事情类型非常聪明来弄清楚我们正在与哪种代理交互的模式。
这有点像是轶事证据,但我认为进步的画面也得到了该领域正在发生的事情的支持。让我从这个故事开始,谈谈我们的基准测试。这里的标题是:我们的基准测试,即我们用来探测模型的任务和数据集,正以前所未有的速度饱和。我将阐明“饱和”的含义。我们这里有一个小框架:沿着X轴是时间,可以追溯到20世纪90年代;沿着Y轴是一个标准化的度量,表示距离我们称为“人类表现”的红色零线的距离。每个基准测试都以自己特定的方式设定了所谓的人类表现估计。我认为我们应该对此持怀疑态度,但尽管如此,这将成为我们衡量进步的一个标志。
第一个数据集,MNIST,这是像数字识别这样的著名任务,于20世纪90年代在人工智能领域推出。我们花了大约20年时间才看到一个系统在这种非常宽松的意义上超越了人类表现。Switchboard语料库,这是从语音到文本的任务,故事非常相似,于90年代推出,我们花了大约20年时间才看到一个超人的系统。ImageNet,我相信是在2009年推出的,我们花了不到10年时间就看到一个系统超越了那条红线。


现在进步将真正加速。SQuAD 1.1,斯坦福问答数据集,于2016年推出,大约三年时间就在这个意义上饱和了。SQuAD 2.0是该团队尝试提出一个更难的问题,其中包含无法回答的问题。但系统超越那条红线的时间甚至更短。然后我们有了GLUE基准测试,这是自然语言理解中一个著名的多任务基准测试。当它推出时,我们很多人认为GLUE对现有系统来说太难了,看起来这可能是一个会持续很长时间的挑战。但系统超越人类表现只用了不到一年时间。回应是SuperGLUE,但它饱和得甚至更快。
现在,我们可以对这个“人类表现”的概念持尽可能的怀疑态度,我认为我们应该思考这样称呼它是否公平。但即使抛开这一点,这看起来无疑是一个进步的故事。我们在2012年拥有的系统甚至无法进入GLUE基准测试,更不用说取得这样的分数了。所以,有意义的事情已经发生。你们可能会认为,按照人工智能的标准,这些数据集有点旧了。这是Jason Wei的一篇帖子,他在其中评估了我们最新、最强大的大型语言模型在一系列主要是新任务上的表现,这些任务实际上是为了压力测试这类新型超大型语言模型而设计的。Jason的观察是,我们看到这些模型在超过100个任务上出现了涌现能力,尤其是我们最大的模型。不过,重点是我们再次认为这些任务会持续很长时间,而我们看到的却是系统一个接一个地,肯定在取得进展,在某些情况下,达到了我们为人类设定的标准。
这又是一个令人难以置信的进步故事。所以我希望这能激励你们,也许有点令人生畏,但我希望从根本上激励你们所有人。接下来我想问你们的问题是:到底发生了什么?是什么推动了所有这些突然的进步?让我们感受一下,这将作为课程本身的基础。
在我开始之前,有什么问题或评论吗?有什么我可以澄清或我遗漏的关于当前时刻的事情吗?Bard做得很好。不过,也许我们应该作为一个群体反思一下“做得很好”意味着什么。我的问题是,当你们说它做得很好时,美国职业棒球大联盟关于球员在帽子上粘东西的规则是什么?你们找到了实际的规则吗?“不”是我……你们找到了吗?我没有找到,是Bard找到了那条规则并给了我那个数字。是的,这将是我们面临的问题。我可以得到,哪个是正确的?幻觉。好吧,我将向你们展示,OpenAI模型会给我提供链接,但这些链接无处可去。你们指出的,我认为是一个日益严重的社会问题:这些模型向我们提供看似证据的东西,但很多证据都是捏造的,这比不提供任何证据更糟糕。我真正需要的是一个了解美国职业棒球大联盟的人告诉我关于球员和他们的帽子的规则是什么。我希望从一个专家人类那里得到,而不是一个专家语言模型。成立。那是什么,我们可以谷歌吗?不过要小心如何谷歌,我想这是2023年的教训。
好吧,到底发生了什么?让我们开始在这方面取得一些进展。再次,首先是一点历史背景。我有一个时间线,沿着X轴可以追溯到20世纪60年代,这大致是该领域本身的开始。在那个早期时代,本质上所有的方法都基于符号算法,就像我展示的Chat-80。事实上,你们知道,这某种程度上是在斯坦福大学开创的,由那些开创人工智能领域本身的人们开创。这种本质上对这些系统进行编程的范式一直持续到20世纪80年代。
在90年代和21世纪初,我们迎来了整个人工智能领域,进而自然语言处理领域的统计革命。那里的重大变化是,我们不再用所有这些规则来编程系统,而是要设计机器学习系统,试图从数据中学习。在底层仍然涉及大量编程,因为我们会编写许多特征函数,这些是帮助我们检测数据特征的小程序,我们希望我们的机器学习系统可以从这些特征函数的输出中学习。但最终,这是完全数据驱动的学习系统的兴起,我们只是希望某种优化过程能为我们带来新的能力。


下一个大阶段是深度学习革命,这大约始于2009-2010年。可以肯定的是,斯坦福大学处于这一领域的前沿。当时感觉这是一个巨大的变化,但回想起来,这与这里的模式并没有太大不同。只是我们现在用真正的大模型、非常深的模型取代了那个简单模型,这些模型具有从数据中学习事物的巨大能力。我们也开始看到进一步远离那些特征函数、远离编写程序,更多地转向一种模式,即我们只希望数据和优化过程能为我们完成所有工作。


然后发生的下一件大事,我想可以带我们到大约2018年,是这种模式:我们有很多预训练参数。这些可能是大型语言模型或计算机视觉模型的图片。当我们构建系统时,我们基于这些预训练组件构建,并用这些特定于任务的参数将它们拼接在一起。我们希望当它们全部组合在一起,并且我们在一些特定于任务的数据上进行一些学习时,我们能得到一些受益于所有这些预训练组件的东西。然后,我们现在似乎所处的模式,我想让我们批判性地反思,是这种模式:我们将用某种可能是一个巨大的语言模型来取代一切,并希望那个东西,那个巨大的黑盒子,能为我们完成所有工作。我们应该批判性地思考这是否真的是前进的道路,但这无疑是时代精神。
问题:是的,如果你认为值得的话,你能回到上一张幻灯片,也许用一个更全面的例子解释一下那一切意味着什么吗?我有点跟不上。我们稍后再做。不过,现在的重点真的是从这里的转变,我们主要是从零开始学习我们的任务;到这里,我们有像BERT这样的东西参与其中,我们有预训练组件,我们希望这些模型处于一个能让我们在试图解决的问题上占得先机的状态。这是发生的大事,你们会看到人们强调发布模型参数。你们知道,在这个早期阶段,比如这里,没有关于发布模型参数的讨论,因为人们训练的模型大多只适用于他们设定的任务。随着我们进入这个时代,然后肯定是这个时代,这些东西意味着像通用语言能力或通用计算机视觉能力,我们将它们拼接成一个能够做比以往任何系统都更多事情的系统。
所以,这就是现在这一切背后的感觉。当然,从这里开始的最后阶段是Transformer架构。让我了解一下房间里的情况,有多少人以前接触过Transformer?是的,如果你们在做这项研究,这几乎是不可避免的。这是它的一个示意图,但我现在不会讲解这个示意图,因为从周三开始,我们将有一整堂课专门来拆解这个东西并理解它。我现在能告诉你们的是,我期望你们经历以下旅程,这是我们所有人都经历的:Transformer到底是如何工作的?它看起来非常非常复杂。我希望我能让你们达到这样的感觉:“哦,这实际上是相当简单的组件,以一种相当直接的方式组合在一起。”这是你们旅程的第二步。真正的顿悟来自于:“等等,这到底为什么有效?”然后你们就和整个领域一起,试图理解为什么这些简单的东西以这种方式组合在一起被证明如此强大。
发生的另一件大事,这在某种程度上一直潜伏着,可以追溯到人工智能的起源,特别是与语言学相关,是自监督、分布学习的概念。因为这将为我们打开一扇门,让我们能够以最普遍的意义从世界中学习。在自监督中,你们模型的唯一目标是从其训练序列中的共现模式中学习。这些序列可以是语言,但也可以是语言加上传感器读数、计算机代码,甚至是嵌入这个空间的图像,只是符号。模型的唯一目标是从它们包含的分布模式中学习,或者对于许多这些模型来说,是为你们输入的任何数据中经过验证的序列分配高概率。对于这种学习,我们不需要做任何标注。我们只需要有大量的符号流。然后当我们从这些模型中生成时,我们是从它们中采样。这就是当我们想到提示并得到回复时都会想到的。但底层机制至少部分是这种自监督的概念。我要再次强调,因为我认为这对于为什么这些模型如此强大真的很重要:符号不一定只是语言,它们可以包含许多其他可能帮助模型拼凑出我们所生活的世界的完整图景以及语言与这些世界片段之间联系的东西,仅仅通过这种分布学习。
这被证明如此强大的结果是大规模预训练的出现,因为现在我们不再受限于对标注数据的需求。我们只需要大量非结构化格式的数据。这真正始于静态词表示的时代,如Word2Vec和GloVe。事实上,这些团队,尤其是GloVe团队,他们非常有远见,因为他们不仅发布了论文和代码,还发布了预训练参数。这对该领域来说真的是全新的:这种用模型工件赋能人们的想法。人们开始将它们用作循环神经网络等的输入,你们开始看到预训练作为在困难任务上表现出色的重要组成部分。
有一些前身我下次会谈到,但上下文表示真正重要的时刻是ELMo模型,这篇论文是《深度上下文化词表示》。我记得2018年在新奥尔良举行的北美计算语言学协会会议上,在最佳论文会议上,他们还没有宣布哪篇最佳论文将获得杰出论文奖,但我们都知道会是ELMo论文,因为他们在困难任务上微调ELMo参数所报告的提升简直令人震惊,是那种你们真的只在一代研究中看到一次的事情。或者我们当时是这么想的,因为第二年,BERT出来了,同样的事情,我想同样获得了最佳论文奖。这篇论文甚至在发表之前就已经产生了巨大影响,他们也发布了他们的模型参数。ELMo不是基于Transformer的,BERT是基于Transformer的一系列事物中的第一个,再次将所有水平提升到甚至高于ELMo带给我们的高度。
然后我们有了GPT,这是第一篇GPT论文,然后快进一点,我们有了GPT-3。那是在以前难以想象的规模上进行预训练,因为现在我们谈论的是,对于BERT模型,1亿个参数,而对于GPT-3,远超过1000亿,数量级不同。我们开始看到涌现能力。

模型大小的事情很重要。再次,这是一种进步的感觉,也许也是绝望。我想我可以稍微提振你们的精神,但我们应该思考模型大小。所以我再次沿着X轴标出年份,沿着Y轴是模型大小,从1亿到1万亿,采用对数刻度。所以
2:课程概览与核心概念 🧠



在本节课中,我们将继续学习斯坦福大学《自然语言理解》课程的核心内容。我们将回顾课程网站结构,深入探讨课程后续单元的主题,并初步了解Transformer模型背后的核心思想。
课程网站与资源导航 🌐

上一节我们介绍了课程的基本框架,本节中我们来看看课程的核心资源平台——课程网站。

课程网站是课程所有资源的中心枢纽。网站顶部包含政策页面、项目页面、背景材料索引、YouTube录屏、幻灯片以及实践材料。此外,课程还设有一个播客,欢迎学生推荐访谈嘉宾。
网站左侧提供了访问课程所需各种系统的快捷入口:
- Ed论坛:用于课程讨论。
- Canvas:存放课程录屏和测验。
- Gradecope:用于提交主要作业和项目,并参与“竞赛”。
- 课程GitHub:存放课程代码,是作业和原创工作的基础。

如需联系教学团队,请优先使用讨论论坛或统一的团队邮箱,这有助于高效管理工作量。

网站中间部分链接了所有课程材料:
- 第一列:幻灯片和Notebook等。
- 第二列:核心阅读材料(主要是论文)。虽然阅读量很大,但这些论文非常重要且富有启发性。
- 第三列:作业链接。
课程后续单元与前沿主题 🚀


在回顾了Transformer和检索增强的上下文学习之后,课程将进入更多样化的前沿主题。
第三单元:组合泛化
第三单元将聚焦于组合泛化,这是一个全新的主题。我们将重点关注COGS基准测试。这是一个相对较新的合成数据集,旨在压力测试模型是否真正学会了解决语言问题的系统性方法。
COGS本质上是一个语义解析任务。输入是一个句子(例如“Lena gave the bottle to John”),任务是学习如何将这些句子映射到其逻辑形式。

COGS的有趣之处在于它提出了困难的泛化任务。例如,在训练中模型可能看到“Lena”作为主语,而在测试时看到“Lena”作为宾语。尽管这些句子非常简单,但模型在这些泛化任务上的表现却极具挑战性。

以下是COGS累积排行榜的部分数据,显示了模型在不同泛化任务上的表现:
| 模型 | 整体准确率 | 宾语介词短语到主语介词短语泛化 |
|---|---|---|
| 系统A | 较高 | 0% |
| 系统B | 较高 | 0% |
| ... | ... | ... |
可以看到,在“宾语介词短语到主语介词短语”这一看似简单的泛化任务上,许多新系统的得分是零。这表明即使对我们最好的系统来说,这仍然是一个极其困难的问题。
本课程将使用COGS的一个变体——ReCOGS。我们认为COGS在某些方面被人为地制造得过难或过易。ReCOGS对原始数据进行了系统性的、保持语义不变的转换,创建了一个我们认为更公平的新数据集。虽然模型在ReCOGS上能取得一些进展,但核心结论不变:这对我们的系统来说仍然极其困难。这个单元将以第三次作业和竞赛结束。
项目阶段与赋能主题
完成常规作业后,课程将进入项目阶段。我们将遵循文献回顾、实验方案(详细规划论文工作的文档)和最终论文的节奏。


为了赋能大家的最终项目,我们将一起探讨几个关键主题。
主题一:更好、更多样化的基准测试
我们需要可靠的测量工具来评估系统性能,这意味着需要优秀的基准测试。数据对于我们的领域就像水和空气一样不可或缺。我们对数据集的要求很高:
- 用于优化模型(训练)。
- 用于评估模型(尤其是当前备受关注的大语言模型)。
- 用于比较模型。
- 通过训练和测试实现新能力。
- 衡量领域进展。
- 用于对语言和世界进行基础科学探究。
我鼓励大家思考数据集,特别是那些在课程背景下作为强大评估工具的数据集。我担心当前仅通过社交媒体上的有趣案例来评估大语言模型的动态。我们需要大量的评估数据集来科学地衡量系统好坏。

当前许多基准测试可能过于简单,导致模型性能迅速超过人类水平估计。这可能是因为过去的评估本质上是“机器任务”而非“人类任务”。我们将讨论对抗性测试和Dynabench等开源努力,旨在开发能真正挑战最佳模型的数据集。


主题二:更有意义的评估
在人工智能领域,我们可能过于关注性能(准确率)。根据古德哈特定律:当一项测量成为目标时,它就不再是一个好的测量。如果我们只关心准确率,就会忽视其他重要方面。
一项关于机器学习研究价值观的调查显示,性能高居榜首,而仁慈、隐私、公平与正义等价值观几乎未被体现。随着系统更广泛地部署,这些方面变得越来越重要。我们需要提升这些原则在评估和实践中的地位。
我们可以设计包含更多维度的排行榜。例如,Dynascore提出了一种综合多个不同维度进行评分的方法。
设想一个评估表格,行是不同的问答系统,列是我们可以衡量的不同方面(例如性能、吞吐量、内存、公平性、鲁棒性)。通过调整不同维度的权重,我们可以得到不同的系统排名。这没有“真正的赢家”,而是反映了我们的偏好排序。我们可以设计符合我们目标的排行榜。


要实现这一点,我们需要可靠的测量工具。例如,公平性是一个复杂、多维的概念,需要更多工作来建立评估基准。
展望未来,我们的评估可以比以往更有意义:
- 从一维到多维:像Dynascore那样综合多个维度。
- 高度情境敏感:根据具体情境调整对不同维度的重视程度。
- 由用户设定评估标准:由系统的使用者,而非研究人员,来设定评估条款。
- 由用户做出判断:用户根据自身表达的偏好选择系统。
- 基于人类任务:评估系统在模糊和依赖情境下,以类人方式进行讨论和裁决的能力。
主题三:可解释性
随着模型部署到现实世界,理解它们变得至关重要。目前我们主要进行行为测试(设计测试用例看模型表现),但这存在归纳问题:你永远无法穷举所有情况。
可解释性研究的目标是深入一层,理解模型内部发生了什么,从而了解它们将如何泛化到新情况。虽然模型庞大且不透明,但它们是封闭的确定性系统,我们能够理解它们学到了什么。
可解释性方法应满足两个标准:
- 人类可解释:用人类层面的概念表达。
- 忠实于底层模型:解释需真实反映系统运作。
我们将讨论多种解释方法:
- 训练/测试:行为测试仍然重要。
- 探针:在模型内部表示上训练监督分类器,探索其编码的信息(如生命性、词性)。
- 归因方法:为模型表示的不同部分分配重要性分数。
- 主动操纵方法:主动操纵模型内部状态,以获得因果性见解并深入理解表示。
我强烈倾向于主动操纵方法,因为它能提供因果性见解并丰富地表征模型行为。我们甚至可能讨论互换干预训练,即使用可解释性方法来推动模型变得更好、更系统、更可靠。
Transformer模型的核心思想 ⚙️
接下来,我们将初步了解Transformer模型背后的核心思想。这部分内容在过去需要两周讲解,现在我们将进行概述。
表示学习的演进
自然语言处理中表示学习的演进历程:
- 基于特征的稀疏表示:手动设计特征函数,生成由0和1组成的长向量。
- 基于计数的分布表示:如点互信息、TF-IDF,通过统计文本中的共现模式获得表示。
- 降维与主题模型:如主成分分析、潜在语义分析、LDA主题模型,对计数数据进行降维,捕捉高阶共现概念。
- 学习到的降维表示:如自编码器、Word2Vec、GloVe,使用机器学习算法从计数数据中学习稠密表示。
对于当今的任何任务,你可能会直接使用上下文表示。
为什么需要上下文表示?
静态词向量(如Word2Vec)为每个词分配一个固定向量,但这存在根本问题:词语的意义随上下文而变化。例如,动词“break”在不同句子中有多种含义(打碎、破晓、发布新闻、打破纪录、违法、闯入、打断、收支平衡)。为“break”枚举所有义项并分配静态向量是不现实的。
上下文表示模型拥抱了一个事实:每个词都可以根据其周围的一切获得不同的表示(即不同的向量)。这更符合语言运作的方式,也带来了工程上的成功。
Transformer的关键洞见
- 从高偏差到低偏差模型:领域从强加许多先验假设(如词向量简单相加、从左到右处理、树结构)的模型,转向连接一切、让数据决定重要性的最大化低偏差模型。
- 注意力机制:“注意力就是你所需要的一切”。Transformer用注意力连接(本质上是点积运算)取代了RNN/LSTM中的循环连接,让序列中任何部分都能直接关注任何其他部分。
- 子词标记化:不再使用固定的大词表(如ELMo的10万词),而是将词拆分为子词单元(如BPE、WordPiece)。例如,“encode”可能被拆为“en”和“##code”。这大大减少了词表大小(如BERT只有3万个子词),并依赖于丰富的上下文表示来重建完整词义。
- 位置编码:除了词嵌入,还为序列中的每个标记添加位置编码,以记录其在序列中的位置。这使得同一个词在不同位置具有不同的表示。
- 大规模预训练:在大量数据上训练这些包含子词、位置信息的上下文模型。模型规模和数据量越大,性能往往出现“涌现”提升。
- 微调:针对特定任务,在预训练模型基础上进行微调,而不是从头开始训练。这利用了预训练阶段学到的关于语言和世界的丰富知识。微调会通过反向传播更新(部分或全部)预训练模型的参数。
总结与下节预告 📚
本节课中,我们一起学习了课程网站的资源结构,探讨了组合泛化、基准测试、评估方法和可解释性等后续单元的前沿主题,并初步了解了Transformer模型的核心思想,包括从静态表示到上下文表示的演进、注意力机制、子词标记化、位置编码、预训练与微调等关键概念。


下节课,我们将正式深入Transformer模型的技术细节,详细解析其架构和工作原理。
3:作业1与竞赛概述 🍰

在本节课中,我们将学习课程的第一个作业及其关联的竞赛。目标是让你了解作业的性质,即你将回答的问题类型及其背后的设计思路。这不仅能帮助你完成当前作业,也能为后续作业打下基础,因为它们都遵循相似的节奏和设计哲学。

作业与竞赛概览
本次作业与竞赛的主题是多领域情感分析。我们将在 Jupyter Notebook 中工作,使用 scikit-learn 拟合分类器,并微调通过 Hugging Face 加载的预训练模型参数。
如果你对此不熟悉或需要复习,建议你查看课程网站此页面链接的资料。我们提供了大量资源,包括基础工具、关于科学计算、Python 和 PyTorch 的背景知识、Jupyter Notebook 使用指南。特别是最后一个 Notebook,它将帮助你高效地使用我们的课程代码库,其中包含大量起始代码,能让你用相对较少的编码构建强大的模型。
此外,针对监督学习,我们也有丰富的材料,包括监督学习的背景知识,以及大量面向情感分析的资源,如视频、幻灯片和动手实践的 Notebook。因此,如果你需要入门或复习,请务必查看这些资料,它们将帮助你高效地完成第一个作业和竞赛。
任务设定与数据资源
如前所述,任务设定是多领域情感分析。我们将此问题设定为三分类问题,标签为“正面”、“负面”和“中性”。
为了训练和开发,我们将为你提供三个主要资源:
- Dynasent Round 1:一个大型数据集,包含由众包工作者标注了三元情感的自然发生句子。
- Dynasent Round 2:一个稍小的数据集,包含众包工作者为试图“欺骗”一个高性能情感模型而从头编写的句子,这些句子也经过了众包工作者的单独验证。
- 斯坦福情感树库:一个经典的情感数据集。它以五标签格式发布,我们已将其稍作调整以符合三元情感规范。
以上是你可以用于训练和开发的资源。所有这些都是为了让你参与我们的竞赛。
竞赛测试集与重要方法说明
对于竞赛测试集,你将获得来自上述资源测试集的样本,以及一组来源未知的“神秘”样本。这样设计的目的是提出一个具有挑战性的情感任务,让你真实地感受你的系统在面对训练和开发阶段无法预见的样本时的泛化能力。
本着这种精神,我需要做一个重要的方法论说明。Dynasent 和 SST 的测试集是公开的,这意味着你拥有所有这些样本的标签。我们依赖大家遵守诚信原则,不在竞赛中通过在这些测试集上开发模型来作弊。你只能在测试集上评估一次,并提交结果,之后不能再进行系统调优或额外运行。在我们的领域中,基于测试集性能进行任何形式的模型选择都是错误的做法。正确的做法是:在测试集上运行你的系统一次,然后提交结果。我们领域的科学诚信在很大程度上依赖于大家遵守这一诚信准则。测试集的功能是让我们真实地一瞥你的系统在开发阶段未见过的样本上的表现。因此,你必须将测试集“锁起来”,直到最后才能使用。对于我们的“神秘”样本,我们可以保证这一点,但对于来自这些公开测试集的样本,我们需要依赖这个诚信准则。
作业内容详解
好了,以上就是背景信息。现在我们将开始浏览 Notebook 本身。
数据加载
我们将使用 Hugging Face 的 load_dataset 来加载 Dynasent 轮次以及 SST。如前所述,SST 以五标签格式加载,Notebook 会完成将其重新格式化为三分类问题的工作。
我们还有一个名为 print_label_distribution 的小函数,它会显示某个数据分割的标签分布。例如,这是 Dynasent Round 1 的分布,它是一个大型资源。Dynasent Round 2 稍小一些,而 SST 是这些资源中最小的。
问题1:线性分类器
现在,我们进入作业本身,从问题1——线性分类器开始。在这里,我们将开发相对轻量级的模型,这些模型通常依赖于非常稀疏的特征表示。你可以将它们视为词袋模型,并可以对其进行增强以使其更有趣。
以下是问题1的提纲。我们有四个背景部分,然后是三个子任务。我强烈建议你在开始任务之前先完成背景部分。无论你是需要复习,还是这就是你的日常工作,背景部分都将帮助你熟悉代码并复习核心概念。所以,先完成它们,然后再深入任务。
问题1,任务1:编写特征函数
在背景部分,我们为你写了一个示例函数 unigrams_phi。它接收一个字符串,按空白字符分割该字符串,并基本上只计算得到的单字词(unigram)数量。它返回一个字典,将单字词映射到它们在输入字符串中的计数。这就是我们在使用 scikit-learn 时特征化的基础。
然后,这里的任务是简单地编写一个更好的版本,我们称之为 tweetgrams_phi。其核心是使用 NLTK 中一个非常优秀的分词器,它能很好地处理表情符号和其他类型的标点符号等。这将是一个更优越的特征函数基础。这是一个非常简单的编码任务,目的是激发你的创造力。编写了这个特征函数后,你可能会思考新的分词方式或可以在特征方面做的新事情。这只是一个开始。
关于单元测试的说明
你会注意到,在这个作业中,每一个问题都有一个关联的单元测试,本课程所有作业的每个问题都是如此。所以,请务必使用这些单元测试。这些单元测试扮演着至关重要的角色。用英语完全清晰地说明我们在编码方面的要求是非常困难的,因此,我们依赖这些单元测试。如果你通过了单元测试,那么你就按照我们的定义完成了任务。当你提交时,自动评分器也会给出“健康”的报告,一切都会顺利进行。所以,请利用这些单元测试。它们还能帮助你理解核心概念和问题的其他方面。如果单元测试失败,它们会给你反馈,并总体上帮助你迭代以达到成功的结果。
问题1,任务2:模型训练
首先,你应该完成两个相关的背景部分:特征空间向量化和 scikit-learn 模型。然后,你就可以很好地处理这个特定任务了。这个任务相对简单直接。你需要完成一个名为 train_linear_model 的函数。我们为你提供了详细的文档字符串,并在注释中引导你完成完成该函数所需的步骤。如果你完成了背景阅读并掌握了核心概念,这在概念或编码上都不应该困难。这里的想法是给你一个工具,一个函数,你可以用它来非常高效地训练新的线性模型,以防你决定在开发原创系统时训练大量此类模型。所以,这是直接的编码任务,完成后你就有了这个新工具可以使用。
问题1,任务3:模型评估
这与任务2非常相似。先完成背景部分,然后你应该能很好地处理问题本身。同样,核心任务是完成一个简单的函数,这个函数叫做 assess_linear_model。我们提供了文档,并引导你完成需要采取的步骤。这应该很简单直接,因为这里的想法同样是给你另一个工具,你可以用它来非常高效地评估你训练过的模型,这样如果你决定的话,就可以迭代出真正有趣的模型。
问题2:微调预训练模型
问题1到此结束。现在我们进入问题2,我们将稍微转换一下思路,开始使用 Hugging Face 代码,并微调预训练模型,这里是一个 BERT-mini 模型。
同样,这里有一些背景部分,先完成它们,然后你就可以处理与此问题相关的三个子任务了。
问题2,任务1:批处理分词
这是另一个关于分词的任务:批处理分词。你将使用 Hugging Face 代码。所以,先完成背景材料,然后深入问题。你只需要完成一个函数 get_batch_token_ids。这样做的目的是让你思考 Hugging Face 分词器的工作原理,让你了解它们拥有的各种关键字参数,并总体上让你思考如何在微调模型的背景下有效地使用这些函数。同样,这不是一个困难的编码任务,你只需按照说明操作,并查看 Hugging Face 文档来完成这项工作。
问题2,任务2:获取表示
这同样是关于熟悉 Hugging Face 代码的工作方式,以及像 BERT 这样的模型如何表示样本。所以,你先完成背景部分,然后就可以处理相关任务,即完成一个函数 get_reps。同样,我们引导你完成了步骤,因为这里的想法是让你快速了解这些表示是什么样子,以及你可能会如何使用它们。
问题2,任务3:编写微调模块
最后一个问题类似,但这是最复杂的一个,因为在这里各个部分需要结合起来。问题2,任务3是编写一个微调模块。还有一个关于掩码的背景部分,你应该查看一下,然后你就可以很好地完成这个任务了。你将完成一个我们称之为 BertClassifierModule 的 nn.Module。这包括两部分:你完成 __init__ 方法,这帮助你建立核心计算图;然后你完成 forward 方法,这是我们在此模型中进行推理的核心,并利用你在 __init__ 方法中建立的图。完成后,你就一切就绪了。这只是几行代码,并不复杂。同样,这里的想法是,一旦你有了一个可运行的 BertClassifierModule,你就拥有了可以轻松修改以用于原创系统、做更强大和创造性事情的东西。
额外说明:分类器接口
我们有一个标记为“可选使用”的部分,叫做“分类器接口”。你不需要作为本作业核心问题的一部分训练任何模型,但你可能希望在评估原创系统时训练一些原创模型。我们的分类器接口可以开箱即用地提供帮助,它将允许你使用刚刚编写的 nn.Module 来实际训练数据和进行评估。所以,它是为你准备的一个包装器,并且也很直接。当你迭代你的 nn.Module 时,可以继续使用这个分类器接口。如果你想更深入地了解这些概念,请查看我在本视频开头提到的教程 Notebook。
问题3:原创系统
现在,我们进入核心部分,在我看来也是最激动人心的部分:问题3,原创系统。在这里,你几乎可以做任何你想做的事情。任务是开发一个原创的三元情感分类器模型。对此有很多选择。我们只有一个规则:在开发原创系统的过程中,任何时候都不能使用 Dynasent Round 1、Dynasent Round 2 或 SST 的测试集。它们处于“锁定”状态。
另一个重要说明
这需要是一个原创系统,因此仅仅从网上下载代码、重新训练并提交是不够的。你可以基于他人的代码进行构建,但你必须弄清楚如何用它做一些新的、有意义的事情。我们将根据你尝试原创性、创造性事物的程度来评估你的工作,而不是基于系统的底层性能。这更多是关于在代码、数据和建模技术方面进行创造性探索,而不仅仅是关于在排行榜上名列前茅(尽管我承认那很令人兴奋)。
如果你对“原创性”这个问题感到不确定,我鼓励你与课程团队互动,他们会指导你某件事是否足够原创,如果他们觉得你应该做更多,也许会建议新的方向。
一个技术说明
你会注意到,在这个 Notebook 以及所有作业的 Notebook 中,都有一个“原创系统”单元格。请遵循这些说明。这实际上是在 # start 注释和 # stop 注释行之间添加你的系统描述和系统代码,并且不要破坏这两行。它们至关重要。
我们希望你这样做有几个原因。首先,从技术上讲,你的代码必须在这两个注释之间,这样自动评分器才知道忽略它。如果你把原创代码放在 Notebook 的其他地方,可能会导致 Gradescope 自动评分器失败,因为它不知道如何执行你的代码,或者没有你需要的库等等。其次,我们非常重视这些文本描述。如果你尝试了很多不同的东西,并决定拒绝那些选项而选择一个看起来简单的原创系统,描述尤其重要。你希望为你所做的所有探索性工作获得学分,而只有当你向我们描述这些工作时,你才能获得这些学分。所以,利用系统的文本描述来为你所有的努力获得满分。
参与竞赛
开发了原创系统后,你将把它提交到竞赛中。这实际上就是获取一些新的未标记样本,并在这些样本上运行你的系统。更详细地说,你可以看到这里加载了未标记的样本。然后,任务是添加一个名为 prediction 的新列。确保它叫做 prediction,并且由字符串“positive”、“negative”或“neutral”组成。这些就是你的预测。
完成后,你将其写入磁盘,作为一个具有指定名称的文件,然后上传到 GradeScope。我们将有一个排行榜,显示大家的成绩。
提交文件注意事项
当你提交到 GradeScope 时,请确保提交具有这两个指定名称的文件。保持这些名称非常重要。自动评分器正在寻找具有这些名称的文件。如果它找不到它们,它会报告你没有获得任何学分。所以,请确保你使用这些文件名,然后你应该就一切就绪了。
总结与展望
这是非常令人兴奋的事情。你开发了一个原创系统,并在这些未标记的样本上运行它。当每个人都提交了他们的所有系统后,我们将公布每个人的分数,然后教学团队将做一份报告,向所有人反馈大家做了什么、什么有效、什么无效。这通常是智力上最令人兴奋的部分,因为你可以奇妙地看到人们尝试的所有创造性和原创性的事物。其中一些取得了巨大的成功,一些则惨败。所有这些对于如何更好地解决类似问题都具有极大的启发性。所以,对我来说,这是整个经历中最令人兴奋和最有启发性的部分。

因此,大胆尝试,勇于创新,我们所有人都将从结果中学习。
4:上下文词表示,第一部分:核心思想 🧠

在本节课中,我们将学习上下文词表示的核心思想。我们将回顾从静态词向量到上下文词向量的发展历程,探讨语言学现象如何驱动这一转变,并了解构建现代上下文表示模型的关键技术理念。

从静态表示到上下文表示 📜
上一节我们介绍了自然语言理解的基本概念,本节中我们来看看词表示方法是如何演进的。
词表示方法的发展经历了几个关键阶段:
-
基于特征的经典词汇表示:其特点是表示向量是稀疏的。我们通常手动编写大量特征函数来捕捉词的属性(如情感极性、词性、后缀等),每个特征对应向量中的一个维度。大多数词不具备这些特征,因此向量中大部分是零。
-
基于计数的方法:引入了分布假说。典型方法包括点互信息和词频-逆文档频率。我们从共现计数矩阵(如词-词矩阵或词-文档矩阵)出发,通过数学变换得到更好的表示。这些向量通常也比较稀疏。
-
经典降维方法:引入了稠密表示。典型方法包括主成分分析、奇异值分解和潜在狄利克雷分配。我们通常将第二阶段得到的表示进行压缩,从而获得更稠密、信息量更大、能捕捉高阶分布相似性的表示。
-
学习式降维方法:这是静态向量表示方法的最后阶段,同样产生稠密表示。例如自编码器、Word2Vec或GloVe。这一阶段本质上结合了基于计数的方法和降维技术,从而得到能够捕捉高阶共现关系的强大表示。
如果你想动手实践并深入理解这些方法,可以查看课程网站上链接的页面,那里提供了许多笔记和旧视频。
语言学的启示:词义依赖于上下文 🔤
从语言学角度看,词的意义高度依赖于其使用语境。这直接引出了对上下文词表示的需求。
以下是几个例子,展示了同一个词在不同上下文中的不同含义:
-
动词 “break”:
The vase broke.(打碎)Dawn broke.(破晓)The news broke.(发布)Sandy broke the record.(打破)Sandy broke the law.(违反)The burglar broke into the house.(闯入)The newscaster broke into the movie broadcast.(打断)We broke even.(收支平衡)
-
形容词 “flat”:
flat beer(走了气的)flat note(降音的)flat tire(瘪了的)flat surface(平坦的)
-
动词 “throw”:
throw a party(举办)throw a fight(故意输掉)throw a ball(投掷)throw a fit(发脾气)
词义的歧义消解也依赖于更广泛的语境:
-
A crane caught a fish.(“crane” 指鸟) -
A crane picked up the steel beam.(“crane” 指起重机) -
I saw a crane.(没有更多上下文,无法确定是鸟还是机器) -
Are there any typos? I didn‘t see any.(“any” 指 “any typos”) -
Are there any bookstores downtown? I didn’t see any.(“any” 指 “any bookstores”)
这些例子表明,静态词向量方法要求一个词在所有语境下都对应同一个向量,这与语言实际运作方式不符。上下文词表示则允许我们捕捉词义的这种灵活性和语境依赖性。
上下文表示的发展简史 ⏳
上下文词表示的思想发展迅速,以下是一些关键里程碑:
- 2015年:Dai & Le 的论文展示了语言模型式预训练对下游任务的价值。
- 2017年8月:CoVe 论文表明,为机器翻译预训练的双向LSTM能提供可用于其他任务的序列表示。
- 2018年2月:ELMo 首次证明,大规模预训练的双向LSTM能产生丰富的、可通过微调轻松适配多种下游任务的多用途表示。
- 2018年6月:GPT 发布。
- 2018年10月:BERT 时代开启。BERT 模型是本单元乃至后续讨论的基石。
模型结构与语言结构 🏗️
模型架构中内置的结构性偏置是另一个核心思想。这关系到我们如何组合词义。
- 简单加性模型:将句子中每个词的静态向量(如GloVe向量)简单相加得到句子表示。这是一种高偏置模型,因为它预先假设加法是最优的组合方式。
- 循环神经网络:将词向量输入RNN,通过神经网络参数学习最优的组合方式。这释放了加性模型的偏置,允许模型从数据中更自由地学习。
- 树结构神经网络:预先确定句子的成分结构,递归地组合子节点表示来生成父节点表示。它功能强大,但同样具有高偏置,因为它预设了句法结构。
- 双向RNN与注意力机制:在RNN基础上添加注意力机制,允许序列中任意位置的隐藏状态相互关联。这种模型几乎不做预设,Transformer时代的经验表明,在足够数据下,“任意关联”是最强大的模式。
注意力机制的核心思想 💡
注意力机制是通向Transformer的关键,也是其大部分能力的来源。
在一个从左到右处理的RNN中,最终的隐藏状态可能缺乏序列早期词的信息。注意力机制通过一个评分函数(如点积)来计算目标表示与之前所有隐藏状态的相似度,经过softmax归一化后,将这些信息加权组合成一个上下文向量,并融入到目标表示中。这使得后续的分类决策能够基于融合了序列全局信息的表示。
点积注意力是Transformer架构的核心思想。
子词建模 🧩
子词建模是另一个被证明极其强大的思想。
- ELMo 的方法:从字符级表示开始,通过不同层级的卷积和池化操作,得到包含丰富子词信息的整词表示。然而,即使ELMo拥有约10万个词的巨大词汇表,在真实文本中仍会遇到大量未登录词。
- Transformer 与 BPE 分词:采用字节对编码等子词分词方法。例如,单词 “encode” 可能被分成 “en” 和 “code”。这样,词汇表可以很小(如不到3万),但遇到未登录词时,不会标记为未知,而是将其分解为已有的子词片段。在上下文模型中,模型可以内部学习这些片段如何组合成有意义的词。
位置编码 📍
Transformer 架构本身几乎无法跟踪词序,因此需要位置编码。
最直接的方法是除了词嵌入向量外,再添加一个位置嵌入向量,记录每个词在序列中的位置。然后将词嵌入和位置嵌入相加,作为上下文表示的基础。
这种方法被证明有效,但也存在局限,我们将在后续单元探讨如何改进。
大规模预训练与微调 ⚙️
大规模预训练是这一切背后的主要指导思想之一。
- 预训练:分布假说指出,我们无需手动编写特征函数,只需利用未标注语料库跟踪词的共现情况。在神经时代,Word2Vec和GloVe等模型使之成为可能。随后,ELMo、GPT、BERT和GPT-3等模型将大规模预训练推向了前所未有的高度。
- 微调:
- 2016-2018年:预训练通常指将静态词向量输入RNN变体,然后对模型进行微调。
- 2018年(BERT时代):开始对上下文模型进行微调。我们可以编写代码读入BERT表示,并将其微调为一个分类器。
- 未来趋势:我们可能进入一个新时代,大部分微调发生在那些我们无法直接访问的大规模语言模型上,我们只能通过API调用和部分已知的微调过程来让模型执行特定任务。尽管如此,编写自定义微调代码在分析和技术上仍然非常强大。
总结 📝


本节课中,我们一起学习了上下文词表示的核心思想。我们回顾了从静态稀疏向量到动态上下文表示的发展脉络,理解了词义对语境的依赖性如何推动了这一技术演进。我们还探讨了实现现代上下文表示的关键技术理念,包括注意力机制、子词建模、位置编码以及大规模预训练与微调范式。这些思想共同构成了当今自然语言处理研究和技术的基石。
5:上下文词表示(第二部分)—— Transformer 架构 🧠



在本节课中,我们将深入学习 Transformer 架构的核心结构。这是理解现代上下文词表示模型的关键。我们将从简单的例子出发,逐步拆解 Transformer 的各个组成部分,包括位置编码、注意力机制、前馈网络等,并最终理解其整体工作流程。
从静态词嵌入到上下文输入
上一节我们介绍了上下文表示的基本概念,本节中我们来看看 Transformer 如何具体构建这些表示。
我们从一个简单的句子“the rock rules”开始。模型首先为每个词元(token)查找其对应的静态词嵌入向量,例如 x47 对应单词“the”。这与 Word2Vec 等早期模型的概念相似。
同时,模型也为每个词元在序列中的位置生成一个位置编码向量。为了将词义和位置信息结合,模型简单地将词嵌入向量和位置编码向量按维度相加,得到初始的上下文输入表示(图中绿色部分)。以序列中的“C”部分为例,其输入计算为:
C_input = x34 + P3
这个相加后的向量,可以被视为模型中的第一个上下文表示。
注意力层:连接一切的核心
接下来是注意力层,这也是著名论文标题“Attention Is All You Need”的由来。作者们观察到,在 Transformer 之前的循环神经网络时代,人们会在循环机制之上添加各种注意力机制来增强连接。这篇论文的核心观点是:可以完全摒弃循环连接,仅依靠注意力机制。
Transformer 使用的注意力机制本质上与上一讲介绍的、来自前 Transformer 时代的点积注意力相同。其计算可以概括为:对于目标表示(如 C_input),计算它与序列中所有其他输入表示(如 A_input, B_input)的点积相似度。
Transformer 论文引入的一个新做法是,将这些点积除以模型维度 D 的平方根进行归一化。这是因为模型中会进行大量加法组合,所有表示的维度必须保持一致(均为 D)。作者发现,通过这种启发式方法对点积进行缩放,能获得更好的模型缩放性能。
归一化后的点积经过 softmax 函数,得到注意力分数 α。要得到对应于当前块(如 C)的注意力表示,我们将 α 的每个分量乘以对应的输入表示,然后求和。例如:
C_attention = α1 * A_input + α2 * B_input
需要强调的是,图中显示的所有密集连接线,是模型中唯一将所有独立的表示“列”编织在一起的地方。正是这些连接赋予了 Transformer 学习序列特征的能力。
图中橙色的表示是“原始”的注意力表示,它们记录了目标表示与周围表示的相似性。为了得到 Transformer 中完整的注意力表示,我们需要将这些橙色表示与最初的绿色上下文输入表示相加,并应用 Dropout 正则化技术,最终得到黄色的 C_A_layer 表示。
层归一化与前馈网络
在得到注意力表示后,模型会进行层归一化操作。这有助于调整数值的尺度,使其均值为 0 并呈正态分布,为后续的机器学习计算创造一个更稳定的环境。
下一步至关重要,即 Transformer 中的前馈组件。图中用蓝色表示,但它实际上隐藏了两个前馈层。
以下是其计算过程:
- 将层归一化后的紫色表示
C_A_norm作为输入。 - 通过第一个具有参数
W1和偏置B1的稠密层。 - 应用 ReLU 激活函数。
- 将结果输入第二个具有参数
W2和偏置B2的稠密层,得到C_FF。
Transformer 的许多参数实际上就隐藏在这些前馈层中。这里也是模型中唯一可以暂时偏离维度 D 的地方:虽然输入 C_A_norm 的维度是 D,但我们可以让第一个前馈层输出一个更大的维度(例如 3072),以增加模型的表示能力,只要第二个前馈层再将其压缩回维度 D。许多大型 Transformer 模型都利用了这一机会来拓宽中间层。
最后,我们将前馈网络的输出 C_FF 与 C_A_norm 相加,再次应用 Dropout 和层归一化,得到本 Transformer 块的最终输出 C_out。
注意力计算的矩阵形式与多头注意力
由于注意力机制如此重要,我们再多花些时间深入探讨。
到目前为止,我展示的是注意力计算的分步形式。然而,在《Attention Is All You Need》论文及后续文献中,该计算通常以更高效的矩阵形式呈现。为了帮助理解这两种形式的等价性,你可以通过动手编写简单的代码来验证。
另一个重要的概念是“多头注意力”。我之前展示的实际上是单头注意力。多头注意力的思想很简单:并行进行多组独立的注意力计算,每组都有自己的可学习参数矩阵(查询 W_Q、键 W_K、值 W_V),下标代表第几个头。
以下是多头注意力的工作流程:
- 对每个注意力头,使用其独有的参数矩阵,分别计算查询、键、值,并进行点积注意力计算。
- 每个头都会产生一组注意力表示。
- 将所有头的输出拼接或组合起来,形成最终的注意力表示。
这样,之前幻灯片中橙色的注意力表示,实际上很可能就是由多个头的输出组合而成的。多头机制为序列不同部分之间的这种关键交互层提供了丰富的多样性。
堆叠块与整体架构视图
Transformer 的核心思想之一是堆叠。一个块的输出(如 C_out)可以作为下一个块的输入。通常,模型会堆叠 12、24 甚至数百个这样的 Transformer 块。
现在,我们或许能更好地理解《Attention Is All You Need》论文中那个著名的架构图了。图中编码器(Encoder)部分展示的,正是对我们刚才讨论的节奏的重复:输入嵌入(红色)、多头注意力、相加与层归一化、前馈网络、再次归一化与相加。
解码器(Decoder)部分结构类似,但有一个关键区别:它使用了掩码注意力(Masked Attention)。在解码(如生成文本)时,模型不能“偷看”未来的信息,因此需要将注意力计算中未来位置的权重掩码掉。除此之外,解码器与编码器结构基本相同。图的顶部增加了输出概率层,用于任务如机器翻译或语言建模。
实战观察:使用代码探索模型结构
要更深入地感受这些模型的工作原理,可以下载模型并使用 Hugging Face 等库的代码来检查其结构。例如,观察 BERT-base 模型:
- 嵌入层:包含约 30,000 个词项,每个词嵌入的维度 D=768。位置编码最大支持 512 个位置,维度同样为 768。
- 注意力层:随处可见维度 768,因为这是模型的基础维度 D。
- 前馈层:这是维度变化的例外。例如,输入 768 维,中间层扩展到 3072 维以增加参数和表示能力,最后再投影回 768 维,以便堆叠。
这种结构会在所有层中重复。你可以用类似的方法查看 GPT、RoBERTa 等模型,它们虽然各有特点,但核心组件都以不同的形式重复出现。



本节课中我们一起学习了 Transformer 架构的核心组成部分。我们从结合位置信息的词嵌入开始,深入探讨了作为模型“粘合剂”的注意力机制(尤其是其多头形式),了解了用于增加模型容量的前馈网络,以及用于稳定训练的层归一化和 Dropout 技术。最后,我们理解了通过堆叠多个这样的块来构建强大模型的基本思想,并能初步解读经典的 Transformer 架构图。这是理解当今绝大多数前沿自然语言处理模型的基石。
6:上下文词表示(三)📍 位置编码




欢迎回来。这是我们关于上下文表示系列课程的第三部分。
我们稍后会讨论一系列著名的基于Transformer的架构。但在那之前,我认为有必要暂停一下,反思一下位置编码这个重要的概念。我觉得这个领域曾长期将其视为理所当然,我自己也是如此。我们现在认识到,这是塑造基于Transformer模型性能的一个关键因素。
概述
在本节中,我们将深入探讨Transformer模型中的位置编码。我们将了解为什么需要它,并分析三种不同的位置编码方案:绝对位置编码、基于频率的位置编码和相对位置编码。我们将重点关注两个核心问题:位置集合是否需要预先确定,以及编码方案是否会阻碍模型向新位置的泛化能力。
位置编码在Transformer中的作用
首先,让我们思考位置编码在Transformer上下文中的作用。核心观察是:Transformer本身跟踪词序的能力非常有限。注意力机制本身是无方向性的,它只是一系列点积运算,并且各列(输入位置)之间没有其他交互。因此,我们极有可能丢失“输入序列ABC与输入序列CBA不同”这一事实。
位置编码将确保我们保留这两个序列之间的差异,无论我们对模型产生的表示进行何种处理。
其次,位置编码还扮演着另一个层次性的角色。例如,在自然语言推理任务中,它被用来跟踪“前提”和“假设”等信息,这是我们稍后会谈到的BERT模型的一个重要特征。
评估位置编码的两个关键问题
为了简化讨论,我将围绕两个关键问题展开:
- 位置集合是否需要预先确定?
- 位置编码方案是否会阻碍向新位置的泛化?
我想引入的另一条规则是:现代Transformer架构可能出于设计和优化的原因对序列施加最大长度限制。我想暂时抛开所有这些因素,单独探讨位置编码方案本身是否对长度泛化能力施加了限制。
方案一:绝对位置编码
这是我们目前讨论过的方案。在这种方案中,我们有词表示,也有我们学习到的、对应固定数量维度的位置表示。为了获得对位置敏感的词表示,我们只需将词向量与位置向量相加。
公式表示:最终表示 = 词嵌入 + 位置嵌入
这种方案在我们两个关键问题上的表现如何?并不理想。
- 首先,位置集合显然需要预先确定。当我们建立模型时,会设定一个嵌入空间(例如最多512个位置)。如果我们选择了512,那么当遇到第513个位置时,我们将没有对应的位置表示。
- 其次,这种方案会阻碍向新位置的泛化。考虑短语“the rock”,如果它出现在序列早期,其表示与出现在序列后期时完全不同。虽然由于两个位置都包含相同的词向量,它们会有一些共享特征,但我们将位置表示作为平等的伙伴加入其中。结果是,学习到的表示严重依赖于位置,这使得模型难以认识到“the rock”在某种意义上是一个相同的短语,无论它出现在序列的开头、中间还是结尾。
方案二:基于频率的位置编码
这种方案实际上可以追溯到原始的Transformer论文。其基本思想是:我们定义一个数学函数,给定一个位置,该函数会返回一个向量,该向量的结构以某种语义方式编码了该位置的信息。在Transformer论文中,他们选择了一种基于频率振荡的方案,本质上基于这些向量的正弦和余弦频率,其中较高的位置振荡更频繁,这些信息被编码在我们创建的位置向量中。
核心特征:这是一个函数 f(position) -> vector。给它位置1,它返回一个向量;给它5、13或一百万,它都返回一个向量。所有这些向量都明确编码了该输入位置的相对位置信息。
因此,我们肯定克服了第一个限制:在这种方案中,位置集合不需要预先确定,因为我们可以为任何给定的位置生成一个新的向量。
但是,我们的第二个问题仍然存在。和之前一样,这种方案仍可能阻碍向新位置的泛化,原因同样是我们将词表示与这些针对不同位置的位置表示作为平等伙伴相加。这使得模型难以看到同一个短语可以出现在多个位置。
方案三:相对位置编码
这是我们即将讨论的三种方案中最有前景的一种。我们将通过几个步骤来理解这种方案的工作原理。
首先回顾一下,这是Transformer注意力层的示意图。我们有三个对位置敏感的输入:A输入、B输入和C输入。记住它们必须对位置敏感是至关重要的,因为这些点积注意力机制中存在大量对称性。
对于位置编码,我们实际上只是添加了一些新参数。幻灯片底部描绘的计算与顶部相同,只是在两个关键位置,我添加了一些我们将学习其表示的新向量(用蓝色标出):
- 在点积计算中,我们添加了键表示。
- 在最后的加权求和步骤中,我们添加了值表示。
这些是我们在此处添加的新的关键参数。基本思想是:由于所有这些位置敏感性都将被编码在这些新向量中,我们不再需要绿色的输入表示本身包含位置信息。因为位置信息现在被引入到注意力层中,我们可能会为每个位置组合(由这些下标表示)学习新的向量。
但这只是故事的一部分。我认为这种方法真正强大之处在于位置编码窗口的概念。为了说明这一点,我在顶部重复了核心计算作为提醒。现在,为了演示,我将窗口大小设置为2。
以下是我们将用作示例的输入序列,其上方是帮助我们在计算中跟踪位置的整数索引(它们不是模型的直接输入)。
让我们从聚焦位置4开始说明。
- 根据我们目前对键值的定义,我们将有一个向量
a_44(从位置4关注位置4)。作为创建这个基于有限窗口的模型版本的一部分,我们实际上会将其映射到键的一个单一向量w_0。 - 当我们向左移动一个位置到位置3时,我们会有键向量
a_43。但我们要做的是将其映射到单一向量w_-1(对应 3 - 4 = -1)。 - 再向左移动一个位置到位置2,我们得到
a_42,但我们现在将其映射到键向量w_-2。 - 然后,因为我们将窗口大小设置为2,当我们到达最左边的位置1时,它再次被映射到
w_-2(因为 4-1=3,超过了窗口大小,所以取窗口最大值-2)。 - 当我们向右移动时,会发生类似的过程:4到5得到
w_1,4到6得到w_2,从起点开始的第三个位置(4到7)同样由于窗口大小而“扁平化”为w_2。
因此,实际上,用蓝色表示,我们只有少数几个向量:w_0, w_1, w_-1, w_2, w_-2。这与之前用 a_43, a_42 等做出的所有区分相反。我们正在将这些向量折叠成对应于窗口大小的更少数量的向量。
如果我们将焦点移到位置3,情况会继续:a_33 被映射到 w_0(与上面位置4的 a_44 映射到的向量相同)。向左移动一位得到 w_-1(与上面位置4向右移动一位得到的向量相同),依此类推。对于你在上面看到的紫色值参数,也有并行的计算,使用相同的相对位置和窗口大小概念。
所以,我们实际上学习了相对较少的位置向量。我们所做的基本上是提供一个小的、基于窗口的相对位置概念,这个概念会滑动,并基于我们以前可能在这些输入的其他部分见过的组合,给我们很大的能力来泛化到新的位置。
最后需要说明的是,这实际上是嵌入在完整的注意力理论中的,该理论可能有很多可学习参数,甚至可能是多头注意力。我在这里描绘的只是完整的计算,以便真正给你所有细节,但认知上的捷径是:这是之前的注意力计算,加入了这些新的位置元素。再次提醒,在这种新模式中,我们在注意力层引入位置相对性,而不是在嵌入层。
回顾关键问题
现在让我们思考我们的两个关键问题。
- 首先,我们不需要预先确定位置集合。我们只需要决定窗口大小,然后对于一个可能极长的字符串,我们只是用相对较少的位置向量在其中滑动,以跟踪相对位置。
- 我认为我们也很大程度上克服了位置嵌入可能阻碍向新位置泛化的担忧。毕竟,如果你考虑像“the rock”这样的短语,无论它出现在字符串的哪个位置,涉及的核心位置向量都是
w_0,w_1,w_-1。当然,根据它出现的位置,会有其他位置相关的事情发生,其他信息也会作为计算的一部分被引入,但我们确实有这种恒常性,这将允许模型看到“the rock”本质上是相同的,无论它出现在字符串的何处。
总结
本节课中,我们一起学习了Transformer中位置编码的核心概念与三种主要方案。


我的假设是:由于我们克服了这两个关键限制,相对位置编码通常是Transformer中进行位置编码的非常好的选择。我相信,目前Transformer领域的结果也很好地支持了这一点。相对位置编码通过引入一个滑动窗口和有限的相对位置向量,既解决了模型对长序列和未知位置的泛化问题,又让模型能够更好地识别在不同位置出现的相同语言单元,是当前最有效的位置编码策略之一。
7:GPT 模型详解 🧠



在本节课中,我们将深入探讨 GPT(Generative Pre-trained Transformer)模型。GPT 是基于 Transformer 架构的最著名模型之一,它通过自回归语言建模进行预训练,并在各种下游任务上展现出强大的能力。我们将从技术细节出发,逐步理解其工作原理、训练过程以及生成机制。
自回归语言建模损失函数 📉
上一节我们介绍了上下文表示的基本概念,本节中我们来看看 GPT 模型的核心训练目标——自回归语言建模。其损失函数旨在根据已出现的词序列,预测下一个词的概率。
损失函数的数学表达式如下,其核心在于计算目标词嵌入向量与模型在上一时间步生成的隐藏表示之间的点积:
公式的分子部分 exp(embed(w_t) · h_{t-1}) 是关键。它表示在时间步 t,我们查找目标词 w_t 的嵌入向量,并将其与模型在时间步 t-1 生成的隐藏表示 h_{t-1} 进行点积运算。整个公式通过 Softmax 归一化,并对所有词汇表 V 中的词进行计算,最终目标是最大化整个序列的对数似然概率。
图解语言建模过程 🖼️
为了更直观地理解,我们通过一个例子来说明。假设我们的序列是 “
以下是语言建模的逐步过程:
- 从起始标记
<start>(时间步 T1)开始,查找其嵌入表示,并形成第一个隐藏表示H1。 - 为了预测下一个词 “the”(时间步 T2),我们使用
H1与词 “the” 的嵌入表示进行点积评分。 - 将 “the” 输入模型,获取其嵌入表示,并基于
H1生成第二个隐藏表示H2(这里可以想象为一个从左到右处理的循环神经网络,GPT 实际使用 Transformer,稍后会详述)。 - 为了预测 “rock”(时间步 T3),我们使用
H2与词 “rock” 的嵌入表示进行点积评分。 - 此过程持续进行,直到预测出结束标记
<end>。
在每个时间步,模型的核心操作都是计算目标词嵌入与前一时刻隐藏表示的点积,以此作为该词得分的依据,再通过 Softmax 得到预测概率。
GPT 的 Transformer 架构与掩码注意力 🔄
GPT 的本质是在 Transformer 架构中实现上述自回归语言建模。与之前介绍的 Transformer 不同,GPT 在训练时需要确保模型在预测当前词时,只能“看到”它之前的词,而不能“看到”未来的词。这是通过注意力掩码实现的。
以下是注意力掩码的工作原理:
- 在位置 A,模型只能关注自身(自注意力)。
- 在位置 B,模型可以关注位置 A 和自身。
- 在位置 C,模型可以关注位置 A、B 和自身。
这种掩码形成了一个下三角矩阵,确保了信息只能从过去流向未来,防止了信息泄露。具体到模型输入,我们首先将词序列转换为独热向量,再通过嵌入层得到词向量。这些向量与位置编码相加后,输入到多层 Transformer 编码器块中。每一层的自注意力操作都遵循上述掩码规则。
训练过程:教师强制 📚
GPT 模型的训练通常采用教师强制策略。这意味着在训练的每个时间步,无论模型预测出什么词,我们在输入下一个时间步时,都会强制使用真实的下一个词(即标注数据中的词),而不是使用模型自己预测的词。
以下是详细的训练步骤:
- 输入序列(如 “
the rock rules”)被转换为独热向量,并通过嵌入层得到向量表示。 - 这些向量经过多层 Transformer 块处理,生成一系列上下文相关的输出表示(绿色部分)。
- 在模型顶部,我们再次使用嵌入层的参数(与步骤1相同)作为一个线性层,将 Transformer 的输出映射到整个词汇表上,得到每个词在当前位置的得分(logits)。
- 我们将这些预测得分与下一个时间步的真实词所对应的独热向量进行比较,计算损失(如交叉熵损失)。
- 这个损失信号作为梯度,反向传播以更新模型所有参数(包括 Transformer 和嵌入层)。
关键点在于:输入序列和用于计算损失的目标序列是错位一格的。模型在时间步 t 的输入是 w_1, ..., w_t,而预测目标是 w_{t+1}。即使模型在时间步 t 的预测错了,在时间步 t+1 的输入中,我们仍然会使用真实词 w_{t+1},这就是“教师强制”。它使训练过程更加稳定。
文本生成过程 🎨
当模型训练完成后,我们进入文本生成阶段。此时,我们不再有真实的下一个词作为输入,因此必须使用模型自身的预测结果。
以下是文本生成的步骤:
- 用户提供一个提示序列(例如 “
the”)。 - 模型处理该序列,并在顶部输出层为词汇表中的每个词生成一个得分。
- 我们根据这些得分,通过某种决策规则(如选择得分最高的词,即贪婪解码)选择下一个词(例如 “rock”)。
- 将预测出的词(“rock”)追加到输入序列末尾,形成新的输入序列(“
the rock”)。 - 重复步骤 2-4,模型处理新序列,预测下一个词(例如 “rolls”),直到生成结束标记或达到指定长度。
需要强调的是,模型本身并不直接“输出一个词”,而是输出所有词的得分分布。生成文本的多样性和质量很大程度上取决于我们在这个分布上采用的采样策略(如贪婪搜索、束搜索、核采样等)。这是生成式任务中的一个重要设计维度。
模型微调与应用 ⚙️
预训练好的 GPT 模型可以通过微调来适应特定的下游任务(如文本分类、问答等)。
标准的微调方式如下:
- 将任务相关的输入文本输入 GPT 模型。
- 通常取模型对最后一个输入标记所产生的最终输出状态(即最后一个隐藏向量)作为整个序列的表示。
- 在这个最终输出状态之上,添加一个任务特定的小型输出层(例如一个线性分类器)。
- 在新的任务数据上,同时微调这个新增的输出层和 GPT 模型的部分或全部参数。
当然,我们也可以利用更丰富的序列信息,例如对所有时间步的输出状态进行均值池化或最大值池化,以获得更好的序列表示。但在最初的 GPT 论文中,微调主要基于最终输出状态。
GPT 模型家族概览 🏛️
最后,我们来了解一下 GPT 模型的发展历程及其规模。以下是 OpenAI 发布的几个主要版本:
以下是 GPT 模型的主要参数规模:
- GPT-1: 12层,模型维度768,前馈层维度3072,参数约1.17亿。
- GPT-2: 48层,模型维度1600,前馈层维度1600,参数约15亿。
- GPT-3: 96层,模型维度12288,参数约1750亿。
此外,开源社区也涌现了许多强大的替代模型,例如拥有1760亿参数的 BLOOM 模型,它们在规模和性能上都具有竞争力。这个领域正在快速发展,不断有新的模型出现。


本节课中我们一起学习了 GPT 模型的核心原理。我们从自回归语言建模的损失函数出发,图解了其工作流程,并深入探讨了 GPT 如何利用带掩码的 Transformer 架构实现这一目标。我们详细分析了其采用教师强制策略的训练过程,以及如何通过采样策略进行文本生成。最后,我们了解了模型微调的基本方法,并回顾了 GPT 模型家族的演进史。理解这些基础,是掌握当今大语言模型的关键第一步。
8:上下文词表示(五)BERT 🧠



在本节课中,我们将聚焦于BERT模型。BERT是GPT的“兄长”,虽然稍早问世,但其重要性和知名度毫不逊色。我们将深入探讨BERT的核心结构、训练目标、使用方法及其局限性。
BERT的核心模型结构 🏗️
上一节我们回顾了Transformer架构,本节我们来看看BERT如何巧妙地运用这一架构。BERT本质上是对Transformer的一种有趣应用。
为了说明,我们以序列“the rock rules”为例。该序列会经过一系列BERT特有的处理。
- 首先,在序列最左侧有一个类别标记。这是BERT架构中的一个重要标记,每个序列都以它开始。
- 其次,我们有一个分层位置编码,由标记
[SEP]给出。这对于我们当前的示例可能不那么有趣,但在处理如自然语言推理等任务时,前提和假设部分会使用不同的[SEP]标记,以帮助编码一个词出现在前提中与出现在假设中是略有不同的情况。这种思想可以推广到许多不同任务所需的各种分层位置编码中。
因此,我们的输入序列具有这种对位置非常敏感的编码。我们像往常一样查找所有这些部分的嵌入表示,然后将它们相加组合,得到输入序列的首次上下文敏感编码,即图中绿色的向量。
然后,与GPT类似,我们有许多Transformer块(可能多达数十个)重复堆叠,最终得到一些输出状态(图中用深绿色表示)。这些输出状态将成为我们使用该模型进行后续操作的基础。
BERT的训练目标 🎯
了解了BERT的结构后,我们来看看它是如何训练的。BERT的核心训练目标是掩码语言建模。
其基本思想是:我们将序列中的某些词的身份掩盖或隐藏,然后让模型尝试重建缺失的部分。
对于我们的序列:
- 一种情况是,我们不对“rules”这个词进行掩码,但仍然训练模型在该时间步预测“rules”。这作为一个重建任务可能相对简单。
- 更困难的情况是进行掩码。在这种情况下,我们会在“rules”的位置插入一个特殊的指定标记
[MASK],然后尝试让模型能够利用该点周围完整的双向上下文来重建“rules”这个缺失的部分。 - 此外,除了掩码,我们还可以进行随机词替换。例如,我们简单地将“rules”替换为一个随机词如“every”,然后让模型学习预测该位置的实际标记是什么。
所有这些任务都利用模型的双向上下文来完成重建。
在训练时,我们只掩码所有标记中的一小部分,大部分标记保持不变。这样,模型就有大量的上下文信息来预测被掩码、缺失或被破坏的标记。这实际上是MLM目标的一个限制和低效之处,后续模型(如ELECTRA)会试图解决这个问题。
以下是MLM损失函数的更多细节。与之前的损失函数一样,这里有很多细节,但关键点在于:
- 分子部分:与我们之前看到的类似,我们将使用要预测的标记的嵌入表示,并与模型在该位置的表示进行点积。关键区别在于,这里我们可以使用整个周围的上下文(仅排除位置T本身的表示),而之前回顾的自回归目标只能使用之前的上下文来进行预测。
- 指示函数:公式中的
M_t是一个指示函数,如果我们正在处理一个掩码标记,则其值为1,否则为0。这实质上关闭了对未掩码标记的目标计算。因此,我们只从掩码标记或被破坏的标记中获得学习信号。这再次体现了该目标的低效性,因为我们实际上对所有时间步都进行了预测计算,但损失函数的误差信号只来自我们指定为掩码的那些标记。
在BERT原始论文中,除了MLM目标,还补充了一个下一句预测的二分类任务。具体做法是:利用语料库资源创建带有所有特殊标记的实际句子序列。对于语料库中实际连续出现的句子对,我们将其标记为“下一句”;对于负例,我们随机配对句子并标记为“非下一句”。这部分目标的动机是帮助模型在学习如何重建序列的同时,学习一些篇章层面的信息。这是一个非常有趣的直觉,关于我们如何将更丰富的上下文概念引入Transformer表示中。
BERT的迁移学习与微调 🔄
当我们考虑迁移学习或微调时,可以采取几种不同的方法。
下图描绘了Transformer架构,标准的轻量级做法是在类别标记上方的最终输出表示之上构建任务参数。这种做法效果很好,因为类别标记是BERT处理的每个序列的第一个标记,并且始终处于固定位置,因此它成为一种包含大量关于对应序列信息的恒定元素。所以,标准的做法是在其上构建几个密集层,然后可能在那里进行一些分类学习。
当然,与GPT一样,我们不应受此限制。另一种标准替代方案是汇聚所有输出状态,然后在这种均值汇聚、最大汇聚或任何你用来汇集所有输出状态以进行任务预测的决策之上构建任务参数。这种方法也可能非常强大,因为你引入了关于整个序列的更多信息。
BERT的分词机制 🔡
我想提醒一下分词是如何工作的。请记住,BERT的词汇表很小,因此静态嵌入空间也很小。它能够做到这一点是因为采用了WordPiece分词。
这意味着我们有很多这样的词片段(用双井号##表示)。因此,模型本质上永远不会遇到未知的输入标记,而是将它们分解成熟悉的片段。其背后的直觉是,掩码语言建模的强大能力将使我们能够学习到那些对应像“encode”这样被分割成多个标记的词的内部表示。
BERT的核心模型发布与规格 📦
我们来谈谈原始BERT论文的核心模型发布。我相信他们只发布了BERT Base和BERT Large,各有区分大小写和不区分大小写的变体。目前,我建议始终使用区分大小写的版本。
非常可喜的是,包括谷歌团队在内的许多团队已经致力于开发更小的模型。我们现在有Tiny、Mini、Small和Medium等版本。这非常受欢迎,因为这意味着你可以在这些微型模型上进行大量开发,然后可能扩展到更大的模型。
例如:
- BERT Tiny:只有2层(即2个Transformer块),模型维度相对较小,前馈层内部的扩展也相对较小,总参数量仅为400万。虽然这确实很小,但当你针对任务对其进行微调时,你能从中获得的性能提升是惊人的。
- BERT Large:原始发布中最大的版本,有24层,模型维度较大,前馈层也较大,总参数量约为3.4亿。
所有这些模型(据我所知)都使用绝对位置嵌入,因此最大序列长度为512。这是一个重要的限制,我们越来越感觉到它限制了我们可以用BERT这类模型完成的工作类型。
现在有许多新的模型发布。要了解最新动态,可以查看Hugging Face,那里有这些模型针对不同语言的变体,可能还有不同尺寸和其他类型的版本。例如,可能已经有使用相对位置编码的版本,这将会非常受欢迎。
BERT的已知局限性 ⚠️
最后,我们来谈谈BERT的一些已知局限性。这将为我们后续讨论RoBERTa和ELECTRA等模型做铺垫。
- 训练优化研究不充分:原始的BERT论文虽然细节详实,但在消融研究和如何有效优化模型的研究方面仍然非常不完整。这意味着,如果我们进行更广泛的探索,我们看到的可能不是可能达到的最佳BERT。
- 预训练与微调之间的不匹配:Devlin等人也观察到了一个缺点。他们说第一个缺点是我们在预训练和微调之间造成了不匹配,因为掩码标记在微调期间从未出现过。这确实不寻常。请记住,掩码标记是针对MLM目标训练模型的关键元素。你在预训练阶段引入了这个外来元素,而在微调时很可能永远看不到它,这可能会拖累模型性能。
- 训练目标低效:他们提到的第二个缺点也是我提到过的。我们只使用大约15%的标记来进行预测。我们完成了处理这些序列的所有工作,然后却关闭了对未掩码标记的建模目标,而我们只能掩码一小部分标记,因为我们需要双向上下文来进行重建。这显然是低效的。
- 假设预测标记相互独立:最后一个局限性很有趣,我将在本系列的最后提到这一点。这来自ELECTRA论文。他们观察到,BERT假设在给定未掩码标记的情况下,被预测的标记是相互独立的,这过于简化了,因为高阶、长距离依赖在自然语言中普遍存在。这只是观察到,如果你碰巧掩码了像地名“New York”中的“New”和“York”这两个标记,模型将尝试独立地重建这两个标记,即使我们可以看到它们之间有非常清晰的统计依赖性。BERT的目标完全忽略了这一点。我稍后会提到ELECTRA如何重新引入这种依赖性,可能会产生非常强大的效果。
总结 📝


本节课中,我们一起学习了BERT模型。我们从其基于Transformer的核心结构开始,了解了它如何通过类别标记和分层位置编码处理输入。然后,我们深入探讨了其核心训练目标——掩码语言建模和下一句预测,并分析了这些目标的优缺点。接着,我们介绍了BERT的迁移学习与微调策略,以及其独特的WordPiece分词机制。我们还回顾了BERT的不同模型规格及其512序列长度的限制。最后,我们讨论了BERT的几个主要局限性,包括训练优化、预训练-微调不匹配、目标低效以及对预测标记独立性的简化假设,这些局限性为后续改进模型(如RoBERTa和ELECTRA)指明了方向。
9:上下文词表示 Part 6 - RoBERTa 🤖

在本节课中,我们将学习RoBERTa模型。RoBERTa是“稳健优化的BERT方法”的缩写。我们将探讨RoBERTa如何通过更全面的设计空间探索,对原始的BERT模型进行了一系列关键的优化和改进。
上一节我们介绍了BERT模型的一些已知局限性,其中最主要的一点是BERT团队最初的消融研究和优化研究虽然详尽,但仍不够全面。本节中,我们来看看RoBERTa团队如何接手,并对BERT的设计空间进行了更彻底的探索。


RoBERTa与BERT的关键区别 🔍
以下是RoBERTa与原始BERT模型之间的主要区别列表:
- 掩码策略:BERT使用静态掩码。这意味着他们将训练数据复制若干份,对每份应用不同的掩码,然后在多个训练周期中重复使用这组已掩码的数据集。RoBERTa则采用动态掩码,即在加载每个批次时随机应用掩码,使得包含相同示例的后续批次具有不同的掩码模式。
- 输入格式:BERT的输入是两个拼接的文档片段,这对“下一句预测”任务至关重要。RoBERTa的输入是句子序列,这些序列甚至可以跨越文档边界。
- 训练目标:BERT包含“下一句预测”目标。RoBERTa则移除了NSP目标,认为其贡献不大。
- 批次大小:BERT的训练批次包含256个示例。RoBERTa将批次大小增加到2000个示例。
- 分词器:BERT使用WordPiece分词器。RoBERTa使用字符级字节对编码算法。
- 训练数据:BERT在BookCorpus和英文维基百科上训练。RoBERTa增加了数据量,在BookCorpus、维基百科、CC新闻、开放网络文本和故事数据集上训练。
- 训练步数:BERT训练了100万步。RoBERTa训练了50万步。虽然步数减少,但由于批次大小大幅增加,RoBERTa实际处理的总实例数要多得多。
- 序列长度:BERT团队认为先训练短序列对优化有益。RoBERTa团队移除了这一策略,在整个训练过程中都使用完整长度的序列。
关键决策的证据支持 📊
现在,我们来看看支持上述部分决策的实验证据。
动态掩码 vs. 静态掩码
RoBERTa团队使用SQuAD、MultiNLI和SST-2作为基准来评估掩码策略。实验结果表明,在SQuAD和SST-2任务上,动态掩码带来了明显的性能提升。虽然在MultiNLI上略有下降,但平均来看,动态掩码效果更好。此外,动态掩码能增加训练数据的多样性,这本身就是一个有益的特性。
输入格式的选择:完整句子 vs. 文档句子
RoBERTa团队评估了两种输入格式:“文档句子”和“完整句子”。“文档句子”将训练实例限制为来自同一文档的句子对,这有助于模型学习语篇连贯性。“完整句子”则允许实例跨越文档边界,连贯性保证较弱。
尽管在SQuAD、MultiNLI、SST-2和RACE基准测试中,“文档句子”略微领先,但团队最终选择了“完整句子”。原因在于,除了准确率,训练效率也是重要考量。“完整句子”更容易创建高效的批次,因此被采纳。
更大的批次大小
RoBERTa团队通过困惑度、MultiNLI和SST-2等指标评估了不同批次大小的影响。他们发现,将批次大小增加到2000个示例能带来最佳性能。这符合深度学习中的一个常见经验:在资源允许的情况下,使用更大的批次通常是有益的。
更多的数据与更长的训练
实验表明,在尽可能多的数据上进行尽可能长时间的训练,能为RoBERTa带来最佳结果。最大的RoBERTa模型使用了160GB的数据,而最大的BERT模型仅使用13GB。虽然RoBERTa的训练步数(50万)少于BERT(100万),但由于批次大小大幅增加,RoBERTa模型实际处理的总训练实例要多得多。这再次印证了深度学习的经验:更多的数据和更长的训练时间,对于创建可用于下游任务微调的预训练模型至关重要。
RoBERTa模型规格 📐
RoBERTa团队发布了两个可直接与对应BERT模型比较的版本:
- RoBERTa-base:具有12层,768维隐藏层,3072维前馈层,总计约1.25亿参数,与BERT-base大致相同。
- RoBERTa-large:具有24层,1024维隐藏层,4096维前馈层,总计约3.55亿参数,与BERT-large大致相同。
总结与延伸阅读 📚
本节课中我们一起学习了RoBERTa模型。正如开头所述,RoBERTa的探索虽然比BERT更全面,但对于BERT模型所暗示的整个设计空间而言,仍然只是非常片面的探索。
对于希望深入了解如何为各种NLP任务最佳设置BERT风格模型的研究者,我强烈推荐阅读Rogers等人撰写的论文《A Primer in BERTology》。这篇论文虽然发布较早,但其内容非常详尽,包含了大量关于BERT模型调优的深刻见解,是本节课内容的绝佳补充读物。


本节课中我们一起学习了RoBERTa模型。 我们了解了RoBERTa如何通过引入动态掩码、移除NSP目标、增大批次大小、使用更多数据和BPE分词器等优化,对BERT模型进行了改进。这些改变基于更全面的实验证据,旨在更高效地利用计算资源并提升模型在下游任务上的性能。RoBERTa的工作标志着预训练语言模型优化方法的一次重要演进。
10:ELECTRA 模型详解 ⚡



在本节课中,我们将要学习一种名为 ELECTRA 的上下文词表示模型。ELECTRA 旨在解决 BERT 模型的两个主要局限性:预训练与微调阶段之间的词汇不匹配问题,以及掩码语言模型(MLM)目标函数的数据利用效率低下问题。我们将深入探讨 ELECTRA 的核心架构、训练目标,并通过实验证据理解其为何能取得更优的性能和更高的效率。
回顾 BERT 的局限性
上一节我们介绍了 BERT 模型及其后续改进。在结束 BERT 部分的讨论时,我们列出了该模型一些已知的局限性:
- 训练数据与时长不足:RoBERTa 模型主要针对此项进行了改进。
- 掩码标记([MASK])的不匹配:BERT 在预训练时使用了
[MASK]标记,但在下游任务微调时该标记从未出现。这种不匹配可能降低模型的有效性。 - 训练效率低下:MLM 目标函数意味着模型在训练时只利用了约 15% 的标记进行学习。虽然需要处理序列中的每一个词元,但只有少数提供了学习信号,这无疑是数据低效的。
ELECTRA 模型正是针对第 2 和第 3 点局限性进行改进的。接下来,让我们看看它的核心结构。
ELECTRA 核心模型结构
ELECTRA 的核心思想是使用一个“生成器-判别器”框架,进行一种称为“替换标记检测”的任务。
假设我们有一个输入序列 X:
厨师 烹饪 了 晚餐
第一步:创建掩码版本
首先,我们像 BERT 一样,随机掩码掉输入序列中约 15% 的标记,得到 X_masked。
例如:厨师 [MASK] 了 晚餐
第二步:生成器工作
我们引入一个较小的、类似 BERT 的模型作为生成器(Generator)。它处理 X_masked,并预测被掩码位置的原始词元,输出一个序列 X_corrupt。
关键点在于:我们并非总是用生成器预测出的最可能词元进行替换,而是根据生成器输出的概率分布进行采样替换。
这意味着有时会用回正确的原词(如“烹饪”),有时则会替换成一个错误的词(如“八”)。
例如,X_corrupt 可能变为:厨师 八 了 晚餐
第三步:判别器工作
这才是 ELECTRA 模型的核心。我们引入一个判别器(Discriminator),它也是一个 Transformer 模型。判别器的任务是判断 X_corrupt 序列中的每一个词元,是原始的(original)还是被替换过的(replaced)。
对于我们的例子,判别器需要输出:[原始, 替换, 原始, 原始]
训练过程
生成器和判别器被联合训练。生成器学习如何更好地预测被掩码的词(类似 MLM),而判别器学习更准确地区分原始词和替换词。训练完成后,我们可以丢弃生成器,仅保留判别器作为预训练好的模型,用于下游任务。
关键设计选择的实验证据
ELECTRA 论文的一个突出优点是其包含了丰富的实验,以探索模型的最佳设置。以下是部分关键发现:
生成器与判别器的关系
一个直观的想法是让生成器和判别器共享参数。实验发现,一定程度的共享是有益的,但最佳结果来自于一个比判别器小的生成器(即更少的参数共享)。
下图展示了这一证据(此处为文字描述):
- X轴:生成器大小(最大到 1024 维)。
- Y轴:GLUE 分数(模型整体性能的代理指标)。
- 趋势:对于固定大小的判别器(例如 768 维),其性能随生成器大小变化呈倒U型曲线。性能峰值出现在生成器较小(如 256 维)时。当生成器变得过大,甚至超过判别器大小时,性能会下降。
- 直觉:一个相对“弱小”的生成器对判别器更有利,因为它产生的替换错误更具挑战性,迫使判别器进行更深入的学习。毕竟,判别器才是我们最终要使用的模型。
效率分析
ELECTRA 在计算效率方面也表现出色。论文进行了详细的效率对比研究。
计算预算下的性能
下图对比了在不同计算预算(预训练浮点运算量)下,各模型的 GLUE 分数:
- 核心结论:在任何给定的计算预算下,完整的 ELECTRA 模型(图中蓝线)性能都优于其他对比模型。
- 有趣对比:
- “对抗式 ELECTRA”(让生成器试图欺骗判别器)性能稍逊。
- “绿色曲线”代表先进行标准 BERT 预训练,中途切换到 ELECTRA 目标。结果显示,切换后性能立即获得提升,并始终优于持续进行 BERT 训练的策略(图中最低的线)。
不同目标函数的对比
论文还对比了几种变体目标函数的效率:
- ELECTRA(完整版):判别器对所有输入词元进行分类。
- ELECTRA 15%:判别器只对被掩码(即可能被替换)的那 15% 的词元进行分类(更接近 BERT 模式)。
- Replace MLM:仅使用生成器(无判别器),这相当于 BERT 的一种变体。
- All Tokens MLM:BERT 的另一种变体,对输入序列中的所有词元(而不仅是 15%)进行 MLM 预测。
以下是它们在 GLUE 基准上的性能排序(从高到低):
- ELECTRA(完整版)
- All Tokens MLM
- Replace MLM
- ELECTRA 15%
- 原始 BERT 模型
这个排序非常具有启发性:
- 它表明,即使沿用 BERT 架构,通过让模型对所有词元进行预测(All Tokens MLM),也能获得比原始 BERT 更好的性能。这印证了 BERT 数据利用效率低的问题。
- ELECTRA 15% 性能下降说明,让判别器做更多预测(完整版)是有效的。
- ELECTRA 完整版综合了这些优点,取得了最佳性能。
模型发布
ELECTRA 团队最初发布了三个预训练模型:
- ELECTRA-Small:一个非常小的模型,设计为可在单张 GPU 上快速训练,体现了对计算效率研究的重视。
- ELECTRA-Base:与 BERT-Base 规模大致相当。
- ELECTRA-Large:与 BERT-Large 规模大致相当。
总结


本节课中我们一起学习了 ELECTRA 模型。它通过创新的“替换标记检测”任务,巧妙地解决了 BERT 预训练中的两个核心问题:[MASK] 标记带来的预训练-微调不匹配,以及 MLM 目标的数据低效问题。ELECTRA 采用生成器-判别器架构,联合训练后仅使用判别器作为下游任务的基石。丰富的实验证据表明,ELECTRA 在相同的计算预算下能获得比 BERT 及其变体更优的性能,同时其设计(如使用较小的生成器)也充满了洞见。ELECTRA 的出现,标志着预训练语言模型在追求更高性能的同时,也越来越注重训练效率和计算资源的合理利用。
11:序列到序列架构 🏗️



在本节课中,我们将要学习序列到序列架构。这是一种强大的模型范式,专门用于处理输入和输出都是序列的任务,例如机器翻译和文本摘要。我们将探讨其核心思想、不同的架构变体,并重点介绍两种著名的模型:T5 和 BART。
任务概览
上一节我们介绍了上下文表示,本节中我们来看看序列到序列架构所针对的任务类型。这些任务天然具有序列到序列的结构。
以下是典型的序列到序列任务示例:
- 机器翻译:输入一种语言的文本,输出另一种语言的文本。
- 文本摘要:输入一个长文本,输出一个更短的摘要文本。
- 自由形式问答:输入一个问题(可能附带上下文信息),解码任务是生成一个答案。
- 对话系统:输入话语,输出回应话语。
- 语义解析:输入自然语言句子,输出其对应的逻辑形式。
- 代码生成:输入描述程序功能的自然语言句子,输出相应的程序代码。
这仅仅是众多序列到序列任务中的一小部分。它们甚至可以被视为更广泛的“编码器-解码器”问题的特例,这类问题不限于序列,也可以处理图像、视频、语音等。
历史背景与架构演变
在讨论Transformer之前,了解历史背景很有帮助。循环神经网络时代为我们思考序列到序列问题奠定了基础。
在经典的RNN序列到序列模型中,输入序列(如 A, B, C, D)被编码,解码过程以一个特殊符号开始,逐步生成输出序列(如 X, Y, Z)。为了帮助解码步骤记住编码部分的信息,人们在其基础上增加了各种注意力机制。
Transformer论文则完全拥抱了注意力机制作为核心,并摒弃了所有循环结构。
Transformer中的序列到序列范式
在Transformer的语境下,我们有多种方式来处理序列到序列问题。T5论文中的一张图清晰地展示了这些选项。
以下是三种主要的架构思路:
- 编码器-解码器架构:输入在编码器侧使用一套参数进行完全编码。解码器使用另一套参数进行解码,在每一步都可以关注编码器的所有输出。
- 标准语言模型架构:使用一个基于Transformer的语言模型(如GPT)处理整个序列。其特点是使用注意力掩码,使得每个位置只能关注过去的信息,而不能看到未来,即使对于我们认为的“编码”部分也是如此。
- 前缀语言模型架构:这是语言模型架构的一个变体。在处理输入(编码)时,允许完全的自注意力。当开始生成输出(解码)时,则切换到只能关注过去(包括所有编码部分)的掩码模式。
中间和右侧的选项(即基于语言模型的变体)随着GPT类架构的不断探索而变得越来越重要。
重点模型解析:T5
接下来,我们将聚焦于两种强大的编码器-解码器模型。首先介绍T5,它正是前述架构图的来源。
T5是一个经过广泛多任务(包括有监督和无监督)训练的编码器-解码器模型。其论文中一项非常创新的做法是使用了任务前缀。
例如,在输入前加上“translate English to German: ”这样的指令,然后再接上真正的待翻译文本。这个左侧的指令以自然语言的形式告诉模型在解码时应该执行什么任务(此处是翻译)。通过改变冒号前的任务描述,同一模型可以执行情感分析等不同任务。
这体现了深刻的洞察力:将所有任务都表达为自然语言,模型通过编码这些任务指令来引导自身行为,仿佛这些指令本身就是结构化的输入信息。
T5有多个不同规模的模型发布,参数从6000万到110亿不等,可供灵活选用。相关的FLAN-T5模型则是在T5基础上专门进行了指令微调的变体,这将在课程后续单元讨论。
重点模型解析:BART
另一个值得重点介绍的架构是BART。它与T5有相似之处,也有显著不同。
BART的本质是:编码器侧采用类似BERT的标准架构,解码器侧采用类似GPT的标准架构。其有趣之处在于预训练方式。
BART的预训练核心思想是:向模型输入被破坏的序列,让它学习如何恢复原貌。
以下是几种破坏输入序列的方法:
- 文本填充:将输入的部分内容完全掩码或删除。
- 句子乱序:重新组织输入句子的顺序。
- 词元掩码:随机掩码部分词元。
- 词元删除:随机删除部分词元。
- 文档旋转:旋转文档内容。
研究发现,最有效的预训练方案是结合文本填充和句子乱序。这种“去破坏”的任务能使模型理解良好序列应有的样子。
在微调阶段,方案有所不同:
- 对于分类任务,将未破坏的输入送入编码器和解码器,然后基于解码器的最终状态进行微调。
- 对于标准的序列到序列任务,则直接将输入-输出对送入模型进行微调,无需破坏输入。破坏操作主要局限于预训练阶段。
论文证据表明,这种预训练目标能使模型达到一个良好的状态,从而在多种下游任务的微调中表现出色。
总结


本节课中我们一起学习了序列到序列架构。我们首先了解了其适用的任务类型,回顾了从RNN到Transformer的演变历程。然后,我们分析了Transformer中处理序列到序列问题的三种主要范式。最后,我们深入探讨了两种重要的编码器-解码器模型:T5(通过自然语言任务前缀统一多任务)和BART(通过“去破坏”序列进行预训练)。它们不仅是强大的预训练模型,也代表了Transformer在序列到序列领域的一些关键创新。
12:上下文词表示(第9部分)- 知识蒸馏 📚


在本节课中,我们将要学习知识蒸馏技术。这是一种旨在提升模型效率的方法,其核心目标是将庞大而性能优异的“教师模型”的知识,压缩到更小、更高效的“学生模型”中。

上一节我们介绍了上下文表示的各种应用,本节中我们来看看如何通过知识蒸馏来优化这些模型。
概述:追求效率的模型压缩
在课程的第一天,我曾展示过一张追踪大型语言模型规模随时间变化的幻灯片。模型参数量一路攀升,直至达到数千亿级别。然而,一个充满希望的视角是,模型可能会开始变小。模型变小的一个原因在于,我们可以将这些大型模型的精髓“蒸馏”到小型模型中,从而获得在部署时更高效的模型。
知识蒸馏的核心在于,我们拥有一个性能优异但体量庞大、使用成本高昂的教师模型。目标是训练一个学生模型,使其输入输出行为与教师模型相似,但同时使用起来要高效得多。
知识蒸馏的目标函数
以下是知识蒸馏的不同目标函数,我将它们从最轻量级到最重量级依次列出。在实践中,人们通常会取这个列表中不同元素的加权平均值。
-
目标0:任务数据训练:如果任务有可用的标注数据,学生模型的训练很可能会部分依赖于这些真实数据。我们讨论的蒸馏目标本质上是为核心训练任务补充额外的目标组件。
-
目标1:模仿教师输出标签:第一个也是最轻量级的蒸馏目标是,我们简单地训练学生模型,使其产生与教师模型相同的输出标签。这非常轻量,因为在蒸馏时,我们实际上不需要直接访问教师模型。我们只需在可用训练数据上运行教师模型以产生标签,然后学生模型在这些标签上进行训练。这种方法之所以有效,一个指导性的见解是:训练数据中可能存在噪声或难以学习的部分。教师模型充当了一种正则化器,学生模型从观察教师模型的输出中受益,即使其中包含一些错误,因为这最终有助于提升泛化能力。
-
目标2:模仿教师输出分数向量:更深一层,我们可以在完整的输出分数向量层面上,训练学生模型使其具有与教师模型相似的输出行为。这实际上是2015年一篇著名蒸馏论文的核心内容。它比仅仅模仿输出标签更重量级,因为我们需要整个分数向量,但它仍然是一种纯粹的行为蒸馏目标。
-
目标3:对齐输出状态(如DistilBERT):在2019年著名的DistilBERT论文中,除了包含类似目标1和2的组件外,其蒸馏目标还有一个余弦损失组件。这里我们试图让教师模型和学生模型在Transformer意义上的输出状态彼此非常相似。这在蒸馏时需要更多地访问教师模型,因为我们需要对每个训练学生的样本在教师模型上进行前向推理以获取这些输出状态,然后应用余弦损失并更新学生模型。
-
目标4:对齐其他隐藏状态(如嵌入层):你也可以考虑绑定教师和学生模型的其他状态,例如其他隐藏状态,或许最突出的是教师和学生模型的嵌入层。其背后的直觉是,如果学生模型的内部表示模仿了教师模型,那么两个模型会更相似,学生模型也会因此更强大。
-
目标5:模仿干预下的反事实行为:这可能是更重量级的方法,这是我参与过的工作。我们现在训练学生模型,使其模仿教师模型在干预下的反事实行为。也就是说,我们实际改变教师模型的内部状态,并对学生模型做相应的操作,确保两者具有匹配的输入输出行为。这是一种对输入输出行为更彻底的探索,目的是将模型置于反事实状态,以期使模型具有非常相似的因果内部结构。
目标3、4和5在蒸馏时需要完全访问教师模型,因此非常重量级。但在所有这些情况下,我都假设教师模型是一个冻结的模型,你只需要进行前向推理。
知识蒸馏的其他维度
这些蒸馏目标还有另一个值得思考的维度,它们可以相互结合,也可以与我刚才描述的不同模式结合。
- 标准蒸馏:如前所述,教师模型是冻结的,只更新学生模型的参数。
- 多教师蒸馏:在这种情况下,我们拥有多个可能具有不同能力的教师模型,我们同时尝试将它们全部蒸馏到一个单一的学生模型中,该学生模型有望执行来自这些教师的多项任务。
- 协同蒸馏:这种情况下的思考方式非常有趣且不同,学生和教师模型被联合训练,这有时也被称为在线蒸馏。这非常重量级,因为你同时在训练这两个模型。
- 自蒸馏:这甚至更难思考。在这种情况下,蒸馏目标包含一些旨在使模型的某些组件与同一模型的其他组件对齐的项。
性能表现与总结
就性能而言,正如我之前所说,核心目标是寻求更高效但仍保持高性能的模型。因此,我想通过总结我们在专注于GLUE的自然语言理解特定案例中所知的情况,来结束这个简短的课程。
基于现有证据,我认为可以公平地说,我们可以将BERT模型蒸馏到更小但仍然高性能的模型中。许多研究都使用GLUE基准来追踪这一点,并且都得出了相同的见解。
- 在著名的DistilBERT论文中,他们将BERT-base蒸馏到6层,保留了97%的GLUE性能。
- Sun等人做了类似的工作。他们尝试将BERT-base蒸馏到3层和6层,也发现可以在GLUE上保持出色的性能。
- 同样,Jiao等人在2020年将BERT-base蒸馏到4层,再次在GLUE上看到了非常强劲的结果。

这组结果值得注意,因为它们都汇聚于同一个经验:我们可以通过将BERT蒸馏到一个更小但仍然在GLUE等基准测试上表现良好的学生模型中,来使其变得更小。因此,这应该能启发我们,将知识蒸馏视为工具箱中的一个强大工具,用于将非常庞大且可能昂贵的教师模型转化为在现实世界中可能更具实用价值的东西。

本节课中我们一起学习了知识蒸馏技术,了解了如何通过不同复杂度的目标函数,将大型教师模型的知识压缩到小型学生模型中,从而在保持高性能的同时显著提升模型效率。
13:上下文词表示总结 🎬


在本节课中,我们将对上下文词表示这一系列内容进行总结。我们将回顾核心内容,补充介绍一些因时间限制未能在主系列中提及的重要架构与创新,并展望该领域及本课程的未来发展方向。

回顾与总结 📝
上一节我们介绍了多种上下文表示模型。本节中,我们首先对整个系列的内容进行简要回顾。
我们探讨了从传统词嵌入到基于Transformer的上下文表示(如BERT)的演进。核心在于,模型能够根据单词出现的具体上下文,动态地生成其表示,从而更精准地捕捉语义。
重要架构补充 🧩
在核心系列中,因时间所限,未能涵盖所有有趣的架构与创新。以下是几个值得注意的补充:
- Transformer-XL:这是一个早期且极具创新性的尝试,旨在处理长上下文。其核心思想是通过缓存长序列的早期部分,并在当前状态的计算中,通过这些缓存状态创建循环连接来实现。
- XLNet:XLNet的目标是在不使用自回归语言建模损失的情况下,获得双向上下文的能力。它通过一种非常有趣的方式实现:对输入序列的不同排列顺序进行采样。这样,模型在按某种顺序(如从左到右)处理时,由于采样了足够多的序列顺序,本质上获得了双向上下文的能力。
- DeBERTa:从我们关于位置编码的讨论来看,DeBERTa非常有趣。我曾表达过一个担忧:在某些情况下,位置编码表示对单词表示的影响过大。DeBERTa可被视为一种将单词与位置在一定程度上解耦的尝试。它通过解耦核心表示,并对这两个部分使用不同的注意力机制来实现。其指导直觉是,DeBERTa能让单词更多地保留其“词性”,而与其在输入字符串中出现的位置相对分离,这看起来非常合理。
BERT局限性的进一步探讨 🔍
在讨论BERT时,我列出了其一些已知局限性,共四点。我提到RoBERTa解决了第一点(关于设计决策),而ELECTRA解决了第二点和第三点(关于掩码标记的人工性以及MLM训练在BERT上下文中的低效性)。我尚未触及第四点。
第四点来自XLNet论文。XLNet确实解决了这个担忧。该担忧在于:BERT假设被预测的标记在给定未掩码标记的条件下是相互独立的,这过于简化了,因为高阶长程依赖在自然语言中普遍存在。XLNet背后的指导思想是,通过引入自回归语言建模损失,我们带入了一些条件概率,这有助于克服MLM目标这种人工统计特性。但请记住,XLNet有趣之处在于它仍然拥有双向上下文,这来自于对输入字符串所有排列顺序的采样。这是一个关于BERT本质的深刻见解。
预训练数据的重要性 📊
我在本系列中完全没有讨论预训练数据,对此我感到有些遗憾。因为我们现在可以看到,预训练数据是塑造这些大型语言模型行为的一个极其重要的因素。
以下是一些核心的预训练资源:
- OpenWebText Corpus
- The Pile
- BigScience数据
- Wikipedia
我列出这些年份,并非真的鼓励大家去训练自己的大型语言模型,而是希望大家思考如何审计这些数据集,以此更深入地理解我们现有模型的特性,并理解它们可能在哪些方面成功,在哪些方面可能实际上存在很大问题。许多问题都可以追溯到输入数据的性质。
展望未来 🔮
最后,让我们展望未来。根据我的最佳估计,以下是一些当前趋势,很可能描述了我们现在所处的状况以及未来的发展方向。
首先,自回归架构似乎已经占据主导地位,这就是GPT的崛起。但这可能仅仅是因为该领域目前如此专注于生成任务。我仍然认为,如果你只是为了获得句子嵌入或理解不同表示之间的比较,那么像BERT这样的双向模型可能仍然比像GPT这样的模型更具优势。
对于具有序列到序列结构的任务,编码器-解码器模型仍然是主导选择。它们在理解任务本身方面可能具有架构偏差上的优势。不过,随着我们获得这些真正庞大的纯语言模型,我们可能会发现自己在向自回归公式转变,即使是对于具有序列到序列结构的任务。我们拭目以待。
最后,也许这是最有趣的一点。人们仍然痴迷于将语言模型扩展到更大规模。但令人高兴的是,我们也看到了向更小模型发展的反向运动。我在这里给“更小”加上了引号,因为我们谈论的仍然是具有大约100亿参数的模型,但这比那些真正庞大的语言模型要小得多。有很多激励因素将鼓励这些更小的模型变得非常好:我们可以在更多地方部署它们,可以更高效地训练它们,可以训练更多这样的模型,并且对于我们想做的事情,我们可能对它们有更多的控制权。所有的激励因素都存在。这是该领域激烈创新和巨变的时刻。我不知道一年后这些小模型能做什么。但我恳请大家思考如何参与这个激动人心的时刻,并帮助我们达到这样一个阶段:相对较小和高效的模型仍然具有令人难以置信的性能,并且对我们非常有用。
总结 📌


本节课中,我们一起学习了上下文词表示系列的总结。我们回顾了核心概念,补充介绍了Transformer-XL、XLNet和DeBERTa等重要架构,探讨了BERT的局限性及XLNet的解决方案,强调了预训练数据的关键作用,并展望了自然语言理解领域未来可能的发展方向,特别是自回归模型的兴起与更小、更高效模型的发展趋势。
14:作业2与Bakeoff概览 🧠


在本节课中,我们将学习课程作业2及其关联的Bakeoff竞赛。本次任务名为“使用DSP进行少样本开放问答”。本概述旨在解析这个听起来复杂的标题,并为你提供完成作业所需的清晰指引。
任务回顾与定位
首先,我们来回顾几种不同的问答任务。本次作业和Bakeoff竞赛所面临的挑战,对应下表中的最后一行,这是一个非常困难的任务。
| 任务类型 | 描述 | 难度 |
|---|---|---|
| 标准问答 | 给定黄金证据段落,训练一个问答阅读器从中寻找答案。 | 基础 |
| 开放问答 | 没有给定段落,需要先检索相关段落,再训练问答模块从中找答案。 | 较难 |
| 少样本问答 | 给定黄金段落,但不允许进行任何任务特定的阅读器训练,必须依赖冻结的大语言模型进行上下文学习。 | 困难 |
| 少样本开放问答 | 没有黄金段落,且必须使用冻结的语言模型进行问答部分。 | 非常困难 |
你的任务正是最后一种:少样本开放问答。这意味着:
- 在开发阶段,你拥有黄金问答对。
- 在测试(Bakeoff)阶段,你只有问题列表,没有黄金段落或其他关联数据。
- 你必须全程使用冻结的组件(检索模型和语言模型),不能训练任何LLM,只能进行上下文学习。
这个任务在几年前几乎不可能完成,但去年的学生取得了惊人成果,相信你们也能做到。
核心概念:检索后阅读
在少样本开放问答中,一个标准的基线方法是 “检索后阅读”。
其工作流程如下:
- 检索:依靠检索机制为问题找到相关的上下文段落。
- 构建提示:可以添加一些少样本示例来指导模型。
- 阅读/生成:使用冻结的语言模型,基于检索到的段落和示例,生成最终答案。
这些少样本示例可以从我们提供的SQuAD数据集中获取,也可以从其他地方构造。关键在于,你的系统需要学会在没有黄金段落和答案、只有问题的情况下进行推理。
工具介绍:DSP编程库
本次作业我们主要使用 Demonstrate-Search-Predict (DSP) 编程库。其核心理念是:将提示工程转变为真正的软件工程。你不再是从头开始编写文本提示,而是编写一个小程序。这为我们设计AI系统开辟了全新的思路,让我们能够组合冻结的预训练组件来完成复杂任务。
以下是DSP程序的一个简单结构示例:
@dsp.transformation
def few_shot_open_qa(example: dsp.Example, k: int = 2):
# 1. 采样示例
example.demonstrations = dsp.sample(train_set, k=k)
# 2. 使用模板构建生成器
generate_answer = dsp.generate(qa_template)
# 3. 生成答案
completions = generate_answer(example)
# 4. 提取答案
example.answer = completions.answer
return example
作业设置详解
环境与数据准备
在Notebook中,我们首先进行一些设置:
- 语言模型:连接OpenAI或Cohere等供应商提供的冻结大语言模型。你需要自行准备API密钥。
- 检索模型:我们为你设置了一个ColBERT服务器,它将提供一个强大的检索机制。
- 数据:我们使用SQuAD数据集。请注意,它在这里的角色是提供训练和开发示例,用于构建少样本提示和模拟测试环境,而不是用于训练模型参数。
DSP基础操作
上一节我们介绍了DSP的理念,本节中我们来看看它的具体用法。
直接调用语言模型
你可以直接向语言模型发送字符串查询,并控制生成参数(如温度temperature)。
responses = lm("Which US states border no US states?", temperature=0.9)
使用模板构建提示
更常用的方式是使用DSP模板来格式化提示,并从中提取结构化信息。
# 定义模板
qa_template = dsp.Template(
instructions="Answer the question.",
question=dsp.Field(),
answer=dsp.Field()
)
# 创建示例并生成
example = dsp.Example(question="Which US states border no US states?")
generate_answer = dsp.generate(qa_template)
completion = generate_answer(example)
print(completion.answer) # 例如:Alaska, Hawaii
进行检索
使用我们提供的ColBERT检索器为问题查找相关段落。
retrieved_passages = dsp.retrieve("Your question here", k=3)
作业问题与要求
所有核心组件准备就绪后,我们进入作业的具体问题。
问题一:带上下文的少样本开放问答
这是对基础“检索后阅读”流程的一个小修改。你需要编写一个DSP程序,在生成答案前,先为问题检索相关的上下文段落,并将其加入提示中。
问题二:使用annotate原语优化示例
annotate是DSP中一个非常强大的原语。在本问题中,你需要利用它来构造更有效的少样本示例,从而更好地引导系统产生你期望的行为。
原创系统设计
在完成上述问题后,你需要设计自己的原创系统。我们期望它是一个DSP程序,因为DSP库提供了丰富的原语来构建强大的解决方案。当然,你也可以自由选择任何其他技术。
如果你想进一步探索DSP,课程提供了介绍Notebook,其中展示了解决更复杂问答问题的先进编程技巧,这些技巧在我们讨论上下文学习时会详细讲解。
总结与挑战
本节课我们一起深入了解了作业2——“使用DSP进行少样本开放问答”。我们明确了这是一个极具挑战性的任务,它结合了开放问答和少样本学习的难点。我们介绍了完成该任务的核心方法(检索后阅读)、主要工具(DSP编程库)以及作业的具体要求。

请记住,你的武器是冻结的模型和聪明的提示设计。虽然不能训练模型,但通过精心构建的DSP程序和提示,你完全能够在这个看似不可能的任务上取得进展。祝你好运!
15:信息检索(第一部分)核心思想 🧠

概述


在本节课中,我们将探讨信息检索(Information Retrieval, IR)的核心思想。我们将看到自然语言处理(NLP)技术如何革新信息检索领域,同时,信息检索又如何反过来推动NLP任务变得更加开放和实用。课程将涵盖从经典检索方法到现代神经检索模型的演变,并重点介绍检索增强的上下文学习这一前沿方向。
NLP如何革新信息检索
上一节我们概述了课程内容,本节中我们来看看NLP技术对信息检索领域的深刻影响。
你可能已经注意到,NLP正在彻底改变信息检索。这个故事真正始于Transformer架构,或者更准确地说,始于其最著名的衍生模型之一:Bert。在Bert发布后不久,谷歌就宣布将其核心搜索技术融入Bert的某些方面。微软也几乎在同一时间对Bing搜索引擎做出了类似的宣布。我有一种感觉,这两次非常公开的宣布只是各大搜索引擎开始发生变革的冰山一角。
稍晚一些,我们看到大型语言模型(LLMs)开始在搜索中扮演直接角色。我认为初创公司u.com在这方面极具远见。我喜欢强调u.com,因为其CEO Richard Socher是本课程的杰出校友。u.com很早就预见到大型语言模型可以成为网络搜索中非常有趣且强大的组成部分。
此后,该领域出现了大量活动。例如,微软与OpenAI合作,现在将OpenAI模型作为Bing搜索体验的一部分。你可能也从另一个角度注意到,当GPT-4发布时,其公告的一部分是与摩根士丹利的合作,旨在帮助其员工使用GPT-4在他们自己的内部文档中查找信息。这表明,虽然我们经常听到公共网络搜索,但在组织内部也存在同样强大的搜索应用,它们同样由Transformer技术驱动。
你可能会问,为什么会发生这种变革?我认为根本原因在于,信息检索本身就是一个困难的自然语言理解问题。因此,我们的NLU技术越强大,我们在检索方面就能做得越好。
以下是一个能说明这一点的例子。
查询是:“what compounds protect the digestive system against viruses”(哪些化合物保护消化系统免受病毒侵害?)。
一个相关的文档内容是:“In the stomach, gastric acid and proteases serve as powerful chemical defenses against ingested pathogens.”(在胃中,胃酸和蛋白酶作为对抗摄入病原体的强大化学防御。)
颜色标注显示了相关性连接。你会注意到,查询中的关键词与文档中的关键词没有字符串重叠。我们在这里需要建立的连接完全是语义层面的。这表明,我们对查询和文档的语言理解得越深入,就越能更好地根据此类查询找到相关段落。
信息检索如何革新NLP
以上主要关于信息检索,但作为一名NLP研究者,对我来说更令人兴奋的方向是,信息检索现在正在革新NLP。其方式是通过让我们的NLP问题变得更加开放,更贴近实际日常任务。
让我用问答(Question Answering)来强调这一点。
在NLP领域目前标准的问答任务设定中,系统会获得一个标题、一个上下文段落和一个问题。任务是回答该问题,并且保证答案将是该上下文段落中的一个字面子字符串。这是在诸如SQuAD(斯坦福问答数据集)等任务中定义的标准问答。
重申一下,在训练时,你获得标题、上下文、问题和答案。在测试时,你获得标题、上下文和问题,并且保证答案是上下文段落的一个字面子字符串。这对于我们最好的模型来说曾经是一个难题,但现在已变得相当容易。同时,你也可以看到,这与我们在现实世界中想要进行的问答任务相当脱节,因为在现实世界中,我们很少能获得如此丰富的上下文或那种子字符串保证。
因此,我们作为一个领域正在转向一种我称之为开放问答(Open QA)的设定。这种模式将困难得多。
在这种模式下,可能有一个标题、一个上下文和一个问题,任务是回答。但现在,在训练时只给出问题和答案。标题和上下文段落需要从某个地方(可能是一个大型文档语料库,比如网络)检索出来。当然,检索出来后,我们无法保证答案会是上下文或标题中任何内容的字面子字符串。这是一个困难得多的问题,但也更贴近实际,因为这模拟了实际在网络上的搜索行为:你提出一个问题,需要检索相关信息来回答问题。
但困难得多的是,训练时只有问题和答案。测试时,你只得到问题,所有相关信息都需要被检索。你在这里看到的是,只要我们拥有真正优秀的检索技术,能为我们回答这些问题找到真正好的证据,我们就能开发出有效的系统。这就是检索在这个开放问答流程中的关键作用,你们将在本单元的相关作业和竞赛中探索这一点。
😊
知识密集型任务
问答实际上只是一系列知识密集型任务中的一个例子。我提到了问答,但我们还有诸如声明验证、常识推理、长篇阅读理解和信息寻求对话等任务。这些任务都明显非常依赖于拥有关于世界的丰富信息,以支撑系统做出的任何预测。
这一点很清楚。但我也有兴趣将标准的、通常是封闭的NLP任务扩展为更开放的变体。例如:
- 摘要:标准设定只是将输入一个长段落并尝试生成一个更短的段落作为任务。但我们难道不能将其变成一个知识密集型任务,用我们检索到的大量信息来增强输入吗?我认为这是一个合理的假设,可能会改进摘要系统。
- 自然语言推理:通常被设定为一个封闭的分类问题:前提、假设,然后给出三个标签之一。但用关于世界的信息来增强前提,帮助系统作为分类器做出更好的预测,这不是很有趣吗?
我认为这只是两个例子,说明我们如何能够将经典问题,甚至是分类问题,重新表述为知识密集型任务,从而受益于检索,结果是它们可以变得更有效,也更易于扩展到现实世界的问题。
信息检索方法
让我们谈谈信息检索方法,我将从经典IR开始。
在这种情况下,我们有一个用户查询进来:“When was Stanford University founded?”(斯坦福大学何时成立?)
以下是经典IR流程的步骤:
- 术语查找:我们离线创建了一个大型索引,将术语映射到相关的文档。这可能是一个包含该术语的文档列表,但我们可能还会根据这些查询术语对这些文档进行一些评分,以按相关性组织它们。
- 文档评分:基于该索引,我们可以进行文档评分,并向用户返回一个按相关性排序的文档排名列表。
- 用户筛选:然后由用户决定查看哪些文档来寻找问题的答案。
这就是我们所熟知的经典搜索体验。
纯语言模型方法
现在有一种趋势,试图用纯语言模型取代上述流程的许多部分。我称之为“LLMs for everything”(万物皆可LLM)方法。
在这种模式下,用户的查询进来:“When was Stanford University founded?”,一个对我们完全不透明的大型语言模型进行一些神秘的工作,然后直接输出答案:“Stanford University was founded in 1891.”(斯坦福大学成立于1891年。)
这对搜索体验是一个真正的改变。以前,我们必须浏览一个排好序的网页列表来找到答案;现在,答案直接给到我们。
这可能非常令人兴奋,然而,我们可能会开始担心。我们知道这些模型可以捏造证据。因此,我们应该批判性地看待它们的输出。由于我们不知道这个答案从何而来,我们对其产生过程一无所知。我们可能会开始怀疑我们的信息需求是否真的得到了满足,是否应该信任这个字符串。
我对这种模式深感担忧,以至于我认为我们应该推动一个不同的方向。这就是为什么神经信息检索模块在NLP的开放知识密集型任务中将继续扮演重要角色。
神经信息检索模型
神经IR模型的功能将很像那些经典模型,只不过是在一个丰富得多的语义空间中运作。
我们将从一个大型语言模型开始,就像在“LLMs for everything”方法中一样,但我们会以不同的方式使用它。
以下是神经IR的步骤:
- 文档编码:我们要做的第一件事是,使用语言模型对我们文档集合中的所有文档进行表示。这样做的结果将是一些密集的数值表示,我们期望这些表示能捕捉到文档结构和意义的重要方面。这本质上相当于经典IR模式中的文档索引,但现在它是一堆深度学习表示。
- 查询编码:然后用户的查询进来,我们对该查询做的第一件事是处理它(可能使用同一个大型语言模型),并获得该查询的密集数值表示。
- 评分与提取:基于所有这些表示,我们可以像往常一样进行评分和提取。此时,我们可以复现经典搜索体验的一切,唯一的区别是评分将以不同的方式进行,因为我们现在处理的不是术语和分数,而是我们在整个深度学习中所熟悉的这些密集数值表示。
但所有这些评分的结果是,我们向用户返回一个排好序的页面列表。因此,就用户需要搜索这些页面并找到问题答案而言,我们为用户复现了经典体验。我们只是希望,由于我们在一个丰富得多的语义空间中操作,我们能在提供相关页面方面做得更好。
通向上下文学习的桥梁
这是通向上下文学习(In-Context Learning)的一个好时机,上下文学习是本单元的另一部分,它们将在作业中结合起来。
让我们想想这个桥梁将如何搭建。现在,我们将处于使用大型语言模型并对其进行提示的模式。在这种情况下,我们只是用问题“who is Bert?”来提示它,任务是以我们正在操作的模式想出一个答案。这是系统给我们的唯一东西。这是一个真正的开放问答设定。
那么,问题是如何使用检索来有效地回答这个问题?
😊
以下是可能的检索增强步骤:
- 检索证据:我们可以从文档存储中为该问题检索一个上下文段落,希望这将成为回答该问题的相关证据。
- 检索演示:我们知道大型语言模型在进行上下文学习时,受益于拥有演示示例。因此,也许我们有一个训练好的问题集,我们可以从该集合中检索一个问题来使用。此时,我们可以使用该问题的训练答案,或者可能检索一个答案,希望这能更接近地模拟系统实际必须做的事情。
- 组合演示与证据:无论如何,我们现在有了这个演示。根据训练集,我们可以进一步使用训练证据(例如来自我们问答数据集的段落),或者再次使用检索器检索一个上下文段落,作为这个小演示的证据。
指导性假设是,通过将训练实例与一些检索步骤编织在一起,为回答这个问题提供证据,我们将在生成预测答案方面做得更好。
这是一个简单的“检索-然后-阅读”流程,我们使用检索器来寻找证据。在上下文学习单元以及你们完成作业时,你们将看到,这只是我们可以用来有效开发使用检索来寻找相关证据的上下文学习系统的一系列丰富选项的开始。这就是这两个主题真正结合的方式。
当前领域的核心问题与挑战
我认为这两个主题的结合是当前NLP和IR领域的核心问题之一。因为我们确实看到,作为搜索技术一部分部署的大型语言模型出现了许多令人担忧的行为。
例如,我们都看到谷歌因其在一个演示视频中犯了一个小的事实错误而导致股价受到重创。考虑到这一切的风险有多高,也许这是恰当的,但想想也很有趣,因为与此同时,OpenAI的模型正在到处捏造证据。
这是一个有点有趣的例子,我问系统:“Are professional baseball players allowed to glue small wings to their caps?”(职业棒球运动员允许在他们的帽子上粘小翅膀吗?),并要求模型为其给出的答案提供一些证据。它确实尽职尽责地说“不”,然后提供了一些证据,但它提供的证据链接完全是捏造的。它们不是指向真实网页的链接。如果你点击它们,会得到一个404页面。我发现这非常令人沮丧,而且比根本不提供证据更糟糕,因为我们已经习惯于看到URL并假设它们确实可以作为所给答案的某种真实证据。因此,这种真实证据被完全捏造的事实,绝对比根本不提供证据更糟糕。
这是另一个有趣的案例。我们将讨论我们的“Demonstrate-Search-Predict”论文,该论文的图一包含一个例子,问题是:“How many stories are in the castle David Gregory inherited?”(大卫·格雷戈里继承的城堡有多少层?)。在Twitter上,一位用户读了我们的论文,然后用Bing搜索引擎尝试了这个例子。他们说,啊哈,你看,Bing可以回答你这个看起来非常困难的问题,没问题。但随后该用户立即注意到,Bing实际上在引用我们自己的论文作为回答这个问题的证据。我要说,这让我深感担忧。我们的论文不应该被视为关于大卫·格雷戈里继承的城堡的良好真实证据。我们纯粹是将其用作说明性例子。如果我们意图稍有不同,我们实际上可能给出这个问题的错误答案。事实上,我们的图中确实嵌入了一些错误答案。因此,一篇关于检索上下文学习的科学研究论文会被用作关于大卫·格雷戈里继承的城堡的证据,这对我来说完全无法理解。这恰恰表明,仅仅因为你有一些搜索机制,并不意味着你在进行良好的搜索。在这种背景下,我们真正需要的是高质量搜索。

为了完整说明这一点,我发现这个例子很有趣,但也可能有点令人担忧。你们都应该用自己的名字试试。我用“write a biography of Christopher Potts from Stanford University”(写一篇斯坦福大学Christopher Potts的传记)来提示ChatGPT。
我对第一段非常满意。它对我非常恭维,我们可以说它是真实的。但红色框中的所有内容完全是虚假的。那里表达的所有事实信息都是假的。这对我来说是一篇不错的传记,我对这些事实没有任何抱怨,除了它们是假的。然而,我担心的原因是,我认为并不是每个人在要求自己的传记时都会得到如此恭维的信息。如果这些语言模型继续以这种方式捏造证据,我们正处在看到真正令人担忧的行为的边缘,这些行为将对社会中的人们产生真正有意义的下游影响。这就是为什么我觉得当前单元以及你们为此所做的工作,对于解决这个日益增长的社会和技术问题绝对极其重要且相关。
😊


延伸阅读与愿景
这为课程奠定了基础。如果你想了解更多,Omar、Mattezaharia和我在几年前写过两篇关于这个主题的博客文章,我认为它们仍然非常相关。
- 第一篇是“Building Scalable, Explainable, and Adaptive NLP Models with Retrieval”(用检索构建可扩展、可解释和自适应的NLP模型)。这是一篇技术性的博客文章。
- 另一篇是更高层次、更具前瞻性的“This Modest Proposal for Radically Better AI-Powered Web Search”(关于彻底改进AI驱动网络搜索的温和建议)。早在2021年,我们就强调了信息的来源和文档中的真实依据作为进行网络搜索(即使使用大型、强大、花哨的语言模型)的一个重要方面。
这就是我们将在整个本单元以及我们的作业中试图向你们展示的愿景。



总结


本节课中,我们一起学习了信息检索的核心思想。我们探讨了NLP与IR之间相互革新的关系:强大的NLP技术(如Transformer和LLMs)通过深化语义理解提升了检索质量;同时,将检索引入NLP任务(如开放问答)使其变得更加开放和实用。我们回顾了从经典术语匹配检索到现代神经语义检索的演变,并重点介绍了检索增强的上下文学习这一前沿方向。最后,我们讨论了当前LLM在搜索中捏造证据等挑战,强调了高质量、可追溯的检索对于构建可靠、负责任的AI系统至关重要。这些概念将为我们后续的深入学习与实践奠定基础。
16:经典信息检索(第二部分)🔍



在本节课中,我们将学习经典信息检索方法的核心概念。虽然本课程的重点是神经信息检索,但理解这些经典思想至关重要,因为它们非常强大,并且很可能成为你未来构建模型的重要组成部分。
经典信息检索的起点:词项-文档矩阵
上一节我们介绍了信息检索的基本概念,本节中我们来看看其核心数据结构。
经典信息检索的标准起点是词项-文档矩阵。矩阵的行代表词项(单词),列代表文档,单元格记录每个单词在每个文档中出现的次数。这些矩阵通常非常庞大且稀疏,但它们潜在地编码了大量关于哪些文档与哪些查询词相关的信息。
为了从矩阵中获取更多相关性信息,一种常见的方法是使用 TF-IDF 对词项-文档矩阵中的值进行调整。
TF-IDF:词频-逆文档频率
TF-IDF 是一种衡量词项在文档集合中重要性的经典方法。以下是其工作原理:
我们从文档集合 D 开始:
- 词频 是文档内部的度量。给定文档 d,词项 t 的 TF 计算公式为:
TF(t, d) = (词项 t 在文档 d 中出现的次数) / (文档 d 的总词数)
这是一个标准的相对频率值。 - 文档频率 是针对整个语料库的函数。我们简单地计算包含目标词项 t 的文档数量,无论该词项在每个文档中出现多少次。
- 逆文档频率 是语料库总大小与文档频率值的比值的对数:
IDF(t, D) = log( |D| / DF(t) ) - TF-IDF 就是 TF 和 IDF 值的乘积:
TF-IDF(t, d, D) = TF(t, d) * IDF(t, D)
TF-IDF 的核心思想是寻找那些能真正区分特定文档的词项。其值在以下情况达到最大:词项在极少数文档中出现非常频繁。相反,其值在以下情况最低:词项在非常多的文档中出现非常不频繁。
对于一个可能包含多个词项的给定查询,计算相关性得分的标准方法是,对词项-文档矩阵中使用的权重(例如 TF-IDF)进行求和。即,将查询中每个词的 TF-IDF 值相加,从而得到整个用户查询的相关性得分。
BM25:最佳匹配算法
BM25 可以说是最著名的经典信息检索方法。它是 TF-IDF 的一种增强版本。
BM25 的权重由两部分组成:
- 平滑的 IDF 值:对标准 IDF 进行了微调,以处理词项在零个文档中出现的情况。
- 评分函数:类似于 TF-IDF 中的词频,但更为复杂,包含了超参数。
其权重是调整后的 IDF 值与评分函数值的乘积。从高层次看,它与 TF-IDF 的构成非常相似。
让我们更详细地看看各个组成部分。
BM25 的 IDF 组件
BM25 使用的 IDF 公式与标准版本略有不同,但通过设置一个标准参数(通常为 0.5),其产生的值与标准 IDF 值在整个文档频率范围内非常接近。其主要作用是处理词项在零个文档中出现时的边界情况。
BM25 的评分函数与超参数
评分函数更为复杂,因为它引入了超参数 K 和 B。
以下是评分函数中各个部分的作用:
- 对长文档的惩罚:评分函数中包含一个惩罚项,旨在降低长文档的得分。直觉是,长文档仅仅因为篇幅长就可能包含更多词项,因此我们应降低对其所含词项的信任度,将其作为相关性证据的权重。
- 超参数 B 的作用:B 控制着对长文档施加的惩罚力度。B 值越高,对长文档的惩罚越大,从而进一步降低其得分。当文档长度等于平均长度时,B 值不产生影响。
- 超参数 K 的作用:K 出现在评分函数的分母中,其整体效果是平滑高频词项的影响。当 K 值设得非常低时(非标准做法),评分函数几乎变成一个指示函数:只要词项出现在文档中就得基本分,而不太关心它出现了多少次。随着 K 值增大,这种极端平滑效果减弱,系统会越来越关心词项在文档中出现的频率。标准 K 值(如 1.2)会产生适度的平滑效果,即当词项频率非常高时,得分的增长会趋于平缓。
高效检索:倒排索引
有了这些组件,我们可以回到信息检索中的经典倒排索引。之所以称为“倒排”,是因为它是从词项映射到文档列表,而不是从文档映射到词项列表。
当查询到来时,我们进行词项查找。在使用 BM25 或 TF-IDF 时,我们可以用预计算的得分、文档频率值和 IDF 值来增强这个索引。这样,对于给定的查询,我们就拥有了高效进行完整文档评分所需的所有要素。这也是经典方法具有巨大可扩展性的关键原因之一。
经典信息检索的扩展方向
以上涵盖了我想介绍的经典信息检索核心内容。但如果不提及其文献中深入探讨的几个明显主题,将是我的疏忽:
以下是经典信息检索可以进一步探索的几个方向:
- 查询与文档扩展:用额外信息或元数据来增强用户查询和语料库内容,以辅助相关性评分。
- 短语级搜索:可以超越单元词,考虑 N 元语法甚至更复杂的语言单位。
- 词项依赖性:经典方法通常假设文档中的词项相互独立,但像“New York”这样的二元词组显然不适用。应考虑词项间的统计依赖关系。
- 不同文档字段:文档并非同质,出现在标题中的词与正文中的词可能具有不同的内在相关性价值。优秀的检索技术应能区分这些差异。
- 链接分析:语料库中的文档通过超链接形成隐含的图结构。现代搜索经验表明,这是影响相关性和让最佳文档排名靠前的关键因素。
- 学习排序:根据查询学习什么是相关的功能,是神经信息检索模型的重要特征。在经典 IR 中,我们也可以学习排序函数,超越 TF-IDF 和 BM25 等先验计算。
工具与实用模式
最后,有许多工具可以帮助你进行经典信息检索:
- Elasticsearch:一个广泛部署、非常健壮、成熟且高度可扩展的搜索技术,功能丰富。
- Pyserini 和 PrimeQA:研究代码库,如果你想建立经典 IR 模型作为基线,或将它们用作更大系统的组件,这些工具会非常有用。
一种常见的实用操作模式是:使用非常快速、健壮的经典 IR 系统(如基于 BM25)进行初步检索,返回大量候选结果;然后让神经模型扮演“重排序器”的角色,对经典模型返回的核心结果进行精细化排序。这种模式既能获得高度可扩展的解决方案,又能利用神经模型的优势提升最终结果质量。


本节课总结:我们一起学习了经典信息检索的核心方法。我们从基础的词项-文档矩阵和 TF-IDF 出发,深入探讨了其增强版 BM25 算法,理解了其评分函数以及对长文档的惩罚机制。我们还回顾了实现高效检索的倒排索引结构,并简要展望了经典 IR 的扩展方向及与现代神经模型结合的实用模式。这些经典思想为理解更复杂的神经信息检索模型奠定了坚实的基础。
17:信息检索评估指标 📊



在本节课中,我们将要学习如何评估信息检索系统的质量。上一节我们介绍了经典的IR模型,本节中我们来看看用于评估这些系统的核心指标。我们将重点讨论准确性指标,但也会强调评估IR系统时需要考虑的其他重要维度。
系统评估的多维度视角
在深入准确性指标之前,需要强调评估IR系统质量有多种方式。准确性指标在文献中很突出,也是系统质量的一个重要方面,但部署IR系统时,特别是工业环境中,还需考虑许多其他因素。
以下是评估IR系统时需要考虑的其他关键维度:
- 延迟:执行单个查询所需的时间。在工业环境中,延迟限制通常非常严格,用户期望低延迟系统。
- 吞吐量:在固定时间内服务的总查询量,可能与延迟相关,但有时需要权衡。
- 计算量:作为硬件无关的总计算资源衡量标准,这是一个很好的整体衡量标准。
- 磁盘使用量:模型或索引的磁盘使用成本,尤其是在索引整个网络时,存储成本可能非常高。
- 内存使用量:模型或索引的内存使用量。为了获得低延迟系统而将整个索引保存在内存中,成本可能迅速增加。
- 成本:一种总结上述所有因素的方式,促使我们整体思考系统以及这些指标之间固有的权衡。
考虑到成本约束,我们开始以一种非常健康的方式思考权衡。更多的IR评估应该处于这种整体模式中,平衡所有这些考虑因素。
尽管如此,我们现在将重点讨论准确性指标。
信息检索的数据集类型
作为预备知识,我们应该讨论一下你可能拥有的数据集类型。它们与我们在NLP中习惯的数据集略有不同。
以下是IR中常见的数据类型:
- 完整或部分黄金排序:对于查询,拥有所有文档的完整或部分黄金排序。为数据集中的每个查询提供这样的排序显然非常昂贵。
- 不完整的部分排序:通过一些启发式方法,将部分文档呈现给人类进行排序,可能每个查询只有少数几个,并以此为基础自动推断总排序。
- 二元相关性判断:简单地判断语料库中的文档对于给定查询是否相关。这很常见,可以基于人工标注,也可以基于弱监督启发式方法。
- 正负文档元组:一个包含查询的一个正例文档和一个或多个负例文档的元组。这可以用于训练和评估IR系统。
有了这些数据类型,让我们开始思考指标本身。
基础评估指标:Success@K 与 Reciprocal Rank
我们将从最简单的指标开始,即Success@K和Reciprocal Rank。
两者的一个常见组成部分是“排名”。对于文档排序 D,查询在该排序中的 rank 是一个整数,表示排序中第一个相关文档的位置。
在此基础上,我们可以定义 Success@K。我们选择一个值 K,然后对于查询和排序,如果查询的 rank 小于或等于 K,则 Success@K 的值为 1,否则为 0。这是一个二元判断。
Reciprocal Rank 类似。文档排序中查询的 RR@K 是排序中该查询的 rank 的倒数(如果 rank 小于或等于 K),否则为 0。这与Success@K相同,只是当成功时,我们使用 1/rank 而不是 1。
然后,MRR@K 是文献中常见的指标,它只是多个查询的 RR@K 值的平均值。
通过示例理解指标
让我们通过一些示例来更深入地理解这些指标。我将使用以下排序作为运行示例。
排序1:[*][*][ ][ ][ ][*]
排序2:[ ][*][ ][ ][*][*]
排序3:[ ][ ][*][*][*][ ]
星号 * 表示文档被判定为与查询相关。
在讨论指标之前,你可能会退一步问自己,这些排序中哪一个最好?这可能并不明显,可能取决于视角。例如,排序1看起来很好,因为前两个文档是相关的,但它把第三个相关文档放在了最后。相比之下,排序3的所有相关文档都在第3、4、5位,但至少没有把它们放在最后。排序2可能看起来介于这两个极端之间。显然,不同的指标会对不同方面的质量敏感。
让我们回到Success和Reciprocal Rank。
Success@2 的值:
- 排序1:1(因为位置1或2有相关文档)
- 排序2:1(因为位置2有相关文档)
- 排序3:0(因为位置1或2没有相关文档)
RR@2 的值:
- 排序1:1/1 = 1.0(第一个相关文档在位置1)
- 排序2:1/2 = 0.5(第一个相关文档在位置2)
- 排序3:0(因为位置1或2没有相关文档)
更细致的指标:精确率与召回率
现在让我们转向精确率和召回率,这些是经典的IR指标,比Success和RR更细致,因为它们对多个相关文档敏感。
首先,两个初步概念:
- 排序在值 K 处的 返回集 是排序中位于 K 或以上的文档集合。
- 给定文档排序,查询的 相关集 是所有与查询相关的文档集合(即所有带星号的文档)。
然后我们可以定义 精确率@K。分子是返回集与相关集的交集大小,分母是 K。直观地说,如果我们将 K 或以上的值视为我们的猜测,精确率表示这些猜测中有多少是好的。
召回率@K 是它的对偶。分子相同(返回集与相关集的交集大小),但分母是相关文档的总数。这类似于说,如果 K 或以上的集合是我们的猜测,那么有多少相关文档实际上出现在 K 或以上?
让我们看看这些值在我们的三个排序中如何体现。
精确率@2:
- 排序1:
2/2 = 1.0 - 排序2:
1/2 = 0.5 - 排序3:
0/2 = 0.0
召回率@2:
- 排序1:
2/3 ≈ 0.67 - 排序2:
1/3 ≈ 0.33 - 排序3:
0/3 = 0.0
这大致重现了我们为Success和Reciprocal Rank看到的排序。
但这里有一个转折。假设我们将 K 值设置为 5,而之前是 2。
精确率@5:
- 排序1:
2/5 = 0.4 - 排序2:
2/5 = 0.4 - 排序3:
3/5 = 0.6
召回率@5:
- 排序1:
2/3 ≈ 0.67 - 排序2:
2/3 ≈ 0.67 - 排序3:
3/3 = 1.0
值得注意的是,当 K=5 时,排序3现在明显领先,因为它没有把任何相关文档放在第6位。这向你展示了 K 值对我们整体质量评估的重要性。当我们使用这些指标时,应该思考设置 K 值意味着什么,以及它如何影响我们对排序质量的评估。
平均精确率:减少对K值的依赖
平均精确率 是一个很好的替代方案,因为它对 K 值的敏感性较低。查询相对于文档排序的平均精确率直观地表述如下:分子,我们将在每个存在相关文档的位置(每个有星号的位置)获得精确率值,然后将它们求和。分母是相关文档的集合大小。
以下是使用我们之前的三个排序的计算结果:
- 排序1:相关文档在位置1, 2, 6。对应的精确率@1=1/1=1.0,@2=2/2=1.0,@6=3/6=0.5。求和:
1.0 + 1.0 + 0.5 = 2.5。除以相关文档数3:2.5 / 3 ≈ 0.833 - 排序2:相关文档在位置2, 5, 6。对应的精确率@2=1/2=0.5,@5=2/5=0.4,@6=3/6=0.5。求和:
0.5 + 0.4 + 0.5 = 1.4。除以3:1.4 / 3 ≈ 0.467 - 排序3:相关文档在位置3, 4, 5。对应的精确率@3=1/3≈0.333,@4=2/4=0.5,@5=3/5=0.6。求和:
0.333 + 0.5 + 0.6 = 1.433。除以3:1.433 / 3 ≈ 0.478
这很有意义,因为排序1是明显的赢家,即使我们不再对 K 敏感。事实上,在这个指标中,排序3领先于排序2,这是我们之前除了将 K 设得很低的情况外没有真正看到的。这很好,因为我们没有对任何特定 K 值的敏感性,我们已经抽象了所有可能选择的不同值,并且分子仍然跟踪相关文档的数量。
如何选择评估指标?
这是一个常见指标的抽样。当然还有更多,但它们遵循类似的模式。让我们退一步问,你应该使用哪个指标?此时你可能预料到我的答案:没有单一的答案。
让我们思考一些权衡:
- 如果用户滚动浏览 K 个文档的成本很低,那么 Success@K 可能已经足够细致,因为你只需要在该 K 个文档集合中找到一个相关的。
- 如果每个查询有多个相关文档,那么Success和Reciprocal Rank可能过于粗糙,因为它们对拥有多个相关文档不敏感。
- 如果找到每个相关文档更重要,则倾向于 召回率。
- 如果只查看相关文档更重要(即遗漏成本高,但审查成本低),则倾向于 精确率。如果审查成本可能很高,但我们不太在意遗漏一些内容,只需要找到几个相关示例,那么也可以倾向于精确率。
- F1@K 是 K 处精确率和召回率的调和平均值,可以在有多个相关文档但其在 K 以上的相对顺序不太重要时使用,并且你决定平衡精确率和召回率。
- 在我展示的所有指标中,平均精确率 将给出最细致的区分。它对排名、精确率和召回率都敏感。因此,如果你没有太多信息,并且希望在不同预测的排序之间进行细致区分,平均精确率可能是一个非常好的选择。
但正如开始时所说,我希望我们能跳出只考虑准确性的思维模式。
超越准确性:综合评估与帕累托前沿
为了引导我们朝这个方向思考,可以考虑所谓的“综合排行榜”,它从文献中汇集了许多不同的系统,并试图从论文中找出它们在硬件、准确性(如MRR)和延迟方面的表现。
如果只关注准确性列,你可能会选择某个性能最好的系统。然而,为了实现那个MRR值,某些系统可能需要非常强大的GPU硬件。而其他一些系统在质量上可能具有可比性,但所需的硬件资源更少。在这些系统中,你可以开始思考硬件和延迟之间的权衡。这让你以一种全新的方式思考哪个系统是最好的。
这是另一种视角,通常称为系统的 帕累托前沿。给定我们决定衡量的两个方面,一些系统严格主导另一些系统。当然,可能还有其他维度会导致其他系统领先。因此,我们需要再次进行整体思考。这强化了一个观念:系统质量问题没有一个固定的答案。最终需要考虑许多维度和许多权衡。


本节课中我们一起学习了信息检索系统的核心评估指标。我们从基础的Success@K和Reciprocal Rank开始,探讨了更细致的精确率与召回率,并介绍了对K值依赖较小的平均精确率。更重要的是,我们认识到评估IR系统不能只局限于准确性,必须综合考虑延迟、吞吐量、成本等多维度因素,并在具体应用场景中进行权衡。没有放之四海而皆准的“最佳”指标或系统,明智的选择取决于你的具体目标与约束条件。
18:神经信息检索 🔍



在本节课中,我们将学习神经信息检索的核心模型。我们将探讨如何利用预训练的BERT模型进行微调,以实现更强大的信息检索能力。课程将涵盖从概念上最简单的交叉编码器,到高效可扩展的密集段落检索器,再到平衡了语义丰富性和效率的ColBERT模型,最后介绍创新的Splade模型。通过学习这些模型,你将理解现代神经信息检索如何将深度学习的语义理解能力与传统检索任务相结合。
交叉编码器:语义丰富但难以扩展 🤔
上一节我们介绍了传统检索模型的基础。本节中,我们来看看神经信息检索中最直观的方法——交叉编码器。
交叉编码器在概念上是最简单的方法。其核心思想是将查询文本和文档文本拼接成一个单一的文本序列,然后使用BERT模型处理这个序列,并利用模型中的表示作为信息检索微调的基础。
具体来说,其工作流程如下:
- 将查询和文档拼接:
[CLS] 查询文本 [SEP] 文档文本 [SEP] - 使用BERT编码器处理拼接后的文本。
- 获取
[CLS]标记上方的最终输出状态。 - 在该状态之上添加任务特定的参数层,并针对信息检索目标对模型进行微调。
这种方法的评分函数可以表示为:
scores = DenseLayer(BERT([CLS] query [SEP] document [SEP]))
模型的损失函数通常是正例段落的负对数似然。假设我们有一个数据集三元组(查询,正例文档,一个或多个负例文档),损失函数公式如下:
Loss = -log( exp(score_positive) / (exp(score_positive) + Σ exp(score_negative)) )
这种方法在语义上极具表现力,因为它允许查询和文档在BERT模型的每一层进行丰富的词元级交互。然而,它存在一个致命缺陷:无法扩展。因为在查询时,我们需要为每一个候选文档(例如十亿个)与查询拼接后进行一次BERT前向传播,这在计算上是不可行的。
密集段落检索器:高度可扩展但交互有限 ⚡
既然交叉编码器因计算成本过高而难以应用,本节我们来看看另一个极端——密集段落检索器。
DPR采用了一种不同的架构:它分别编码查询和文档。查询和文档通过两个独立的BERT类编码器进行处理,我们同样只取[CLS]标记上方的最终输出状态作为其表示。
然后,评分通过这两个向量的点积来计算:
score = dot(encode_query(query), encode_document(document))
其损失函数与交叉编码器形式相同,依然是正例段落的负对数似然,只是内部的比较函数Sim换成了点积操作。
DPR的优势在于其高度的可扩展性。所有文档可以离线预先编码并存储为单个向量。在查询时,我们只需编码一次查询,然后与所有文档向量进行快速的点积运算即可。然而,这种效率的代价是失去了词元级的细粒度交互。模型必须希望查询和文档的所有信息都能被压缩到那一个单一的向量表示中,这可能导致语义表达能力的损失。
ColBERT:在丰富性与效率间取得平衡 ⚖️
为了在语义丰富性和计算效率之间找到更好的平衡点,我们接下来介绍ColBERT模型。
ColBERT的工作机制如下:
- 分别使用BERT编码查询和文档,但这次我们保留所有词元的最终输出状态,而不仅仅是
[CLS]标记的。 - 计算查询每个词元输出向量与文档每个词元输出向量之间的相似度矩阵。
- 评分基于“最大相似度和”:对于查询中的每个词元,找出它与文档所有词元相似度中的最大值,然后将所有查询词元的这些最大值相加。
其评分函数MaxSim可以表示为:
score = Σ_over_query_tokens( max_over_document_tokens( cosine_sim(q_i, d_j) ) )
ColBERT兼具了可扩展性和语义丰富性。与DPR一样,文档可以预先编码并存储(此时存储的是每个词元的向量),实现了可扩展性。同时,它又保留了类似交叉编码器的词元级交互能力(尽管这种交互只发生在最终输出层,而非每一层),从而获得了语义丰富性。
这种设计带来了一个关键优势:它实现了基于语义的“词项匹配”。例如,对于查询“When did the Transformers cartoon series come out?”和文档“The animated Transformers was released in August 1986”,ColBERT不仅能匹配“Transformers”,还能在“cartoon”和“animated”、“come out”和“released”之间建立强大的语义关联。这使得模型既有效又可解释。
让神经检索走向实用:索引与优化策略 🛠️
尽管ColBERT等模型在效果上表现出色,但其计算成本仍然是实际部署的挑战。本节我们来看看如何通过系统优化使其走向实用。
一个直接的方法是将其用作重排序器。具体流程如下:
- 第一阶段:使用BM25等快速、基于词项的检索模型,从海量文档中快速召回Top-K个相关文档。
- 第二阶段:仅对这K个候选文档使用ColBERT进行精细的重排序和评分。
这种方法用廉价的BM25承担了从全量文档库中粗筛的重任,而让强大的ColBERT只负责小范围精排,从而在控制成本的同时大幅提升最终结果质量。
为了更进一步,我们可以构建专门的索引并进行多阶段检索:
- 预先构建索引,存储每个文档的所有词元向量。
- 查询时,将查询编码为词元向量序列。
- 第一阶段:对查询中的每个词元向量,从索引中查找最相似的P个文档词元向量。
- 第二阶段:通过这些词元向量找到其关联的文档,形成一个较小的候选文档集。
- 第三阶段:仅对这个小型候选集使用完整的ColBERT模型进行评分。
为了极致优化,可以采用基于质心的排序:
- 将索引中所有文档词元向量进行聚类,并用各簇的质心作为代表。
- 查询时,将查询向量与这些质心进行比较,找到最相似的质心。
- 通过这些质心关联到相似的文档词元,进而找到候选文档。
- 最后仅对这批少量文档进行ColBERT全模型评分。
通过名为Plaid的优化工作,研究团队将ColBERT的延迟从287毫秒成功降低到了58毫秒。这启示我们,在追求模型精度的同时,对延迟、成本等系统级指标的优化同样充满创新空间,并且至关重要。
Splade:基于词汇表的稀疏表示 💡
最后,我们介绍另一种强大且具有独特视角的模型——Splade。
Splade的核心思想发生了转变:它不再直接计算查询与文档之间的交互,而是分别将查询和文档表示成相对于整个词汇表的稀疏向量。
- 对于一段文本(查询或文档),模型计算其每个词元与词汇表中每个词项的交互分数,形成一个分数网格。
- 通过一个特定的
sparsemax函数,为词汇表中的每个词项生成一个针对该文本的分数,得到一个长而稀疏的向量。 - 分别得到查询和文档的稀疏向量后,它们的相似度通过点积计算:
score = dot(SparseVector(query), SparseVector(document))。
其损失函数在标准负对数似然基础上,增加了一个促进表示稀疏性的正则化项。
Splade的强大之处在于,它以一种全新的方式回归了信息检索中“词项匹配”的核心思想,但这次匹配发生在由神经网络定义的、极其丰富的语义空间里。它生成的稀疏表示也带来了效率上的潜在优势。
总结与权衡:不仅仅是准确率 📊
本节课中,我们一起学习了神经信息检索的演进之路。
我们从语义丰富但难以扩展的交叉编码器开始,认识了高度可扩展但交互有限的密集段落检索器。然后,我们深入探讨了在两者间取得优雅平衡的ColBERT模型,它通过“最大相似度和”实现了高效的细粒度交互。接着,我们讨论了如何通过重排序、多阶段检索和索引优化(如Plaid)使这些强大模型变得实用。最后,我们了解了Splade模型如何利用稀疏的词汇表表示开辟新路径。


重要的是,在实际应用中,选择模型远不止看准确率这一项指标。我们需要在准确率、延迟、计算成本和硬件需求之间进行复杂的权衡。例如,在严格的计算预算下,BM25可能是唯一选择;而在资源允许时,则需要在ColBERT的不同配置或ColBERT与Splade等模型之间,根据对延迟和成本的承受能力来权衡准确率的得失。信息检索领域正是思考和探索这些系统级权衡的绝佳舞台。
19:信息检索(五)—— 数据集与总结 📚



在本节课中,我们将学习信息检索领域常用的几个核心数据集,并了解一些未深入讨论的重要主题,最后对本单元内容进行总结。
数据集资源 📊
上一节我们介绍了神经信息检索模型,本节我们来看看用于训练和评估这些模型的关键数据集。以下是几个重要的公开数据集:
-
TREC (文本检索会议):该会议每年举办竞赛。2023年的竞赛包含多个不同赛道,适合参与“烘焙赛”式的研究。TREC通常强调使用少量查询(例如50个)进行精细评估,每个查询约有100个已标注的相关文档。这并不意味着文档总量少,而是评估过程更为精确。
-
MS MARCO:这是信息检索领域极其重要的资源,也是最大的公开检索基准。它由一个问答数据集改编而来,基于超过50万个Bing搜索查询。虽然标注相对稀疏(每个查询只有一个相关性标签),但这恰好符合训练之前介绍的神经IR模型所需的环境。对于段落排序任务,它提供了900万个短段落;对于文档排序任务,它提供了300万个长文档。这是一个用于探索系统性能和创建预训练资源的绝佳平台。
-
BEIR (信息检索基准测试):这是一个重要的新基准,其核心目标是在多种不同领域和任务设置下,对IR模型进行多样化的零样本评估。该基准近期在模型评估中非常有用。
-
LOTTE (长尾主题分层评估):这是我们发布的一个配套数据集。其核心思想是主要利用Stack Exchange平台,来探索相当复杂和多样化的问题。它同样用于零样本评估。我们发布的数据集包含了主题对齐的开发集和测试集对,因此你可以在开发集上测试系统的零样本性能,然后尝试迁移到可比较的领域。LOTTE的另一个特点是包含两个部分:一部分侧重于网络搜索中常见的查询,另一部分则侧重于论坛(如Stack Exchange)中人们直接提出的更复杂的问题。
-
Xor/TyDi QA:这是一个出色的项目,旨在将信息检索推向更广泛的多语言环境,涵盖问答、开放域问答以及纯检索应用。如果你考虑开发多语言IR解决方案,这个数据集值得关注。
以上就是关于数据集的内容。当然还有其他数据集,但以上是一些最核心的资源。

未深入讨论的核心主题 💡
接下来,我想列出几个我未能深入讨论的核心主题。
首先,关于负采样技术有大量文献。回想一下我描述的那些三元组(查询、正例文档、负例文档)。关键问题是:负例从哪里来?你总需要在“让负例足够简单以便模型区分”和“让负例足够困难以便模型学习细微差别”之间取得平衡。把握好这个平衡可能非常具有挑战性。
其次,我也没有充分讨论弱监督。我提到过一种策略:检查文档是否包含查询词作为子字符串,并将其用作相关性的信号。我们在先前的工作中发现,这种简单的启发式方法可能非常强大。我认为这尤其表明,在训练系统时,我们应该更多地采用弱监督方法,因为它通常非常有效且成本低廉。
最后,我在最近的论文中多次提到 DINOSCORE。这是一种将许多不同指标整合为单一统一指标的方法,用于创建能够全面体现IR各个方面的排行榜。我们将在本季度晚些时候讨论DINOSCORE。我认为我会再次回到IR这个例子,因为它很好地说明了在考虑系统质量时,多种因素是如何共同作用的。
总结 🎯
本节课中我们一起学习了信息检索领域的关键数据集和一些延伸主题。
最后,我想强调一点:自然语言理解(NLU)和信息检索(IR)再次紧密地结合在了一起,这对研究和技术发展具有深远影响。我希望这一系列的课程向你展示了这个研究领域是多么活跃和令人兴奋,并促使你思考如何参与其中。无论是在学术界,还是在努力应用语言技术的工业界,你都可以产生非常大的影响。



这是一个在科学和技术上都极其激动人心的领域,也是一个关于这些领域如何重新结合以实现新的、更大目标的精彩而鼓舞人心的故事。
20:上下文学习,第一部分:起源 🧠

在本节课中,我们将要学习上下文学习这一核心概念的起源。我们将回顾从早期基于规则的语言模型到现代大型语言模型的发展历程,了解“仅通过文本提示即可让模型执行多种任务”这一革命性想法是如何诞生的。

欢迎各位。这是我们关于上下文学习系列的第一个视频。
这个系列与我们之前关于信息检索的系列相辅相成。


这两个系列将共同帮助你完成作业2和竞赛2,其重点是使用冻结的检索器和冻结的大型语言模型进行少样本开放域问答。
为了开启这个系列,我们首先反思一下上下文学习这一概念的起源。
这实际上是一个关于自然语言处理领域如何发展到当前这个既奇特、令人兴奋又有些混乱的时期的故事,或许对整个社会而言也是如此。
所有功劳归于“乔姆斯基机器人”将我们带到这一刻。
我是在开玩笑。“乔姆斯基机器人”是一个非常简单的基于模式的语言模型。
我相信它自90年代就已存在。通过非常简单的机制,它能生成大致模仿政治哲学家兼语言学家诺姆·乔姆斯基风格的散文。
它生成的散文令人愉悦,或许也能给我们带来启发。其底层机制非常简单。
我认为这很好地提醒了我们,即使是当今所有这些大型语言模型,其本质可能也是如此。
不过,我确实只是在开玩笑,尽管这玩笑只开了一半。
当我们思考上下文学习的先例时,值得提到的是,在深度学习时代之前,基于N-gram的语言模型——那些非常稀疏的大型语言模型——通常确实非常庞大。
例如,Brants等人在2007年使用了一个拥有3000亿参数、在2万亿文本标记上训练的语言模型来辅助机器翻译。
这是一个非常庞大且强大的机制,与当今的大型语言模型性质不同,但值得注意的是,它们在很久以前就在许多不同领域发挥了重要作用。
我认为,就我们所知的上下文学习而言,最早的论文,据我所知,是DaCa NLP论文。
这是McCann等人在2018年的工作。他们使用自然语言问题作为任务指令进行多任务训练,这似乎就是“通过自由形式的自然语言指令,我们最终可以得到仅由文本引导就能执行多种任务的模型”这一想法的起源。
同样值得指出的是,在GPT论文(Radford等人,2018)中,你可以发现一些关于使用该模型进行基于提示的实验的初步提议。
但这个想法真正的起源,再次据我所知,是Radford等人在2019年的GPT-2论文。
让我展示一下这篇论文的一些片段。他们所做的工作之多,确实令人鼓舞。
他们在开头写道:“我们证明语言模型可以在零样本设置下执行下游任务,而无需任何参数或架构修改。”
在这里,你看到了使用冻结模型、提示它们并观察其是否能产生有趣行为这一想法。
他们研究了许多不同的任务,例如摘要生成。
他们写道:“为了诱导摘要行为,我们在文章后添加文本‘TL;DR’,然后生成100个标记。”这非常令人震惊。
我记得当我第一次听说这个想法时,我对这类上下文学习能成功抱有强烈的认知偏见,以至于我以为他们想告诉我们的是,他们专门训练了那个标记来做摘要,然后只是给它起了一个花哨的名字。但并非如此,他们确实是认真的。他们只是用这个标记提示模型,然后观察输出结果。
对于翻译任务,他们写道:“我们测试GPT-2是否已经开始学习如何将一种语言翻译成另一种语言。为了帮助模型推断出这是期望的任务,我们以示例对的上下文为条件,格式为‘英语句子 = 法语句子’。然后,在最后的提示‘英语句子 =’之后,我们使用贪婪解码从模型中采样,并将第一个生成的句子作为翻译。”
这非常了不起。你在这里看到浮现的是“演示”这一想法,即在提示中包含一些你期望行为的示例,以此引导模型去做你想让它做的事情。
这里有一个类似的例子。他们写道:“与翻译类似,语言模型的上下文被设定为示例问答对,这有助于模型推断数据集的简短答案风格。”这是针对问答任务的。同样,他们开始发现演示可以帮助模型理解隐含的任务指令。
他们在论文中还评估了许多其他内容,如文本补全、Winograd模式、阅读理解等,可能还有其他任务。这是一次非常令人印象深刻且全面的探索,对方法的优点和局限性非常开放,是一篇极具创意和启发性的论文。
这就是该想法在研究意义上的开端。
而文化意义上的转折点无疑出现在GPT-3论文(Brown等人,2020)中,这篇论文本身也以多种方式令人印象深刻。
在这里,我将引用其摘要的一部分,我们可以稍作停留,思考一下它的内容。
他们开头写道:“我们表明,扩大语言模型的规模极大地改善了任务无关的少样本性能,有时甚至达到了与先前最先进的微调方法相竞争的水平。”
我们可以争论他们是否真的达到了那种竞争水平,但毫无疑问,他们在这种任务无关的少样本设置中,从他们的模型中获得了非常令人印象深刻的行为。
具体来说:“我们训练了GPT-3,这是一个拥有1750亿参数的自回归语言模型,比以往任何非稀疏语言模型多10倍,并在少样本设置中测试其性能。”
关于这部分,有两点我非常喜欢。第一,1750亿参数确实非常宏大且令人印象深刻,即使在今天也是如此,更不用说在2020年了。第二,我真的很喜欢他们提到了“非稀疏语言模型”,这是对我之前提到的那些通常非常庞大的基于N-gram模型的认可。

对于所有任务,GPT-3的应用都没有任何梯度更新或微调,任务和少样本演示纯粹通过与模型的文本交互来指定。
这很好。事后你可能会觉得他们在这里有点重复,因为他们已经确立了这些将是冻结模型。但我认为他们有必要这样做,因为这在当时是一个非常陌生的想法。我可以想象,作为这篇论文的读者,会认为他们不可能真的意味着对所有任务都只使用冻结模型,肯定在某个地方有微调。因此他们强调,事实上,模型是完全冻结的。
GPT-3在许多NLP数据集上取得了强大的性能,包括翻译、问答和完形填空任务,以及一些需要即时推理或领域适应的任务,例如在句子中使用新词来解读乱序词或执行三位数算术。
我喜欢这一点。任务的多样性非常真实。我认为你可以看到他们真正在尝试挑战在这种模式下可能达到的极限。
同时,我们也发现了一些GPT-3的少样本学习仍然存在困难的数据集,以及一些GPT-3面临与在大型网络语料库上训练相关的方法论问题的数据集。
我也很喜欢这句话。它再次对他们取得的成就和存在的局限性非常开放。他们承认发现了一些对模型来说仍然困难的任务。他们还在论文中承认,他们本意是确保没有在相关测试任务的数据上进行训练,但实际上他们并没有完全做到这一点。他们对此非常开放,并探讨了在他们所操作的规模下,要做到这一点有多困难。
因此,就像GPT-2论文一样,这是一次对思想非常开放和彻底的探索。

在本节课中,我们一起学习了上下文学习概念的起源。我们从简单的“乔姆斯基机器人”模式模型谈起,回顾了早期大规模N-gram模型的作用,然后重点探讨了GPT-2和GPT-3论文如何开创性地展示了仅通过文本提示和演示,就能让冻结的大型语言模型执行多种复杂任务。这些早期工作为当前自然语言处理领域激动人心的发展奠定了基础。
21:上下文学习核心概念(第二部分)🚀



在本节课中,我们将深入探讨上下文学习的几个核心概念。这些概念将帮助我们理解大型语言模型如何在不更新参数的情况下,仅通过给定的提示文本来执行任务。
术语定义 📖
首先,让我们明确一些关键术语。文献中对这些术语的使用存在差异,因此我将清晰地阐述我的定义。
上下文学习 指的是一个冻结的语言模型,仅通过条件化于提示文本来执行任务。模型是冻结的,意味着没有梯度更新。我们唯一的学习机制是输入一些文本,使模型进入一个临时的状态,我们希望这个状态能帮助它生成对我们任务有用的内容。
少样本上下文学习 是上下文学习的一个特例。其特点是提示中包含预期行为的示例,并且这些示例未在训练中见过。当然,在模型基于海量文本训练的时代,我们通常无法验证这一点。但这是少样本学习的理想和精神所在:即仅凭少数几个例子,模型就能完成我们期望的任务。
零样本上下文学习 是另一个特例。其特点是提示中不包含预期行为的示例,但可以包含一些指令。同样,预期行为的示例也未在训练中见过。提示中的格式说明和其他指令是一个灰色地带,但我们将允许仅包含描述的提示仍属于零样本范畴。
模型工作机制回顾 🔄
上一节我们定义了核心术语,本节中我们来看看GPT等模型的工作原理。我们在“上下文表示”单元中介绍过,这里再回顾一下,以便在思考上下文学习技术时能将其置于首要位置。
这些模型使用自回归损失函数。其核心在于,评分是基于两个关键要素进行的:
- 我们想要在时间步
T预测的那个词元的嵌入表示。 - 模型在时间步
T之前创建的隐藏状态。
公式表示:P(w_t | w_<t) = softmax(E * h_t-1),其中 E 是嵌入矩阵,h_t-1 是上一个时间步的隐藏状态。
训练阶段:教师强制
下图展示了训练阶段,特别是教师强制的过程。

以下是训练过程的分解:
- 底部是代表训练序列中词元的独热向量。
- 这些向量在嵌入层(图中灰色部分)中查找,得到一系列向量。
- 这些向量作为输入,送入用于语言建模的大型Transformer模型。注意其注意力机制的模式:在自回归建模中,注意力只能关注过去,不能关注未来。
- 经过所有Transformer块处理后,在顶部再次使用嵌入层。
- 模型的“标签”是底部序列偏移一个位置的序列。例如,用起始词元预测“the”,用“the”预测“rock”,依此类推。
- 模型在每个时间步预测的是整个词表上的得分向量。学习信号来自于比较这个得分向量和真实的独热向量之间的差异,并据此进行梯度更新。
需要强调的是,模型并不直接预测词元,而是预测得分向量。我们通过特定的规则(如选择最高分)来决定生成哪个词元。即使在训练中,我们也可以采用不同的方式使用预测的得分向量。
推理阶段:文本生成
我们的重点在于本单元的冻结语言模型,因此我们真正要思考的是生成过程。
假设模型已被提示了起始词元和“the”,并生成了“rock”。我们将“rock”的独热向量作为下一个时间步的输入,模型处理并做出下一个预测(例如“rolls”),如此循环。
这即是生成过程。再次强调,在每个时间步,模型预测的是词表上的得分向量。我们使用自己的规则(例如贪婪解码,即每步选最高分)来决定实际对应哪个词元。但也可以使用其他规则,如束搜索,它会考虑多个时间步的整体得分来选择最佳序列。
现代大型语言模型的API提供了许多参数,本质上都是在塑造生成过程。这提醒我们,生成并非模型固有的能力,而是我们通过外部规则强加给它们的行为。
一个值得探讨的问题 💭
基于以上机制,我们可以提出一个值得探讨的问题:自回归语言模型是否只是简单地预测下一个词元?
初看答案似乎是肯定的。然而,从技术层面更准确的说法是:它们预测的是每个时间步上整个词表的得分,然后我们利用这些得分来“迫使”它们预测某个词元。此外,模型在其内部和输出表示中承载着数据,在NLP中,我们常常关心的是这些表示,而非特定的生成过程。这表明自回归语言模型所做的远不止“说话”。
但权衡之下,出于与公众进行科学沟通的目的,说它们“基于已生成的词元和输入的词元来预测下一个词元”可能是最好的方式。这是一个恰当的机制性解释,有助于人们理解实际发生的过程。
我们应该提醒自己,即使看到模型表现出更令人印象深刻的行为,其底层机制是统一的。例如:
- 提示“better late than”,模型回复“never”。这显然是提示序列的一个高概率延续。
- 提示“Every day, I eat breakfast, lunch, and”,模型可能回复“dinner”。这看似反映了世界知识,但对语言模型而言,这只是基于世界规律的一个高概率延续。
- 提示“The president of the US is”,模型给出一个人名。这看似存储了世界知识,但就我们所知,机制上这只是提供了序列的高概率延续。
因此,当提示“The key to happiness is”,模型给出一个看似深刻的答案时,你应该再次提醒自己:这仅仅是基于模型所有训练经验,对输入序列的一个高概率延续。机制是统一的。
指令微调:重要的背景概念 🛠️
最后,我想提及一个我们将在本系列中多次回归的核心概念:指令微调。
这个概念来自发布ChatGPT的博客文章,描述了如何对该模型进行指令微调。主要包含三个步骤:
以下是步骤概述:
- 监督微调:使用人类精心编写的“提示-优质输出”示例对模型进行训练。这看起来是标准的监督学习。
- 奖励模型训练:人类对模型针对不同提示生成的多个输出进行质量排序。模型学习预测人类偏好的输出。
- 强化学习:利用上一步训练的奖励模型,通过近端策略优化等强化学习算法进一步微调语言模型。
关键点在于,步骤1和2中,人类扮演了至关重要的角色。我们已经离开了纯粹分布假说的版本(即仅对无结构的序列符号进行语言模型训练就能得到强大模型),重新进入了一个模式:许多最有趣的行为,无疑是因为人类直接提供了关于“给定输入,什么是好输出”的监督。
当这些模型似乎能完成非常复杂的任务时,这并非魔法,很大程度上是因为它们被非常复杂的人类指令去这样做。这对于理解模型为何有效至关重要,对于理解各种上下文学习技术的行为也很重要。因为 increasingly,我们正在看到一个反馈循环:我们想在提示中做的事情,正在影响监督学习阶段发生的事情,使其变得更强大。这并非关于大语言模型工作原理的神秘发现,而只是对当前非常普遍的指令微调方式的一种反映。
总结 📝


本节课我们一起学习了上下文学习的核心概念。我们首先明确了上下文学习、少样本和零样本学习的定义。接着,我们回顾了GPT等自回归语言模型的工作原理,区分了训练时的教师强制和推理时的文本生成过程,并认识到模型本质是预测得分向量。在此基础上,我们探讨了“模型是否只是预测下一个词元”这一问题,并提醒自己所有惊人输出本质上都是基于训练数据的高概率序列延续。最后,我们介绍了指令微调的概念,认识到人类提供的直接监督在塑造模型强大能力中的关键作用。理解这些概念,是深入探索上下文学习技术的基础。
22:上下文学习(第三部分):当前时刻 📚

在本节课中,我们将探讨上下文学习领域的最新动态,重点关注用于训练大型语言模型的数据,特别是从无监督预训练到指令微调的范式转变。我们将了解数据如何塑造模型行为,并介绍一种名为“自我指导”的创新方法,它展示了如何使用模型自身来生成训练数据。


数据:理解模型行为的关键 🔑
上一节我们讨论了上下文学习的基本原理。本节中,我们来看看数据,特别是用于自监督学习的数据。这是理解我们大型语言模型行为的一个极其重要的因素。
以下是一些关键的数据集和概念:
- C4 数据集:这是一个为 T5 建模工作创建的大规模爬取语料库,由 Dodge 等人在 2021 年进行了审计。《华盛顿邮报》的一篇相关文章称其为“让 ChatGPT 等 AI 听起来很聪明的秘密网站列表”。尽管“秘密”一词可能并不准确,但该文章有助于我们审计此类数据集的内容。
- 数据的重要性:用于无监督预训练的数据是理解模型能力和局限性的关键因素。
从无监督预训练到指令微调 🚀
正如上一节末尾提到的,我们已不再处于语言模型预训练仅仅是无监督语言模型预训练的时代。我们现在已经进入了指令微调的时代。
然而,我们对指令微调的具体情况知之甚少:
- 工业实验室的做法:我们并不确切知道大型工业实验室在此方面的数据和协议。可以推断,他们雇佣了大量人员来生成指令数据。这些人员通常执行复杂的任务,例如根据提示编写特定类型的 Python 程序。
- 监督的本质:当前从语言模型中看到的复杂能力,并非以某种神奇的方式从无监督预训练中涌现,而是直接来自于标准、传统的监督学习。
- 模型的自我改进:我们还可以推断,这些大型工业实验室正在使用他们自己的模型来生成示例,并在示例之间进行裁决。接下来我们将回顾一种名为“自我指导”的方法。
如果你想了解指令微调的感觉,我鼓励你查看 斯坦福人类偏好数据集。这是一个基于 Reddit 帖子构建的新指令微调数据集。你可以使用它(或其子集)进行微调,以感受指令数据如何影响模型行为,这可能会很有启发性。
自我指导:用模型改进模型 🤖
我之前提到了“自我指导”。这是一种强大的方法,指出了我们可以使用模型来使模型变得更好的多种新途径。
以下是“自我指导”方法的工作流程:
- 任务池初始化:从人类编写的 175 个任务开始,放入任务池。
- 指令生成:通过上下文学习,让语言模型生成一些新的指令。
- 任务类型识别:将生成的指令反馈给同一个语言模型,使用新的提示来帮助模型判断该指令是分类任务还是其他类型的任务。
- 输入-输出对生成:根据第 2 步的生成结果,将生成的输出输入到下方两个提示中的一个,从而得到新的输入-输出对,可用于后续的监督式语言模型预训练。
- 数据过滤与迭代:对生成的数据进行质量过滤并确保数据集的多样性,然后将这些生成的指令放回任务池,可以参与生成更多数据。
通过这种方式,我们可以使用一个语言模型来自举生成一个新的数据集,然后用这个新数据集更新同一个模型,希望它能获得更多样化的能力。
自我指导的提示词示例
这听起来有些抽象。让我们通过他们使用的提示词来逐步了解“自我指导”是如何发生的。
步骤 1:指令生成
模型被给予 8 个示例(最初多为人工创建,后续迭代中会加入模型生成的指令),然后被要求生成一个新指令。
步骤 2:分类任务识别
将步骤 1 的生成结果输入此提示,模型在上下文中学习预测它是否是一个分类任务。
步骤 3:生成输入-输出对
根据步骤 2 的生成结果,将其输入到分类任务提示或非分类任务提示中。这里的结果为我们提供了新的输入-输出对,可用于扩充我们的自我指导数据集。
然后,如前所述,我们以标准方式进行后续的监督式语言模型预训练,或者使用其他技术来更新用于此生成过程的模型。
Alpaca:自我指导的成功案例 🦙
“自我指导”是 Alpaca 模型背后的主要机制。Alpaca 是该领域近期的一个重要时刻,因为它开始向人们展示,我们可以通过自我指导方法,对像 70 亿参数这样相对较小的模型进行指令微调,并获得非常强大的结果。
更详细地说,Alpaca 的工作方式如下:
- 基础模型:从一个 LLaMA 模型开始(LLaMA 是 Meta AI 最近发布的一类模型)。
- 种子任务:使用自我指导论文中人类编写的 175 个任务作为起点。
- 数据生成:遵循自我指导流程(略有简化),使用 text-davinci-003 作为引擎来创建新的输入-输出对。
- 数据集:最终得到一个包含 52,000 个示例的数据集。
- 模型更新:使用这些示例更新 LLaMA 模型,从而创建出 Alpaca。
观察发现,这次相对小规模的模型更新工作,在赋予 Alpaca 新的指令遵循行为方面,效果实际上非常强大。
这里有一个关于技术的重要启示:这是一个令人兴奋的新方向,让我们思考如何使这些相对较小的模型性能越来越高。同时,这对你的上下文学习也有启示:显然,如果你能调整自己的提示词,使其与 Alpaca 等模型见过的指令微调数据保持一致,你将会更成功。这个经验可以推广到所有大型语言模型。
对于像 Alpaca 这样的模型,我们可以了解其指令微调数据,但对于最大的模型,我们则无法了解。因此,人们必须有机地发现哪些提示技术有效,我认为这实际上是一个揭示它们指令微调阶段情况的过程。
模型小型化与性能提升的趋势 📉
正如我所说,Alpaca 令人兴奋,因为它打破了模型规模不断增大的趋势。在本课程介绍讲座中使用的幻灯片显示,模型参数规模一路攀升至 5400 亿的 PaLM。GPT-4 的规模可能比这还要大得多。
由于这种指令微调,我们开始看到模型规模可能会下降,但性能依然非常强大。这极其令人兴奋,因为它必将发生。在智力、技术和财务方面,我们都有很多动力去寻找让小型模型保持高性能的方法。我认为,这将是真正实现大型语言模型及其所能实现的能力民主化访问的重要一步。


本节课中,我们一起学习了当前上下文学习领域的关键动态。我们探讨了数据,特别是从无监督预训练到指令微调的转变,并深入了解了“自我指导”这一利用模型自身生成训练数据的方法。最后,我们以 Alpaca 为例,看到了模型小型化与性能提升的积极趋势,这为未来更广泛地应用大型语言模型能力带来了希望。
23:上下文学习(第四部分)技术与建议方法 🧠


在本节课中,我们将深入探讨上下文学习的具体技术,并为你未来的研究提供一些方向建议。我们将从核心概念“演示”开始,逐步介绍多种提升模型表现的技术,最后总结一些实用的研究方法。

概述:什么是演示?🤔
上一节我们介绍了上下文学习的基本概念,本节中我们来看看一个核心技巧:演示。演示的概念至少可以追溯到GPT-2论文,它在设计有效的上下文学习系统中极其强大。
让我们以“少样本开放域问答”为例进行说明。假设我们有一个问题:“Bert是谁?”。我们准备将这个提问输入给语言模型,并希望它能生成一个好答案。
现在你可能已经意识到,在提示词中插入一个相关的上下文段落会很有帮助,可以为模型提供回答问题的证据。演示背后的思想是,向模型展示我们希望它模仿的行为示例也可能很有用。
因此,我们可能有一个训练集的问答对,我们取出其中一个问答对并将其插入到提示词中。例如,我们插入问题“Kermit是谁?”以及它的答案。
如何选择与构建演示?🔍
以下是关于选择和构建演示的一些关键考虑点:
选择答案的来源
- 你可以直接使用训练集中问答对的“黄金答案”。
- 但反直觉的是,使用从某个数据存储中检索到的答案,甚至使用你正在提示的同一语言模型生成的答案,可能更有用。这可能有助于找到更符合你当前语言模型实际能力的演示。
选择证据段落的来源
- 当然,如果有的话,可以直接使用训练数据中的“黄金段落”。
- 但由于我们为目标问题检索了一个段落,为了更贴近模型的实际体验,使用检索到的段落而非黄金段落来构建演示,可能能更好地示范预期行为。
选择演示的策略
- 你可以从可用数据中随机选择演示。
- 更好的方法是根据演示与目标示例的关系来选择。例如,在生成任务中,可以根据与目标输入的某种相似性来检索示例;在分类任务中,可以选择能帮助模型隐式确定目标输入类型的演示。
过滤演示以满足特定标准
- 在生成任务中,可能希望确保证据段落包含输出字符串,以帮助模型理解如何处理我们提供的证据。
- 在分类任务中,一个直接的做法是确保每个提示的演示集都包含数据集中出现的每个标签,这样模型就能看到每个可能行为的示例。
加工可用的演示
- 我们可以对演示进行采样,然后用语言模型重写它们。
- 这样做可以综合多个初始演示,可能更高效,并允许我们包含更多演示。
- 我们还可以改变风格或格式以匹配目标,使用语言模型使演示更符合语言模型的期望或能力。
你需要习惯的一个基本点是:对于强大的上下文学习系统,你的提示词可能包含由同一个语言模型通过不同提示生成的子字符串。是的,这可以是递归的。尽管子字符串本身可能是多次调用语言模型的产物,但最终结果可以非常有效地将语言模型的行为与你希望看到的结果对齐。
链式思维与分步推理 🧩
让我们转向另一种技术:链式思维。我认为这也是一个持久有效的思想。
链式思维背后的直觉是,对于复杂的事情,要求模型在初始标记中直接生成答案可能负担过重。因此,在链式思维中,我们构建鼓励模型以逐步方式生成、暴露自身推理并最终得出答案的演示。
这再次展示了演示的力量:我们用这些可能手工构建的、详尽的提示来示范链式思维。然后,当模型执行我们的目标行为时,演示会引导它进行类似的链式思维,最终产生我们希望的正确答。
我认为存在一个更通用的版本,可以非常强大,我称之为带指令的通用分步推理。在这里,我们肯定在某种程度上与这些模型可能经历过的指令微调对齐,并以某种间接方式利用它。
自我一致性与自我提问 ✅
自我一致性是另一个强大的方法。这来自于Wang等人2022年的工作,与早期称为“检索增强生成”的模型密切相关。
我们将使用语言模型来采样一堆不同的生成响应,这些响应可能通过类似链式思维的推理走过不同的推理路径,并最终产生一些答案。这些答案可能因模型采取的不同生成路径而异。我们要做的是,选择在所有不同推理路径中最常产生的答案。从技术上讲,这是通过边缘化推理路径来得出的答案的一种形式,其直觉是,被最多路径得出或给定所有路径最可能的答案,很可能是可信的。
自我提问是另一个有趣的想法。自我提问背后的思想是,通过演示,鼓励模型将其推理分解成一系列它向自己提出并试图回答的问题。这样,模型将迭代地达到能够找到整体问题答案的程度。这对于可能是“多跳”的问题尤其强大,即可能涉及多个不同资源的问题,你可以将其分解为需要解决的多个子问题,以获得最终问题的答案。
自我提问对我们这些以检索为导向的研究者来说有一个有趣的特性:它可以与检索结合来回答中间问题。与其信任模型对这些中间问题的生成,不如使用像搜索引擎这样的工具来回答这些问题,然后将答案插入提示词中,模型继续运行。
迭代重写与工具整合 🔄
另一个我相信无论人们发现什么关于上下文学习的新技术都会存续的、非常强大的通用思想是:迭代重写提示词的部分内容可能很有用。你可以重写演示、它们包含的上下文段落、问题或答案。
特别是在提示窗口有限或信息非常复杂的情况下,迭代地让语言模型重写其自身提示词的部分内容,然后用这些重写的块来提示模型,作为一种综合信息和获得更好结果的方式,这可能很有帮助。这是一个非常强大的想法。

最后,在当前这个或许是短暂的时刻,涉及多个预训练组件和工具的提示设计,相对于其潜在价值而言,似乎尚未被充分探索。对于本单元,我们正在探索检索模型和语言模型如何协同工作以完成强大的任务。但我们显然可以引入其他预训练组件,甚至其他核心计算能力,如计算器、API等。思考如何设计能利用所有这些不同工具的提示词,是一个美妙的新途径。
总结与建议方法 📝
本节课中我们一起学习了多种提升上下文学习效果的技术,从演示的选择与构建,到链式思维、自我一致性和自我提问等高级推理方法,再到迭代重写和工具整合的通用思想。
基于以上内容,以下是一些建议的研究方法供你思考:

建立评估基准
首先,作为一种工作习惯,根据你想要解决的任务,为自己创建开发集和测试集,并采用能与许多不同提示词配合的格式。首先做这件事,这样在你探索时,你就有一个固定的目标去努力实现,这将帮助你获得更好的结果并更加科学严谨。

了解你的目标模型
尽可能了解你的目标模型,包括它是如何训练的等等。特别要注意它是否针对特定的指令格式进行过微调。我认为我们已经看到,只要你能与其指令微调数据对齐,你就会获得更好的结果。
将提示词编写视为AI系统设计
尝试编写系统化、可推广的代码来处理整个工作流程,从读取数据到提取响应和分析结果。这是DSP背后的指导哲学思想。即使超越DSP,我认为这也是一个重要的方法论说明。我们不应该以非常临时的方式敲出提示词和设计系统。我们应该将其视为我们编程AI系统的新模式,并尽可能认真地对待它。

探索多组件与工具整合
最后,探索如何将检索模型、语言模型乃至计算器、API等其他工具结合起来,设计强大的提示系统,这是一个充满潜力的新方向。
24:作业3与竞赛概述 🧠


在本节课中,我们将学习作业3及其关联竞赛的核心内容。我们的主题是组合泛化,旨在深入探究模型是否学会了系统性地解释自然语言。
背景介绍
研究的起点是Kim和Lndson的Cogs论文及其相关基准。我们将使用其改进版本——Recogs。Recogs在保留Cogs核心见解与议程的同时,试图解决我们在原始Cogs基准中发现的一些局限性。
Recogs任务本质上是一个语义解析任务。输入是简单句子,输出是如下所示的逻辑形式。
示例1:
- 输入:
a rose was helped by a dog - 输出:
help.v ( theme ( a.det rose.n ) , agent ( a.det dog.n ) )
示例2:
- 输入:
The sailor dusted a boy - 输出:
dust.v ( agent ( the.det sailor.n ) , theme ( a.det boy.n ) )
你可以看到,Cogs和Recogs的句子通常有些特殊。这是一个合成基准,由上下文无关文法自动生成,因此其实际含义有些非常规,但这并非这两个基准的重点。
Cogs与Recogs的对比
我们将在本单元的核心视频中更详细地讨论Cogs和Recogs的对比。简而言之,Cogs是原始版本,Recogs在其基础上构建,并试图重构Cogs的某些方面,以专注于纯粹的语义现象。我们认为Cogs还额外测试了逻辑形式中许多无关紧要的细节。
快速对比示例:
- 输入:
the sailor saw Emma - Recogs格式:
see.v ( agent ( the.det sailor.n ) , theme ( Emma ) ) - Cogs格式:
see.v ( x1 / see :agent ( x2 / sailor :ref ( x3 ) ) :theme ( x4 / Emma :ref ( x5 ) ) )
概括地说,Recogs格式更简单。它移除了一些冗余符号,并重组了语义的核心方面,同时保留了原始含义。
数据集划分
Recogs的数据划分如下:
- 训练集: 约136,000个示例。
- 开发集: 3,000个示例,与训练集分布相似(IID划分)。我们不会过多使用开发集。
- 泛化划分: 21个类别,共21,000个示例。这是Cogs和Recogs最有趣的部分。其核心在于测试模型是否对任务找到了组合式的解决方案,即考察模型能否处理熟悉元素的新颖组合。
以下是三个泛化划分的示例,它们代表了整个集合的特点。可以说,这些泛化划分的一个标志是,对于我们语言使用者而言,它们几乎不像是泛化任务,看起来极其简单。然而,正如你将看到的,即使对我们最好的模型来说,它们也非常困难。
1. 主语到宾语专有名词
- 训练集示例:
Lina helped a cat.(Lina是主语) - 泛化集示例:
A dog helped Lina.(Lina是宾语) - 目标: 测试模型能否理解Lina在这个不熟悉的输入中扮演的语义角色。对人类很简单,对模型则极具挑战。
2. 原始形式到主语
- 训练集示例: 名字作为孤立元素出现(无句法上下文)。
- 泛化集示例: 名字作为完整句子的主语出现。
- 目标: 看似简单,但被证明具有挑战性。
3. CP递归
- 训练集示例:
Emma said that Noah knew that the cat danced.(两层嵌套) - 泛化集示例:
Emma said that Noah knew that Lucas saw that the cat danced.(三层嵌套) - 目标: 测试模型能否处理新数量的嵌套句子。对我们来说几乎不像是泛化任务,但对模型而言再次变得困难。
作业问题详解
以上是背景介绍。现在,让我们来看看作业的具体问题。
问题1:专有名词及其语义角色
对于这个问题,你不需要训练模型。这是经典的数据分析任务。它包含两部分:
任务1: 编写一个名为 get_proper_name_roles 的函数。该函数接收一个逻辑形式,并提取其中出现的所有(名字,角色)对列表。
任务2: 编写 find_name_roles 函数。该函数使用 get_proper_name_roles 来发现不同专有名词在Recogs各个数据划分中扮演的角色。
剧透预警: 分析会发现,专有名词“Charlie”在训练集中只作为主题出现,而在泛化划分中只作为施事者出现;而“Lina”则相反,在训练集中只作为施事者,在泛化划分中只作为主题。这个关于数据的观察很大程度上解释了后续模型的性能表现。这些名字确实被证明对我们的模型来说非常难以处理。
建模环节说明
在问题1之后,我需要提醒你,接下来有一个较长的建模环节。我已经提供了训练你自己的Recogs模型所需的所有代码片段。你并非必须这样做,但我希望提供这些资源,以便你可以将其作为构建原创系统的一个途径。
让我为你梳理一下这个环节:
- Hugging Face分词器: 我原本计划将其设为作业问题,但编写这个分词器非常困难和令人困惑,因此决定不增加你们的负担。我直接提供了它,希望你们能从中受益,并可能为未来的任务修改它。
- PyTorch数据集: 这是为Recogs准备的数据集。它有一些棘手的细节,因此我也直接提供给你们。
- 预训练的Recogs模型: 这是一个名为
Zen的预训练模型,性能出色。你可以直接加载并使用它作为你的原创系统的基础。你可以微调它或进行其他操作,但下一个作业问题并不需要你这样做。 - Recogs损失函数: 这是一个简单的PyTorch模块,帮助我将
Zen训练的模型与我们课程代码兼容,方便你进行微调。 - Recogs模块: 这是
Zen模型的轻量级包装器,旨在帮助我们与课程代码库中的底层优化代码兼容。 - Recogs模型: 这是主要的接口。如果你不打算为原创系统训练模型,只需关注这一步,将其视为加载和使用
Zen模型的简单接口。
我希望你们中有人愿意深入研究这个模型的训练方式并改进它。在这种情况下,步骤1到5将特别有用。这就是为什么它们都嵌入在笔记本中。
问题2:探索模型预测
完成建模环节后,我们来到问题2:探索模型预测。对于这个问题,你只需直接使用预训练的Zen Recogs模型。
你要做的是继续问题1开始的数据分析。你需要完成一个名为 category_assess 的函数。这里的核心目标是让你自己发现,这个非常优秀的模型在处理处于不熟悉位置的专有名词时(正是你在问题1中识别出的那些名字)确实遇到了很大困难。
因此,你可以在这里验证Cogs和Recogs背后的假设:这些元素的新颖组合,无论多么简单,对于一个真正优秀的模型来说都是具有挑战性的。
关于Recogs评估的说明
在继续之前,我想谈谈Recogs的评估。我们将在本单元的主视频中更详细地讨论这一点。简而言之,Recogs的目标是真正测试语义解释,并超越逻辑形式中一些无关紧要的细节。
因此,我们的评估代码有些复杂。以下是三个有启发性的例子:
-
绑定变量的精确名称无关紧要。
help.v ( theme ( a.det rose.n ) , agent ( a.det dog.n ) )与help.v ( theme ( a.det rose.n ) , agent ( a.det dog.n ) )是等价的,即使第一个用变量4,第二个用变量7。因为所有变量都是隐式绑定的,我们只关心它们建立的绑定关系。
-
合取项的顺序无关紧要。
dog.n and happy.a与happy.a and dog.n评估为真。合取项的顺序是无关紧要的。
-
变量名称的一致性很重要。
dog.n ( x4 ) and happy.a ( x4 )与dog.n ( x4 ) and happy.a ( x7 )评估为假。因为第一个逻辑形式是关于一个元素,而第二个(可能)是关于两个不同的元素,它们在语义上是不同的。
这三个例子让你感受到我们评估代码的目标:即使逻辑形式不同,也要达到语义等价。
问题3:上下文学习基础方法
作业主要部分的最后一个问题是问题3,它完全转换了思路。这是一个基础的上下文学习方法。这里的想法是帮助你们迈出第一步,像在作业2中那样使用DSP,并将其应用于这个新案例。
我的想法是,如果我推动你们为Recogs编写第一个DSP程序,你们可能会尝试更多版本并取得真正进展。以下是你将提供给模型的提示示例:
输入:a rose was helped by a dog
输出:help.v ( theme ( a.det rose.n ) , agent ( a.det dog.n ) )
输入:The sailor dusted a boy
输出:dust.v ( agent ( the.det sailor.n ) , theme ( a.det boy.n ) )
输入:A cat saw Emma
输出:
模型的任务是生成一个新的逻辑形式。你在编码方面的任务就是编写一个非常简单的DSP程序。正如我所说,我希望它能激励你们为原创系统做更复杂的事情。
我需要警告你,即使对于我们最好的大语言模型,它们表面上似乎理解这个任务是什么,当你瞥一眼它们预测的逻辑形式时,它们通常看起来还不错。但当你运行评估代码时,你会得到零分,然后意识到“还不错”对于这个任务来说并不足够。你需要完全正确,而这些大语言模型似乎很难在这个语义解析任务上做到完全正确。
问题4:原创系统
最后,和往常一样,问题4是构建你的原创系统。对于你的原创系统,你可以做任何你想做的事情。唯一的限制是:你不能在泛化划分的任何示例上训练你的系统,也不能将这些示例的输出表示包含在你用于上下文学习的任何提示中。
这里的想法是,我们希望保持泛化划分的纯粹性,以真正了解系统是否以我们关心的方式进行泛化。
在这个规则下,我想回顾几个原创系统的想法。记住,这并非详尽无遗,只是为了启发一些潜在的途径:
- 编写DSP程序。
- 对我们的模型进行进一步训练。
- 使用预训练模型。
- 从头开始训练。
- 甚至可以编写符号求解器。
- 可能还有其他你可以做的事情。
让我简要阐述其中几个选项:
- 进一步训练我们的模型应该非常容易。提供的代码片段可以加载
Zen训练的模型,然后你可以使用开发集示例对其进行额外的微调(这是允许的,因为我们的重点是泛化划分)。代码中暴露了许多不同的优化参数,以便你思考如何最好地设置模型,从这次进一步的训练中榨取更多性能。 - 我还在笔记本中提供了代码,展示如何轻松修改我们的起点以使用预训练模型(例如T5)。你可以微调T5,使其能够执行Recogs任务,并假设T5所经历的预训练对处理泛化划分特别有用。
- 类似的代码可以修改为从头开始训练,只需使用Hugging Face代码加载具有BERT等模型结构的随机参数即可。Hugging Face使这变得非常容易。你可以探索在Recogs任务上从头开始训练的不同变体。
我将其他选项留给你们思考。我真的很期待看到你们用Recogs数据做些什么。
竞赛说明
最后是竞赛部分,这很直接。有一个TSV文件包含一些测试用例(这些是泛化测试用例)。你只需要添加一个名为prediction的列,其中包含你预测的逻辑形式。然后,使用提供的最终代码片段将其写入磁盘,以便上传到GradeScope自动评分器。我们将看到你们在这个令人惊讶的、极具挑战性的语义解释任务上表现如何。

本节课总结: 我们一起学习了作业3和关联竞赛的核心内容,重点探讨了组合泛化的概念及其在Recogs基准测试中的体现。我们分析了数据特点,探索了预训练模型的预测局限性,并介绍了构建原创系统的多种可能途径。最终目标是测试模型是否能够系统性地理解和组合语言元素,实现真正的语义泛化。
25:NLU模型的行为评估(第一部分):概述 🧠


在本节课中,我们将开始学习关于自然语言理解模型的高级行为评估。我们将暂时将注意力从模型架构和设计上移开,转而关注评估的本质:我们如何收集证据,以及如何衡量该领域的进展。


上一节我们介绍了模型架构,本节中我们来看看如何评估这些模型的行为。
评估方法的多样性
在人工智能领域,我们进行多种类型的评估。本单元我们将专注于行为评估方法,即仅关注模型在给定输入下是否产生期望的输出,而不直接关注它们是如何实现这种映射的。
行为评估的类型
以下是几种主要的行为评估类型:
标准评估
标准评估通常被称为IID评估,即独立同分布评估。其核心思想是,我们有一些与系统训练数据不相交的测试样例,但我们有一个潜在的保证:测试样例与训练中看到的样例非常相似。这种标准模式为我们对测试时的预期提供了很多保证,但它对我们的系统也非常友好。
探索性分析
在探索性分析中,你可能会开始超越IID假设。你可能知道或不知道训练数据是什么样的,但核心思想是,你现在要开始通过构建的样本来探测模型是否具有某些能力,这些样本可能超出了你对训练数据的预期。这也可以是假设驱动的,例如,你可能会问:“我的模型知道同义词吗?”或者“它知道词汇蕴含吗?”,然后构建一个专门用于回答该特定问题的数据集。
挑战数据集
使用挑战数据集时,你可能会开始进入不那么“友好”的模式。在这种模式下,你可能会提出一些已知对模型来说会很困难的问题,因为这些问题超出了其训练经验的范围。你试图突破极限,看看它究竟会在哪里失败。这可能会变得真正具有对抗性,因为你可能已经对训练数据和模型属性进行了全面研究,然后构建了你明知模型会失败的例子,以此来揭示某种有问题的行为或重要弱点。
面向安全的行为评估
我们可以将对抗性升级到我称之为面向安全的行为评估的模式。在这种模式下,你可能会故意构建一些你预期会超出模型正常用户交互范围的例子,例如使用不熟悉的字符或字符组合,看看会发生什么。特别是,你可能会观察在这些非常不寻常的、分布外的输入下,模型是否会做出有毒、有问题或不安全的行为。
以上都是行为评估。我们可以将这些与我称之为结构评估的方法进行对比,后者包括探测、特征归因和干预。这些是下一个单元的主题。在结构评估中,我们试图超越输入输出映射,真正理解这些行为背后的工作机制。我认为其理想目标是揭示模型行为背后的因果机制。这些方法超越了行为测试,并与行为测试形成了强有力的互补。
对标准评估的反思
我认为,标准评估对我们的系统极其友好,但当我们考虑到系统在更广阔的世界中部署时,这种友好性应该越来越引起我们的担忧。
以下是标准评估的步骤:
- 你通过一个单一的过程创建一个数据集。这是需要强调的部分:单一过程。你可以抓取网站、重新格式化数据库、为一些例子众包标签等等。无论你做什么,你只运行这一个过程。
- 然后,在下一阶段,你将数据集划分为不相交的训练集和测试集,并将测试集搁置一旁。它被严格保管,直到最后才会查看。这很好,因为这将是我们估计系统泛化能力的依据。
- 但请注意,你已经对你的系统非常友好了,因为步骤1在某种意义上保证了这些测试样例将与你在训练中看到的非常相似。
- 你在训练集上开发你的系统。
- 只有在所有开发完成后,你才根据测试集上的某种准确率标准来评估系统。
- 然后,关键的一步是:你报告结果,将其作为系统泛化能力的估计。此时,你正在与更广阔的世界交流,说你有一个衡量系统准确率的指标。人们会推断,这意味着如果他们在自由使用中使用该模型,他们将体验到这种准确率。
这正是让我担忧的部分。步骤1是创建数据的单一过程,我们将其报告为系统泛化能力的估计,尽管我们非常清楚世界并不是一个单一的同质过程。我们绝对知道,一旦模型部署,它将遇到与步骤1创建的例子非常不同的例子。这就是令人担忧的部分,也是所谓的对抗性评估的用武之地。它们不一定是完全对抗性的,但其理念是揭示标准评估模式的某些脆弱性。
对抗性评估
在对抗性评估中,步骤有所不同:
- 像往常一样,通过你喜欢的任何方式创建一个数据集。
- 根据你选择的任何协议,使用该数据集开发和评估系统。
- 新的部分:开发一个新的测试数据集,其中包含你怀疑或知道对你的系统和原始数据集具有挑战性的例子。
- 只有在所有系统开发完成后,你才根据这个新测试集上的准确率来评估系统。
- 然后,像以前一样,你报告结果,将其作为系统泛化能力的某种估计。
这就是新的部分。我们有一个用于创建系统(特别是用于训练)的数据集。但在步骤3中,我们有一个新的测试数据集,它现在发挥着至关重要的作用,为我们提供了系统泛化能力的估计。只要我们以这种方式创建了一些困难且多样化的新测试集,我们或许就能越来越有信心地认为,我们正在模拟模型部署后将面临的情况。
这是一种行动号召,要真正有效地做到这一点,真正让你能够支持这里的步骤5,你应该以覆盖尽可能广泛的用户行为、用户目标、用户输入频谱的方式来构建这些对抗性或挑战性数据集,正如你所预期会看到的那样。这意味着需要让多样化的团队对模型进行实战测试,创建困难的例子,并研究由此产生的行为。通过这种协同努力,你可以逐步接近对模型部署时的行为有一个真正的保证。
行为测试的一个特点是,你永远不会有完全的保证,但你可以接近它。然后,如下一个单元所示,你可以用对模型工作原理的更深入理解来补充它。但无论如何,我认为,在这个影响范围不断扩大的现代时代,当我们思考人工智能系统时,我们应该处于这种模式。
对抗性评估的历史
这段历史很有趣。对抗性测试感觉像是一个新想法,但实际上,它至少可以一直追溯到图灵测试。你可能还记得,图灵测试背后的基本见解是,当我们将人与计算机对抗时,我们会得到一个可靠的评估,其中计算机的目标是试图欺骗人,使其认为它本身是一个人,而人则尽其所能去弄清楚那个实体是人还是某种人工智能。这是一种固有的对抗性动态,以语言互动为中心。因此,我认为我们必须称之为第一个,或者肯定是最有影响力的对抗性测试。
一段时间后,Terry Winograd提出开发涉及非常复杂问题的数据集,他希望这些问题能超越简单的统计技巧,真正探测模型是否真正理解世界是什么样子。
Hector Levesque在他那篇精彩的论文《Our Best Behavior》中,复兴了Winograd关于对抗性测试模型以查看它们是否真正理解语言和世界的想法。
Winograd句子现在反思起来真的很有趣。它们是一些可以相当揭示物理现实和社会现实等的简单问题。以下是一个典型的Winograd案例:
- “奖杯放不进棕色手提箱,因为它太小了。”什么太小了?人类的直觉是说手提箱。这可能是因为你可以对这两个物体进行某种心理模拟,然后得出问题的答案。
- 其最小对比对是:“奖杯放不进棕色手提箱,因为它太大了。”什么太大了?这里,人类的答案是奖杯,同样是因为你可以进行那种心理模拟。
其理念是,这是一种行为测试,将帮助我们理解模型是否也对我们的物理现实有那种深刻的理解。
这里有一个更侧重于社会规范和人们所扮演角色的案例:
- “委员会拒绝了示威者的许可,因为他们害怕暴力。”谁害怕暴力?人类的答案是委员会,基于对示威者和政治家的刻板印象角色。
- 与之相对的是:“委员会拒绝了示威者的许可,因为他们主张暴力。”谁主张暴力?我们默认说是示威者,因为我们对人们将扮演的角色有默认假设。
其理念是,对于一个模型来说,要正确回答这些问题,它也需要深刻理解这些实体以及所涉及的社会规范发生了什么。这就是指导性假设。再次强调,行为测试永远不能给我们完全的保证,证明我们已经完全探测到了我们所关心的潜在能力,但像这样的例子在让我们更接近那个理想方面具有启发性。
Hector Levesque以一种我认为对该领域真正具有启发性的方式进一步发展了这一点。例如,他说:“鳄鱼能跑障碍赛吗?”这里的意图很明确。这个问题可以通过思考来回答:鳄鱼腿短,障碍赛中的栅栏对鳄鱼来说太高了,跳不过去。所以不,鳄鱼不能跑障碍赛。这再次唤起了对一个非常不熟悉的情况进行心理模拟并得出系统答案的想法。
Levesque真正追求的是他所谓的“挫败廉价技巧”:我们能否找到一些问题,使得像这样的廉价技巧不足以产生期望的行为?

不幸的是,这没有简单的答案。也许我们能做的最好的事情,就是精心设计一套多项选择题,然后研究可能能够回答这些问题的计算机程序类型。再次强调,我在这篇2013年的早期论文中听到的,是对构建对抗性数据集的呼吁,这些数据集将更多地揭示我们的模型所找到的解决方案。

本节课中我们一起学习了自然语言理解模型行为评估的概述,包括标准评估的局限性、对抗性评估的理念及其历史渊源。我们了解到,为了更可靠地评估模型在真实世界中的表现,我们需要超越单一、同质的测试集,主动构建具有挑战性和多样性的评估方案。下一节我们将深入探讨具体的行为评估方法和实践。
26:NLU模型的行为评估与分析考量(第二部分)🔍



在本节课中,我们将继续探讨自然语言理解模型的行为评估方法,并深入分析其背后的考量。我们将重点讨论行为测试能揭示什么、不能揭示什么,以及如何区分模型缺陷与数据集缺陷。
行为测试的目标与模式 🎯
上一节我们介绍了行为测试的基本概念,本节中我们来看看其具体的目标与模式。行为测试并非总是对抗性的,它也可以用于探索系统能力。
以下是几种可能的研究问题示例,它们从纯粹的探索性逐渐过渡到对抗性:
- 探索性问题:我的系统是否学习了关于数字术语的知识?我的系统是否理解否定是如何工作的?我的系统能否处理新的文体或体裁?
- 对抗性问题:当应用于虚构的、非常陌生的输入体裁时,系统是否会产生有社会问题的(例如刻板印象的)输出?是否存在某些随机输入会导致系统产生有问题的输出?
所有这些都属于有趣的行为测试范畴。
行为测试的局限性 ⚠️
然而,行为测试有其固有的局限性。任何数量的行为测试都无法真正保证系统在所有情况下的表现。测试结果完全取决于你决定构建的示例集。
为了说明这一点,请考虑一个判断数字奇偶性的模型。通过有限的测试(如输入4、21、32、36、63),模型可能表现完美。但如果我们“窥视”模型内部,可能会发现它只是一个简单的查找表,仅能处理测试过的几个数字。对于未在列表中的输入(如22),它会默认预测为“奇数”,从而出错。这个弱点并非通过行为测试发现,而是通过检查模型内部机制发现的。
即使模型变得更复杂(例如,通过检查输入字符串的最后一个词来进行分类),我们仍然可能通过检查内部机制(而非行为测试)发现其缺陷(例如,输入“16”时出错)。这说明了行为测试的局限性:我们始终会担心测试中遗漏了某些能暴露系统重大问题的关键案例。
另一个需要记住的附带限制是,在讨论行为测试时,我们通常搁置了评估指标的问题。文献中的挑战和对抗性测试大多采用基础任务中熟悉的指标。虽然这可以接受,但在完整的对抗性测试中,我们应该勇于突破这些任务的限制,以新的方式评估模型,从而暴露新的局限性。
关键分析点:失败归因 🤔
进行行为测试时,一个关键的分析点是:当我们看到失败时,这是模型的失败,还是底层数据集的失败?
刘等人2019年的一篇题为《通过微调进行“接种”》的论文为此提供了一个思考框架。其核心思想体现在以下引述中:“当系统在挑战数据集上失败时,我们应得出什么结论?在某些情况下,挑战可能利用了原始数据集设计中的盲点(称为数据集弱点)。在其他情况下,挑战可能暴露了特定模型族处理某些自然语言现象的固有不足(称为模型弱点)。当然,这两者并非互斥。”
人们往往倾向于声称发现了模型弱点,因为这更具影响力。但更可能的情况是,你发现的是数据集弱点——可用的训练数据存在某些问题,导致模型未能达到学习目标。这是一个不那么有趣的结果,因为它通常意味着我们只需要补充更多数据。我们需要谨慎,避免将数据集弱点误认为模型弱点。
我们在关于设计公平但具有挑战性的评估任务的论文中也提出了类似观点:“然而,对于任何评估方法,我们都应该问它是否公平。公平在此意义上指:模型是否看到了足以支持我们所要求的那种泛化能力的数据?除非我们能完全肯定地回答‘是’,否则我们无法确定失败的评估是源于模型限制,还是任何模型都无法克服的数据限制。”
当我们说对模型“公平”时,并非担心它们受到虐待,而是担心犯下分析错误:将失败归咎于模型,而实际上失败在于我们,因为我们给出的规范没有完全消除我们心中学习目标的歧义。这很容易发生,并可能导致对问题的误诊。
“接种”微调框架 💉
之前提到的刘等人2019年的论文提出了一个很好的框架,用于思考如何克服这一分析障碍,区分数据集弱点和模型弱点。这个框架被称为“通过微调进行接种”。
该方法的流程如下:
- 在原始数据上训练系统。
- 在原始测试集和我们感兴趣的挑战集上测试它。假设系统在原始测试上表现良好,但在挑战集上表现很差。
- 为了找出原因,我们在少量挑战示例上进行微调以更新模型。
- 然后在原始数据集和挑战数据集上重新测试。
可能出现三种一般性结果:
- 数据集弱点:微调后,模型在原始数据和挑战数据上都表现良好(尤其是挑战集性能大幅提升)。这表明模型的可用训练经验存在一些空白,通过微调可以快速克服。
- 模型弱点:即使微调后,模型在挑战数据集上仍然表现不佳,同时保持了原始数据上的性能。这可能意味着挑战集中的新示例对于该模型来说存在根本性的困难。
- 标注伪影:微调后,模型在原始测试集上的性能急剧下降。这可能表明我们的挑战数据集对模型做了某些不寻常且有问题的操作,需要我们重新反思所提出挑战的性质。
该论文提供了一个图表,展示了他们在详细研究的对抗性测试中观察到的这三种结果模式。
案例分析:否定与单调性推理 📚
我想分享的另一个故事来自我们课题组的工作,涉及将否定作为学习目标。这同样是为了帮助大家避免在行为测试中可能犯的严重分析错误。
我们有一个关于否定的直观学习目标:如果A蕴含B,那么非B蕴含非A。这是否定的经典蕴含反转特性。文献中的许多论文观察到,我们顶级的自然语言推理模型未能达到这一学习目标。一个诱人的结论是:我们的顶级模型无法学习否定。
但我们必须结合另一个观察:在驱动这些模型的NLI基准测试中,否定严重 underrepresented。因此,这应该让我们怀疑,我们发现的可能不是模型弱点,而是数据集弱点。
为了探究这个问题,我们遵循“接种微调”模板,构建了一个略微合成的数据集,称为MoNLI。它包含两部分:
- Positive MoNLI:我们从SNLI基准中获取真实假设(如“食物被供应了”),使用WordNet查找特例(如“披萨”),创建蕴含案例(“披萨被供应了”),从而生成新的测试对。
- Negative MoNLI:我们从否定示例开始(如“孩子们没有拿着植物”),使用WordNet查找蕴含关系(“花”蕴含“植物”),创建新示例(“孩子们没有拿着花”)。由于否定的蕴含反转特性,标签模式与正例相反。
我们尽力将此任务设置为困难的泛化任务(例如,在测试中保留整个词),以确保我们考察系统是否真正掌握了词汇关系理论和否定理论。
使用MoNLI作为挑战数据集的初步结果令人担忧。例如,一个在SNLI上训练的BERT模型,在SNLI上表现很好,在MoNLI的正例部分也表现极佳,但在MoNLI的负例部分准确率几乎为零。策略似乎很明显:模型直接忽略了否定。
你可能会想:啊哈,我们发现了BERT的根本局限!但我认为这是不正确的。如果我们对负例MoNLI案例进行一点“接种”微调,该部分的性能立即上升。同时,模型保持了在SNLI上的性能,并在MoNLI负例部分获得了优秀的性能。这强烈表明,我们发现的不是模型弱点,而是数据集弱点。
总结与延伸思考 🧠
本节课中,我们一起学习了NLU模型行为评估的第二部分,重点探讨了分析考量。
我强调了对我们系统的公平性,这很重要,可以避免我们混淆视听。但我忍不住要指出,生物体是惊人的。我们现在知道,它们经常能解决在我刚才描述的意义上“不公平”的任务。
一个经典案例是“关系匹配样本”任务。即使是非常年幼的人类和一些动物(包括乌鸦和非人类灵长类动物)也能解决此类任务。例如,向你展示两个红色方块,然后让你从两个选项中选择,人们会选择“两个相同的”来匹配原始提示。人们不需要训练实例就能自然地做到这一点。而如果展示两个不同的形状,人们会选择“两个不同的”。这是我们几乎无需训练数据就能持续进行的“相同-不同”推理。
按此方式提出,我认为这些任务是不公平的。然而,人类和许多生物实体却能系统地解决这些任务。这是关于人类及其他生物认知的一个谜题,我们应该牢记:人类能解决不公平的任务。问题是,如果我们确实希望机器学习模型做到这一点,我们该如何让它们解决此类任务?这些还只是较简单的案例,例如,我们还可以进行层次化的相等性推理。经过一些训练,甚至乌鸦也能解决此类问题,而人类基本上无需训练实例或没有足够的训练实例来完全消除任务歧义就能解决。
因此,在向我们的系统提出公平任务的同时,我们应该记住,存在一些场景,我们可能期望一种不被数据支持的解决方案,但尽管如此,我们所有人似乎都能毫不费力地得出这个解决方案。


本节课中,我们一起学习了行为测试的局限性、失败归因的重要性、“接种”微调的分析框架,并通过否定推理的案例加深了理解。最后,我们对比了机器评估的“公平性”要求与人类解决“不公平”任务的能力,为思考模型评估与人类认知的差异提供了启发。
27:组合性 🧩

在本节课中,我们将学习自然语言理解中一个核心原则——组合性。我们将探讨其定义、重要性,以及如何通过系统性概念来评估模型的行为表现。


组合性原则
上一节我们介绍了高级行为测试,本节中我们来看看组合性原则。这是语言学语义学中的一个重要原则,也是理解组合泛化基准(如COGS和ReCOGS)目标的前提。
组合性原则的非正式表述是:一个短语的意义是其直接句法成分的意义以及它们组合方式的函数。
让我们通过一个例子来解析这个原则。考虑一个简单的句法结构:句子“Every student admired the idea”。组合性原则指出,这个句子(S节点)的意义完全由其两个组成部分——名词短语(NP)和动词短语(VP)——的意义决定。这暗示了一个递归过程。
名词短语(NP)的意义又完全由其组成部分——限定词(Det)“every”和名词(N)“student”——的意义决定。而这些成分的意义又由其各自的词汇项决定。这就是递归过程的起点。
直觉是:你只需要学习一门语言的所有词汇项,并弄清楚它们如何相互组合,你就获得了一个递归过程,允许你以新的方式组合这些元素并理解新颖的组合。组合性保证了这一点,因为整体的意义是部分意义及其组合方式的函数。
我们也可以自底向上地思考这个过程。我们从词汇项开始,它们的意义是规定或学习记忆的。然后,这些意义依次决定了其父节点(如NP、VP)的意义,进而决定了更复杂节点(如S)的意义,直到我们自底向上推导出整个句子的意义。
为何重视组合性?
为什么语言学家倾向于坚持组合性原则?其动机通常如下:
首先,作为研究语言的语义学家,我们希望为语言的所有有意义单元建模。这意味着我们需要为每一个词汇项(即使看起来最偶然的)赋予独立的意义,就像优秀的词典编纂者所做的那样。
在实践中,这意味着语言学语义学中存在大量抽象。因为很难(或许不可能)为像“every”这样的词脱离其组合对象而赋予独立意义。因此,实践中赋予的意义通常是函数。例如,“every”是一个函数意义,当与“student”的意义结合时,会产生另一个函数,再与动词短语的意义结合,最终得到句子(S节点)的意义。这类似于全称量化。
其次,我们常听到语言学家谈论人类处理语言的“无限能力”。虽然从抽象角度看,我们理解的句子在复杂性或长度上似乎没有原则性限制,但这需要严格限定。实际上,作为有限的存在,我们制造和理解语言的能力也是有限的。这个说法有些夸大,但其核心直觉更接近于“创造性”。
我们拥有令人印象深刻的语言创造力。大体上,你今天产生和理解的句子,在整个人类历史中可能从未出现过。大多数句子都是如此。然而,我们却能即时、毫不费力地产生这些句子并理解其含义。这确实意味着我们拥有利用有限资源(如词汇项)并以新方式组合它们从而进行语言创造的能力,而组合性可以被视为对此的一种解释。
组合性与系统性
还有一个来自认知科学的相关概念叫做“系统性”。它可能是一个比组合性更普遍、更准确的描述。
系统性的思想可追溯至Fodor和Pylyshyn。他们说,当我们说语言能力是系统性的时,是指产生或理解某些句子的能力,与产生或理解其他某些句子的能力有着内在联系。
例如,如果你理解句子“Sandy loves the puppy”,那么仅凭这一事实,你也理解“The puppy loves Sandy”。如果你认识到“turtle”和“puppy”之间存在某种分布上的亲和性,你也能立即理解“The turtle loves the puppy”、“The puppy loves the turtle”、“The turtle loves Sandy”等等。你的知识数量会瞬间爆炸式增长,这在某种意义上是你对语言的理解具有系统性的结果。
我认为组合性可能是解释人类语言能力系统性的一种特定方式,但系统性 arguably 更为普遍。它在这里被赋予了一种分布式的描述,可能允许非严格组合但仍具系统性的情况。系统性是思考我们进行的许多行为测试(尤其是假设驱动的挑战测试)背后直觉的一个有力概念。
系统性直觉示例
以下是一个简短的例子来说明基于系统性的担忧。这来自一个我开发的、我认为相当不错的真实情感分类模型。我开始向它提出一些小挑战。
最初,我对这些例子感到鼓舞:
- “The bakery sells a mean apple pie.”(这家面包店卖的苹果派很棒。)—— 这是一个积极的评价,涉及“mean”这个词非常特殊的含义(意为“出色的”)。我很高兴模型的预测标签与黄金标签一致。
- “They sell a mean apple pie.”(他们卖的苹果派很棒。)—— 同样,预测正确。
我开始认为我的模型真正理解了形容词“mean”的这个非常专业的含义。
但这种想法在接下来的两个例子中破灭了:
- “She sells a mean apple pie.”(她卖的苹果派很棒。)—— 模型预测为消极。
- “He sells a mean apple pie.”(他卖的苹果派很棒。)—— 模型预测为消极。
而黄金标签当然仍然是积极的。
这些错误令人担忧,但我更担心的是缺乏系统性。作为人类,我绝不期望将主语从复数代词改为单数代词,或者使用代词而非完整名词短语(如“the bakery”),会影响到对其中形容词“mean”的解释。然而,模型的预测却改变了,这对我来说表现为一种系统性的缺失。
这种直觉指导了许多对抗性或挑战性数据集的构建。人们基于语言的系统性提出假设,并在模型中观察到偏离该假设的情况,从而开始担忧这些模型。
AI模型历史中的组合性
回顾AI模型的历史,思考组合性原则很有趣。
在AI的早期时代,如我们在第一天看到的SHRDLU或CHAT-80系统,我们通过设计获得了某种组合性,因为它们是本身遵循组合性原则的符号语法实现。因此我们并不怀疑这些NLU模型是否具有组合性,因为我们预设它们会有。
这种思想的一部分实际上延续到了更现代的机器学习时代。例如,许多语义解析系统(如Percy Liang工作中描述的系统)在底层也有组合语法,其任务是学习该语法规则的权重。因此,可以说其产物是具有组合性的,并带有一些随机性(因为它们是概率模型)。
即使在更现代的深度学习时代,我们也看到了 arguably 具有组合性的系统。例如,启动斯坦福情感树库的论文中描述的是一个递归树结构神经网络。从所有节点表示向量,并通过复杂的深度学习函数组合这些向量以推导其父节点意义的角度看,它遵循了组合性原则。这个过程递归进行,直到获得整个句子的意义。
因此,它不像旧系统或语言学语义学中的许多工作那样是符号化的,但它 arguably 是一个组合系统。事实上,这是这些深度学习产物一个有趣的性质。
当前挑战与开放问题
但现在,我们似乎已经远离了那种视角。我们时刻面对着这些庞大的、通常基于Transformer的模型,其中一切都相互连接。显然,我们无法保证这些网络内置了组合性或系统性。
事实上,在早期,人们常常担心,尽管这些模型表现良好,但它们可能在学习非系统性的解决方案,这激发了对它们的大量挑战测试。
现在的问题是:我们能否提出行为测试,来真正评估这些难以进行解析分析的模型,是否为我们提出的语言问题找到了系统性的解决方案?

如果答案是否定的,我们应该担忧。如果答案是肯定的,那将是一个惊人的发现,既解释了这些模型为何表现如此出色,也揭示了仅靠数据驱动学习就能为语言问题提供系统性解决方案的强大能力。因此,这是一个开放性问题,但随着我们的模型即使在面对我们提出的困难行为任务时也表现得越来越好,探索这些问题变得异常令人兴奋。
总结

本节课中,我们一起学习了自然语言理解中的组合性原则。我们了解了其定义、作为解释人类语言创造性和系统性基础的重要性,并通过实例看到了模型缺乏系统性可能带来的问题。我们还回顾了组合性原则在AI模型历史中的体现,并提出了当前大模型时代评估其系统性的重要性与挑战。理解并测试组合性与系统性,对于构建真正可靠、可理解的NLU模型至关重要。
28:NLU模型的行为评估(四):COGS与ReCOGS 📚



在本节课中,我们将学习两个专门用于测试模型组合泛化能力的基准:COGS和ReCOGS。我们将探讨它们的设计动机、逻辑形式的特点、评估分割的结构,以及ReCOGS如何改进COGS以更纯粹地测试语义现象。
概述
上一节我们讨论了组合性原则。本节我们将聚焦于课程作业相关的两个基准:COGS和ReCOGS。它们旨在测试模型是否能像人类一样,系统性地理解熟悉元素的新颖组合。
COGS设定了议程,而ReCOGS是我们的扩展。我们希望通过ReCOGS,首先理解为何COGS中的某些泛化分割对当今模型极具挑战性;其次,重新构建COGS,使其更接近测试纯粹的语义现象,并抽象掉COGS中某些逻辑形式的偶然性特征。
COGS任务描述
COGS的输入是简单的英语句子,例如:
a rose was helped by a dog.
输出是逻辑形式,即句子含义的描述。对于COGS和ReCOGS,这些描述采用一种事件语义风格。
示例逻辑形式:
rose(x1) & indefinite(x1) & help_theme(e3, x1) & agent(e3, x6) & dog(x6) & indefinite(x6)
rose(x1)和indefinite(x1)对应句子的语法主语“a rose”。help_theme(e3, x1)描述了帮助事件的主题论元,e3是该事件的变量。agent(e3, x6)描述了该事件的施事者论元。dog(x6) & indefinite(x6)将x6识别为“a dog”。
另一个涉及定指描述的例句:
The sailor dusted a boy.
其逻辑形式包含 * 操作符来表示定指描述。
ReCOGS任务描述
ReCOGS在许多方面与COGS相似,但逻辑形式更简洁。
相同例句在ReCOGS中的逻辑形式:
rose(x1) & indefinite(x1) & help(e7) & theme(e7, x1) & agent(e7, x6) & dog(x6) & indefinite(x6)
主要改进包括:
- 移除了许多与变量相关的冗余符号。
- 重组了合取结构。
- 事件描述更透明(例如,将“帮助事件”本身作为一个独立的谓词
help(e7))。
设计动机与核心问题
COGS和ReCOGS的动机紧密关联组合性原则。我们观察到,人类能轻松、系统地解释熟悉元素的新颖组合。对我们说英语的人来说,这种泛化如此不费吹灰之力,以至于COGS的泛化分割有时都难以被视为组合泛化任务。
核心问题:
- 我们最好的模型能否进行组合泛化?
- 它们是否也找到了组合性的解决方案?(一个关于其内部因果机制的更深层问题)
COGS和ReCOGS的愿景是,通过行为任务帮助我们解决关于泛化的问题。如果模型能在这些任务上成功,我们就有理由相信它们找到了组合性解决方案,因为这是对其成功的最佳解释。
深入理解COGS逻辑形式
COGS的逻辑形式有一些有趣特征,有助于解释文献中观察到的结果模式。
动词与事件:
动词指定了具有自身核心概念结构的原始事件,可涉及一个或多个强制性或可选性角色。
- 例句:
Emma broke a vase.- 核心是一个打破事件
break(e2),有两个参与者:施事者Emma和主题a vase。
- 核心是一个打破事件
- 相关句:
The vase broke.- 缺少施事者论元,主题论元被提升为英语句子的语法主语。
变量编号规则:
在COGS中,变量编号由其在输入句子中的线性位置决定。例如,动词break在输入句中是第2个位置,因此它锚定的事件变量是e2。事实证明,这一特征严重影响了现代模型(尤其是带有位置编码的模型)的性能。
变量绑定:
COGS和ReCOGS逻辑形式中的所有变量都是被绑定的。看似自由的变量(如x1, x2)实际上都被最广辖域的存在量词前缀所约束。定指描述则由*操作符进行局部绑定。
COGS评估分割结构
COGS的数据分割结构如下:
- 训练集: 规模较大。
- 开发集和测试集: 均为IID(独立同分布)数据,用于标准评估。
- 泛化示例集: 包含21,000个示例,对应21种不同的分割,每种都旨在探究模型对不同组合泛化现象的能力。
以下是泛化分割的主要类别:
熟悉短语置于新位置:
例如,“主语到宾语”分割意味着在训练中,我们看到像“hedgehog ate the cake”这样的句子,其中“hedgehog”是主语;而在泛化分割中,我们首次遇到“hedgehog”出现在非主语的位置。
原始语法角色:
在训练中,像“shark”这样的原始元素作为孤立元素出现;在泛化中,我们在完整的句子语境中遇到它们,模型需要弄清楚如何处理。
修饰短语的新组合:
例如,“宾语修饰到主语修饰”意味着像“on the plate”这样的修饰语在训练示例中出现在宾语位置,而在泛化分割中出现在主语位置。这被证明非常困难。
更深层的递归:
对于句子补语和介词短语补语,在训练中我们看到一定递归深度,在泛化中我们看到更深的递归。
其他类别:
包括句法角色交替(主动到被动)、论元结构转换以及涉及动词类别的分割。
现有模型的性能与谜题
为了解现状,我们在ReCOGS论文中汇总了文献中多个重要论文处理COGS问题的结果,形成了一个“合成排行榜”。
观察结果:
- 整体性能: 如果只看“整体”列,一些模型在泛化分割上的准确率达到了80%以上,看起来表现不错。
- 词汇泛化: 在涉及词汇泛化的分割上,模型取得了令人印象深刻的高分。
- 结构泛化: 然而,在三个被我们称为“结构泛化任务”的列中(Obj PP to Subj PP, CP Recursion, PP Recursion),模型的表现几乎是全零或接近零。
这强烈表明模型完全无法在这些结构泛化任务上取得任何进展,背后存在系统性问题。这正是我们开始ReCOGS研究时想要解开的谜团:这些零分或接近零分的背后原因是什么?
ReCOGS的改进措施
基于对COGS局限性的分析,我们实施了多项改进以创建ReCOGS。
1. 移除冗余标记
COGS逻辑形式中存在大量冗余标记。例如,每个变量都以“X _ [数字]”的形式出现,其中“X _ ”是冗余的。我们移除了这些冗余部分,只保留数字作为变量标识。这个看似保留语义的简单更改,极大地改善了模型性能,因为它平衡了数据中的n-gram频率分布,使语言模型所处的数据环境更健康。
2. 解耦长度与递归深度
我们发现,在CP和PP递归分割中,泛化示例的长度分布与训练示例有显著不同,泛化示例要长得多。这使得“递归”问题与“长度泛化”问题纠缠在一起。为了将它们分开,我们通过拼接现有训练示例并重新索引变量名的方式,创建了更长的训练示例。这确保了模型在训练时就能接触到与测试时相似的长度范围和变量名。实验表明,这一方法显著提升了LSTM和Transformer模型在递归分割上的性能,说明原先的难点主要在于长度泛化,而非递归本身。
3. 扩展PP修饰语的分布
对于PP修饰语分割(那一列零分),我们的假设是:COGS的训练数据教会了模型“PP只与特定的变量和位置关联”。当模型学会这一“错误”教训后,就无法处理在泛化时出现的、违反此规律的例子。为了打破这种虚假关联,我们进行了多种语义保留的数据增强:
- 宾语名词短语前置: 例如,将“Emma was lent the box in the tent.”变为“The box in the tent, Emma was lent.”。
- 插入感叹词: 在句子中随机插入“um”等填充停顿词,这会改变变量名和位置。
- 使用分词结构: 例如,将介词修饰语改为分词结构“a leaf painting the spaceship”。
这些操作扩展了PP在训练数据中关联的变量名和位置范围,从而大幅提升了模型在PP修饰语分割上的性能。
4. 引入任意变量命名
在COGS中,变量名与输入字符串中的位置绑定。在ReCOGS中,我们切断了这种联系,以语义一致但任意的方式分配变量名。这迫使模型学习抽象于具体变量名的语义结构。
ReCOGS逻辑形式示例:
对于输入句“Mia ate a cake”,经过上述改进后,ReCOGS的逻辑形式更加简洁,变量命名与输入位置无关。
改进效果与总结
这些改进的综合效果是显著的:
- 对于COGS,结构泛化任务的表现非常差。
- 冗余标记移除主要帮助了词汇泛化,但对顽固的结构分割影响不大。
- 语义保留的数据增强和任意变量重命名则戏剧性地改善了结构泛化分割的性能,使得模型在COGS/ReCOGS问题的各个方面的表现更加均衡。
实验结果表明,ReCOGS并非一个更简单的任务,它的某些方面实际上比COGS更难。但关键是我们证明了,在那些曾导致全零结果的、极其顽固的结构泛化分割上取得进展是可能的。因此,我们认为ReCOGS是一个更健康的、可供模型攀登的基准,它让我们更接近测试我们所关心的纯粹语义现象。
遗留的开放性思考
在深入研究COGS和ReCOGS之后,一些概念性问题依然萦绕:
- 如何通过逻辑形式测试真实含义? 逻辑形式本身也是句法表达式,总带有一定的任意性。这始终会阻碍我们纯粹地判断模型是否真正理解了句子的含义。
- 什么是公平的泛化测试? 我们关于组合性的许多见解,开始触及“不公平”的边界。例如,我们有意在训练中隐藏某些模式(如PP只出现在宾语位置),却期望模型在测试时能处理它们(如PP出现在主语位置)。困难在于,对于某些现象,我们希望模型不要学会训练数据中的限制;而对于另一些现象,我们又希望它们学会。从概念上区分这两类现象极其困难。
- 人类组合性的界限在哪里? 这或许是最终的基准。我们假设自然语言是组合性的,但这假设很强,必然有其局限性。也许我们应该先弄清楚人类如何泛化、在何处无法泛化,然后期望我们的模型能遵循。但这引发更多问题:如果我们有数据集无法支持、但对模型而言是良好的目标,该如何在任务和模型中表达?
总结


本节课我们一起深入探讨了用于评估NLU模型组合泛化能力的两个重要基准:COGS和ReCOGS。我们了解了COGS的任务设计、逻辑形式特点及其具有挑战性的泛化分割。通过分析模型在COGS上的失败模式,我们揭示了其背后可能的原因,如冗余标记、长度泛化与递归的耦合、以及训练数据带来的虚假分布限制。在此基础上,ReCOGS通过移除冗余、解耦长度与深度、进行语义保留的数据增强以及引入任意变量命名等改进,旨在更纯粹、更公平地测试模型的语义组合能力。尽管仍有许多开放性问题,但这些基准为我们推动模型实现真正的人类式组合泛化提供了重要的工具和思考方向。
29:NLU模型的行为评估,第五部分:对抗性测试 🛡️


在本节课中,我们将学习对抗性测试,这是一种评估自然语言理解模型鲁棒性的重要方法。我们将回顾几个著名的对抗性测试案例,分析它们揭示的模型弱点,并探讨这些挑战如何推动了模型的进步。

上一节我们讨论了行为测试的优势与局限。本节中,我们将通过几个近期著名的对抗性测试案例,来学习它们带给我们的启示。特别是从历史视角来看,我们对于这些挑战的本质有了许多新的认识。
SQuAD 对抗性测试 📚
让我们从SQuAD开始。这张幻灯片展示了近期SQuAD排行榜的截图。SQuAD排行榜对人类很友好,因为它将人类表现置于排行榜顶端。可以看到,人类在SQuAD上的精确匹配率约为87%。
但请注意,根据这个指标,你需要一直翻到排行榜第31位才能找到一个表现不如人类的系统。许多系统的表现都远超人类。这很容易让人得出“计算机在回答问题方面已超越人类”的结论,其依据就是SQuAD。Jia和Liang在2017年进行的首次重要对抗性测试,正是受到了这类标题的启发。这标志着NLU现代对抗性测试时代的一个重要开端。
首先,回顾一下SQuAD任务:给定上下文证据段落,提出一个问题,任务是在段落中找到一个子字符串作为答案。
Jia和Liang的直觉是,模型可能过度拟合了SQuAD中的特定数据。他们设置了一些对抗样本来诊断这个问题。他们的对抗方法是在这些段落的末尾附加误导性句子。
例如,附加句子“Qua Leland Stanford had Jersey number 37 in Champo 34”。Jia和Liang发现,有了这些附加句子,模型会转而开始回答“Leland Stanford”。它们被这个新的、错误的证据分散了注意力。
这令人担忧。你可能会想,我们肯定能克服这个对抗样本。我们应该做的是用这些附加了句子的增强训练集重新训练模型,模型就一定能克服这个对抗样本。事实上,模型确实克服了这个特定的对抗样本,不再被附加句子误导。
但Jia和Liang想得更远。如果我们将误导性句子前置到证据段落开头呢?他们再次发现模型被分散注意力,开始使用第一个新句子来回答“Leland Stanford”。
你可能会想,我们现在可以在同时包含前置和附加句子的增强训练集上训练,也许就能克服对抗样本了。但你可以看到我们陷入了一种动态博弈。现在我们可以把误导性句子放在段落中间。模型很可能再次表现不佳。
模型确实再次失败了。这里展示了一个排行榜,对比了当时SQuAD的顶级系统在原始数据集和Jia-Liang对抗集上的表现。显然,系统在这个对抗集上的整体性能大幅下降,这本身就足够令人担忧。
但我们应该看得更仔细。值得注意的是,原始排名在这个对抗性排行榜上几乎完全被打乱。原来的第一名系统跌到了第5位,第二名跌到了第10位,第三名跌到了第12位。原来的第7名现在在对抗集上排第一。关键是,原始表现和对抗表现之间几乎没有关联。
这张图证实了这一点:X轴是原始系统性能,Y轴是对抗性能。这些点呈云状分布,显示两者之间没有明显的相关性。这可能表明系统过度拟合了原始的SQuAD问题,并且以相当混乱的方式处理这个对抗集。这本身就令人担忧。
需要说明的是,我不确定这个特定对抗集在当前模型上的状态。我很想为你提供关于更现代的Transformer系统在这些对抗集上表现如何的证据。但据我所知,还没有人进行过系统性的测试。我认为拥有这些数据点会很有价值。
自然语言推理的对抗性测试 🤔
让我们看第二个例子:自然语言推理。幻灯片上展示了SNLI(该任务的主要基准之一)随时间的性能变化图。X轴是时间,Y轴是F1分数,红线标记了我们对人类性能的估计,蓝线追踪了已发表文献中的不同系统。需要强调的是,这些基本上都是已发表的论文。
你可以看到随着时间的推移,性能快速提升,最终超过了我们对人类性能的估计,并且这条线几乎是单调递增的。这强烈地向我表明,已发表的论文正在从前人的论文中学习如何在SNLI任务上表现出色的隐性经验。
但重点是,我们现在确实有了超越人类水平的系统。MultiNLI排行榜则有些不同。它托管在Kaggle上,任何人都可以参加。因此,有更多的系统在这个排行榜上竞争,并且那种社区范围内在任务上的“爬山”现象要少得多,因为互不沟通的人们只是提交系统看看结果。所以蓝线上下振荡,但这仍然是一个朝着人类性能估计值进步的故事。
如果你只看这些数字的表面价值,你可能会得出结论:我们正在开发真正擅长进行自然语言推理(实际上是常识推理)的系统。
然而,对抗性测试背后的直觉再次让我们对此感到担忧。NLI领域最早且最具影响力的对抗性测试之一是Glockner等人2018年的工作,即“Breaking NLI”论文。他们的方法在概念上非常简单,并且很好地利用了关于系统性和组合性的直觉。
以下是两个例子。第一个例子利用了同义词。来自SNLI的原始前提是“A little girl kneeling in the dirt, crying.”,这蕴含了“A little girl is very sad.”。他们为对抗样本所做的只是将“sad”改为“unhappy”。😔 这些本质上是同义词,因此我们期望系统在这种情况下继续判断为“蕴含”。
但Glockner等人观察到,即使是最好的系统也倾向于开始将其判断为“矛盾”情况。它们这样做是因为它们过度拟合了“否定词的出现是矛盾的指标”这一假设。
我再次喜欢这个测试,因为它显然利用了关于系统性的直觉。我们假设同义词替换应该保留SNLI标签,但系统就是不遵守这种基本原则。
第二个例子类似。前提是“An elderly couple are sitting outside a restaurant enjoying wine.”。原始的SNLI案例是“A couple drinking wine.”,标签是“蕴含”。对于Breaking NLI,他们将“wine”换成了“champagne”。现在,我们有了两个在概念层次上是“兄弟”关系的词。它们彼此互斥,但语义上非常相关。人类的直觉是,这些例子现在是“中立”的,因为“wine”和“champagne”是互斥的。但系统对这种词汇细微差别只有非常模糊的理解,因此它们也非常倾向于将这个案例判断为“蕴含”。这再次体现了关于词汇系统性及其如何影响我们对自然语言推理判断的直觉,而我们并没有从这些系统中看到类似人类的行为。
这是Glockner等人论文中的结果表。我认为我们应该排除最后几行,理由是那些系统使用了WordNet(创建对抗集时使用的资源)。看看前三行的系统,你会发现它们在SNLI测试集上表现很好(F1分数在80多分),但在新的对抗测试集上表现极差,性能存在巨大落差。
这很有趣,也令人担忧。但我们应该在此暂停,更仔细地看看这个表格,特别是“模型”这一列。所有这些模型都来自Transformer时代之前。事实上,它们正处于Transformer时代的边缘。这些都是带有大量注意力机制的循环神经网络实例,几乎触及了“注意力应成为主要机制”这一洞见。你也能从它们的SNLI测试结果(低于我们今天基于Transformer架构常规训练的系统)中看出它们所处的历史时期。
因此,我们应该问自己,如果我们测试一些更新的Transformer模型会发生什么?我决定这样做。我简单地下载了一个在MultiNLI数据集上微调过的RoBERTa模型(这与Glockner等人用来创建数据集的SNLI不同)。这是进行测试的代码,有点繁琐,所以我决定复现它。
这里的结论是:这个现成的模型基本上解决了Glockner等人的对抗集。我们应该只看“矛盾”和“蕴含”类别,因为“中立”在这个小挑战集中的样本太少。你可以看到令人印象深刻的高F1分数,与Glockner等人在前Transformer时代报告的结果截然不同。请记住,这甚至是在领域转移的情况下,因为这个RoBERTa模型是在MultiNLI上训练的,而测试的是源自SNLI的例子。这看起来像一个真正的成功故事,一个基本上被克服了的对抗集。我认为即使是最持怀疑态度的人也会将此视为进步的一个实例。
另一个NLI对抗性测试案例 🔍
让我们看第二个NLI案例。这个案例的发展会有些不同,但同样有一些重要的经验教训。这来自Nie等人2018年的工作。这是一个更大的对抗性测试基准,包含许多不同的类别:反义词、数字、词汇重叠、否定等。
对于其中一些类别,他们做了与Glockner非常相似的事情,即利用关于组合性或系统性的底层直觉,来处理诸如“爱/恨”或围绕数字术语的推理。但这个数据集也包含了一些在我看来更直接的对抗性内容,例如在示例末尾附加一些冗余或令人困惑的元素,以查看是否影响系统性能。我认为这更像是SQuAD对抗性测试的直觉。
这是一个相当大的基准,里面有很多例子。结果讲述了一个类似的故事:系统在MultiNLI上表现相当好,但在这个对抗性基准的所有子集上表现得非常、非常差。
但我们之前见过这个数据集。在讨论“通过微调进行免疫”的论文时,我们谈到过它。这张中心图中六个面板中的五个实际上都来自这个Nie等人的基准,但它们讲述了非常不同的故事。我们看到“词汇重叠”和“否定”被诊断为数据集弱点实例,即如果给予足够的相关证据,模型解决这些任务没有问题。相比之下,“拼写错误”和“长度不匹配”是模型弱点,模型在这些方面确实无法取得进展,因此这些可能仍然令我们担忧。而“数字推理”是数据集伪影的一个例子,即示例中的某些东西确实干扰了原本相当稳健的模型的性能。
因此,来自同一个挑战或对抗性基准,我们得到了三个非常不同的教训。我认为这也是进步的一个标志,因为我们现在有了工具,可以帮助我们在理解模型为何在这些不同的挑战测试集上失败方面,深入一个层次。毕竟,这正是我们希望通过这种新的行为测试模式来实现的分析性洞见。

总结 📝

本节课中,我们一起学习了对抗性测试在评估NLU模型鲁棒性中的关键作用。我们回顾了SQuAD和NLI领域的几个经典对抗性测试案例,看到了模型如何因过度拟合、缺乏系统性理解或对特定数据模式的依赖而失败。同时,我们也见证了技术进步(如Transformer架构)如何帮助模型克服了早期的某些对抗性挑战。更重要的是,我们认识到对抗性测试不仅能暴露弱点,其细致的分析(如区分数据集弱点、模型弱点和数据集伪影)还能为我们提供更深入的诊断见解,从而指导模型朝着更稳健、更类人的方向改进。对抗性测试是推动NLU模型不断超越表面指标、实现真正理解的重要工具。
30:对抗性自然语言推理 🛡️

在本节课中,我们将学习自然语言理解模型行为评估的进阶部分,重点关注对抗性训练的潜在益处。我们将深入探讨开创性的 ANLI 基准及其背后的动态对抗数据收集愿景。

上一节我们回顾了模型在系统性测试中暴露的弱点。本节中,我们将探讨如何通过将对抗性案例纳入训练集来增强模型的鲁棒性。

ANLI:对抗性自然语言推理基准
ANLI 论文及相关基准是这一领域的开创性工作。据我所知,ANLI 是首次尝试创建一个真正大规模、充满对抗性示例的训练集。这些示例能够“欺骗”当时性能顶尖的模型,但对人类而言却直观易懂。
可以公允地说,ANLI 是对我们上一节所回顾的对抗性测试结果的直接回应。当时我们看到,一些 NLI 模型的表现超过了我们对人类水平的估计,却在涉及语言系统性或组合性的简单现象上失败。
ANLI 的愿景是:通过在训练集创建中引入对抗性动态,我们可以获得更鲁棒的模型。
以下是数据集创建的工作流程:
- 向标注员展示一个前提句和一个条件(蕴含、矛盾或中立,即 NLI 的标签之一)。
- 标注员根据条件撰写一个假设句。
- 一个顶尖模型对这个生成的前提-假设对进行预测。
- 如果模型的预测与条件匹配(即模型预测“正确”),则标注员返回第 2 步重试。
- 如果模型被“欺骗”(预测错误),则该前提-假设对会由其他人类标注员独立验证后纳入数据集。
与顶尖模型的这种动态交互过程,产生了一个充满真正困难案例的训练集——既包含欺骗了该模型的案例,也包含未能欺骗它的案例。
ANLI 的示例颇具特色。其前提句往往较长,假设句则具有挑战性。有趣的是,数据集中还包含了“推理文本”,这是标注员对模型为何在该特定示例上遇到困难的最佳解释。据我所知,这些推理文本在文献中未被充分利用,但它们作为任务的一种间接监督来源,非常值得关注。
ANLI 核心结果分析
以下是 ANLI 论文的核心结果表。信息量很大,但故事线相当清晰。
让我们聚焦于 BERT 模型。可以看到,在所有不同的训练方案变体中,BERT 在 SNLI 和 MultiNLI 基准上都表现优异。
然而,当模型仅在 SNLI 和 MultiNLI 上训练时,它在 ANLI 上的表现非常差(三回合数据汇总后准确率仅约 20%)。
当我们用之前回合的 ANLI 数据来增强该模型的训练数据时,在 ANLI 列确实看到了整体性能的提升,这令人鼓舞。看起来,随着更多对抗性示例加入训练,模型在该任务上变得更好。
但根本的洞见在于:ANLI 上的性能远低于其他基准的性能,因为这是一个巨大的挑战。据我所知,这个重大挑战至今依然存在,模型在 ANLI 上并未达到卓越水平。
动态基准的愿景
ANLI 最吸引我的一点是,它为领域未来训练和测试资产的发展投射了一个非常有趣的愿景。这要完全归功于 Zellers 等人的工作,他们在关于 SWAG 和 HellaSWAG 的论文中也描述了这个愿景。
他们为 NLP 的进步规划了一条道路:基准与不断发展的顶尖模型进行对抗性协同进化。
这个故事细节很多,但简要来说:Zellers 等人首先引入了 SWAG,这是一个为对抗性测试创建的合成训练与测试环境。他们发现它非常困难,但当 BERT 论文出现后,BERT 基本上解决了 SWAG 问题。作为回应,Zellers 等人对 SWAG 数据集进行了一些调整,产生了 HellaSWAG。HellaSWAG 对 BERT 来说要困难得多,并且我相信它至今仍是一个具有挑战性的基准。
这开启了一条道路,让我们看到创建数据集、用其开发模型,然后在模型似乎成功时以更难的挑战作为回应,这一过程可以多么富有成效。
在 ANLI 论文中,他们非常直接地阐明了这一愿景:
这个过程为 NLU 系统产生了一个动态移动的目标,而不是一个最终会饱和的静态基准。
这听起来极具生产力。在整个领域,大型团队花费大量时间和金钱,只为在已有基准上获取微小的性能提升。如果我们能在看到基准饱和时,直接创建新的基准并为自己提出新的挑战,那该多好。如果进行这种“移动目标”式的实践,模型很可能会进步得更快,能力也变得更强。
Dynabench:实现愿景的平台
这正是 Dynabench 的愿景。Dynabench 是一个开源软件项目,一个用于(除其他功能外)动态对抗性数据收集的开源平台。
截至目前,Dynabench 已经产生了许多数据集。ANLI 是第一个,是先驱。此外,还有 Dynabench 衍生的用于问答、情感分析的数据集,以及多个用于仇恨言论(包括反仇恨言论)的数据集。我们还有几个关于问答的数据集和一个关于德语仇恨言论的数据集。我相信这个列表将继续增长,为我们提供这些不可思议的新资源。
本节课中,我们一起学习了对抗性训练的理念,深入分析了 ANLI 基准的创建方法、核心结果及其揭示的模型局限性。更重要的是,我们探讨了通过 Dynabench 平台实现的、让基准与模型协同进化的愿景,这为自然语言理解领域的持续进步指明了一个富有前景的方向。


下一节,我们将深入探讨一个我们创建的、名为 Dynasent 的 Dynabench 衍生数据集。
31:DynaSent 数据集与行为评估结论 🧠


在本节课中,我们将深入探讨 DynaSent 数据集,并总结关于自然语言理解模型行为评估的系列内容。DynaSent 是一个大规模、多轮次构建的情感分析数据集,其创建过程融合了对抗性数据收集与人工验证,旨在为模型评估提供更严苛的基准。

上一节我们介绍了对抗性训练集的概念以及 DynaBench 平台。本节中,我们将详细解析 DynaSent 数据集的构建过程、设计理念及其在模型评估中的应用。
DynaSent 项目概述 📊
DynaSent 是一个包含超过 12 万个句子的重要资源,涵盖两轮数据收集。每个例句都附有五位众包工作者提供的黄金标签。该项目的第二轮数据是在 DynaBench 平台上通过有趣的对抗性动态过程创建的。
以下是该项目的整体流程概览:
- 两轮构建:包含初始数据收集和对抗性增强两轮。
- 两个模型参与:使用初始模型(Model 0)发现数据,使用增强模型(Model 1)进行对抗性挑战。
- 广泛人工验证:每一轮都进行了大量的人工标注与验证。
第一轮数据构建 🔄
第一轮的起点是 Model 0。我们将其作为一个工具,用于从网络上发现自然出现的有趣案例。对这些案例进行人工验证后,便得到了第一轮数据集。
Model 0 的构建
Model 0 是一个基于 RoBERTa 的模型,在大量情感分析示例上进行了微调。我们使用了五个基准数据集来开发这个模型,并将所有数据集都视为三元情感问题(积极、消极、中性)。该模型在 SST-3、Yelp 和 Amazon 这三个外部数据集上表现良好,使其成为一个可靠的、用于从真实场景中挖掘示例的工具。
数据收集与验证
我们探索的空间是 Yelp 开放数据集,并采用以下启发式方法:
- 倾向于选择评论为一星但 Model 0 预测为积极的句子。
- 反之,倾向于选择评论为五星但 Model 0 预测为消极的句子。
我们使用的唯一标签来自人工验证阶段。每个例子由五位工作者验证,他们需要判断句子的情感是积极、消极、无情感还是混合情感。
第一轮数据集概览
最终得到的数据集规模可观,其中 47% 的例子是对抗性的。数据集同时包含对抗性和非对抗性案例,这对于构建高质量的基准测试非常重要。
关于在此资源上进行训练,有两种方式:
- 多数标签训练:将一个例子的标签定义为至少三位标注者选择的标签。如果没有这样的多数标签,则将其归入“其他”类别。
- 分布训练:将每个例子根据其从众包工作者那里获得的所有五个标签重复五次,并在整个集合上进行训练。这种方式能保留所有例子,并让模型更细致地学习人类情感判断的分布,实践中能产生更鲁棒的模型。
对于开发集和测试集,我们只关注积极、消极和中性三类,以构成一个清晰的三元情感问题,并在这三个标签上进行了平衡。
模型与人类表现
我们设置实验使得 Model 0 在第一轮数据上的表现处于随机水平。相比之下,人类在第一轮数据上表现极佳,我们估计人类的 F1 分数约为 88%。数据显示,1200 位工作者中有 614 位从未与多数标签产生分歧,这表明人类在该资源上具有高度的一致性和共识。
第二轮数据构建 ⚔️
第二轮与第一轮有显著不同。我们以 Model 1 为起点,这是一个在外部情感基准以及我们所有第一轮数据上微调过的 RoBERTa 模型。此阶段的直觉来源于 ANLI 项目,即应该在自身动态数据集收集的先前轮次上训练模型。
在此阶段,我们不再从野外收集例子,而是使用 DynaBench 平台来众包那些能够“愚弄” Model 1 的句子,然后对这些句子进行人工验证,从而得到第二轮数据集。
Model 1 的构建与表现
Model 1 同样基于 RoBERTa,并在相同的外部基准上进行训练,但为了给予第一轮数据更多权重,对外部数据进行了降采样。该模型在外部数据集上保持了良好性能,同时在第一轮数据上达到了约 80% 的准确率,这表明在引入第一轮数据后,模型性能得到了有效提升。
对抗性例句的众包策略
我们深入探讨了例句的众包方式。最初,我们仿照 ANLI 的做法,要求工作者从头开始编写句子来以特定方式愚弄模型。然而,这被认为是一项非常困难的创造性写作任务,容易导致数据集中出现重复模式。
因此,我们转向强调 “提示条件”。在这种条件下,我们向众包工作者提供一个来自 Yelp 开放数据集的自然出现的句子,他们的任务是编辑这个句子以达到愚弄模型的目的。结果,我们获得了质量更高、例子更自然的数据集。

第二轮数据集概览

验证方式与第一轮相同。最终数据集中只有 19% 的例子是对抗性的,这表明在此过程中,我们已经拥有了一个非常强大、难以被愚弄的情感模型。尽管如此,19% 在数量上仍然可观。这是一个比第一轮稍小的基准,但具有类似的结构,同样支持多数标签训练和分布训练,并拥有平衡的开发集和测试集。
模型与人类表现对比
同样,我们设置使得 Model 1 在第二轮数据上的表现处于随机水平。而人类在这一轮的表现更加出色,估计 F1 分数高达 90% 左右。244 位工作者中有 116 位从未与多数标签产生分歧。这一轮的例子更广泛地使用了复杂的句法结构以及隐喻、讽刺、反语等非字面语言,这些对人类来说直观,但对即使是最好的模型也极具挑战性。
结论与开放性问题 🤔
以上就是对 DynaSent 数据集的介绍。借此机会,我想提出几个结论性的开放性问题,旨在引导我们展望对抗性训练和测试的未来。

以下是几个核心的开放性问题:
- 对抗性训练能否改进系统? 总体证据显示答案是肯定的,但其中存在细微差别,需要精确校准。
- 什么构成了公平的非独立同分布泛化测试? 在讨论围绕所有行为评估的分析考量时,我们引入了“公平性”的概念。当我们谈论为什么某些 COGS 和 ReCOGS 的数据划分如此困难时,这个问题变得非常紧迫。我们甚至需要思考,要求机器学习系统以特定方式泛化(即使这对人类来说很直观)是否公平。
- 困难的行为测试能否为我们提供认证系统可信度所需的洞察? 如果可以,是哪些测试?如果不可以,我们应该怎么做?这是一个关键问题。某种程度上,我们知道答案是否定的——任何数量的行为测试都无法提供我们所寻求的那种保证。但它是深入了解这些系统特性的有力组成部分。我们当然可以使用行为测试来发现系统明显失败的案例。但对于安全和可信度的实际认证,我们需要更深入的方法,这将是课程下一单元的主题。
- 我们的最佳系统是否找到了系统性的解决方案? 如果答案是肯定的,作为人类我们会感到可以信任它们。如果答案是否定的,即使它们在某些场景下表现良好,我们也可能总是担心它们会做出让我们完全困惑的事情。
- 人类能以直接经验不支持的方式进行泛化。AI 在系统设计上应如何回应? 这是一个宏大且涉及认知与哲学的问题。为了实现这些非常不寻常的、准认知/准行为的学习目标,我们应该做什么?目前我无法解答这个问题,但当我们考虑挑战系统用语言做复杂事情时,它确实非常紧迫。

本节课中,我们一起深入学习了 DynaSent 数据集的构建细节、其对抗性数据收集策略,并探讨了行为评估在衡量和提升 NLU 模型鲁棒性方面的作用与局限。我们认识到,虽然对抗性测试是强大的工具,但要实现真正的系统可信度认证,仍需探索更深入的方法。
32:文献综述概述 📚


在本节课中,我们将学习如何为课程项目撰写文献综述。文献综述是项目阶段的关键起点,旨在帮助你为最终项目建立坚实的知识基础。
概述
文献综述的核心在于进行富有成效的对话。你需要与团队成员、导师以及自己进行对话,探讨在最终项目中计划实现的目标。这包括提出问题、识别障碍、构思初步解决方案、寻找数据集与模型,并仔细评估可用资源。其根本理念是从现有文献中收集信息,了解相关领域的研究现状,并以此为基础,规划出自己项目的原创方向。
具体要求
以下是文献综述的具体要求,你可以在课程网站找到详细说明。
- 篇幅:文档长度约为6页,最多不超过8页(不含参考文献部分)。
- 模板:我们提供了一个基于ACL格式的LaTeX模板。虽然不强制使用,但建议你使用它,以便提前熟悉最终论文所需的格式。
- 文献数量:单人小组需评阅5篇论文,双人小组7篇,三人小组9篇。这在一定程度上鼓励了团队合作。
- 主题一致性:理想情况下,文献综述与最终项目应主题一致,这样最高效。但我们也理解,完成文献综述后你可能会改变研究方向。若发生这种情况,请务必与导师和团队成员沟通,确保能在有限时间内调整并完成项目。
核心内容构成
以下是文献综述应包含的主要部分,你可以直接将这些短语用作章节标题,以帮助导师理解你的思路。
- 问题与任务定义:这是绝对关键的部分。你需要阐明将要研究的问题类型,并引导我们关注对项目至关重要的方面。
- 文献简明摘要:我们需要的并非简单的文献内容复述,而是能够提出问题、指出对你思考项目工作本身有启发的问题和观点的理想摘要。
- 文献比较与对比:你需要比较这些文献在模型、数据和核心结果等方面的异同,因为这有助于为你指明原创贡献的可能方向。
- 未来工作展望:这是非常重要的一环。你需要思考下一步计划,以及如何将这些想法整合成一个完整的项目。创造性思考越早开始越好,你在此部分思考得越深入,与导师的对话就会越有成效,项目也就能走得更远。
- 参考文献:最后,为了养成良好习惯并让我们清楚你评阅了哪些文献,必须包含参考文献部分。
如何进行文献检索
在具体进行文献检索时,以下是我多年来总结的一些高效技巧,我至今仍经常使用这个循环流程。
- 初步搜索:在ACL Anthology、Google Scholar或Semantic Scholar中使用关键词进行搜索。鉴于这是NLP课程,建议从ACL Anthology开始,因为NLP领域的文献组织得非常完善。
- 筛选与下载:下载相关或高被引的搜索结果,并查看其摘要和相关工作部分。此时的目标是找出关键问题、技术以及其他高被引文献,切勿在此阶段通读全文,那样效率极低。
- 扩展检索:将相关工作中频繁出现的论文也下载下来,加入你的核心文献集。
- 迭代优化:带着在搜索过程中收集到的新关键词,返回第1步。当你对该领域的研究现状和自己的方向有清晰认识,并开始围绕几篇你认为至关重要的论文进行深入思考时,就可以跳出这个循环了。
完成上述流程后,你便有了选择文献综述核心论文的基础。此时,从下载的文献集中选出一些核心论文,最后再对其进行深度阅读和评述。这样,你可以先通过广泛、轻量的调研获取最大信息量,然后在明确投资方向后进行深度钻研。
关于AI助手与学术诚信的特别说明
这涉及到一个有趣的学术诚信政策。鉴于我们研究大语言模型,学术界日益担忧这些模型会增加评估学生写作的难度。让我们尝试接纳这一点。例如,我使用GPT-4搜索了关于ELECTRA论文与Transformer论文关系的资料,返回的结果看起来非常有用,像是可以为文献综述提供信息的原始资料。
但请务必了解课程政策:政策允许你使用像GPT-4这样的AI助手来协助完成文献综述,但模型的所有输出都必须被引用。你需要将其视为任何其他资源来对待。当然,完全由任何资源的引文组成的作业在评估中不会获得好成绩。
此外,文字有实质性重叠的作业将被审查是否抄袭。这意味着如果两个小组使用了相似的提示词,得到了相似的结果,并且未加引用地将其放入文献综述,他们可能会因抄袭而被扣分——这不是因为他们使用了模型,而是因为两份作业看起来过于相似。此时,问题不在于语言模型本身,而在于我们通常担心的那种标准抄袭行为。
因此,我建议使用这些助手不是为了为你生成原始文本,而是帮助你了解文献内容。同时,你需要保持审慎的态度。因为即使AI生成的描述看起来不错,在未经彻底核实确保其事实正确性之前,也不应直接使用(即使是转述)。毕竟,我们最终追求的是事实的准确性,而非文字的来源。这些工具显然有价值,可以提升研究的某些方面,我们不想禁止它们(这正是我们学习这门课程的原因),但我们希望谨慎使用,并确保它们不会最终产生糟糕的学术成果。
衔接下一个环节:实验方案
在完成文献综述后,值得提前考虑下一个文档——实验方案。这在课程中是一个相对独特的环节。这是一份简短的结构化报告,旨在帮助你建立核心实验框架。
其必需部分包括:假设、数据、评估指标、模型、总体推理、进度总结和参考文献。你可以看到,这基本上构成了一个NLP项目的原始材料。我们试图通过它来检查是否有任何缺失,或者是否存在其他可能阻碍项目按时完成的障碍。其核心思想是明确项目目标、识别障碍和评估项目风险。因此,你应该倾向于披露更多信息,以确保我们能克服所有障碍、填补所有空白,最终使项目成功。
虽然实验方案是下一个任务,但你在撰写文献综述时就可以开始沿着这些思路进行思考。越早开始构思最终项目的具体样貌越好。即使在文献综述阶段,你也可以开始感受哪些假设有趣、希望尝试哪些技术等等。这正是所有这些前期项目作业的意义所在。
总结

本节课中,我们一起学习了文献综述的目的、具体要求、核心构成部分以及高效的检索方法。我们还特别讨论了在AI助手时代如何合理利用工具并遵守学术规范。最后,我们预览了下一个环节——实验方案,并鼓励大家尽早为最终项目进行规划。记住,文献综述是项目成功的基石,扎实的调研将为你的原创工作照亮道路。🚀
33:NLU分析方法概述(第一部分)🔍



在本节课中,我们将开始学习自然语言处理(NLP)中的分析方法。我们将超越单纯的行为测试,深入探讨如何理解模型内部的工作机制,以获得关于模型行为的因果性保证。
从行为测试到结构分析
在上一单元中,我们重点讨论了行为测试,特别是以假设驱动的挑战集和对抗性测试作为工具,来深入理解模型在陌生场景下的行为。然而,行为测试有其固有的局限性。
为了更生动地说明这一点,让我们回顾一下“奇偶检测器”的例子。假设一个模型接收像“4”这样的字符串,并预测它指的是偶数还是奇数。它可能在前几个测试(如4、21、32、36、63)中都做出正确预测,让我们感觉它是一个好模型。
但当我们看到其内部工作原理时,真相才被揭示。例如,第一个模型可能只是一个简单的查找表,遇到不熟悉的输入就默认预测为奇数。一旦我们看到 if input in lookup_table: return lookup_table[input] else: return "odd" 这样的逻辑,我们就完全明白了模型是如何失效的,以及如何在行为上击败它(例如输入“22”,它会错误地预测为奇数)。
第二个模型可能更复杂,它会对输入进行分词,并使用最后一个词元作为预测奇偶的基础。这听起来是个不错的策略,但它可能同样有一个默认预测为奇数的 else 子句。只有当我们看到内部因果机制时,我们才能确切知道模型如何工作以及它将在何处失败。
对于现代NLP模型,它们几乎从不象刚才展示的符号程序那样易于理解。相反,我们的模型看起来像巨大的、不透明的“鸟巢”,由权重和权重的乘法构成,没有明显的符号,这使得我们很难像理解简单程序那样理解它们。
为什么需要超越行为测试?
行为测试虽然重要,但不足以提供我们所需的全部保证。这主要有三个原因:
-
系统性(Systematicity):人类的语言能力是系统性的。理解“Sandy loves the puppy”这句话,内在关联着理解“The puppy loves Sandy”。我们不会将每句话都视为全新的事实来学习,而是基于已有的底层能力进行推导。我们希望验证模型找到的解决方案是否也具有这种系统性,甚至是组合性(Compositionality),否则我们总会担心它们在关键时刻的行为是任意的。
-
基准测试的局限性:虽然模型在各类基准测试上进步神速,但我们怀疑,即使在这些任务上表现良好的模型,距离我们试图诊断的人类能力仍然很远。我们感觉它们拥有脆弱的、可能以问题方式暴露自身的解决方案。要真正超越这种担忧,我们需要超越行为测试。
-
安全与可信赖的目标:领域内有许多关乎安全与可信赖的高层目标,例如:认证模型可在何处使用、不应在何处使用;认证模型没有有害的社会偏见;保证模型在特定上下文中的安全性。行为测试或许能告诉我们模型存在问题,但无法提供不存在问题的正面保证(如“无社会偏见”、“在上下文中安全”)。要获得这些保证,我们需要在深层理解模型的结构和引导其行为的机制。
三类核心分析方法
为了向上述目标迈进,我们将讨论三类主要方法:
1. 探针分析(Probing)
探针分析通过训练小型监督模型来探测神经网络内部表示(如BERT的不同层)中编码的信息。Tenney等人(2019)的研究具有开创性,他们发现BERT的各层系统性地编码了丰富的语言学信息。
例如,在他们的研究中,词性(POS)信息大约在中间层出现,依存句法信息出现稍晚,命名实体(NER)信息更微弱且出现更晚,语义角色(SRL)在中间层附近很强,共指(Coref)信息在网络较深层出现。这表明,即使BERT以“黑盒”方式运行,其内部表示也学习到了系统性的语言结构。
探针分析能很好地表征内部表示,但它本身不能证明这些信息是模型做出决策的原因。
2. 特征归因(Feature Attribution)
这类方法旨在理解模型的输入-输出行为由哪些内部神经元或特征引导。在深度学习背景下,通常通过研究模型的梯度来实现。
例如,在一个情感分析挑战集中,特征归因方法可以高亮显示模型做出预测时所依赖的输入部分。如果高亮的部分是直观上重要的词语(如情感强烈的动词或转折词),这可能会让我们感到安慰,认为模型正在使用人类可解释的、系统性的信息。
特征归因方法能提供一些因果性保证(例如,通过积分梯度法可以量化每个输入特征对最终预测的贡献),但它们对内部表征的描述相对模糊,通常只给出权重或贡献度。
3. 基于干预的方法(Intervention-based Methods)
这是我们将重点探讨的一类方法。其核心思想是对模型进行“脑外科手术”,即主动操纵其内部状态,并观察这对输入-输出行为产生的影响。
通过这种方式,我们可以拼凑出塑造模型行为的因果机制。这类方法有望推动我们获得所需的那种保证。
分析方法评估框架
我们可以用一个简单的评估框架来思考这些方法。假设我们有三个目标:
- 表征内部表示:描述模型内部状态的含义。
- 做出因果断言:证明特定表示或机制是模型行为的原因。
- 改进模型:基于获得的见解,找到改进模型的清晰路径。
以下是三类方法在这个框架下的表现:
| 方法 | 表征表示 | 因果保证 | 改进路径 |
|---|---|---|---|
| 探针分析 | 优秀 👍 | 弱/无 👎 | 不明确 ❓ |
| 特征归因 | 模糊/微弱 👎 | 中等(部分方法)👍 | 不明确 ❓ |
| 基于干预 | 优秀 👍 | 优秀 👍 | 清晰 👍 |
基于干预的方法在三个方面都表现突出。它不仅能帮助我们表征和理解内部表示,还能通过主动干预建立因果联系,并且这些见解能直接用于指导模型改进(例如,修复已识别的缺陷或增强特定能力)。因此,这也是我个人最推崇的一类方法。
总结


本节课中,我们一起学习了超越行为测试、深入分析NLP模型内部机制的必要性。我们探讨了行为测试的局限性,并介绍了三类核心的分析方法:探针分析、特征归因和基于干预的方法。我们还建立了一个评估框架,从“表征表示”、“因果保证”和“改进路径”三个维度来审视这些方法。在接下来的课程中,我们将系统地深入学习这些方法,以更深入地理解它们的工作原理。
34:NLU分析方法(第二部分):探针分析 🔍

在本节课中,我们将继续探讨自然语言理解的分析方法,重点介绍一种称为“探针分析”的技术。我们将了解其工作原理、潜在价值以及需要谨慎对待的局限性。


概述:什么是探针分析?🤔
探针分析的核心思想是使用有监督的模型(即我们的“探针模型”),来确定目标模型(我们真正关心的模型)的隐藏表征中潜在编码了哪些信息。
探针分析常应用于所谓的“BERTology”领域。Tenny等人2019年的研究是该领域的一项基础性贡献,它揭示了BERT模型通过其训练机制在多大程度上诱导出了关于语言的有趣结构。
虽然探针分析能提供有价值的见解,但我们必须谨慎行事。
探针分析的步骤与注意事项 ⚠️
以下是进行探针分析时需要遵循的步骤和注意事项:
首先,你需要提出一个关于目标模型内部结构某个方面的假设。例如,你可以假设它存储了关于词性、命名实体或依存句法分析的信息。
接着,你需要选择一个有监督的任务,作为你感兴趣的内部结构的代理。例如,如果你想寻找词性信息,就需要一个词性标注数据集,并且探针本身的定义将依赖于这个数据集。
然后,你需要在模型中选择一个位置,即一组你认为该结构会被编码的隐藏表征。
之后,你在选定的位置上训练一个有监督的探针。
最后,探针的成功程度就是你对你所提基础假设正确性的估计。但这里有一些需要注意的地方。
探针分析的核心方法 🛠️
让我们先了解核心方法。以一个简化的三层BERT类模型为例。假设我们选择隐藏表征 H 作为探针的目标位置。
我们将使用一些任务标签,在该内部表征上拟合一个小的线性模型。实际操作过程如下:
- 在输入序列上运行BERT模型。
- 获取目标位置的向量表征。
- 开始构建一个小型的有监督学习数据集,其中
X是向量,Y是输入示例的任务标签。 - 对不同的输入序列重复此过程,获取不同的向量表征和任务标签,不断扩充数据集。
- 最终,在这个
(X, Y)数据对上拟合一个小的线性模型。
需要注意的是,我们只是将BERT模型用作获取这些向量表征的“引擎”,以供探针模型使用。通常,我们会进行分层分析。例如,你可以认为整个层编码了词性信息,然后构建一个由向量列表及其对应标签列表组成的数据集,并在此基础上训练一个词性标注模型,这就是你的探针。
核心问题:我们到底在探测什么?🎯
探针分析面临的第一个紧迫问题是:我们是在探测目标模型,还是仅仅在学习一个新的探针模型?
在当前语境下,探针本身就是有监督模型,其输入是我们所探测模型的冻结参数。我们使用BERT模型作为创建特征表征的引擎,这些表征是另一个独立建模过程的输入。这很难与通常的、基于特定特征化选择(即我们根据BERT的计算方式选择的位置)来拟合有监督模型的过程区分开来。
因此,我们知道,我们识别出的信息至少有一部分可能存储在探针模型中,而非目标模型中。当然,更强大的探针可能会在目标模型中发现更多信息,但这仅仅是因为它们在探针参数中存储了更多信息——它们有更大的容量来做到这一点。
探针选择性:校准信息源 📏
为了帮助解决上述问题,Hewett和Leang引入了探针选择性的概念,这有助于我们在一定程度上校准有多少信息实际上存在于目标模型中。
第一步是定义一个控制任务。这是一个随机任务,具有与你的目标任务相同的输入输出结构。例如:
- 对于词义分类,你可以为单词分配随机的固定词义。
- 对于词性标注,你可以将单词分配到随机的固定标签,或许保持与底层词性数据集相同的标签分布。
- 对于句法分析,你可以使用一些简单策略随机分配边,从而得到与黄金数据集中结构截然不同的树结构。
然后,探针的选择性指标就是探针在目标任务上的性能与在控制任务上的性能之差。这样,你就衡量了你的模型在一种随机任务上的表现能力。
Hewett和Leang提供了一个总结性图示,表明能提供可靠见解的探针往往是那些非常小的模型(例如只有两个隐藏单元的模型),它们具有很高的选择性。相反,如果探针模型参数很多、能力很强,其选择性就会很低,因为它有巨大的容量去单纯记忆数据集的各个方面。
第二个担忧:因果推断的缺失 ⛓️
现在让我们转向第二个担忧,即关于因果推断的问题。为了阐明这个论点,我们使用一个简单的例子。
假设我们有一个小型神经网络,它接收三个数字作为输入,并完美计算它们的和。问题是,它是如何实现这一壮举的?模型是如何工作的?
你可能有一个假设:它以组合方式工作,前两个输入 X 和 Y 结合形成一个中间变量 S1,第三个输入 Z 被复制到内部状态 W,然后 S1 和 W 这两个模块化表征被加在一起形成输出表征。这是一个关于模型如何工作的假设。
现在的问题是,我们能否使用探针分析来可靠地评估这个假设?
假设我们探测 L1 层,并发现它总是完美编码第三个输入 Z 的身份。接着我们探测 L2 层,发现它总是完美计算 X + Y。这看起来支持了我们最初的假设。
然而,探针误导了我们。实际上,L2 层对输出行为完全没有影响(查看输出层的权重向量,L2 的权重全为零,没有因果影响)。探针说它存储了 X + Y,它可能确实在做这件事,但这种方式并不能告诉我们关于输入输出行为的信息。因此,探针在因果层面误导了我们。
探针分析能改进模型吗?🚀
我设定的最终目标是:我们是否有一条路径,能通过所选的分析方法来改进模型?我的答案是混合的。
似乎存在一条从探针分析到多任务训练的路径。例如,我训练这个模型做加法,同时额外训练它,使某个表征编码 Z,另一个表征编码 X + Y。我们当然可以设定这样的目标。但这是否真的能诱导出我们感兴趣的那种模块化,仍是一个悬而未决的问题。
对我来说,真正深层的担忧是,即便如此,我们仍然得不到因果保证。我们可以进行多任务训练,但这并不能保证我们诱导出的结构(无论它是什么样)实际上塑造了核心任务(此处是数字相加)的性能。因此,我们必须谨慎行事。
无监督探针 📝
最后快速提一下无监督探针。这个领域有出色的工作,使用了多种不同的方法。这里列出了一些该文献中具有开创性的参考文献。同样,我认为这些技术不受探针能力过强问题的影响(因为它们通常没有自己的参数),但我认为它们确实存在因果推断方面的局限性。
总结 📋
让我们用评分卡来总结一下:
- 表征刻画:探针分析可以很好地刻画表征(我们使用有监督探针来实现这一点)。👍
- 因果推断:探针无法提供因果推断。👎
- 模型改进:目前尚不清楚多任务训练是否真的是一条从探针分析到更好模型的可行、通用的途径。🤔


本节课中,我们一起学习了探针分析这种NLU分析方法。我们了解了其通过有监督模型探测目标模型内部表征的基本流程,同时也深入探讨了其两大核心局限:难以区分信息是存储在目标模型还是探针模型中,以及无法提供关于模型行为的因果性见解。理解这些优点和局限性,对于正确应用和解读探针分析至关重要。
35:NLU分析方法(三)特征归因 🔍



在本节课中,我们将学习自然语言理解中的特征归因方法。特征归因旨在解释模型的预测结果,帮助我们理解模型在决策时关注了输入的哪些部分。我们将重点介绍一种强大且具有理论保证的方法——积分梯度法。
概述:什么是特征归因?
特征归因方法试图为模型的每个输入特征分配一个重要性分数,以解释该特征对最终预测的贡献。这对于理解复杂的深度学习模型(如BERT)的内部工作机制至关重要。
特征归因的公理框架
在深入具体方法之前,我们先了解评估特征归因方法的理论框架。积分梯度法的论文提出了几个公理,其中最重要的是敏感性公理。
敏感性公理指出:如果两个输入 x 和 x‘ 仅在维度 i 上不同,并且导致了不同的预测结果,那么与维度 i 相关的特征必须具有非零的归因分数。
用公式表示,对于一个模型 M:
- 若
M(x) ≠ M(x‘),且x与x‘仅在维度i上不同。 - 则
attribution_i ≠ 0。
这个公理非常直观,它要求归因方法必须能够识别出导致预测差异的关键特征。
基线方法:梯度 × 输入
让我们从一个直观的基线方法开始:梯度 × 输入法。这种方法计算模型输出相对于目标特征的梯度,然后将梯度值乘以该特征的实际值。
其核心计算如下:
attribution = gradient_of_output_wrt_input * input_value
以下是两种实现方式:
- 使用原始PyTorch计算。
- 使用Captum AI库的封装函数。
这种方法实现简单,并且可以推广到深度学习模型中的任何神经元状态。
一个关键的概念难题
在应用归因方法时,我们面临一个选择:归因计算应该基于预测的标签还是真实的标签?这两个标签对应于模型输出向量的不同维度。
对于高性能模型,预测标签和真实标签几乎相同,这个选择影响不大。但当我们研究一个性能较差的模型以找出其缺陷时,这两种选择会产生截然不同的归因结果,从而为我们提供关于模型行为的不同图景。没有先验的理由偏爱其中一种,最佳做法是明确你在分析中所做的假设和使用的方法。
基线方法的缺陷
然而,“梯度 × 输入”法存在一个根本性问题:它违反了敏感性公理。
考虑一个简单的单输入模型 M(x) = 1 - ReLU(1 - x):
- 输入
x=0时,输出为0。 - 输入
x=2时,输出为1。
根据敏感性公理,由于输入维度的变化导致了输出差异,该特征应获得非零归因。但“梯度 × 输入”法对这两个输入计算出的归因分数均为 0。这个反例揭示了该方法的局限性,也引出了我们需要更优的方法。
核心方法:积分梯度法
积分梯度法通过探索输入的反事实版本来改进归因,这对于获得模型行为的因果洞察至关重要。
工作原理
IG的直觉是:我们不仅看当前输入点的梯度,而是沿着一条从基线输入(如零向量)到实际输入的路径,对路径上所有点的梯度进行积分。
具体步骤如下:
- 设定基线:选择一个参考点(如零向量)。
- 线性插值:在基线和实际输入之间创建一系列插值输入
x’ = baseline + α * (input - baseline),其中α从0逐步增加到1。 - 计算路径梯度:计算模型输出对每个插值输入的梯度。
- 积分近似:对所有插值点的梯度进行求和(积分近似)。
- 缩放:将积分结果乘以
(input - baseline),得到最终的归因分数。
用公式概括为:
IntegratedGrads(x) = (x - baseline) * ∫_{α=0}^{1} (∂F(baseline + α*(x-baseline)) / ∂x) dα
其中 F 是模型函数。
为何IG更优?
回到之前那个违反敏感性公理的例子。IG方法通过积分路径上所有点的梯度,成功地为该特征分配了约为 1 的非零归因分数。理论上可以证明,IG满足敏感性公理,提供了更强的因果保证。
实践应用:分析BERT类模型
IG方法最强大的特性之一是其灵活性。对于像BERT这样的复杂模型,我们可以计算模型中任何层次、任何神经元状态对最终预测的归因。
这结合了探针技术的灵活性,同时提供了归因与输入-输出行为之间因果效力的理论保证。
完整工作示例
以下是一个使用Captum库和基于RoBERTa的推特情感分类器进行IG分析的简化流程:
- 加载模型与定义函数:加载预训练模型,并定义用于计算概率和生成基线/实际输入表示的函数。
- 指定目标:选择要计算归因的目标类别(如真实标签“积极”)。
- 执行归因计算:调用
LayerIntegratedGradients函数,传入模型、目标层、基线输入和实际输入。 - 后处理与可视化:对归因分数进行标准化(如Z-score),并使用Captum的可视化工具生成结果。
分析结果通常以高亮文本的形式呈现,其中颜色深度表示归因分数的大小:
- 绿色:该特征支持目标标签(例如,在积极情感分析中,支持“积极”标签)。
- 红色:该特征反对目标标签。
- 白色:中性贡献。
通过观察不同示例(如包含“great”、“wrong”等词的句子),我们可以定性地评估模型是否系统性地利用了合理的特征进行情感预测。
总结与思考
本节课我们一起学习了特征归因方法。总结如下:
- 价值:特征归因提供了对模型表征的宏观描述,为每个特征分配一个重要性标量,是理解模型决策的有用指南。
- 因果保证:使用如积分梯度法这类方法,可以获得理论上的因果保证,增强解释的可信度。
- 局限性:归因方法本身并不能直接用于改进模型。它提供的是“环境信息”,这些洞察可能需要在一个独立的后继建模步骤中,才能指导我们优化模型。


总而言之,特征归因是一种强大而灵活的启发式方法,能够为我们提供关于模型如何解决任务的宝贵见解。
36:因果抽象与互换干预分析 🧠



在本节课中,我们将学习因果抽象分析的核心方法。这是一种基于干预的技术,旨在为复杂的自然语言处理模型提供概念层面的因果解释。我们将重点理解“互换干预”这一基本操作,并探讨如何利用它来验证模型内部机制与人类可理解的因果假设是否一致。
因果抽象分析:一个操作指南 📋
上一节我们讨论了其他分析方法,本节中我们来看看因果抽象分析的具体步骤。其核心流程可以概括为以下两步:
- 提出假设:首先,你需要对你的目标模型(例如一个神经网络)的因果结构提出一个假设。这个假设通常可以表示为一个小型计算机程序或一个清晰的因果图模型。
- 寻找对齐:接着,你需要在这个假设的因果模型中的变量,与目标模型中的神经元(或神经元集合)之间,寻找一种对齐关系。这本质上是一个关于“哪些神经元组在扮演哪些因果角色”的假设。
为了评估这种对齐假设是否正确,我们需要执行因果抽象分析的基本操作:互换干预。
理解互换干预:一个加法网络的例子 ➕
为了让你对互换干预如何工作有直观感受,我们来看一个简单的运行示例。
假设我们有一个简单的神经网络,它的任务是输入三个数字并将它们相加。我们假设这个网络能成功完成此任务。那么问题来了:这个网络是如何以人类可理解的方式执行这个加法功能的?
我们可以提出一个因果假设模型(用绿色表示):
- 该网络先将前两个输入相加,得到一个中间变量 S1。
- 同时,第三个输入被复制到另一个中间变量 W。
- 最后,S1 和 W 直接相加得到模型的输出。
这是一个关于我们原本不透明的神经网络内部可能发生什么的假设。问题是:这个假设正确吗? 我们将使用互换干预来评估它。
第一步:评估 L3 是否对齐 S1
以下是评估“神经表示 L3 是否扮演与 S1 相同角色”的具体步骤:
-
在因果模型上进行干预:
- 我们用因果模型处理输入
(1, 3, 5),得到输出9。 - 再用同一个因果模型处理输入
(4, 5, 6),得到输出15。 - 现在进行干预:我们锁定右侧例子(输入为
(4,5,6))中值为9的变量 S1,将这个值直接替换到左侧例子(输入为(1,3,5))中 S1 的位置。 - 由于因果模型是我们完全理解的,我们知道干预后的输出将变为
9 + 5 = 14。被干预变量下方的子节点信息被完全覆盖。
- 我们用因果模型处理输入
-
在神经模型上进行平行操作:
- 我们用神经模型处理
(1, 3, 5),得到输出9。 - 用神经模型处理
(4, 5, 6),得到输出15。 - 现在进行干预:我们锁定右侧例子中的 L3 状态,将这些值直接替换到左侧例子中 L3 的对应位置。
- 然后观察输出。如果干预后的输出也是
14,那么我们就获得了一个证据,表明 L3 与 S1 的因果角色是一致的。
- 我们用神经模型处理
核心逻辑:如果我们对模型所有可能的输入都重复这个干预,并且总是看到因果模型和神经模型的输出在这种对齐下保持一致,那么我们就证明了 L3 与 S1 扮演相同的因果角色。
第二步:评估其他变量
我们可以继续这个过程来评估其他对齐假设:
- 评估 L1 是否对齐 W:假设 L1 扮演 W 的角色。在因果模型上,将右侧例子的 W 值(例如
6)替换到左侧,输出应变为1+3+6=10。如果在神经模型上对 L1 进行同样的互换干预后,输出也变为10,则证明 L1 与 W 因果对齐。 - 评估 L2 的因果角色:如果我们对 L2 进行各种可能的干预,但从未观察到模型输出行为因此改变,那么我们就证明了 L2 在此网络的输入-输出行为中不扮演任何因果角色。
如果所有输入、输出以及中间变量的对齐假设都通过了互换干预的检验,那么我们就证明了那个绿色的因果模型,就是那个更复杂的神经模型的一个抽象。这意味着我们可以放心地用更简单、可理解的因果模型来推理神经模型的行为机制。
现实世界的考量与评估指标 📊
刚才描述的是因果抽象分析的理想情况。现实中需要考虑以下几点:
- 无法穷举所有干预:对于真实模型,可能的输入是无穷的,我们只能选择一个小子集进行测试。
- 不存在完美的抽象:由于自然训练模型的复杂性,我们几乎永远不会看到完美的因果抽象关系。因此,我们需要一个分级的成功度量标准。
一个很好的基线指标是 互换干预准确率:
IIA = (导致输出与因果模型预测一致的互换干预次数) / (执行的互换干预总次数)
关于 IIA 的重要说明:
- IIA 的值在 0 到 1 之间,类似于准确率。
- 它可能高于任务本身的性能。这是因为互换干预有时会将模型置于比原始状态更好的“弗兰肯斯坦”状态。
- IIA 高度依赖于你所选择执行的干预子集。特别是,那些应该改变输出标签的干预,才是真正提供因果洞察的关键。
因果抽象的研究发现与应用 🚀
以下是来自相关研究(主要是我们团队的工作)的一些发现:
- 微调后的 BERT 模型之所以能在涉及词汇蕴含和否定的困难域外例子上成功,是因为它们被简单的单调性程序所抽象。这里的“因为”是一个因果声明,这正是因果抽象分析所允许的。
- 模型在 MQNLI(多重量化自然语言推理)任务上的成功,是因为它们找到了组合式解决方案。因果分析证明了模型成功的程度与其找到组合解的程度直接相关。
- 模型在 MIS 指针值检索任务上的成功,是因为它们被类似
if the digit is 6, then the label is in the lower left的简单程序所抽象。这种解释与任务结构本身完美对齐,令人振奋。 - 研究还表明,BART 和 T5 模型使用了连贯的实体和情境表征,这些表征会随着语篇展开而演化。
一个深刻的启示:因果抽象开始模糊神经模型与符号模型之间的界限。如果你能证明两者通过因果抽象对齐,那么它们之间就不存在有意义的区别。这引发了人们对符号 AI 与神经 AI 是否真有本质不同的思考。


从分析到改进:互换干预训练 🛠️
因果抽象不仅能解释模型,还能改进模型。这就是 互换干预训练 的核心思想。
方法很简单,直接建立在因果抽象之上。回顾之前的加法例子,假设我们对 L3 的干预没有得到预期的 14,而是得到了 4。这表明我们假设的对齐关系不正确。
但这里也蕴含着一个改进的机会:我们知道干预后应有的输出(14)和实际输出(4)之间的差异。这个差异可以作为一个梯度信号,用来更新模型的参数,使其在此对齐假设下更符合底层的因果模型。
IIT 的更新过程:
- 对于 L1 和 L2,梯度像往常一样流回输入状态。
- 对于被干预的 L3,情况更复杂:由于我们复制了完整的计算图(包括梯度信息),L3 会得到一个“双重更新”——既来自当前例子,也来自提供该表征的源例子。
通过反复使用因果模型作为“标签”来执行这种 IIT 更新,我们可以推动模型将关于 S1 的信息模块化到 L3 变量中。这样,对齐的重要性就降低了,重点变成了通过赋予模型我们假设的因果结构来主动改进模型,希望它们能以更系统化的方式形成,从而在我们设定的任务上表现更好。
IIT 的研究发现:
- 在 MIS 指针值检索 和 ReSCAN(一个接地语言理解基准)任务上达到了最先进的性能。
- 可作为蒸馏目标,不仅迫使师生模型的输入输出行为一致,还迫使它们在 IIT 创建的反事实条件下,内部表征也保持一致。这是一种强大的蒸馏方法。
- 可用于在基于子词分词的语言模型中,诱导出基于字符的内部表征,这有助于处理各种字符级游戏和任务。
- 最近被用于创建解释模型行为的概念级方法,即 因果代理模型 技术。
总结 ✨
本节课中,我们一起学习了基于干预的模型分析方法,重点是因果抽象与互换干预。
- 因果抽象分析 允许我们为黑盒神经网络提出可理解的因果假设,并通过互换干预这一核心操作来验证神经元的集合是否与假设中的因果变量扮演相同的角色。
- 我们探讨了评估指标 IIA,并了解了该领域的一些关键研究发现,这些发现揭示了成功模型背后的可解释机制。
- 更进一步,我们看到了如何将分析工具转化为改进工具。互换干预训练 利用干预产生的误差信号来更新模型,主动地将其内部结构塑造成我们期望的因果形式,从而提升模型的系统性和性能。


综上所述,基于干预的方法(尤其是因果抽象和 IIT)能够丰富地表征模型内部表示,进行因果推断,并最终指导我们改进模型,是目前我们深入理解 NLP 模型工作机制的最佳途径之一。
37:分布式对齐搜索 (DAS) 🧠

在本节课中,我们将学习一种全新的自然语言处理分析方法——分布式对齐搜索。我们将探讨它如何克服先前介绍的因果抽象方法的局限性,并通过一个简单示例理解其核心思想。最后,我们将展望可解释性研究的未来方向。


回顾分析方法的挑战
上一节我们介绍了因果抽象方法。现在,让我们回到分析方法的评估表。
我已在“干预”这一行证明了三个笑脸标记的合理性,但这类方法仍存在两个紧迫问题。
以下是两个主要问题:
- 对齐搜索成本高昂。对于复杂的因果模型和现代大型语言模型,可能的对齐方式数量极其庞大。我们引入了许多近似方法,但仍可能错过真正优秀的对齐方案。
- 因果抽象可能因预设标准基而失败。DAS 的核心见解是,如果我们能以各种方式旋转这些表示,可能会发现可解释的结构。DAS 的目标正是学习一个旋转矩阵,以帮助我们找到最优对齐。
我将通过一个简单示例来直观地解释这些概念。
一个运行示例:布尔合取
为了保持直观,我将使用一个非常简单的运行示例:布尔合取运算。
- 左侧是一个因果模型。它接收布尔变量输入,有对应的中间变量,然后输出结果:当且仅当两个输入都为真时输出真,否则为假。
- 右侧是一个非常简单的神经网络模型。该神经网络模型通过这组参数完美解决了我们的布尔合取任务。
这就是我们的起点。
经典因果抽象模式下的问题
在经典的因果抽象模式下,我可以像图中红色箭头那样定义一个对齐关系,这看起来不错。我按预期对齐了输入和输出,并添加了决策规则:如果神经网络输出负值,则对应因果模型的假;如果输出正值,则对应因果模型的真。这很直观。
然后,我直观地将因果模型的中间变量 V1 与神经网络的隐藏单元 H1 对齐,V2 与 H2 对齐。
现在,如前所述,这个模型在行为上是完美的,但它在我们选择的对齐方式下并不抽象神经网络模型,而“选择的对齐方式”这一点至关重要。我直接给出结论:我不小心颠倒了那些内部变量的顺序。我本应将 V1 映射到 H2,将 V2 映射到 H1。
我们通过这个简单示例模拟了一种情况:我错误地决定了我所要查看的对齐集合,并且选择了一个在寻找实际存在的结构方面是次优的对齐方案。
DAS 的承诺是,即使我从这个不正确的对齐开始,一个旋转操作也能帮助我找到正确的结构。
验证因果抽象失败
首先,我来证实因果抽象确实失败了。我将展示一个失败的互换干预。
在顶部,像往常一样,我们用因果模型进行干预。我们从右侧示例中取出 V1,并将其放入左侧示例的相应位置。左侧示例的原始输出是假,但由于干预,我们应该得到输出值真。
当我们在神经网络模型上进行相应的对齐干预时,我们最终得到一个输出状态为负。这意味着预测为假,但因果模型说我们应该预测为真。这正是导致我们说这不处于抽象关系中的那种情况:这个因果模型和这个神经网络模型。
两个模型具有不相等的反事实预测。这是问题的核心。但请记住,我们已经知道原因:由于运气不好或研究不足等原因,我选择了错误的对齐。
DAS 的核心见解
DAS 背后的关键见解是:对齐关系在一个非标准基中成立。
如果我采用当前的网络和当前的对齐方式,并简单地使用这个旋转矩阵旋转 H1 和 H2,那么我将得到一个在行为上完美且满足因果抽象关系的网络。
因果抽象经典模式错过了这一点,正是因为我们选择了标准基。其本质在于,没有理由必须选择标准基。这对我们人类来说是直观的,但没有理由假定我们的神经网络模型更倾向于在那个基中运行。这个例子揭示,通过放弃关于基的假设,我们可能会发现可解释的结构。
因此,DAS 的本质(请关注重点)确实是学习这个旋转矩阵。这是 DAS 学习的目标,然后这个旋转矩阵就成为你可以用来实际发现、展示和评估内部因果结构的资产。
DAS 的高级抽象概述
以下是如何使用一对对齐干预来实现这一点的更高级抽象概述。
- 图中红色部分是我的目标模型。
- 左侧和右侧有两个源模型。它们处理各自的示例,我们将针对模型中这些不同用法所对应的变量 X1、X2 和 X3。
我们做的第一件事是旋转我们锁定的那个表示,以创建一些新变量 Y1、Y2 和 Y3。请记住,这里的 R 是 DAS 的本质,也是我们将要学习的矩阵,本质上是通过互换干预训练来学习。
完成这个旋转后,我然后创建一个新矩阵,这来自于我决定用 Y2 对 Y1 进行干预,然后将 Y3 从这个核心基础示例中复制过来。这给了我这里的新向量。然后我们进行反旋转,并执行干预。
请记住,DAS 的本质是我们将冻结模型参数。这是一种分析方法,而不是改变核心底层目标模型的方法。但我们做的是学习一个旋转矩阵,该矩阵本质上最大化我们通过进行这种旋转和反旋转来创建这些新模型所获得的互换干预准确率。
所以,这是 IIT 类技术与经典因果抽象的结合。我们冻结模型是因为我们想要解释它,但我们学习那个旋转矩阵。这就是 DAS 的本质。

DAS 的现有发现
到目前为止 DAS 的发现。这些在我们的 DAS 论文中相当微妙。
- 我们表明,模型学习到了针对分层相等性任务的真正分层解决方案。事实上,这是我们为本课程笔记本回顾的那个任务。但由于这个非标准基问题,这些解决方案很容易被标准因果抽象所忽略。
- 这是一个更微妙的发现。在早期的因果抽象工作中,我们发现模型学习了词汇蕴含和否定的理论,这些理论与高层次直观因果模型基本一致。但通过 DAS,我们可以揭示它们以一种脆弱的方式做到这一点,实际上保留了词汇项的身份,而不是真正学习到解决蕴含问题的通用方案。
- 第三个发现来自另一篇论文,这非常令人兴奋,因为它表明我们可以扩展到以前由于缺乏搜索对齐方式而无法达到的规模,因为现在我们本质上学习了对齐。因此,我们将 DAS 扩展到了 Alpaca 模型,并发现 Alpaca 这个拥有 70 亿参数的模型实现了一种直观算法来解决数值推理任务。

我认为这只是我们看到的利用 DAS 来理解我们最大、性能最强、最有趣的大型语言模型的潜力的开始。
高级结论与未来展望
现在,让我转向总结一些高级结论。
首先,我想回到这张图,我用它来总体激励分析方法。我们对该领域有这些极其重要的目标:识别批准和禁止的用途,识别和纠正有害的社会偏见,以及保证模型在某些上下文中的安全性。我认为,除非我们对底层模型有分析性的保证,否则我们无法对这些议题提供保证。对我来说,这意味着需要对塑造其输入输出行为的机制有真正深入的因果理解。因此,我认为 NLP 中的分析项目是该领域最紧迫的项目之一。
本着这种精神,让我们稍微展望一下该领域可解释性研究的近期未来。
以下是几个关键方向:
- 寻求因果且人类可解释的解释。正如我所说,我们应该寻求因果解释,但我们也需要人类可解释的解释。如果因果性是唯一要求,我们可以只给出 Transformer 如何工作的低层次机械数学解释,并称之为可解释性研究。但对于试图提供安全性和可信度保证的人类来说,这是错误的层次。我们需要人类可解释的解释。
- 将这些方法应用于越来越大的指令微调 LLM。这些是当前时刻最相关的人工制品。我认为我们正开始通过 DAS 接近这个目标。我刚提到我们如何将其应用于 Alpaca。我认为我们可以扩展得更远,但我们真的希望在探索内容方面不受限制。这需要在该领域进行更多创新。
- 模型正在诱导一种语义学。最后,回到上一个单元以及我们关于认知和组合性的讨论,我认为我们正看到越来越多的证据表明,模型正在诱导一种语义学,即从语言到概念网络的映射。如果它们正在这样做,并且如果我们能找到强有力的证据,那么关于哪些数据驱动的学习过程可以导致语言技术从其经验中实际诱导出语义学,这将极具启发性。这反过来将引导我们走上一条道路,使我们对其行为的系统性有更多的保证,这可能是它们再次变得可信、安全、可靠以及实现该领域和社会所有重要目标的基础。


本节课中,我们一起学习了分布式对齐搜索这一新兴分析方法。我们了解了它如何通过引入可学习的旋转矩阵来克服传统因果抽象方法在对齐搜索成本和标准基假设上的局限性。通过布尔合取的示例,我们直观地理解了其核心思想。最后,我们探讨了可解释性研究对于确保模型安全、可信的重要性,并展望了未来结合因果性、人类可解释性并应用于大型指令模型的研究方向。
38:实验方案概述 📋


在本节课中,我们将学习课程项目中的第二个关键文档——实验方案文档。这份文档旨在帮助你、你的团队成员以及导师,就最终论文的目标和实现路径达成清晰共识。
文档概述与核心理念
上一节我们介绍了文献综述,本节我们来看看实验方案文档。这份文档虽然形式有些特殊,但对于确保项目最终能成功完成至关重要。
其核心理念与文献综述相同,都是为了促进高效对话。我们希望你能与队友、导师以及自己进行有效沟通,明确项目的范围与总体目标。
实验方案的核心组成部分
以下是实验方案文档需要涵盖的几个关键部分,每一部分都旨在推动项目的清晰规划。
-
核心假设
- 你需要尽可能清晰地陈述你的核心假设(或假设群)。这是你实验设计的出发点。
-
数据资源
- 详细说明你将使用的数据资源,并讨论任何潜在的限制,例如数据获取难度、数据生成成本等可能威胁项目数据需求的问题。
-
评估指标
- 明确你将使用的评估指标。对于标准分类问题,这可能很简单(例如报告宏平均F1分数
macro F1)。但如果你在研究一个特殊问题或自创指标,这里则需要更详细的讨论。
- 明确你将使用的评估指标。对于标准分类问题,这可能很简单(例如报告宏平均F1分数
-
模型与方法
- 描述你计划使用的模型或架构。这包括你设定的基线模型、用于对比的模型点以及消融实验设计等。这部分内容需要与你列出的核心假设紧密关联。
-
整体逻辑
- 阐述整个项目是如何整合在一起的。即数据、模型和指标如何共同验证你的假设。这是文档中最需要传达清楚、也最具力量的部分。
-
当前进展总结
- 总结到目前为止的项目进展。请注意,现阶段并不要求你必须得出任何实验结果。这份文档可以纯粹是计划性的。当然,如果你已有结果,汇报出来会非常好,这证明你的项目已具备最小可行性。
文档要求与撰写建议
实验方案是一份简短的结构化报告,用于确立核心实验框架并进行讨论。我们强调“简短”,如果项目进展顺利,它本应是一份短文档。具体要求如下:
- 长度:最大页数为8页,但通常会更短。
- 模板:我们提供了可选的Overleaf模板(基于ACL模板),鼓励使用但不强制。
- 参考文献:与之前一样,必须包含参考文献部分。
关于撰写,有以下几点建议:
- 积极揭示问题:请务必指出你遇到的任何疑虑或障碍,即使是远期可能出现的。这份文档是确保项目能在规定时间内顺利收尾的最后机会,因此宁可多披露一些。
- 假设是必须的:你需要能够陈述一个假设。常有工程师表示“我没有假设,我只想看看这个模型是否适合我的问题”。这本身就是一个假设——只需将其表述为一个关于你认为什么会奏效的论断即可。这将从智力上指导我们,并帮助我们选择基线、设计消融实验等,以验证你的想法。
- 尽早建立完整流程:我们希望你尽快建立一个完整、可运行的项目流程。理想状态是,在任何一天你都能提交一个“可运行”的项目(即使它还不是你最终设想的样子)。达到这个状态后,你将主要专注于添加新的实验结果、分析和报告,从而充实整个项目,这能让你在没有过大压力的情况下进行创造性探索。
额外资源与总结
我准备了一份非常全面的Markdown文档,其中包含了许多常见问题解答、与最终项目相关的各文档讨论、以及过往优秀最终论文(其中一些后来已发表为出版物)的示例等。如果你在如何开展项目方面需要关键指导,我强烈推荐查阅这份文档。
最后,如果你的课程论文最终得以发表,请务必告诉我。在你的允许下,我很乐意将其加入源自本课程工作的已发表论文列表中。我为这个列表的长度和多样性感到非常自豪。😊

本节课中,我们一起学习了实验方案文档的目的、核心组成部分以及撰写要点。这份文档是项目成功的关键规划工具,旨在通过清晰的沟通和问题预判,确保你的研究路径坚实可靠。
39:方法与度量概述 🧭



在本节课中,我们将探讨自然语言处理项目中的核心方法论与评估度量。我们将了解如何为项目做出明智的实验设计、数据管理和度量选择决策,并讨论当前领域面临的挑战与未来的发展方向。

课程目标与当前问题
首先,我们来概述本系列课程的目标以及当前NLP研究领域在方法与度量上面临的一些普遍问题。
我们的根本目标是帮助你顺利完成项目,在实验、数据、度量等方面做出明智选择。同时,本课程也旨在成为你在面对艰难研究决策时可以信赖的伙伴和参谋。
关于课程材料,我们提供了一个关于评估度量的大型实践笔记,让你可以亲手操作我在视频中概述的一些详细技术内容。此外,课程网站还嵌入了关于如何更广泛地思考AI模型评估的优秀页面。我们还有一个内容广泛的实践笔记,让你可以动手操作我们将要讨论的方法论内容,并通过实验来验证我将在这里作为一般经验分享的一些观点。
在阅读材料方面,虽然相关文献比硬科学和行为科学领域要少得多,但这可能表明我们的领域仍在发展中。本单元的目标就是为这些构成我们领域基础的关键事项提供更系统的指导。
项目评估的核心原则
上一节我们介绍了课程的整体目标,本节中我们来看看评估项目时一个至关重要的原则。
关于我们如何看待你的项目,首先要说明一件非常重要的事:我们永远不会根据结果的“好坏”来评估你的项目。这里的“好”通常意味着在排行榜上名列前茅或类似的标准。
我认识到该领域的学术出版机构确实这样做,其理由是它们有版面限制,这导致它们更倾向于发表关于新进展的积极结果,而非消极结果。但这对科学文献是一种扭曲,并且绝对最终会阻碍进步,因为消极结果在指导人们将精力投向何处(特别是何处不应投入)方面可能非常强大和有用。
对于我们这门课程而言,我们不受任何关于可以发表什么内容的真实或想象的限制。因此,我们可以做正确且有益的事,即同等重视积极结果、消极结果以及介于两者之间的一切。
这意味着,根据你自己的实验,你可能在排行榜上名列前茅。但如果你的报告很肤浅,没有真正解释那个数字是如何得出的或其背后的思考过程,你也不会得到好成绩。更重要的是,反过来,你可能尝试了一些非常有创意和雄心勃勃的东西,它可能失败了。但这可能是一项杰出的贡献,因为你在我们真正关心的事情上非常谨慎,这些事包括:度量的适当性、方法的严谨性,以及论文在多大程度上公开、清晰地认识到其发现的局限性。
这是该领域一个可喜的趋势,我们越来越强调找出我们想法的外部局限性,并在论文中描述这些局限性。我鼓励你们也做类似的事情。总的来说,这类工作将引导你获得更富有成果的系统、更有价值的成果和更高质量的论文。
因此,我对这一点感到非常满意。我们可以在下一单元讨论如何应对与这种发表偏见相关的棘手问题。我认为从根本上说,我们也能在这方面做得很好。
你需要转变的视角是:从将论文视为一场偏袒你所选系统的竞赛,转向将论文视为仅仅是公开评估科学假设,并尽可能多地收集证据来为这些假设提供信息。一旦你进入这种模式,你就不再考虑如何挑选赢家,而是思考证据的强度和假设的重要性。这样我们就能达到目标,每个人都会因此更快乐。但这确实需要我们摆脱经常听到的、以竞争为导向的规范,进行视角的转变。
方法论的演变与困境
上一节我们明确了项目评估的价值导向,本节中我们来看看具体的研究方法在过去十几年间发生了怎样的变化,以及我们面临的困境。
我将这部分内容放在“时代如何变迁”的标题下。不幸的是,我在这里没有太多令人愉快的经验可以传授。
让我们把时钟拨回到2010年左右。在那个时代,你可以在训练数据的微小样本上开发完整的系统。一旦系统运行起来,你将仅使用训练数据进行常规的交叉验证。这是一个非常理想的实验环境。你只会偶尔在保留的开发集上进行评估,以避免在该开发集上进行“爬山”优化并最终对其过拟合。这就是为什么你在那里会非常谨慎。然后,在项目的最后阶段,你将使用开发数据进行一轮完整的超参数调优,选择最佳模型,运行最终的测试评估,并或多或少地直接报告那个数字。
那是2010年。作为我们领域的科学图景,这其中有某种深刻正确的东西。但不幸的是,时代已经变了。
在2023年,你仍然可以像以前一样在数据的微小样本上开发你的系统,这很好。然而,对于第二步,要么你的任务没有训练数据,要么在其上进行交叉验证将花费2万美元并耗时六个月。因此,就我们理想的科学图景而言,我们已经偏离了轨道。与此相关的是,开发集对于优化过程经常至关重要。因此,你必须祈祷它确实是测试集的绝佳代理,因为毕竟,你将把所有优化过程都导向这个开发集。最后,对于最终阶段,要么超参数调优将花费10万美元并耗时10年,要么没有超参数,但每次测试运行要花费4000美元,因为你在调用OpenAI模型之类的东西。
这看起来难以为继,对吧?我们该怎么办?
前一时代的核心原则仍然是合理的。正如我所说,我喜欢它们。它们有真正的好处,但我们无法强制执行它们。强制执行已经变得不可能。如果我们只这样做,那么只有最富有的组织才能遵循它们,这将以一种可怕的方式限制该领域的参与。如果你要创建一个排名列表,你必须将广泛参与置于所有这些我们过去在每台消费级笔记本电脑上都能快速训练模型时能够侥幸使用的、非常理想化和规范化的方法之上。
因此,你必须做的是阐明你的方法及其背后的原理,包括资源限制等实际细节以及你不得不采用的启发式方法。
然而,有两条规则在这里应该绝对保持不变。我对此非常坚持。
第一,你永远不要基于测试集评估(即使是非正式地)进行任何模型选择。我知道该领域有人违反这条规则,但不要走那条路。这对我们来说非常重要,特别是当我们考虑到我们可能部署系统的高风险场景时,我们需要原始的测试评估,以诚实地了解我们的系统在未见示例上的表现。一旦你基于测试集数字选择模型,你就完全破坏了这一点。
第二,当你考虑构建基线、进行消融研究以及与文献进行比较时,你必须努力为你评估的所有系统提供成功的最佳机会。你永远、永远不应该偏袒你倡导的系统。我们都知道可以这样做。所有这些模型都有超参数,你可以为你反对的模型选择非常糟糕的设置,并为你喜欢的模型努力寻找最优设置。通过这种方式,你似乎赢得了某种竞赛,但你却损害了你项目的基础。
相反,你需要做的是给每个系统最好的机会,努力让它们都具有竞争力。结果将是更好的、你可以信赖的科学成果。最终,如果你对这条规则也同样严谨,你将在该领域走得更远。
评估度量的现状与展望
上一节我们讨论了研究方法面临的挑战,本节中我们转向评估度量,在这方面我可以更乐观一些。
我将这部分内容放在“时代应如何改变”的标题下,我确实感觉它们正在以令人愉快的方式迅速改变。
我们在这里可以牢记的总体思想是古德哈特定律:当一个度量本身成为目标时,它就不再是一个好的度量。我们必须警惕古德哈特定律,必须保持警惕,确保我们不会落入这个陷阱。
在这种背景下,我总是会想到排行榜。排行榜是该领域运作方式的核心。我们都思考它们,并将其用作进步的标志。它们确实有其好的一面。排行榜可以成为客观比较的基础,这为即使是看似疯狂的想法提供了被倾听的机会。在没有排行榜的领域,这些疯狂的想法经常被社区直接拒绝,没有任何评估。而至少排行榜给了我们领域的人们一个参与的机会。
这是好的一面。然而,坏的一面是,排行榜可能变得非常糟糕。我们经常将基准改进与实际进步混为一谈,而事实上我们知道基准可能是有缺陷的。与此相关的是,我们将基准与经验领域混为一谈。人们会说诸如“OCR解决了”、“问答解决了”之类的话。他们真正的意思是某些基准被解决了。我们现在都意识到,关于基准和能力的这两个主张是截然不同的,但人们仍然将它们混为一谈。甚至在我们说话的方式中,我经常发现我们犯有第三种错误,即将基准性能与能力混为一谈。我们看到一个系统在SQuAD问答上表现良好,就假设它是一个好的问答系统,尽管我们心里知道这两者是非常不同的。
这就是排行榜的坏处。我认为我们未来应该做的是思考如何引入更多好的方面、更多维度的优点,并减少对这些我们经常做出的糟糕假设的依赖。
这里的根本问题,我想说的是,你选择的度量(包括那些嵌入在排行榜中的度量)实际上与你试图解决的问题紧密相连。而在该领域,我们往往没有真正建立这种联系。
让我为你提供一些场景,它们应该能让你思考,如果考虑到不同的度量,你会如何以不同的方式处理这些问题。
以下是需要考虑不同度量的场景示例:
- 场景一: 假设你处于一个错过安全信号会付出生命代价,并且人工审查可行的场景中。你会青睐哪种类型的度量来评估系统?
- 场景二: 相反,假设需要在一个海量数据集中找到范例。在这种背景下,你会使用哪种度量来评估系统?
- 场景三: 假设特定的错误是致命的,而其他错误几乎无关紧要。现在,你需要一个度量,能以不同的方式对不同类型错误和良好预测给予奖励和惩罚,以体现这些基本理念。
- 场景四: 假设需要对案例进行优先级排序。你谈论的不再是分类,而是排序。同样,你应该有好的排序度量。
- 场景五: 假设解决方案需要在老化的蜂窝网络上运行。那么,你对准确性的执着应该让位于能够在非常受限的硬件上运行的系统(低能耗、低功耗、非常快等)。
- 场景六: 假设解决方案不能为特定群体提供更差的服务。标准的机器学习模型通常会偏向多数群体。如果你的最终目标是确保系统在各群体间公平,你将不得不改变你的度量标准,甚至可能改变围绕优化的基本实践。
- 场景七: 假设必须绝对阻止特定的预测。现在你进入了一个完全不同的领域,某些类型的错误代价无限大,而其他错误几乎无关紧要。这又是一个与常规非常不同的场景。
在该领域,可悲的是,科学文献似乎为几乎每个场景提供了一个答案:使用F1和相关准确率度量作为系统性能的衡量标准。
如果你回顾这个列表,你会发现F1不适用于其中任何一个场景。F1只是我们作为研究者在没有应用领域信息时做出的选择。当我们有信息时,我们应该根据这些具体场景定制我们的度量标准。但这几乎从未做过。我担心我们向世界投射的教训是“你不需要费心”。我们不做,而我们被认为是专家。那么为什么其他人要做呢?尽管作为专家,我们可以看到这些不同的场景需要非常不同的度量。
与此相关的是,如果你对科学文献进行调查,你会发现一种对性能(准确率、F1等)的普遍痴迷。Birhane等人2021年的论文《机器学习研究中编码的价值观》很好地支持了这一点。我将他们的证据提炼成一个卡通化的图景,我认为这抓住了本质。我使用字体大小来传达他们发现编码在我们文献中的价值观。毫不奇怪,性能以最大的字体占据主导地位,压倒了我们可能希望反映在我们研究中的所有其他价值观。
紧随其后但差距相当大的第二位是效率。然后是可解释性,但请注意,这是针对研究者的可解释性。我们在这门课中可能也犯了这种错误,上一单元讨论的可解释性工作非常侧重于技术消费者。适用性、鲁棒性、可扩展性也有较好的体现。然后,我使用了不同且更浅的字体来反映在这个排名中非常遥远的事物:针对用户的可解释性、仁慈、隐私、公平、正义。我们都认识到这些是成功NLP系统的关键方面。但它们很少反映在我们关于假设和系统评估的实践中。真的,如果有人只是消费我们的文献,他们从中得到的,再次是,对准确性和相关性能概念的痴迷。
因此,我们应该抵制。我们应该以我们使用的度量形式提升其中一些其他价值观。幸运的是,已经有这方面的努力。我将其放在“多维排行榜”的标题下。我参与了一项努力——DynaBoard。还有Don Bench和Explainaboard。这些都是为我们的系统提供更多维度评估,以获得关于实际发生的更丰富图景的努力。
在这种背景下,我想提一下Dynascore。我认为这是一种非常强大的方式,可以引入多个度量,甚至允许系统背后的人决定在多大程度上青睐哪些度量。它是一个如此强大的度量,以至于我实际上为你提供了一个实现Dynascore并提供一些使用技巧的笔记,这样你也可以探索使用Dynascore来综合你所测量的多个方面。
让我给你一个感觉,为什么这可能如此强大。我这里有一个真实的问答系统排行榜。根据我的Dynascore,DeBERTa模型排名第一。那个Dynascore是通过给予性能很大权重,然后给予吞吐量、内存、公平性和鲁棒性相等权重创建的。
然而,使用Dynascore,我可以调整这些权重。假设我决定我真的想要一个高性能且公平(根据我的公平性度量)的系统。因此,我调整Dynascore,给予公平性5倍权重,并相应降低吞吐量、内存和鲁棒性的权重。那么,之前排名第一的系统现在变成了第二,而ELECTRA-large成为了第一。当然,对我这里不同度量的不同加权会以其他方式调整排名。这表明没有唯一真实的排名,只有相对于我采取的不同优先级、价值观和测量的排名。这就是Dynascore的本质:透明地展示这些价值观,并在传统的排行榜中反映它们,就像我们在这里做的那样。
对图灵测试与人类性能评估的反思
上一节我们探讨了多维评估的重要性,本节中我们来看看两个经典的评估概念:图灵测试和人类性能基准,并反思其局限性。
在这种背景下,当我们谈论评估和不同度量时,人们常说,等等,这些都太技术性、太定制化、太复杂了。我们应该做的是更像图灵测试的事情。毕竟,在某种意义上,那是终极测试。这里的想法是,一个人和一台计算机进行交互,然后人试图弄清楚那是计算机,而计算机则尽其所能欺骗那个人。通过这种方式,我们应该对系统的整体质量和智能等有一个良好的诊断。
我只想在这里发出一个警示。
第一个有记录的图灵测试出现在Sheber 1994年的报告中。在那个测试中,莎士比亚专家Cynthia Clay三次被误分类为计算机,理由是没有人能知道那么多关于莎士比亚的知识。这是一个人们并不真正了解人类经验全部范围和普遍性的例子。
相反,这是另一个滑稽的故事。2014年,一个非常简单的名为Eugene Goostman的AI通过了图灵测试。它是怎么做到的?它通过采用一个13岁男孩的人格做到了这一点。当它粗鲁或显得心不在焉(因为它对人类试图做的事情感到困惑)时,人们只是将其归因于13岁男孩经常有点粗鲁和心不在焉。通过这种方式,它轻松过关。
Google Duplex是一个真实的、复杂的AI系统,它是一个经常运行并赢得与服务人员图灵测试的AI。它打电话,即使它依法在对话一开始就宣布自己是AI,人们也常常忘记这个信息,并相信他们正在与计算机交谈。
与此相关的是,既然我们已经进入了进行大量自然语言生成的模式,我们都发现人们不擅长区分人类书写的文本和来自我们最好的大语言模型的文本。
因此,通过这种方式,特别是Duplex和LLM的故事,我们应该反思这样一个事实:我们所有人可能在某些情况下不断未能通过图灵测试,在某些情况下是与复杂的AI,但在某些情况下是与实际上相当简单的AI。关于社交互动的一些认知偏见使得这不是一个非常可靠的测试。
在评估的背景下,我们应该思考的另一个维度是我们如何估计人类性能。我在这里的总结是:我们通过强迫人类执行机器任务来估计人类性能,然后说这就是人类的实际表现。
让我在自然语言推理的背景下给你一个例子。想象一下你是一个众包工作者。你被要求为“前提-假设”对标注它们是中性、蕴含还是矛盾。你接受了一点培训。培训后,你看到,“一只狗在跳”和“一只穿着毛衣的狗”。这两者彼此是中性关系,因为我们从“跳”中不知道它是否穿着毛衣。没有关系。
然后你看到例子“乌龟”和“语言学家”。你想,嗯,我可以在某个可能的世界里想象乌龟语言学家,但我被告知这是一个常识推理情境。所以我会说矛盾,因为“没有真正的乌龟是语言学家”似乎是一个安全的假设。
但然后你看到一张赛马的照片和一张运动员的照片,你被要求分配一个标签,你想,嗯,我以前没怎么想过这个。赛马能是运动员吗?一般来说,动物能是运动员吗?你可能决定对此有固定的看法。也许你说,当然,赛马可以是运动员。或者,当然不是。但真正根本的是,你可能不确定其他人对此的看法。反过来,你可能对你应该分配什么标签感到不确定。人类的方式是讨论和辩论,以弄清楚为什么问这个问题,以及人们对此相关问题有什么想法。但我们所做的却是阻止所有这些互动,简单地强迫众包工作者选择一个标签,然后我们实际上会惩罚他们,惩罚的程度取决于他们没有选择其他人选择的标签,尽管我们所有人都感到不确定。
这是另一个例子:“一位厨师在使用烧烤架”和“一个人在使用机器”。烧烤架是机器吗?我认为这可能取决于情境、目标、假设等所有因素。人类的方式是讨论这些不确定点,然后分配一个标签。但当我们进行众包时,我们只是阻止了这一点。
所以现在,当你听到“人类性能的估计”时,你应该记住,人类可能不被允许做大多数人类会做的事情,比如“让我们讨论一下”。因此,这些背景下的人类性能实际上意味着匆忙的众包工作者重复执行机器任务的平均表现。
我们都可以做这种心理简写,但当然,在现实世界中,人们听到“人类性能”,会想到最重大意义上的人类性能。我们应该意识到这不是真的。我们应该抵制这种假设,即当我们实际上这样做时,这就是我们的本意。
我们真正寻求的评估度量是什么?
上一节我们反思了传统评估方式的局限,本节中我们总结一下,在评估度量方面,我们真正应该追求的是什么。
我会说,我们寻找的是介于标准旧评估之间的东西。
“一个系统能否在友好的测试中比执行相同机器任务的人类更准确?”——这是我对我标准评估的略带讽刺的转述。
但我们也不想转向“一个系统能否在开放式对抗性交流中表现得像人类?”——那是图灵测试。它是一个非常特殊的东西,而且非常棘手。
在这两者之间,有很多富有成效的东西。
本着我们之前单元的精神,我们可以问:
- 系统性: 一个系统能否行为系统化,即使它不准确?这可能是一个我们最终可以信任的系统,即使它目前表现不佳。
- 置信度评估: 一个系统能否评估自己的置信度,知道何时不做预测?我们AI中的系统过去会在每个未预料到的输入上失败。现在,无论你扔给它什么,它似乎都自信地给出一个答案。我们需要改变这一点。我们需要系统在不确定信息是否良好时保留信息。
- 终极目标: 也许从根本上,我们应该问,一个系统能否让人们更快乐、更高效?这将使我们远离自动评估,转向更像人机交互评估的东西。但最终,我觉得这是我们的目标,我们不妨就设计面向它的评估。
正如我所说,我对这一切充满希望。我认为时代应该改变,而且它们正在改变。


昨天的评估(
40:分类器评估指标 📊

在本节课中,我们将深入学习分类器评估指标。上一节我们介绍了方法与指标的高层主题,本节我们将深入探讨分类器评估的具体技术细节。

概述

不同的评估指标体现了不同的价值取向,因此选择指标是实验工作的关键环节。你需要结合假设、数据和模型来做出明智的指标选择。即使是在拟合看似简单的分类器时,也应根据目标来定义新指标或调整现有指标的使用方式。
对于成熟的任务,通常会存在使用特定指标的压力,例如排行榜或先前文献中使用的指标。但如果你认为有必要,也应该勇于提出质疑。毕竟,研究领域可能因指标选择不当而停滞不前。
混淆矩阵
让我们从混淆矩阵开始,这是许多计算的基础。作为一个示例,我将使用一个三元情感分类问题。行代表真实标签,列代表预测标签。
例如,这个混淆矩阵显示,有15个真实为“积极”的样本被系统预测为“积极”,而有100个真实为“积极”的样本被系统预测为“中性”。
需要强调的是,这些分类预测很可能基于一个阈值,特别是对于概率分类器。模型输出的是各类别的概率分布,然后应用某个决策规则来确定最终的预测类别。
显然,不同的决策规则会产生截然不同的结果表。此外,值得关注的是“支持度”,即每个类别在真实数据中的样本数量。在我们的示例中,数据是高度不平衡的,这在选择合适指标时是一个重要因素。
准确率
准确率是正确预测数除以总样本数。给定一个混淆矩阵,这意味着我们对角线上所有元素求和,然后除以表中所有元素的总和。
准确率的取值范围是0到1,0最差,1最好。准确率体现的价值很简单:系统正确的频率。
这引出了两个弱点。首先,没有针对每个类别的指标。其次,它完全无法控制类别大小的影响。准确率只关注你猜对的原始次数,而不敏感于系统中的不同类别以及系统对这些类别的预测方式。
我们的示例表很好地说明了这可能存在的问题。本质上,所有真实案例都是“中性”,所有预测也都是“中性”。因此,系统在“积极”和“消极”类别上的表现对准确率影响微乎其微,因为准确率完全由“中性”类别的表现主导。
如果你确实有在最小类别上也表现良好的目标,我将为你介绍一些指标。但请记住,如果你使用交叉熵损失,你实际上是在隐式地优化模型的准确率,因为准确率与负对数损失(即交叉熵损失)成反比。
精确率
为了摆脱原始准确率的局限,第一步是引入精确率。
类别K的精确率是K类正确预测数除以所有被预测为K类的样本数。我们在这里按列操作。
以下是“积极”类别的精确率计算示例:
公式:
精确率(K) = 正确预测为K的数量 / 所有预测为K的数量
精确率的边界是0和1,0最差,1最好。需要注意的是,当分母为0时精确率未定义,通常我们将其映射为0。
精确率体现的价值是惩罚错误的猜测。其弱点是,你可以通过很少预测类别K来获得该类的高精确率。如果你对这个类别的预测非常谨慎,你很可能会获得高精确率,但这不一定是我们想要体现的全部价值。
召回率
通常,我们用召回率来平衡精确率。
类别K的召回率是K类正确预测数除以所有真实为K类的样本数。我们在这里按行操作。
以下是“积极”类别的召回率计算示例:
公式:
召回率(K) = 正确预测为K的数量 / 所有真实为K的数量
召回率的边界是0和1,0最差,1最好。
召回率体现的价值是惩罚遗漏的真实案例。它与精确率形成一种对立。其弱点是,我们可以通过总是猜测K来获得该类的高召回率。如果我想确保不遗漏任何样本,我就会不断猜测K,以增加不错过的机会。
现在你可以非常直接地看到,我们应该用精确率来平衡召回率,因为它施加了相反的价值。这通常是F分数(通常是F1分数)的动机。
F分数
原则上,我们可以有一个权重参数beta来控制我们偏向精确率和召回率的程度。同样,无需盲从。有些场景精确率重要,有些场景召回率重要。你可以使用beta来使你的指标与你高层的价值取向保持一致。但默认情况下,beta为1,表示均衡。
F1分数是精确率和召回率的调和平均数。这可以是一个针对每个类别的概念。
以下是每个类别的F1分数计算示例:
公式:
Fβ = (1 + β²) * (精确率 * 召回率) / (β² * 精确率 + 召回率)
F1 = 2 * (精确率 * 召回率) / (精确率 + 召回率)
F1分数的边界是0和1,0最差,1最好,并且它总是作为精确率和召回率的调和平均数介于两者之间。
F1分数体现的价值类似于:类别K的预测与K的真实实例在多大程度上对齐,beta控制着精确率和召回率的权重。因此,它有点像精确率和召回率都融入了这个“与真实对齐”的概念中。
其弱点是:没有对数据集大小进行归一化;它忽略了K所在行和列之外的所有值。例如,在计算“积极”类别的F1时,我不关注其他单元格的值,无论那些非对角线元素中有多少样本。这是一种结构性的偏差。
F分数的平均方法
我们可以用多种方式对F分数进行平均,我将讨论三种:宏平均、加权平均和微平均。
宏平均
这是该领域最主要的选择。原因是我们作为NLP研究者,倾向于关心类别本身,无论其大小。甚至,我们通常更关心小类别,因为它们可能更有趣或更难。
宏平均就是对这些数值进行简单的算术平均。
公式:
宏平均F1 = (F1(类别1) + F1(类别2) + ... + F1(类别n)) / n
其边界是0和1,0最差,1最好。它体现的价值与F分数相同,外加一个假设:所有类别无论大小或支持度如何都是平等的。
其弱点是:一个只在小类别上表现良好的分类器在现实世界中可能表现不佳;一个只在大类别上表现良好的分类器可能在重要的小类别上表现很差。
加权平均F分数
这是一种考虑总支持度的直接平均方法,即对三个F1分数进行直接的加权数值平均。
公式:
加权平均F1 = Σ (支持度(类别i) * F1(类别i)) / 总支持度
其边界是0和1,0最差,1最好。它体现的价值与F分数相同,外加一个假设:类别大小确实重要。因此,这会更像准确率。
其弱点当然是,大类别将严重主导结果,我们又回到了准确率所具有的弱点。
微平均F分数
微平均的做法是:为每个类别形成其自己的二元混淆矩阵,然后将它们加在一起,得到一个单一的二元表。
其属性同样是边界0和1,0最差,1最好。它体现的价值与准确率完全相同。如果你关注最终构建的那个表中的“是”类别,它完全等同于准确率。
因此,其弱点与F分数相同,外加一个“是”分数和一个“否”分数,这有点烦人,因为你怎么处理“否”类别?你必须关注“是”,而“是”那个毕竟就是准确率。据我所知,这是唯一一个大家都关注的数字。
总的来说,我认为在这一点上,你可以忽略微平均F分数。你仍然会在文献和scikit-learn的结果表中看到它们,但总的来说,基本上就是:用宏平均来抽象掉类别大小的影响,或者用加权平均来将总体类别大小作为指标的一个要素。这是我建议未来使用的两种方法。只有在完全平衡的问题中,你才应该回到准确率,因为那时类别大小不会成为干扰因素。
超越单一决策边界
最后,我想回到开始时的一个观察:我们总是需要强加一个决策边界,这有点令人烦恼。对于精确率和召回率,我们也必须做同样的事情。我们可以用不同的方式思考这个问题。
例如,我们可以有精确率-召回率曲线,这允许我们探索在给定决策边界下,系统可能进行预测的所有可能方式。这提供了关于这两种压力之间权衡的更多信息,并且可以使人们更容易地将系统选择与他们对系统的潜在价值取向对齐。
我知道要求这样做是不切实际的,因为该领域相当关注单一汇总数字,但我认为思考精确率-召回率曲线以获得更多信息可能很有趣。然后,如果我们确实需要选择一个单一数字,平均精确率是对这条曲线的总结,它再次避免了关于如何权衡精确率和召回率的决定,并带来了更多信息。你会认出这类似于我们在信息检索背景下所做的平均精确率计算,它同样提供了关于系统表现的非常细致的解读。
总结


本节课我们一起学习了分类器评估的核心指标。我们从混淆矩阵出发,理解了准确率、精确率、召回率和F分数的定义、计算、价值取向及各自的优缺点。我们还探讨了宏平均、加权平均和微平均这三种对F分数进行平均的方法,并了解了它们适用的场景。最后,我们思考了超越单一决策边界、使用精确率-召回率曲线来获取更丰富系统信息的可能性。理解这些指标将帮助你更好地评估和优化你的分类模型。
41:生成评估指标 📊

在本节课中,我们将学习用于评估自然语言生成系统性能的各种指标。生成任务的核心挑战在于,表达同一件事通常有多种有效方式,这使得评估变得复杂。我们将从困惑度开始,逐步探讨基于参考文本的指标、无参考指标以及面向任务的评估方法。
困惑度:生成任务的“准确率” 📈


上一节我们讨论了分类器指标,本节我们来看看生成任务的基础指标——困惑度。困惑度可以被视为生成任务中“准确率”的类比。
困惑度的定义如下:对于一个序列 X 和一个能够为其分配概率的模型,该序列的困惑度是该模型分配给序列中各个时间步概率的几何平均数。
公式:
困惑度(X) = (∏_{t=1}^{T} P(x_t | x_{<t}))^{-1/T}
在评估整个语料库时,我们计算所有序列困惑度的几何平均数,得到平均困惑度。
困惑度的特性:
- 范围:1 到无穷大,1 为最佳(我们希望最小化此值)。
- 本质:它等价于交叉熵损失的指数化。由于现代语言模型普遍使用交叉熵损失进行训练,这意味着我们实际上是在针对困惑度进行优化。
- 评估含义:困惑度衡量的是模型为输入序列分配高概率的程度。评估时,我们在评估集上运行模型,计算平均困惑度,并将该数值作为系统质量的估计。
困惑度的弱点:
- 依赖词汇表:困惑度严重依赖于底层词汇表。例如,若将所有词元映射为同一个未知字符,困惑度会变得完美,但生成系统会非常糟糕。
- 无法跨数据集比较:我们无法脱离数据本身定义“好”或“坏”的困惑度标准,因此比较不同数据集上的困惑度数值如同比较不可比之物。
- 模型间比较困难:进行模型间比较时,必须确保分词方式、数据集等众多因素保持一致,否则比较可能无效。
词错误率:对齐参考文本 🔤
词错误率可能比困惑度更好,因为它更紧密地对齐了人工创建的参考文本,这在评估思路上是一种进步。
词错误率是一类指标的总称。你需要选择一个字符串间的距离度量(如编辑距离),词错误率则由该距离度量参数化。
计算方法:
对于参考文本 X 和预测文本 pre,词错误率 = 距离(X, pre) / len(X)。
在语料库层面,分子是所有(参考文本,预测文本)对距离的总和,分母是所有参考文本的总长度。
词错误率的特性:
- 范围:0 到无穷大,0 为最佳(我们希望最小化此值)。
- 评估含义:它衡量预测序列与真实序列的对齐程度,在选择距离度量后,其思路类似于 F 分数。
词错误率的弱点:
- 仅容纳单一参考文本:这与“表达方式多样”的根本挑战相悖,因为它只能容纳一种(假设是好的)表达方式。
- 默认是句法概念:大多数距离度量(如字符串编辑距离)对字符串的具体结构非常敏感。因此,从语义上看相近的句子(如“It was good.” 和 “It was great.”)与语义相反的句子(如“It was not good.”)可能被计算为相似的“距离”。
BLEU 分数:平衡精确率与召回率 ⚖️
BLEU 分数建立在词错误率的直觉之上,试图更好地应对“表达方式多样”的挑战。
以下是 BLEU 分数的工作原理。它同样是精确率与召回率的平衡,但针对生成任务进行了调整。
修正的 N 元语法精确率:
这是 BLEU 中的精确率概念。我们通过一个简单例子来理解:假设候选文本是七个连续的“the”,这显然不是一个好候选。我们有两个参考文本。
对于词元“the”,其修正的 N 元语法精确率是 2/7。因为候选文本中有 7 个“the”,而参考文本中“the”出现次数最多的是 2 次(来自参考文本1)。
简短惩罚:
为了平衡精确率,BLEU 引入了简短惩罚。其本质是:如果生成的文本短于语料库的期望长度,系统会受到惩罚。一旦达到期望长度,则停止惩罚,主要依赖修正的 N 元语法精确率。
BLEU 分数:
BLEU 分数是简短惩罚得分与各 N 元语法(如一元、二元、三元)的加权修正精确率之和的乘积。
BLEU 分数的特性:
- 范围:0 到 1,1 为最佳。对于自然数据,我们并不期望任何系统能达到 1,因为理论上我们无法拥有所有相关的参考文本。
- 评估含义:它编码了一种(我们希望是)恰当的精确率与召回率的平衡。
- 与词错误率的关系:它与词错误率相似,但试图容纳“对于给定输入通常存在多个合适输出”这一生成任务的根本挑战。
BLEU 分数的弱点:
- 与人工评分相关性存疑:有大量文献指出,BLEU 在翻译(其重要应用领域)任务上与人工评分的相关性不佳。
- 对 N 元语法顺序敏感:这使得它非常关注比较中的句法元素。
- 对 N 元语法类型不敏感:这仍然是字符串依赖性的体现。例如,“that dog”、“the dog”和“that toaster”在 BLEU 评分中可能被同等对待,尽管前两者在语义上显然更接近。
- 需谨慎考虑应用领域:BLEU 可能与特定领域的生成目标不匹配。例如,在评估神经对话代理时,有研究反对使用 BLEU 作为指标。
因此,需要仔细思考你的生成任务目标、拥有的参考文本类型,以及它们是否与你的高级目标一致。
其他基于参考文本的指标 🧩
上文提到的词错误率和 BLEU 都是基于参考文本的指标,因为它们依赖于人工创建的参考文本。这个家族中还有其他成员,例如 ROUGE 和 METEOR。
以下是这些指标的发展趋势:
- 特别是 METEOR,它试图更面向任务(如摘要),并且对参考文本和生成文本的细粒度细节不那么敏感,以捕捉更多语义概念。它通过词干还原和同义词匹配来实现这一点。
- 随着 CIDEr 和 BERTScore 等评分方法的出现,我们实际上进入了向量空间模型,希望能捕捉语义的深层方面。
- CIDEr 使用 TF-IDF 向量。
- BERTScore 使用词元级别的加权最大值来定义两个文本之间的分数,这是一个非常语义化的概念。其评分过程与 ColBERT 检索模型使用的过程非常相似。
可以看到,特别是 BERTScore,我们正试图摆脱字符串的所有细节,真正切入意义的更深层方面。
基于图像的 NLG 指标 🖼️
有些系统以图像作为输入并生成文本,我们需要评估生成的文本是否适合该图像。
对于此任务:
- 基于参考文本的指标(如 BLEU 和词错误率)在存在人工标注且这些标注与你的生成目标一致时是可行的。
- 无参考指标:但在许多领域和任务中,获取合适的人工标注可能负担沉重。无参考指标旨在无需人工创建的参考文本来评估文本-图像对。目前最流行的是 CLIP Score,此外还有 UIC、SPURTS 等。其愿景是摆脱对人工标注的依赖(这是评估的主要瓶颈),直接独立地评估这些图像-文本对。
我们认为无参考指标前景广阔。然而,我们也有研究指出,当前的无参考指标对文本的目的和图像出现的上下文不敏感,而这些在图像描述生成的目标中是至关重要的方面。不过,我们乐观地认为,可以设计 CLIP Score 及相关指标的变体,将这些质量概念纳入其中。因此,无参考指标可能是基于图像的 NLG 评估的一条富有成果的前进道路。
面向任务的评估:回归生成的根本目标 🎯
最后,为了完善讨论,我们提出一个更高层次的评论:面向任务的指标。
到目前为止,我们一直非常关注与参考文本的比较和其他内在质量概念。但我们应该反思:当我们进行生成时,通常是为了实现某种沟通目标或帮助智能体采取某种行动。
- 传统基于参考文本的指标:它们只能捕捉到任务的相关方面,前提是人工标注本身包含了这些任务目标。如果你的参考文本没有反映生成的目标,那么评估也不会反映。
- 面向任务的模型指标:可以想象针对特定任务进行调整的模型指标,但这目前还非常罕见。
我们认为,思考文本的目标并考虑评估是否可以基于该目标,这是一种富有成果的新思维方式。
评估思路的转变:
你可以问自己:
- 任务成功:接收生成文本的智能体能否利用它来完成任务?你的指标就是任务成功率。
- 信息可靠传达:特定的信息是否被可靠地传达了?我们可以直接询问接收消息的智能体是否可靠地提取了我们关心的信息。
- 引导期望行动:消息是否引导接收者采取了期望的行动?这可以是对沟通成功的一种更间接的衡量。
这可以成为我们用于生成评估的基本指标。它会捕捉某些方面(如任务有效性),而忽略其他方面(如流畅度)。但总体而言,你可以想象,这与我们为生成系统设定的实际目标更加紧密地对齐。


本节课总结:
本节课我们一起学习了评估自然语言生成系统的多种指标。我们从基础的困惑度开始,认识到其局限性。接着探讨了基于参考文本的指标,如词错误率和 BLEU 分数,它们试图与人类输出对齐,但仍面临表达多样性的挑战。我们还了解了其他更语义化的参考指标(如 METEOR、BERTScore)以及面向图像生成任务的无参考指标(如 CLIP Score)。最后,我们强调了回归生成任务根本目标的重要性,提出了面向任务的评估思路,这可能是未来更有效评估生成系统的关键方向。选择评估指标时,务必清晰定义你的高级目标。
42:方法与指标(第四部分)数据集 📊



在本节课中,我们将探讨数据集在自然语言处理领域中的核心作用,以及如何有效地构建和使用它们。上一节我们深入讨论了分类器和生成模型的评估指标,现在让我们提升视角,从概念层面理解数据集如何塑造我们的研究进展。
概述:数据集的基石作用
著名海洋学家雅克·库斯托曾说过:“水和空气是所有生命赖以生存的两种基本流体。” 在NLP领域,数据集就是所有进展所依赖的资源。我们使用数据集来优化模型、评估模型、比较模型、通过训练为模型赋予新能力、衡量整个领域的进展,并进行科学探究。可以说,我们在NLP领域所做的一切都依赖于数据集。因此,正确构建和使用数据集至关重要,否则我们的研究基础将不稳固,甚至可能产生对进展的误判。
已故的阿拉文德·乔希曾将数据集比作我们领域的“望远镜”。他指出,NLP研究者就像想看星星却拒绝建造望远镜的天文学家。如今,我们拥有的数据集比以往任何时候都多,这或许会让他感到欣慰。
然而,一个值得关注的现象是“基准饱和速度加快”。下图展示了模型性能随时间(自90年代起)接近所谓“人类表现”的归一化距离。虽然一些人从中看到了快速进步的轨迹,但另一个令人担忧的事实是:图表中没有任何系统在真正意义上达到“超人类”水平。这背后的根本问题可能在于,我们的数据集本身就不足以衡量我们想要衡量的能力。
数据集的局限性
随着时间推移,我们发现数据集局限性的速度越来越快。以宾州树库为例,这个句法解析数据集驱动了数十年的进展。但多年来,只有相对较少的论文指出了其中的解析树错误。
相比之下,2015年发布的斯坦福自然语言推理基准发布后,立即涌现出大量论文,指出了数据集中的伪影、偏见和覆盖缺口等问题。类似的情况也发生在SQuAD问答数据集和ImageNet图像分类数据集上。这标志着一个新时代的到来:如果一个基准取得成功并被广泛使用,人们也会迅速发现其局限性。虽然作为数据集创建者,这可能令人难以接受,但这种对基础工具的批判性质询,本身就是一种健康的进步标志。
为了简洁起见,我将围绕数据集的三个核心问题进行阐述,并在最后列出更多值得思考的方向。
核心问题一:自然数据 vs. 众包数据 🤔
第一个问题是:我们应该依赖从网站抓取或现有数据库中提取的自然数据,还是应该转向众包?我的答案是:两者都用。
以下是两种方法的权衡对比:
自然数据(或称“发现”或“整理”数据)
- 优势:数据量丰富,收集成本可能较低,并且在某种意义上具有“真实性”,因为这些数据并非为实验而创造,而是源于真实的交流目的。
- 劣势:数据集不可控,受限于你在世界中观察到的内容。可收集的信息类型有限,并且可能存在隐私侵犯问题,因为你可能并未获得每位数据贡献者的知情同意。
众包数据(或称“实验室培育”数据)
- 优势:高度可控,因为你可以设定任务。可以保护隐私,确保贡献者知情并有机会退出。具有表达性,原则上可以让众包工作者完成在自然环境中难以观察到的复杂任务。
- 劣势:数据稀缺,永远不够用,且成本高昂。任务可能显得做作,因为工作者是在完成你设定的、非自然的任务,结果可能为了取悦任务发布者而显得不真实。
如何平衡这些因素?我认为可以找到混合模型,兼顾真实性与表达性,最大化优势,最小化劣势。
例如,在Dynabench Round 2项目中,我们设置了两种条件:一种是让工作者从头编写文本来试图欺骗顶级情感模型;另一种是给他们现有句子进行编辑以达到相同目的。编辑条件在保持我们所需结果的同时,提供了更多的自然性。在长度和词汇多样性上,编辑后的结果更接近从Yelp等网站获取的自然句子。这种混合模型在某种意义上让我们获得了两种世界的最佳体验。
核心问题二:对抗样本 vs. 常见案例 📈
第二个问题是:我们应该使用对抗样本,还是仅包含最常见案例的基准?我的答案同样是:两者都用。
回顾一下:
- 标准评估:从一个独立的、与模型无关的过程中创建数据集,并划分为训练集、开发集和测试集。
- 对抗性评估:创建一个单独的测试集,其构建方式旨在挑战你的系统。
- 完全对抗性数据集:训练集、开发集和测试集都通过(通常由人)试图欺骗顶级模型的方式来构建。
目前已有许多覆盖广泛领域的完全对抗性数据集,相关文献表明,尤其是对抗性训练和测试,带来了许多积极成果。
但也存在不同的观点。例如,Bowman和Dahl在2021年的论文中指出,对抗性过滤可能会系统性地消除对任务必要但已被对抗模型很好解决的某些语言现象或技能的覆盖。这种“模式寻求”而非“质量覆盖”的行为,如果不受控制,会降低数据集多样性,从而使有效性更难实现。
我承认这是一个合理的观点,但关键在于“对抗性过滤”这个概念。我并非主张进行过滤。以Dynabench为例,我们的训练集、开发集和测试集都混合了对抗性案例和模型原本能正确处理的案例(即他们所说的“模式寻求”案例)。我主张的是“两者兼顾”的视角。
他们还认为,通过构建一个大规模的基准,就能自然而然地覆盖所有相关现象。我认为这在事实上是不正确的。考虑到语言的复杂性,很难开发出一个大到足以覆盖所有困难案例的基准。而对抗性训练样本的作用,恰恰是帮助我们以更高效的方式填补这些空白。
以情感分析领域为例,我们的模型不仅需要正确处理“食物很好”这样的常规案例,还需要处理复杂的视角转换(如“我妹妹讨厌这食物,但她大错特错”)、非字面语言使用(如讽刺“早餐真好,如果你打算喂狗的话”),以及语言创新(如“值得发出美食的惊叹”)。如果仅进行标准数据收集,你可能根本看不到这些例子,或者密度不足以改进系统。因此,我主张在训练、开发和测试中引入一定程度的对抗性,但避免Bowman和Dahl所担心的过滤操作。
关于对抗性测试,我们目前学到的主要经验有:
- 我们的顶级系统往往找到了非系统性的解决方案,这令人担忧。
- 在挑战集上的进展似乎与整体上的实质性进展相关。
- 现有系统能在不损害通用案例性能的前提下,处理对抗性案例。
- 无论你对对抗性在系统开发中的作用持何观点,当你部署系统时,人们构思并抛向系统的对抗性例子将定义公众对你系统的看法。因此,出于自我保护,我鼓励你在任何部署之前,就为评估考虑对抗性动态。
核心问题三:合成基准 vs. 自然基准 🔬
第三个问题是:应该使用合成基准还是自然基准?我的答案依然是:两者都有其作用。
领域内有一种突出的观点,认为我们只应使用自然基准。从科学层面看,这令我深感忧虑,因为它为我们几乎所有的实验引入了两个未知数:
- 数据集是未知的:我们不完全掌握其结构。
- 模型是未知的:我们正试图探索其属性。
在这种情况下,你有一个无法全面审计、甚至可能不完全理解其创建过程的大规模数据集,将其输入到一个同样是主要未知数的模型中,然后得到输出。问题是:输出中的因果因素是什么?由于存在两个未知数,因果归因变得非常困难。
如果我们能将数据集固定为一个已知量,就可以将输出的某些方面追溯到我们操纵的模型属性上。但有两个未知数在起作用,这始终是不确定的。
让我用一个关于“否定作为学习目标”的例子来说明。我们期望系统知道:如果A蕴含B,那么非B蕴含非A(否定的蕴含逆转属性)。许多论文观察到,顶级NLI模型未能达到这个学习目标。人们很容易得出结论:问题出在模型上——顶级模型似乎无法学习否定。
但我们同时观察到,这些模型所训练的自然基准数据集严重低度表征了否定。现在我们不知道问题究竟出在模型还是数据集上,因为我们有两个未知数。
作为回应,我们创建了一个“略微合成”的基准——单调性NLI。它包含两部分:一个正例部分,我们使用WordNet从现有SNLI假设创建新的例子,以触发系统性的中性B和B蕴含A的案例;一个否定部分,我们对否定例子做了同样处理。替换后,我们得到了这些模式的反转。这个数据集以自然发生的案例为基础,但通过系统性的操作,保证了我们对词汇蕴含和否定有特定类型的表征。
当我们将其用作挑战数据集时,我们获得了深刻的见解。例如,BERT在SNLI上表现极佳,在我们合成基准的正例部分也表现极好,但在否定部分的表现几乎为零——它显然忽略了否定。问题到底是数据还是模型?当我们对负例MonNLI进行少量微调后,模型在该部分的表现立即得到提升。这明确地告诉我们:当向BERT这样的模型展示相关的否定案例时,它能够处理这个任务。
因此,通过拥有一个已知的数据集,我们直接学到了关于模型的知识。当我们转向自然数据时(我强调“当”,因为我认为这很重要),我们知道BERT在原则上能够学习否定,而数据覆盖将是其性能的主要影响因素。这些清晰的分析性经验,正是因为我们允许进行一些合成评估才得以获得。
总结与更多思考方向
本节课中,我们一起探讨了数据集在NLP中的核心作用,并围绕三个核心问题展开了讨论:自然数据与众包数据的权衡、对抗样本与常见案例的结合、以及合成基准与自然基准的互补价值。我的核心观点是,在这些看似对立的选择中,采取“两者兼顾”的混合策略往往能带来更稳健和深刻的见解。
当然,关于数据集还有更多值得深入思考的问题,例如:
- 数据表:为数据集提供披露文件,帮助我们理解如何负责任地使用它们以及其局限性所在。
- 跨语言覆盖:如何实现基准的跨语言覆盖?目前我们对英语的关注仍然过多,而我们需要的是在全球范围内都表现良好的系统和模型。
- 统计功效:我们需要关注数据集的统计功效。
- 社会偏见:我们必须深刻关注数据集中嵌入的有害社会偏见,并思考如何消除它们,以创造更公平的技术。


通过审慎地构建和使用数据集,我们才能为NLP领域的持续进步奠定坚实的基础。
43:数据组织方法 📊



在本节课中,我们将要学习在自然语言处理(NLP)和人工智能(AI)领域中,如何有效地组织数据以进行评估。我们将重点探讨当数据集没有预定义划分时,应如何通过交叉验证等方法来确保评估的稳健性和一致性。
数据划分的常规做法
在NLP乃至整个AI领域,我们通常习惯于将数据集划分为训练集、开发集和测试集。这在大型公开数据集中非常普遍。
这种做法预设了一个相当大的数据集,因为我们几乎从不轻易使用测试集。正如我在该领域反复强调的,我们遵循一个“荣誉体系”:只有在所有系统开发完成后,才能对测试集进行一次性的最终评估。因此,测试集在大部分研究过程中是“上锁”的,这意味着它在科学探究过程中很少被使用。
拥有固定的测试集是有益的,因为它确保了评估的一致性。如果两个模型按照完全相同的协议进行评估,那么比较它们会容易得多。然而,它也有一个缺点:由于我们总是使用相同的测试集,整个研究社区会在这个测试集上进行某种“集体爬山”,后来的论文会从文献中早期的论文间接地学习到关于测试集的信息,这最终会导致性能指标的虚高。
但总体而言,我认为训练-开发-测试的划分方式对NLP领域是有益的。
处理无预定义划分的数据集
然而,如果你在NLP之外进行工作,可能会遇到没有预定义划分的数据集。这可能是因为数据集较小,或者来自不同的领域。例如,在心理学领域,你几乎不会遇到这种训练-开发-测试的方法论。因此,来自该领域、你可能想利用的数据集不太可能有预定义的划分。
这对评估提出了挑战。因为正如我所说,为了进行稳健的比较,我们真的希望所有模型都在相同的评估机制下运行,这意味着为你所有的实验运行使用相同的划分。
对于大型数据集,你可以自己设定划分,然后在整个项目中使用它们。这将简化你的实验设计,并减少你需要进行的超参数优化量。所以,如果可以的话,就自己设定划分,也许可以将其融入NLP中人们思考数据的方式。
但对于小型数据集,强行进行这种划分可能只会给你留下太少的数据。这可能导致系统评估的变异性非常大。要么你用于训练的样本太少,要么用于评估的样本太少,这都会导致评估结果充满噪声且高度可变。在这种情况下,很难做到正确。
交叉验证方法
我认为在这种情况下,你应该考虑使用交叉验证。在交叉验证中,我们取一组样本,将它们划分为两个或多个训练-测试分割。我们进行一系列系统评估,然后以某种方式(通常是取平均值)汇总这些分数,并将其报告为系统性能的衡量标准。
以下是两种主要的交叉验证方法:
1. 随机分割法
第一种方法非常简单,我在这里称之为随机分割。其思想是,对于K次分割(即K次实验),你打乱你的数据集,然后将其分割为T%的训练集和(1-T)%的测试集(以使用所有数据),然后进行一次评估。你重复这个过程K次,得到一个分数向量,然后以某种方式汇总这些分数。通常你会取平均值,但你也可以考虑平均值加上置信区间,或者某种统计检验,来告诉你两个系统在这种机制下有何不同。
通常,你希望这些分割是分层的,即训练集和测试集在类别或输出值上具有大致相同的分布,以提供一致的评估。
权衡分析:
- 优点:你可以创建任意多的实验,而不会影响训练与测试样本的比例。这里的K值与T和(1-T)的值是独立的。这意味着你可以运行大量实验,并独立设置训练样本数量或评估样本数量。
- 缺点:由于引入了大量随机性的打乱操作,你无法保证每个样本在训练和测试中被使用的次数相同。坦率地说,对于规模合理的数据集,这个缺点确实非常小。因此,我非常喜欢随机分割法。只有在数据集非常小的情况下,我才会担心这个缺点。
最后,Scikit-learn有很多用于进行这种随机分割的实用工具。我鼓励你使用它们。它们是经过精心设计的、可靠的工具代码,将帮助你实施这些协议。
2. K折交叉验证法
在某些情况下,你可能希望进行所谓的K折交叉验证。这有些不同。
假设我们有一个数据集,我们事先将其划分为三个“折”,即三个互不相交的部分。
- 实验1:我们以折1作为测试集,在折2和折3上训练。
- 实验2:我们以折2作为测试集,在折1和折3上训练。
- 实验3:我们以折3作为测试集,在折1和折2上训练。
这样我们就涵盖了所有组合。我们的三个折给了我们三个独立的实验。然后,我们汇总所有三个实验的结果。
权衡分析:
- 优点:每个样本在训练集中恰好出现K-1次,在测试集中恰好出现一次。在这方面,我们得到了一个非常理想的实验设置。
- 缺点:在我看来,这个缺点确实很严重。K值的大小决定了训练集的大小。如果我进行3折交叉验证,我可以在67%的数据上训练,在33%的数据上测试。但如果我想做10折交叉验证,现在我必须在90%的数据上训练,在10%的数据上测试。感觉实验次数与我想要的训练和测试比例问题性地纠缠在一起了。这确实是个问题。你可能想要很多折(即很多次实验),但在每种情况下却只能在80%的数据上训练。
这导致我在几乎所有情况下都更倾向于随机分割法,因为相对于K折交叉验证所引入的这种混淆因素,随机分割法的缺点相对较小。
最后,我再次指出,Scikit-learn也为你提供了支持。他们有很多很棒的工具,可以以各种方式进行这种K折交叉验证。所以,请务必利用它们来确保你的协议是你想要的。
总结


本节课中,我们一起学习了在数据组织方面的关键方法。我们回顾了传统的训练-开发-测试划分的优缺点,并重点探讨了当数据集没有预定义划分时,应如何采用交叉验证策略。我们比较了随机分割法和K折交叉验证法各自的权衡,并得出结论:在大多数情况下,尤其是数据集规模适中时,随机分割法因其灵活性和对训练/测试比例的独立控制而更具优势。最后,我们强调了利用像Scikit-learn这样的成熟工具库来实施这些协议的重要性,以确保评估的可靠性和可重复性。
44:模型评估与结论 🧪



在本节课中,我们将学习模型评估的核心概念与实践方法。我们将探讨基线模型的重要性、超参数优化的挑战、分类器比较的策略,以及深度学习时代特有的评估问题,如模型收敛性和随机初始化。这些知识将帮助你为最终项目建立坚实的评估基础。
基线模型 📊
上一节我们讨论了各种评估指标,本节我们来看看如何为模型性能设定参考标准。基线模型为我们理解模型性能提供了至关重要的上下文。
以下是关于基线模型的核心要点:
- 性能需要参照系:评估分数本身没有绝对意义。一个获得0.95 F1分数的系统可能只是因为任务过于简单;一个获得0.6 F1分数的系统,如果人类表现也只有0.61,则可能意味着重大成功。
- 基线是实验设计的核心:定义基线不应是事后想法,而应是假设检验和实验设计的中心环节。思考简单的系统以及目标系统的消融实验。
- 基线用于构建有说服力的论证:它们帮助我们校准和理解所取得的成就,并能阐明问题的特定方面或所提出系统的特定优势。
- 随机基线:随机基线(如下限模型)可以提供性能的真实下限,有时它们可能出人意料地稳健,并且有助于早期调试系统。Scikit-learn提供了
DummyClassifier和DummyRegressor来实现。 - 任务特定基线:某些任务存在能揭示问题本质的特定基线。例如,在自然语言推理任务中,“仅假设”基线(仅使用假设句进行预测的模型)表现可能很强,这揭示了数据构建过程中可能引入的偏差。
超参数优化 ⚙️
在设定了合适的基线后,我们需要优化模型本身以获得最佳性能。超参数优化旨在为模型找到最优的参数设置。
超参数优化主要有两个动机:
- 获得模型的最佳版本。
- 确保模型之间的公平比较。比较不同模型时,应为每个模型提供展现最佳性能的机会,而不是使用随机选择的参数设置。
核心原则:超参数调优必须仅在训练集和开发集上进行,绝不能基于测试数据进行任何形式的模型选择。这是保证评估泛化能力的基本原则。
然而,在模型训练耗时且昂贵的时代,穷举式网格搜索变得不可行。例如,如果有3个超参数,每个取5个值,进行5折交叉验证,就需要进行 5 * 5 * 5 * 5 = 625 次实验。如果每次实验需要一天,成本将无法承受。
因此,我们需要一些折中的策略。以下是按推荐程度降序排列的实用方法:
- 随机采样与引导采样:在固定预算内,随机或通过模型引导在超参数空间中进行采样,而非尝试所有组合。
- 基于少量训练周期的搜索:仅训练少数几个周期,根据早期性能选择超参数,假设学习曲线趋势一致。
- 基于数据子集的搜索:在小规模数据子集上进行搜索,但需注意某些超参数对数据规模敏感,这可能带来风险。
- 启发式搜索:手动设置影响较小的超参数,并证明其合理性,仅对关键超参数进行搜索。
- 单次拆分确定参数:在单个数据拆分上找到最优超参数,并将其应用于所有后续拆分,前提是假设各拆分相似。
- 沿用他人选择:直接采用其他研究或默认的超参数设置。这在资源有限或使用大型模型时可能是唯一选择。
工具方面,Scikit-learn 和 Scikit-optimize 提供了丰富的超参数搜索工具,后者支持更智能的模型引导搜索。
分类器比较 🔬
当我们评估了两个分类器模型并发现其性能存在差异时,如何确定这种差异是否具有统计意义?以下是几种方法:
- 实际差异:如果两个模型做出了大量不同的预测,并且这种差异能转化为有意义的实际结果,这是最直接的证据。
- 置信区间:计算性能得分的置信区间,可以显示两个系统差异的一致性程度。
- Wilcoxon 符号秩检验:该方法是领域内比较分类器的常用统计检验方法,类似于T检验,但其假设更符合分类器比较的场景。使用此方法需要模型在多个不同设置下运行,以得到一系列分数(如10-20个)作为检验基础。
- McNemar 检验:如果重复实验成本过高,可以使用McNemar检验。它基于两个已训练分类器的混淆矩阵进行比较,只需单次运行。虽然稳定性可能较差,但能在资源有限时提供统计参考。
深度学习的特殊考量 🧠
传统的线性模型通常会收敛到一个稳定的低损失值,但深度学习模型的行为更加复杂,这给评估带来了新的挑战。
如何评估未严格收敛的模型?
神经网络模型很少收敛到损失为 epsilon 的程度,且不同运行间的收敛速度可能不同。测试集性能与最终损失值的大小可能没有特别强的关联。因此,需要仔细思考停止训练的标准。
一种有效的方法是增量开发集测试:在训练过程中定期(如每100次迭代)在开发集上进行评估并记录性能。本课程提供的PyTorch模型包含了早停参数及相关设置,以帮助实现这一点。
观察整个性能曲线而非单一终点也至关重要。有时,损失曲线持续下降可能只是过拟合的迹象,而非模型在关心任务上变得更好。通过绘制不同模型在各个训练周期(X轴)的性能(如F1,Y轴)曲线,我们可以获得更全面的认识。例如,某个模型可能在训练早期表现最佳,但如果训练足够久,所有模型的差异可能会消失。
随机参数初始化的作用
大多数深度学习模型的参数在开始时是随机初始化的。对于非凸优化问题,不同的初始化可能导致截然不同的性能结果,甚至造成因“运气不佳”的初始化而导致的灾难性失败。
例如,对于一个简单的XOR问题,一个前馈网络可能10次运行中有8次成功,2次完全失败。这凸显了初始化的重要性。
由于我们无法从分析上完全理解这种差异,最好的应对策略(如果资源允许)是进行多次实验,并报告性能的统计分布(如均值、标准差),以反映初始化带来的方差。

总结与展望 🚀

本节课我们一起学习了模型评估的完整流程。我们从基线模型的重要性出发,探讨了如何为性能建立参照系。接着,我们深入分析了超参数优化的挑战与实用折中方案。然后,我们学习了如何对分类器进行有意义的统计比较。最后,我们讨论了深度学习模型评估中的两个特殊问题:非严格收敛下的评估策略,以及随机初始化对性能的影响。
展望未来,在当前的NLP领域,架构创新可能被高估,而评估指标创新和评估方法创新则被严重低估。我们需要仔细思考衡量成功的标准。同时,任务创新也值得更多关注。对于穷尽的超参数搜索,我们需要权衡其科学价值与实际成本,采取更务实的策略。


希望本系列关于方法与度量的内容,能帮助你批判性地思考你的项目方案,并为最终的成功奠定坚实的基础。
45:展示你的研究,第一部分:你的论文 📄



在本节课中,我们将学习如何为课程项目撰写论文。我们将重点介绍课程论文的特殊要求、核心评价标准,以及如何通过特定章节(如“已知项目局限性”和“作者贡献声明”)来提升论文的科学严谨性和透明度。

上一节我们介绍了研究展示的整体系列,本节中我们来看看课程论文的具体要求。
课程资源与核心视角
以下是一些有用的链接,包括课程网站和代码仓库中的项目页面。项目页面尤其有用,它包含了项目常见问题解答、各组成部分的建议,以及关于在该领域发表论文的一般性建议。它还列出了许多最初作为本课程作业而诞生、后来正式发表的论文清单,这非常鼓舞人心。
关于本课程项目工作的核心视角,需要再次强调。我们永远不会仅根据结果的好坏来评价一个项目。我们认识到,整个科学文献中存在对所谓“阳性结果”的偏好,而回避“阴性结果”。我们认为这种偏见是不幸的。
对于本课程,我们摆脱了所有这些偏见。我们不受任何可能激发这种偏见的限制。因此,我们可以做正确且有益的事:同等重视阳性结果、阴性结果以及介于两者之间的一切。
从根本上说,我们将根据以下标准评估你的工作:
- 所选指标的恰当性。
- 所采用方法的严谨性。
- 论文在多大程度上公开、清晰地认识到其发现的局限性。
这反映了我们的价值观。这意味着,如果你的论文报告了某个排行榜上的顶尖结果,但选择了奇怪的指标且动机不明,那么你的期末论文不一定能获得高分。反之,如果你尝试了真正有创意和雄心的想法,但在某个排行榜上的结果不尽如人意,这几乎完全不重要。你可能得到了一个非常有信息量的阴性结果,整个科学界都将从看到它而受益。我们会关注你方法的严谨性和你提供的证据,这才是决定性的。
论文的特殊章节
课程论文在结尾处有几个特殊章节。我们来回顾一下,特别是谈谈其动机。
已知项目局限性
这个部分的提示是:想象你的读者是一位善意的自然语言处理从业者,他正寻求将你的数据、模型或发现用于另一个学术项目、部署的系统或某种现实世界的干预中。心中想着这个人,然后问:这样的人应该了解你工作的哪些方面?
以下是你可以思考的内容:
- 工作的益处与风险。
- 对你的参与者、社会、地球等造成的成本。
- 对你的数据、模型和发现的负责任使用。
- 你可能想到的应归于此标题下的其他事项。
我想强调,我要求你们心中想着一位善意的自然语言处理从业者。思考如何触及一个打算作恶或有问题地使用你想法的人是非常困难的。把那种情况放在一边,只关注那些试图富有成效地基于你的想法在世界上做些好事的人。这个人可能意图最好,但并未真正意识到你想法局限所在。这是一个直接与那个人沟通局限性的机会。这样做,我认为可以为他们避免很多麻烦,也可以为他们的用户避免很多麻烦。最终,在我们的研究可能产生如此广泛影响的这个时代,这似乎是我们应该做的一件非常重要的事情。
本着这种精神,如果你真的深入思考,可以考虑制作诸如数据说明书、模型卡片和影响声明等更广泛的结构化文档。这些文档再次帮助你进行披露,主要是面向善意的用户。我没有在课程作业中强制要求这些,因为工作量很大。但如果你考虑向更广阔的世界发布数据和模型,我认为面对这类结构化文档要求你面对的所有问题将是非常有益的。
作者贡献声明
我们还要求一份作者贡献声明,这同样是关于我们的科学视角,而非评价。
从根本上说,这份声明应解释每位作者对项目的贡献。你可以包含任何你认为重要的信息。如果你需要一些例子,我推荐这份美国国家科学院院刊的出版指南,其中包含了一些关于撰写良好作者声明的小贴士。
其理由同样是科学性的:我们认为这是学术研究的一个重要方面,尤其是在我们拥有大型团队论文的时代。这与评分无关,也并非意在惩罚,只有在极端情况下,并在与整个团队讨论后,我们才会考虑根据此声明给团队成员不同的分数。这不是关于评分,而是关于我们如何发表、如何为我们的想法获得认可,以及如何解释每位科学家的贡献。
总结


本节课中,我们一起学习了如何为本课程撰写研究论文。我们明确了评价的核心在于方法的严谨性、指标的恰当性以及对局限性的坦诚,而非单纯的结果好坏。我们还介绍了论文末尾的两个关键特殊章节:“已知项目局限性”旨在帮助善意的同行负责任地使用你的工作;“作者贡献声明”则体现了对科学合作中个体贡献的认可。这些要求旨在培养严谨、透明和负责任的科研习惯。
46:撰写 NLP 论文 📝



在本节课中,我们将学习如何撰写自然语言处理领域的学术论文。我们将探讨典型论文的结构、各部分的写作要点,并分享一些关于科学写作的宝贵建议。
📄 典型 NLP 论文结构
上一节我们介绍了研究展示的总体思路,本节中我们来看看一篇典型的 NLP 论文是如何组织的。虽然结构并非强制要求,但遵循大致框架有助于符合领域规范,让读者(尤其是会议审稿人)更容易理解你的思路。
我们通常讨论的是四页或八页的双栏论文,其中参考文献不计入页数限制。
以下是八页论文的典型组成部分:
- 标题与摘要:位于首页,提供论文的最高层次概述。
- 引言:可能延续到第二页,需要在较高层次上讲述论文的完整故事。
- 相关工作:用于将你的工作置于学术背景中。
- 任务与数据:论文的核心部分由此开始。
- 模型:阐述你的核心思想。
- 方法与结果:直接报告实验结果。
- 分析:对结果进行讨论。
- 结论:简短总结。
对于四页论文,你只需压缩上述所有部分,可能需要在相关工作部分节省篇幅,以集中解释自己的思想,但基本结构是相同的。
🔍 各部分写作详解
以下是关于论文各部分的更详细说明:
引言
在 NLP 论文的惯例中,引言需要在较高层次上讲述论文的完整故事。事实上,摘要提供了更高层次的完整概述,而引言则深入一层。读者读完引言后,应能基本了解论文将要做什么,剩下的只是细节。
相关工作
此部分旨在为你的工作提供背景,并阐述相关文献中的主要主题。利用每篇论文或每个主题来阐明你的论文有何特别之处。我倾向于采用一种模板化的格式:相关工作部分的每个子节或段落先提出某个主题性问题,然后列出属于该主题的相关论文,最后解释这些思想与当前论文思想的关联——是补充、冲突还是扩展了现有文献。这样做的整体效果是,为你的研究领域提出关键主题,帮助读者理解这些主题,并解释当前思想如何与这个复杂的背景相关联。相关工作部分既是引用文献的机会,也是以有益的方式将你的思想置于背景中的机会。
数据
如果数据集是新的、任务是新的、数据不常见,或者你以不常见的方式处理问题,这部分可能会非常详细。如果是熟悉的数据集和任务结构,这部分可以简短许多。
模型
这里指的是你思想的本质。你可能没有一个严格意义上的“模型”,但你应该有一些正在追求和评估的核心思想。这是你详细阐述这些思想的机会。你可以利用前面的部分来提供背景和强调,幸运的话,相关工作部分已经帮助我们理解了你为何要进行这样的建模或分析工作。
方法
这包括你的实验方法,例如评估指标、基线模型等。由于篇幅限制,你可以将超参数优化选择、计算细节等内容放入附录,以便将正文空间留给叙述的真正核心。
结果
最好能直接描述结果表格或图表中的内容,并说明其与前面章节的基本关联。
分析
这部分可以稍微展开,讨论结果的含义、未涵盖的方面、如何改进、局限性等。此部分的性质很大程度上取决于你的建模工作和结果的性质。对于包含多个实验、多个数据集甚至多个模型的论文,可以重复“方法-结果-分析”的结构,甚至在独立的子节中呈现“数据-方法-结果-分析”,形成自包含的实验报告单元。然后,可以有一个最终的分析或讨论部分,将所有内容编织在一起,并与引言和相关工作中的思想重新联系起来。
结论
你需要快速总结论文内容,这与摘要的作用类似。不过,这里有一个很好的机会:规划可能的未来方向,提出你遗留的开放性问题等,为他人指明下一步可能的研究方向。这样,你至少能在论文的最后几句话中,展现出前瞻性和更广阔的视野。
💡 科学写作建议
我想分享一些关于科学写作的有趣建议,供你思考。
以下是 NLP 学者 Stuart Shieber 提出的一种解构。他主张采用 理性重构 的方法。
他首先将其与 大陆风格 对比,在这种风格中,作者陈述解决方案时很少或根本不介绍动机,有时甚至不说问题是什么。他认为,读者若不付出巨大努力仔细阅读,将无法判断作者是否正确,但至少他们会认为作者是个天才。我认为他略带讽刺意味,我们应避免以这种模式写作。
另一个极端是他所谓的 历史风格。论文中充满了整个错误开端、错误尝试、接近成功和问题重新定义的历史。这比大陆风格好,因为细心的读者可能能跟随作者的推理思路,并将其作为动机。但读者可能会觉得作者有点糊涂。总的来说,这类论文也很难阅读,因为很难分辨什么重要、什么不重要。
因此,Shieber 提出 理性重构 是更好的模式。你不呈现实际经历的历史,而是呈现一个理想化的历史,完美地推动解决方案的每一步。追求理性重构风格的目标不是让读者认为你才华横溢或糊涂,而是让你的解决方案显得 理所当然。将这作为目标需要一定的品格力量。你的论文写得越好,读者就越会觉得:“这非常清晰明了,甚至我也能有那些想法。”这感觉有些矛盾,但却是最佳的操作模式。
有时,人们会感到理性重构方法与我在这些讲座中其他地方呼吁的“尽可能披露、对所做之事保持开放和诚实”之间存在张力。如果你开始感到这种张力,我鼓励你使用附录来真正列举每一个错误的开端(可能以列表形式),以便真正想了解发生了什么的人能获得所需的所有信息。这将允许你在论文中讲述一个能触及最多读者、让人感到有信息量、有进展的故事。
我也喜欢 David Goss 关于数学风格的建议。他的根本建议是 体谅读者。其中一部分就是时刻想着读者,撰写论文时仿佛自己是第一次接触这些思想的人,思考需要什么信息、可以省略什么,以及总体上什么最有助于向这位假想读者传达思想。
小说家 Cormac McCarthy 也有一篇出色的文章(链接在底部),充满了对科学作家的建议。我认为他实际上与圣塔菲研究所的许多科学家交往,可能学到了很多关于他们如何工作的方式。
我想强调的一条建议是:确定你论文的主题和两到三个你希望每个读者都能记住的要点。这些内容可以放在引言中,并可能围绕这些思想来构建引言。这个主题和这些要点构成了贯穿你文章的唯一主线。词语、句子、段落和章节是将其缝合在一起的针线活。如果某些内容无助于读者理解主题,就省略它。我发现这非常有启发性。一旦我弄清楚我的两三个主要要点是什么,并至少在引言中勾勒出来,那么在我写作、决定进行或放弃哪些实验时,我总是在思考它们是否服务于这些要点。这极大地帮助我做出决策,也帮助我以相对清晰的方式撰写这些论文。
这种策略不仅会产生更好的论文,而且写起来也会更容易,因为正如我所说,你选择的主题将决定包含和排除什么,并解决许多关于叙述的低层次问题。
我想在这里提供的最后一条建议来自 Patrick Blackburn,这实际上是关于做演讲的(我稍后会提到),但我认为它适用于任何类型的科学交流。其根本见解是:好的演讲或论文从何而来?答案是 诚实。一个好的演讲或一篇好的论文永远不应远离简单、诚实的交流。我在进行研究时,脑海中始终有这个短语,我发现它非常具有启发性和激励性。
✨ 优秀论文范例
为了完善本节内容,我想提两篇我认为写得特别好的论文。我能想到很多这样的论文,事实上,在课程代码仓库的 papers.md 文档中我有一个更长的列表,但我想重点介绍两篇很有趣的。链接已提供。
第一篇是 ELMo 论文:《Deep contextualized word representations》。我喜欢这篇论文的几乎每个方面。引言在背景化结果和开始激发上下文表示及预训练的核心思想方面做得非常出色。模型本身的呈现非常清晰,你获得了关于其结构所需的所有符号表示。它有点密集,但我想这是非常复杂模型的结果,所以我认为这没问题。然后,你会看到一个非常详尽的实验探索,以及后续的问题和假设,这些真正为你提供了关于 ELMo 及其优缺点的完整图景。这是一篇短文,但感觉充满了思想,仅仅通过阅读它就能学到很多。
我还想单独提一下 GloVe 论文。这是另一个非常有趣的例子。我认为整篇论文都写得很好,但我想特别指出的是模型本身的呈现部分,因为在 NLP 中,很少能看到作者从一个分析起点开始,逐步构建成一个模型。他们讨论了实现该模型的实际挑战,以及这为何导致他们做出某些实现选择。最终,你获得了关于最终实现中涉及的各种超参数的描述。读完这些,你不仅了解了 GloVe 模型本身的细节,还感觉真正学到了一些概念性的东西。当然,论文其他部分也写得很好,并且有令人难以置信的结果,这并无坏处。但我真的特别指出模型报告部分,认为这是一篇出色的写作范例,我们在思考自己建模思想的动机时都可以借鉴。
📚 总结


本节课中,我们一起学习了如何撰写 NLP 学术论文。我们剖析了典型论文的结构,从引言、相关工作、数据模型到方法结果与分析,并了解了每个部分的写作要点与目标。我们还探讨了理性重构、体谅读者、聚焦核心主题以及诚实交流等重要写作原则。最后,通过分析 ELMo 和 GloVe 两篇优秀论文,我们看到了这些原则的实际应用。掌握这些知识将帮助你更清晰、更有说服力地展示你的研究成果。
47:NLP会议投稿指南 📝



在本节课中,我们将学习如何向自然语言处理领域的顶级会议提交研究论文。我们将详细介绍从投稿前的准备到最终“定稿”的完整流程,并探讨其中的关键策略与注意事项。
概述:NLP会议投稿流程
上一节我们介绍了研究展示的核心要素,本节中我们来看看如何将你的研究正式提交给NLP会议。这个过程有其独特的规则和挑战。
ACL匿名期政策
让我们从一个最不寻常的方面开始:ACL匿名期。ACL系列会议采用了一项统一政策,规定在提交截止日期前一个月开始,直到评审结果公布期间,投稿论文不能上传到ArXiv等公开库或以任何方式公开。
对于具体会议,请务必在其官网上核实政策生效的精确日期和时间。临近截止日期时,这些细节至关重要。
该政策旨在平衡新思想、新成果的自由快速传播与双盲同行评审的益处。其核心是防止评审人在看到论文标题后,通过社交媒体等渠道获知作者身份,从而产生潜在偏见。
关于该政策及其理由的更多信息,请参考本幻灯片底部链接的页面。
我个人认为,ACL匿名期是一个高尚的实验,但也是一个失败的实验。原因有三:
- 围绕政策细节的讨论往往低效且混乱。
- 如果论文发布后发现错误,在匿名期内无法更新,导致已知的错误结果无法及时纠正。
- 它加剧了“抢发”现象,促使研究者在截止日期前匆忙发布未成熟的想法,不利于领域内的审慎思考。
投稿与评审流程
了解了匿名期,现在假设你准备提交论文。以下是典型的投稿与评审流程:
以下是投稿与评审流程的关键步骤:
- 提交论文与关键词:提交论文时,需要选择领域关键词,这有助于决定由哪个委员会处理你的论文。最好能咨询专家,选择能为你论文匹配到最佳评审人的关键词。
- 填写清单:越来越多会议要求填写关于伦理、可复现性等事项的冗长清单。建议找专家帮忙,判断哪些问题至关重要,哪些可以简要回答。
- 评审人投标:所有提交完成后,评审人会浏览标题和摘要列表,并投标选择他们希望评审的论文。此时,标题可能是决定投标的主要因素,因为评审人可能面对数百篇提交,无暇细读所有摘要。
- 分配论文:程序主席或领域主席根据投标情况(尽管投标的实际影响力可能有限)为评审人分配论文。
- 评审与评分:评审人阅读论文,撰写评论并提供评分。
- 作者回复:作者有一个短暂的时间窗口,可以用有限的文本对评审意见进行简要回应,以纠正错误、回答问题。
- 讨论与决策:领域主席促进评审人之间的讨论,以澄清分歧或回应作者回复。最终,程序委员会综合所有信息,通过某种方式决定最终录用名单。这个过程在最后阶段可能相当不透明。
评审表格解析
以下是评审人通常需要填写的表格内容概览:
- 论文概述:要求评审人总结论文内容、贡献、主要优缺点。这有助于确保评审人真正理解了论文。
- 录用理由与拒稿理由:这两个通常是必填项。即使对于想支持的论文,评审人也可能被迫想出一些“拒稿理由”来填表。
- 给作者的问题与反馈:评审人可以在这里提出直接问题,希望能在作者回复期得到解答。
- 缺失的参考文献:遗漏相关文献可能让评审人感到被轻视,并导致扣分。
- 格式与表达改进:关于语法、风格和呈现的建议。
- 评分:包括总体推荐意见(可能是决定论文命运的主要数据点)和评审人自信度(用于校准推荐意见的权重)。
- 保密信息:用于与会议领导层直接沟通可能出现的问题。
如何撰写作者回复
作者回复是流程中复杂且常令人困惑的一环。许多会议允许作者对评审意见提交简短回复,但时间窗口紧,字数限制严格。
以下是关于作者回复的一些建议:
- 态度至关重要:尽管有观点认为评审人很少在回复后改变分数,但完全不提交回复会传递出“你不在乎”的信号,这很不利。
- 对领域主席的价值:对于设有领域主席的会议,作者回复可能产生重大影响。领域主席会综合评审意见、论文和作者回复来推动讨论并形成最终建议。
- 遵守规则:仔细阅读会议关于作者回复的说明。通常有规则禁止报告新结果。如果不确定,应咨询专家。
- 保持礼貌与策略:始终保持礼貌。可以坚定、直接地回应,但要有策略地强调你最坚持的观点。绝对不要写下攻击性语言(如“你的疏忽令人尴尬”)。可以换一种方式表达,例如:“感谢指出。您所询问的信息已在第6节中提供。我们将在修订版中使其更加突出。”
- 目标:通过礼貌且富有成效的回应,让各方都感到被尊重,从而有望提升你的评分。
报告类型与会议场所
录用后,涉及两个维度:报告类型和会议场所。
报告类型分为口头报告和海报展示。分配方式通常不透明,由会议方决定。目前,论文本身比报告形式更重要。
会议场所分为研讨会和主会。这是一个重要的区别,各有优劣:
- 研讨会:通常声望和选择性较低。优点是能与志同道合的社群深入交流,可能建立长期的合作关系。
- 主会:选择性高,声望高。缺点是规模庞大,可能难以找到特定领域的研究者,你的报告也可能淹没在众多报告中。
你需要根据自己的目标和期望的体验来做决定。
相关会议列表
以下是一些主要的NLP及相关领域会议:
- 顶级ACL会议:ACL、NAACL、EMNLP通常被认为是领域内最顶级的会议。
- 其他重要ACL会议:AACL、EACL也极具影响力。
- 优秀次级会议:CoNLL、COLING是出色的第二梯队会议,发表了大量重要工作,兼具研讨会和主会的优点。
- 其他领域顶级会议:WWW、WSDM、AAAI、IJCAI、CogSci等也欢迎NLP方向的投稿。
- 顶级机器学习会议:NeurIPS、ICML、ICLR是公认的三大机器学习顶会,都非常欢迎NLP研究,但可能需要面向更广泛的受众。
对NLP评审的个人看法
以下是我对当前NLP评审生态的一些观察:
- 会议主导的积极面:以会议论文为中心有利于领域快速发展,保持了学术活力。
- 评审质量的变化:在2010年之前(尤其是深度学习时代之前),NLP领域的评审质量相比其他领域非常出色和严谨。近年来,随着领域规模急剧扩大,提交量和评审人数激增,评审的总体质量有所下降。
- 评审人的态度问题:评审人有时会非常刻薄。你需要对此脱敏。一个方法是与有经验的同行分享你的评审意见和经历。他们很可能会告诉你:“别往心里去,我们都经历过。”请记住,刻薄的评审更多反映了评审人自身的问题,而不是你的问题。如果你受邀评审,请务必保持友善。
- 格式限制:强制将论文限制在4或8页(长短文)并不理想。幸运的是,通过更多地使用补充材料,这个问题正在得到有效解决。现在流行“短文+长附录”的模式,兼顾了可读性和细节完整性。
- 最大的缺失环节:当前会议流程缺乏作者向编辑申诉并与之互动的机会,而这正是期刊模式的优势。《Transactions of the ACL》 这本期刊遵循ACL会议模式,但允许期刊式的编辑互动,是领域内评审模式的一个优秀范例。
论文标题与摘要写作
标题至关重要,尤其是在评审人投标阶段。请根据你贡献的范围来校准标题,并考虑它可能吸引的评审人类型。避免使用特殊字体或格式,因为它们可能在传输中丢失(尽管我个人对近来标题中使用的一些表情符号抱有亲切感)。
摘要为你的工作创造第一印象。可以遵循以下模板构思:
- 开篇:概述广阔背景,点明核心问题。
- 中段:详细阐述开篇提到的概念,通常通过连接论文中的具体实验和结果来实现。这是摘要的主体。
- 结尾:建立你的研究与更广泛理论关切之间的联系,让评审人能判断摘要是否提出了实质性的原创贡献。
例如:
开篇句:本研究旨在解决以下核心问题……(定位读者)。
我们的方法:我们采用了……技术。
实验与结果:我们的实验表明……
总结与意义:总体而言,我们的方法具有以下特性,其意义在于……
其他实用建议
最后,还有一些虽平凡但重要的注意事项:
- 避免“桌面拒稿”:仔细阅读征稿启事中的格式要求和其他规定。这些细节经常变化。违反任何一条规则都可能导致可怕的“桌面拒稿”,让你本轮投稿迅速终结。
- 理解“定稿”版本:“Camera Ready”是一个过时的术语,指最终用于出版的版本。如今它只是一个奇怪的惯用语。
- 利用额外篇幅:大多数NLP会议在录用后会给予额外一页的篇幅,本意是用于回应评审人的要求。在实践中,你可以自由使用这部分空间。明智而审慎地使用它。通常,这额外的篇幅更适合用于扩展因压缩篇幅而过于简略的内容,而不是加入全新的结果。将全新的发现留待后续发表通常是更佳选择。
总结


本节课中,我们一起学习了NLP会议投稿的完整流程。我们从ACL匿名期政策谈起,逐步分析了投稿、评审、作者回复等关键环节,探讨了不同会议场所的特点,并提供了关于撰写标题、摘要以及应对评审的实用建议。记住,这个过程虽有挑战,但通过精心准备、遵守规则并保持建设性的沟通,你可以有效地展示你的研究成果。
48:如何做学术报告(第四部分)🎤



在本节课中,我们将学习如何有效地进行学术报告,特别是在NLP研讨会或会议上做报告。我们将探讨报告的结构、幻灯片设计、现场技巧以及与听众的互动讨论。
上一节我们介绍了如何组织报告内容,本节中我们来看看具体的演讲技巧和现场注意事项。
报告结构与核心原则
一个好的学术报告结构应反映论文结构,但必须更加简化。报告的目标是传达思想的精髓,激发听众阅读论文的兴趣。
以下是报告的标准结构:
- 开场与背景:说明要解决的问题、其重要性、前人工作及其不足。
- 核心内容:介绍你的方法、数据、任务结构和核心思想。
- 支持性结果:展示定量结果、消融研究和错误分析。
- 总结与展望:快速总结,并展望未来工作和开放性问题。
Jeff Pullham提出了做报告的“黄金法则”,以下是这些法则的要点:
- 不要以道歉开场:以自信有力的开场代替道歉。
- 不要低估听众的智慧:将听众视为能够理解你核心思想的同行。
- 严格遵守时间限制:通过大量练习来确保不超时。
- 不要全面综述整个领域:只提供理解你工作所必需的背景。
- 记住你是倡导者,而非被告:你是在为你的思想辩护,但个人并未受审。
- 准备好被问倒的问题:将具有挑战性的问题视为探索和学习的一部分。
Patrick Blackburn关于报告的根本见解是:诚实。好的报告不应偏离简单、诚实的交流。从教育的角度出发,真诚地尝试向听众传授你的思想。
幻灯片设计:极简主义与比较主义
在使用幻灯片(如PowerPoint)时,需要注意其使用方式。通常有两种设计哲学:
- 极简主义:幻灯片应尽可能简洁,听众大部分时间应听你讲并看着你。幻灯片只是演讲的标点。
- 比较主义:幻灯片在保持清晰的前提下应尽可能信息丰富,便于听众长时间研读、进行比较和建立联系。
无论你属于哪个阵营,引导听众注意力都至关重要。避免一次性展示所有信息,而应按照讲解顺序逐步呈现。可以使用以下工具:
- 叠加动画:逐步展示内容。
- 系统性的颜色:用于区分(需考虑色盲和投影效果)。
- 大小、粗体、箭头和方框:用于突出关键部分,引导听众视线。
选择适合你个人风格和报告目标的幻灯片风格。极简主义适合在时间有限时讲述故事;比较主义则更像一块组织良好的黑板,适合深入教学。
演讲前的技术准备
为确保演讲顺利进行,以下是一些务实的准备工作:
- 关闭屏幕通知:避免个人消息等通知在演讲时弹出。
- 关闭电脑休眠模式:防止屏幕在演讲中途熄灭。
- 关闭无关应用程序:避免其占用内存或弹出更新提示。
- 清理桌面文件:确保投影时不会显示你不想公开的文件或笔记。
- 准备PDF备份:如果使用依赖网络的演示软件,务必准备离线PDF版本。
- 做好无幻灯片演讲的准备:投影仪可能故障,要准备好仅凭口述完成报告。
讨论环节的处理
讨论环节(常被误称为“问答环节”)可能是最令人焦虑的部分。其本质应是讨论,旨在让听众更深入地理解你的思想。

处理问题时的建议如下:
- 回答前稍作停顿:确保提问者已说完,并显得你经过深思熟虑。
- 避免只说“我不知道”:可以尝试说“我不知道,但我们可以朝某个方向思考……”,以此开启对话。
- 理解问题可能不清晰:提问者可能刚接触你的思想,需要你帮忙理清问题,使其富有成效。
- 转化每个问题:无论问题是否清晰或带有敌意,都设法将其转化为一个有意义、能让提问者感到受重视的讨论点。

本节课中我们一起学习了如何组织和进行有效的学术报告。关键点包括:构建清晰简化的报告结构、根据个人风格设计幻灯片、做好充分的技术准备,以及以讨论的心态积极应对听众提问。最终,提升演讲能力的最佳途径是不断实践并进行深刻的自我反思。
49:神奇的语言模型与构建方法(第一部分)🚀



在本节课中,我们将学习两种创新的语言模型架构:ELECTRA 和序列到序列模型(如 T5 和 BART)。我们还将探讨模型蒸馏技术,并深入了解 Transformer 架构的核心设计思想及其演变过程。
ELECTRA 模型 🧠
上一节我们介绍了 BERT 模型的一些已知局限性。本节中,我们来看看 ELECTRA 模型如何巧妙地解决其中两个问题:预训练与微调阶段词汇不匹配的问题,以及 BERT 学习数据效率低下的问题。
ELECTRA 的核心思想是使用一个“生成器-判别器”框架进行对比学习。
模型结构与训练目标
- 输入与掩码:首先,我们有一个输入序列
X(例如 “the chef cooked the meal”)。我们随机掩码其中约 15% 的标记(token),这与 BERT 类似。 - 生成器:我们使用一个小型的 BERT 模型作为生成器,其目标是进行掩码语言建模。它接收掩码后的序列,并尝试预测被掩码的标记。
- 构造损坏序列:关键的一步是,我们不直接使用生成器最可能的预测结果,而是采样一个标记来替换原输入中被掩码的位置。这样就得到了一个“损坏的”序列
X_corrupt。 - 判别器(ELECTRA 核心):判别器(即我们最终要使用的 ELECTRA 模型)接收这个损坏的序列
X_corrupt。它的任务是判断序列中的每一个标记是原始输入中的(original),还是由生成器替换的(replaced)。 - 联合训练:模型的总体损失是生成器的标准 MLM 损失与判别器的对比损失(带权重)之和。
一旦预训练完成,我们可以丢弃生成器,仅使用判别器进行下游任务的微调。这解决了 BERT 中因引入 [MASK] 标记而导致的词汇不匹配问题,因为判别器从未见过 [MASK] 标记。
核心优势与实验分析
ELECTRA 的设计带来了几个显著优势:
- 数据利用效率高:判别器从序列中的每一个标记获取学习信号,而不像 BERT 只从 15% 的掩码标记学习,计算资源利用率更高。
- 小生成器,大判别器:实验表明,当生成器小于判别器时(例如,生成器维度为 256,判别器为 768),模型性能最佳。这可能是因为一个“有噪声”的生成器能为判别器提供更具挑战性的学习任务。
- 性能与效率:在相同的计算预算(FLOPs)下,ELECTRA 在 GLUE 基准测试上的表现 consistently 优于 BERT 和 RoBERTa。
以下是论文中的一些消融实验,展示了 ELECTRA 各组成部分的贡献:
- Full ELECTRA:完整的 ELECTRA 模型,性能最佳。
- All Tokens MLM:使用 BERT 架构,但对所有标记(而不仅是掩码标记)计算 MLM 损失。这证明了 BERT 本可以通过更高效地利用数据来获得更好性能。
- Replace MLM:一种 BERT 变体,不使用
[MASK]标记,而是直接用随机标记替换,解决了预训练-微调不匹配问题。 - ELECTRA 15%:仅对 15% 的标记(即被替换的部分)进行判别任务。
- BERT:原始 BERT 模型,作为基线。
这些结果验证了 ELECTRA 设计思路的有效性。


序列到序列(Seq2Seq)模型 🔄
本节我们将目光转向另一类重要模型:序列到序列模型。这类模型适用于输入和输出均为序列的任务。
常见的 Seq2Seq 任务
以下是自然落入 Seq2Seq 框架的任务示例:
- 机器翻译(源语言 -> 目标语言)
- 文本摘要(长文本 -> 短文本)
- 开放式问答(问题 -> 生成答案)
- 对话系统
- 语义解析(句子 -> 逻辑形式)
- 代码生成
架构选择
对于 Seq2Seq 问题,主要有三种架构思路:
- 编码器-解码器(Encoder-Decoder):这是经典框架。编码器(如 Transformer Encoder)双向编码整个输入序列;解码器(如 Transformer Decoder)以自回归方式(只能看到已生成的部分)生成输出序列,并可以随时关注编码器的全部输出。
- 仅语言模型(Language Model Only):将整个任务(包括输入和输出)拼接成一个长序列,使用纯自回归语言模型(如 GPT)从左到右生成。例如:
“翻译成中文:Hello world -> 你好世界”。 - 前缀语言模型(Prefix LM):输入部分可以进行双向编码(类似编码器),输出部分则以自回归方式生成(类似解码器),但共享同一套模型参数。

目前,这三种变体在实践中都有广泛应用。

代表性模型:T5 与 BART
T5 (Text-To-Text Transfer Transformer)
- 架构:采用标准的编码器-解码器 Transformer。
- 核心思想:将所有 NLP 任务都统一转化为“文本到文本”的格式。通过任务前缀(如
“translate English to German: ”)来指导模型执行特定任务。 - 训练:进行了大规模的多任务预训练,混合了无监督(如掩码语言建模)和有监督任务。
BART (Bidirectional and Auto-Regressive Transformers)
- 架构:同样是编码器-解码器结构,编码器类似 BERT(双向),解码器类似 GPT(自回归)。
- 核心创新:去噪预训练:在预训练阶段,使用多种方式破坏输入文本(如文本填充、句子重排、令牌删除、文档旋转等),然后训练模型重建出原始的、未损坏的文本。
- 适用性:这种预训练目标使得 BART 在需要“纠正”或“复原”的任务上表现突出,例如语法纠错、文本去噪等。
模型蒸馏技术 🫙
随着模型变得越来越大,如何让它们更高效地运行成为一个关键问题。模型蒸馏(Distillation)就是一种“以小博大”的技术,旨在训练一个小的“学生”模型来模仿大的“教师”模型的行为。
蒸馏目标
我们可以从浅到深地让学生模型对齐教师模型:
- 任务黄金标签:使用原始标注数据训练学生(基础方法)。
- 教师输出标签:使用教师模型预测的硬标签(如分类结果)作为监督信号。
- 教师输出分布(Logits):使用教师模型预测的完整概率分布(而不仅是最大概率的标签)作为“软标签”。这包含了类别间的关系信息,是早期蒸馏论文的核心。
- 内部表示对齐:强制让学生模型的某一层(如最终输出层)的表示与教师模型对应层的表示(例如,通过余弦相似度)尽可能接近。这需要访问教师模型的内部状态。
- 更深入的对齐:尝试让学生模型在多种输入变化下模仿教师模型的行为。

蒸馏范式
- 标准蒸馏:教师模型固定,学生模型向其学习。
- 多教师蒸馏:多个大型教师模型共同指导一个学生模型。
- 协同蒸馏/在线蒸馏:教师模型和学生模型共同学习,相互促进。
- 自蒸馏:让同一模型的较浅层去模仿较深层的表示。
为什么蒸馏有效?


一个有趣的问题是:如果教师模型只是在原始数据上训练得到的,那么直接用相同数据训练一个小的学生模型不就行了吗?为什么通过教师模型“过滤”一遍的数据会更有效?
一种可能的解释是,教师模型作为一种强大的正则化器,其复杂的决策边界和甚至其错误,都能为学生模型提供更丰富、更平滑的学习信号,帮助学生模型更好地泛化。有时,蒸馏后的学生模型性能甚至能超越教师模型。
Transformer 架构的演进 🏗️
最后,我们回到基础,探讨 Transformer 这一现代语言模型基石是如何演化而来的。其设计遵循两个核心原则:需要海量、易获取的数据,以及需要简单、高吞吐量的方式来消费这些数据。
从 RNN 和 CNN 到 Transformer
- RNN(循环神经网络):
- 优势:理论上能处理任意长序列,并催生了注意力机制的早期应用。
- 劣势:难以并行化(必须按顺序计算),训练不稳定(难以加深),难以快速处理海量数据。
- CNN(卷积神经网络):
- 优势:高度可并行化(每个卷积核窗口独立计算),通过残差连接可以构建极深的网络,非常适合现代硬件。
- 劣势:需要堆叠很多层才能获得较大的感受野,捕获长距离依赖较慢。
Transformer 巧妙地融合了二者的思想:
- 自注意力机制:来自 RNN+注意力。其核心是让序列中的每个标记都能直接与所有其他标记交互,计算它们之间的相关性权重。
- 多头注意力与并行化:来自 CNN。将输入投影到多个子空间(“头”),每个头独立进行注意力计算,这类似于 CNN 中使用多个不同的卷积核从不同视角提取特征。整个过程是高度并行化的。
- 代码示例:在实现中,我们通常通过一个大的权重矩阵
W(形状为[embed_dim, 3 * embed_dim])来同时生成查询(Q)、键(K)、值(V)向量。然后将其“切分”为多个头,每个头独立进行注意力运算。
- 代码示例:在实现中,我们通常通过一个大的权重矩阵
Transformer 的关键组件:MLP 层
然而,仅有多头自注意力还不够。自注意力本质上是加权平均,缺乏非线性变换。为了引入非线性表达能力,Transformer 在每个注意力层后加入了 MLP(前馈网络)层。
一个标准的 MLP 层通常进行以下操作:
output = DownProject(Activation(UpProject(input)))
其中,UpProject 通常将维度扩大 4 倍(例如从 512 到 2048),然后经过激活函数(如 GELU),最后 DownProject 回原始维度。
MLP 层的作用:
- 提供非线性:这是深度学习表达能力的核心来源。
- 特征空间变换:类似于 SVM 中的核函数,MLP 将特征投影到更高维空间,以便学习更复杂的模式,然后再压缩回来。
- 与残差连接的分工:残差连接负责“记住”重要信息(恒等映射),而 MLP 层则负责“忘记”或“过滤”掉不重要的信息,共同塑造最终的上下文表示。
总结 📚
本节课我们一起深入学习了:
- ELECTRA 模型:通过“生成器-判别器”的对比学习框架,更高效地利用数据,并解决了 BERT 预训练与微调的词汇不匹配问题。
- 序列到序列模型:了解了 T5(统一文本到文本框架)和 BART(去噪自编码预训练)这两种重要 Seq2Seq 模型的设计理念与适用场景。
- 模型蒸馏技术:探索了如何通过让小型学生模型模仿大型教师模型,来获得高性能、高效率的模型部署方案。
- Transformer 架构演进:回顾了从 RNN、CNN 到 Transformer 的设计思路融合,并深入理解了多头注意力和 MLP 层在 Transformer 中的核心作用。

这些知识为我们理解、使用乃至设计下一代语言模型奠定了坚实的基础。
50:构建卓越语言模型(第二部分)🚀


在本节课中,我们将继续学习信息检索的核心概念,并深入探讨神经信息检索模型。随后,我们将回顾语言模型的发展历程,并学习如何高效地训练大型模型。
信息检索评估指标回顾
上一节我们介绍了信息检索评估的多维性。虽然我们主要关注了准确性指标,但其他维度(如延迟、索引大小)同样至关重要。本节我们将继续探讨几种关键的准确性评估指标。

成功率和倒数排名
以下是两种基础的评估指标:

- 成功率 @K:对于选定的K值,判断排名前K的文档中是否存在相关文档(即“星标”文档)。它是一个非常粗略的度量。
- 倒数排名 @K:同样关注前K个文档,但会考虑第一个相关文档出现的位置。其值为1除以第一个相关文档的排名。它比成功率更细致一些。
精确率和召回率
这两种经典指标对多个相关文档敏感。
- 精确率 @K:在前K个返回的文档中,相关文档所占的比例。它衡量了结果的“纯度”。
- 召回率 @K:在前K个返回的文档中,包含了多少比例的全部相关文档。它衡量了找到所有相关文档的能力。
选择K值需要谨慎,因为它可能极大地影响系统排名。例如,一个将所有相关文档都排在K值附近(但不在顶部)的系统,在特定K值下可能优于一个将部分相关文档排在顶部但其余排在很后面的系统。
平均精确率
平均精确率是我们最细致的指标,它不再依赖一个固定的K值。
公式:AP = (Σ Precision@每个相关文档位置) / (相关文档总数)
它的计算方式是:对于排名列表中的每一个相关文档出现的位置,计算该位置对应的精确率(即该位置之前所有文档的精确率),然后将所有这些精确率值求和,最后除以相关文档的总数。这种方法抽象掉了K值,并检查了排名产生的每一个相关点,从而能更细致地区分不同系统的表现。
超越准确性:多维度评估
在实际应用中,我们不能只关注准确性。系统在查询延迟、索引大小、内存需求等维度上差异巨大。例如,一个模型可能平均倒数排名很高,但查询延迟长达691毫秒,或者索引大小高达154GB。最佳的系统选择取决于具体的应用场景、预算和对不同维度的重视程度。
神经信息检索模型
传统基于词项的检索模型(如BM25)在处理语义匹配时可能显得脆弱。神经信息检索模型因其丰富的语义表示能力,在这方面表现出色。
交叉编码器
这是一种直观但计算昂贵的架构。
核心思想:将查询和文档文本拼接在一起,输入一个大型Transformer模型(如BERT)进行联合编码,然后在模型顶部添加一个评分函数来评估文档的相关性。
优点:充分利用了查询和文档之间所有可能的交互,准确性高。
缺点:无法扩展。每次查询都需要与整个文档库中的所有文档进行实时交互计算,耗时过长,无法用于大规模检索。通常仅用于对初步检索结果(如Top 1000)进行重新排序。
密集段落检索
这是一种更高效的架构,旨在解决交叉编码器的扩展性问题。
核心思想:使用两个独立的编码器(可以是同一模型)分别处理查询和文档,生成对应的密集向量表示(例如,取[CLS]标记的向量)。然后通过计算两个向量的点积或余弦相似度来评分。
公式:score(q, d) = dot_product(Encoder_query(q), Encoder_doc(d))
优点:高度可扩展。所有文档可以预先编码成向量并存储。查询时,只需编码查询并执行快速的向量相似度搜索(如使用近似最近邻算法)。
缺点:查询和文档之间几乎没有直接的交互,语义匹配能力可能弱于交叉编码器。
ColBERT模型
ColBERT在可扩展性和表达能力之间取得了巧妙的平衡。
核心思想:仍然使用编码器分别处理查询和文档,但保留每个标记的最终层向量表示。然后,计算每个查询标记向量与所有文档标记向量之间的相似度矩阵,并对每个查询标记取与之最相似的文档标记的分数,最后将这些最大分数求和作为最终相关性得分。
公式:score(q, d) = Σ_{i in q_tokens} max_{j in d_tokens} (sim(q_i, d_j))

优点:
- 可扩展:文档标记向量可以预先计算并索引。
- 表达力强:允许细粒度的、基于标记的“软”对齐,能捕捉深层的语义相似性(例如,“come out”与“released”的匹配)。
- 直观:其对齐方式类似于传统IR中的词项匹配,但发生在语义空间。

挑战与优化:原始的ColBERT索引庞大(需存储每个标记的向量)。通过以下技术可以大幅优化:
- 作为重排序器:先用BM25等快速检索器获取候选文档,再用ColBERT重排序。
- 分阶段检索:先通过快速相似性搜索缩小候选文档范围,再使用完整的ColBERT评分。
- 向量聚类与量化:对标记向量进行聚类和量化,显著减少存储和计算开销。经过Plaid框架等优化,ColBERT的延迟已可降至毫秒级,变得实用。
SPLADE模型
SPLADE提供了一种全新的神经检索视角。
核心思想:将查询和文档分别输入模型,模型会输出一个针对整个词汇表的稀疏激活向量。这个向量的每个维度对应一个词汇,其值表示该词汇与输入文本的语义相关性强度。然后,通过计算查询和文档的稀疏向量的点积来得到相关性分数。
优点:
- 生成的表示是稀疏的,便于高效存储和检索。
- 兼具语义匹配能力和可扩展性。
- 其输出类似于传统的TF-IDF向量,但建立在深度语义模型之上,性能出色。
构建与训练大型语言模型
现在,让我们将焦点转向如何构建和训练大型语言模型。
Transformer架构的演进与稳定化
原始的Transformer块结合了自注意力机制和前馈网络。然而,直接堆叠会导致激活值爆炸。
解决方案:引入层归一化。在每个子层(自注意力和前馈网络)之前对输入进行归一化,以稳定激活值。
新问题:层归一化与Adam优化器结合时,在训练初期会导致梯度不稳定。
解决方案:采用学习率预热策略。在训练开始时使用一个较小的学习率,然后逐步增加到预设值,之后再衰减。这通常能稳定训练过程。
现代Transformer的改进
为了提升性能和效率,现代Transformer进行了一些改进:
- 移除偏置项:在注意力层的线性投影中移除偏置项,节省计算量。
- 激活函数:使用Swish-GLU等更高效的激活函数替代ReLU。
- 前置层归一化:将层归一化移到残差连接之前(即“Pre-Norm”),这通常能带来更稳定的训练。
- RMSNorm:一种更简单的归一化方法,无需可学习参数,计算为
x / sqrt(mean(x^2))。
大规模训练技术
当模型参数达到数亿甚至数十亿时,单GPU训练变得不切实际。我们需要分布式训练技术。
1. 数据并行
- 思想:将训练数据批次分割到多个GPU上,每个GPU持有完整的模型副本,独立计算梯度,然后同步梯度并更新所有副本的模型参数。
- PyTorch实现:使用
DistributedDataParallel包装模型,并配合torchrun启动脚本。
2. 混合精度训练
- 思想:在前向传播和大部分反向传播中使用16位浮点数,以减少内存占用并利用GPU张量核心加速计算。优化器状态和主模型参数副本仍保留为32位以保证数值稳定性。
- 优势:显著减少内存使用,大幅提升训练速度。
3. ZeRO冗余优化器
- 思想:在数据并行的基础上,将优化器状态、梯度和模型参数在多个GPU间进行分区存储,而不是在每个GPU上保存完整副本。这可以极大降低每个GPU的内存需求。
- 效果:使得在有限显存的GPU集群上训练超大模型成为可能。
内存占用估算:
- 全精度训练:每个参数约占用
20字节 = 4(参数) + 4(梯度) + 4(优化器参数副本) + 4(一阶动量) + 4(二阶动量)。 - 混合精度训练:参数和梯度占用减半,但优化器状态仍是32位。
通过结合数据并行、混合精度和ZeRO技术,可以将训练时间从单GPU上的上百天缩短到多GPU上的几天。
高效微调
对于预训练好的大模型,全参数微调成本高昂。参数高效微调技术应运而生。
- 代表方法:LoRA、Adapter、Prefix-Tuning等。
- 核心思想:冻结预训练模型的大部分参数,只引入少量可训练的新参数(如低秩适配矩阵)来适应下游任务。这能大幅减少训练开销和存储需求。
- 推荐工具:Hugging Face的PEFT库。
总结

本节课我们一起深入学习了信息检索的核心评估指标,并探讨了交叉编码器、DPR、ColBERT和SPLADE等神经信息检索模型,理解了它们在准确性、语义能力和可扩展性之间的权衡。随后,我们回顾了Transformer架构的稳定化过程,并学习了数据并行、混合精度训练和ZeRO等关键技术,这些是构建和训练当今大规模语言模型的基石。最后,我们了解了参数高效微调技术,为在实际项目中应用大模型提供了实用指导。

浙公网安备 33010602011771号