鹤啸九天 自律更自由,平凡不平庸 Less is More

自然语言处理-NLP

Notes(温馨提示):

  1. ★ 首次阅读建议浏览:导航指南
  2. 右上角工具条搜索文章,右下角二维码关注微信公众号(鹤啸九天),底栏分享、赞赏、评论
  3. ★ 转载请注明文章来源,知识点积累起来不容易,水滴石穿,绳锯木断,谢谢理解
  4. ★ 如有疑问,邮件讨论,欢迎贡献优质资料


总结

能力总结

  • 【2021-2-27】中文NLP实话实话:中文自然语言处理,目前在AI泡沫之下,真假难辨,实战技术与PPT技术往往存在着很大的差异。目前关于AI或者自然语言处理,做的人与讲的人往往是两回事。
  • 深度学习在自然语言处理当中,除了在分类问题上能够取得较好效果外(如单选问题:情感分类、文本分类、正确答案分类问题等),在信息抽取上,尤其是在元组抽取上基本上是一塌糊涂,在工业场景下很难达到实用水准。
  • 目前各种评测集大多是人为标注的,人为标注的大多为干净环境下的较为规范的文本,而且省略了真实生产环节中的多个环节。在评测环节中达到的诸多state-of-art方法,在真实应用场景下泛化能力很差,大多仅仅是为了刷榜而刷榜。
  • 目前关于知识图谱的构建环节中,数据大多数都还是来自于结构化数据,半结构化信息抽取次之,非结构化数据抽取最少。半结构化信息抽取,即表格信息抽取最为危险,一个单元格错误很有可能导致所有数据都出现错误。非结构化抽取中,实体识别和实体关系识别难度相当大。
  • 工业场景下命名实体识别,标配的BILSTM+CRF实际上只是辅助手段,工业界还是以领域实体字典匹配为主,大厂中往往在后者有很大的用户日志,这种日志包括大量的实体信息。因此,生产环节中的实体识别工作中,基础性词性的构建和扩展工作显得尤为重要。
  • 目前关于知识图谱推理问题,严格意义上不属于推理的范畴,最多只能相当于是知识补全问题,如评测中的知识推理任务,是三元组补全问题。

  • Bert本质上仅仅是个编码器,是word2vec的升级版而已,不是无所不能,仅仅是编码能力强,向量表示上语义更为丰富,然而大多人都装糊涂。
  • 学界和业界最大的区别在于
    • 学术界以探索前沿为目的,提新概念,然后搭个草图就结束,目光并不长远,打完这一战就不知道下一战打什么,下一战该去哪里打,什么时候打,或者打一枪换个阵地再打。
    • 而工业界,往往面临着生存问题,需要考虑实际问题,还是以解决实际问题为主,因此没必要把学界的那一套理念融入到生产环节中,要根据实际情况制定自己的方法。
  • 利用结构化数据,尤其是百科类infobox数据,采集下来,存入到Neo4j图数据库中,就称自己建立了知识图谱的做法是伪知识图谱做法。基于这类知识图谱,再搞个简单的问答系统,就标榜自己是基于知识图谱的智能问答,实际上很肤浅。
  • 知识图谱不是结构化知识的可视化(不是两个点几条边)那么简单,那叫知识的可视化,不是知识图谱。知识图谱的核心在于知识的图谱化,特点在于知识的表示方法和图谱存储结构,前者决定了知识的抽象表示维度,后者决定了知识运行的可行性,图算法(图遍历、联通图、最短路径)。基于图谱存储结构,进行知识的游走,进行知识表征和未知知识的预测。
  • 物以稀为贵,大家都能获取到的知识,往往价值都很低。知识图谱也是这样,只有做专门性的具有数据壁垒的知识图谱,才能带来商业价值。
  • 目前智能问答,大多都是人工智障,通用型的闲聊型问答大多是个智障,多轮对话缺失,答非所问等问题层出不穷。垂直性的问答才是出路,但真正用心做的太少,大多都是处于demo级别。
  • 大多数微信自然语言处理软文实际上都不可不看,纯属浪费时间。尤其是在对内容的分析上,大多是抓语料,调包统计词频,提取关键词,调包情感分析,做柱状图,做折线图,做主题词云,分析方法上千篇一律。应该从根本上去做方法上的创新,这样才能有营养,从根本上来说才能有营养可言。文本分析应该从浅层分析走向深层分析,更好地挖掘文本的语义信息。
  • 目前百科类知识图谱的构建工作有很多,重复性的工作不少。基于开放类百科知识图谱的数据获取接口有复旦等开放出来,可以应用到基本的概念下实体查询,实体属性查询等,但目前仅仅只能做到一度。
  • 基于知识图谱的问答目前的难点在于两个方面
    • 1)多度也称为多跳问题,如姚明的老婆是谁,可以走14条回答,但姚明的老婆的女儿是谁则回答不出来,这种本质上是实体与属性以及实体与实体关系的分类问题。
    • 2)多轮问答问题。多轮分成两种,一种是指代补全问答, 如前一句问北京的天气,后者省略“的天气”这一词,而只说“北京”,这个需要进行意图判定并准确加载相应的问答槽。另一种是追问式多轮问答,典型的在天气查询或者酒店预订等垂直性问答任务上。大家要抓住这两个方面去做。
  • 关系挖掘是信息抽取的重要里程碑,理解了实体与实体、实体与属性、属性与属性、实体与事件、事件与事件的关系是解决真正语义理解的基础,但目前,这方面,在工业界实际运用中,特定领域中模板的性能要比深度学习多得多,学界大多采用端到端模型进行实验,在这方面还难以超越模版性能。

NLP难点

NLU信心调研

【2022-10-1】自然语言理解要凉?62%从业者认为30年内寒冬将至调查主页 原版报告

  • 来自华盛顿大学、纽约大学和约翰霍普金斯大学的组成的研究团队,就 NLP 领域的一些争议性问题征求了广大研究者的意见,包括研究者在大模型、AGI(通用人工智能)、语言理解、未来方向等多个方面的看法。
  • 从调查结果来看,受访者对于这些问题的看法几乎都是对半开,这意味着自然语言理解(NLP)从业者的想法,与整个领域的现状之间,出现了巨大的分歧。
专题 问题 认可比例 调研分析
NLP 领域现状 (1)私营公司的影响力过大? 77%  
NLP 领域现状 (2)工业界将会产出最被广泛引用的研究成果? 86% 未来十年被广泛引用的论文更有可能来自工业界而非学术界
NLP 领域现状 (3)NLP会在十年内进入寒冬? 30% 认同仅占7%,其余都是稍微认同
NLP 领域现状 (4)NLP会在三十年内进入寒冬? 62% 寒冬将在未来 30 年内到来,长期来看,NLP 领域可能会退烧甚至变冷
NLP 领域现状 (5)大部分NLP领域发表的相关工作在科学价值上都值得怀疑(dubious)? 67% 大多数 NLP 工作在科学意义上是可疑的
NLP 领域现状 (6)作者匿名评审很重要? 63% 评审期间作者的匿名是有价值的,可以保证限制预印本的传播
规模化、归纳偏差和来自临近领域的启发 (1)规模化可以解决几乎所有的关键问题? 17% 如果用上21世纪内所有的计算资源和数据资源,用现有技术的规模化实施将足以实际解决任何重要的现实世界问题或NLP应用。
规模化、归纳偏差和来自临近领域的启发 (2)引入语言学结构是必要的? 50% 语言学理论为基础的语言结构的离散的通用表征(例如,涉及词义、句法或语义图)对于实际解决NLP中的一些重要的现实世界的问题或应用是必要的。
规模化、归纳偏差和来自临近领域的启发 (3)专家的归纳偏见是必要的? 51% 专家设计的强归纳偏见(如通用语法、符号系统或认知启发的计算基元)对于实际解决NLP中一些重要的现实世界问题或应用是必要的。
规模化、归纳偏差和来自临近领域的启发 (4)Ling/CogSci将对引用最多的模型作出贡献? 61% 2030年被引用最多的五个系统中,很可能至少有一个会从过去50年的语言学或认知科学研究中的具体的、非微不足道的成果中获得明确的灵感。
AGI和主要风险 (1)AGI是一个重要的关注点? 58% 了解人工通用智能(AGI)的潜在发展以及与之相关的利益/风险,应该是NLP研究人员的一个重要优先事项
AGI和主要风险 (2)最近的进展正在使我们走向AGI? 57% 大规模ML建模的最新发展(如语言建模和强化学习)是朝着AGI发展的重要步骤。
AGI和主要风险 (3)人工智能可能很快导致革命性的社会变革? 73% 本世纪,由人工智能/ML的进步引起的劳动自动化可能会导致经济重组和社会变革,其规模至少是工业革命时期的规模。
AGI和主要风险 (4)人工智能的决策可能导致核弹级别的灾难? 36% 人工智能或机器学习系统做出的决策可能会在本世纪造成至少与全面核战争一样严重的灾难。
语言理解 (1)语言模型能理解(understand)语言? 51% 一些只对文本进行训练的生成模型,如果有足够的数据和计算资源,就可以在某种意义上理解自然语言
语言理解 (2)多模态模型能理解语言? 67% 对于多模态生成模型而言,比如一个经过训练可以访问图像、传感器和驱动器actuator数据等的模型,只要有足够的数据和计算资源,就可以理解自然语言。
语言理解 (3)纯文本评价可以衡量模型的语言理解能力? 36% 原则上,可以通过跟踪一个模型在纯文本分类或语言生成基准上的表现来评估其理解自然语言的程度。
NLP未来的研究方向 (1)从业者太过于关注语言模型的规模? 72% 目前,该领域过多地关注机器学习模型的大规模化
NLP未来的研究方向 (2)过于关注基准数据集? 88% 目前NLP模型过多地关注在基准上优化性能
NLP未来的研究方向 (3)模型架构走错了方向? 37% 过去5年发表的大部分关于模型架构的研究都走在了错误的道路上。
NLP未来的研究方向 (4)语言生成走错了方向? 41% 过去5年中发表的关于开放式语言生成任务的大部分研究都走在了错误的道路上。
NLP未来的研究方向 (5)可解释模型的研究走错了方向? 50% 过去5年中发表的大多数关于建立可解释模型的研究都走在了错误的道路上
NLP未来的研究方向 (6)黑盒的可解释性走错了方向? 42% 过去5年中发表的关于解释黑箱模型的大部分研究都走在了错误的道路上。
NLP未来的研究方向 (7)我们应该做更多的工作来吸收跨学科的见解? 82% 与目前的状况相比,NLP研究人员应该更优先考虑纳入相关领域科学(如社会语言学、认知科学、人机交互)的见解和方法。

(1)NLP研究领域

尽管 30%不是一个大数字,但这也反映了这一部分 NLP 研究者的一种信念,即 NLP 研究将在不久的将来发生重大变化(至少在谁提供资金以及提供多少资金方面)。

为什么他们的态度会相对悲观?背后有许多可能原因。

  • 比如由于工业界影响力过大而导致的创新停滞,工业界将凭借少量资源充足的实验室来垄断行业,NLP 和其他 AI 子领域之间的界限将消失等等。

67% 的受访者认同,他们认为,大多数 NLP 工作在科学意义上是可疑的。

  • 受访者对“可疑”的定义可能是多样的,包括根本不具有完整性的工作、所研究问题不恰当、研究结果无意义,或者研究发现并不重要、不可靠等等。

(2)规模化、归纳偏差和来自临近领域的启发

(3)AGI和主要风险

(4)语言理解

(5)NLP未来的研究方向

NLP ≠ NLU

【2021-8-21】NLP≠NLU,机器学习无法理解人类语言,详情见机器之心的不同于NLP,数据驱动方法与机器学习无法攻克NLU,原因有三点英文原文

  • 长期以来,我们一直在与机器沟通:编写代码–创建程序–执行任务。然而,这些程序并非是用人类“自然语言“编写的,像Java、Python、C和C ++语言,始终考虑的是”机器能够轻松理解和处理吗?”
  • “自然语言处理”(Natural Language Processing,NLP)的目的与此相反,它不是以人类顺应机器的方式学习与它们沟通,而是让机器具备智力,学习人类的交流方式。
  • 自然语言处理,实际上是人工智能和语言学的交叉领域,但多年来,仅在语音转录、语音命令执行、语音关键词提取的工作上兢兢业业,规规矩矩,应用到人机交互,就显得十分吃力。NLP的核心步骤:分词→词干提取→词形还原→词性标注→命名实体识别→分块
  • 因为在语料预处理阶段,NLP通常直接给出“断句”,比如 “订一张明天从北京到杭州的机票,国航头等舱”,经过NLP模型处理后,机器给出的输出出发地、目的地等信息,准确率高但这背后,我们并不知道机器理解了什么。由于足够好用,人们也就不多问了。在更加复杂的任务中,比如机器翻译,基于深度学习的编码、解码架构会将原句子转换成我们根本不熟悉的样子,也就是在无穷维空间中的点。研究人员试图向神经网络添加参数以提高它们在语言任务上的表现,然而,语言理解的根本问题是“理解词语和句子下隐藏的含义“
  • 伦斯勒理工学院的两位科学家撰写了一本名为《人工智能时代语言学》的书,探讨了目前的人工智能学习方法在自然语言理解(Natural Language Understanding,NLU)中的瓶颈,并尝试探索更先进的智能体的途径。
  • (1)AI必须从“处理”自然语言到“理解”自然语言
    • 机器“记录”了数据并不意味着“理解”了数据。近几十年来,机器学习算法一直尝试完成从NLP 到 NLU 的转型,机器学习曾长期承载着转型使命的荣光。机器学习模型是一种知识精益系统,它试图通过统计词语映射来回答上下文关系。在这些模型中,上下文是由词语序列之间的统计关系形成的,而非词语背后的含义。因而数据集越大、示例越多样化,机器对上下文关系的理解越精确。
    • 机器学习终将失宠,因为它们需要太多的算力和数据来自动设计特征、创建词汇结构和本体,以及开发将所有这些部分结合在一起的软件系统,而且机器人也不知道自己在做什么,以及为什么这样做。它们解决问题的方法不依赖与世界、语言或自身的互动(人类)。因此,它们无法理解两个人长时间对话中对同一件事情的描述越来越简短的情景,也就是文本缺失现象。巨大人工成本使机器学习陷入瓶颈,并迫使人们寻求其他方法来处理自然语言, 并导致了自然语言处理中经验主义范式(认为语言理解起源于感觉)的出现。
  • 具有“感觉”的人工智能,或许会在自然语言处理上有三个突破:
    • 通过语言交流激活感觉模型,并以此承载记忆,从而可以应对人类之间交流时的文本缺失现象,实现“默契”(正确)的解码;
    • 理解语言的上下文相关含义,并从单词和句子的歧义中找到合适的理解,以及从感觉世界中寻找更强的约束和限制;
    • 向它们的人类合作者解释它们的想法、行动和决策;
  • 机器也需要在世界互动时保持终身学习。而机器学习由于将可压缩性和可学习性对等起来,并且限于表面的符号统计关系理解,以及不可解释性等原因,不可避免丢失背景信息,而做不到上述层次的理解。总之,机器要理解自然语言,感觉经验是必不可少的。
  • 书中指出:“ 语言理解不能与整体的认知过程区分开来,启发机器人理解语言也要运用其他感知(例如视觉、触觉)。”正如在现实世界中,人类也是利用他们丰富的体态动作来填补语言表达的空白。
  • NLP 中广泛使用数据驱动的经验方法有以下原因:符号和逻辑方法未能产生可扩展的 NLP 系统,导致 NLP (EMNLP,指数据驱动、基于语料库的短语,统计和机器学习方法)中所谓的经验方法的兴起。EMNLP的先驱之一肯尼思·丘奇(Kenneth Church)所解释的,NLP数据驱动和统计方法的拥护者对解决简单的语言任务感兴趣,其动机从来不是暗示语言就是这样运作的,而是”做简单的事情总比什么都不做好”。这种转变的动机被严重误解,他们以为这个“可能大致正确的”( Probably Approximately Correct ,PAC)范式将扩展到完全自然的语言理解。
  • 是时候重新思考NLU方法了,对 NLU 的”大数据”方法不仅在心理上、认知上甚至计算上都是难以操作的,而且这种盲目的数据驱动 NLU 方法在理论和技术上也有缺陷。
    • “新一代和当代的NLP研究人员在语言学和NLP的理解上有差别,因此,这种被误导的趋势导致了一种不幸的状况:坚持使用”大语言模型”(LLM)构建NLP系统,这需要巨大的计算能力,并试图通过记住海量数据来接近自然语言。
    • 这几乎是徒劳的尝试。我们认为,这种伪科学方法不仅浪费时间和资源,而且引诱新一代年轻科学家认为语言只是数据。更糟糕的是,这种方法会阻碍自然语言理解(NLU)的任何真正进展。
  • 为什么NLP与NLU不同?
  • 语言理解不承认任何程度的误差,它们要充分理解一个话语或一个问题。
    • 常见的”下游 NLP”任务:综述–主题提取–命名实体识别(NER)–(语义)搜索–自动标记–聚类
    • 上述所有任务都符合所有机器学习方法的基础可能大致正确(PAC) 范式。
    • 对普通口语的真正理解与单纯的文本(或语言)处理是完全不同的问题。在文本(或语言)处理中,我们可以接受近似正确的结果。

NLU为什么难

【2022-5-31】思考:人类发明语言是为了高效传达信息,潜在要点:

  • 忽略共同背景信息:故意省略一些常识信息(都知道的知识)、场景信息(当前时间地点情景)
  • 压缩:尽量使用简短语言传达最重要的信息
  • 解压缩:对方接收到压缩的信息后,根据常识、场景推断背后的传达的意思

然而,机器远没有人那么聪明,现在没法完成人一样的解压缩工作

  • 当前的数据驱动+机器学习方法与NLU关系不大
  • 机器学习将大量数据概括为单一函数(模式、范式)
  • 统计无法捕捉(甚至不能近似)语义

为什么 NLU 很困难:

  • (1)文本容易丢失:”缺失文本现象”(MTP)自然语言理解中所有挑战的核心。
    • 场景:演讲者将思想“编码”为某种自然语言中的话语,然后听众将话语“解码”为演讲者打算/希望传达的思想。”解码”过程是NLU中的”U”–即理解话语背后的思想。
    • MTP:媒体传输协议,Media Transfer Protocol
  • (2)”解码”过程中需要没有任何误差,才能从说话者的话语中,找出唯一一种意在传达的含义。这正是NLU困难的原因。
    • 两种优化通信的方案:
      • 1.说话者可以压缩(和最小化)在思想编码中发送的信息量,并且听者做一些额外的工作解码(解压缩)话语;
      • 2.演讲者多做一部分工作,把所有想要传达的思想信息告诉听者,减少听者的工作量;
  • NLU的问题所在:机器不知道我们遗漏了什么,它们不知道我们都知道什么。如果它们不能以某种方式”整理”我们话语的所有的含义,那么软件程序将永远不能完全理解我们话语背后的想法。
    • 为了有效地沟通,人们在交流中通常不会说对方知道的信息。这也正是为什么都倾向于忽略相同的信息——因为都了解每个人都知道的,而这正是所谓的共同背景知识。人类在大约 20 万年的进化过程中,发展出的这一天才优化过程非常有效。
    • NLU的挑战,并不是解析,阻止,POS标记,命名实体识别等, 而是解释或揭示那些缺失的信息。并隐含地假定为共享和共同的背景知识
  • 在此背景下,整理了三个原因,说明为什么机器学习和数据驱动的方法不会为自然语言理解提供解决方案。
    • 1、ML 方法甚至与 NLU 无关:ML 是压缩的,语言理解需要解压缩
      • 机器的自然语言理解由于MTP而变得困难,因为日常口语被高度压缩,因此”理解”的挑战在于未压缩(或发现)缺失的文本。
      • MTP 现象正是为什么数据驱动和机器学习方法虽然在某些 NLP 任务中可能很有用,但与 NLU 甚至不相关的原因。
      • 机器可学习性(ML) 和可压缩性(COMP)之间的等价性已在数学上建立。即已经确定,只有在数据高度可压缩(未压缩的数据有大量冗余)时,才能从数据集中学习,反之亦然。
      • 机器学习是关于发现将大量数据概括为单一函数。另一方面,由于MTP,自然语言理解需要智能的”不压缩”技术,可以发现所有缺失和隐含的假定文本。因此,机器学习和语言理解是不兼容的——事实上,它们是矛盾的。
    • 2、ML 方法甚至与 NLU 无关:统计上的无意义
      • ML 本质上是一种基于在数据中找到一些模式相关性)的范式。因此,该范式的希望是在捕捉自然语言中的各种现象时,发现它们存在统计上的显着差异。
      • 但是当”小”和”大”(或”打开”和”关闭”等)等反义词/反义词以相同的概率出现在相同的上下文中,统计分析不能建模(甚至不能近似)语义——就这么简单!
      • 有人说,收集足够的例子,一个系统可以确立统计学意义。但是,需要多少个示例来”学习”如何解决结构中的引用呢?机器学习/数据驱动系统需要看到上述 40000000 个变体,以学习如何解决句子中的引用。如果有的话,这在计算上是不可信的。正如Fodor和Pylyshyn曾经引用著名的认知科学家乔治.米勒( George Miller),为了捕捉 NLU 系统所需的所有句法和语义变化,神经网络可能需要的特征数量超过宇宙中的原子数量!这里的寓意是:统计无法捕捉(甚至不能近似)语义
    • 3、ML 方法甚至与 NLU 无关:意图
      • 逻辑学家们长期以来一直在研究一种语义概念,试图用语义三角形(符号概念语义)解释什么是”内涵”。
      • 一个符号用来指代一个概念,概念可能有实际的对象作为实例,但有些概念没有实例,例如,神话中的独角兽只是一个概念,没有实际的实例独角兽。类似地,”被取消的旅行”是对实际未发生的事件的引用,或从未存在的事件等。
      • 每个”事物”(或认知的每一个对象)都有三个部分:
        • 一个符号,符号所指的概念以及概念具有的具体实例。
        • 一个概念(通常由某个符号/标签所指)是由一组属性和属性定义,也许还有额外的公理和既定事实等。
        • 然而,概念与实际(不完美)实例不同,在数学世界中也是如此。
  • 内涵决定外延,但外延本身并不能完全代表概念。
    • 自然语言充斥着内涵现象,因为语言具有不可忽视的内涵。但是机器学习/数据驱动方法的所有变体都纯粹是延伸的——它们以物体的数字(矢量/紧张)表示来运作,而不是它们的象征性和结构特性,因此在这个范式中,我们不能用自然语言来模拟各种内涵。顺便说一句,神经网络纯粹是延伸的,因此不能表示内涵,这是它们总是容易受到对抗性攻击的真正原因

人类在传达自己的想法时,其实是在传递高度压缩的语言表达,需要用大脑来解释和”揭示”所有缺失但隐含假设的背景信息。 语言是承载思想的人工制品,因此,在构建越来越大的语言模型时,机器学习和数据驱动方法试图在尝试找到数据中甚至不存在的东西时,徒劳地追逐无穷大。

【2021-8-21】NLP≠NLU,机器学习无法理解人类语言英文原文

示例

示例:

  • cover me ! → 让盖外套,还是 掩护 ?

【2023-6-4】中文博大精深

NLU is hard! 自然语言理解太难了系列

