• [技术干货] “霸榜CLUE” ,刷新多项世界纪录的盘古中文NLP大模型
    华为云在华为开发者大会(Cloud)上发布了全球最大的中文语言(NLP)及视觉(CV)预训练模型——盘古系列大模型。据悉,华为云盘古系列 AI 大模型计划包括四大模型:NLP 大模型、CV 大模型、多模态大模型、科学计算大模型。整个大模型设计遵循三大原则:一是超大的神经网络;二是网络架构强壮,相比于定制化小模型,大模型综合性能提升了 10% 以上;三是健壮(Robust)的网络性能,全场景覆盖率提升 10 倍以上。1为什么我们需要大模型?2020 年 5 月,OpenAI 发表了一篇关于 GPT-3 的论文,GPT-3 模型迭代之后,拥有 1750 亿个参数。2019 年,GPT-2 就凭借 30 亿条参数获得了“最强 NLP 模型”的称号,1750 亿条参数的 GPT-3 发布之后,自然也就在工业界和学术界引发了广泛的谈论。我们真的需要大模型吗?大模型会给我们带来哪些改变?过去十年,AI 算法对算力的需求增长了 40 万倍,神经网络从小模型到大模型已经成为了必然的发展趋势。同时,我们也看到人工智能与科学计算深度融合,已经在众多领域都有所应用,大模型就是解决 AI 模型定制化和应用开发碎片化的一种方式,它可以吸收海量的知识,提高模型的泛化能力,减少对领域数据标注的依赖。大模型出现之后,高度定制化的小模型可能会被“兼并”。在技术方面,大模型对于 AI 框架的深度优化和并行能力都有很高的要求,同时它也会牵引 AI 产业快速收敛,成为 AI 产业底座,从而改变 AI 发展的规则和格局。现在业界普遍的 AI 开发方式还是作坊式的,针对不同场景的 AI 应用需要进行定制化开发,不仅要投入大量的专家和时间,而且 AI 模型的性能也很难做到极致。一旦场景变化,整个模型可能都需要重新开发。如果把工业化模式引入到 AI 开发过程,让一个模型可以应用到多个场景中,那么 AI 开发就会获得突飞猛进的发展。2业界首个千亿参数的中文大模型——盘古 NLP 大模型为了加速 AI 工业化开发进程,华为发布了全栈全场景 AI 解决方案。2019 年 8 月,发布了昇腾 910 芯片力和计算框架 MindSpore;2020 年 3 月,在 HDC.Cloud 发布了视觉研究计划,正式开源 MindSpore;2020 年 9 月,升级发布了 AI 一站式开发平台 ModelArts3.0。就在刚刚,华为云又发布了业界首个千亿参数的中文大模型——盘古 NLP 大模型。据了解,盘古 NLP 大模型,由华为云、循环智能和鹏城实验室联合开发,是全球最大的中文语言预训练模型,在预训练阶段就学习了 40 TB 的中文文本数据,其中包括细分行业的小样本数据,可以优化提升模型在具体场景中的应用性能。与其他大模型不同的是,盘古 NLP 大模型瞄准的是细分行业,主要解决商业环境中低成本大规模定制的问题。在最新的中文语言理解评测基准(CLUE)中,盘古 NLP 大模型获得了总排行榜、分类任务、阅读理解三项榜单第一,其中,总排行榜得分 83.046。盘古 NLP 大模型获得 CLUE 总排行榜第一盘古 NLP 大模型在 CLUE 分类任务排名第一盘古 NLP 大模型在 CLUE 阅读理解任务排名第一为什么盘古 NLP 大模型能够在 CLUE 刷新三项历史记录?相比于业界其他大模型,它又有哪些不同呢?第一,盘古 NLP 大模型在预训练阶段沉淀了大量的通用知识,既能做生成又能做理解的特性让它有能力支持行业知识库和数据库的嵌入,进而对接行业经验。大模型可以充当系统中的任意模块,快速适配和扩展不同的场景。第二,盘古 NLP 大模型在 encoder-decoder 的架构基础上植入了华为云的训练技巧和方法,所以性能优异,在 CLUE 三项榜单中都获得了第一名。同时,盘古 NLP 大模型还进行了 nlpcc2018 文本摘要任务的评测,获得了 Rouge Score 平均分 0.53 的业界最佳成绩,超越第二名百分之六十。第三,之前业界发布的大模型基本都不调优,或者是使用 non-gradient(非梯度下降)调优,为了追求泛化能力而牺牲一些场景的性能。而盘古 NLP 大模型为了改变这一缺陷,采用了大模型小样本的调优方式,基于提示(prompt-based)的调优、动态冰化等一系列正则化技术,实现了小样本学习任务上超越 GPT 系列。盘古 NLP 在各种榜单中都获得了不错的成绩,那么在具体场景中它的表现如何呢?在华为开发者大会(Cloud)现场,华为云人工智能首席科学家、IEEE Fellow 田奇就在现场对盘古 NLP 大模型进行了连续追问。通过这几个来回的问答,我们发现盘古 NLP 大模型可以如同人类一般自如交流,体现出惊人的理解能力和生成能力。通过 40TB 中文文本的训练,它能够通过少样本学习对意图进行识别,准确回答我们的问题,而且即使你在一句话中提出了多个问题,它也能够逐一识别并回答,具备了多重意图识别能力。在其中一个问题中,完全没有提到“碳中和”这个关键词,盘古也可以基于上下文推断出当前的讨论对象,并且针对“碳中和”话题发表自己的观点与看法。3 三十亿参数、十亿级图像知识的 CV 模型——盘古 CV 大模型除了 NLP 模型,华为云还同时发布了盘古 CV 大模型。据了解,该 CV 模型包含 30 亿 + 参数,是目前业界最大的 CV 模型,并且在 ImageNet 1%、10% 等数据集上的小样本分类精度上均达到目前业界最高水平(SOTA)。与其他 CV 大模型不同的是,盘古 CV 大模型首次兼顾了图像判别与生成能力,能够同时满足底层图像恢复与高层语义理解的需求,同时融合了各行业知识,能够快速适配各种下游任务。目前,盘古 CV 大模型已经在医学影像、金融等 100+ 项任务中应用实践,不仅可以大幅提升业务测试精度,还能平均节约 90% 以上的研发成本。现有的 AI 工程通常都需要针对不同场景做定制化开发,费时费力。盘古 CV 大模型的出现,解决了 AI 工程难以泛化和复制的问题,让 AI 开发进入工业化模式,一套流水线可以复制到不同的场景中,节约人力和算力。在功能方面,盘古 CV 大模型提供了大模型预训练、大模型部署和大模型迭代三个功能,三者既是个有机整体,也形成了 AI 开发的完整闭环。大模型预训练:这个阶段解决的核心问题是如何将超大规模数据,特别是各种行业数据中蕴含的知识,存储在大模型中。预训练的关键是整合无标签和有标签图像,捕捉其中隐含的结构化特征,特别是样本和样本之间的关系信息。盘古 CV 大模型中包含了数据处理、架构设计和模型优化三个步骤,支持层次化空间特征聚合、监督式对比语义调整等算法,可以将图像的表征效率提升数千倍。大模型部署:这个阶段解决的核心问题是如何覆盖各类算力差别较大的设备,包括用于高清遥感影像分析的云侧设备、用于电力线路巡检的边侧设备、以及用于铁路故障检测的端侧设备等等。三十亿参数的大模型未必能够满足用户的速度要求,盘古 CV 大模型中专门设计了模型抽取和知识蒸馏算法,能够根据用户需求抽取高效子模型,并且确保将大模型学习到的知识最大限度地传递给子模型。大模型迭代:盘古 CV 大模型配备了数据挖掘和增量学习模块,其中的一比特监督学习、双向自步学习等算法能够减少 90% 以上的人力干预;同时类别增量、难例增量学习等技术也能够在增量学习过程中减少 90% 以上的算力消耗。配合基于图网络的模型融合技术,盘古 CV 大模型最终可实现闭环迭代,模型的泛化能力也会在使用过程中逐渐增强。4 大模型背后的技术支撑以及实践案例盘古 NLP 大模型具备千亿参数、10的23次方、40TB 的中文文本训练数据,如果是使用单卡来支持盘古大模型训练,需要数百年的时间才能训练完。那么,盘古大模型背后到底有着什么样的技术支撑呢?据悉,盘古大模型的 AI 算力和数据吞吐能力都是由鹏城云脑 II 提供的,这是国内最大规模的 AI 训练集群。除了硬件算力支持,华为底层软件、训练框架、ModelArts 平台也为盘古大模型提供了技术保障。在算法方面,华为云的算法团队和循环智能(Recurrent AI)的 NLP 团队联合攻关,突破了大模型微调的难题。针对底层算子性能,盘古大模型基于 CANN 采用了算子量化、算子融合优化等技术,单算子性能能够提升 30% 以上。针对并行策略,华为 MindSpore 采用了“流水线并行、模型并行和数据并行”的多维自动混合并行技术,大幅降低了手动编码的工作量,集群线性度提升 20%。针对训练资源调度,华为云 ModelArts 支持 E 级算力调度,提供最优的网络通信能力。借助 ModelArts 平台的海量数据处理能力,盘古大模型仅用 7 天就可以完成 40TB 文本数据处理。光说不练假把式,了解了盘古大模型背后的技术支撑之后,我们来看看盘古大模型是如何应用到实际案例中。国网重庆永川供电公司是国内早期采用无人机智能巡检技术来替代人工巡检的电力公司,并将无人机数据采集应用于输电线路、变电站、配电线路自主巡检等多个业务场景。但是传统的无人机智能巡检 AI 模型开发中,他们遇到了两个难题,一是如何进行缺陷样本的高效标注,二是智能巡检故障种类繁多。为了解决这两个问题,国网重庆永川供电公司与华为云合作应用了盘古 CV 大模型。在数据标注方面,盘古 CV 大模型利用海量无标注电力数据进行预训练,并结合少量标注样本微调的高效开发模式,提出了针对电力行业的预训练模型。应用之后,样本筛选效率提升约 30 倍,筛选质量提升约 5 倍,以永川每天采集 5 万张高清图片为例,可节省人工标注时间 170 人天。在模型通用性方面,结合盘古搭载的自动数据增广以及类别自适应损失函数优化策略,可以做到一个模型适配上百种缺陷,一个模型就可以替代永川原先的 20 多个小模型,极大地减少了模型维护成本,平均精度提升 18.4%,模型开发成本降低 90%。国网重庆永川供电公司的应用案例,让我们见识到了盘古大模型在电力智能巡检方面的优势,盘古大模型能够快速适配到电力行业的不同场景,真正做到了规模化可复制。相信未来,我们可以在更多行业领域看到盘古大模型的应用实践。
  • [技术干货] 华为云细粒度文本情感分析及应用-华为云 NLP算法专家分享
    分享嘉宾:李明磊博士 华为云 NLP算法专家编辑整理:付一韬出品平台:DataFunTalk导读:随着移动互联网的普及,网络上每天产生大量的文本数据,蕴含着巨大的有价值信息。情感分析作为自然语言处理中的一个重要研究方向。在实践中有着广泛的应用,如商品评论分析、政治、金融、旅游等领域中的商品推荐、产品辅助决策、公司政府的舆情监测、服务评价等等。本文主要介绍情感分析的概念、应用、任务和方法,进一步会介绍华为云在细粒度情感分析方面的实践,包括属性级情感分析和观点四元组分析。主要内容包括:文本情感分析介绍属性级情感分析观点四元组分析总结一、情感分析介绍首先介绍下文本情感分析的基本概念。情感分析,主要是识别媒介中目标对象的情感,这里面可能有两个概念比较容易混淆,一个是sentiment analysis,另一个是emotion analysis。一般我们说的情感分析都是sentiment,主要指的正面和负面的分析,然后emotion会更详细一些,它不仅包含正负面,还包含比如说生气、开心、高兴这些,会更加细粒度一些。我们主要分析sentiment,从分析对象来看会包含文本、图像、语音,EEG(脑电波)、多模态分析情感。从任务方面来看,不仅是有情感的识别,还有情感生成的一些任务,像现在有情感对话的生成,还有虚拟人情感生成。在本报告中,主要侧重文本方面的情感识别。1. 文本情感分析上面文本情感分析五要素定义是采用刘冰老师的定义,这个定义分为了实体 ( entity )、实体的某一个方面 ( aspect )、针对这个实体的情感正负面 ( opinion=sentiment,即情感正负面也称作观点正负面 )、观点持有者 ( hold ) 和持有观点的时间 ( time ) 这五要素,一般来说hold和time文本很少提及。另一个概念一般会把entity和aspect合并在一起成为一个target,是针对我们目标对象的情感或者观点。例如:“我觉得华为手机的拍照非常牛逼”这里面对应的实体是“华为手机”,对应的aspect是“拍照”,对应的情感是“非常牛逼”为正面,对应的观点持有者是“我”,而时间没有提及所以为空。当前的文本情感分析就是根据输入文本,然后识别其中这五要素里的几个要素,现在还没有相关工作可以同时识别出五个要素。一般的话现在最简单的情感分析是只识别出这个文本的观点/情感,既不包含实体也不包含aspect并且也不包含观点持有者,再进一步的工作就是识别出针对哪一个aspect(实体)的观点(情感)。这里简单介绍一些细粒度情感分析和我们说的一般情感分析的区别。一般的情感分析都是直接识别整个文本的正负面,然而细粒度情感分析会更细一些,这里面有两个概念,一个是从情感的粒度上会更细,比如从sentiment到emotion的情感粒度升级,之前我们只分析正负面,现在除了正负面还有情绪,如高兴、伤心等,从情感这个维度讲这是一种细粒度情感分析。还有一个是从分析对象的角度来讲,之前的情感分析是直接识别整个句子或整篇文章的情感,它不区分情感对象是谁,再细粒度一些的话就需要识别出整个句子里面情感针对的对象是谁,它是句子里的某个实体或者是某个实体的某个属性,从这个角度这也是细粒度情感分析的一种,我们今天主要侧重第二个针对对象角度的情感分析。2. 情感分析任务下面介绍一下情感分析的各个任务,这里面分析是情感的识别,不包含生成,还有前面提到的语音图片也不涉及。针对文本的情感分析会分成几个等级:词级别的情感分析:这个类似于情感词典的构建,怎么去构建一个大规模的情感词典,比如“车祸”这个词对应的情感就是负面的,“生日”这个词对应的情感就是正面的。句子/文档级的情感分析:我们现在用比较多的,各大云服务厂商都会有的一个服务,针对句子或者文档的情感分析,输入一句话返回相应的情感正负面,但它不区分正负面针对哪一个句子里面哪个实体或者哪个对象。目标级的情感分析:这是我们今天侧重的目标级的细粒度情感分析,这里面的目标就是上边说的target,它可以是一个实体也可以是一个属性,还可以是实体+属性的组合形式。对于目标级的情感分析分为三种:针对属性的情感分析 ( TG-ABSA ):这里面对象是固定然后只分析里面某几个属性的正负面,这就会涉及到两个任务,一个是对象的属性识别,另一个是该属性的情感识别。例如图中的例子“外观XXX”,这里的对象是固定说的是手机,我们只需要识别出其中的属性外观、内存和性能,然后分别识别出各个属性的情感正负面。针对属性识别也分成两个任务,一是属性词的抽取,就是我们要定位出属性描述词在文中的位置,另一个是该属性描述词对应的属性类别,因为针对某个属性的描述可能是“外观”也可能是“看起来很好看”,它这个描述不一定包含显性的属性描述词。针对情感识别会分为观点词抽取和观点分类。针对实体的情感分析 ( TN-ABSA ):这里是文本中只有实体而没有属性,只针对实体的情感进行分析,这涉及到的两个任务,实体识别和情感识别。实体识别分为实体词抽取和实体分类,情感识别分为观点词抽取和观点分类。针对目标的情感分析 ( T-ABSA ):这里面的目标就是实体+属性的组合,例如:“小米性价比”、“华为拍照”等,这会比上面两个任务相对更细一些。目标识别分为目标词抽取和目标分类,情感识别分为观点词抽取和观点分类。针对情感分析,简单介绍一些方法简史。最早的一个方法是基于字典加规则的方式,我们人工构建一个情感词典,每个词都有对应的正负面,然后根据句子中正面词和负面词的数量,最后做一个投票,这是一个最简单的方法。后边就有了基于机器学习的方法,像传统的机器学习SVM等,将情感词典和词袋作为它的一个特征。再进一步就是深度学习,还有就是现在的基于预训练语言模型+fine tune的方法,应该是现在效果最好的一个方法。二、属性级情感分析下边我介绍一下我们其中的一个工作,属性级情感分析(TG-ABSA),这里面实体是固定的,分析它各个属性的正负面。像上面句子级情感分析是大部分厂商提供的,比如“买没几天就降价一点都不开心,闪存跑分就五百多点”,这个整体是负面,但是它针对价格和闪存两个属性都有相应情感,这里并没有区分。属性级情感分析这个任务就是给定属性的类别集合,然后预测它各个属性的正负面。其中,这里的表达也分为两种,一种是显式的观点表达,另一种是隐式的观点表达。显式的观点表达会显示提到属性的属性词和观点词,比如“手机内存非常大,系统流畅,性价比非常高”,这里属性词“内存”、“系统”和“性价比”都有显示的提到,而像“手机太贵了,颜值非常高,一点都不卡”,这里“手机太贵了”、“一点都不卡”表达的属性分别是“价格”和“性能”,但是没有相应的属性词。针对这两种不同的表达方式,处理方式是不一样的,后边会介绍一种专门针对显示的方法。1. 属性级情感分析—相关工作介绍① 无监督方法:最传统的一个方法是无监督的,这种方法的优势是不需要标注数据,比如使用基于句法解析的方法,先抽取句子里主语谓语宾语的表达方式,比如“服务员很漂亮”,通过抽到的主语“服务员”和它对应的形容词“漂亮”,这样我就可以知道它的评价对象是“服务员”,观点是“漂亮”,再根据查情感词典知道这是一个正面的情感,这样就可以得到针对服务员的评价是正面的。这种方法只能处理显示的表达,如果是隐式的表达,因为句子中没有属性词,那么通过句法解析没法得到对应的角色,所以无法分析来处理隐式的表达。这种无监督方法的优点是不需要标数据,缺点是准确率相对低一些,没法处理隐式表达。② 阅读理解方法:最近的一个工作是复旦邱锡鹏老师组提出的基于深度学习的方法,分析一个句子里面各个属性的正负面,他把这个问题转化成一个阅读理解的问题,本来一个句子有N个属性集合,他把句子和属性转换成句子-属性 pair。输入一个句子,这里面aspect可以描述成阅读理解的一个问你题,比如“针对外观评价是怎么样的”,这样转换成问答对的方式,然后基于Bert来识别这个问答对正负面的答案,这是一个比较新的工作。这种方式的优势是比较灵活,属性可以无限的扩充,不管是新增或者减少属性,都可以用这种方法直接取处理,而且准确率还比较高。但是这种方法的缺点就是它的效率相对要低一些,因为如果有N个属性,在预测的时候,它需要预测N次才能得到结果。2. 属性级情感分析—方案介绍我们提出了一个基于类似多标签,多任务的方法。整个任务给定属性类别集合,然后预测每个属性的正负面。这里面的难点是,首先我们大框架使用的是有监督的方法,因为最终我们想要把应用部署到华为云的服务上,所以准确率要求是比较高的,要求达到90%以上,一般无监督的方法无法满足,所以还是需要有监督的方法。这就需要标注数据,如果是多个属性它的一个问题就是标注起来比较困难,比如说一个手机评论可能会涉及到二三十个属性或者说甚至上百种属性,如果要标数据的话,这会非常的困难。我们的方法不同于传统的多标签分类,像文本多标签分类任务的类别有政治、经济、新闻,该任务只涉及标签是否出现,但这里不一样的地方是它不仅涉及到属性是否出现,还要预测出属性的正负面,相当于每个属性都要预测出它的三个标签—正面、负面和未出现。相当于每个属性是一个多分类任务而不是一个二分类任务。之前那种多标签分类,一般最后会把每个标签转化成logits,这里的话用这种方法就没办法处理。然后还有就是隐式表达。我们解决的技术思路是,把它转换成一个Multi-task多分类任务,每个属性都处理成一个多分类的任务,所以它输出不是二分类而是一个多分类。在标注数据的过程中,我们引入主动学习的思路,先标注一批少量的数据,然后用模型对剩余未标注的做一个预测,然后再对那些置信度比较低的再去人工审核标注这些数据,如果置信度比较高的就不用再标了,这样的话可以提高标注效率。另一个方法是,如果一个样本同时标注多个属性,这个标注成本是很高的,我们引入Label mask的思路,就是在训练的时候 某几个属性可能标也可能没标,如果没标的话就把这个属性mask掉,然后在计算loss的时候该属性就不参与计算了,只将那些已经标注的属性参与loss计算和反向传播的计算,这样的一个好处就是我在真正标注样本的时候想标注哪几个属性就标注哪几个属性,不用每个样本的所有属性都要标注,这样标注就更加灵活,可以先针对某一个属性只标注它,标完该属性后再标另一个属性,这实际上是一个很灵活的标注。使用这个方法的一个优势是,它最终基于深度学习模型,准确率比较高,也支持隐式的表达,因为深度学习可以编码各种语义的表达,还有一个就是我们这种方法可以提高标注效率。在中间编码这块可以是基于bert、roberta这种预训练语言模型,最终输出使用label mask的方法。3. 属性级情感分析—结果上面是我们最终的实验结果,针对汽车领域测试样本大概有7000多个,每个样本平均的属性数量是4.27个,其中预定义的属性集合是8个,最终可以看到每个属性的准确率都是很高的,基本上达到90%以上。针对手机领域的结果基本上也是每个属性F值基本上能达到将近90%。右上角的图是针对每个属性预测的标签的置信度的阈值,随着阈值的上升,命中的属性(即预测的标签的置信度在阈值以上的属性)准确率也在上升,而Attribute Hit Rate(即预测标签的置信度在阈值以上的属性占比)也随着阈值的上升而下降,即有些属性预测的标签的置信度低于阈值,但是命中的属性预测出标签的准确率是慢慢上升的,这个也是符合我们的一般认知的。这个的一个好处是最终产品上线之后,用户要求有一部分不需要人工审核,另一部分则需要人工审核,当达到某个阈值之后,他们就可以不用参与人工审核。通过调节阈值,让某些属性的指标达到了这个阈值,比如准确率都达到95%,这一部分就不需要人工审核。4. 属性级情感分析—应用案例这是我们基于多属性情感分析的一个应用案例,这是汽车领域的案例,针对网上很多的汽车领域的评论,我们可以分析汽车在八个属性维度上的正负面评价。上图左上角里红色的线就是一个行业的平均水平,蓝色的线是针对这个车它的各个维度的雷达图像,这样就可以很方便地对比出不同车型,它的一个好坏。可以方便用户在产品选型的时候做一个对比,也可以方便厂家针对评论本身对他们的产品做相应的改进。三、观点四元组分析1. 四元组观点挖掘—介绍上面讲到的虽然可以分析出各个属性的正负面,但是它的一个缺点是没办法定位出针对某个属性具体评价的属性描述词位置和观点描述的位置,因为有些用户不仅想要找到属性正负面,还要找到它对应的评价位置,所以我们这个工作是针对观点四元组进行挖掘的。观点四元组挖掘这个任务不仅要分析出各个属性的正负面,还要定位出它属性描述词的位置以及观点描述词的位置。比如“手机内存非常大”中属性描述词定位到“内存”,评价词定位“非常大”,对于“性价比非常高”这句话,属性描述词定位到“性价比”,观点描述定位到“非常高”,不仅要识别出属性的类别还要定位到位置,所以这里一共有四个要素要预测出来,分别是属性词、属性类别、评价词和评价极性,其中属性类别和评价极性在前面的工作已经做到了。2. 四元组观点挖掘—方案针对这个任务,我们提出了一个基于抽取加分类的联合模型,上图是我们现在采用的框架,底层是基于编码的模型,可以是bert或者roberta等,然后将句子编码成一个向量表示。图中左边这侧是用于定位属性描述位置和观点描述位置的,是一个序列标注模型,比如这里B_A是属性描述词起始位置,I_A则是在属性描述词中间的位置,例如这里“内存”和“颜色”都是属性描述词。在这里最上层用的是CRF序列标注模型来进行属性描述词的抽取。图中右边这侧对应的跟上面的工作有点类似了,有N个属性对应有N个输出,然后对应每个属性预测它的正负面和未出现这几类。左边做属性词抽取,右边做属性正负面预测,最终可以输出每个属性的四元组(属性类别,属性描述词,观点描述词,观点类别)。3. 四元组观点挖掘—数据标注这里的比较耗时间的工作就是数据标注,因此我们专门做了四元组观点挖掘的数据标注平台。上面“简单”这个分类标签是为了解决标注过程中有些不同标注人员他可能对同一个样本就会有冲突,他觉得这个样本比较难标或者好标的话这里就是用这进行区分,如果样本好标会打个“简单”的分类标签,如果让他觉得不确定,他会不打“简单”的标签,即“复杂”标签。因为我们标的属性比较多,涉及到差不多三四十个属性,这里做了一个对属性做了大致的分类。这里的标注任务是类似于关系抽取里面3元组的标注任务,先标注属性描述词,然后再标注它的观点描述词,这里面它两个其实是形成一个搭配关系,这个类似于一个三元组中实体和实体及他们的关系,只不过这里的关系是一种搭配的关系,将它们连起来就可以了,最后再加上它对应的正负面以及属性描述词对应的属性类别,这样每个样本的四元组就标出来了。上图左边是我们标注大概两万条手机评论的数据分布,其实可以看到数据分布式非常不均衡的。这个是拿到真实用户在线上评论的数据,有些评论会偏的非常多,然而有些类别评论会非常少。上图右边是针对所有属性对应正负面的分布,这个也是非常不均衡的,正面的评论比较多,负面的评论会相对少很多。4. 四元组观点挖掘—结果上图为我们最终的评价结果,因为它是一个四元组既包含分类也包含抽取,对于评价指标我们用了一个Fuzzy F1值。我们对每一个属性加正负面标签作为一个评价对象,比如“外观正”作为一个评价对象,然后去找它对应的位置,计算这个位置它们字符的重合率(包括观点描述词和属性描述词的重合率)这样去算它的F值。EM F1值是预测描述词的位置完全精准匹配,稍微有一点不对也算错,这个比前面的指标更加严格。在编码器这部分我们尝试了几个不同的编码器,包括bert、roberta还有nezha等。由于我们有很多未标注的数据,基于这些数据我们做了领域的预训练,然后再进行fine tune。右图展示了不同指标下的结果,可以看到在未标注数据上进行领域预训练的话是可以带了一个点的提升,Fuzzy F1能达到0.79。另外,这个评估指标对于人的实际感知不太直观,我们随机抽取500条数据进行人工评价。人工评价的过程是每个样本预测出每个属性标签和正负面且包括它们的位置,将这样的四元组抽取出来进行人工评价,判断预测是否合理,如果合理标记为1,如果不合理则标记为0,这样来看人工对模型预测的指标判断。人工评价的准确率是非常高的,差不多96%的准确率,即人工认为预测是合理的。这两个结果差别是比较大的,但也是比较合理的,因为在数据标注过程中,不同标注人员对观点描述词的位置以及属性描述的位置也可是会有歧义。比如“外观非常好看”这句话,有些人观点描述词会标“好看”,有些人就会标“非常好看”,这其实对最终预测结果影响不大,但是如果用字符重合率的方法,那会严重影响计算这个指标,所以说它两个差异比较大也是合理的。5. 四元组观点挖掘—Demo上图是我们一个简单的demo,输入一个样本,生成对应每个属性的正负面,当点击某个属性的时候它对应的评价词位置就可以高亮出来,红色代表属性描述词,绿色代表观点描述词。上面说的人工评价就是这些结果预测出来后,人工看看预测是否合理。四、总结本文主要介绍了情感分析的一些基本任务,包括文本、语音、图像还有生成、识别。对于文本情感分析任务做了详细介绍,重点介绍了两个工作,一个是属性级情感分析,这个是给定属性集合情况下,预测每个属性的正负面,我们将它构建成了一个多任务分类。另一个工作比上面的粒度更细一点,不仅要预测出属性正负面,还要定位出它具体的属性描述词和观点描述词的位置,我们把它做成了一个抽取加分类的多任务联合模型,既包括抽取也包括分类。对于未来的趋势,我们在实际做的过程中发现大家在工业界会碰到标注数据成本非常高的问题,每一个任务基本上我们需要标将近两万条数据,所以最终的效果准确率是比较高的。另一方面,对于模型加速这部分,由于使用深度学习像bert这种预训练模型,它的推理成本还是比较高的,我们华为可以对硬件进行底层适配。对于领域迁移未来也是关注重点,怎么能从更低成本从某一领域迁移到另一个领域,比如从汽车领域迁移到手机领域,或者从手机领域迁移到房地产领域等等。另外,还有自监督去训练超大规模的模型,比如像bert、roberta还有最近GPT3等等,这也是未来的趋势,然后再考虑如何将知识图谱加入到大模型当中进行知识增强来提升模型理解的效果。还有就是多模态这部分,怎么把图像、文本或者语音这些信息辅助来提升模型的效果。因为人在学习的时候不仅参考了文本的信息,还有视觉方面的信息等等。现在对于多模态情感分析我们也有一些工作正在做,比如说从视频中分析出一个人的情感,既考虑人脸的图像信息,也考虑他语音的一些信息,比如语气等等。今天的分享就到这里,谢谢大家。嘉宾介绍:李明磊,华为云NLP算法专家,博士毕业于香港理工大学,从事文本情感分析和情绪识别的研究,在TAC、ACL、EMNLP等发表论文多篇,获得IALP 2016 最佳论文奖,KSEM2017最佳学生论文奖。目前就职于华为云语音语义创新Lab,主要负责华为云文本分析、多模态分析等业务,所孵化服务已在多个实际业务场景中落地。团队DigScience2019,CCF BDCI 2019, WSDM Cup 2020比赛金牌。文章来源:https://mp.weixin.qq.com/s/yeiODUxkTpvi2AsghjbeeQ
  • [技术干货] 陈丹琦团队最新论文:受GPT-3启发,用小样本学习给语言模型做微调,性能最高提升30%
    2020年,GPT-3可谓火出了圈。不仅讲故事的本职工作做得风生水起,还跨界玩起了网页设计、运维、下象棋……不过,尽管表现惊艳,GPT-3背后到底是实实在在的1750亿参数,想要在实际应用场景中落地,难度着实不小。现在,针对这个问题,普林斯顿的陈丹琦、高天宇师徒和MIT博士生Adam Fisch在最新论文中提出,使用较小的语言模型,并用少量样本来微调语言模型的权重。并且,实验证明,这一名为LM-BFF(better few-shot fine-tuning fo language models)的方法相比于普通微调方法,性能最多可以提升30%。详情如何,一起往下看。方法原理首先,研究人员采用了基于提示的预测路线。所谓基于提示的预测,是将下游任务视为一个有遮盖(mask)的语言建模问题,模型会直接为给定的提示生成文本响应。这里要解决的问题,是寻找正确的提示。这既需要该领域的专业知识,也需要对语言模型内部工作原理的理解。在本文中,研究人员提出引入一个新的解码目标来解决这个问题,即使用谷歌提出的T5模型,在指定的小样本训练数据中自动生成提示。其次,研究人员在每个输入中,以额外上下文的形式添加了示例。问题的关键在于,要有限考虑信息量大的示例,一方面,因为可用示例的数量会受到模型最大输入长度的限制;另一方面,不同类型的大量随机示例混杂在一起,会产生很长的上下文,不利于模型学习。为此,研究人员开发了一种动态的、有选择性的精细策略:对于每个输入,从每一类中随机抽取一个样本,以创建多样化的最小演示集。另外,研究人员还设计了一种新的抽样策略,将输入与相似的样本配对,以此为模型提供更多有价值的比较。实验结果那么,这样的小样本学习方法能实现怎样的效果?研究人员在8个单句、7个句子对NLP任务上,对其进行了系统性评估,这些任务涵盖分类和回归。结果显示: 基于提示的微调在很大程度上优于标准微调;自动提示搜索能匹敌、甚至优于手动提示;加入示例对于微调而言很有效,并提高了少样本学习的性能。在K=16(即每一类样本数为16)的情况下,从上表结果可以看到,该方法在所有任务中,平均能实现11%的性能增益,显著优于标准微调程序。在SNLI任务中,提升达到30%。不过,该方法目前仍存在明显的局限性,性能仍大大落后于采用大量样本训练获得的微调结果。关于作者论文有两位共同一作。高天宇,清华大学本科生特等奖学金获得者,本科期间即发表4篇顶会论文,师从THUNLP实验室的刘知远副教授。今年夏天,他本科毕业后赴普林斯顿攻读博士,师从本文的另一位作者陈丹琦。此前,量子位曾经分享过他在写论文、做实验、与导师相处方面的经验。Adam Fisch,MIT电气工程与计算机科学专业在读博士,是CSAIL和NLP研究小组的成员,主要研究方向是应用于NLP的迁移学习和多任务学习。他本科毕业于普林斯顿大学,2015-2017年期间曾任Facebook AI研究院研究工程师。至于陈丹琦大神,想必大家已经很熟悉了。她本科毕业于清华姚班,后于斯坦福大学拿下博士学位,2019年秋成为普林斯顿计算机科学系助理教授。最后,该论文代码即将开源,如果还想了解更多论文细节,请戳文末论文链接详读~传送门论文地址:https://arxiv.org/abs/2012.15723v1项目地址:https://github.com/princeton-nlp/LM-BFF本文来源:量子位 https://www.qbitai.com/2021/01/20919.html鱼羊 发自 凹非寺量子位 报道 | 公众号 QbitAI
  • [技术干货] 2020年这10大ML、NLP研究最具影响力:为什么?接下来如何发展?
    作者 Sebastian Ruder去年有哪些机器学习重要进展是你必须关注的?听听 DeepMind 研究科学家怎么说。2020 年因为新冠疫情,很多人不得不在家工作和学习,大量人工智能学术会议也转为线上。不过在去年我们仍然看到了很多 AI 技术领域的进展。DeepMind 研究科学家 Sebastian Ruder 近日帮我们对去年的机器学习社区进行了一番总结。首先你必须了解的是:这些重点的选择基于作者个人熟悉的领域,所选主题偏向于表示学习、迁移学习,面向自然语言处理(NLP)。如果读者有不同的见解,可以留下自己的评论。Sebastian Ruder 列出的 2020 年十大机器学习研究进展是:大模型和高效模型语言模型从 2018 年到 2020 年的发展(图片来自 State of AI Report 2020)。2020 年发生了什么?在过去的一年,我们看到了很多前所未有的巨型语言和语音模型,如 Meena(Adiwardana et al., 2020)、Turing-NLG、BST(Roller et al., 2020)和 GPT-3(Brown et al., 2020)。与此同时,研究人员们也早已意识到训练这样的模型要耗费过量的能源(Strubell et al., 2019),并转而探索体量更小、效果仍然不错的模型:最近的一些进展方向来自于裁剪((Sajjad et al., 2020、Sanh et al., 2020、)、量化(Fan et al., 2020b)、蒸馏(Sanh et al., 2019、Sun et al., 2020)和压缩(Xu et al., 2020)。另有一些研究关注如何让 Transformer 架构本身变得更高效。其中的模型包括 Performer(Choromanski et al., 2020)和 Big Bird(Zaheer et al., 2020),如本文第一张图所示。该图显示了在 Long Range Arena 基准测试中不同模型的性能(y 轴)、速度(x 轴)和内存占用量(圆圈大小)(Tay et al., 2020)。像 experiment-impact-tracker 这样的工具(Henderson et al., 2020)已让我们对于模型的能耗效率更为了解。其研究者还推动了评估效率的竞赛和基准测试,如 EMNLP 2020 上的 SustaiNLP 研讨会,NeurIPS 2020 上的 Efficient QA 竞赛和 HULK(Zhou et al., 2020)。模型体量的扩大可以让我们不断突破深度学习能力的极限。而为了在现实世界部署它们,模型必须高效。这两个方向也是相辅相成的:压缩大号模型可以兼顾效率和性能(Li et al., 2020),而效率更高的方法也可以推动更强、更大的模型(Clark et al., 2020)。鉴于对效率和可用性的考虑,我认为未来研究的重点不仅仅是模型的表现和参数数量,也会有能耗效率。这会有助于人们对于新方法进行更全面的评估,从而缩小机器学习研究与实际应用之间的差距。检索增强使用 REALM 进行无监督预训练,检索器和编码器经过了联合预训练。大规模模型可以利用预训练数据学习出令人惊讶的全局知识,这使得它们可以重建事实(Jiang et al., 2020)并在不接触外界上下文的情况下回答问题(Roberts et al., 2020)。然而,把这些知识隐式地存储在模型参数中效率很低,需要极大的模型来存储足量的信息。与之不同的是,最近的一些方法选择同时训练检索模型和大规模语言模型,在知识密集型 NLP 任务上获得了强大的结果,如开放域问答(Guu et al., 2020、Lewis et al., 2020)和语言建模(Khandelwal et al., 2020)。这些方法的主要优点是将检索直接集成到语言模型的预训练中,从而让语言模型效率更高,专注于学习自然语言理解中更具挑战性的概念。因此在 NeurIPS 2020 EfficientQA 竞赛中的最佳系统依赖于检索(Min et al., 2020)。检索是很多生成任务的标准方法,例如文本摘要和对话此前已大量被摘要生成所替代 (Allahyari et al., 2017)。检索增强生成可以将两个方面的优点结合在一起:检索段的事实正确性、真实性以及所生成文本的相关性和构成。检索增强生成对于处理过去困扰生成神经模型的失败案例尤其有用,尤其是在处理幻觉(hallucination)上(Nie et al., 2019)。它也可以通过直接提供预测依据来帮助使系统更易于解释。少样本学习在过去几年中,由于预训练的进步,给定任务的训练样本数量持续减少(Peters et al., 2018、Howard et al., 2018)。我们现在正处在可以使用数十个示例来完成给定任务的阶段(Bansal et al., 2020)。自然地,人们想到了少样本学习变革语言建模的范式,其中最为突出的例子就是 GPT-3 中上下文学习的方法。它可以根据一些输入 - 输出对和一个提示进行预测。无需进行梯度更新。不过这种方式仍然有其限制:它需要一个巨大的模型——模型需要依赖现有的知识——这个模型能够使用的知识量受到其上下文窗口的限制,同时提示需要手工完成。最近的一些工作试图通过使用小模型,集成微调和自动生成自然语言提示(Schick and Schütze, 2020、Gao et al., 2020、Shin et al., 2020)让少样本学习变得更加有效。这些研究与可控神经文本生成的更广泛领域紧密相关,后者试图广泛地利用预训练模型的生成能力。有关这一方面,可以参阅 Lilian Weng 的一篇博客:https://lilianweng.github.io/lil-log/2021/01/02/controllable-neural-text-generation.html少样本学习可以使一个模型快速承接各种任务。但是为每个任务更新整个模型的权重是很浪费的。我们最好进行局部更新,让更改集中在一小部分参数里。有一些方法让这些微调变得更加有效和实用,包括使用 adapter(Houlsby et al., 2019、Pfeiffer et al., 2020a、Üstün et al., 2020),加入稀疏参数向量(Guo et al., 2020),以及仅修改偏差值(Ben-Zaken et al., 2020)。能够仅基于几个范例就可以让模型学会完成任务的方法,大幅度降低了机器学习、NLP 模型应用的门槛。这让模型可以适应新领域,在数据昂贵的情况下为应用的可能性开辟了道路。对于现实世界的情况,我们可以收集上千个训练样本。模型同样也应该可以在少样本学习和大训练集学习之间无缝切换,不应受到例如文本长度这样的限制。在整个训练集上微调过的模型已经在 SuperGLUE 等很多流行任务中实现了超越人类的性能,但如何增强其少样本学习能力是改进的关键所在。对比学习对比学习是一种为 ML 模型描述相似和不同事物的任务的方法。利用这种方法,可以训练机器学习模型来区分相似和不同的图像。最近,对比学习在计算机视觉和语音的自监督表征学习(van den Oord, 2018; Hénaff et al., 2019)中越来越受欢迎。用于视觉表征学习的新一代自监督强大方法依赖于使用实例判别任务的对比学习:将不同图像视为 negative pairs,相同图像的多个视图视为 positive pairs。最近的方法进一步改善了这种通用框架:SimCLR(Chen et al., 2020)定义了增强型实例的对比损失;Momentum Contrast(He et al., 2020)试图确保大量且一致的样本对集合;SwAV(Caron et al., 2020)利用在线聚类;而 BYOL 仅使用 positive pairs(Grill et al., 2020)。Chen 和 He (2020) 进一步提出了一种与先前方法有关的更简单的表述。最近,Zhao et al. (2020)发现数据增强对于对比学习至关重要。这可能表明为什么在数据增强不那么普遍的 NLP 中使用大型预训练模型进行无监督对比学习并不成功。他们还假设,实例判别比计算机视觉中的有监督预训练更好的原因是:它不会试图让一个类中所有实例的特征相似,而是保留每个实例的信息。在 NLP 中,Gunel et al. (2020)无监督的预训练涉及对成千上万个单词类型进行分类的问题不大。在 NLP 中,Gunel et al. (2020)最近采用对比学习进行有监督的微调。语言建模中常用的 one-hot 标签与模型输出的 logit 之间的交叉熵目标存在一些局限性,例如在不平衡的类中泛化效果较差(Cao et al., 2019)。对比学习是一种可选择的补充范式,可以帮助缓解其中的一些问题。对比学习与 masked 语言建模相结合能够让我们学习更丰富、更鲁棒的表征。它可以帮助解决模型异常值以及罕见的句法和语义现象带来的问题,这对当前的 NLP 模型是一个挑战。要评估的不只是准确率NLP 中的 SOTA 模型已在许多任务上实现了超越人类的表现,但我们能否相信这样的模型可以实现真正的自然语言理解(Yogatama et al., 2019; Bender and Koller, 2020)?其实,当前的模型离这个目标还很远。但矛盾的是,现有的简单性能指标无法体现这些模型的局限性。该领域有两个关键主题:a)精选当前模型难以处理的样例;b)不只是选择准确率等简单指标,而是进行更细粒度的评估。关于前者,常用的方法是在数据集创建过程中使用对抗过滤(Zellers et al., 2018),过滤出由当前模型正确预测的样例。最近的研究提出了更有效的对抗过滤方法(Sakaguchi et al., 2020; Le Bras et al., 2020)和一种迭代数据集创建处理方法(Nie et al., 2020; Bartolo et al., 2020),其中样例经过过滤,模型经过了多轮的重新训练。Dynabench 提供了此类不断变化的基准的子集。针对第二点的方法在本质上也是相似的。该领域通常会创建 minimal pairs(也称为反事实样例或对比集)(Kaushik et al., 2020; Gardner et al., 2020; Warstadt et al., 2020),这些 minimal pairs 以最小的方式干扰了样例,并且经常更改 gold label。Ribeiro et al. (2020) 在 CheckList 框架中形式化了一些基本的直觉,从而可以半自动地创建此类测试用例。此外,基于不同的属性来描述样例可以对模型的优缺点进行更细粒度的分析(Fu et al., 2020)为了构建功能更强大的机器学习模型,我们不仅需要了解模型是否优于先前的系统,还需要了解它会导致哪种错误以及还有哪些问题没被反映出来。通过提供对模型行为的细粒度诊断,我们可以更轻松地识别模型的缺陷并提出解决方案。同样,利用细粒度的评估可以更细致地比较不同方法的优缺点。语言模型的现实应用问题与 2019 年语言模型 (LMs) 分析侧重于此类模型所捕获的语法、语义和世界认知的氛围相比,最近一年的分析揭示了许多实际问题。比如经过预训练的 LM 容易生成「有毒」的语言 (Gehman et al., 2020)」、泄露信息 (Song & Raghunathan, 2020)。还存在微调后易受到攻击的问题,以致攻击者可以操纵模型预测结果 (Kurita et al., 2020; Wallace et al., 2020),以及容易受到模型的影响(Krishna et al., 2020; Carlini et al., 2020)。众所周知,预训练模型可以捕获关于受保护属性(例如性别)的偏见(Bolukbasi et al., 2016; Webster et al., 2020),Sun et al., 2019 的研究给出了一份减轻性别偏见的调查。大公司推出的大型预训练模型往往在实际场景中会有积极的部署,所以我们更应该意识到这些模型存在什么偏见,又会产生什么有害的后果。随着更大模型的开发和推出,从一开始就将这些偏见和公平问题纳入开发过程是很重要的。 Multilinguality2020 年,多语言 NLP 有诸多亮点。旨在加强非洲语种 NLP 研究的 Masakhane 机构在第五届机器翻译会议 (WMT20) 上发表的主题演讲,是去年最令人鼓舞的演讲之一。此外,这一年还出现了其他语言的新通用基准,包括 XTREME (Hu et al., 2020)、XGLUE (Liang et al., 2020)、IndoNLU (Wilie et al., 2020)、IndicGLUE (Kakwani et al., 2020)。现有的数据集也拓展到了其他语言中,比如:SQuAD: XQuAD (Artetxe et al., 2020), MLQA (Lewis et al., 2020), FQuAD (d'Hoffschmidt et al., 2020);Natural Questions: TyDiQA (Clark et al., 2020), MKQA (Longpre et al., 2020);MNLI: OCNLI (Hu et al., 2020), FarsTail (Amirkhani et al., 2020);the CoNLL-09 dataset: X-SRL (Daza and Frank, 2020);the CNN/Daily Mail dataset: MLSUM (Scialom et al., 2020)。通过 Hugging Face 数据集可以访问其中的大部分数据集,以及许多其他语言的数据。涵盖 100 种语言的强大模型也就应运而生了,包括 XML-R (Conneau et al., 2020)、RemBERT (Chung et al., 2020)、InfoXLM (Chi et al., 2020)等,具体可参见 XTREME 排行榜。大量特定语言的 BERT 模型已经针对英语以外的语言进行了训练,例如 AraBERT (Antoun et al., 2020)和 IndoBERT (Wilie et al., 2020),查看 Nozza et al., 2020; Rust et al., 2020 的研究可以了解更多信息。借助高效的多语言框架,比如 AdapterHub (Pfeiffer et al., 2020)、Stanza (Qi et al., 2020)和 Trankit (Nguyen et al., 2020) ,世界上许多语种的建模和应用工作都变得轻松了许多。此外,还有两篇很有启发的研究,《The State and Fate of Linguistic Diversity(Joshi et al., 2020)》和《Decolonising Speech and Language Technology (Bird, 2020)》。第一篇文章强调了使用英语之外语言的紧迫性,第二篇文章指出了不要将语言社区及数据视为商品。拓展到英语之外的 NLP 研究有很多好处,对人类社会能产生实实在在的影响。考虑到不同语言中数据和模型的可用性,英语之外的 NLP 模型将大有作为。同时,开发能够应对最具挑战性设置的模型并确定哪些情况会造成当前模型的基础假设失败,仍然是一项激动人心的工作。图像TransformersTransformer 在 NLP 领域取得了巨大的成功,但它在卷积神经网络 CNN 占据主导地位的计算机视觉领域却没那么成功。2020 年初的 DETR (Carion et al., 2020) 将 CNN 用于计算图像特征,但后来的模型完全是无卷积的。Image GPT (Chen et al., 2020)采用了 GPT-2 的方法,直接从像素进行预训练,其性能优于有监督的 Wide ResNet,后来的模型是将图像重塑为被视为「token」的补丁。Vision Transformer (ViT,Dosovitskiy et al., 2020)在数百万个标记好的图像上进行了训练,每一个图像都包含此类补丁,模型效果优于现有最新的 CNN。Image Processing Transformer(IPT,Chen et al., 2020)在被破坏的 ImageNet 示例上进行对比损失预训练,在 low-level 图像任务上实现了新的 SOTA。Data-efficient image Transformer (DeiT,Touvron et al., 2020) 以蒸馏方法在 ImageNet 上进行了预训练。有趣的是,研究者们发现了 CNN 是更好的教师,这一发现类似于蒸馏归纳偏置(inductive bias)应用于 BERT (Kuncoro et al., 2020)。相比之下在语音领域,Transformer 并未直接应用于音频信号,而通常是将 CNN 等编码器的输出作为输入(Moritz et al., 2020; Gulati et al., 2020; Conneau et al., 2020)。与 CNN 和 RNN 相比,Transformer 的归纳偏置更少。尽管在理论上,它不如 RNN (Weiss et al., 2018; Hahn et al., 2020)强大,但如果基于充足的数据和规模,Transformer 会超越其他竞争对手的表现。未来,我们可能会看到 Transformer 在 CV 领域越来越流行,它们特别适用于有足够计算和数据用于无监督预训练的情况。在小规模配置的情况下,CNN 应该仍是首选方法和基线。自然科学与机器学习去年,DeepMind 的 AlphaFold 在 CASP 蛋白质折叠挑战赛中实现了突破性的表现,除此之外,将机器学习应用于自然科学还有一些显著的进展。MetNet (Sønderby et al., 2020)证明机器学习在降水预测方面优于数值天气预报;Lample 和 Charton(2020)采用神经网络求解微分方程,比商用计算机系统效果更好;Bellemare et al. (2020)使用强化学习为平流层的热气球导航。此外,ML 现已被广泛应用于 COVID-19,例如 Kapoor 等人利用 ML 预测 COVID-19 的传播,并预测与 COVID-19 相关的结构,Anastasopoulos 等人将相关数据翻译成 35 种不同的语言,Lee 等人的研究可以实时回答有关 COVID-19 的问题。有关 COVID-19 相关的 NLP 应用程序的概述,请参阅第一期 COVID-19 NLP 研讨会的会议记录:《Proceedings of the 1st Workshop on NLP for COVID-19 (Part 2) at EMNLP 2020》。自然科学可以说是 ML 最具影响力的应用领域。它的改进涉及到生活的许多方面,可以对世界产生深远的影响。随着蛋白质折叠等核心领域的进展,ML 在自然科学中的应用速度只会加快。期待更多促进世界进步的研究出现。强化学习与最先进的智能体相比,Agent57 和 MuZero 整个训练过程中在雅达利游戏中的表现优于人类基准(Badia et al., 2020)。单个深度强化学习智能体 Agent57(Badia et al., 2020)首次在 57 款 Atari 游戏上超过人类,这也是深度强化学习领域中的一个长期基准。智能体的多功能性来自于神经网络,该网络允许在探索性策略和利用性策略之间切换。强化学习在游戏方面的另一个里程碑是 Schrittwieser 等人开发的 MuZero,它能预测环境各个方面,而环境对精确的规划非常重要。在没有任何游戏动态知识的情况下,MuZero 在雅达利上达到了 SOTA 性能,在围棋、国际象棋和日本象棋上表现也很出色。最后是 Munchausen RL 智能体(Vieillard et al., 2020),其通过一个简单的、理论上成立的修改,提高了 SOTA 水平。强化学习算法有许多实际意义 (Bellemare et al., 2020)。研究人员对这一领域的基本算法进行改进,通过更好的规划、环境建模和行动预测产生很大的实际影响。随着经典基准(如 Atari)的基本解决,研究人员可能会寻找更具挑战性的设置来测试他们的算法,如推广到外分布任务、提高样本效率、多任务学习等。参考内容:https://ruder.io/research-highlights-2020/本文来源:https://www.jiqizhixin.com/articles/2021-01-20-4
  • [技术干货] 情感分析方法入门(A)
    作者:Frank转自:网络人工智能园地https://zhuanlan.zhihu.com/p/3005950161、情感分析任务介绍文本情感分析(Sentiment Analysis)是指利用自然语言处理和文本挖掘技术,对带有情感色彩的主观性文本进行分析、处理和抽取的过程[1]。目前,文本情感分析研究涵盖了包括自然语言处理、文本挖掘、信息检索、信息抽取、机器学习和本体学等多个领域,得到了许多学者以及研究机构的关注,近几年持续成为自然语言处理和文本挖掘领域研究的热点问题之一。从人的主观认知来讲,情感分析任务就是回答一个如下的问题“什么人?在什么时间?对什么东西?哪一个属性?表达了怎样的情感?”因此情感分析的一个形式化表达可以如下:(entity,aspect,opinion,holder,time)。比如以下文本“我觉得2.0T的XX汽车动力非常澎湃。”其中将其转换为形式化元组即为(XX汽车,动力,正面情感,我,/)。需要注意的是当前的大部分研究中一般都不考虑情感分析五要素中的观点持有者和时间。情感分析问题可以划分为许多个细分的领域,下面的思维导图[2]展示了情感分析任务的细分任务:其中词级别和句子级别的分析对象分别是一个词和整个句子的情感正负向,不区分句子中具体的目标,如实体或属性,相当于忽略了五要素中的实体和属性这两个要素。词级别情感分析,即情感词典构建,研究的是如何给词赋予情感信息。句子级/文档级情感分析研究的是如何给整个句子或文档打情感标签。而目标级情感分析是考虑了具体的目标,该目标可以是实体、某个实体的属性或实体加属性的组合。具体可分为三种:Target-grounded aspect based sentiment analysis (TG-ABSA), Target no aspect based sentiment analysis (TN-ABSA), Target aspect based sentiment analysis (T-ABSA). 其中TG-ABSA的分析对象是给定某一个实体的情况下该实体给定属性集合下的各个属性的情感分析;TN-ABSA的分析对象是文本中出现的实体的情感正负向;T-ABSA的分析对象是文本中出现的实体和属性组合。下表例举了不同目标的情感分析任务:任务粒度文本情感词级中奖正向句子/文档级这家外卖分量足,味道好。正向目标级(TG-ABSA)2.0T涡轮增压发动机动力强,高速120超车没压力;外观是我和老婆都比较喜欢的款;后排空间有点小;有点费油啊。动力:正向外观:正向空间:负向油耗:负向目标级(TN-ABSA)丰田汽车比别克汽车更耐用。丰田:正向别克:负向目标级(T-ABSA)三星手机外观漂亮,苹果手机系统流畅。三星外观:正向苹果系统:正向2、情感分析常用文本预处理方法2.1中文分词技术词是最小的能够独立活动的有意义的语言成分,英文单词之间是以空格作为自然分界符的,而汉语是以字为基本的书写单位,词语之间没有明显的区分标记,因此,中文词语分析是中文信息处理的基础与关键。研究表明特征粒度为词粒度远远好于字粒度,其大部分分类算法不考虑词序信息,基于字粒度的损失了过多的n-gram信息。中文分词主要分为两类方法:基于词典的中文分词和基于统计的(HMM,CRF)中文分词。举个例子:“网商银行是蚂蚁金服微贷事业部的最重要产品”,其对应的分词结果为:网商银行/是/蚂蚁金服/微贷事业部/的/最重要/产品。当前我们讨论的分词算法可分为两大类:基于字典、词库匹配的分词方法;基于词频度统计(HMM,CRF)的分词方法。第一类方法应用词典匹配、汉语词法或其它汉语语言知识进行分词,核心是首先建立统一的词典表,当需要对一个句子进行分词时,首先将句子拆分成多个部分,将每一个部分与字典一一对应,如果该词语在词典中,分词成功,否则继续拆分匹配直到成功。如:最大匹配法、最小分词方法等。这类方法简单、分词效率较高,但汉语语言现象复杂丰富,词典的完备性、规则的一致性等问题使其难以适应开放的大规模文本的分词处理。第二类基于统计的分词方法则基于字和词的统计信息,统计学认为分词是一个概率最大化问题,即拆分句子,基于语料库,统计相邻的字组成的词语出现的概率,相邻的词出现的次数多,就出现的概率大,按照概率值进行分词,所以一个完整的语料库很重要。当前中文分词技术已经非常成熟,下表[3]展示了当前业界主流的分词服务支持的功能:2.2去除停用词停用词是指在信息检索中,为节省存储空间和提高搜索效率,在处理自然语言数据(或文本)之前或之后会自动过滤掉某些字或词,这些字或词即被称为Stop Words(停用词)。这些停用词都是人工输入、非自动化生成的,生成后的停用词会形成一个停用词表。但是,并没有一个明确的停用词表能够适用于所有的工具。甚至有一些工具是明确地避免使用停用词来支持短语搜索的。2.3 文本特征提取2.3.1 Bag of wordsBoW模型最初应用于文本处理领域,用来对文档进行分类和识别。其核心思想是建立一个词典库,该词典库包含训练语料库的所有词语,每个词语对应一个唯一识别的编号,利用one-hot文本表示。文档的词向量维度与单词向量的维度相同,每个位置的值是对应位置词语在文档中出现的次数,即词袋模型(BOW)BoW 模型因为其简单有效的优点而得到了广泛的应用。如下示例,给定两句简单的文档:文档 1:“我喜欢跳舞,小明也喜欢。”文档 2:“我也喜欢唱歌。”基于以上这两个文档,便可以构造一个由文档中的关键词组成的词典:词典={1:“我”,2:“喜欢”,3:“跳舞”,4:“小明”,5:“也”,6:“唱歌”}这个词典一共包含6个不同的词语,利用词典的索引号,上面两个文档每一个都可以用一个6维向量表示(用整数数字0~n(n为正整数)表示某个单词在文档中出现的次数。这样,根据各个文档中关键词出现的次数,便可以将上述两个文档分别表示成向量的形式:文档 1:[1, 2, 1, 1, 1, 0]文档 2:[1, 1, 0, 0, 1, 1]通过上面的例子可以看出,虽然BOW模型理解和实行起来简单,但是他有以下缺点问题:(1)容易引起维度灾难问题,语料库太大,字典的大小为每个词的维度,高维度导致计算困难,每个文档包含的词语数少于词典的总词语数,导致文档稀疏。(2)仅仅考虑词语出现的次数,没有考虑句子词语之间的顺序信息,即语义信息未考虑。2.3.2 TF-IDFTF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF是词频(Term Frequency),IDF是逆文本频率指数(Inverse Document Frequency)。TF-IDF的主要思想是:如果某个词或短语在一篇文章(句子)中出现的频率TF高,并且在其他文章(句子)中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。其中其计算方法如下:如下示例可以清楚说明TF-IDF的计算方法:假如一篇文件的总词语数是100个,而词语“母牛”出现了3次,那么“母牛”一词在该文件中的词频就是3/100=0.03。一个计算文件频率 (IDF) 的方法是文件集里包含的文件总数除以测定有多少份文件出现过“母牛”一词。所以,如果“母牛”一词在1,000份文件出现过,而文件总数是10,000,000份的话,其逆向文件频率就是 lg(10,000,000 / 1,000+1)=4。最后的TF-IDF的分数为0.03 * 4=0.12。2.3.3 预训练模型当我们用机器学习或者深度学习方法来处理NLP任务时,为了使自然语言成为计算机可以读懂的语言,首先我们需要对文本进行编码。在编码时,我们期望句子之间保持词语间的相似行,词的向量表示是进行机器学习和深度学习处理NLP任务的基础。由此也催生了各种各样的预训练模型发展,同时预训练加模型微调(Pre-training and fine tuning)的方法也是当前NLP领域各种任务state-of-art的方法的基本流程。预训练的方法最初是在图像领域提出的,达到了良好的效果,后来被应用到自然语言处理。预训练一般分为两步,首先用某个较大的数据集训练好模型(这种模型往往比较大,训练需要大量的内存资源),使模型训练到一个良好的状态,然后下一步根据不同的任务,改造预训练模型,用这个任务的数据集在预训练模型上进行微调。这种做法的好处是训练代价很小,预训练的模型参数可以让新的模型达到更快的收敛速度,并且能够有效地提高模型性能,尤其是对一些训练数据比较稀缺的任务,在神经网络参数十分庞大的情况下,仅仅依靠任务自身的训练数据可能无法训练充分,预训练方法可以认为是让模型基于一个更好的初始状态进行学习,从而能够达到更好的性能。预训练模型的发展也反映了深度学习在NLP领域的进步。NLP领域的预训练模型大致可以分为以下两类:基于词嵌入的预训练方法2003年,Bengio等人提出了神经语言模型(Neural Network Language Model)[4],神经语言模型在训练过程中,不仅学习到预测下一个词的概率分布,同时也得到了一个副产品:词嵌入表示。相比随机初始化的词嵌入,模型训练完成后的词嵌入已经包含了词汇之间的信息。2013年,Mikolov等人提出了word2vec工具,其中包含了CBOW(Continue Bag of Words)模型和Skip-gram模型[5-6],该工具仅仅利用海量的单语数据,通过无监督的方法训练得到词嵌入,在很长一段时间内word2vec在各种任务中都被广泛使用。基于语言模型的预训练方法词嵌入本身具有局限性,最主要的缺点是无法解决一词多义问题,即不同的词在不同的上下文中会有不同的意思,但是词嵌入对模型中的每个词都分配了一个固定的表示。针对上述问题,Peters等人提出了ELMo(Embedding from Language Model)[7],即使用语言模型来获取深层的上下文表示。ELMo的具体做法是,基于每个词所在的上下文,利用双向LSTM的语言模型来获取这个词的表示。ELMo的方法能够提取丰富的特征给下游任务使用,但是ELMo仅仅进行特征提取而没有预训练整个网络,远远没有发挥预训练的潜力。针对上述两个问题,Radford等人提出了 GPT Generative Pre-Training)[8],即生成式的预训练。GPT将LSTM换成了Transformer,获得了更高的成绩,但是由于使用的是单向模型,只能通过前面词预测后面的词,可能会遗漏信息。Devlin等人提出了BERT(Bidirectional Encoder Representations from Transformers)[9],即基于Transformer的双向编码器表示。BERT和GPT的结构和方法十分相似,最主要的不同之处在于GPT模型使用的是单向语言模型,可以认为是基于Transformer的解码器表示,而BERT使用的基于Transformer的编码器能够对来自过去和未来的信息进行建模,能够提取更丰富的信息。三个预训练模型的图如下所示:BERT提出后大火,也许是因为BERT的效果太好。目前绝大多数的预训练模型都是在BERT上改造而来。清华大学的王晓智和张正彦同学给出了目前的预训练模型关系图,这里引用一下,如下图所示:总结本篇博文主要介绍了情感分析任务的概述以及进行情感分析任务之前我们需要进行的准备工作,其中着重介绍了NLP领域最重要的预训练模型的主要里程碑。下一篇博文将着重介绍进行情感分析任务的具体方法,包括传统基于统计的方法和深度学习方法。参考文献PANG B,LEE L. Opinion mining and sentiment analysis[J].Foundations and Trends in InformationRetrieval,2008,2 (1 -2) :130 - 135.https://www.infoq.cn/article/XGoSsRfZRSupblTGGJCMhttps://blog.csdn.net/fendouaini/article/details/82027310Bengio Y, Ducharme R, Vincent P, et al. A neural probabilistic language model.Mikolov T, Chen K, Corrado G S, et al. Efficient Estimation of Word Representations in Vector Space.Mikolov T, Sutskever I, Chen K, et al. Distributed Representations of Words and Phrases and their Compositionality.Matthew Peters, Mark Neumann, Mohit Iyyer, Matt Gardner, Christopher Clark, Kenton Lee, and Luke Zettlemoyer. 2018. Deep Contextualized Word Representations.Alec Radford, Karthik Narasimhan, Tim Salimans, and Ilya Sutskever. 2018. Improving Language Understanding by Generative Pre-Training.Jacob Devlin, Ming-Wei Chang, Kenton Lee, and Kristina Toutanova. 2018. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding.
  • [技术干货] 中文预训练语言模型回顾
    论文名称:Revisiting Pre-trained Models for Chinese Natural Language Processing论文作者:崔一鸣,车万翔,刘挺,秦兵,王士进,胡国平 原创作者:崔一鸣 论文链接:https://www.aclweb.org/anthology/2020.findings-emnlp.58 转载须标注出处:哈工大SCIR1. 简介以BERT为代表的预训练语言模型在众多自然语言处理任务中取得了显著性能提升,并且随后涌现出一批效果更优的预训练语言模型。在本文中,我们将经典的预训练语言模型应用在中文场景并使用相同的实验设置去验证它们在中文领域的性能表现。同时,我们创新地提出了一种基于文本纠错的预训练语言模型MacBERT,应用纠错型掩码语言模型(MLM as correction,Mac)解决了预训练模型中“预训练-精调”不一致的问题。为了验证实验效果,我们选择了8个经典的中文自然语言处理任务,包括阅读理解、单句文本分类、句对文本分类等。大量实验结果表明所提出的MacBERT能够在大多数任务上取得显著性能提升。我们已将所有本文涉及到的中文预训练资源进行开源,希望能够进一步促进中文信息处理的研究与发展。2. 构建中文预训练系列模型首先,我们提出了一整套的中文预训练系列模型,以构建较为完整的基线系统并为后续工作提供相对标准的参照数据。我们主要训练了以下几种预训练语言模型:BERT-wwm:我们在谷歌原版中文BERT-base[1]的基础上,将全词掩码技术(Whole Word Masking,wwm)应用在中文环境,即在掩码语言模型(Masked Language Model,MLM)中使用词粒度进行掩码。我们使用了LTP[2]作为中文分词工具。需要注意的是,虽然掩码粒度为词,但模型的输入仍然以字为粒度(使用WordPiece分词)进行切分,即与原版BERT并无差别。XLNet:Yang等人提出基于Transfromer-XL构建了XLNet模型[3],解决了BERT的“预训练-精调”不一致的问题,提出了Permutation Language Model。与BERT不同的是,XLNet采用了sentencepiece进行分词,因此分词粒度更大。RoBERTa-wwm:RoBERTa模型[4]由Liu等人提出,进一步挖掘了BERT的潜力。我们训练的RoBERTa-wwm与BERT-wwm类似,但从中删除了Next Sentence Prediction(NSP)预训练任务,并使用了全词掩码技术。需要注意的是,与英文RoBERTa不同,这里我们同样使用了WordPiece分词。通过后续实验发现WordPiece相比sentencepiece在中文预训练模型中更有效。ELECTRA:Clark等人提出一套全新的生成器-判别器架构的预训练模型ELECTRA[5],其中生成器是一个小型的MLM,用于替换输入文本。而判别器则是判断输入文本是否经过替换。由于判别器只需进行二分类,相比传统MLM来说效率更高。在下游任务精调中,我们只使用判别器。3. MacBERT为了解决预训练模型中的“预训练-精调”不一致的问题,我们巧妙地修改了掩码语言模型,并提出基于文本纠错的掩码语言模型(MLM as correction,Mac)。该方法不需要对现有结构进行任何改动,只需针对掩码方式进行改变,因此极大程度地保留了BERT的原始特性,并可以无缝迁移到任何使用BERT的下游任务精调代码中。 具体地,针对掩码语言模型任务,我们进行了如下修改:我们使用全词掩码技术以及N-gram掩码技术来选择待掩码的token,其中unigram至4-gram的概率分别为40%、30%、20%、10%。为了解决[MASK]标记在下游任务中不会出现的问题,我们提出使用相似词来替换[MASK]标记。我们使用Synonyms库[6]来获取待掩码单词的相似词。在N-gram掩码时,我们针对N-gram中的每个词均进行相似词替换。在少数情况下,当相似词不存在时,我们将使用词表中的随机词进行替换。与原版BERT类似,我们对输入序列总长度15%的token进行掩码,其中80%的情况下会替换为相似词,10%的情况下会替换为随机词,剩余10%则不进行任何替换(负样本)。下表给出了几种不同的掩码方式的对比示例。表1 不同掩码方式的对比除此之外,由于ALBERT模型[7]在众多自然语言处理任务上获得显著性能提升,我们采用了其中的Sentence Order Prediction(SOP)预训练任务来替换BERT中的Next Sentence Prediction(NSP)任务。在SOP任务中,正样本由相邻的两个片段构成,而负样本则是将两个片段的顺序进行倒置。4. 实验4.1. 预训练模型设置接下来简要介绍预训练模型的训练设置,详细内容请参考论文的4.1节。预训练数据:我们采用了中文维基百科数据(同时保留简体和繁体中文)以及额外爬取的中文数据(包括百科、问答、新闻等),总词数达到了5.4B。在模型中我们以ext标记采用扩展数据的BERT或RoBERTa模型。基本参数:我们对所有模型(除XLNet)采用了统一预训练词表,与原版中文BERT-base相同,包含21128个token。序列最大长度设置为512。训练设备:根据模型规模大小,我们采用了单个TPU v3或者TPU v3-32进行训练。4.2. 下游精调数据集我们选用了以下8个中文自然语言处理数据集:阅读理解:CMRC 2018[8],DRCD[9],CJRC[10] 单句文本分类:ChnSentiCorp[11],THUCNews[12] 句对文本分类:XNLI[13],LCQMC[14],BQ Corpus[15]为了保证结果的稳定性,对于每一组实验结果,我们均运行10次,并汇报其平均值和最大值。相关实验超参设置请参考论文的表2。4.3. 实验结果本文涉及的预训练模型的部分实验结果如下表所示(详细结果请参考论文4.3节)。可以看到MacBERT在多数任务上取得了显著性能提升,尤其在机器阅读理解的各项任务中的提升更为明显。表2 CMRC 2018中文阅读理解结果4.4. 消融实验为了进一步了解性能提升的来源,我们对MacBERT-large进行了消融实验。可以看到,整个模型中最重要的部分是纠错型掩码语言模型(Mac)和N-gram掩码语言模型(NM),而相对来说模型使用NSP还是SOP预训练任务并没有对模型性能造成很大影响,因此后续工作应进一步将重点放在掩码语言模型及其变种模型的设计上。表4 MacBERT模型上的消融实验结果5. 讨论前面提到MLM任务是这类预训练语言模型最重要的组成部分。MLM类任务包括两个方面:1)如何选择需要掩码的token;2)待掩码的token替换成什么。在前面的章节中,我们已经展示了不同的选择掩码token的方法,例如全词掩码、N-gram掩码等。现在我们将探索第二个方面,即探索“待掩码的token替换成什么”。我们在CMRC 2018和DRCD数据集上进行了验证。在15%的整体掩码比例下,其中的10%将保持不变(负样例),而剩余的90%将采取如下4类方案进行对比。MacBERT:80%的词替换成相似词,10%替换为随机词;随机替换:90%的词替换为随机词;部分MASK:(BERT原始MLM)80%替换为[MASK],10%替换为随机词;全部MASK:90%的词替换为[MASK]。实验结果如下图所示。可以看到依赖于替换成[MASK]的实验设置(例如部分MASK和全部MASK)下效果相对较差,说明“预训练-精调”不一致的确会为下游任务带来一定的性能下降。而简单地将所有待掩码的词替换为随机词后,其性能显著优于依赖[MASK]的MLM方法。最后,我们使用相似词进行进一步优化后,其性能还会得到显著提升,说明MacBERT设计是有效的。6. 结论在本文中,我们回顾了经典预训练语言模型在中文场景下的性能表现,以验证这些模型在非英文语种上的通用性。同时我们提出了一种基于文本纠错的预训练语言模型MacBERT,解决了预训练模型中的“预训练-精调”不一致的问题。大量实验结果表明所提出的MacBERT能够在多数任务上带来显著性能提升。我们已将所有与本文相关的中文预训练语言模型开源,并希望能够进一步促进中文信息处理的研究与发展。基于我们在文章最后的分析讨论,未来我们将探索一种有效调整掩码比例的方法以取代手工设置的方案,从而进一步提升预训练语言模型的性能表现。7. 参考文献[1] Jacob Devlin, Ming-Wei Chang, Kenton Lee, and Kristina Toutanova. BERT: Pre-training of deep bidirectional transformers for language understanding. In NAACL 2019. [2] Wanxiang Che, Zhenghua Li, and Ting Liu. LTP: A chinese language technology platform. In COLING 2010. [3] Zhilin Yang, Zihang Dai, Yiming Yang, Jaime Carbonell, Ruslan Salakhutdinov, and Quoc V Le. Xlnet: Generalized autoregressive pretraining for language understanding. arXiv preprint arXiv:1906.08237. [4] Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar Joshi, Danqi Chen, Omer Levy, Mike Lewis, Luke Zettlemoyer, and Veselin Stoyanov. Roberta: A robustly optimized bert pretraining approach. arXiv preprint arXiv:1907.11692. [5] Kevin Clark, Minh-Thang Luong, Quoc V. Le, and Christopher D. Manning. ELECTRA: Pretraining text encoders as discriminators rather than generators. In ICLR. [6] Zhenzhong Lan, Mingda Chen, Sebastian Goodman, Kevin Gimpel, Piyush Sharma, and Radu Soricut. Albert: A lite bert for self-supervised learning of language representations. arXiv preprint arXiv:1909.11942. [7] Hailiang Wang and Yingxi Hu. 2017. Synonyms. https://github.com/huyingxi/Synonyms [8] Yiming Cui, Ting Liu, Wanxiang Che, Li Xiao, Zhipeng Chen, Wentao Ma, Shijin Wang, and Guoping Hu. A Span-Extraction Dataset for Chinese Machine Reading Comprehension. In EMNLP 2019. [8] Chih Chieh Shao, Trois Liu, Yuting Lai, Yiying Tseng, and Sam Tsai. Drcd: a chinese machine reading comprehension dataset. arXiv preprint arXiv:1806.00920. [9] Xingyi Duan, Baoxin Wang, Ziyue Wang, Wentao Ma, Yiming Cui, Dayong Wu, Shijin Wang, Ting Liu, Tianxiang Huo, Zhen Hu. Cjrc: A reliable human-annotated benchmark dataset for chinese judicial reading comprehension. In CCL 2019. [10] Songbo Tan and Jin Zhang. 2008. An empirical study of sentiment analysis for chinese documents. Expert Systems with applications, 34(4):2622–2629. [11] Jingyang Li and Maosong Sun. Scalable term selection for text categorization. In EMNLP 2007. [12] Alexis Conneau, Ruty Rinott, Guillaume Lample, Adina Williams, Samuel R. Bowman, Holger Schwenk, and Veselin Stoyanov. Xnli: Evaluating crosslingual sentence representations. In EMNLP 2018. [13] Xin Liu, Qingcai Chen, Chong Deng, Huajun Zeng, Jing Chen, Dongfang Li, and Buzhou Tang. Lcqmc: A large-scale chinese question matching corpus. In COLING 2018. [14] Jing Chen, Qingcai Chen, Xin Liu, Haijun Yang, Daohe Lu, and Buzhou Tang. The BQ corpus: A large-scale domain-specific Chinese corpus for sentence semantic equivalence identification. In EMNLP 2018.
  • [赛事资讯] 华为云获得自然语言处理领域顶级赛事NLPCC开放任务第一名
    近日,华为云 AI 团队获得第 9 届国际自然语言处理与中文计算会议 NLPCC 2020 轻量级预训练中文语言模型测评第一名。NLPCC 由中国计算机学会主办,是自然语言处理(NLP)和中文计算(CC)领域的顶级国际前沿会议,每年会议都秉承国际化和一流化的严格标准来进行自然语言处理任务的开放评测,推动相关任务的研究和发展。NLPCC 2020 吸引了康奈尔大学、伦敦大学、普林斯顿大学等海内外近 600 位自然语言处理领域的专家及学者参加大会,其中 400 余位专家学者在现场共同见证开放评测任务第一名的诞生。当下,预训练语言模型已经成为 NLP 的主流方法,在多项 NLP 任务上都取得了明显的效果提升。但是预训练语言模型往往比较大,限制了预训练语言模型的应用场景。因此,如何构建轻量级的预训练语言模型就成了一个关键问题。预训练语言模型出现以来发展得非常迅速,目前已经演化形成了一个家族中文轻量级预训练语言模型能力评测任务的目的在于让参赛团队减少语言模型大小的同时尽可能保证模型效果。本次比赛包含四个任务,分别是指代消解,关键词识别两个句子级别分类任务,实体识别序列标注任务,MRC 阅读理解任务,从不同角度评测模型的语义表达能力。同时,比赛要求模型的参数量低于 bert-base 模型的 1/9,模型推理速度达到 bert-base 模型的 8 倍,这就要求模型运行快,体积小,效果好。一般来说,可以通过量化、剪枝、蒸馏等方法来压缩大预训练语言模型来获得轻量级模型。华为云与诺亚方舟实验室联合团队基于自研的 NEZHA 中文预训练模型通过知识蒸馏得到 tiny-NEZHA 轻量级模型摘得桂冠。相比其他模型,华为的模型在结构上找到了一个较好的平衡点,采用 TinyBERT 两步蒸馏的方式让模型更好地学到任务相关的知识,蒸馏过程中用语言模型预测并替换部分 token 的方式进行数据增强可以使小模型拥有更强泛化性。TinyBERT 知识蒸馏的损失函数中一个重要环节是让中间层去学习隐藏状态和 attention 向量同时,华为自研的 NEZHA 预训练语言模型采用相对位置编码替换 BERT 的参数化绝对位置编码,能更直接地建模 token 间的相对位置关系,从而提升语言模型的表达能力。在即将过去的 2020 年里,华为云 AI 在人工智能领域的研发成绩斐然,斩获十二项包含 WSDM、WebVision、CCKS 篇章级事件抽取技术评测冠军、人工智能金炼奖、德国红点在内的国际国内榜单冠军和奖项。面向未来,华为云 AI 希望可以继续保持技术优势,做智能世界的「黑土地」,持续践行普惠 AI,将 AI 服务触及更多开发者和企业,助力各行各业进入人工智能新时代。本文来源:https://www.jiqizhixin.com/articles/2020-12-31
  • [技术干货] 26亿参数,智源、清华开源中文大规模预训练模型
    近日,北京智源人工智能研究院和清华大学研究团队联合发布了以中文为核心的大规模预训练语言模型 CPM-LM,参数规模达 26 亿,预训练中文数据规模 100 GB。自 2018 年谷歌发布 BERT 以来,预训练模型在自然语言处理(NLP)领域逐渐成为主流。今年 5 月份,OpenAI 推出的史上最大 AI 模型 GPT-3更是引起了大量讨论。但是,目前 NLP 领域的预训练模型多针对英语语言,以英语语言数据为训练数据,例如 GPT-3:用于训练 GPT-3 的数据集。近日,北京智源人工智能研究院和清华大学研究团队合作开展了一项名为「清源 CPM (Chinese Pretrained Models)」的大规模预训练模型开源计划,旨在构建以中文为核心的大规模预训练模型。首期开源内容包括预训练中文语言模型和预训练知识表示模型,可广泛应用于中文自然语言理解、生成任务以及知识计算应用,所有模型免费向学术界和产业界开放下载,供研究使用。清源 CPM 主页:https://cpm.baai.ac.cn/清源 CPM Github 托管代码主页:https://github.com/TsinghuaAI/模型特点根据清源 CPM 主页介绍,该计划发布的预训练模型具备以下特点:模型规模大:本次发布的CPM-LM 参数规模达 26 亿,预训练中文数据规模 100 GB,使用了 64 块 V100 GPU,训练时间约为 3 周;CPM-KG 的参数规模为 217 亿,预训练结构化知识图谱为 WikiData 全量数据,包含近 1300 个关系、8500 万实体、4.8 亿个事实三元组,使用了 8 块 V100 GPU 训练时间约为 2 周。语料丰富多样:收集大量丰富多样的中文语料,包括百科、小说、对话、问答、新闻等类型。学习能力强:能够在多种自然语言处理任务上进行零次学习或少次学习,并达到较好的效果。行文自然流畅:基于给定上文,模型可以续写出一致性高、可读性强的文本,达到现有中文生成模型的领先效果。在模型训练方面,CPM 模型预训练过程分布在多块 GPU 上,采用层内并行的方法进行训练,并基于当前已有的成熟技术,减少同步提高通讯速率。在硬件设施方面,为训练该 CPM 模型,共有 64 块 V100 显卡投入使用。经过预训练的 CPM 模型可以用来促进诸多下游中文任务,如对话、论文生成、完形填空和语言理解等。为了促进中文自然语言处理研究的发展,该项目还提供了 CPM-LM (2.6B) 模型的文本生成代码,可用于文本生成的本地测试,并以此为基础进一步研究零次学习 / 少次学习等场景,详情参见项目 GitHub 主页。模型性能清源 CPM 使用新闻、百科、对话、网页、故事等不同类型的中文语料数据进行预训练。在多个公开的中文数据集上的实验表明,清源 CPM 在少样本或无样本的情况下均能够实现较好的效果。中文成语填空 ChIDChID 是 2019 年清华大学对话交互式人工智能实验室(CoAI)收集的中文成语填空数据集,其目标是对于给定的段落,在 10 个候选项中选择最符合段意的成语进行填空。其中有监督设定是指在 ChID 的训练集上进行训练,随后在测试集上测试;无监督设定是指不经过任何额外训练,直接使用预训练模型进行测试。具体做法是,将候选项依次填入段落中,计算填充后段落的困惑度 (Perplexity),选择困惑度最小的候选项作为预测结果。表中汇报了预测的准确率,可以看到,CPM (大) 在无监督设定下甚至达到了比有监督 CPM (小) 更好的结果,反映出清源 CPM 强大的中文语言建模能力。对话生成 STCSTC 是 2015 年华为诺亚方舟实验室提出的短文本对话数据集,要求在给定上文多轮对话的条件下预测接下来的回复。其中 CDial-GPT 是清华大学对话交互式人工智能(CoAI)实验室 2020 年提出的中文对话预训练模型。用于衡量多样性的 Dist-n 指标的两个数字分别是所有不重复的 N-Gram 的数量及占所有 N-Gram 的比例。可以看到,在无监督的设定下,清源 CPM 具有更好的泛化性,在有监督设定下,清源 CPM 能达到比 CDial-GPT 更优的效果,尤其在多样性指标上表现更佳。文本分类清源 CPM 使用头条新闻标题分类(TNEWS,采样为 4 分类)、IFLYTEK 应用介绍分类(IFLYTEK,采样为 4 分类)、中文自然语言推断(OCNLI,3 分类)任务作为文本分类任务的基准。具体做法是,先输入分类样本,再输入「该文章的类别为 / 该介绍的类别为 / 两句话的关系为」,要求模型直接生成标签,四个标签中概率最高的标签作为预测结果。在无监督设定下,不同规模的清源 CPM 在文本分类任务上的精确度如下表所示:清源 CPM 能够在无监督的设定下达到比随机预测好得多的精确度(TNEWS/IFLYTEK/OCNLI 随机预测精确度分别为 0.25/0.25/0.33)。自动问答CPM 使用 DuReader 和 CMRC2018 作为自动问答任务的基准,要求模型从给定段落中抽取一个片段作为对题目问题的答案,其中 DuReader 由百度搜索和百度知道两部分数据组成。在无监督的设定下,不同规模的 CPM 模型的表现如下表所示:其中单样本是指在测试时,从数据集中随机抽取一个正确的「(段落,问题,答案)」三元组,插入到用于评价的样例前,作为 CPM 模型生成答案的提示;零样本是指直接使用 CPM 模型预测给定段落和问题的答案。在单样本设定下,CPM 能从给定的样本中学习到生成答案的模式,因此效果总是比零样本设定更好。由于模型的输入长度有限,多样本输入的场景将在未来进行探索。模型效果展示我们可以从以下示例中,观察 CPM 预训练中文语言模型的效果。比如基于对单个常识性问题的学习,依照规律进行提问和正确回答:根据前文真实的天气预报,继续报道天气预报(不保证正确性):执行数理推理:甚至续写《红楼梦》片段:据了解,清源 CPM 未来计划开源发布更大规模的预训练中文语言模型、以中文为核心的多语言预训练模型、融合大规模知识的预训练语言模型等。本文转载自:https://news.51cto.com/art/202011/632184.htm?pc
  • [前沿快讯] 刘群:预训练语言模型研究进展和趋势展望
    作者 | 戚路北自2018年下半年开始,到现在为止,预训练语言模型的发展基本呈现爆发趋势,研究人员数目越来越多,研究方向也越来越广。近日,在第十九届中国计算语言学大会(CCL2020)上,华为诺亚方舟实验室语音语义首席科学家刘群介绍了预训练语言模型研究进展和趋势展望。演讲内容包括自然语言处理的预训练方法的背景,预训练语言模型的近期进展,华为课题组的成员们做的工作,以及目前的成就与未来的展望。刘群是自然语言处理和机器翻译领域的国际著名专家,研究方向包括多语言信息处理、机器翻译模型、方法与评价等。2012 年 7 月之前,刘群是中国科学院计算技术研究所的研究员和自然语言处理研究组负责人。2012 年 7 至 2018 年 6 月,刘群任都柏林城市大学教授、爱尔兰 ADAPT 研究中心(前身 CNGL 研究中心)自然语言处理主题负责人。2018 年 7 月开始,他正式加入华为诺亚方舟实验室,任语音语义首席科学家,主导语音和自然语言处理领域的前沿研究和技术创新,除了语音、对话、翻译、多模态以外,其实验室也在重点布局预训练语言模型。以下是演讲全文,AI科技评论进行了不改变原意的整理。1自然语言处理的预训练方法的背景自然语言处理的预训练方法属于自然语言的表示学习,自然语言表示学习的形成已经经过了长期的历史发展。首先,1948年N-gram分布式模型被提出来,这是最初的语言模型。1986年出现了分布式语义表示,即用一个词的上下文来表示该词的词义。2003年神经语言模型被提出,开始使用神经网络来进行语言建模。2013年word2vec的提出,标志着神经网络方法开始在NLP领域获得成功,word2vec将词语从一个符号空间映射到了一个向量空间,使得NLP中大规模使用神经网络方法成为可能。到2018年,出现了预训练语言模型。不管是统计方法还是神经网络方法,都是一种基于数据的方法。如果数据不够的话,模型就无法有效建立。但是现实生活中,数据永远是一个很大的问题。在实际应用场景中,我们得到的很多数据都是无标注的,在这种情况下传统模型就无法解决实际问题。预训练的思想是,在利用标注数据之前,先利用无标注的数据也就是纯文本数据,去训练一个模型,这个模型能够学到一些潜在的跟标注无关的知识。然后在具体的任务上,预训练模型就可以利用大量的无标注数据训练所得到的知识。第一代自然语言处理预训练模型是词向量模型。词向量模型是把大量的无标注的文本送到一个比较简单的神经网络里面,经过训练,每个词都会被赋予一个静态的向量。词的静态向量在空间分布上有一个非常好的特点,即相似的词会聚在一起。词与词之间的关系也会以一种向量的形式得到体现,从而实现了符号空间到向量空间的映射。第二代自然语言处理的预训练模型,就是我们今天研究和使用的预训练语言模型。预训练语言模型是词向量模型的进化,它的本质其实是有上下文的词向量模型。预训练语言模型的训练过程是,首先给句子中的每个词赋予一个静态向量,然后它会跟句子的上下文词进行交互,最后就得到了这个词在句子中的变化的词向量。这种特殊的词向量模型我们叫做预训练语言模型。预训练语言模型有一个很重要的特点,它既会给每一个句子赋予一个概率,同时还会给每个词赋予一个表示或一些特征。利用预训练语言模型的这个特点,就可以使用现实生活中几乎无穷无尽的无标注文本,来训练预训练语言模型,然后就能把经过训练的预训练语言模型,用在任何的下游任务上。这不仅可以使下游任务的性能得到非常大的提高,还可以大大降低下游任务所依赖的标注语料的规模。实际上,预训练语言模型的出现,几乎使所有的下游任务的性能都得到了很大的提高,使得自然语言处理技术又上了一个台阶,因此这是一个具有重大意义的突破。在实际应用中,使用预训练语言模型可以分成两个过程,一个叫预训练,一个叫微调。首先在大量的文本上训练出一个预训练语言模型,然后在下游的任务上,根据实际情况对得到的预训练语言模型进行微调。Transformer模型是预训练语言模型的主要框架,它的主要特点就是词与词之间可以互相关注。类似于卷积神经网络中具有多个卷积核,并且每个卷积核会自动去会分配不同的权重,Transformer的基本结构的每一层都由多头的自注意力网络,以及一个前向的神经网络共同组成。自注意力机制是预训练语言模型中非常有趣的机制。通过一些可视化工具,我们可以看到不同的自注意力头呈现出不同的特点或不同的关注结构,比如关注句子的第一个词、相邻的词、中心词甚至是句子结尾的标点符号。所有的关注信息,或者说词的注意力都可以在可视化图里看到。预训练语言模型出现以来发展得非常迅速,目前已经演化形成了一个家族。2预训练语言模型的近期进展预训练语言模型的近期进展包括以下几个方面:1.更强大,也被戏称为叫大力出奇迹。2.更小巧,即怎么把做模型做的更小、更快。3.更优秀、功能更多、性能更高、训练更快的模型。4.更聪明,即怎么引入外部知识。5.更能干,即预训练语言模型如何影响了自然语言处理以外的一些领域。1.更强大预训练语言模型几乎成为了大公司之间的军备竞赛,目前学术界还还很难参与这种军备竞赛。很多大企业都将自己的预训练语言模型做的越来越大,仿佛没有终点,并且这种趋势还在不断加强。预训练语言模型的做大不仅仅是带来量的提高,更带来了模型使用性质的变化。最早在词向量模型时期,整个自然语言处理就被带入了神经网络时代。在神经网络时代,单一的CPU已经不能满足需求了。可以通过GPU,在不需要进行过多额外计算的情况下,做到在整个词表上进行词的选择,这在以前的SMT上是不可想象的。正是有了GPU,我们才可以通过词向量模型这类神经语言模型来完成这类工作。如果没有GPU支持,或者用以前的统计方法,是难以想象的。预训练语言模型通过使用更大的GPU,更多的数据,也带来了更大的变化,即微调的模式。微调为下游任务大致规定了几种固定的模式,包括句子分类、句子关系的分类、词语序列标注,以及QA任务中常见的句子片段的提取等。以前解决每个NLP问题,都要先设计模型。现在通过微调这一简单的模式,我们不再需要去为每个任务去设计特定的NLP模型,而可以将所有的NLP任务都纳入几个模式。GPT-3有一个非常吸引人的地方,就是它几乎无需做微调,并且它的演示效果也很好。GPT-3给我们带来了非常大的冲击。这个模型有着极高的训练成本,使得实际上绝大部分的企业和科研机构都无力承担。它的1750亿参数比BERT-base模型大了100倍,比 GPT-2大了10倍。它单次训练需要1万亿单词的训练数据,以及1200万美元的训练成本,能够承担这种训练成本的企业在世界范围内也非常少。虽然它的训练成本如此之高,但是它的效果非常令人吃惊。以前我们解决特定的问题,都需要专门去找语料,做专门的训练才能做。现在这个模型,只要是需要的功能都可以直接实现,基本不用训练。还有一些我们原来觉得很难做到的事情,GPT-3也能做到,例如算术计算、写代码等等。它还能够很细致的区分56和49这两个词,甚至在数量上都能区分出来,如此的细腻度令人吃惊,这也给它的商业价值也带来巨大的想象空间。很多人都在想,大算力会不会成为预训练语言模型的瓶颈?实际上,算力最终并不会成为瓶颈。上世纪90年代IBM提出统计机器翻译模型的时候,大家几乎都重复不了。但是99年以后,统计机器翻译模型基本上变成普遍的、所有人都能用的模型了。深度学习也是一样,深度学习在GPU出现以前,也是曲高和寡,然而 GPU的出现,突破了算力瓶颈以后,也变成了一种普通的工具。那么GPT-3这样的模型,现在的成本虽然非常高,但是我们大家可以去憧憬一下,未来的某一天,它或许也会变成一种非常普遍的工具。训练大模型实际上是很困难的,它并不是在单一的CPU或者GPU上进行训练,而是在多个硬件的组合结构上进行训练。但同时,每引入一种更复杂的硬件结构,也会带来更多的问题。上图为一些常见的用来解决这些问题的技术。下面着重介绍三维并行训练技术和稀疏注意力加速技术。三维并行训练技术,是指把数据和模型进行各种维度的切分,包括数据并行、pipeline并行和模型并行。模型并行又包括不同类型的模型变形,通过把整个数据和模型进行三维的切分,建立三维并行坐标和物理设备之间的映射,然后每一个区域运行一小块的方法。稀疏注意力加速技术也是一个被证明有效的技术,GPT-3就使用了这个技术。它的原理是把一个注意力矩阵分成两个小型矩阵的乘积,这是一个可以有效处理更长注意力的机制,这也是目前为止被证明非常有效的办法。2.更小巧目前的大型预训练模型,不但训练麻烦,而且推理时间也很长,因此只能用在云端应用上,在设备端应用有明显的局限性。因此训练出更小的模型,实际上也具有非常大的应用价值。就华为来说,华为目前的业务方向除了手机业务外,也在做大量的用于物联网的小设备。既然希望将模型用到小设备上,我们就面临将模型进行加速和压缩的问题。预训练语言模型就形成了这两种趋势。一方面是人们把模型越做越大,去探索模型能力的边界。另外一方面就是模型越做越小,让它在各种下游任务上形成生产力,即在手机端等各种小设备上能够单独运行。目前模型压缩这一方面研究也非常多,主要包括三大类技术,一类是基于知识蒸馏的预训练语言模型压缩,另一类是基于剪枝的预训练语言模型压缩,还有一类是基于量化的预训练语言模型压缩。基于剪枝的预训练语言模型压缩,就是基于一定的准则,去除掉参数矩阵的冗余部分。比如在神经网络模型中,我们可以去掉一些冗余的神经元节点,和神经元连接,使得模型变小一点。基于量化的预训练语言模型压缩,就是减少数值表示所需要的比特值。目前我们使用的GPU都是用32位的浮点数计算,计算代价非常高。我们可以将它量化为8位的浮点数,甚至4位的浮点数、2位的浮点数,这样运算过程就得到了简化。还有一些别的压缩技术,比如矩阵参数分解、参数共享、模型架构设计与搜索。矩阵参数分解就是将一个大矩阵,分解成两个小矩阵的乘积。参数共享有很多方式,比如Transformer有很多层,各层之间可以共享其中一些参数。而ALBERT,就是所有的层共享其中一层的参数。共享参数的好处就是参数量大大减少,但实际上在推理时间上并不能大幅度减少,所以它能带来的好处还是有限。模型架构设计与搜索这方面的发展,其实跟近年来自动机器学习的发展有关系,我们希望通过自动机器学习,能够去搜索出更好的、更精简的架构。3.更优秀目前看来Transformer模型架构确实非常优秀,当下也很难去做大的改动。真正做出一些影响力的工作是transformer XL,它的贡献是引入了recurrent的思想,以及引入了相对位置编码。而其它方面的话,大的改动很少。另外就是试图降低复杂度,因为attention机制是每两个词之间都要做一次 attention,这样的话attention的计算数量就是一个句子长度的平方级。在日常处理更长的文本的时候,都会面临这样的问题。目前我们需要的文本长度一般都不能超过1024,很多任务甚至只能用512或者256。很多研究工作速度希望把它的计算数量从平方量级降到线性量级,从而可以使语言模型处理更长的文本,所以目前这方面的研究也非常多。除了去寻找更好的模型结构,我们还需要训练更复杂的任务。现在BERT训练的过程实际上并不高效,它的训练时间很长,很多学者就试图在这方面去改进,提出更好的训练任务。Baseline是基础的预训练语言模型的训练,包括LM、MLM和NSP等训练任务。除此之外,大家也提出了各种各样的新的训练任务来进行改进。BERT就提出了几种新的训练方法,一种叫做next sentence prediction(NSP),就是根据前文预测下一个句子。另一种叫做whole word masking,这跟BERT的设计有关系。因为BERT里很多词都被拆分成一个个小单位,这样单独预测其中一个subword难度就比较小。通过把小单位合起来,加大训练难度,预测效果就会更好一点。以下还列举了其它模型的一些训练任务。replaced token prediction:也就是将一个词给换掉,然后来预测这个词是换掉之后的词还是原来的词。Sentence order prediction:将两个句子的顺序给颠倒,来检测哪种顺序是正确的。Denoising Autoencoder:这个是更复杂的训练任务,它是对一个句子进行插入、删除、替换等操作之后,再将它还原出来。Multi-task Learning:它同时使用了多种训练任务。Generator and discriminator:它是用一个生成器去替换一些词,然后由判别器来判断每个词是否替换。它的好处在于一个句子中的所有词都可以做错误的反向传播,所有词都能被我们使用,而BERT一个句子只能利用15%的词。这样我们就能加快它的训练速度。另外我们还在追求更多的功能,比如多语言预训练语言模型,像mBERT和XLM,另外还有一些想法就是把GPT和BERT这一类模型给综合起来,像UniLM和PMLM。4.更聪明现在,人们都意识到语言模型缺乏知识,那么是否可以融入一些外部知识呢?知识这个话题很大,目前也有一些争议,但是相关研究还是很多的。图中是刘知远团队跟华为合作的早期工作,就是试图把采用TransE预训练得到的知识空间的向量表示嵌入到语言模型里面去。这是刘知远团队改进后的工作叫KEPLER,也就是将知识图谱融入到语言模型中,像这一类的工作还有很多。还有一种更简单的想法,Span知识融入:就是让实体或者关系对应着句子中的一个span,通过利用span的方式来把知识嵌入。图中是赵海团队做的SemBERT, 这种方法是将语义角色标记这种更复杂的句法语义的知识融入到语言模型。5.更能干目前在预训练语言模型中,有很多想法都非常好,而且在自然语言处理方面取得了成功。因此很多人都在想,能不能将这种思路应用到别的领域?这个想法很好,做起来很困难,但最终也取得了一些喜人的成果。比如说在语音识别领域, Facebook提出了 wave2vec,它就是通过使用大量没有标注的、纯语音的数据,去预训练一个模型,然后利用这个模型,在一个少量文本标注的语料上进行语音识别,最终取得了非常好的效果。那么最近在图像上面,包括图像分类、目标检测等任务,都有一些预训练的相关研究。其中,DETR是用了transformer模型,但不算预训练。信息检索也已经开始用预训练语言模型,并取得了非常好的效果。在这方面目前大概有两类模型,一类采用sparse索引,它是使用传统的搜索引擎的前提下,去改进传统倒排表的方法。另一类采用dense索引,这种方法不需要建立传统的倒排表,而是直接用dense向量去对文本进行信息检索。3我们的工作接下来我将介绍一下华为诺亚方舟实验室在这方面所取得的成果。首先,我们开发了一个自研的预训练语言模型叫哪吒。其次,我们在模型压缩方面做的工作非常多,华为的TinyBERT模型被压缩的非常小,小到可以用在端侧。如今的预训练语言模型太多了,但我们还是希望有自主开发的模型,然后兼收并蓄,融合好的技术,并且把新技术也结合,然后训练好用的模型。同时我们也把它开源,大家可以去网上下载。目前我们已经推出了不同的版本,另外还有生成模型和TinyBERT,也都开源了。哪吒的性能也是非常强的,我们在目前中文的CLUE排行榜上是第二名,仅次于human模型,事实上在之前很长时间内我们都是第一名。另外在英文的排行榜SUPERGLUE,我们现在已经排到第二名,第一名的是目前在规模上大哪吒十倍的T5模型。哪吒在华为产品的落地,包括华为云,华为手机小艺,以及华为的 HMS。哪吒在华为产品落地的技术,包括基础的算法和模型,对话系统,还有推荐搜索等。TinyBERT是我们目前取得成就最多的一个模型,接下来我着重讲一下TinyBERT的原理。TinyBERT知识蒸馏的基本流程包括两步,第一步叫做general distillation,即使用一个大的预训练语言模型,训练一个小的预训练语言模型。第二步叫做task-specific distillation,即使用一个大的预训练语言模型,去对一个小的预训练语言模型进行微调。在这里我们引入了一个新的技术,叫做数据增强,这个技术非常重要,如果没有这个技术的话,整个模型的性能会下降很多。TinyBERT知识蒸馏的损失函数中一个比较重要的就是,让中间层去学习隐藏状态和attention向量。TinyBERT知识蒸馏的选层策略就是,我们用4层或者6层的学生模型,去学习12层的教师模型。但是让哪一层去学习哪一层,这就是一个有关映射的策略的问题了。我们最早提出的是一个均匀映射模型,即用小模型的1,2,3,4层,去依次学习大模型的3,6,9,12层。后来我们就在想,是否可以让每一层都自动去搜索一个最合适的层次学习?我们就引入了进化学习算法。然后我们发现,对小模型来说,最好的学习层次是0,0,5,10。即小模型的第一层,第二层不要去学习,最好直接使用自动反向传播去调。用第3层去学大模型的第5层,第4层去学大模型的第10层,这样效果最好。6层的学生模型我们学到的是0,5,0,0,0,10。通过选层策略可以发现,选择好的层次的话就可以提高整体的效果。TinyBERT知识蒸馏数据增强是一个非常有效的技术。因为下游任务一般数据都比较少,那么我们在蒸馏小模型的时候,数据的数量经常是不足的。我们采取的办法,就是把用于下游任务的数据进行增强。数据增强实际上就是利用了BERT本身的特点,它的每个词都是可以替换成别的词的。我们采用一种替换策略,就是把每个词都去做一些替换,这样的话就会生成很多的跟原来的句子很相似的句子,比如10个词的句子换掉2个或者3个词,去生成增强的语料。最后,我们发现大概增强20倍的时候,即将原来的一个句子替换生成20个左右相似的句子,用来做下游任务的蒸馏的效果最好。这是我们的实验结果,我们看到在4层的模型,在GLUE上面,总的分数大概降低了2.5,从79.5降到77。6层的TinyBERT基本上是跟12层的没有什么变化。在参数量方面,BERT-base有109M,而4层的模型只有14.5M,只有原模型的13.3%。6层的模型只降到了原来的一半。在速度方面,我们也可以看到4层的模型提速了9.4倍,提速非常高。并且我们现在模型空间非常小,参数量是14.5M的模型大小只有50M左右,完全可以放入手机之中,并且它的推理速度比原来快将近快10倍。目前我们这个模型已经大量的运用在华为的设备与应用之中。我们还做了一个工作,在华为自研的BOLT深度学习加速库下,利用了底层的硬件再一次进行压缩和加速,使得TinyBERT最终的推理速度,可以达到1.3毫秒。我们的TinyBERT在中文的CLUE小模型排行榜上一直是第一名。然后我们参加了 NLPCC的小模型评测比赛,也是获得了第一名。4总结与展望从历史角度来讲,模型越来越大。GPT-3已经这么大了,我们还能做得更大吗?当然如果未来计算设备的硬件的问题解决了,可以更大,但是近期内呢?更大的模型应该是什么样子?我设想的一种方式就是分布式,把模型分布到很多机器上计算,就像搜索引擎一样。像BERT这一类模型如何再把它训练的更大?现在最大的几个预训练语言模型都是GPT类的,BERT这一类模型很难做得更大,一些工程上的问题目前还是很难解决的。那么未来我们是否可能训练更大的BERT类的模型?小模型相反, BERT这类模型可以压缩的很小,GPT模型就很难压缩。BERT这个模型的压缩是不是还有潜力可以挖掘?另外知识融入是一个很有意思的问题。知识融入人们做了很多工作,实际上我是不太满意的。因为很多工作只是在解决知识类的问题效果比较好, 一般的 NLP的问题,知识融入的作用并不是那么大,所以希望知识融入能够解决一般的 NLP的问题。还有就是知识应该如何表示?现在大部分人认为知识都是三元组,我觉得这个是存在争议的,三元组实际上能够表达的知识其实非常有限。比如序列关系、空间关系、集合关系、数值关系等等关系知识都是很难学到的。关于搜索引擎,我希望以后预训练语言模型可以和搜索引擎结合起来,预训练语言模型就是个能够回答任何问题的搜索引擎。最后就是多模态预训练,希望将来它能带来无限的想象空间。
  • [其他] 深度学习库 JAX
        JAX是一个似乎同时具备Pytorch和Tensorflow优势的深度学习框架。 JAX 是 Google Research 开发的机器学习库,被称为“在 GPU/TPU上运行的具有自动微分功能的Numpy”,该库的核心是类似 Numpy 的向量和矩阵运算。我个人认为,与Numpy和PyTorch/TensorFlow最大的不同在于JAX是“(纯)面向函数的”,对于自动微分和误差反向传播的处理方式有着根本的不同。    如果你在“PyTorch vs TensorFlow in 2022”这篇博客文章[2]中阅读了Hacker News的评论部分,以及标题为“2022 Are you a PyTorch sect? TensorFlow sect?”的 Reddit 帖子[3]中的许多评论,诸如“人们开始转向JAX”、“使用 JAX”和“JAX 正在取代 TensorFlow”这样的评论表明它甚至在社区基础上也逐渐流行起来。2021 年,DeepMind 发表的许多优秀研究在其实现中使用 JAX 和基于 JAX 的神经网络库Haiku。视觉Transformer和MLP-Mixer的实现中也使用了基于JAX的深度学习库Flax。最近,谷歌发布了一个基于JAX的计算机视觉库SCENIC,它利用视觉Transformer以统一的方式解决图像、视频和音频任务。在自然语言处理(NLP)领域,Flax 已经正式被用于NLP的流行框架 HuggingFace Transformers 和目前开源最强的语言    模型GPT-J。我经常使用Haiku(一个基于JAX的神经网络库),并使用JAX的并行化机制xmap进行模型并行化。今年6月发布的Cloud TPU VM也有助于使 TPU 更易于使用。总之,我们期待着“2022年是JAX年”的未来发展。
  • [技术干货] 【2.1管理中心安装】只安装一个管理中心,不安装其他服务(如:NLP服务),场景包需要做哪些修改?
    背景:场景包中包含了其他服务,安装时直接导入场景包会使得配置中含有服务节点信息,而我们并没有配置服务节点信息,从而导致安装失败。以只安装一个管理中心为例操作步骤场景包修改:删除不需要服务节点信息(API、Manas、NLP、Mobile)tenant页签partition页签service页签
  • [其他] iBOT 方法概述
    在 NLP 的大规模模型训练中,MLM (Masked Language Modeling)是非常核心的训练目标,其思想是遮住文本的一部分并通过模型去预测这些遮住部分的语义信息,通过这一过程可以使模型学到泛化的特征。NLP 中的经典方法 BERT 就是采用了 MLM 的预训练范式,通过 MLM 训练的模型已经被证明在大模型和大数据上具备极好的泛化能力,成为 NLP 任务的标配。但是在大多数 CV 中的自监督学习任务里面,关注的往往是图片的 global view,比如 MoCo v3。而没有认真研究 image 的内部结构,也就不算是真正的 MIM (Masked Image Modeling)。对于 NLP 任务的 MLM 中,lingual tokenizer 非常重要。它的任务是把 language 变成富含文本语义的 tokens。与此相似,对于 CV 任务的 MIM 中,visual tokenizer 非常重要。它的任务是把 image 变成富含图像语义的 tokens。但是,图片不像是文本,文本中自然蕴含有语言的语义信息,NLP 中 tokenization 通过离线的词频分析即可将语料编码为含高语义的分词。但是图片不一样,图片的信息比较连续,图像 patch 是连续分布的且存在大量冗余的底层细节信息,而图像 patch token 的语义信息丰富。所以图像 patch 的 visual semantic 信息不那么容易被提取。这个属性直观地带来了一个多阶段的训练策略,即:在训练目标模型之前,我们需要首先训练一个 off-the-shelf 的 tokenizer,它能够把 image 转换成语义丰富的 tokens。BEiT 中使用的是一个 Pre-trained discrete VAE 作为 tokenizer。虽然提供了一定程度的抽象,但discrete VAE 仍然只能在局部细节中捕获低级语义。
  • [应用实践] 昇思MindSpore NLP模型迁移之Bert模型—文本匹配任务(二):训练和评估
    在上一节中,我们已经将Bert模型迁移到MindSpore上。在这节中,我将会介绍如何使用MindSpore的Bert模型来做下游任务:lcqmc的文本匹配任务。主机环境:系统:ubuntu18GPU:3090MindSpore版本:1.3数据集:lcqmclcqmc文本匹配任务的定义:哈工大文本匹配数据集,LCQMC 是哈尔滨工业大学在自然语言处理国际顶会 COLING2018 构建的问题语义匹配数据集,其目标是判断两个问题的语义是否相同。数据集中的字段分别如下:text_a, text_b, label。其中text_a和text_b为两个问题的文本。若两个问题的语义相同则label为1,否则为0。权重迁移PyTorch->MindSpore由于官网已经提供了微调好的权重信息,所以我们尝试直接转换权重进行预测。我们先要知道模型权重名称以及形状等,需要PyTorch与MindSpore模型一一对应。首先,我们将huggingface的bert-chinese-base的torch bin文件下载下来。接下来使用下面的函数将Torch权重参数文件转化为MindSpore权重参数文件def torch_to_ms(model, torch_model,save_path): """ Updates mobilenetv2 model mindspore param's data from torch param's data. Args: model: mindspore model torch_model: torch model """ print("start load") # load torch parameter and mindspore parameter torch_param_dict = torch_model ms_param_dict = model.parameters_dict() count = 0 for ms_key in ms_param_dict.keys(): ms_key_tmp = ms_key.split('.') if ms_key_tmp[0] == 'bert_embedding_lookup': count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.word_embeddings.weight', ms_key) elif ms_key_tmp[0] == 'bert_embedding_postprocessor': if ms_key_tmp[1] == "token_type_embedding": count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.token_type_embeddings.weight', ms_key) elif ms_key_tmp[1] == "full_position_embedding": count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.position_embeddings.weight', ms_key) elif ms_key_tmp[1] =="layernorm": if ms_key_tmp[2]=="gamma": count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.LayerNorm.weight', ms_key) else: count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.LayerNorm.bias', ms_key) elif ms_key_tmp[0] == "bert_encoder": if ms_key_tmp[3] == 'attention': par = ms_key_tmp[4].split('_')[0] count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.'+ms_key_tmp[2]+'.'+ms_key_tmp[3]+'.' +'self.'+par+'.'+ms_key_tmp[5], ms_key) elif ms_key_tmp[3] == 'attention_output': if ms_key_tmp[4] == 'dense': print(7) count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.'+ms_key_tmp[4]+'.'+ms_key_tmp[5], ms_key) elif ms_key_tmp[4]=='layernorm': if ms_key_tmp[5]=='gamma': print(8) count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.LayerNorm.weight', ms_key) else: count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.LayerNorm.bias', ms_key) elif ms_key_tmp[3] == 'intermediate': count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.intermediate.dense.'+ms_key_tmp[4], ms_key) elif ms_key_tmp[3] == 'output': if ms_key_tmp[4] == 'dense': count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.output.dense.'+ms_key_tmp[5], ms_key) else: if ms_key_tmp[5] == 'gamma': count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.output.LayerNorm.weight', ms_key) else: count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.output.LayerNorm.bias', ms_key) if ms_key_tmp[0] == 'dense': if ms_key_tmp[1] == 'weight': count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'pooler.dense.weight', ms_key) else: count+=1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'pooler.dense.bias', ms_key) save_checkpoint(model, save_path) print("finish load") def update_bn(torch_param_dict, ms_param_dict, ms_key, ms_key_tmp): """Updates mindspore batchnorm param's data from torch batchnorm param's data.""" str_join = '.' if ms_key_tmp[-1] == "moving_mean": ms_key_tmp[-1] = "running_mean" torch_key = str_join.join(ms_key_tmp) update_torch_to_ms(torch_param_dict, ms_param_dict, torch_key, ms_key) elif ms_key_tmp[-1] == "moving_variance": ms_key_tmp[-1] = "running_var" torch_key = str_join.join(ms_key_tmp) update_torch_to_ms(torch_param_dict, ms_param_dict, torch_key, ms_key) elif ms_key_tmp[-1] == "gamma": ms_key_tmp[-1] = "weight" torch_key = str_join.join(ms_key_tmp) update_torch_to_ms(torch_param_dict, ms_param_dict, 'transformer.' + torch_key, ms_key) elif ms_key_tmp[-1] == "beta": ms_key_tmp[-1] = "bias" torch_key = str_join.join(ms_key_tmp) update_torch_to_ms(torch_param_dict, ms_param_dict, 'transformer.' + torch_key, ms_key) def update_torch_to_ms(torch_param_dict, ms_param_dict, torch_key, ms_key): """Updates mindspore param's data from torch param's data.""" value = torch_param_dict[torch_key].cpu().numpy() value = Parameter(Tensor(value), name=ms_key) _update_param(ms_param_dict[ms_key], value) def _update_param(param, new_param): """Updates param's data from new_param's data.""" if isinstance(param.data, Tensor) and isinstance(new_param.data, Tensor): if param.data.dtype != new_param.data.dtype: print("Failed to combine the net and the parameters for param %s.", param.name) msg = ("Net parameters {} type({}) different from parameter_dict's({})" .format(param.name, param.data.dtype, new_param.data.dtype)) raise RuntimeError(msg) if param.data.shape != new_param.data.shape: if not _special_process_par(param, new_param): print("Failed to combine the net and the parameters for param %s.", param.name) msg = ("Net parameters {} shape({}) different from parameter_dict's({})" .format(param.name, param.data.shape, new_param.data.shape)) raise RuntimeError(msg) return param.set_data(new_param.data) return if isinstance(param.data, Tensor) and not isinstance(new_param.data, Tensor): if param.data.shape != (1,) and param.data.shape != (): print("Failed to combine the net and the parameters for param %s.", param.name) msg = ("Net parameters {} shape({}) is not (1,), inconsistent with parameter_dict's(scalar)." .format(param.name, param.data.shape)) raise RuntimeError(msg) param.set_data(initializer(new_param.data, param.data.shape, param.data.dtype)) elif isinstance(new_param.data, Tensor) and not isinstance(param.data, Tensor): print("Failed to combine the net and the parameters for param %s.", param.name) msg = ("Net parameters {} type({}) different from parameter_dict's({})" .format(param.name, type(param.data), type(new_param.data))) raise RuntimeError(msg) else: param.set_data(type(param.data)(new_param.data)) def _special_process_par(par, new_par): """ Processes the special condition. Like (12,2048,1,1)->(12,2048), this case is caused by GE 4 dimensions tensor. """ par_shape_len = len(par.data.shape) new_par_shape_len = len(new_par.data.shape) delta_len = new_par_shape_len - par_shape_len delta_i = 0 for delta_i in range(delta_len): if new_par.data.shape[par_shape_len + delta_i] != 1: break if delta_i == delta_len - 1: new_val = new_par.data.asnumpy() new_val = new_val.reshape(par.data.shape) par.set_data(Tensor(new_val, par.data.dtype)) return True return False实际应用案例如下:import BertConfig import BertModel as ms_bm import BertModel as tc_bm bert_config_file = "./model/test.yaml" bert_config = BertConfig.from_yaml_file(bert_config_file) model = ms_bm(bert_config, False) torch_model = tc_bm.from_pretrained("/content/model/bert_cn") torch_to_ms(model, torch_model.state_dict(),"./model/bert2.ckpt")这里名称一定要一一对应。如果后期改动了模型,也需要在检查一下这个转换函数是否能对应。下游任务:lcqmc文本匹配任务训练1、封装Bert为bert_embeding首先我们先将之前构建好的Bert再进行一步封装为bert_embeding# Copyright 2021 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================ """Bert Embedding.""" import logging from typing import Tuple import mindspore.nn as nn from mindspore import Tensor from mindspore.train.serialization import load_checkpoint, load_param_into_net import BertModel, BertConfig logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) class BertEmbedding(nn.Cell): """ This is a class that loads pre-trained weight files into the model. """ def __init__(self, bert_config: BertConfig, is_training: bool = False): super(BertEmbedding, self).__init__() self.bert = BertModel(bert_config, is_training) def init_bertmodel(self, bert): """ Manual initialization BertModel """ self.bert = bert def from_pretrain(self, ckpt_file): """ Load the model parameters from checkpoint """ param_dict = load_checkpoint(ckpt_file) load_param_into_net(self.bert, param_dict) def construct(self, input_ids: Tensor, token_type_ids: Tensor, input_mask: Tensor) -> Tuple[Tensor, Tensor]: """ Returns the result of the model after loading the pre-training weights Args: input_ids (:class:`mindspore.tensor`):A vector containing the transformation of characters into corresponding ids. token_type_ids (:class:`mindspore.tensor`):A vector containing segemnt ids. input_mask (:class:`mindspore.tensor`):the mask for input_ids. Returns: sequence_output:the sequence output . pooled_output:the pooled output of first token:cls.. """ sequence_output, pooled_output, _ = self.bert(input_ids, token_type_ids, input_mask) return sequence_output, pooled_output2、下游任务:BertforSequenceClassification将Bert作为预训练模型,接着在Bert的基础上,取Bert的cls token的embeding作为输入,输入到全连接网络中,这就是BertforSequenceClassification。
  • [应用实践] 昇思MindSpore NLP模型迁移之Roberta ——情感分析任务(一)
    熟悉 BERT 模型的小伙伴对于 Roberta 模型肯定不陌生了。Roberta 模型在 BERT 模型的基础上进行了一定的改进,主要改进点有以下几个部分:1. 训练语料:BERT只使用 16 GB 的Book Corpus数据集和英语维基百科进行训练,Roberta增加了 CC-NEWS 、OPEN WEB TEXT、STORIES 等语料,一共有 160 GB 的纯文本。2. Batch Size:Roberta模型在训练中使用了更大的Batch Size -> [256 ~ 8000]。3. 训练时间:Roberta模型使用 1024 块 V100 的 GPU 训练了整整 1 天的时间,模型参数量和训练时间更加多和更加长。同时Roberta在具体的训练方法上也有所改进:1. 动态 MASK 机制2. 去除了 NSP 任务3. Tokenizer部分更换成 BPE 算法,分词这一点和 GPT-2 十分相似Roberta 源码(huggingface):https://huggingface.co/roberta-baseRoberta论文:https://arxiv.org/abs/1907.11692这里我们采用了华为开发的 MindSpore 框架,并且选择了 Pytorch 版本 Roberta 模型进行模型迁移。欢迎大家一起参与到 MindSpore 开源社区的开发中来!前言本文环境:系统:Ubuntu 18GPU:RTX 3090MindSpore版本:1.3数据集:SST-2(情感分析任务)SST-2 数据集定义:这是一个二分类的数据集,训练集和验证集的句子所对应的标签是0或1模型权重转换我们需要将 Pytorch 版本的 Roberta 权重转换成 MindSpore 适用的权重,这里提供一个转换的思路。主要可以参考官网的API映射文档进行改写。官网链接:转换映射(https://www.mindspore.cn/docs/migration_guide/zh-CN/r1.5/api_mapping/pytorch_api_mapping.html)def torch_to_ms(model, torch_model): """ Updates mobilenetv2 model mindspore param's data from torch param's data. Args: model: mindspore model torch_model: torch model """ print("start load") # load torch parameter and mindspore parameter torch_param_dict = torch_model ms_param_dict = model.parameters_dict() count = 0 for ms_key in ms_param_dict.keys(): ms_key_tmp = ms_key.split('.') if ms_key_tmp[0] == 'roberta_embedding_lookup': count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.word_embeddings.weight', ms_key) elif ms_key_tmp[0] == 'roberta_embedding_postprocessor': if ms_key_tmp[1] == "token_type_embedding": count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.token_type_embeddings.weight', ms_key) elif ms_key_tmp[1] == "full_position_embedding": count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.position_embeddings.weight', ms_key) elif ms_key_tmp[1] =="layernorm": if ms_key_tmp[2]=="gamma": count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.LayerNorm.weight', ms_key) else: count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'embeddings.LayerNorm.bias', ms_key) elif ms_key_tmp[0] == "roberta_encoder": if ms_key_tmp[3]=='attention': par = ms_key_tmp[4].split('_')[0] count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.'+ms_key_tmp[2]+'.'+ms_key_tmp[3]+'.' +'self.'+par+'.'+ms_key_tmp[5], ms_key) elif ms_key_tmp[3]=='attention_output': if ms_key_tmp[4]=='dense': count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.'+ms_key_tmp[4]+'.'+ms_key_tmp[5], ms_key) elif ms_key_tmp[4]=='layernorm': if ms_key_tmp[5]=='gamma': count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.LayerNorm.weight', ms_key) else: count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.attention.output.LayerNorm.bias', ms_key) elif ms_key_tmp[3]=='intermediate': count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.intermediate.dense.'+ms_key_tmp[4], ms_key) elif ms_key_tmp[3]=='output': if ms_key_tmp[4]=='dense': count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.output.dense.'+ms_key_tmp[5], ms_key) else: if ms_key_tmp[5]=='gamma': count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.output.LayerNorm.weight', ms_key) else: count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'encoder.layer.' + ms_key_tmp[2] + '.output.LayerNorm.bias', ms_key) if ms_key_tmp[0]=='dense': if ms_key_tmp[1]=='weight': count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'pooler.dense.weight', ms_key) else: count += 1 update_torch_to_ms(torch_param_dict, ms_param_dict, 'pooler.dense.bias', ms_key) save_checkpoint(model, "./model/roberta-base.ckpt") print(count) print("finish load")这里值得注意的是转换的参数一定要对应的上,不然在后续权重加载中会出现权重加载失败,或是训练过程中loss值降不下去的情况!转换完后可以试着打印对应参数的 key 值防止错漏。这样我们就获得了转换出来的roberta.ckpt文件用于加载权重。这里的权重文件一定要和tensorflow的权重文件进行区分!数据处理对于数据的输入这一块,MindSpore和Pytorch也是存在差异的。这里我们直接使用自己准备的dataset部分,这里面封装了多种NLP任务的数据集处理方式,可以将数据集转换成mindrecord形式,然后用于模型的训练和验证。下面跟着笔者继续去了解一下吧! """ SST-2 dataset """ from typing import Union, Dict, List import mindspore.dataset as ds from ..base_dataset import CLSBaseDataset class SST2Dataset(CLSBaseDataset): """ SST2 dataset. Args: paths (Union[str, Dict[str, str]], Optional): Dataset file path or Dataset directory path, default None. tokenizer (Union[str]): Tokenizer function, default 'spacy'. lang (str): Tokenizer language, default 'en'. max_size (int, Optional): Vocab max size, default None. min_freq (int, Optional): Min word frequency, default None. padding (str): Padding token, default `<pad>`. unknown (str): Unknown token, default `<unk>`. buckets (List[int], Optional): Padding row to the length of buckets, default None. Examples: >>> sst2 = SST2Dataset(tokenizer='spacy', lang='en') # sst2 = SST2Dataset(tokenizer='spacy', lang='en', buckets=[16,32,64]) >>> ds = sst2() """ def __init__(self, paths: Union[str, Dict[str, str]] = None, tokenizer: Union[str] = 'spacy', lang: str = 'en', max_size: int = None, min_freq: int = None, padding: str = '<pad>', unknown: str = '<unk>', buckets: List[int] = None): super(SST2Dataset, self).__init__(sep='\t', name='SST-2') self._paths = paths self._tokenize = tokenizer self._lang = lang self._vocab_max_size = max_size self._vocab_min_freq = min_freq self._padding = padding self._unknown = unknown self._buckets = buckets def __call__(self) -> Dict[str, ds.MindDataset]: self.load(self._paths) self.process(tokenizer=self._tokenize, lang=self._lang, max_size=self._vocab_max_size, min_freq=self._vocab_min_freq, padding=self._padding, unknown=self._unknown, buckets=self._buckets) return self.mind_datasetsfrom mindtext.dataset.classification import SST2Dataset #对SST-2情感分析的数据集进行处理 如果本来缓存就有只需要直接读缓存 dataset = SST2Dataset(paths='./mindtext/dataset/SST-2', tokenizer="roberta-base", max_length=128, truncation_strategy=True, columns_list=['input_ids', 'attention_mask','label'], test_columns_list=['input_ids', 'attention_mask'], batch_size=64 ) ds = dataset() #生成对应的train、dev的mindrecord文件 ds = dataset.from_cache( columns_list=['input_ids', 'attention_mask','label'], test_columns_list=['input_ids', 'attention_mask'], batch_size=64 ) dev_dataset = ds['dev'] #取出转成mindrecord的验证集用于验证生成出来的mindrecord文件,一个是 .mindrecord文件 一个是 .mindrecord.db文件,值得注意的是我们不能随意去修改它们的名字,两个文件是存在着一定的映射关系,如果强行去修改它们名字会出现读取不了mindrecord文件的错误!还有进行数据处理的参数一定要和模型输入的参数一致,例如我们Roberta模型输入的参数是['input_ids', 'attention_mask','label']。模型的主体架构 项目架构图: 架构方面我们主要是参考的fastnlp的划分方式。将模型划分为Encoder、Embedding、Tokenizer三个部分,后续会进一步的优化模型的架构。1.Embedding"""Roberta Embedding.""" import logging from typing import Tuple import mindspore.nn as nn from mindspore import Tensor from mindspore.train.serialization import load_checkpoint, load_param_into_net from mindtext.modules.encoder.roberta import RobertaModel, RobertaConfig logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) class RobertaEmbedding(nn.Cell): """ This is a class that loads pre-trained weight files into the model. """ def __init__(self, roberta_config: RobertaConfig, is_training: bool = False): super(RobertaEmbedding, self).__init__() self.roberta = RobertaModel(roberta_config, is_training) def init_robertamodel(self,roberta): """ Manual initialization BertModel """ self.roberta=roberta def from_pretrain(self, ckpt_file): """ Load the model parameters from checkpoint """ param_dict = load_checkpoint(ckpt_file) load_param_into_net(self.roberta, param_dict) def construct(self, input_ids: Tensor, input_mask: Tensor)-> Tuple[Tensor, Tensor]: """ Returns the result of the model after loading the pre-training weights Args: input_ids:A vector containing the transformation of characters into corresponding ids. input_mask:the mask for input_ids. Returns: sequence_output:the sequence output . pooled_output:the pooled output of first token:cls.. """ sequence_output, pooled_output, _ = self.roberta(input_ids, input_mask) return sequence_output, pooled_output这部分主要用来加载预训练好的权重,在前文我们就得到了mindrecord形式的权重文件。2.Encoderclass RobertaModel(nn.Cell): """ Used from mindtext.modules.encoder.roberta with Roberta Args: config (Class): Configuration for RobertaModel. is_training (bool): True for training mode. False for eval mode. use_one_hot_embeddings (bool): Specifies whether to use one hot encoding form. Default: False. """ def __init__(self, config: RobertaConfig, is_training: bool, use_one_hot_embeddings: bool = False): super().__init__() config = copy.deepcopy(config) if not is_training: config.hidden_dropout_prob = 0.0 config.attention_probs_dropout_prob = 0.0 self.seq_length = config.seq_length self.hidden_size = config.hidden_size self.num_hidden_layers = config.num_hidden_layers self.embedding_size = config.hidden_size self.token_type_ids = None self.compute_type = numbtpye2mstype(config.compute_type) self.last_idx = self.num_hidden_layers - 1 output_embedding_shape = [-1, self.seq_length, self.embedding_size] self.roberta_embedding_lookup = nn.Embedding( vocab_size=config.vocab_size, embedding_size=self.embedding_size, use_one_hot=use_one_hot_embeddings, embedding_table=TruncatedNormal(config.initializer_range)) self.roberta_embedding_postprocessor = EmbeddingPostprocessor( embedding_size=self.embedding_size, embedding_shape=output_embedding_shape, use_token_type=False, token_type_vocab_size=config.type_vocab_size, use_one_hot_embeddings=use_one_hot_embeddings, max_position_embeddings=config.max_position_embeddings, dropout_prob=config.hidden_dropout_prob) self.roberta_encoder = RobertaTransformer( hidden_size=self.hidden_size, seq_length=self.seq_length, num_attention_heads=config.num_attention_heads, num_hidden_layers=self.num_hidden_layers, intermediate_size=config.intermediate_size, attention_probs_dropout_prob=config.attention_probs_dropout_prob, initializer_range=config.initializer_range, hidden_dropout_prob=config.hidden_dropout_prob, hidden_act=config.hidden_act, compute_type=self.compute_type, return_all_encoders=True) self.cast = P.Cast() self.dtype = numbtpye2mstype(config.dtype) self.cast_compute_type = SecurityCast() self.slice = P.StridedSlice() self.squeeze_1 = P.Squeeze(axis=1) self.dense = nn.Dense(self.hidden_size, self.hidden_size, activation="tanh", weight_init=TruncatedNormal(config.initializer_range))\ .to_float(mstype.float32) self._create_attention_mask_from_input_mask = CreateAttentionMaskFromInputMask(config) def construct(self, input_ids: Tensor, input_mask: Tensor) -> Tuple[Tensor, Tensor, Tensor]: """Bidirectional Encoder Representations from Transformers. Args: input_ids:A vector containing the transformation of characters into corresponding ids. input_mask:the mask for input_ids. Returns: sequence_output:the sequence output . pooled_output:the pooled output of first token:cls. embedding_table:fixed embedding table. """ # embedding embedding_tables = self.roberta_embedding_lookup.embedding_table word_embeddings = self.roberta_embedding_lookup(input_ids) embedding_output = self.roberta_embedding_postprocessor(input_ids, word_embeddings) # attention mask [batch_size, seq_length, seq_length] attention_mask = self._create_attention_mask_from_input_mask(input_mask) # roberta encoder encoder_output = self.roberta_encoder(self.cast_compute_type(embedding_output), attention_mask) sequence_output = self.cast(encoder_output[self.last_idx], self.dtype) # pooler batch_size = P.Shape()(input_ids)[0] sequence_slice = self.slice(sequence_output, (0, 0, 0), (batch_size, 1, self.hidden_size), (1, 1, 1)) first_token = self.squeeze_1(sequence_slice) pooled_output = self.dense(first_token) pooled_output = self.cast(pooled_output, self.dtype) return sequence_output, pooled_output, embedding_tables这是我们的模型主体,这里我们将模型整体放入到了encoder文件下的roberta.py。我们可以看到encoder部分主要包括 encoder_output 和 sequence_output 两个部分。这里的部分实现我们是参照了 MindSpore ModelZoo 项目的 BERT 模型去实现的(小伙伴们在迁移模型时候可以登录MindSpore官网前去参考哦~),所以只需要简单的将几个重要的模块进行拼接就OK了,这几个模块包括:EncoderOutput:每个sub-layer加上残差连接和归一化的模块。RobertaAttention:单个多头自注意力层。RobertaEncoderCell:单个的RobertaEncoder层。RobertaTransformer:将多个RobertaEncoderCell拼接在一起,形成完整的roberta模块。这样可以大大减少我们模型架构的时间,也能更好的学习到MindSpore框架的使用。3.Tokenizer分词方面我们封装在dataset中。可以通过指定huggingface库中存在的预训练模型的名字来直接加载词表等文件!使用起来非常方便,详情可以回溯到数据处理部分的代码。如果想实现别的下游任务,但在dataset中没有的话,也可以使用我们实现的tokenlizer来用自己的方式去构建mindrecord形式的数据。def get_tokenizer(tokenize_method: str, lang: str = 'en'): """ Get a tokenizer. Args: tokenize_method (str): Select a tokenizer method. lang (str): Tokenizer language, default English. Returns: function: A tokenizer function. """ tokenizer_dict = { 'spacy': None, 'raw': _split, 'cn-char': _cn_split, } if tokenize_method == 'spacy': import spacy spacy.prefer_gpu() if lang != 'en': raise RuntimeError("Spacy only supports english") if parse_version(spacy.__version__) >= parse_version('3.0'): en = spacy.load('en_core_web_sm') else: en = spacy.load(lang) def _spacy_tokenizer(text): return [w.text for w in en.tokenizer(text)] tokenizer = _spacy_tokenizer elif tokenize_method in tokenizer_dict: tokenizer = tokenizer_dict[tokenize_method] else: raise RuntimeError(f"Only support {tokenizer_dict.keys()} tokenizer.") return tokenizer模型参数加载在模型主体的roberta.py文件中 RobertaConfig 模块可以加载yaml文件中的对应参数到 RobertaModel中去。以下是yaml文件的参数配置: seq_length: 128 vocab_size: 50265 hidden_size: 768 bos_token_id: 0 eos_token_id: 2 num_hidden_layers: 12 num_attention_heads: 12 intermediate_size: 3072 hidden_act: "gelu" hidden_dropout_prob: 0.1 attention_probs_dropout_prob: 0.1 max_position_embeddings: 514 pad_token_id: 1 type_vocab_size: 1 initializer_range: 0.02 use_relative_positions: False dtype: mstype.float32 compute_type: mstype.float32模型训练 roberta_config_file = "./mindtext/config/test.yaml" roberta_config = RobertaConfig.from_yaml_file(roberta_config_file) rbm = RobertaModel(roberta_config, True) param_dict = load_checkpoint('./mindtext/pretrain/roberta-base-ms.ckpt') p = load_param_into_net(rbm, param_dict) em = RobertaEmbedding(roberta_config, True) em.initRobertaModel(rbm) roberta = RobertaforSequenceClassification(roberta_config, is_training=True, num_labels=2) roberta.init_embedding(em)模型权重加载完毕后,设置好学习率lr、训练轮数epoch、损失函数、优化器等等,就可以开始训练啦!这里我们根据论文提供的learning_rate来设置:3e-5。其次还使用了warm_up预热学习率,待模型趋于稳定后,再选择预先设置的学习率进行训练,使得模型收敛速度变得更快,模型效果更佳。epoch设为3轮。epoch_num = 3 save_path = "./mindtext/pretrain/output/roberta-base_sst.ckpt" lr_schedule = RobertaLearningRate(learning_rate=3e-5, end_learning_rate=1e-5, warmup_steps=int(train_dataset.get_dataset_size() * epoch_num * 0.1), decay_steps=train_dataset.get_dataset_size() * epoch_num, power=1.0) params = roberta.trainable_params() optimizer = AdamWeightDecay(params, lr_schedule, eps=1e-8)一切准备好后,就进入训练阶段,最后将经过微调的模型参数保存至指定路径的ckpt文件中。def train(train_data, roberta, optimizer, save_path, epoch_num): update_cell = DynamicLossScaleUpdateCell(loss_scale_value=2 ** 32, scale_factor=2, scale_window=1000) netwithgrads = RobertaFinetuneCell(roberta, optimizer=optimizer, scale_update_cell=update_cell) callbacks = [TimeMonitor(train_data.get_dataset_size()), LossCallBack(train_data.get_dataset_size())] model = Model(netwithgrads) model.train(epoch_num, train_data, callbacks=callbacks, dataset_sink_mode=False) save_checkpoint(model.train_network, save_path)
  • [其他干货] MindSpore开发NLP模型中遇到的问题和解决经验分享
    本文分享我在参与MindSpore的NLP模型开发中遇到的一些问题以及最终是如何解决的。如果大家有遇到类似的问题欢迎讨论交流。问题一:训练时性能差。一开始mindspore实现的模型使用八卡跑22个小时都跑不完训练,每一步需要跑3000+ms。   后来得知由于Ascend芯片矩阵运算的设计,会存在需要和16对齐的要求。尝试后发现,MindSpore的mindspore.nn.Embedding()函数中的两个参数vocab_size和embedding_size需要设置为16的倍数,不然会对性能有很大的影响。修改后使用八卡跑完训练只需要半个小时,每步只需要300+ms,性能提高了10倍以上。问题二:处理得到的mindrecord数据训练中使用报错。将处理好的mindrecord数据读出来用于训练时发现维度多了一维,而直接处理数据并送入模型不会出错,因此将问题定位在了数据处里为mindrecord格式和读取mindrecord那里。尝试后发现,在数据处理为mindrecord的时候就将batch size设置为了8,而在读取mindrecord时又将参数batch_size设置为了8,导致数据读出来后直接多了一维。最终将数据在处理为mindrecord时的batch size设置为1就可以解决这个问题了。问题三:静态图中有的算子会报错。MindSpore中mindspore.nn、mindspore.ops、mindspore.numpy中有一些同名参数相同功能也相同的算子,但有的使用后在动态图中不会报错但静态图中会报错,替换为不同的包里的同名函数后静态图不会报错。推测可能是这些同名算子中有的能够支持静态图而有的不行。