一直关注刘群老师的微博,常常看见他分享的一些好玩的#自然语言处理太难了#。 遂整理了NLP实在是太难了系列语句,大家一笑无妨。这里列举了一些关于分词、实体识别、知识图谱相关的语句,按照难度从低到高排列,最高难度的放在了最后(需要强大的知识图谱哦,欢迎大家把答案开在评论里,也欢迎添加新的or搞笑的例子,O(∩_∩)O谢谢!)。

  • Github repo

  • 难度:※※ 两颗星
    • 来到杨过曾经生活过的地方,小龙女动情地说:“我也想过过过儿过过的生活。”
    • 来到儿子等校车的地方,邓超对孙俪说:“我也想等等等等等过的那辆车。”
    • 赵敏说:我也想控忌忌己不想无忌。
    • 你也想犯范范范玮琪犯过的错吗
    • 对叙打击是一次性行为?
    • 《绿林俊杰》–林俊杰做错了什么?为什么要绿他
  • 难度:※※※ 三颗星
    • 写给卖豆芽的对联: 长长长长长长长,长长长长长长长。(solution: changzhangchangzhangchangchangzhang zhangchangzhangchangzhangzhangchang,zhangchangchangzhangchangzhangchang,zhangchangzhangchangzhangchangchang)
    • 季姬寂,集鸡,鸡即棘鸡。棘鸡饥叽,季姬及箕稷济鸡。鸡既济,跻姬笈,季姬忌,急咭鸡,鸡急,继圾几,季姬急,即籍箕击鸡,箕疾击几伎,伎即齑,鸡叽集几基,季姬急极屐击鸡,鸡既殛,季姬激,即记《季姬击鸡记》。
    • 石室诗士施氏,嗜狮,誓食十狮。氏时时适市视狮。十时,适十狮适市。是时,适施氏适市。施氏视是十狮,恃矢势,使是十狮逝世。氏拾是十狮尸,适石室。石室湿,氏使侍拭石室。石室拭,氏始试食是十狮尸。食时,始识是十狮尸,实十石狮尸。试释是事。《施氏食狮史》
    • 去商店买东西一算账1001块,小王对老板说:“一块钱算了。” 老板说好的。于是小王放下一块钱就走了,老板死命追了小王五条街又要小王付了1000,小王感慨:#自然语言理解太难了# ​
    • “碳碳键键能能否否定定律一” ​
    • 书《无线电法国别研究》
    • 要去见投资人,出门时,发现车钥匙下面压了一张员工的小字条,写着“老板,加油!”,瞬间感觉好有温度,当时心理就泪奔了。心里默默发誓:我一定会努力的! 车开了15分钟后,没油了。。。
    • 他快抱不起儿子了,因为他太胖了
    • 中文里面“大胜”和“大败”意思相同,刚发现英文里面也有类似的现象:valuable和invaluable都是表示非常有价值的意思
    • How can I help you? 我能帮您什么?我怎么可以帮你!米国某酒店前台翻译机
    • 一家名为“宝鸡有一群怀揣着梦想的少年相信在牛大叔的带领下会创造生命的奇迹网络科技有限公司”走红网络,该公司全名长达39个字,还是一句主谓宾齐全的句子。宝鸡工商部门表示,该公司属合法注册,但名字太长不利于刻公章开发票
    • “一位友好的哥谭市民” “一位友好/的哥/谭市民”
  • 难度:※※※※ 四颗星
    • 宝宝的经纪人睡了宝宝的宝宝,宝宝不知道宝宝的宝宝是不是宝宝的亲生的宝宝,宝宝的宝宝为什么要这样对待宝宝!宝宝真的很难过!宝宝现在最担心的是宝宝的宝宝是不是宝宝的宝宝,如果宝宝的宝宝不是宝宝的宝宝那真是吓死宝宝了。
    • 中不不建交是受印度的影响,中不建交不受印度的影响。
  • 难度:※※※※※ 五颗星
    • NLP同学接招。这玩意非得配合超强知识图谱才能解决,非单纯NLP技术搞的定
    • 人工智障:“明天早上六点半的时候,叫我起床” —— 好的,明天早上六点半的时候,我称呼你为“起床”
    • 同学会标语:从小便相识,大便情更浓
  • 一些easy的作为结尾
    • 校长说衣服上除了校徽别别别的
    • 过几天天天天气不好
    • 看见西门吹雪点上了灯,叶孤城冷笑着说:“我也想吹吹吹雪吹过的灯”,然后就吹灭了灯。
    • 今天多得谢逊出手相救,在这里我想真心感谢“谢谢谢逊大侠出手”
    • 灭霸把美队按在地上一边摩擦一边给他洗脑,被打残的钢铁侠说:灭霸爸爸叭叭叭叭儿的在那叭叭啥呢
    • 姑姑你估估我鼓鼓的口袋里有多少谷和菇!!
    • “你看到王刚了吗”“王刚刚刚刚走”
    • 张杰陪俩女儿跳格子:俏俏我们不要跳跳跳跳过的格子啦
    • 骑车出门差点摔跤,还好我一把把把把住了
    • 我朋友问父亲:我大大大(大大爷)和我姑姑谁年龄大?朋友爸爸说:你大大大大!
    • 我背有点驼,麻麻说“你的背得背背背背佳
    • 南京市长江大桥

男人的一生,分四个阶段:中文:

  • 喜欢上一个人 Like someone
  • 喜欢上一个人 Like to fuck someone
  • 喜欢上一个人 Like the last one
  • 喜欢上一个人 Like to be alone

翻译这段话:”人要是行,干一行行一行,一行行行行行。行行行干哪行都行。要是不行,干一行不行一行,一行不行行行不行,行行不行,干哪行都不行。要想行行,首先一行行。成为行业内的内行,行行成内行。行行行,你说我说得行不行。”

Translate this passage: “If a person is capable, they can excel in any profession they choose. If they’re not capable, they won’t succeed in any profession, no matter which one they choose. If you want to be successful, you must first become proficient in one field. Become an expert in your industry, and you’ll achieve success. Is what I’m saying reasonable?”

如何处理OOV

NLP 研究主流目前如何处理 out of vocabulary words?

解决OOV问题的集中方法

  • 更换更复杂的字符级模型,字符有限,以单词为单位为导致组合爆炸
  • OOV单词较少时,可以直接替换成< UNK>标签来忽略OOV的问题,尽管实际应用时候并不想这样————总不能给用户输出一个< UNK>吧?

如果OOV单词占比较多(如30%),改怎么办?对数据的处理可操作性更强效果也是特别直观地好。

  1. Mixed Word/Character Model 字符模型
    • 即把所有的OOV词,拆成字符。比如 Jessica,变成< B>_J,< M>_e,< M>s,< M>s,< M>i,< M>c,< E>a。其中< B>< M>< E>是Begin,Middle,End的标记。这样处理的好处就是消灭了全部的OOV。坏处就是文本序列变得非常长,对于性能敏感的系统,这是难以接受的维度增长。
  2. Wordpiece Model(WPM) 拆成子词
    • 和上面一样,同样要进行拆词。不同的是,非OOV的词也要拆,并且非字符粒度,而是sub-word 子词。还是 Jessica,变成< B>Je,< M>ssi,< E>ca。这类方法最早应用于Google的语音识别系统,现在已经在NLP中遍地开花了。拆词规则可以从语料中自动统计学习到,常用的是BPE(Byte Pair Encode)编码,出处在《Neural Machine Translation of Rare Words with Subword Units》
    • 和第一种方法相比,虽然序列的长度控制住了,但是在有限词表的情况下,OOV仍然存在
    • 另外,sub-word的OOV有一种麻烦,对于Jessica的例子,即使只有ssi是OOV,Je和ca都在词表内,整个Jessica的**单词仍然无法正确表示**。
  3. UNK处理
    • 在训练数据充足的情况下,RNN模型可以轻松支持30k-80k的词表。在大多数情况下,扩大词表都是首选的方案。经过WPM处理后,配合词表加大,剩下的OOV都是冷门的长尾词。如果不关注这部分性能,可以直接扔掉OOV词,删掉包含OOV的数据。对于分类型任务,就全部替换成标签。对于生成型任务,有不同的细节处理方案,可以看下经典的[《Addressing the Rare Word Problem in Neural Machine Translation》](https://arxiv.org/abs/1410.8206),里面介绍了Copyable、PosALL和PosUNK三种替换策略。这类策略对于实体类NER的词,有比较好的效果。
  4. 中文的处理
    • 英文中包含的姓名、复合词、同源词和外来词,使得WPM的方法效果拔群。
    • 在处理中文时,WPM可以有效帮助解决混入的英文词和阿拉伯数字等。对于纯中文的句子,分割成子词的意义不大
    • 这时候,扩大词表仍然是首选。
  5. 扩大词表
    • 终极解决办法。通常情况不使用大词表,一方面是因为训练数据的多样性有限,另一方面是softmax的计算速度受限。对于第一种情况,扩大语料范围。对于第二种情况,相关的加速策略可以将词表扩大10倍而GPU上的预测速度只降低一半(从5W词到50W词)。比如《On Using Very Large Target Vocabulary for Neural Machine Translation》。tensorflow中有对应的实现 tf.nn.sampled_softmax_loss
  6. 模型
    • 构建一个固定词表的同时,维护一个动态的词表。这种机制一般称为Copy/Pointer Mechanism。这个动态的词表,事实上就是source input里面的词copy过来的。动态词表里面一般是一些罕见词,而固定的词表是你基于某种规则构建你的词表(比如:出现频数大于5)。这样的方法在十分优雅,两个不同词表的合作,就像GPU的缓存和内存之间的合作。

NLP简介

《集智俱乐部》NLP介绍专题:北大李嫣然

NLP 就是人类和机器之间沟通的桥梁

自然语言就是大家平时在生活中常用的表达方式,大家平时说的「讲人话」就是这个意思。

  • 自然语言:我背有点驼(非自然语言:我的背部呈弯曲状)
  • 自然语言:宝宝的经纪人睡了宝宝的宝宝(微博上这种段子一大把)

什么是NLP

自然语言处理研究在人与人交际中以及在人与计算机交际中的语言问题的一门学科。自然语言处理要研制表示语言能力和语言应用的模型,建立计算框架来实现这样的语言模型,提出相应的方法来不断完善这样的语言模型,根据这样的语言模型设计各种实用系统,并探讨这些实用系统的评测技术。

NLP 诞生

1948年,香农提出信息熵的概念。此时尚未有NLP,但由于熵也是NLP的基石之一,在此也算作是NLP的发展历程。

按照维基百科的说法,NLP发源于1950年。图灵于该年提出“图灵测试”,用以检验计算机是否真正拥有智能。

NLP可以追溯到20世纪50年代计算机程序员开始尝试简单的语言输入。NLU在20世纪60年代开始发展,希望让计算机能够理解更复杂的语言输入。NLU被认为是NLP的一个子方向,主要侧重于机器阅读理解:让计算机理解文本的真正含义

自然语言处理,即 Natural Language Processing,简称 NLP ,是一门旨在利用计算机技术来理解运用自然语言的学科。在不同的场景下,有时候也称之为计算语言学(Computational Linguistics, CL)或者自然语言理解(Natural Language Understanding, NLU)。

  • NLP 主要通过计算机技术来进行:通过计算机技术承载、运用
  • NLP 要理解和运用的是自然语言:英语、法语等自然演变而来的语言,而非C/Java等人类创造出来的程序设计语言
  • NLP 试图理解自然语言,但何谓「理解」其实并没有一个确定的标准
    • 脑科学尚未研究清楚人类使用语言时大脑如何运作,还没有一个系统的、全面的认识;现有的技术框架下,用计算机做到完全理解自然语言,是不可能的
    • 特定场景中,机器能对自然语言表达的语句进行正确响应,就算是理解了自然语言

自然语言处理本质上属于认知智能任务。众所周知,认知智能是人类与动物对主要区别之一,与许多动物也具有低级的感知智能不同,认知智能需要更强的抽象推理能力。自然语言处理本身有很多特性,包括歧义性、抽象性、组合性、进化性、非规范性、主观性、知识性、难迁移性等。这些特性提升了自然语言处理的难度,自然语言处理也成为制约人工智能取得更大突破和更广泛应用的瓶颈。包括多位图灵奖得主在内的多位知名科学家都认为自然语言处理是下一个人工智能需要重点攻克的方向

自然语言处理的核心困难,在于自然语言的形式与语义之间存在多对多的映射。为了解决这个困难,我们通常利用“知识”来进行约束。因此,如何获取和利用“知识”成为了一个关键科学问题。

“知识”(广义)的来源:

  • (1)广义的“知识”包括狭义的知识、算法以及数据。其中,狭义的知识指可以人工定义的、显性的知识,包括语言知识、常识知识和世界知识。语言知识通常可以通过词典、规则库等来获取;世界知识也可以从文本中挖到,如知识图谱;而常识知识往往很难从文本中直接获取,现在一般通过人工的方式,将人类的常识知识结构化地存储下来(如CYC项目)。
  • (2)算法在本质上也是一种知识,但它是一种动态的知识。在深度学习出现之前,主流的算法是浅层学习,通过人工提取解决问题的关键特征,再对特征进行线性加权,而所谓的“知识”就体现在对“特征”的定义和提取之中。后来,随着深度学习的发展,深层神经网络越来越多地取代人工进行特征的归纳和提取,端到端的学习使得任务可以自动实现。另外,如CKY,MST等NLP算法,也与语言知识密切相关。
  • (3)数据也是一种自动的、隐性的知识。数据包括有标注和无标注两种类型。有标注的数据往往规模有限,蕴含的知识也有限;为了扩大数据的规模,最好使用无标注的数据,如大量传统的文本数据,然后通过设计自监督任务来预训练一个语言模型,这也就是目前整个人工智能领域最火的预训练语言模型方向。

NLP分类

自然语言处理主要包括两个方面:一是对文本符号本身的理解,二是自然语言的生成。

NLU与NLP

与NLP类似,NLU使用算法将人类语音转化为结构化本体。 然后使用AI算法检测意图,时间,位置和情绪等

自然语言理解是许多过程的第一步,例如分类文本,收集新闻,归档单个文本,以及更大规模地分析内容。NLU的实际例子包括从基于理解文本发布短命令到小程度的小任务,例如基于基本语法和适当大小的词典将电子邮件重新发送到合适的人。更为复杂的行为可能是完全理解诗歌或小说中的新闻文章或隐含意义。

  • 总而言之, NLU是实现NLP的第一步:在机器处理语言之前,必须首先理解它。

NLU是NLP的组成部分,负责人类理解某个文本所呈现的含义。与NLP最大的区别之一是NLU超越了解单词,因为它试图解释和处理常见的人类错误,如错误发音或字母或单词的颠倒。

推动NLP的理论是 Noam Chomsky 在1957年的“句法结构”中所设定的假设:“语言L的语言分析的基本目标是将L的句子的语法序列与不符合语法的序列分开。 这不是研究语言L的句子,而是研究语法序列的结构。”

句法分析确实用于多个任务,通过将语法规则应用于一组单词并通过多种技术从中获得意义来评估语言如何与语法规则保持一致:

  • 词形还原:将单词的变形形式简化为单一形式,以便于分析。
  • 词干:将变形的词语切割成它们的根形式。
  • 形态分割:将单词划分为语素。
  • 分词:将连续文本分成不同的单元。
  • 解析:句子的语法分析。
  • 词性标注:识别每个单词的词性。
  • 句子破坏:将句子边界放在连续文本上。

NLP与NLU:从语言理解到语言处理

发展历史

微软亚洲研究院成立20周年时表示:NLP将迎来黄金十年

  • 比尔·盖茨曾说过,“语言理解是人工智能皇冠上的明珠”。自然语言处理(NLP,Natural Language Processing)的进步将会推动人工智能整体进展。 NLP的历史几乎跟计算机和人工智能(AI)的历史一样长。回顾基于深度学习的NLP技术的重大进展,从时间轴来看主要包括:
  • 2003年,NNLM
  • 2013年,Word Embeddings
  • 2014年,Seq2Seq
  • 2015年,Attention
  • 2015年,Memory-based networks
  • 2017年,Transformer
  • 2018年,BERT
  • 2019年,XLNet
flowchart TD %% 节点颜色 classDef red fill:#f02; classDef green fill:#5CF77B; classDef blue fill:#6BE0F7; classDef orange fill:#F7CF6B; classDef grass fill:#C8D64B; %%节点关系定义 O(传统NLP):::grass-->|神经网络|A(2003,NNLM):::blue A -->|词嵌入| B(2013,Word Embedding):::green B -->|编码-解码结构| C(2014,Seq2seq):::green C -->|注意力| D(2015,Attention):::green D -->|记忆力| E(2015,Memory Network):::green E -->|transformer结构| F(2017,Transformer):::green F -->|综合Elmo+GPT| G(2018,Bert):::green G -->|双流| H(2019,XLNet):::green

【2022-4-24】哈工大教授车万翔:自然语言处理中的伪数据, 报告回放

自然语言处理技术已经经历了四次范式变迁:

  • 1950-1990,小规模专家知识
  • 1990-2010,浅层学习模型
  • 2010-2017,深度学习模型
  • 2018年至今,大规模预训练模型 数据越来越重要,目前主要是通过“预训练+精调”的范式来处理大规模数据,但预训练与精调之间的任务往往差距较大,这限制了进一步提高下游任务的准确率。

自然语言处理被誉为“人工智能皇冠上的明珠”,而语言的理解需要“知识”——狭义知识、算法和数据的约束。数据的作用越来越重要,但是目前的预训练方式,预训练任务与目标任务之间的差距较大,本文提出的伪数据方法,正是为了弥补这种差距。同时,伪数据也是融合规则知识的一种手段。

预训练语言模型发展历史

【2021-1-17】Impressive progress of deep learning on unsupervised text corpora,A Review of the Neural History of Natural Language Processing

  • 2001 : Neural language models 神经语言模型,完成了n-gram到神经网络的转变
    • Bengio 等人于 2001 年提出第一个神经语言模型,前馈神经网络(feed-forward neuralnetwork)
    • 根据出现前N个词语预测下一个单词,得到副产物,词向量,即后来熟知的词嵌入(word embeddings)
    • 语言模型的建立是一种无监督学习(unsupervised learning),Yann LeCun 也将其称之为预测学习(predictive learning),是获得世界如何运作常识的先决条件。
    • 接着,前馈神经网络已经被循环神经网络(RNNs)和长短期记忆神经网络(LSTMs)取代
  • 2008 : Multi-task learning 多任务学习
    • 1993 年由 Rich Caruana 首次提出多任务学习思想,并应用于道路追踪和肺炎预测。
    • 2008 年Collobert 和 Weston 等人首次在自然语言处理领域将多任务学习应用于神经网络,多任务学习是在多个任务下训练的模型之间共享参数的方法,在神经网络中可以通过捆绑不同层的权重轻松实现;共享的词嵌入矩阵使模型可以相互协作,共享矩阵中的低层级信息,而词嵌入矩阵往往构成了模型中需要训练的绝大部分参数。Collobert 和 Weston 发表于 2008 年的论文,影响远远超过了它在多任务学习中的应用。它开创的诸如预训练词嵌入和使用卷积神经网络处理文本的方法,在接下来的几年被广泛应用。他们也因此获得了 2018 年机器学习国际会议(ICML)的 test-of-time 奖。
  • 2013 : Word embeddings,词嵌入 → Neural networks for NLP开启
    • 长久以来,NP领域一直通过稀疏向量对文本进行表示的词袋模型
    • 2001年首次出现用稠密的向量对词语进行描述,即词嵌入
    • 2013年Mikolov等人工作的主要创新之处在于,通过去除隐藏层近似计算目标使词嵌入模型的训练更为高效。尽管这些改变在本质上是十分简单的,但它们与高效的 word2vec(word to vector,用来产生词向量的相关模型)组合在一起,使得大规模的词嵌入模型训练成为可能。Word2vec 有两种不同的实现方法:CBOW(continuous bag-of-words)和 skip-gram
    • 虽然 word2vec 捕捉到的关系具有直观且几乎不可思议的特性,但后来的研究表明,word2vec 本身并没有什么特殊之处:词嵌入也可以通过矩阵分解来学习,经过适当的调试,经典的矩阵分解方法 SVD 和 LSA 都可以获得相似的结果。
    • Word2vec 的应用范围也超出了词语级别:带有负采样的 skip-gram——一个基于上下文学习词嵌入的方便目标,已经被用于学习句子的表征。它甚至超越了自然语言处理的范围,被应用于网络和生物序列等领域。
    • 2013年 和 2014 年是自然语言处理领域神经网络时代的开始。其中三种类型的神经网络应用最为广泛:
      • 循环神经网络(recurrent neural networks):Vanilla 循环神经网络 → 经典的长短期记忆网络(解决梯度消失和梯度爆炸问题)→ 双向的长短期记忆记忆网络
      • 卷积神经网络(convolutionalneural networks):优点是具有更好的并行性。因为卷积操作中每个时间步的状态只依赖于局部上下文,而不是循环神经网络中那样依赖于所有过去的状态
      • 结构递归神经网络(recursive neural networks):自下而上构建序列的表示,与从左至右或从右至左对序列进行处理的循环神经网络形成鲜明的对比。树中的每个节点是通过子节点的表征计算得到的。一个树也可以视为在循环神经网络上施加不同的处理顺序,所以长短期记忆网络则可以很容易地被扩展为一棵树。
  • 2014 : Sequence-to-sequence models 序列到序列模型
    • 2014 年,Sutskever 等人提出了序列到序列学习,即使用神经网络将一个序列映射到另一个序列的一般化框架。
    • 2016 年,谷歌宣布他们将用神经机器翻译模型取代基于短语的整句机器翻译模型。谷歌大脑负责人 Jeff Dean 表示,这意味着用 500 行神经网络模型代码取代 50 万行基于短语的机器翻译代码。
    • 代码解析
  • 2015 : Attention及Memory-based networks 注意力机制
    • 序列到序列学习的主要瓶颈是,需要将源序列的全部内容压缩为固定大小的向量。注意力机制通过让解码器回顾源序列的隐藏状态,以此为解码器提供加权平均值的输入来缓解这一问题
    • 注意力机制是神经网络机器翻译 (NMT) 的核心创新之一,也是使神经网络机器翻译优于经典的基于短语的机器翻译的关键
    • 注意力机制一个有用的附带作用是它通过注意力权重来检测输入的哪一部分与特定的输出相关,从而提供了一种罕见的虽然还是比较浅层次的,对模型内部运作机制的窥探
    • 自注意力机制 可以用来观察句子或文档中周围的单词,获得包含更多上下文信息的词语表示。多层的自注意力机制是神经机器翻译前沿模型 Transformer 的核心。
    • 注意力机制可以视为模糊记忆的一种形式,其记忆的内容包括模型之前的隐藏状态,由模型选择从记忆中检索哪些内容。与此同时,更多具有明确记忆单元的模型被提出。他们有很多不同的变化形式,比如神经图灵机(Neural Turing Machines)、记忆网络(Memory Network)、端到端的记忆网络(End-to-end Memory Newtorks)、动态记忆网络(DynamicMemory Networks)、神经可微计算机(Neural Differentiable Computer)、循环实体网络(RecurrentEntity Network)。
    • 记忆的存取通常与注意力机制相似,基于与当前状态且可以读取和写入。这些模型之间的差异体现在它们如何实现和利用存储模块。
  • 2016年,谷歌发布了 Google Neural Machine Translation (GNMT),即谷歌神经机器翻译,一个 sequence-to-sequence (“seq2seq”) 的模型。现在,它已经用于谷歌翻译的产品系统。资讯
  • 2018 : Pretrained language models,BERT系列 预训练语言模型
    • 预训练的语言模型于 2015 年被首次提出,但直到最近它才被证明在大量不同类型的任务中均十分有效。
  • 其它里程碑:一些其他进展虽不如上面提到的那样流行,但仍产生了广泛的影响。
    • 基于字符的描述(Character-based representations)
      • 在字符层级上使用卷积神经网络和长短期记忆网络,以获得一个基于字符的词语描述,目前已经相当常见了,特别是对于那些语言形态丰富的语种或那些形态信息十分重要、包含许多未知单词的任务。据目前所知,基于字符的描述最初用于序列标注,现在,基于字符的描述方法,减轻了必须以增加计算成本为代价建立固定词汇表的问题,并使完全基于字符的机器翻译的应用成为可能。
    • 对抗学习(Adversarial learning)
      • 对抗学习的方法在机器学习领域已经取得了广泛应用,在自然语言处理领域也被应用于不同的任务中。对抗样例的应用也日益广泛,他们不仅仅是探测模型弱点的工具,更能使模型更具鲁棒性(robust)。(虚拟的)对抗性训练,也就是最坏情况的扰动,和域对抗性损失(domain-adversariallosses)都是可以使模型更具鲁棒性的有效正则化方式。生成对抗网络 (GANs) 目前在自然语言生成任务上还不太有效,但在匹配分布上十分有用。
    • 强化学习(Reinforcement learning)
      • 强化学习已经在具有时间依赖性的任务上证明了它的能力,比如在训练期间选择数据和对话建模。在机器翻译和概括任务中,强化学习可以有效地直接优化”红色”和”蓝色”这样不可微的度量,而不必去优化像交叉熵这样的代理损失函数。同样,逆向强化学习(inverse reinforcement learning)在类似视频故事描述这样的奖励机制非常复杂且难以具体化的任务中,也非常有用。

资料

发展趋势:

  • 规则时代 → 统计时代 → 深度学习时代

NLP 规则时代

1950-1970年,模拟人类学习语言的习惯,以语法规则为主流。除了参照乔姆斯基文法规则定义的上下文无关文法规则外,NLP领域几乎毫无建树。

NLP 统计时代

  • 20世纪70年代开始统计学派盛行,NLP转向统计方法,此时的核心是以具有马尔科夫性质的模型(包括语言模型,隐马尔可夫模型等)。
  • 2001年,神经语言模型,将神经网络和语言模型相结合,应该是历史上第一次用神经网络得到词嵌入矩阵,是后来所有神经网络词嵌入技术的实践基础。也证明了神经网络建模语言模型的可能性。
  • 2001年,条件随机场CRF,从提出开始就一直是序列标注问题的利器,即便是深度学习的现在也常加在神经网络的上面,用以修正输出序列。
  • 2003年,LDA模型提出,概率图模型大放异彩,NLP从此进入“主题”时代。Topic模型变种极多,参数模型LDA,非参数模型HDP,有监督的LabelLDA,PLDA等。
  • 2008年,分布式假设理论提出,为词嵌入技术的理论基础。

在统计时代,NLP专注于数据分布,如何从文本的分布中设计更多更好的特征模式是这时期的主流。在这期间,还有其他许多经典的NLP传统算法诞生,包括tf-idf、BM25、PageRank、LSI、向量空间与余弦距离等。

  • 20世纪80、90年代,卷积神经网络、循环神经网络等就已经被提出,但受限于计算能力,NLP的神经网络方向不适于部署训练,多停留于理论阶段。

NLP 深度时代

  • 2013年,word2vec提出,NLP的里程碑式技术。
  • 2013年,CNNs/RNNs/Recursive NN,随着算力的发展,神经网络可以越做越深,之前受限的神经网络不再停留在理论阶段。在图像领域证明过实力后,Text CNN问世;同时,RNNs也开始崛起。在如今的NLP技术上,一般都能看见CNN/LSTM的影子。
    • 本世纪算力的提升,使神经网络的计算不再受限。有了深度神经网络,加上嵌入技术,人们发现虽然神经网络是个黑盒子,但能省去好多设计特征的精力。至此,NLP深度学习时代开启。
  • 2014年,seq2seq提出,在机器翻译领域,神经网络碾压基于统计的SMT模型。
  • 2015年,attention提出,可以说是NLP另一里程碑式的存在。带attention的seq2seq,碾压上一年的原始seq2seq。记得好像17年年初看过一张图,调侃当时学术界都是attention的现象,也证明了attention神一般的效果。
  • 2017年末,Transformer提出。似乎是为了应对Facebook纯用CNN来做seq2seq的“挑衅”,google就纯用attention,并发表著名的《Attention is All You Need》。初看时以为其工程意义大于学术意义,直到BERT的提出才知道自己还是too young。
  • 2018年末,BERT提出,横扫11项NLP任务,奠定了预训练模型方法的地位,NLP又一里程碑诞生。光就SQuAD2.0上前6名都用了BERT技术就知道BERT的可怕。

深度学习时代,神经网络能够自动从数据中挖掘特征,人们从复杂的特征中脱离出来,得以更专注于模型算法本身的创新以及理论的突破。并且深度学习从一开始的机器翻译领域逐渐扩散到NLP其他领域,传统的经典算法地位大不如前。但神经网络似乎一直是个黑箱,可解释性一直是个痛点,且由于其复杂度更高,在工业界经典算法似乎还是占据主流。

NLP入门

AI产品经理必修课:NLP技术原理与应用

1. 什么是语言?

语言是指生物同类之间由于沟通需要而制定的指令系统,语言与逻辑相关,目前只有人类才能使用体系完整的语言进行沟通和思想交流。

2. 什么是自然语言?

自然语言通常会自然地随文化发生演化,英语、汉语、日语都是具体种类的自然语言,这些自然语言履行着语言最原始的作用:人们进行交互和思想交流的媒介性工具。

  • 语音:与发音有关的学问,主要在语音技术中发挥作用。
  • 音韵:由语音组合起来的读音,即汉语拼音和四声调。
  • 词态:封装了可用于自然语言理解的有用信息,其中信息量的大小取决于具体的语言种类。中文没有太多的词态变换,仅存在不同的偏旁,导致出现词的性别转换的情况。
  • 句法:主要研究词语如何组成合乎语法的句子,句法提供单词组成句子的约束条件,为语义的合成提供框架。
  • 语义和语用:自然语言所包含和表达的意思。

3. 什么是自然语言处理?

自然语言处理(Natural Language Processing,NLP):计算机科学,人工智能和语言学的交叉领域。目标是让计算机处理或“理解”自然语言,以执行语言翻译和问题回答等任务。

NLP包含自然语言理解(Natural Language Understanding,NLU) 和自然语言生成(Natural Language Generation, NLG)两个重要方向,如下图所示。

  • 自然语言理解NLU: 将人的语言形式转化为机器可理解的、结构化的、完整的语义表示,通俗来讲就是让计算机能够理解和生成人类语言。
  • 自然语言生成NLG: 让机器根据确定的结构化数据、文本、音视频等生成人类可以理解的自然语言形式的文本。

场景   小明 小红
非自然语言 汪汪汪汪喵喵喵 (说人话,不然滚犊子)
自然语言但无法理解 苟利国家生死已,岂因祸福避趋之,小红你有没有一种钦定的感觉? (这个人在说什么……)
自然语言,理解并回复 小明,下午放学后你把教室的窗户玻璃擦一擦吧! 我擦,我不擦!

场景一: 接收到非自然语言

  • —— 小明: 汪汪汪汪喵喵喵
  • —— 小红: (说人话,不然滚犊子)

场景二: 接收到自然语言,但不能理解

  • —— 小明: 苟利国家生死已,岂因祸福避趋之,小红你有没有一种钦定的感觉?
  • —— 小红: (这个人在说什么……)

场景三: 接收到自然语言,理解并回复

  • —— 小红: 小明,下午放学后你把教室的窗户玻璃擦一擦吧!
  • —— 小明: 我擦,我不擦!

NLP主要的研究或应用方向有三部分

  • 感知 Perceive:
  • 理解 Understand:
  • 沟通 Communicate:

4. 自然语言处理的难度

  • 自然语言千变万化,没有固定格式。同样的意思可以使用多种句式来表达,同样的句子调整一个字、调整语调或者调整语序,表达的意思可能相差很多。
  • 不断有新的词汇出现,计算机需要不断学习新的词汇。
  • 受语音识别准确率的影响。
  • 自然语言所表达的语义本身存在一定的不确定性,同一句话在不同场景/语境下的语义可能完全不同。
  • 人类讲话时往往出现不流畅、错误、重复等现象,而对机器来说,在它理解一句话时,这句话整体所表达的意思比其中每个词的确切含义更加重要。

自然语言理解的5个难点:

  • 语言的多样性
  • 语言的歧义性
  • 语言的鲁棒性
  • 语言的知识依赖
  • 语言的上下文

NLP难点

  • 没有规律:语言是没有规律的,或者说规律是错综复杂的。
  • 自由组合:语言是可以自由组合的,可以组合复杂的语言表达。
  • 开放集合:语言是一个开放集合,我们可以任意的发明创造一些新的表达方式。
  • 知识依赖:语言需要联系到实践知识,有一定的知识依赖。
  • 上下文:语言的使用要基于环境和上下文。

【2022-3-21】自然语言处理专题

NLP难点

  • 中文分词,这条是专门针对中文说的。众所周知汉语博大精深,老外学汉语尚且虐心,更别提计算机了。同一个任务,同一个模型在英文语料的表现上一般要比中文语料好。无论是基于统计的还是基于深度学习的NLP方法,分词都是第一步。分词表现不好的话,后面的模型最多也只能尽力纠偏
    • 梁启超生前住在这里
    • 武汉市长江大桥
  • 词义消歧:很多单词不只有一个意思,但这个在今年BERT推出后应该不成问题,可以通过上下文学到不同的意思。另一个较难的是指代消歧,即句子中的指代词还原,如“小明受到了老师的表扬,他很高兴”,这个“他”是指“小明”还是指“老师”。
    • 词语(最小单元)级别歧义:
      • The box is in the pen —— 盒子在笔中 or 盒子在围栏里 ?时至今日,google翻译依然无法解决
        • 依赖于文本之外的、海量的「常识」:盒子比笔大
      • 多义词:你这个人真有意思,你到底几个意思
      • 同义词:缩写、专名的别名、网络用语、方言、口语、书面语等 —— 搜索引擎用查询改写(query rewrite)、知识图谱用实体链接
      • 目前 NLP 领域并没有一劳永逸的解决办法,有靠人工构建的小规模高质量知识库如 WordNet、HowNet、同义词词林,也有靠机器学习方法从大量语料中学习到词语的向量表示来隐式地反映词义 —— 量大但并不足够精确。前者往往质量很好但只能覆盖人们实际语言中很小的一部分,后者依赖于语料的数量、质量和领域,对于语料中较少出现的一些词往往就会得到莫名其妙的结果。
    • 句子级别(或段落/篇章)歧义:结构性歧义
      • 喜欢乡下的孩子
      • 放弃美丽的女人让人心碎
  • 二义性:有些句子,往往有多种理解方式,其中以两种理解方式的最为常见,称二义性。
  • OOV问题:随着词嵌入技术大热后,使用预训练的词向量似乎成为了一个主流。但有个问题,数据中的词很可能不在预训练好的词表里面,此即 OOV(out of vocabulary)。主流方法是要么当做UNK处理,要么生成随机向量或零向量处理,当然都存在一定的弊端。
  • 文本相似度计算:文本相似度计算依旧算是难点之一。不过与其说难点,主要是至今没有一种方法能够从理论证明。主流认可的是用余弦相似度。但看论文就会发现,除了余弦相似度外,有人用欧式距离,有人用曼哈顿距离,有人直接向量內积,且效果还都不错。
  • 文本生成的评价指标:文本生成的评价指标多用 BLEU 或者 ROUGE ,但尴尬的是,这两个指标都是基于n-gram的,也就是说会判断生成的句子与标签句子词粒度上的相似度。然而由于自然语言的特性(同一个意思可以有多种不同的表达),会出现生成的句子尽管被人为判定有意义,在BLEU或ROUGE上仍可能会得到很低的分数的情况。这两个指标用在机翻领域倒是没多大问题(本身就是机翻的评价指标),但用在文本摘要和对话生成就明显不合适了。

5. 技术概述

自然语言理解技术概述

基于规则的方法

指利用规则定义如何如何从文本中提取语义。大致思路是人工定义很多语法规则,它们是表达某种特定语义的具体方式,然后自然语言理解模块根据这些规则解析输入该模块的文本。

  • 优点:灵活,可以定义各种各样的规则,而且不依赖训练数据;
  • 缺点:需要大量的、覆盖不同场景的规则,且随着规则数量的增长,对规则进行人工维护的难度也会增加。
  • 结论:只适合用在相对简单的场景,其优势在于可以快速实现一个简单可用的语义理解模块。

基于统计的方法

通常使用大量的数据训练模型,并使用训练所得的模型执行各种上层语义任务。

  • 优点:数据驱动且健壮性较好;
  • 缺点:训练数据难以获得且模型难以解释和调参; 通常使用数据驱动的方法解决分类和序列标注方法。

在具体实践中,通常将这两种方法结合起来使用

  • 没有数据及数据较少时先采取基于规则的方法,当数据积累到一定规模时转为使用基于统计的方法。
  • 在一些基于统计的方法可以覆盖绝大多数场景,在一些其覆盖不到的场景中使用基于规则的方法兜底,以此来保证自然语言理解的效果。

基于深度学习的方法

2019年,BERT 和 GPT-2 的表现震惊了业界,他们都是用了 Transformer,下面将重点介绍 Transformer,因为他是目前「最先进」的方法。

Transformer 和 CNN / RNN 的比较

  • (1)语义特征提取能力:Transformer » 原生CNN = 原生RNN
    • 目前实验结论:Transformer在这方面的能力非常显著地超过RNN和CNN(在考察语义类能力的任务WSD中,Transformer超过RNN和CNN大约4-8个绝对百分点),RNN和CNN两者能力差不太多。
  • (2)长距离特征捕获能力:Transformer > 原生CNN > 原生RNN
    • 原生CNN特征抽取器在这方面极为显著地弱于RNN和Transformer,Transformer微弱优于RNN模型(尤其在主语谓语距离小于13时),能力由强到弱排序为Transformer>RNN»CNN; 但在比较远的距离上(主语谓语距离大于13),RNN微弱优于Transformer,所以综合看,可以认为Transformer和RNN在这方面能力差不太多,而CNN则显著弱于前两者。
  • (3)任务综合特征抽取能力:Transformer » 原生CNN = 原生RNN
    • Transformer综合能力要明显强于RNN和CNN(你要知道,技术发展到现在阶段,BLEU绝对值提升1个点是很难的事情),而RNN和CNN看上去表现基本相当,貌似CNN表现略好一些。
  • (4)并行计算能力及运算效率:Transformer > 原生CNN > 原生RNN
    • Transformer Base最快,CNN次之,再次Transformer Big,最慢的是RNN。RNN比前两者慢了3倍到几十倍之间。

一文看懂自然语言理解-NLU(基本概念+实际应用+3种实现方式)

NLP基础任务

追求创建一个能够以人类方式与人类互动的聊天机器人的目标 - 并最终通过图灵测试,企业和学术界正在研发更多的NLP和NLU技术。他们想到产品实现的目标应该轻松,无监督学习,并能够以适当的方式直接与人们互动。

为实现这一目标,该研究分三个层次进行:

  • 语法:理解文本的语法
  • 语义:理解文本的字面意义
  • 语用:理解文本试图表达的意思

不幸的是,理解和处理自然语言并不是提供足够大的词汇量和训练机器那么简单。 如果要取得成功,NLP必须融合来自各个领域的技术:语言,语言学,认知科学,数据科学,计算机科学等。 只有结合所有可能的观点,我们才能揭开人类语言的神秘面纱

NLP 有2个核心的任务:NLUNLG

  • 自然语言理解 – NLU/NLI
    • 希望机器像人一样,具备正常人的语言理解能力,由于自然语言在理解上有很多难点(下面详细说明),所以 NLU 是至今还远不如人类的表现。
  • 自然语言生成 – NLG
    • NLG 是为了跨越人类和机器之间的沟通鸿沟,将非语言格式的数据转换成人类可以理解的语言格式,如文章、报告等。

NLG 的6个步骤:

  • 内容确定 – Content Determination
  • 文本结构 – Text Structuring
  • 句子聚合 – Sentence Aggregation
  • 语法化 – Lexicalisation
  • 参考表达式生成 – Referring Expression Generation, REG
  • 语言实现 – Linguistic Realisation

一文看懂自然语言生成 - NLG(6个实现步骤+3个典型应用)

英文NLP过程:文章

  1. 分词 – Tokenization
  2. 词干提取 – Stemming
  3. 词形还原 – Lemmatization
  4. 词性标注 – Parts of Speech
  5. 命名实体识别 – NER
  6. 分块 – Chunking 中文NLP过程:
  7. 中文分词 – Chinese Word Segmentation
  8. 词性标注 – Parts of Speech
  9. 命名实体识别 – NER
  10. 去除停用词

【2020-11-08】邱锡鹏自然语言处理中的预训练模型

语言表示学习

  • 短语
    • 组合语义模型
  • 句子
    • 连续词袋模型
    • 序列模型
    • 递归组合模型
    • 卷积模型
  • 篇章
    • 层次模型

自然语言处理任务类型划分为:

  • 序列到类别
    • 文本分类
    • 情感分析
  • 同步的序列到序列
    • 中文分词
    • 词性标注
    • 语义角色标注
  • 异步的序列到序列
    • 机器翻译
    • 自动摘要
    • 对话系统
  • 类别(对象)到序列
    • 文本生成
    • 图像描述生成

常见任务

  • 词法分析(Lexical Analysis):对自然语言进行词汇层面的分析,是NLP基础性工作
    • 分词(Word Segmentation/Tokenization):对没有明显边界的文本进行切分,得到词序列
    • 新词发现(New Words Identification):找出文本中具有新形势、新意义或是新用法的词
    • 形态分析(Morphological Analysis):分析单词的形态组成,包括词干(Sterms)、词根(Roots)、词缀(Prefixes and Suffixes)等
    • 词性标注(Part-of-speech Tagging):确定文本中每个词的词性。词性包括动词(Verb)、名词(Noun)、代词(pronoun)等
    • 拼写校正(Spelling Correction):找出拼写错误的词并进行纠正
  • 句子分析(Sentence Analysis):对自然语言进行句子层面的分析,包括句法分析和其他句子级别的分析任务
    • 组块分析(Chunking):标出句子中的短语块,例如名词短语(NP),动词短语(VP)等
    • 超级标签标注(Super Tagging):给每个句子中的每个词标注上超级标签,超级标签是句法树中与该词相关的树形结构
    • 成分句法分析(Constituency Parsing):分析句子的成分,给出一棵树由终结符和非终结符构成的句法树
    • 依存句法分析(Dependency Parsing):分析句子中词与词之间的依存关系,给一棵由词语依存关系构成的依存句法树
    • 语言模型(Language Modeling):对给定的一个句子进行打分,该分数代表句子合理性(流畅度)的程度
    • 语种识别(Language Identification):给定一段文本,确定该文本属于哪个语种
    • 句子边界检测(Sentence Boundary Detection):给没有明显句子边界的文本加边界
  • 语义分析(Semantic Analysis):对给定文本进行分析和理解,形成能勾够表达语义的形式化表示或分布式表示
    • 词义消歧(Word Sense Disambiguation):对有歧义的词,确定其准确的词义
    • 语义角色标注(Semantic Role Labeling):标注句子中的语义角色类标,语义角色,语义角色包括施事、受事、影响等
    • 抽象语义表示分析(Abstract Meaning Representation Parsing):AMR是一种抽象语义表示形式,AMR parser把句子解析成AMR结构
    • 一阶谓词逻辑演算(First Order Predicate Calculus):使用一阶谓词逻辑系统表达语义
    • 框架语义分析(Frame Semantic Parsing):根据框架语义学的观点,对句子进行语义分析
    • 词汇/句子/段落的向量化表示(Word/Sentence/Paragraph Vector):研究词汇、句子、段落的向量化方法,向量的性质和应用
  • 信息抽取(Information Extraction):从无结构文本中抽取结构化的信息
    • 命名实体识别(Named Entity Recognition):从文本中识别出命名实体,实体一般包括人名、地名、机构名、时间、日期、货币、百分比等
    • 实体消歧(Entity Disambiguation):确定实体指代的现实世界中的对象
    • 术语抽取(Terminology/Giossary Extraction):从文本中确定术语
    • 共指消解(Coreference Resolution):确定不同实体的等价描述,包括代词消解和名词消解
    • 关系抽取(Relationship Extraction):确定文本中两个实体之间的关系类型
    • 事件抽取(Event Extraction):从无结构的文本中抽取结构化事件
    • 情感分析(Sentiment Analysis):对文本的主观性情绪进行提取
    • 意图识别(Intent Detection):对话系统中的一个重要模块,对用户给定的对话内容进行分析,识别用户意图
    • 槽位填充(Slot Filling):对话系统中的一个重要模块,从对话内容中分析出于用户意图相关的有效信息
  • 顶层任务(High-level Tasks):直接面向普通用户,提供自然语言处理产品服务的系统级任务,会用到多个层面的自然语言处理技术
    • 机器翻译(Machine Translation):通过计算机自动化的把一种语言翻译成另外一种语言
    • 文本摘要(Text summarization/Simplication):对较长文本进行内容梗概的提取
    • 问答系统(Question-Answering Systerm):针对用户提出的问题,系统给出相应的答案
    • 对话系统(Dialogue Systerm):能够与用户进行聊天对话,从对话中捕获用户的意图,并分析执行
    • 阅读理解(Reading Comprehension):机器阅读完一篇文章后,给定一些文章相关问题,机器能够回答
    • 自动文章分级(Automatic Essay Grading):给定一篇文章,对文章的质量进行打分或分级

参考:

上手案例

工具汇总

  • 【2020-8-27】NLP模型可视化工具LIT,为什么模型做出这样的预测?什么时候性能不佳?在输入变化可控的情况下会发生什么?LIT 将局部解释、聚合分析和反事实生成集成到一个流线型的、基于浏览器的界面中,以实现快速探索和错误分析。
  • 【2021-7-26】5个流行的自然语言处理库及入门用法
    • Hugging Face Datasets: Hugging Face 的 Datasets 库本质上是一个对公开可用的 NLP 数据集的打包集合,带有一组通用的 API 和数据格式,以及一些辅助功能。Datasets 提供了两大特性:用于许多公共数据集的单行数据加载器,以及高效的数据预处理。安装:pip install datasets
    • TextHero:在其 GitHub 存储库中的介绍很简单:文本预处理、表示和可视化,助你从零迈向大师。安装:pip install texthero
    • spaCy: 专门设计的,其宗旨是成为一个用于实现生产就绪系统的有用库。
    • Hugging Face Transformers:Hugging Face 的 Transformers 库已成为 NLP 实践不可或缺的一部分,Transformers 提供了数千个预训练模型,可以对 100 多种语言的文本执行分类、信息提取、问答、摘要、翻译、文本生成等任务。它的目标是让所有人都更容易使用尖端的 NLP 技术。Transformers由两个最流行的深度学习库 PyTorch 和 TensorFlow 提供支持,它们之间无缝集成,允许你使用一个模型来训练你的模型,然后加载它来推理另一个。
# pip install texthero
def text_texthero():
	import texthero as hero
	import pandas as pd
	df = pd.read_csv("https://github.com/jbesomi/texthero/raw/master/dataset/bbcsport.csv")
	df['pca'] = (
		df['text']
			.pipe(hero.clean)
			.pipe(hero.tfidf)
			.pipe(hero.pca)
		)
	hero.scatterplot(df, 'pca', color='topic', title="PCA BBC Sport news")
# pip install spacy
# python -m spacy download en # 加载语言模型
import spacy
from spacy.lang.en.stop_words import STOP_WORDS
nlp = spacy.load('en')
doc = nlp(sample)

print("Tokens:\n=======)
for token in doc:
    print(token)

print("Stop words:\n===========")
for word in doc:
    if word.is_stop == True:
        print(word)

print("POS tagging:\n============")
for token in doc:
    print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
          token.shape_, token.is_alpha, token.is_stop)

print("Named entities:\n===============")
for ent in doc.ents:
    print(ent.text, ent.start_char, ent.end_char, ent.label_)

# pip install transformers
from transformers import pipeline
# Allocate a pipeline for sentiment-analysis
classifier = pipeline('sentiment-analysis')
# Classify text
print(classifier('I am a fan of KDnuggets, its useful content, and its helpful editors!'))
# [{'label': 'POSITIVE', 'score': 0.9954679012298584}]
# Allocate a pipeline for question-answering
question_answerer = pipeline('question-answering')
# Ask a question
answer = question_answerer({
	'question': 'Where is KDnuggets headquartered?',
	'context': 'KDnuggets was founded in February of 1997 by Gregory Piatetsky in Brookline, Massachusetts.'
})
# Print the answer
print(answer)
# {'score': 0.9153624176979065, 'start': 66, 'end': 90, 'answer': 'Brookline, Massachusetts'}

算法理论

词库构建

详见站内分词专题

分类

根据NLP的终极目标,大致可以分为自然语言理解(NLU)和自然语言生成(NLG)两种。

  • NLU侧重于如何理解文本,包括文本分类、命名实体识别、指代消歧、句法分析、机器阅读理解等。
  • NLG则侧重于理解文本后如何生成自然文本,包括自动摘要、机器翻译、问答系统、对话机器人等。 两者间不存在有明显的界限,如机器阅读理解实际属于问答系统的一个子领域。

自然语言理解基本技术分为:词法分析、句法分析、语义分析三类。

词法分析

词法分析包括分词和词性标注。

分词 word segmentation

  • 含义:中文不同于英文,其没有自然分隔符(明显的空格标记),因此汉语自然语言处理的首要工作就是将输入的字串切分为单独的词语。

分词方法:

  • A、基于词表匹配的方法:会逐字对字符串进行扫描,发现字符串的子串和词表中的词相同就算匹配。
    • 常见方法:有正向最大匹配法、逆向最大匹配法、双向扫描法和逐词遍历法。
    • 常见的基于词表的分词工具:IKAnalyzer、庖丁解牛等。
  • B、基于统计模型的方法:根据人工标注的词性和统计特征对中文进行建模,通过模型计算各种分词出现的概率,将概率最大的分词结果作为最终结果。
    • 常见算法:HMM、CRF
    • 常见的基于统计模型的分词工具:ICTCLAS、Stanford word segmenter等。深度学习兴起后,长短期记忆网络LSTM结合CRF的方法得到了快速发展。

词性标注

含义:词性是词语最基础的语法属性之一,因此词性标注Part-Of-Speech Tagging,POS Tagging是词法分析的一部分。

目的:为句子中的每个词赋予一个特定的类别,即为分词结果中的每个单词标注词性。

  • 最重要的词性为名词、动词、形容词和副词。
  • 模型:最初隐马尔可夫、之后最大熵模型、支持向量机模型
  • 两种方法:基于规则的方法、基于统计模型的方法
    • 基于规则的词性标注:兼类词搭配关系和上下文语境建造词类消歧规则;
    • 基于统计模型的词性标注:通过模型计算各类词性出现的概率,将概率最大的词性作为最终结果。
  • 常见方法:结构感知器模型和条件随机场模型。随着深度学习技术的发展,也提出了基于深层神经网络的词性标注方法。
  • 工具:standford log-linear part-of-speech tagger、哈工大的LTP工具等。

句法分析

含义:句法分析syntactic parsing的主要任务是对输入的文本句子(字符串)进行分析以得到句子句法结构syntactic structure。

  • 原因:一方面是nlu任务自身的需求,另一方面可以为其他nlu任务提供支持。

分类:根据句法结构的不同表示形式,任务分为以下3类:

  • 依存句法分析dependency syntactic parsing,主要任务是识别句子中词汇之间的相互依存关系。
  • 短语结构句法分析phrase-structure syntactic parsing,也称作为分句法分析constituent syntactic parsing,主要任务是识别句子中短语结构和短语之间的层次句法关系。
  • 深层文法句法分析,主要任务是利用深层文法,对句子进行深层的句法及语义分析,这些深层文法包括词汇化树邻接文法、词汇功能文法、组合范畴文法等。

语义分析

语义,指的是自然语言所包含的意义,在计算机科学领域,可以将语义理解为数据对应的现实世界中的事物所代表概念的含义。

语义分析semantic analysis,指运用各种机器学习方法,让机器学习与理解一段文本所表示的语义内容。任何对语言的理解都可以归为语义分析的范畴,涉及语言学、计算语言学、人工智能、机器学习,甚至认知语言。

语义分析的最终目的是理解句子表达的真实含义。

  • 语义分析在机器翻译任务中有重要应用。
  • 基于语义的搜索一直是搜索追求的目标。
  • 语义分析是实现大数据的理解与价值发现的有效手段。

机器翻译

机器翻译介绍

机器翻译工具

插件

Chrome插件

本地翻译: LibreTranslate

【2021-1-22】【LibreTranslate:可完全本地化部署的开源机器翻译API服务,基于 Argos TranslateLibreTranslate

  • Free and Open Source Machine Translation API. 100% self-hosted, no limits, no ties to proprietary services. Built on top of Argos Translate.’ by UAV4GEO
  • 在线体验Demo

实测:windows下安装失败,错误信息

ERROR: Could not find a version that satisfies the requirement ctranslate2 (from argostranslate==1.0) (from versions: none)ERROR: No matching distribution found for ctranslate2 (from argostranslate==1.0)

本地翻译: Offine-Text-Translate

Offine-Text-Translate

  • 支持多语言的本地离线文字翻译API工具,基于开源项目 LibreTranslate 封装而成,提供方便的本地机器部署翻译API服务,无需Docker,同时提供了Windows预编译exe包,简化了部署过程。参考文献

分词

分词算法深度综述

NLP的底层任务由易到难大致可以分为词法分析、句法分析和语义分析。分词是词法分析(还包括词性标注和命名实体识别)中最基本的任务,可以说既简单又复杂。说简单是因为分词的算法研究已经很成熟了,大部分的准确率都可以达到95%以上,说复杂是因为剩下的5%很难有突破,主要因为三点:

  1. 粒度,不同应用对粒度的要求不一样,比如“苹果手机”可以是一个词也可以是两个词
  2. 歧义,比如“下雨天留人天留我不留”
  3. 未登录词,比如“skrrr”、“打call”等新兴词语

然而,在真实的应用中往往会因为以上的难点造成分词效果欠佳,进而影响之后的任务。对于追求算法表现的童鞋来说,不仅要会调分词包,也要对这些基础技术有一定的了解,在做真正的工业级应用时有能力对分词器进行调整。这篇文章不是着重介绍某个SOTA成果,而是对常用的分词算法(不仅是机器学习或神经网络,还包括动态规划等)以及其核心思想进行介绍。

总结

分词作为NLP底层任务之一,既简单又重要,很多时候上层算法的错误都是由分词结果导致的。因此,对于底层实现的算法工程师,不仅需要深入理解分词算法,更需要懂得如何高效地实现。而对于上层应用的算法工程师,在实际分词时,需要根据业务场景有选择地应用上述算法,比如在搜索引擎对大规模网页进行内容解析时,对分词对速度要求大于精度,而在智能问答中由于句子较短,对分词的精度要求大于速度。

分词算法

分词算法根据其核心思想主要分为两种

  • 第一种是基于字典的分词,先把句子按照字典切分成词,再寻找词的最佳组合方式;
  • 第二种是基于的分词,即由字构词,先把句子分成一个个字,再将字组合成词,寻找最优的切分策略,同时也可以转化成序列标注问题。 归根结底,上述两种方法都可以归结为在图或者概率图上寻找最短路径的问题。接下来以“他说的确实在理”这句话为例,讲解各个不同的分词算法核心思想。

基于词典的分词

最大匹配分词算法

最大匹配分词寻找最优组合的方式是将匹配到的最长词组合在一起。主要的思路是先将词典构造成一棵Trie树,也称为字典树,如下图:

Trie树由词的公共前缀构成节点,降低了存储空间的同时提升查找效率。最大匹配分词将句子与Trie树进行匹配,在匹配到根结点时由下一个字重新开始进行查找。比如正向(从左至右)匹配“他说的确实在理”,得出的结果为“他/说/的确/实在/理”。如果进行反向最大匹配,则为“他/说/的/确实/在理”。

可见,词典分词虽然可以在O(n)时间对句子进行分词,但是效果很差,在实际情况中基本不使用此种方法。

最短路径分词算法

最短路径分词算法首先将一句话中的所有词匹配出来,构成词图(有向无环图DAG),之后寻找从起始点到终点的最短路径作为最佳组合方式,引用《统计自然语言处理》中的图:

我们认为图中每个词的权重都是相等的,因此每条边的权重都为1。

在求解DAG图的最短路径问题时,总是要利用到一种性质:即两点之间的最短路径也包含了路径上其他顶点间的最短路径。比如S->A->B->E为S到E到最短路径,那S->A->B一定是S到B到最短路径,否则会存在一点C使得d(S->C->B)<d(S->A->B),那S到E的最短路径也会变为S->C->B->E,这就与假设矛盾了。利用上述的最优子结构性质,可以利用贪心算法或动态规划两种求解算法:

最短路径分词算法

基于Dijkstra算法求解最短路径。该算法适用于所有带权有向图,求解源节点到其他所有节点的最短路径,并可以求得全局最优解。Dijkstra本质为贪心算法,在每一步走到当前路径最短的节点,递推地更新原节点到其他节点的距离。针对当前问题,Dijkstra算法的计算结果为:“他/说/的/确实/在理“。可见最短路径分词算法可以满足部分分词要求。但当存在多条距离相同的最短路径时,Dijkstra只保存一条,对其他路径不公平,也缺乏理论依据。

N-最短路径分词算法

N-最短路径分词是对Dijkstra算法的扩展,在每一步保存最短的N条路径,并记录这些路径上当前节点的前驱,在最后求得最优解时回溯得到最短路径。该方法的准确率优于Dijkstra算法,但在时间和空间复杂度上都更大。

基于n-gram model的分词算法

在前文的词图中,边的权重都为1。而现实中却不一样,常用词的出现频率/概率肯定比罕见词要大。因此可以将求解词图最短路径的问题转化为求解最大概率路径的问题,即分词结果为“最有可能的词的组合“。计算词出现的概率,仅有词典是不够的,还需要有充足的语料。因此分词任务已经从单纯的“算法”上升到了“建模”,即利用统计学方法结合大数据挖掘,对“语言”进行建模。

语言模型的目的是构建一句话出现的概率p(s),根据条件概率公式我们知道:

  • [公式]

而要真正计算“他说的确实在理”出现的概率,就必须计算出上述所有形如 [公式] n=1,…,6 的概率,计算量太过庞大,因此我们近似地认为:

  • [公式]

其中 [公式][公式] 为字或单词。我们将上述模型成为二元语言模型(2-gram model)。类似的,如果只对词频进行统计,则为一元语言模型。由于计算量的限制,在实际应用中n一般取3。

将基于词的语言模型所统计出的概率分布应用到词图中,可以得到词的概率图

对该词图用2.1.2中的算法求解最大概率的路径,即可得到分词结果。

基于字的分词

与基于词典的分词不同的是,基于字的分词事先不对句子进行词的匹配,而是将分词看成序列标注问题,把一个字标记成B(Begin), I(Inside), O(Outside), E(End), S(Single)。因此也可以看成是每个字的分类问题,输入为每个字及其前后字所构成的特征,输出为分类标记。对于分类问题,可以用统计机器学习或神经网络的方法求解。

统计机器学习方法通过一系列算法对问题进行抽象,进而得到模型,再用得到的模型去解决相似的问题。也可以将模型看成一个函数,输入X,得到f(X)=Y。另外,机器学习中一般将模型分为两类:生成式模型和判别式模型,两者的本质区别在于X和Y的生成关系。生成式模型以“输出Y按照一定的规律生成输入X”为假设对P(X,Y)联合概率进行建模;判别式模型认为Y由X决定,直接对后验概率P(Y|X)进行建模。两者各有利弊,生成模型对变量的关系描述更加清晰,而判别式模型容易建立和学习。下面对几种序列标注方法做简要介绍。

生成式模型分词算法

生成式模型主要有n-gram模型、HMM隐马尔可夫模型、朴素贝叶斯分类等。在分词中应用比较多的是n-gram模型和HMM模型。如果将2.1.3中的节点由词改成字,则可基于字的n-gram模型进行分词,不过这种方法的效果没有基于词的效果要好。

HMM模型认为在解决序列标注问题时存在两种序列,一种是观测序列,即人们显性观察到的句子,而序列标签是隐状态序列,即观测序列为X,隐状态序列是Y,因果关系为Y->X。因此要得到标注结果Y,必须对X的概率、Y的概率、P(X|Y)进行计算,即建立P(X,Y)的概率分布模型。例句的隐马尔科夫序列如下图:

HMM模型是常用的分词模型,基于Python的jieba分词器和基于Java的HanLP分词器都使用了HMM。要注意的是,该模型创建的概率图与上文中的DAG图并不同,因为节点具有观测概率,所以不能再用上文中的算法求解,而应该使用Viterbi算法求解最大概率的路径。

判别式模型分词算法

判别式模型主要有感知机、SVM支持向量机、CRF条件随机场、最大熵模型等。在分词中常用的有感知机模型和CRF模型:

平均感知机分词算法

感知机是一种简单的二分类线性模型,通过构造超平面,将特征空间(输入空间)中的样本分为正负两类。通过组合,感知机也可以处理多分类问题。但由于每次迭代都会更新模型的所有权重,被误分类的样本会造成很大影响,因此采用平均的方法,在处理完一部分样本后对更新的权重进行平均。

CRF分词算法

CRF可以看作一个无向图模型,对于给定的标注序列Y和观测序列X,对条件概率P(Y|X)进行定义,而不是对联合概率建模。CRF可以说是目前最常用的分词、词性标注和实体识别算法,它对未登陆词有很好的识别能力,但开销较大。

神经网络分词算法

在NLP中,最常用的神经网络为循环神经网络(RNN,Recurrent Neural Network),它在处理变长输入和序列输入问题中有着巨大的优势。LSTM为RNN变种的一种,在一定程度上解决了RNN在训练过程中梯度消失和梯度爆炸的问题。双向(Bidirectional)循环神经网络分别从句子的开头和结尾开始对输入进行处理,将上下文信息进行编码,提升预测效果。

目前对于序列标注任务,公认效果最好的模型是BiLSTM+CRF。结构如图:

利用双向循环神经网络BiLSTM,相比于上述其它模型,可以更好的编码当前字等上下文信息,并在最终增加CRF层,核心是用Viterbi算法进行解码,以得到全局最优解,避免B,S,E这种标记结果的出现。

分词算法中的数据结构

前文主要讲了分词任务中所用到的算法和模型,但在实际的工业级应用中,仅仅有算法是不够的,还需要高效的数据结构进行辅助。

词典

中文有7000多个常用字,56000多个常用词,要将这些数据加载到内存虽然容易,但进行高并发毫秒级运算是困难的,这就需要设计巧妙的数据结构和存储方式。前文提到的Trie树只可以在O(n)时间完成单模式匹配,识别出“的确”后到达Trie树对也节点,句子指针接着指向“实”,再识别“实在”,而无法识别“确实”这个词。如果要在O(n)时间完成多模式匹配,构建词图,就需要用到Aho-Corasick算法将模式串预处理为有限状态自动机,如模式串是he/she/his/hers,文本为“ushers”。构建的自动机如图:

这样,在第一次到叶节点5时,下一步的匹配可以直接从节点2开始,一次遍历就可以识别出所有的模式串。

对于数据结构的存储,一般可以用链表或者数组,两者在查找、插入和删除操作的复杂度上各有千秋。在基于Java的高性能分词器HanLP中,作者使用双数组完成了Trie树和自动机的存储。

词图

图作为一种常见的数据结构,其存储方式一般有两种:

邻接矩阵

邻接矩阵用数组下标代表节点,值代表边的权重,即d[i][j]=v代表节点i和节点j间的边权重为v。如下图:

用矩阵存储图的空间复杂度较高,在存储稀疏图时不建议使用。

邻接表

邻接表对图中的每个节点建立一个单链表,对于稀疏图可以极大地节省存储空间。第i个单链表中的节点表示依附于顶点i的边,如下图:

在实际应用中,尤其是用Viterbi算法求解最优路径时,由于是按照广度优先的策略对图进行遍历,最好是使用邻接表对图进行存储,便于访问某个节点下的所有节点。

NER 命名实体识别

详见 NER专题

同义词/近义词

相似度判断

GitHub WordSimilarity, 基于哈工大词林扩展版的单词相似度计算方法的python实现

# pip install WordSimilarity

from word_similarity import WordSimilarity2010

ws_tool = WordSimilarity2010()

b_a = "抄袭"
b_b = "克隆"
sim_b = ws_tool.similarity(b_a, b_b)
print(b_a, b_b, '相似度为', sim_b)
#抄袭 克隆 最终的相似度为 0.585642777645155

w_a = '人民'
sample_list = ["国民", "群众", "党群", "良民", "同志", "成年人", "市民", "亲属", "志愿者", "先锋" ]

for s_a in sample_list:
    sim_a = ws_tool.similarity(w_a,s_a)
    print(w_a, s_a, '相似度为', sim_a)
# 人民 国民 相似度为 1
# 人民 群众 相似度为 0.9576614882494312
# 人民 党群 相似度为 0.8978076452338418
# 人民 良民 相似度为 0.7182461161870735
# 人民 同志 相似度为 0.6630145969121822
# 人民 成年人 相似度为 0.6306922220793977
# 人民 市民 相似度为 0.5405933332109123
# 人民 亲属 相似度为 0.36039555547394153
# 人民 志愿者 相似度为 0.22524722217121346
# 人民 先锋 相似度为 0.18019777773697077
        

同义词词库

【2023-10-26】哈工大有个大词林,提供了75w同义词信息,Web查询

大词林》由 哈尔滨工业大学社会计算与信息检索研究中心秦兵教授和刘铭副教授主持研制,一个自动构建的大规模开放域中文知识库。

  • 自2014年11月推出《大词林》第一版,第一版的《大词林》包含了自动挖掘的实体和细粒度的上位概念词,类似一个大规模的汉语词典,其特点在于自动构建、自动扩充,细粒度的上下位层次关系。
  • 2019年8月推出的第二版《大词林》引入了实体的义项和关系、属性数据,将每一个实体的义项唯一对应到细粒度的上位词概念路径,让《大词林》中实体的含义更加清晰。

相比于传统的开放域实体知识库,《大词林》的特点在于:

  • 构建过程不需要领域专家的参与,而是基于多信息源自动获取实体类别并对可能的多个类别进行层次化,从而达到知识库自动构建的效果。
  • 其数据规模可以随着互联网中实体词的更新而扩大,很好地解决了以往的人工构建知识库对开放域实体的覆盖程度极为有限的问题。
  • 《大词林》是一个树状的网络,每一个实体的义项均能够唯一对应到细粒度的上位词概念路径且具有丰富的实体和关系数据,能够更加清晰明确的展示实体的含义。

《大词林》中的 75万的核心实体词,以及 这些核心实体词对应的细粒度概念词(共 1.8万概念词, 300万实体-概念元组),还有 相关的关系三元组(共 300万)。这75万核心实体列表涵盖了常见的人名、地名、物品名等术语。概念词列表则包含了细粒度的实体概念信息。借助于细粒度的上位概念层次结构和丰富的实体间关系,本次开源的数据能够为人机对话、智能推荐、等应用技术提供数据支持。

下载地址:

短语挖掘

关键词提取方案

  • 知乎话题:关键词提取都有哪些方案

  • 刘知远的博士论文:基于文档主题结构的关键词抽取方法研究
  • 关键词挖掘的方法:(2014年,作者:zibuyu9
      1. TFIDF是很强的baseline,具有较强的普适性,如果没有太多经验的话,可以实现该算法基本能应付大部分关键词抽取的场景了。
      1. 对于中文而言,中文分词和词性标注的性能对关键词抽取的效果至关重要。
      1. 较复杂的算法各自有些问题,如Topic Model,它的主要问题是抽取的关键词一般过于宽泛,不能较好反映文章主题。这在我的博士论文中有专门实验和论述;TextRank实际应用效果并不比TFIDF有明显优势,而且由于涉及网络构建和随机游走的迭代算法,效率极低。这些复杂算法集中想要解决的问题,是如何利用更丰富的文档外部和内部信息进行抽取。如果有兴趣尝试更复杂的算法,我认为我们提出的基于SMT(统计机器翻译)的模型,可以较好地兼顾效率和效果。
        • TextRank源于page-rank,page-rank是谷歌提出的对网页按照影响力进行排序的算法。同样的,text-rank认为文档或句子中相邻的词语重要性是相互影响的,所以text-rank引入了词语的顺序信息。
      1. 以上都是无监督算法,即没有事先标注好的数据集合。而如果我们有事先标注好的数据集合的话,就可以将关键词抽取问题转换为有监督的分类问题。这在我博士论文中的相关工作介绍中均有提到。
    • 从性能上来讲,利用有监督模型的效果普遍要优于无监督模型,对关键词抽取来讲亦是如此。在Web 2.0时代的社会标签推荐问题,就是典型的有监督的关键词推荐问题,也是典型的多分类、多标签的分类问题,有很多高效算法可以使用。
  • 作者:小Fan
  • 分两步走:
    • 候选词匹配:基于关键词词库的多模式匹配得到候选,这里最重要的工作是词库构建,往往会融合多种方法:垂直站点专有名词,百科词条,输入法细胞词库,广告主购买词,基于大规模语料库的自动词库挖掘(推荐韩家炜团队的 shangjingbo1226/SegPhrase ,shangjingbo1226/AutoPhrase 方法)等。这里会涉及大量的数据清洗工作,甚至还可以有一个质量分类器决定哪些词条可以进入词库。
    • 候选词相关性排序:包括无监督和有监督方法,如下:
      • 无监督方法:常见的有 TFIDF(需要统计 phrase 级别的 DF), textrank(优势不明显,计算量大,慎用),topic 相似度(参见 baidu/Familia),embedding 相似度(需要训练或计算 keyword 和 doc embedding),TWE 相似度(参见 baidu/Familia)
      • 有监督方法:常见的有基于统计机器翻译 SMT 的方法(转换成翻译问题,可以采用 IBM Model 1),基于序列标注模型的方法(转换成核心成分识别问题,类似 NER,状态只有0和1,即是否是核心成分,较适用于短文本),基于排序学习LTR的方法(转换成候选词排序问题,采用 pairwise 方法,或者深度语义匹配方法,如 DSSM),基于传统机器学习分类方法(转换成二元或多元分类问题)。有监督方法依赖一定规模的标注数据,效果通常会显著好于无监督方法。

AutoPhrase

具体工具如下:

  • TopMine:频率模式挖掘+统计分析
  • SegPhrase:SegPhrase:弱监督、高质量的 Phrase Mining
    • 论文:Mining Quality Phrases from Massive Text Corpora
    • TopMine 的方法完全是无监督的,如果有少量的 Label 数据可能会在很大程度上提高 Topic Model 的结果。
    • SegPhrase框架只需要有限的培训,但是生成的短语的质量却接近于人类的判断力。而且,该方法具有可伸缩性:随着语料库大小的增加,计算时间和所需空间都会线性增长。论文在大型文本语料库上的实验证明了该新方法的质量和效率。
    • segphrase已有GitHub开源工具
  • AutoPhrase:自动的 Phrase Mining
    • 论文:Automated Phrase Mining from Massive Text Corpora
    • AutoPhrase支持多种语言(包含简体中文和繁体中文)基本思想是通过分别在训练和解析过程中添加编码/解码层来重用英语实现。在训练阶段,在中文单词片段和英文字母之间创建一个字典,将输入数据编码为英文伪单词。在解析阶段,在识别出编码后的新文档中的优质短语之后,进行解码以恢复可读的中文。
    • AutoPhrase已有GitHub开源工具
  • 韩家炜团队开源工具
  • 【2020-7-3】数据挖掘之父韩家炜团队的自动短语挖掘论文:Automated Phrase Mining from Massive Text Corpora,提出自动挖掘短语的方法:AutoPhrase
  • 思路:使用通用知识库(KB)的来构造正样本(应该就是用完全匹配的方式),然后训练一个NER模型(非神经网络的),然后用这个NER模型的预测结果来减少负样本噪声,引入词性信息
  • 先从KB里匹配出正样本,其他的词是负样本,然后训练NER/CRF模型,再卡个阈值,筛掉分低的实体,最后出的作为抽取出的短语。

对于自动短语挖掘任务,

  • 输入:语料库(特定语言和特定领域的文本单词序列,长度任意)和知识库
  • 输出:一个按质量递减排列的短语列表

短语质量 定义为一个单词序列成为一个完整语义单元的概率,满足以下条件:

  • 流行度: 在给定的文档集合中,质量短语应该出现的频率足够高。
  • 一致性: 由于偶然因素,令牌在高质量短语中的搭配出现的概率明显高于预期。
  • 信息性: 如果一个短语表达了一个特定的主题或概念,那么这个短语就是信息性的。
  • 完备性: 长频繁短语及其子序列均满足上述3个条件。当一个短语可以在特定的文档上下文中解释为一个完整的语义单元时,它就被认为是完整的

流程图

  • AutoPhrase会根据正池和负池对短语质量进行两次评估,一次在短语分割前,一次在短语分割后。也就是说,POS-Guided短语分割需要一组初始的短语质量分数;我们预先根据原始频率估计分数;然后,一旦特征值被纠正,我们重新估计分数。

  • AutoPhrase超越了分段短语,进一步摆脱了额外的手工标注工作,提高了性能。
  • 主要使用以下两种新技术:
    • Robust Positive-Only Distant Training(鲁棒正向远程训练)
      • 即:利用已有的知识库(Wikipedia)做远程监督训练
      • 公共知识库(如维基百科)中的高质量短语,免费并且数量很多。在远程训练中,使用一般知识库中高质量短语,可以避免手工标注。
      • 具体做法是:
        • 从一般知识库中构建积极标签的样本
        • 从给定的领域语料库中构建消极标签的样本
        • 训练大量的基本分类器
        • 将这些分类器的预测聚合在一起
    • POS-Guided Phrasal Segmentation. (POS-Guided短语分割)
      • 即:利用词性信息来增加抽取的准确性
      • 语言处理器应该权衡:性能领域独立能力
        • 对于领域独立能力,如果没有语言领域知识,准确性会受限制
        • 对于准确性,依赖复杂的、训练有素的语言分析器,就会降低领域独立能力
      • 解决办法: 在文档集合的语言中加入一个预先训练的词性标记,以进一步提高性能

新词发现 (互信息)

WordsDiscovery

互信息(Pointwise Mutual Information)

  • 互信息越大,说明这两个词经常出现在一起,意味着两个词的凝固程度越大,其组成一个新词的可能性也就越大。

举例:

  • “电影院”的互信息是 p(电影院)分别除以 p(电) * p(影院) 和 p(电影) * p(院) 所得的商的较小值再取对数
  • 这样处理会有更好的效果,因为用最小值来代表这个词的互信息,更能有力的证明该词的成词性。

左右熵(Information Entropy)

  • 如果一个文本片段能够算作一个词的话,它应该能够灵活地出现在各种不同的环境中,具有非常丰富的左邻字集合和右邻字集合。

信息熵来衡量一个文本片段的左邻字集合和右邻字集合有多随机。

  • 示例:“吃葡萄不吐葡萄皮不吃葡萄倒吐葡萄皮”
  • “葡萄”一词出现了四次,其中左邻字分别为 {吃, 吐, 吃, 吐} ,右邻字分别为 {不, 皮, 倒, 皮} 。
  • 根据公式,“葡萄”一词
    • 左邻字的信息熵为 – (1/2) * log(1/2) – (1/2) * log(1/2)
    • 右邻字的信息熵则为 – (1/2) * log(1/2) – (1/4) * log(1/4) – (1/4) * log(1/4)。

Demo

from word_discovery import NewWords
discover = NewWords()
discover.parse('''中国科兴生物研发的克尔来福是一种灭活疫苗,由已杀灭的病原体制成,主要通过其中的抗原诱导细胞免疫的产生。另外几种疫苗,例如莫德纳和辉瑞的疫苗都属于核糖核酸疫苗,使用的是RNA疫苗原理,抽取病毒内部分核糖核酸编码蛋白制成疫苗。新加坡南洋理工大学感染与免疫副教授罗大海对BBC表示,“克尔来福是用比较传统的方法制成的(灭活)疫苗,灭活疫苗使用广泛而且非常成功,例如狂犬病疫苗。”理论上,科兴疫苗主要的优势在于它能够在常规冰箱温度下(2至8摄氏度)保存,这一点和牛津/阿斯利康研发的病毒载体疫苗有相同优点。莫德纳的疫苗必须存放在摄氏零下20度,而辉瑞疫苗必须存放在摄氏零下70度。这意味着科兴和牛津/阿斯利康这两种疫苗,更能有效地在发展中国家使用,因为那些地方可能没有足够的低温储存设备供疫苗保存。但是,相对于最新加入接种行列的单剂疫苗 — 美国杨森和中国康希诺 — 而言,科兴疫苗仍需注射两针。疫苗谣言的打破:改变DNA、植入微芯片等疫苗阴谋论。新冠疫苗接种在即,你该了解的四大问题。效果如何?科兴疫苗三期临床试验在4个国家展开,各国试验结果相差较大,有效性从50% - 90%不等。从2021年1月以来,至少有7个国家先后批准科兴疫苗紧急使用。不过到目前为止它的三期临床整体有效性数据仍未公布。截止今年3月8日,香港有10多万人接种第一剂科兴疫苗,虽然近期出现三宗接种科兴疫苗后死亡的案例,但港府新冠疫苗临床事件评估专家委员会对三宗案例的调查结果称科兴疫苗与死亡并无直接关系。今年1月13日,科兴董事长在谷物元联防联控机制发布会上给出一组数据:土耳其中期分析结果显示该疫苗保护率91.25%;印尼三期临床试验保护率65.3%;巴西三期临床试验从2020年10月开始,试验结果显示重症保护率达100%,对高危人群总体保护率达50.3%。''')
for k, v in discover.candidates():
	print(k, v) 

输出:

主要 {'pmi': 10.448116305409464, 'freq': 2, 'entropy': 1.0}
辉瑞 {'pmi': 10.448116305409464, 'freq': 2, 'entropy': 1.0}
NA {'pmi': 10.448116305409464, 'freq': 2, 'entropy': 1.0}
数据 {'pmi': 10.448116305409464, 'freq': 2, 'entropy': 1.0}
死亡 {'pmi': 10.448116305409464, 'freq': 2, 'entropy': 1.0}
莫德纳 {'pmi': 10.448116305409464, 'freq': 2, 'entropy': 1.0}
病毒 {'pmi': 9.448116305409464, 'freq': 2, 'entropy': 1.0}
新加 {'pmi': 9.448116305409464, 'freq': 2, 'entropy': 1.0}
今年 {'pmi': 9.448116305409464, 'freq': 2, 'entropy': 1.0}
案例 {'pmi': 9.448116305409464, 'freq': 2, 'entropy': 1.0}
个国家 {'pmi': 9.448116305409464, 'freq': 2, 'entropy': 1.0}
其中 {'pmi': 9.1261882105221, 'freq': 2, 'entropy': 1.0}
使用 {'pmi': 9.1261882105221, 'freq': 4, 'entropy': 1.5}
试验 {'pmi': 9.1261882105221, 'freq': 5, 'entropy': 1.3709505944546687}
结果 {'pmi': 9.1261882105221, 'freq': 4, 'entropy': 1.5}
制成 {'pmi': 9.03307880613062, 'freq': 3, 'entropy': 1.584962500721156}
例如 {'pmi': 8.863153804688308, 'freq': 2, 'entropy': 1.0}
三宗 {'pmi': 8.863153804688308, 'freq': 2, 'entropy': 1.0}
保护率 {'pmi': 8.863153804688308, 'freq': 4, 'entropy': 1.5}
年1月 {'pmi': 8.863153804688308, 'freq': 2, 'entropy': 1.0}
有效性 {'pmi': 8.64076138335186, 'freq': 2, 'entropy': 1.0}
接种 {'pmi': 8.318833288464496, 'freq': 4, 'entropy': 2.0}
科兴 {'pmi': 8.1261882105221, 'freq': 10, 'entropy': 1.3567796494470397}
下2 {'pmi': 8.055798882630704, 'freq': 2, 'entropy': 1.0}

Reference

句法分析

李宏毅 人类语言处理 独家笔记 成分句法分析

NLP 任务中,句法分析有两种

  • 一种是成分句法分析: 找到一个句子的组成成分
  • 另一种是依存句法分析。 句法分析不适用于之前的 NLP 任务分类体系。它的输出形式相对来说会比较不一样。

成分句法分析

成分句法分析要做的是给定一个句子,句子中每个词汇都是成分。

  • 每一个成分都会有一个标签,比如 deep learning 的标签是 NP,very powerful 的标签是 ADJP。
    • 示例
    • 标签集合
  • 所有词性标注的词项标签也都是可能的标签。
  • 相邻的成分可以组合成一个更大的单位。比如 deep 和 learning 可以组合起来成为一个名词短语。最后这个动词短语和名词短语组合起来变成整个句子。

成分句法分析通用的解决方案

  • 一个是 char-based 方案。训练一个分类器,输入是一串 tokens,它决定这个 span 是不是成分。如果确定它是成分,接下来我们要用另一个分类器,对该成分确定它的标签。
    • char-based过程
  • 另一个方法叫作基于转移的方法。它的精神是把产生的句子加入到一个 Buffer 中,加上一连串的操作,就可以做到成分句法解析。
    • transition-based
  • tree2seq:把树状的结构表示为一个序列,比如用深度优先遍历方法,由上而下,由左到右把每个节点按遍历顺序放在序列中。

资料:成分分析方法综述

依存句法分析

文本分类

见本博客的文本分类专题

文本生成

综述

  • 文本生成被称为NLG,目标是根据输入数据生成自然语言的文本。
    • NLP领域使用更多的一般是NLU(Nature Language Understanding 自然语言理解)类任务,如文本分类、命名实体识别等,NLU的目标则是将自然语言文本转化成结构化数据。
    • NLU和NLG两者表向上是一对相反的过程,但其实是紧密相连的,甚至目前很多NLU的任务都受到了生成式模型中表示方法的启发,更多只在最终任务上有所区别
  • 文本生成,广义上只要输出是自然语言文本的各类任务都属于这个范畴
    • 端到端文本生成应用领域

技术方案

  • 文本生成包含文本表示和文本生成两个关键的部分,既可以独立建模,也可以通过框架完成端到端的训练

文本生成

  • (1) seq2seq
    • 2014年提出的Seq2Seq Model,是解决这类问题一个非常通用的思路,本质是将输入句子或其中的词Token做Embedding后,输入循环神经网络中作为源句的表示,这一部分称为Encoder;另一部分生成端在每一个位置同样通过循环神经网络,循环输出对应的Token,这一部分称为Decoder。通过两个循环神经网络连接Encoder和Decoder,可以将两个平行表示连接起来。
  • (2) attention
    • 本质思想是获取两端的某种权重关系,即在Decoder端生成的词和Encoder端的某些信息更相关。它也同样可以处理多模态的问题,比如Image2Text任务,通过CNN等将图片做一个关键特征的向量表示,将这个表示输出到类似的Decoder中去解码输出文本,视频语音等也使用同样的方式
  • Encoder-Decoder是一个非常通用的框架,它同样深入应用到了文本生成的三种主流方法,分别是规划式、抽取式和生成式,下面看下这几类方法各自的优劣势:
    • 规划式:根据结构化的信息,通过语法规则、树形规则等方式规划生成进文本中,可以抽象为三个阶段。宏观规划解决“说什么内容”,微观规划解决“怎么说”,包括语法句子粒度的规划,以及最后的表层优化对结果进行微调。
    • 抽取式:顾名思义,在原文信息中抽取一部分作为输出。可以通过编码端的表征在解码端转化为多种不同的分类任务,来实现端到端的优化。
      • 优势: 控制力极强、准确率较高,特别适合新闻播报等模版化场景。控制力极强,对源内容相关性好,改变用户行文较少,也不容易造成体验问题,可以直接在句子级别做端到端优化
      • 劣势是很难做到端到端的优化,损失信息上限也不高。
        • 在优化评估上,首先标题创意衡量的主观性很强,线上Feeds的标注数据也易受到其他因素的影响,比如推荐排序本身;其次,训练预测数据量差异造成OOV问题非常突出,分类任务叠加噪音效果提升非常困难。对此,我们重点在语义+词级的方向上来对点击/转化率做建模,同时辅以线上E&E选优的机制来持续获取标注对,并提升在线自动纠错的能力。
        • 在受限上,抽取式虽然能直接在Seq级别对业务目标做优化,但有时候也须兼顾阅读体验,否则会形成一些“标题党”,亦或造成与原文相关性差的问题。对此,我们抽象了预处理和质量模型,来通用化处理文本创意内容的质控,独立了一个召回模块负责体验保障。并在模型结构上来对原文做独立表示,后又引入了Topic Feature Context来做针对性控制。
    • 生成式:通过编码端的表征,在解码端完成序列生成的任务,可以实现完全的端到端优化,可以完成多模态的任务。其在泛化能力上具有压倒性优势,但劣势是控制难度极大,建模复杂度也很高。
  • 目前的主流的评估方法主要基于数据和人工评测。基于数据可以从不同角度衡量和训练目标文本的相近程度,如基于N-Gram匹配的BLUE和ROUGE等,基于字符编辑距离(Edit Distance)等,以及基于内容Coverage率的Jarcard距离等。基于数据的评测,在机器翻译等有明确标注的场景下具有很大的意义,这也是机器翻译领域最先有所突破的重要原因。但对于我们创意优化的场景来说,意义并不大,我们更重要的是优化业务目标,多以线上的实际效果为导向,并辅以人工评测。
  • 另外,值得一提的是,近两年也逐渐涌现了很多利用GAN(Generative Adversarial Networks,生成对抗网络)的相关方法,来解决文本生成泛化性多样性的问题。有不少思路非常有趣,也值得尝试,只是GAN对于NLP的文本生成这类离散输出任务在效果评测指标层面,与传统的Seq2Seq模型还存在一定的差距,可视为一类具有潜力的技术方向。

文本表示

  • 整个2018年有两方面非常重要的工作进展:
    • Contextual Embedding:该方向包括一系列工作,如最佳论文Elmo(Embeddings from Language Models),OpenAI的GPT(Generative Pre-Training),以及谷歌大力出奇迹的BERT(Bidirectional Encoder Representations from Transformers)。解决的核心问题,是如何利用大量的没标注的文本数据学到一个预训练的模型,并通过通过这个模型辅助在不同的有标注任务上更好地完成目标。传统NLP任务深度模型,往往并不能通过持续增加深度来获取效果的提升,但是在表示层面增加深度,却往往可以对句子做更好的表征,它的核心思想是利用Embedding来表征上下文的的信息。但是这个想法可以通过很多种方式来实现,比如ELMo,通过双向的LSTM拼接后,可以同时得到含上下文信息的Embedding。而Transformer则在Encoder和Decoder两端,都将Attention机制都应用到了极致,通过序列间全位置的直连,可以高效叠加多层(12层),来完成句子的表征。这类方法可以将不同的终端任务做一个统一的表示,大大简化了建模抽象的复杂度。我们的表示也经历了从RNN到拥抱Attention的过程。

图5 GPT ELMo BERT模型结构

  • Tree-Based Embedding:另外一个流派则是通过树形结构进行建模,包括很多方式如传统的语法树,在语法结构上做Tree Base的RNN,用根结点的Embedding即可作为上下文的表征。Tree本身可以通过构造的方式,也可以通过学习的方式(比如强化学习)来进行构建。最终Task效果,既和树的结构(包括深度)有关,也受“表示”学习的能力影响,调优难度比较大。在我们的场景中,人工评测效果并不是很好,仍有很大继续探索的空间。

信息流中的应用

  • 【2020-5-26】大众点评信息流基于文本生成的创意优化实践
  • 核心目标与推荐问题相似,提升包括点击率、转化率在内的通用指标,同时需要兼顾考量产品的阅读体验包括内容的导向性等
  • 信息流中落地重点包括三个方向:
    • 文本创意:在文本方面,既包括了面向内容的摘要标题、排版改写等,也包括面向商户的推荐文案及内容化聚合页。它们都广泛地应用了文本表示和文本生成等技术,也是本文的主要方向。
    • 图像创意:图像方面涉及到首图或首帧的优选、图像的动态裁剪,以及图像的二次生成等。
    • 其他创意:包括多类展示理由(如社交关系等)、元素创意在内的额外补充信息。
  • 文本创意优化,在业务和技术上分别面临着不同的挑战。
    • 首先业务侧,启动创意优化需要两个基础前提:
      • 第一,衔接好创意优化与业务目标,因为并不是所有的创意都能优化,也不是所有创意优化都能带来预期的业务价值,方向不对则易蹚坑。
      • 第二,创意优化转化为最优化问题,有一定的Gap。其不同于很多分类排序问题,本身相对主观,所谓“一千个人眼中有一千个哈姆雷特”,创意优化能不能达到预期的业务目标,这个转化非常关键。
    • 其次,在技术层面,业界不同的应用都面临不一样的挑战,并且尝试和实践对应的解决方案。对文本创意生成来说,我们面临的最大的挑战包括以下三点:
      • 带受限的生成 生成一段流畅的文本并非难事,关键在于根据不同的场景和目标能控制它说什么、怎么说。这是目前挑战相对较大的一类问题,在我们的应用场景中都面临这个挑战。
      • 业务导向 生成能够提升业务指标、贴合业务目标的内容。为此,对内容源、内容表示与建模上提出了更高的要求。
      • 高效稳定 这里有两层含义,第一层是高效,即模型训练预测的效果和效率;第二层是稳定,线上系统应用,需要具备很高的准确率和一套完善的质量提升方案。

指针网络

  • 【2021-3-24】Pointer-Generator模型,解决了摘要中存在事实性错误的问题。然后作者又向前走了一步,就是加入了Coverage机制来解决重复问题
  • Pointer Networks天生具备输出元素来自输入元素这样的特点,于是它非常适合用来实现“复制”这个功能。Pointer Networks其实特别适合用于解决OOV(out of vocabulary)问题
  • 演进路线

多轮对话改写

【2021-3-31】指代消解

  • 代词是用来代替重复出现的名词
  • 例句:
    1. Ravi is a boy. He often donates money to the poor.
      • 先出现主语,后出现代词,所以流动的方向从左到右,这类句子叫回指(Anaphora)
    2. He was already on his way to airport.Realized Ravi.
      • 这种句子表达的方式的逆序的,这类句子叫预指(Cataphora)
  • 【2020-6-19】浅谈多轮对话改写
    • 2000条日常对话数据进行了简单地统计,发现其中33.5%存在指代,52.7%存在省略的情况
    • 人脑具有记忆的能力,能够很好地重建对话历史的重要信息,自动补全或者替换对方当前轮的回复,来理解回复的意思。同样,为了让对话系统具备记忆的能力,通常会通过对话状态跟踪(DST),来存储对话历史中的一些重要信息。
    • DST的主要问题有:
      • 存储的信息量有限,对于长对话的历史信息无法感知;
      • 存储信息不会太丰富,否则会导致冗余信息太多;
      • 存储的信息不太便于对话系统中其他模块的任务使用。
    • rewrite模型分为Pipeline的方式和End2End的方式
      • Pipeline方法将rewrite任务分成两个子任务,即指代和零指代的检测以及指代消解
      • 基于模型复杂度和性能的考虑,End2End方法的探索一直没有停止,直到2019年出现了几篇比较优秀的工作,本文将其划分为3种类型:基于联合训练的方法、基于序列标注的方法和基于指针网络的方法。
  • ACL 2019 使用表达改写提升多轮对话系统效果
  • 模型框架
  • 对于任务导向型对话系统和闲聊型对话系统均有效果提升,实现了用更成熟的单轮对话技术解决多轮对话问题。
  • Transformer多轮对话改写实践
    • 介绍了多轮对话存在指代和信息省略的问题,同时提出了一种新方法-抽取式多轮对话改写,可以更加实用的部署于线上对话系统,并且提升对话效果
  • 日常的交流对话中
    • 30%的对话会包含指代词。比如“它”用来指代物,“那边”用来指代地址
    • 同时有50%以上的对话会有信息省略
  • 对话改写的任务有两个:1这句话要不要改写;2 把信息省略和指代识别出来。对于baseline论文放出的数据集,有90%的数据都是简单改写,也就是满足任务2,只有信息省略或者指代词。少数改写语句比较复杂,本文训练集剔除他们,但是验证集保留。
  • Transformers结构可以通过attention机制有效提取指代词和上下文中关键信息的配对,最近也有一篇很好的工作专门用Bert来做指代消岐[2]。经过transformer结构提取文本特征后,模型结构及输出如下图。
  • 输出五个指针中:
    • 关键信息的start和end专门用来识别需要为下文做信息补全或者指代的词;
    • 补全位置用来预测关键信息(start-end)插入在待改写语句的位置,实验中用插入位置的下一个token来表示;
    • 指代start和end用来识别带改写语句出现的指代词。
    • 当待改写语句中不存在指代词或者关键信息的补全时,指代的start和end将会指向cls,同理补全位置也这样。如同阅读理解任务中不存在答案一样,这样的操作在做预测任务时,当指代和补全位置的预测最大概率都位于cls时就可以避免改写,从而保证了改写的稳定性。
  • 效果评估
    • 准确度
    • 性能
    • 对数据集的依赖
    • 对负样本(不需要改写样本)的识别.基于指针抽取的方法对负样本的识别效果会更好。同时根据对长文本的改写效果观察,生成式改写效果较差。
  • 示例
A1 B1 A2 算法改写结果 用户标注label
你知道板泉井水吗 知道 她是歌手 板泉井水是歌手 板泉井水是歌手
乌龙茶 乌龙茶好喝吗 嗯好喝 嗯乌龙茶好喝 嗯乌龙茶好喝
武林外传 超爱武林外传的 它的导演是谁 武林外传的导演是谁 武林外传的导演是谁
李文雯你爱我吗 李文雯是哪位啊 她是我女朋友 李文雯是我女朋友 李文雯是我女朋友
舒马赫 舒马赫看球了么 看了 舒马赫看了 舒马赫看球了
  • 结论
    • 抽取式文本改写和生成式改写效果相当
    • 抽取式文本改写速度上绝对优于生成式
    • 抽取式文本改写对训练数据依赖少
    • 抽取式文本改写对负样本识别准确率略高于生成式
  • 参考
  • 几种模型:
    • CopyNet:基于LSTM 的Seq2Seq模型,使用attention 和 copy 机制 (基本的指针网络)
    • PAC:首先使用bert fintune 的 H,U 词向量,然后直接喂给标准的指针生成网络
    • T-Ptr-λ:就上面讲的那一篇腾讯论文的方法,主要是利用6层-6层 的Transformer Encoder Decoder结构
    • Seq2Seq-Uni: 这个baseline 是将Transformer 的各个block 层的输出做了统一结合,然后应用到 seq2seq 结构
    • SARG:论文提出的模型,超参数使用 α=3,λ=1

小样本学习

  • 从「文本增强」和「半监督学习」这两个角度出发,谈一谈如何解决少样本困境
  • NLP中文本增强方法
  • 详情参考:
  • 【2020-7-7】创新奇智有关少样本学习(Few-shot Learning)的研究论文《Prototype Rectification for Few-Shot Learning》被全球计算机视觉顶会ECCV 2020接收为Oral论文,入选率仅2%。参考地址
  • 本文提出一种简单有效的少样本学习方法,通过减小类内偏差和跨类偏差进行原型校正,从而显著提高少样本分类结果,并且给出理论推导证明本文所提方法可以提高理论下界,最终通过实验表明本方法在通用数据集中达到了最优结果,论文被ECCV 2020 接收为Oral。

  • 【2020-8-19】少样本学习中的深度学习模型综述

  • 【2020-11-12】Few-shot Learning最新进展调研
  • 【2021-1-20】少样本学习可以使一个模型快速承接各种任务。但是为每个任务更新整个模型的权重是很浪费的。最好进行局部更新,让更改集中在一小部分参数里。有一些方法让这些微调变得更加有效和实用,包括:
    • 使用 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 等很多流行任务中实现了超越人类的性能,但如何增强其少样本学习能力是改进的关键所在。

多模态学习

【2021-8-2】多模态为什么比单模态好?第一份严谨证明来了!:一篇多模态学习理论分析的文章,从数学角度证明了潜表征空间质量直接决定了多模态学习模型的效果。而在充足的训练数据下,模态的种类越丰富,表征空间的估计越精确

  • What Makes Multimodal Learning Better than Single (Provably),基于一种经典的多模态学习框架,即无缝进行潜空间学习(Latent Space Learning)与任务层学习(Task-specific Learning)。
  • 两个角度回答了这个问题:
    • (When)在何种条件下,多模态学习比单模态学习好
    • (Why)是什么造成了其效果的提升
  • 从真实世界收集的多模态情绪分析的数据集IEMOCAP(Interactive Emotional Dyadic Motion Capture),它包括三种模态:文字(Text)、视频(Video)和音频(Audio)。首先使用离线的特征抽取工具对三种模态信息提取好特征:Audio 100维,Text 100维以及Video 500维。这个数据集的分类有六种,分别是快乐、悲伤、中立、愤怒、兴奋和沮丧。使用了13200条数据做训练,3410条做测试。实验模型上,潜空间的映射使用了一层线性层+Relu,任务层使用了一层Softmax。在对比实验中,如果是单模态模型,则直接进行对应特征映射;如果是多模态模型,则首先进行多模态特征拼接,然后再进行映射。
  • 论文使用机器自动生成的方式,构造了不同的模态关联数据用于验证。这里考虑三种情况:
  • (1)模态之间完全不共享信息,即每个模态只包含模态特定的信息。
  • (2)所有模态之间共享所有信息,没有区分。
  • (3)介于两者之间,既共享一部分信息,也保有模态特定信息。

多模态模型

PaLM-E

【2023-3-7】谷歌发布了个多模态模型 PaLM-E,使用传感器数据、自然语言、视觉训练,能直接用人话操作机器人完成任务。

纠错

错误类型

在中文中,常见的错误类型大概有如下几类:

由于字音字形相似导致的错字形式:体脂称—>体脂秤

  • 字错误:iphonee —> iphone
  • 字错误:爱有天意 –> 假如爱有天意
  • 顺序错误: 表达难以 –> 难以表达

常见的文本错误可以分为

  • (1)字形相似引起的错误
  • (2)拼音相似引起的错误 两大类;如:“咳数”->“咳嗽”;“哈蜜”->“哈密”。错别字往往来自于如下的“相似字典”。
  • 其他错误还包括方言口语化重复输入导致的错误,在ASR中较为常见

现有的NLP技术已经能解决多数文本拼写错误。

  • 剩余的纠错难点主要是部分文本拼写错误需要常识背景(world-knowledge)才能识别。
Wrong: "我想去埃及金子塔旅游。"
Right: "我想去埃及金字塔旅游。"

将其中的“金子塔”纠正为“金字塔”需要一定的背景知识。

同时,一些错误需要模型像人一样具备一定的推理和分析能力才能识破。例如:

Wrong: "他的求胜欲很强,为了越狱在挖洞。"
Right: "他的求生欲很强,为了越狱在挖洞。"

“求胜欲”和“求生欲”在自然语言中都是正确的,但是结合上下文语境来分析,显然后者更为合适。

文本纠错技术对于误判率有严格的要求,一般要求低于0.5%。

  • 如果纠错方法的误判率很高(将正确的词“纠正”成错误的),会对系统和用户体验有很差的负面效果。

纠错方法

常用方法可以归纳为错别字词典编辑距离语言模型等。

  • 构建错别字词典人工成本较高,适用于错别字有限的部分垂直领域;
  • 编辑距离采用类似字符串模糊匹配的方法,通过对照正确样本可以纠正部分常见错别字和语病,但是通用性不足。

所以,现阶段学术界和工业界研究的重点一般都是基于语言模型的纠错技术。

  • 2018年之前,语言模型的方法可以分为传统的 n-gram LM 和 DNN LM,可以以字或词为纠错粒度。
    • 其中“字粒度”的语义信息相对较弱,因此误判率会高于“词粒度”的纠错;
    • “词粒度”则较依赖于分词模型的准确率。
  • 为了降低误判率,往往在模型的输出层加入CRF层校对,通过学习转移概率和全局最优路径避免不合理的错别字输出。
  • 2018年之后,预训练语言模型开始流行,研究人员很快把BERT类的模型迁移到了文本纠错中,并取得了新的最优效果。

纠错模块

纠错一般分两大模块:

  • 错误检测:识别错误发生的位置
  • 错误纠正:对疑似的错误词,根据字音字形等对错词进行候选词召回,并且根据语言模型等对纠错后的结果进行排序,选择最优结果。 如下图所示:

拼音纠错

【2021-9-28】语音识别有误,NLU环节如何补救?基于拼音的纠错

from pypinyin import lazy_pinyin,pinyin
print(lazy_pinyin('江西赣州')) #返回拼音
# ['jiang', 'xi', 'gan', 'zhou']
print(lazy_pinyin('江西赣州',1))    #带声调的拼音
# ['jiāng', 'xī', 'gàn', 'zhōu']
print(lazy_pinyin('江西赣州',2))    #另一种拼音风格
# ['jia1ng', 'xi1', 'ga4n', 'zho1u']
print(lazy_pinyin('江西赣州',3))    #只返回拼音首字母
# ['j', 'x', 'g', 'zh']
print(lazy_pinyin('重要',1))    #能够根据词组智能识别多音字
# ['zhòng', 'yào']
print(lazy_pinyin('重阳',1))
# ['chóng', 'yáng']
print(pinyin('江西')) #返回拼音
# [['jiāng'], ['xī']]
print(pinyin('重阳节',heteronym=True)) #返回多音字的所有读音
# [['zhòng', 'chóng', 'tóng'], ['yáng'], ['jié', 'jiē']]
import jieba
x='中英文混合test123456'
print(lazy_pinyin(x))  #自动调用已安装的pypinyin扩展分词功能
# ['zhong', 'ying', 'wen', 'hun', 'he', 'test123456']
print(list(jieba.cut(x))) #自动调用jieba扩展分词功能
# ['中英文', '混合', 'test123456']
x='江西的桃子真好吃'
print(sorted(x,key=lambda ch:lazy_pinyin(ch))) #按拼音对汉字进行排序
# ['吃', '的', '好', '江', '桃', '西', '真', '子']

主流方案

业界纠错主流方案一般包括错误检测→候选召回→候选排序三部分,根据作者调研工作其技术方案主要可分为以下三种:

  • ① 基于规则式的通用纠错库pycorrector;
  • ② 基于大样本训练深度学习模型的检错算法,以百度纠错系统为代表;
  • ③ 基于垂直领域的DCQC纠错框架。

总结

  • ① 从百度纠错系统和IJCNLP第一名使用方法来看,当具有充足的标注语料时,将LSTM+CRF这种序列标注方式用来进行错误位置检测是一个比较好的方法,但当标注语料有限时,该种方法难以应用落地;
  • ② 基于机器翻译的纠错方法是目前业界及学术界关注的焦点,寿险场景也可以尝试使用NMT的方法来测试效果,然而该技术落地的条件是仍然需要大量的标注数据。 那么在标注资源受限的条件下,如何部署高性能、高效率的纠错系统将成为寿险场景中纠错问题所面临也是急需解决的关键挑战。

参考:NLP上层应用的关键一环——中文纠错技术简述

Hanlp

HanNLP文本纠错在线Demo

pycorrector

pycorrector 通用纠错模块是github上的开源项目,它提供了一种规则式检错、纠错方案,该方法因逻辑清晰、不依赖大量标注样本从而较容易实现落地,因此为广大研究者提供了良好的借鉴意义。

  • pycorrector 支持 kenlm 、 rnn_crf 、 seq2seq 、BERT 等各种模型。
  • 结合具体领域的微调和少量规则修正,应该可以满足大部分场景中的文本纠错需求了。

使用人民日报语料微调过的BERT模型,通过pycorrect加载来做基于MLM的文本纠错。识别结果还算可以,甚至“金字塔”这种需要常识的错别字都纠正出来了。

该模块在检错部分利用常用字典、混淆字典与传统语言模型共同判断当前位置是否有错。制订了如下规则:

  • ①当切词后的片段不在常用字典中或存在于混淆字典的映射对中时判定有错;
  • ②计算传统语言模型概率是否低于门限并判错。 候选召回部分利用同音、同型召回候选字词,打分排序利用句子困惑度来计算候选词权重,从而对候选进行排序。

该方案是面向通用领域开发的,思路简单、易实现,但在保险垂直领域中容易得到较差的表现。

百度纠错系统

百度纠错系统凭借其海量用户点击语料训练了基于深度学习的序列标注模型,方法如下:

  • 错误检测:在错误检测部分,它利用10TB的无监督语料预训练Transformer/Lstm + CRF模型,再利用对齐语料(错误句子→正确句子)进行有监督学习该序列标注模型;
  • 候选召回:在候选召回部分,利用了对齐语料和对齐模型构建字级别、词级别、音级别的混淆字典,先利用字、音混淆字典初步召回候选,然后再利用词级别混淆字典和语言模型二次筛选候选,从而形成最终候选;
  • 候选排序:利用上下文DNN特征和人工提取的形音、词法、语义等特征一起训练GBDT&LR的排序模型。

腾讯基于垂域的DCQC纠错框架

腾讯提出一套针对垂直业务的通用纠错框架——DCQC(Domain Common Query Correction),由召回层和决策层两层组成。该方法可以方便扩展到其他领域[2] 。

  • 召回层:每个领域建立属于自己的一个数据库,建立字和拼音两个维度的倒排索引,通过检索排序的方式召回一定量的候选;
  • 决策层:人工提取用户特征、拼音特征等5种类型特征训练svm二分类模型用于候选排序。

学术界的进展

学术界近期发表的中文纠错论文主要集中在中文纠错比赛项目上,如:SIGHAN举办的CSC(中文拼写纠错)比赛、IJCNLP举办的CGED(中文语法错误诊断)比赛及NLPCC举办的GGED(中文语法错误诊断)比赛等。

LSTM+CRF序列标注用于错误检测

IJCNLP2017 [3]和2018 [4]的CGED比赛任务中,第一名的方法都用了LSTM+CRF用于错误位置的检测。然而文中,该方法在错误位置检测方面的F1值最高也只有0.39,目前还没有达到工业化使用的要求。

NMT基于神经机器翻译模型纠错方法

基于机器翻译模型的纠错方法的思想是,将纠错任务类比于机器翻译任务,预想利用模型将错误语句翻译为正确语句,利用Seq2seq模型完成端到端的纠正过程。

YUAN等学者在2016首次利用双向RNN编码器+单向RNN解码器+Attention的经典结构对CoNll-2014(英文语料)进行语法纠错,达到当时最好效果,其统计指标F0.5为39.9%;其后,有道团队在NLPCC-2018举办的CGEC比赛中利用Transformer的翻译模型达到比赛最好的结果,其F0.5值 为29.9% [5]。

深度学习纠错

【2021-3-20】中文纠错(Chinese Spelling Correct)最新技术方案总结, 总结:

FASPell(爱奇艺)

爱奇艺团队2019年发表在EMNLP会议上的论文,通过训练一个以BERT为基础的深度降噪编码器(DAE)和以置信度-字音字行相似度为基础的解码器(CSD)进行中文拼写纠错。在DAE阶段,BERT可以动态生成候选集去取代传统的混淆集,而CSD通过计算置信度和字音字形相似度两个维度去取代传统的单一的阈值进行候选集的选择,提高纠错效果,取得了SOTA( state-of-the-art)的一个效果。

模型主要分两大块组成:

  • 第一:Masked Language Model (bert)
    • 是一个自动编码器(DAE), 基于bert模型,每次获取预测词的top k个候选字。
  • 第二:Cofidence-Similarity Decoder
    • 该部分是一个解码器,通过编码器输出的置信度confidence分值和中文字音字形的相似度similarity分值两个维度进行候选集的过滤和刷选,选择最佳候选的路径作为输出。

模型结构

Similarity:包含形体相似(visual similarity) 和字音相似(phonological similarity) ,本论文通过这两种情况进行汉字的相似度计算。

  • (1)Visual similarity
    • 在字形上采用Unicode标准的Ideographic Description Sequence (IDS)表征。描述汉字更细粒度字体的笔画结构和布局形式(相同的笔画和笔画顺序,例如:“牛”和“午”相似度不为1),比起纯笔画或者五笔编码等计算方式要精细。如下图,展示的是“贫”字的IDS计算,每个字符编码是每个叶子节点从根节点到的搜索路径
  • (2)Phonological similarity
    • 在字音上,使用了所有的CJK语言中的汉字发音,本文用了普通话(MC),粤语 (CC),日语(JO),韩语(K)和越南语 (V) 中的发音,计算拼音的编辑距离作为相似度分值,最终做一个归一化操作。如下图展示的是字形和字音相似度结果

训练过程

  • 预训练MLM部分
    • 按照bert原始的mlm方式:对句子15%部分进行置换操作,其中80%替换成[MASK],10%替换成随机的一个词, 10%替换成原始的词
  • fine-tune MLM
    • 第一部分: 对于没有错词的文本,按照bert原始的mlm方式
    • 第二部分: 对于有错词的文本, 两种样本构造:1)用原始错误的词作为mask,正确的词作为target目标词; 2)同时对正确的词也做mask,用原始的词作为mask,目标词为原始词
  • 训练CSD
    • 训练完encoder,然后根据encoder预测出的confidence分值和字音字形相似度分值,绘制散点图,通过人工观察用直线拟合,确定能够分开正确和错误的点的分界曲线,论文最终给出的曲线为: 0.8 × \times× confidence + 0.2 × \times× similarity >0.8

优点和缺点

  • 优点:
    • 用MLM预测动态生成候选集,取代了传统的混淆表,整个流程相对简单
    • 通过字音字形特征,用多种语言表达的字音特征进行曲线拟合,可解释好
  • 缺点
    • 不包括少词和多词错误形式纠错
    • 训练不是end-to-end的过程,CSD分界曲线靠观察拟合生成

SpellGCN (阿里)

技术方案

阿里团队于2020年在ACL会议上发表,主要通过graph convolutional network (GCN)对字音和字形结构关系进行学习,并且将这种字音字形的向量融入到字的embedding中,在纠错分类的时候,纠错更倾向于预测为混淆集里的字。模型训练是一个end-to-end的过程,试验显示,在公开的中文纠错数据集上有一个较大的提升

模型也主要分两部分组成:

  • 第一部分:特征提取器, 特征提取器基于12层的bert最后一层的输出
  • 第二部分:纠错分类模型, 通过GCN学习字音字形相似结构信息,融合字的语义信息和字的结构信息,在分类层提高纠错准确率。

  • 优点
    • 将字音字形特征通过GCN学习嵌入到语义字向量表征中去,使得错词在纠错的时候能够更倾向于纠正为混淆集中的词,提高纠错准确率
  • 缺点
    • 不包括少词和多词错误形式纠错
    • 混淆集在测试集的覆盖率影响效果评估

Soft-Mask BERT (字节)

技术方案

字节团队于2020年发表在ACL会议,将纠错任务分成两部分:detection network(错误检测)和correction network(错误纠正)。在错误检测部分,通过BiGRU模型对每个输入字符进行错误检测,得到每个输入字符的错误概率值参与计算soft-masked embedding作为纠错部分的输入向量,一定程度减少了bert模型的过纠问题,提高纠错准确率。

论文首次提出了Soft-Masked BERT模型,主要创新点在于:

  • (1)将文本纠错划分为检测网络(Detection)和纠正网络(Correction)两部分,纠正网络的输入来自于检测网络输出。
  • (2)以检测网络的输出作为权重,将 masking-embedding以“soft方式”添加到各个字符特征上,即“Soft-Masked”。

  • 优点
    • 对中文纠错分成错误检测和错误纠正,并给通过soft-masking技术将两者进行融合,减少bert的过纠问题,提高准确率
  • 缺点
    • 不包括少词和多词错误形式纠错
    • 模型没有引入字音字形相似性约束,虽然引入了错误检测模块,通过soft mask技术减少过纠问题,但是只是依赖bert的语义识别进行纠错,不够鲁棒

Spelling Correction as a Foreign Language (ebay)

技术方案

ebay团队于2019年发表在SIGIR 2019 eCom会议上,将纠错任务当做机器翻译任务,基于encoder-decoder框架。

训练过程

  • 训练数据: 主要基于电商平台用户搜索session,通过跟踪用户行为构造样本数据,一个前提假设是,在一个session内,在没有找到满足用户意图商品情况下,用户会主动修改搜索query直到搜索结果符合用户的意图,而基于这样的一个搜索组成的query序列,从中可以挖掘出潜在的错误和正确的query pair对构造训练样本。
  • 训练过程: end-to-end训练seq2seq模型。

优点和缺点

  • 优点
    • 将纠错当做翻译任务去做,可以对不同类型的错误形式:错词,少词,多词等进行纠错
  • 缺点
    • 模型没有对字音字形相似关系的学习,纠错后的结果不受约束,很容易出现过纠错和误纠问题

HeadFit (加利福尼亚大学)

技术方案

在中文公开纠错数据集上取得了不错的效果。纠错模块分两部分:第一部分是基于bert的base模型,输出可能纠错后的结果,第二部分是一个filter模块,主要基于treeLSTM模型学习出字的hierarchical embedding,通过向量相似度衡量两个字的相似度,取代了预先设定好的混淆集并且可以通过模型的自适应学习,发现字与字之间新的混淆关系能力,通过filter模块,进一步过滤bert模型的过纠等问题,提高准确率。

  • 优点
    • 通过treeLSTM模型学习字的hierarchical向量,不依赖于固定的混淆集,让模型自适应学习字形结构向量特征,通过模型的学习能够扩充混淆关系集,并且对新词和新的领域有较好的适应能力
  • 缺点
    • 模型学习中没有利用到字与字之间的拼音相似关系
    • 模型训练不是一个end-to-end的过程

nlp工具集合

Demo集合

  • 【2020-5-19】NLP各类应用Demo汇总(Colab实现),The Super Duper NLP Repo,如文本生成、对话、问答、翻译等

数据集

web平台

  • 【2021-7-15】nlp-web-demo页面集成了Stanford, Hanlp, FNLP, Thulc, FudanDNN, Boson NLP and Jieba等方法,对比分词、词性标注、句法、摘要等效果
  • watson的Natural Language Understanding工具包 demo,支持中文,可以实测。

开源nlp工具包

nlp工具包汇总推荐

工具包 作者 基本功能 特殊功能 擅长语种 备注  
jieba 个人 分词/关键词/词性 自定义字典/三种模式分词 中文 -  
pkuseg 北大 分词/词性 自定义字典/多领域分词/高准确/用户自训练/文件分词 中文 优于jieba+THULAC  
LTP 哈工大 分词/词性/句法分析 - 中文 pyltp, demo,命名实体标注集没有提取“时间”  
THULAC 清华 分词/词性/句法分析 - 中文 中文词法分析工具包,准确率高,速度快; demo  
stanfordNLP 斯坦福 分词/词性/句法分析/实体识别/语法树 词干还原/wordnet(同义词)/语料库 英文 Java+python,依赖pytorch,demo  
allennlp 组织 - 多种高级NLP能力(阅读理解/指代消解等) 英文 紧跟sota,demo  
wastonnlp IBM - - 英文 demo  
NLTK 宾大 分词/词性/句法分析/实体识别 句法可视化 英文 学术界  
TextBlob 个人 分词/词性/实体识别/摘要/关键词 文本分类/情感分析/词根化/纠错/机器翻译/wordnet 英文 Nltk抽象而来  
SnowNLP 个人 分词/词性/分句/摘要/关键词 文本分类/情感分析/繁简/拼音/相似度 中文 TextBolb非官方中文版,不依赖nltk  
DeepNLP - 分词/词性/句法/摘要/关键词/实体识别 文本分类/pipeline/web api/用户自训练 中文  
小明NLP 个人 分词/词性/摘要/关键词 自定义字典/文本分类/情感分析/繁简/拼音/纠错/偏旁部首 中文    
spaCy - 分词/词性/摘要/关键词/分句/句法/语法树 文本相似度/统计学习/深度学习/可视化 53种语言 工业级,cython,高性能,TensorFlow/pytorch支持,标注工具 https://prodi.gy/  
FoolNLP 复旦 分词/关键词/词性 自定义字典 中文 非最快但最准,bi-LSTM  
HanNLP - 分词/词性/实体识别/摘要/关键词/句法分析 繁简/拼音/纠错/聚类/w2v 中文 Java→python,支持TensorFlow  
bosonnlp 公司 - - 中文 Demo云孚科技  

杭州实在智能(阿里P8创立的公司)的nlp-base基础能力demo

Jieba结巴

github地址

分词

  • jieba.cut 方法接受三个输入参数: 需要分词的字符串;cut_all 参数用来控制是否采用全模式;HMM 参数用来控制是否使用 HMM 模型
  • jieba.cut_for_search 方法接受两个参数:需要分词的字符串;是否使用 HMM 模型。该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细
  • 待分词的字符串可以是 unicode 或 UTF-8 字符串、GBK 字符串。注意:不建议直接输入 GBK 字符串,可能无法预料地错误解码成 UTF-8
  • jieba.cut 以及 jieba.cut_for_search 返回的结构都是一个可迭代的 generator,可以使用 for 循环来获得分词后得到的每一个词语(unicode),或者用jieba.lcut 以及 jieba.lcut_for_search 直接返回 list
  • jieba.Tokenizer(dictionary=DEFAULT_DICT) 新建自定义分词器,可用于同时使用不同词典。jieba.dt 为默认分词器,所有全局分词相关函数都是该分词器的映射。

结巴中文分词采用的算法

  • 基于Trie树(前缀树)结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG)
  • 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
  • 对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法

三种分词模式:

  • 精确模式,试图将句子最精确地切开,适合文本分析;
  • 模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
  • 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。

自定义字典

  • 开发者可以指定自己的词典,以便包含 jieba 词库里没有的词。虽然 jieba 有新词识别能力,但是自行添加新词可以保证更高的正确率
  • 用法: jieba.load_userdict(file_name) # file_name 为文件类对象或自定义词典的路径
  • 词典格式和 dict.txt 一样,一个词占一行;每一行分三部分:词语词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。file_name 若为路径或二进制方式打开的文件,则文件必须为 UTF-8 编码。
  • 词频省略时使用自动计算的能保证分出该词的词频。
  • 注:词性可以自定义,如norm、project都可以
创新办 3 i
云计算 5
凱特琳 nz
台中

调整字典

  • 使用 add_word(word, freq=None, tag=None) 和 del_word(word) 可在程序中动态修改词典。
  • 使用 suggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。

注意:自动计算的词频在使用 HMM 新词发现功能时可能无效。

延迟加载机制

  • jieba 采用延迟加载,import jieba 和 jieba.Tokenizer() 不会立即触发词典的加载,一旦有必要才开始加载词典构建前缀字典。如果你想手工初始 jieba,也可以手动初始化。
  • 手工初始化:jieba.initialize() # 手动初始化(可选)
  • 在 0.28 之前的版本是不能指定主词典的路径的,有了延迟加载机制后,你可以改变主词典的路径: 示例
    • jieba.set_dictionary(‘data/dict.txt.big’)
import re
import pandas as pd

# 测试数据
df = pd.DataFrame([['你好,我是链家经纪人', 20],['贝壳是房地产公司', 13],['贝壳分下降了怎么办,你帮忙看下',30],['[哭泣]',23]], columns=['query','freq'])
print(df.shape)

# 加载停用词
stop_words = [line.strip() for line in open('stopWord2.txt', encoding='gbk').readlines()]

# 分词函数一:中文分词,包括除去数字字母及停用词,得到一个分词用空格隔开的字符串,便于向量化(因为这个CountVouterizer()是针对英文分词的,英文之间直接用空格隔开的)
def cut_word(sent):
    line = re.sub(r'[a-zA-Z0-9]*','',sent)
    wordList = jieba.lcut(line,cut_all=False)
    #文本分词,并且用空格连接起来,便于下面向量化
    return ' '.join([word for word in wordList if word not in stopWord and len(word)>1])

# 分词函数二:没去停用词,CountVouterizer()中可以直接添加停用词表参数,不统计文档中的停用词的数量
def cutword(sent):
    line = re.sub(r'[a-zA-Z0-9]*','',sent)
    wordList = jieba.lcut(line,cut_all=False)
    return ' '.join([word for word in wordList if len(word)>1])

# 分词函数三:精准分词,选择词性
import jieba.posseg as pseg
def jieba_cut(comment):
    word_list = []  # 建立空列表用于存储分词结果
    seg_list = pseg.cut(comment)  # 精确模式分词[默认模式]
    for word in seg_list:
        if word.flag in ['ns', 'n', 'vn', 'v', 'nr']:  # 选择属性
            word_list.append(word.word)  # 分词追加到列表
    return word_list

#将文本分词,并且分词用空格隔开变成文本存才DataFrame中
df['word_list']=df['query'].map(cutword)
#df['word_list']=df['query'].apply(cutword) # apply也行
# 向量化
vectorizer = TfidfVectorizer(stop_words=stop_words,  tokenizer=jieba_cut,  use_idf=True)  # 创建词向量模型
X = vectorizer.fit_transform(comment_list)  # 将评论关键字列表转换为词向量空间模型
# K均值聚类
model_kmeans = KMeans(n_clusters=3)  # 创建聚类模型对象
model_kmeans.fit(X)  # 训练模型
# 聚类结果汇总
cluster_labels = model_kmeans.labels_  # 聚类标签结果
word_vectors = vectorizer.get_feature_names()  # 词向量
word_values = X.toarray()  # 向量值
comment_matrix = np.hstack((word_values,  cluster_labels.reshape(word_values.
    shape[0], 1)))  # 将向量值和标签值合并为新的矩阵
word_vectors.append('cluster_labels')  # 将新的聚类标签列表追加到词向量后面
comment_pd = pd.DataFrame(comment_matrix, columns=word_vectors)  # 创建包含词向量和聚类标签的数据框
comment_pd.to_csv('comment.csv')
print(comment_pd.head(1))  # 打印输出数据框第1条数据
# 聚类结果分析
comment_cluster1 = comment_pd[comment_pd['cluster_labels'] == 1].drop('cluster_labels', axis=1)  # 选择聚类标签值为1的数据,并删除最后一列
word_importance = np.sum(comment_cluster1, axis=0)  # 按照词向量做汇总统计
print(word_importance.sort_values(ascending=False)[:5])   # 按汇总统计的值做逆序排序并打印输出前5个词

并行分词

  • 原理:将目标文本按行分隔后,把各行文本分配到多个 Python 进程并行分词,然后归并结果,从而获得分词速度的可观提升
  • 基于 python 自带的 multiprocessing 模块,目前暂不支持 Windows
  • 用法:
    • jieba.enable_parallel(4) # 开启并行分词模式,参数为并行进程数
    • jieba.disable_parallel() # 关闭并行分词模式
  • 例子

实验结果:

在 4 核 3.4GHz Linux 机器上,对金庸全集进行精确分词,获得了 1MB/s 的速度,是单进程版的 3.3 倍。

注意:并行分词仅支持默认分词器 jieba.dt 和 jieba.posseg.dt。

Tokenize 分词位置

返回词语在原文的起止位置

注意,输入参数只接受 unicode

result = jieba.tokenize(u'永和服装饰品有限公司')
for tk in result:
    print("word %s\t\t start: %d \t\t end:%d" % (tk[0],tk[1],tk[2]))

命令行分词

使用示例:python -m jieba news.txt > cut_result.txt

使用: python -m jieba [options] filename

结巴命令行界面。

固定参数:
  filename              输入文件

可选参数:
  -h, --help            显示此帮助信息并退出
  -d [DELIM], --delimiter [DELIM]
                        使用 DELIM 分隔词语,而不是用默认的' / '。
                        若不指定 DELIM,则使用一个空格分隔。
  -p [DELIM], --pos [DELIM]
                        启用词性标注;如果指定 DELIM,词语和词性之间
                        用它分隔,否则用 _ 分隔
  -D DICT, --dict DICT  使用 DICT 代替默认词典
  -u USER_DICT, --user-dict USER_DICT
                        使用 USER_DICT 作为附加词典,与默认词典或自定义词典配合使用
  -a, --cut-all         全模式分词(不支持词性标注)
  -n, --no-hmm          不使用隐含马尔可夫模型
  -q, --quiet           不输出载入信息到 STDERR
  -V, --version         显示版本信息并退出

如果没有指定文件名,则使用标准输入。

关键词

(1)基于 TF-IDF 算法的关键词抽取 import jieba.analyse

  • jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
    • sentence 为待提取的文本
    • topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20
    • withWeight 为是否一并返回关键词权重值,默认值为 False
    • allowPOS 仅包括指定词性的词,默认值为空,即不筛选
  • jieba.analyse.TFIDF(idf_path=None) 新建 TFIDF 实例,idf_path 为 IDF 频率文件 代码示例 (关键词提取)

  • 关键词提取所使用逆向文件频率(IDF)文本语料库可以切换成自定义语料库的路径
    • 用法: jieba.analyse.set_idf_path(file_name) # file_name为自定义语料库的路径
    • 自定义语料库示例, 用法示例
  • 关键词提取所使用停止词(停用词)(Stop Words)文本语料库可以切换成自定义语料库的路径
    • 用法: jieba.analyse.set_stop_words(file_name) # file_name为自定义语料库的路径
    • 自定义语料库示例, 用法示例
  • 关键词一并返回关键词权重值示例

(2) 基于 TextRank 算法的关键词抽取

算法论文: TextRank: Bringing Order into Texts

基本思想:

  • 将待抽取关键词的文本进行分词
  • 以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图
  • 计算图中节点的PageRank,注意是无向带权图 使用示例: test/demo.py

  • jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=(‘ns’, ‘n’, ‘vn’, ‘v’)) 直接使用,接口相同,注意默认过滤词性。
  • jieba.analyse.TextRank() 新建自定义 TextRank 实例

停用词

自定义语料库示例, 用法示例

国内比较常用的中文停用词库,有以下几个:

  • 中文停用词表
  • 哈工大停用词表
  • 百度停用词表
  • 四川大学机器智能实验室停用词库 而elephantnose对以上4个词库进行了合并去重,共计2311个,还有3500个常用汉字,生僻字,可在github直接下载使用~~ 链接:GitHub链接
# 下载 https://github.com/elephantnose/characters/blob/master/stop_words
stop_words_file = "/Users/bytedance/Desktop/code/data/stop_words"
# 读取字典
stopword_list = [i.strip() for i in open(stop_words_file, encoding='utf8')]
# 或者直接设置jieba
import jieba.analyse as analyse
jieba.analyse.set_stop_words('stop_words')

词性标注

  • jieba.posseg.POSTokenizer(tokenizer=None) 新建自定义分词器,tokenizer 参数可指定内部使用的 jieba.Tokenizer 分词器。jieba.posseg.dt 为默认词性标注分词器。
  • 标注句子分词后每个词的词性,采用和 ictclas 兼容的标记法

更多内容:python使用结巴中文分词以及训练自己的分词词典, github代码示例

# -*- coding:utf-8 -*-
import jieba

text = '我来到北京清华大学'
# (1)添加或管理自定义词典,dict.txt,一个词占一行;
# 每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。
# file_name 若为路径或二进制方式打开的文件,则文件必须为 UTF-8 编码。
# 实例:
# 创新办 3 i
# 不处理 nr
# 不还款
jieba.load_userdict("./dict.txt")
# (2)修改字典
# 使用add_word(word, freq=None, tag=None)和del_word(word)可在程序中动态修改词典。
# 使用suggest_freq(segment, tune=True)可调节单个词语的词频,使其能(或不能)被分出来。
jieba.suggest_freq('不处理',True)
jieba.add_word('不处理',tag='d')
jieba.add_word('中国银行APP',tag='d')
jieba.del_word('不处理')
word_list = jieba.cut("我今天不处理逾期信用贷款,因为你们中国银行APP根本打不开")
print("|".join(word_list))
# (4)分词
default_mode = jieba.cut(text) # 精确
full_mode = jieba.cut(text,cut_all=True) # 全模式
search_mode = jieba.cut_for_search(text) # 搜索引擎

print("精确模式:","/".join(default_mode))
print("全模式:","/".join(full_mode))
print("搜索引擎模式:","/".join(search_mode))
# (5)关键词提取
tags = jieba.analyse.extract_tags(text,2)
print("关键词抽取:","/".join(tags))

NER

代码

import jieba
import jieba.analyse
import jieba.posseg as posg

# 使用 jieba 进行词性切分,allowPOS 指定允许的词性,这里选择名词 n 和地名 ns
sentence = u'''上线三年就成功上市,拼多多上演了互联网企业的上市奇迹,却也放大平台上存在的诸多问题,黄峥在美国上市。'''
kw = jieba.analyse.extract_tags(sentence, topK=10, withWeight=True, allowPOS=('n', 'ns', 'nr'))
print(kw)
for item in kw:
    print(item[0], item[1])

kw = jieba.analyse.textrank(sentence,topK=20,withWeight=True,allowPOS=('ns','n'))
print(kw)
for item in kw:
    print(item[0],item[1])

北大pkuseg —— 超过jieba+THULAC

北京大学语言计算与机器学习研究组研制推出的一套全新的中文分词工具包。pkuseg具有如下几个特点:

  • 多领域分词。不同于以往的通用中文分词工具,此工具包同时致力于为不同领域的数据提供个性化的预训练模型。根据待分词文本的领域特点,用户可以自由地选择不同的模型。 我们目前支持了新闻领域,网络领域,医药领域,旅游领域,以及混合领域的分词预训练模型。在使用中,如果用户明确待分词的领域,可加载对应的模型进行分词。如果用户无法确定具体领域,推荐使用在混合领域上训练的通用模型。各领域分词样例可参考txt。
  • 更高的分词准确率。相比于其他的分词工具包,当使用相同的训练数据和测试数据,pkuseg可以取得更高的分词准确率。
  • 支持用户自训练模型。支持用户使用全新的标注数据进行训练。
  • 支持词性标注。
import pkuseg

seg = pkuseg.pkuseg()   # 以默认配置加载模型
seg = pkuseg.pkuseg(model_name='medicine')  # 程序会自动下载所对应的细领域模型, news/web/tourism/medicine
seg = pkuseg.pkuseg(postag=True)  # 开启词性标注功能
seg = pkuseg.pkuseg(user_dict='my_dict.txt')  # 给定用户词典为当前目录下的"my_dict.txt"

text = seg.cut('我爱北京天安门')  # 进行分词
print(text)

# 对input.txt的文件分词输出到output.txt中, 开8个进程
pkuseg.test('input.txt', 'output.txt', nthread=8)
# 模型训练
pkuseg.train(trainFile, testFile, savedir, train_iter = 20, init_model)

pkuseg分词示例,及词云可视化

import pkuseg
from collections import Counter
import pprint
from wordcloud import WordCloud
import matplotlib.pyplot as plt

with open("data/santisanbuqu_liucixin.txt", encoding="utf-8") as f:
    content = f.read()

with open("data/CNENstopwords.txt", encoding="utf-8") as f:
    stopwords = f.read()

lexicon = ['章北海', '汪淼', '叶文洁']
seg = pkuseg.pkuseg(user_dict=lexicon)
text = seg.cut(content)

new_text = []
for w in text:
    if w not in stopwords:
        new_text.append(w)
counter = Counter(new_text)
pprint.pprint(counter.most_common(50))

cut_text = " ".join(new_text)

wordcloud = WordCloud(font_path="font/FZYingXueJW.TTF", background_color="white", width=800, height=600).generate(
    cut_text)

plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()

img

哈工大LTP

  • LTP, pyltp是python下对ltp(c++)的封装。
  • 安装
    • pip install pyltp
    • 安装完毕后,还需要下载模型文件,文件下载地址

【2023-9-12】huggingface 地址 base2

模型性能以及下载地址

深度学习模型 分词 词性 命名实体 语义角色 依存句法 语义依存 速度(句/S)
Base 98.7 98.5 95.4 80.6 89.5 75.2 39.12
Base1 99.22 98.73 96.39 79.28 89.57 76.57 --.–
Base2 99.18 98.69 95.97 79.49 90.19 76.62 --.–
Small 98.4 98.2 94.3 78.4 88.3 74.7 43.13
Tiny 96.8 97.1 91.6 70.9 83.8 70.1 53.22
感知机算法 分词 词性 命名实体 速度(句/s) 备注
Legacy 97.93 98.41 94.28 21581.48 性能详情
# pip install -U ltp ltp-core ltp-extension -i https://pypi.org/simple # 安装 ltp
import torch
from ltp import LTP

ltp = LTP("LTP/small")  # 默认加载 Small 模型

# 将模型移动到 GPU 上
if torch.cuda.is_available():
    # ltp.cuda()
    ltp.to("cuda")

output = ltp.pipeline(["他叫汤姆去拿外衣。"], tasks=["cws", "pos", "ner", "srl", "dep", "sdp"])
# 使用字典格式作为返回结果
print(output.cws)  # print(output[0]) / print(output['cws']) # 也可以使用下标访问
print(output.pos)
print(output.sdp)

# 使用感知机算法实现的分词、词性和命名实体识别,速度比较快,但是精度略低
ltp = LTP("LTP/legacy")
# cws, pos, ner = ltp.pipeline(["他叫汤姆去拿外衣。"], tasks=["cws", "ner"]).to_tuple() # error: NER 需要 词性标注任务的结果
cws, pos, ner = ltp.pipeline(["他叫汤姆去拿外衣。"], tasks=["cws", "pos", "ner"]).to_tuple()  # to tuple 可以自动转换为元组格式
# 使用元组格式作为返回结果
print(cws, pos, ner)

原工具包代码

from ltp import LTP

ltp = LTP()  # 默认加载 Small 模型
seg, hidden = ltp.seg(["他叫汤姆去拿外衣。"])
pos = ltp.pos(hidden)
ner = ltp.ner(hidden)
srl = ltp.srl(hidden)
dep = ltp.dep(hidden)
sdp = ltp.sdp(hidden)

pyltp示例

import os
from pyltp import SentenceSplitter
from pyltp import Segmentor
from pyltp import Postagger
from pyltp import NamedEntityRecognizer
from pyltp import Parser
from pyltp import SementicRoleLabeller

LTP_DATA_DIR = 'D:\CodeHub\CutSeg\ltp_data_v3.4.0'  # ltp模型目录的路径

# 分句
sents = SentenceSplitter.split('元芳你怎么看?我就趴窗口上看呗!')  # 分句
print('\n'.join(sents))

# 分词
cws_model_path = os.path.join(LTP_DATA_DIR, 'cws.model')  # 分词模型路径,模型名称为`cws.model`
segmentor = Segmentor()  # 初始化实例
segmentor.load(cws_model_path)  # 加载模型
words = segmentor.segment('元芳你怎么看')  # 分词
print('/'.join(words))
segmentor.release()  # 释放模型

# 词性标注
pos_model_path = os.path.join(LTP_DATA_DIR, 'pos.model')  # 词性标注模型路径,模型名称为`pos.model`
postagger = Postagger()  # 初始化实例
postagger.load(pos_model_path)  # 加载模型
postags = postagger.postag(words)  # 词性标注
print('/'.join(postags))
postagger.release()  # 释放模型

# 命名实体识别
ner_model_path = os.path.join(LTP_DATA_DIR, 'ner.model')  # 命名实体识别模型路径,模型名称为`ner.model`
recognizer = NamedEntityRecognizer()  # 初始化实例
recognizer.load(ner_model_path)  # 加载模型
netags = recognizer.recognize(words, postags)  # 命名实体识别
print('/'.join(netags))
recognizer.release()  # 释放模型

# 依存句法分析
par_model_path = os.path.join(LTP_DATA_DIR, 'parser.model')  # 依存句法分析模型路径,模型名称为`parser.model`
parser = Parser()  # 初始化实例
parser.load(par_model_path)  # 加载模型
arcs = parser.parse(words, postags)  # 句法分析
print("/".join("%d:%s" % (arc.head, arc.relation) for arc in arcs))
parser.release()  # 释放模型

# 语义角色标注
# srl_model_path = os.path.join(LTP_DATA_DIR, 'pisrl.model')  # 语义角色标注模型目录路径,模型目录为`pisrl.model`
srl_model_path = os.path.join(LTP_DATA_DIR,
                              'pisrl_win.model')  # windows系统要用不同的SRL模型文件,http://ospm9rsnd.bkt.clouddn.com/server/3.4.0/pisrl_win.model或http://model.scir.yunfutech.com/server/3.4.0/pisrl_win.model
labeller = SementicRoleLabeller()  # 初始化实例
labeller.load(srl_model_path)  # 加载模型
roles = labeller.label(words, postags, arcs)  # 语义角色标注
for role in roles:
    print(role.index, "".join(
        ["%s:(%d,%d)" % (arg.name, arg.range.start, arg.range.end) for arg in role.arguments]))
labeller.release()  # 释放模型

清华THULAC

THULAC(THU Lexical Analyzer for Chinese)由清华大学自然语言处理与社会人文计算实验室研制推出的一套中文词法分析工具包,具有中文分词和词性标注功能。THULAC具有如下几个特点:

  • 能力强。利用我们集成的目前世界上规模最大的人工分词和词性标注中文语料库(约含5800万字)训练而成,模型标注能力强大。
  • 准确率高。该工具包在标准数据集Chinese Treebank(CTB5)上分词的F1值可达3%,词性标注的F1值可达到9%,与该数据集上最好方法效果相当。
  • 速度较快。同时进行分词和词性标注速度为300KB/s,每秒可处理约15万字。只进行分词速度可达到3MB/s。

安装

  • pip install thulac
  • 安装时会默认下载模型文件。

示例:

#===========命令行============
#从input.txt读入,并将分词和词性标注结果输出到ouptut.txt中
python -m thulac input.txt output.txt
#如果只需要分词功能,可在增加参数"seg_only" 
python -m thulac input.txt output.txt seg_only

Python接口

#=======================
import thulac

# 示例1
thu1 = thulac.thulac()  # 默认模式
text = thu1.cut("我爱北京天安门", text=True)  # 进行一句话分词
print(text)

# 示例2
thu2 = thulac.thulac(seg_only=True)  # 只进行分词,不进行词性标注
thu2.cut_f("input.txt", "output.txt")  # 对input.txt文件内容进行分词,输出到output.txt
# 完整格式
thulac(user_dict = None, model_path = None, T2S = False, seg_only = False, filt = False, max_length = 50000, deli='_', rm_space=False)

参数:

  • user_dict:设置用户词典,用户词典中的词会被打上uw标签。词典中每一个词一行,UTF8编码
  • model_path:设置模型文件所在文件夹,默认为models/
  • T2S:默认False, 是否将句子从繁体转化为简体
  • seg_only:默认False, 时候只进行分词,不进行词性标注
  • filt:默认False, 是否使用过滤器去除一些没有意义的词语,例如“可以”。
  • max_length:最大长度
  • deli:默认为‘_’, 设置词与词性之间的分隔符
  • rm_space:默认为False, 是否去掉原文本中的空格后再进行分词
  • text:默认为False, 是否返回文本,不返回文本则返回一个二维数组([[word, tag]..]),seg_only模式下tag为空字符。

斯坦福 stanford NLP

多个版本:

  • Stanford CoreNLP的源代码stanfordnlp是使用Java写的,提供了Server方式进行交互。
  • stanfordcorenlp(推荐使用):一个对Stanford CoreNLP进行了封装的Python工具包。

安装流程:

  • 安装Python包:pip install stanfordcorenlp
  • 下载安装JDK(版本要求JDK 1.8以上)
  • 下载安装Stanford CoreNLP文件即语言包。解压CoreNLP文件,并将中文包放在解压文件的根目录。

python调用

from stanfordcorenlp import StanfordCoreNLP

nlp = StanfordCoreNLP('D:\\stanford-corenlp-full-2018-02-27', lang='zh')
sentence = '斯坦福大学自然语言处理包StanfordNLP'
print(nlp.word_tokenize(sentence))  # 分词, ['斯坦福', '大学', '自然', '语言', '处理', '包', 'StanfordNLP']
print(nlp.pos_tag(sentence))  # 词性标注, [('斯坦福', 'NR'), ('大学', 'NN'), ('自然', 'AD'), ('语言', 'NN'), ('处理', 'VV'), ('包', 'NN'), ('StanfordNLP', 'NN')]
print(nlp.ner(sentence))  # 实体识别, [('斯坦福', 'ORGANIZATION'), ('大学', 'ORGANIZATION'), ('自然', 'O'), ('语言', 'O'), ('处理', 'O'), ('包', 'O'), ('StanfordNLP', 'O')]
print(nlp.parse(sentence))  # 语法树, 略
print(nlp.dependency_parse(sentence))  # 依存句法, [('ROOT', 0, 5), ('compound:nn', 2, 1), ('nsubj', 5, 2), ('advmod', 5, 3), ('nsubj', 5, 4), ('compound:nn', 7, 6), ('dobj', 5, 7)]

#========服务方式调用=========
# 启动服务:java -mx6g -cp "*" edu.stanford.nlp.pipeline.StanfordCoreNLPServer -timeout 5000
from stanfordcorenlp import StanfordCoreNLP
nlp = StanfordCoreNLP('http://localhost', port=9000, lang='zh')
sentence = '斯坦福大学自然语言处理包StanfordNLP'
print(nlp.word_tokenize(sentence))  # 分词
print(nlp.pos_tag(sentence))  # 词性标注
print(nlp.ner(sentence))  # 实体识别
print(nlp.parse(sentence))  # 语法树
print(nlp.dependency_parse(sentence))  # 依存句法

TextBlob——nltk加工

TextBlob是一个用Python编写的开源的文本处理库。是自然语言工具包NLTK的一个包装器,目的是抽象其复杂性。它可以用来执行很多自然语言处理的任务,比如,词性标注,名词性成分提取,情感分析,文本翻译,等等。

主要特性:

  • 名词短语提取
  • 词性标记
  • 情绪分析
  • 分类
  • 由 Google 翻译提供的翻译和检测
  • 标记(将文本分割成单词和句子)
  • 词句、短语频率
  • 解析
  • n-gram
  • 词变化(复数和单数化)和词形化
  • 拼写校正
  • 通过扩展添加新模型或语言
  • WordNet 集成

安装

  • pip install textblob
from textblob import TextBlob
text = 'I love natural language processing! I am not like fish!'
blob = TextBlob(text) # 可能报错,此时需要安装nltk

完整示例

from textblob import TextBlob
from textblob import Word

text = 'I love natural language processing! I am not like fish!'
blob = TextBlob(text)

print(blob.words)  # 分词
print(blob.tags)  # 词性标注
print(blob.noun_phrases)  # 短语抽取

# 分句+计算句子情感值
# 使用TextBlob情感分析的结果,以元组的方式进行返回,形式如(polarity, subjectivity).
# polarity 是一个范围为 [-1.0 , 1.0 ] 的浮点数, 正数表示积极,负数表示消极。
# subjectivity 是一个 范围为 [0.0 , 1.0 ] 的浮点数,其中 0.0 表示 客观,1.0表示主观的。
for sentence in blob.sentences:
    print(sentence + '------>' + str(sentence.sentiment.polarity))

# 词语变形(Words Inflection)
w = Word("apple")
print(w.pluralize())  # 变复数
print(w.pluralize().singularize())  # 变单数

# 词干化(Words Lemmatization)
w = Word('went')
print(w.lemmatize('v'))
w = Word('octopi')
print(w.lemmatize())

# 拼写纠正(Spelling Correction)
sen = 'I lvoe naturl language processing!'
sen = TextBlob(sen)
print(sen.correct())

# 句法分析(Parsing)
text = TextBlob('I lvoe naturl language processing!')
print(text.parse())

# N-Grams
text = TextBlob('I lvoe naturl language processing!')
print(text.ngrams(n=2))

SnowNLP——繁体转换、idf,相似度

SnowNLP是一个python写的类库,可以方便的处理中文文本内容,是受到了TextBlob的启发而写的,由于现在大部分的自然语言处理库基本都是针对英文的,于是写了一个方便处理中文的类库,并且和TextBlob不同的是,这里没有用NLTK,所有的算法都是自己实现的,并且自带了一些训练好的字典。

主要特性:

  • 中文分词(Character-Based Generative Model)
  • 词性标注(TnT3-gram 隐马)
  • 情感分析(现在训练数据主要是买卖东西时的评价,所以对其他的一些可能效果不是很好,待解决)
  • 文本分类(Naive Bayes)
  • 转换成拼音(Trie树实现的最大匹配)
  • 繁体转简体(Trie树实现的最大匹配)
  • 提取文本关键词(TextRank算法)
  • 提取文本摘要(TextRank算法)
  • tf,idf
  • Tokenization(分割成句子)
  • 文本相似(BM25)

安装:

  • pip install snownlp

代码

from snownlp import SnowNLP

s1 = SnowNLP('这个东西真心很赞')
print(s1.words) # ['这个', '东西', '真心', '很', '赞']
print(list(s1.tags)) # [('这个', 'r'), ('东西', 'n'), ('真心', 'd'), ('很', 'd'), ('赞', 'Vg')]
print(s1.sentiments) # 0.9769551298267365
print(s1.pinyin) # ['zhe', 'ge', 'dong', 'xi', 'zhen', 'xin', 'hen', 'zan']

s2 = SnowNLP('「繁體字」「繁體中文」的叫法在臺灣亦很常見。')
print(s2.han) # 「繁体字」「繁体中文」的叫法在台湾亦很常见。

text = '''
自然语言处理是计算机科学领域与人工智能领域中的一个重要方向。
它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。
自然语言处理是一门融语言学、计算机科学、数学于一体的科学。
因此,这一领域的研究将涉及自然语言,即人们日常使用的语言,
所以它与语言学的研究有着密切的联系,但又有重要的区别。
自然语言处理并不是一般地研究自然语言,
而在于研制能有效地实现自然语言通信的计算机系统,
特别是其中的软件系统。因而它是计算机科学的一部分。
'''
s3 = SnowNLP(text)
print(s3.keywords(3)) # ['语言', '自然', '计算机']
print(s3.summary(3)) # ['因而它是计算机科学的一部分', '自然语言处理是计算机科学领域与人工智能领域中的一个重要方向', '自然语言处理是一门融语言学、计算机科学、数学于一体的科学']
print(s3.sentences) # ['自然语言处理是计算机科学领域与人工智能领域中的一个重要方向', '它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法', '自然语言处理是一门融语言学、计算机科学、数学于一体的科学', '因此', '这一领域的研究将涉及自然语言', '即人们日常使用的语言', '所以它与语言学的研究有着密切的联系', '但又有重要的区别', '自然语言处理并不是一般地研究自然语言', '而在于研制能有效地实现自然语言通信的计算机系统', '特别是其中的软件系统', '因而它是计算机科学的一部分']

s4 = SnowNLP([['这篇', '文章'], ['那篇', '论文'], ['这个']])
print(s4.tf) # [{'这篇': 1, '文章': 1}, {'那篇': 1, '论文': 1}, {'这个': 1}]
print(s4.idf) # {'这篇': 0.5108256237659907, '文章': 0.5108256237659907, '那篇': 0.5108256237659907, '论文': 0.5108256237659907, '这个': 0.5108256237659907}
print(s4.sim([u'文章'])) # [0.4686473612532025, 0, 0]

DeepNLP——神经网络版

DeepNLP项目是基于Tensorflow平台的一个python版本的NLP套装, 目的在于将Tensorflow深度学习平台上的模块,结合 最新的一些算法,提供NLP基础模块的支持,并支持其他更加复杂的任务的拓展,如生成式文摘等等。

NLP 套装模块

  • 分词 Word Segmentation/Tokenization:线性链条件随机场 Linear Chain CRF, 基于CRF++包来实现
  • 词性标注 Part-of-speech (POS):单向LSTM/ 双向BI-LSTM, 基于Tensorflow实现
  • 命名实体识别 Named-entity-recognition(NER):单向LSTM/ 双向BI-LSTM/ LSTM-CRF 结合网络, 基于Tensorflow实现
  • 依存句法分析 Dependency Parsing (Parse):基于arc-standard system的神经网络的parser
  • 自动生成式文摘 Textsum (Seq2Seq-Attention)
  • 关键句子抽取 Textrank
  • 文本分类 Textcnn (WIP)
  • 预训练模型:
    • 中文: 基于人民日报语料和微博混合语料: 分词, 词性标注, 实体识别
  • 可调用 Web Restful API
  • 计划中: 句法分析 Parsing
# pip install deepnlp
import deepnlp
# Download all the modules
deepnlp.download()
# Download specific module
deepnlp.download('segment')
deepnlp.download('pos')
deepnlp.download('ner')
deepnlp.download('parse')
# Download module and domain-specific model
deepnlp.download(module = 'pos', name = 'en') 
deepnlp.download(module = 'ner', name = 'zh_entertainment')

示例

from deepnlp import segmenter, pos_tagger, ner_tagger, nn_parser
from deepnlp import pipeline

# 分词模块
tokenizer = segmenter.load_model(name='zh')
text = "我爱吃北京烤鸭"
seg_list = tokenizer.seg(text)
text_seg = " ".join(seg_list)
print(text_seg)

# 词性标注
p_tagger = pos_tagger.load_model(name='zh')
tagging = p_tagger.predict(seg_list)
for (w, t) in tagging:
    pair = w + "/" + t
print(pair)

# 命名实体识别
n_tagger = ner_tagger.load_model(name='zh')  # Base LSTM Based Model
tagset_entertainment = ['city', 'district', 'area']
tagging = n_tagger.predict(seg_list, tagset=tagset_entertainment)
for (w, t) in tagging:
    pair = w + "/" + t
    print(pair)

# 依存句法分析
parser = nn_parser.load_model(name='zh')
words = ['它', '熟悉', '一个', '民族', '的', '历史']
tags = ['r', 'v', 'm', 'n', 'u', 'n']
dep_tree = parser.predict(words, tags)
num_token = dep_tree.count()
print("id\tword\tpos\thead\tlabel")
for i in range(num_token):
    cur_id = int(dep_tree.tree[i + 1].id)
    cur_form = str(dep_tree.tree[i + 1].form)
    cur_pos = str(dep_tree.tree[i + 1].pos)
    cur_head = str(dep_tree.tree[i + 1].head)
    cur_label = str(dep_tree.tree[i + 1].deprel)
    print("%d\t%s\t%s\t%s\t%s" % (cur_id, cur_form, cur_pos, cur_head, cur_label))

# Pipeline
p = pipeline.load_model('zh')
text = "我爱吃北京烤鸭"
res = p.analyze(text)
print(res[0])
print(res[1])
print(res[2])
words = p.segment(text)
pos_tagging = p.tag_pos(words)
ner_tagging = p.tag_ner(words)
print(list(pos_tagging))
print(ner_tagging)

小明NLP——拼写检查、偏旁部首

小明NLP xmnlp的主要功能:

  • 中文分词 & 词性标注
  • 支持繁體
  • 支持自定义词典
  • 中文拼写检查
  • 文本摘要 & 关键词提取
  • 情感分析
  • 文本转拼音
  • 获取汉字偏旁部首
mport xmnlp
print(xmnlp.radical('自然语言处理'))
print(xmnlp.radical('自然語言處理'))

spaCy——(工业界)

spaCy 是一个Python自然语言处理工具包,诞生于2014年年中,号称“Industrial-Strength Natural Language Processing in Python”,是具有工业级强度的Python NLP工具包。spaCy里大量使用了 Cython 来提高相关模块的性能,这个区别于学术性质更浓的NLTK,因此具有了业界应用的实际价值。

主要特性:

  • 分词
  • 命名实体识别
  • 多语言支持(号称支持53种语言)
  • 针对11种语言的23种统计模型
  • 预训练词向量
  • 高性能
  • 轻松的整合深度学习
  • 词性标注
  • 依存句法分析
  • 句法驱动的句子切分
  • 用于语法和命名实体识别的内置可视化工具
  • 方便的字符串到哈希映射
  • 导出到numpy数据数组
  • 高效的二进制序列化
  • 易于模型打包和部署
  • 稳健,精确评估

先执行包的安装:pip install spacy,再执行数据集和模型的下载。

  • 英文:python -m spacy download en_core_web_sm
  • 无官方中文,小道中文版
    • 模型:https://github.com/howl-anderson/Chinese_models_for_SpaCy
    • 执行:pip install ./zh_core_web_sm-2.0.5.tar.gz
import spacy

nlp = spacy.load("en_core_web_sm") # 英文
nlp = spacy.load("zh_core_web_sm") # 中文

doc = nlp("王小明在北京的清华大学读书")
# 分词 词性标注
for token in doc:
    print(token, token.pos_, token.pos)
# 命名实体识别(NER)
for ent in doc.ents:
    print(ent, ent.label_, ent.label)
# 名词短语提取
for np in doc.noun_chunks:
    print(np)
# 依存关系
for token in doc:
    print(token.text, token.dep_, token.head)
# 文本相似度
doc1 = nlp(u"my fries were super gross")
doc2 = nlp(u"such disgusting fries")
similarity = doc1.similarity(doc2)
print(similarity)
# 句法树展示
for token in doc:
    print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
          token.shape_, token.is_alpha, token.is_stop, token.has_vector,
          token.ent_iob_, token.ent_type_,
          token.vector_norm, token.is_oov)
spacy.displacy.serve(doc)

同时启动web服务

复旦FoolNLTK——最准(非最快)的开源中文工具包

FoolNLTK 文章介绍, 复旦大学,一个使用双向 LSTM (BiLSTM 模型)构建的便捷的中文处理工具包,该工具不仅可以实现分词、词性标注和命名实体识别,同时还能使用用户自定义字典加强分词的效果。根据该项目所述,这个中文工具包可能不是最快的开源中文分词,但很可能是最准的开源中文分词。

  • 基于神经网络的方法,往往使用「字向量 + 双向 LSTM + CRF」模型,利用神经网络来学习特征,将传统 CRF 中的人工特征工程量将到最低。

使用示例:

# pip install tensorflow==1.15 # tf版本限制
import fool
sentence = "中文分词测试:我爱北京天安门"
print(fool.cut(sentence))  # 分词, [['中文', '分词', '测试', ':', '我', '爱', '北京', '天安', '门']]
print(fool.pos_cut(sentence))  # 词性标注, [[('中文', 'nz'), ('分词', 'n'), ('测试', 'n'), (':', 'wm'), ('我', 'r'), ('爱', 'v'), ('北京', 'ns'), ('天安', 'nz'), ('门', 'n')]]
print(fool.analysis(sentence)[1]) # 明名实体识别, [[(9, 15, 'company', '北京天安门')]]

HanLP——支持TensorFlow 2

  • 借助世界上最大的多语种语料库,HanLP支持包括简繁中英日俄法德在内的104种语言上的10种联合任务:分词(粗分、细分2个标准,强制、合并、校正3种词典模式)、词性标注(PKU、863、CTB、UD四套词性规范)、命名实体识别(PKU、MSRA、OntoNotes三套规范)、依存句法分析(SD、UD规范)、成分句法分析、语义依存分析(SemEval16、DM、PAS、PSD四套规范)、语义角色标注、词干提取、词法语法特征提取、抽象意义表示(AMR)。
  • HanLP已经被广泛用于Lucene、Solr、ElasticSearch、Hadoop、Android、Resin等平台,有大量开源作者开发各种插件与拓展,并且被包装或移植到Python、C#、R、JavaScript等语言上去。 基于深度学习的HanLP2.x已于2020年初发布,面向下一个十年的前沿NLP技术,与1.x相辅相成,平行发展。

HanLP原先是一个JAVA版本的自然语言处理工具包,在目前的升级中已经支持了Python。当前已经支持基于 TensorFlow 2.x。HanLP具备功能完善、性能高效、架构清晰、语料时新、可自定义的特点。特殊功能:

  • 短语提取
  • 拼音转换
  • 繁简转换
  • 文本推荐

Demo 体验

官方体验地址

代码调用

# https://github.com/hankcs/pyhanlp
from pyhanlp import *

sen = '贝壳和链家什么关系,左晖和stanly又是谁'
CustomDictionary.add("链家", "n") # 自定义字典
# 加载模型
NLPTokenizer = pyhanlp.JClass('com.hankcs.hanlp.tokenizer.NLPTokenizer')  # 加载模型
NER = NLPTokenizer.segment(text)  # 命名实体识别

res = HanLP.segment(sen) # pos
for term in res:
    print(term, term.word, str(term.nature))
res = HanLP.extractKeyword(sen, 10)
print(res)
summary  = HanLP.extractSummary(sen, 5)
print(summary)
print('分词:', HanLP.segment(sen))
#TextRankKeyword = JClass("com.hankcs.hanlp.summary.TextRankKeyword")
print('关键词:', HanLP.extractKeyword(sen, 2))
print('自动摘要:', HanLP.extractSummary(sen, 3))
sentence_list = HanLP.getSummary(sen, 50)  #提取短语,同时指定摘要的最大长度 
print('自动摘要:', sentence_list)
NER=HanLP.newSegment().enableNameRecognize(True)
print('中文名识别:', NER.seg(sen))
person_ner = HanLP.newSegment().enableTranslatedNameRecognize(True)
print('英文名识别:', person_ner.seg(sen))
print('句法分析:', HanLP.parseDependency(sen))
PerceptronLexicalAnalyzer=JClass('com.hankcs.hanlp.model.perceptron.PerceptronLexicalAnalyzer')
analyzer=PerceptronLexicalAnalyzer()
print('感知机句法分析:', analyzer.analyze(sen))
print('短语提取:', HanLP.extractPhrase(sen, 5))
print('简体:', HanLP.convertToSimplifiedChinese("我愛自然語言處理技術!"))
print('繁体:', HanLP.convertToTraditionalChinese("我爱自然语言处理技术!"))
pinyinList = HanLP.convertToPinyinList(sen)
for pinyin in pinyinList:
    print(pinyin.getPinyinWithoutTone(),pinyin.getTone(), pinyin, pinyin.getPinyinWithToneMark())
# 可视化服务:shell命令
hanlp serve  # http://localhost:8765
# 命令行方式传入
hanlp segment <<< '欢迎新老师生前来就餐' 

CRF工具包

CRF++工具包,CRF++: Yet Another CRF toolkit

(1)编译安装

步骤:python调用CRF++工具包

# 拉取github上的源文件
git clone https://github.com/taku910/crfpp.git
cd crfpp

# 去除找不到winmain.h的错误 [2021-7-15] sed命令有误,手工删除winmain引用即可
sed -i '/#include "winmain.h"/d' crf_test.cpp
sed -i '/#include "winmain.h"/d' crf_learn.cpp

# 编译安装
./configure
make && make install

# 配置文件并导入,消除【错误2】 【2021-7-15】mac下没有ld.so.conf文件
echo "include /usr/local/lib" >> /etc/ld.so.conf
/sbin/ldconfig -v
# 导入python
cd python
python3 setup.py install

(2)直接安装

命令:

  • pip install crfpy

使用

  • 训练模型
    • crf_learn template train.data model
  • 测试使用
import CRFPP
import codecs

# 加载模型
tagger=CRFPP.Tagger(r'-m C:\Users\secoo\Desktop\CRF++\model')

# 加载测试文件
input_data = codecs.open(r'C:\Users\secoo\Desktop\CRF++\shangde.txt', 'r', 'utf-8')
word_str=input_data.readlines()
word_str=''.join(word_str)
# 测试
print(tagger.parse(word_str))

python工具包

  • 【2021-1-19】python高效使用统计语言模型kenlm:新词发现、分词、智能纠错等
  • kenlm的优点(关于kenlm工具训练统计语言模型): 训练语言模型用的是传统的“统计+平滑”的方法,使用kenlm这个工具来训练。它快速,节省内存,最重要的是,允许在开源许可下使用多核处理器。 kenlm是一个C++编写的语言模型工具,具有速度快、占用内存小的特点,也提供了Python接口。
  • 额外需要加载的库:
    • kenlm
    • pypinyin
    • pycorrector
  • 粗略整理代码:
  • kenlm模型训练,详见地址
    • 文件必须是分词以后的文件。
    • -o后面的5表示的是5-gram,一般取到3即可,但可以结合自己实际情况判断
# 训练命令
bin/lmplz -o 5 --verbose_header --text data/chat_log.txt --arpa result/log.arpa --vocab_file result/log.vocab
# 结果后得到arpa文件

kenlm模式

import kenlm
model = kenlm.Model('lm/test.arpa')
print(model.score('this is a sentence .', bos = True, eos = True))
# 豆瓣语料模型
model = kenlm.Model('build/my_model/douban.arpa')
test_list = ["我是一名程序员",    "是一名程序员我",    "我 是 一名 程序员",    "是 一名 程序员 我",    "一名 是 程序员 我",    "一名 程序员 是 我",    "我 我 我 啊 嗯 你 一名 是 吗 噢噢 程序员 是 吗 我",    "我 等一下 去 交 进去 的 觉得 我 不卡 我 要 能 给我 媳妇 上 了 取得 这样的 他 方便 一点 他 就 觉得 9个人 要 办个 手续 这样 的"]
for i in test_list:
   time_start = time.time()
   print(i, ': ', model.score(i, bos=True, eos=True), 'time: ', time.time() - time_start)
# 结果见下图

#Stateful query 状态转移概率
state = kenlm.State()
state2 = kenlm.State()
#Use <s> as context.  If you don't want <s>, use model.NullContextWrite(state).
model.BeginSentenceWrite(state)

示例:

pypinyin拼音模块

  • 拼音模块涉及到了pypinyin,用来识别汉字的拼音,还有非常多种的模式:
from pypinyin import lazy_pinyin, Style
	# Python 中拼音库 PyPinyin 的用法
	# https://blog.csdn.net/devcloud/article/details/95066038

tts = ['BOPOMOFO', 'BOPOMOFO_FIRST', 'CYRILLIC', 'CYRILLIC_FIRST', 'FINALS', 'FINALS_TONE',
 'FINALS_TONE2', 'FINALS_TONE3', 'FIRST_LETTER', 'INITIALS', 'NORMAL', 'TONE', 'TONE2', 'TONE3']
for tt in tts:
    print(tt,lazy_pinyin('聪明的小兔子吃', style=eval('Style.{}'.format(tt))   ))

pinyin('中心') # [['zhōng'], ['xīn']]
pinyin('中心', heteronym=True)  # 启用多音字模式,[['zhōng', 'zhòng'], ['xīn']]
pinyin('中心', style=Style.FIRST_LETTER)  # 设置拼音风格,[['z'], ['x']]
pinyin('中心', style=Style.TONE2, heteronym=True)[['zho1ng', 'zho4ng'], ['xi1n']]
pinyin('中心', style=Style.BOPOMOFO)  # 注音风格,[['ㄓㄨㄥ'], ['ㄒㄧㄣ']]
pinyin('中心', style=Style.CYRILLIC)  # 俄语字母风格,[['чжун1'], ['синь1']]
lazy_pinyin('中心')  # 不考虑多音字的情况,['zhong', 'xin']

其中结果为:

BOPOMOFO ['ㄘㄨㄥ', 'ㄇㄧㄥˊ', 'ㄉㄜ˙', 'ㄒㄧㄠˇ', 'ㄊㄨˋ', 'ㄗ˙', 'ㄔ']
BOPOMOFO_FIRST ['ㄘ', 'ㄇ', 'ㄉ', 'ㄒ', 'ㄊ', 'ㄗ', 'ㄔ']
CYRILLIC ['цун1', 'мин2', 'дэ', 'сяо3', 'ту4', 'цзы', 'чи1']
CYRILLIC_FIRST ['ц', 'м', 'д', 'с', 'т', 'ц', 'ч']
FINALS ['ong', 'ing', 'e', 'iao', 'u', 'i', 'i']
FINALS_TONE ['ōng', 'íng', 'e', 'iǎo', 'ù', 'i', 'ī']
FINALS_TONE2 ['o1ng', 'i2ng', 'e', 'ia3o', 'u4', 'i', 'i1']
FINALS_TONE3 ['ong1', 'ing2', 'e', 'iao3', 'u4', 'i', 'i1']
FIRST_LETTER ['c', 'm', 'd', 'x', 't', 'z', 'c']
INITIALS ['c', 'm', 'd', 'x', 't', 'z', 'ch']
NORMAL ['cong', 'ming', 'de', 'xiao', 'tu', 'zi', 'chi']
TONE ['cōng', 'míng', 'de', 'xiǎo', 'tù', 'zi', 'chī']
TONE2 ['co1ng', 'mi2ng', 'de', 'xia3o', 'tu4', 'zi', 'chi1']
TONE3 ['cong1', 'ming2', 'de', 'xiao3', 'tu4', 'zi', 'chi1']

可以看出不同的style可以得到不同拼音形式。

命令行工具:

pypinyin 音乐 # yīn yuè
pypinyin -h
pypinyin '银行,行道树,人行道'  # yín háng , háng dào shù , rén xíng dào

pycorrector纠错模块

  • pycorrector的detect,可以返回,错误字的信息
import pycorrector

sentence = '这瓶洗棉奶用着狠不错'
idx_errors = pycorrector.detect(sentence)
# [['这瓶', 0, 2, 'word'], ['棉奶', 3, 5, 'word']]
#correct是专门用来纠正:
pycorrector.correct(sentence)
  • pycorrector与kenlm纠错对比
  • 来对比一下pycorrector自带的纠错和本次实验的纠错:
import pycorrector
sentence = '这瓶洗棉奶用着狠不错'
idx_errors = pycorrector.detect(sentence)

correct = []
for ide in idx_errors:
    right_word = km.find_best_word(ide[0],ngrams_,freqs = 0)
    if right_word != ide[0]:
        correct.append([right_word] + ide)

print('错误:',idx_errors)
print('pycorrector的结果:',pycorrector.correct(sentence))
print('kenlm的结果:',correct)

错误: [[‘这瓶’, 0, 2, ‘word’], [‘棉奶’, 3, 5, ‘word’]] pycorrector的结果: (‘这瓶洗面奶用着狠不错’, [[‘棉奶’, ‘面奶’, 3, 5]]) kenlm的结果: [[‘面奶’, ‘棉奶’, 3, 5, ‘word’]]

其他类似的案例:

sentence = ‘少先队员因该给老人让坐’

错误: [[‘因该’, 4, 6, ‘word’], [‘坐’, 10, 11, ‘char’]] pycorrector的结果: (‘少先队员应该给老人让座’, [[‘因该’, ‘应该’, 4, 6], [‘坐’, ‘座’, 10, 11]]) kenlm的结果: [[‘应该’, ‘因该’, 4, 6, ‘word’]] 这里笔者的简陋规则暴露问题了,只能对2个字以上的进行判定。

sentence = ‘绿茶净华可以舒缓痘痘机肤’

错误: [[‘净华’, 2, 4, ‘word’], [‘机肤’, 10, 12, ‘word’]] pycorrector的结果: (‘绿茶净化可以舒缓痘痘肌肤’, [[‘净华’, ‘净化’, 2, 4], [‘机肤’, ‘肌肤’, 10, 12]]) kenlm的结果: [[‘精华’, ‘净华’, 2, 4, ‘word’], [‘肌肤’, ‘机肤’, 10, 12, ‘word’]]

nlp教程 Curriculum - (Example Purpose)

nlp-tutorial

nlp-tutorial is a tutorial for who is studying NLP(Natural Language Processing) using TensorFlow and Pytorch. Most of the models in NLP were implemented with less than 100 lines of code.(except comments or blank lines)

文本分类 (每个模型内部使用optuna进行调参)

1. 基础嵌入模型 Basic Embedding Model

词向量

神经网络语言模型

2. CNN(Convolutional Neural Network)

CNN家族在文本分类比较出名的就是Kim的 TextCNN 和kaiming的 DPCN

3. RNN(Recurrent Neural Network)

4. 注意力 Attention Mechanism

5. Model based on Transformer

Model Example Framework Lines(torch/tensor)
NNLM Predict Next Word Torch, Tensor 67/83
Word2Vec(Softmax) Embedding Words and Show Graph Torch, Tensor 77/94
TextCNN Sentence Classification Torch, Tensor 94/99
TextRNN Predict Next Step Torch, Tensor 70/88
TextLSTM Autocomplete Torch, Tensor 73/78
Bi-LSTM Predict Next Word in Long Sentence Torch, Tensor 73/78
Seq2Seq Change Word Torch, Tensor 93/111
Seq2Seq with Attention Translate Torch, Tensor 108/118
Bi-LSTM with Attention Binary Sentiment Classification Torch, Tensor 92/104
Transformer Translate Torch 222/0
Greedy Decoder Transformer Translate Torch 246/0
BERT how to train Torch 242/0

Dependencies

  • Python 3.5+
  • Tensorflow 1.12.0+
  • Pytorch 0.4.1+
  • Plan to add Keras Version

应用

项目实战

  • 【2020-6-2】京东AI项目实战课:五个阶段从理论到实践、从项目实战到面试准备的一站式教学,涵盖NLP领域核心技能(特征工程、分类模型、语法树等),前沿技术(BERT、XLNet、Seq2Seq、Transformer、ALBERT、模型蒸馏、模型压缩等);

资料

结束


支付宝打赏 微信打赏

~ 海内存知已,天涯若比邻 ~

Share

Similar Posts

Related Posts

下一篇 分词算法

标题:对话系统之对话管理器-Dialogue Manager

摘要:对话管理器技术总结

标题:分词算法

摘要:NLP分词方法汇总

Comments

--disqus--

    My Moment ( 微信公众号 )
    欢迎关注鹤啸九天