washer fluid only

2024-05-0702:41:43综合资讯0

项目地址:https://github.com/baidu/lac

项目简介

LAC是一个联合词法分析模型,集成了中文分词、词性标注、专名识别这三个任务。LAC既可以看做是Lexical Analysis of Chinese的首字母缩写,也可以理解为LAC Analyzes Chinese的递归缩写。

LAC基于堆叠的双向GRU结构,在长文本上准确复刻了百度AI开放平台的词法分析算法。效果方面,分词、词性、专名识别的整体准确率达到95.5%;单独评估专名识别任务,F值达87.1%(准确率90.3%,召回率85.4%),总体略高于开放平台版本。在效果优化的基础上,LAC的模型结构简洁高效,内存开销小于100M,处理速度比百度AI开放平台提高了57%。

任务定义与建模

词法分析任务的输入是文本(以下称之为句子),输出是句子中的词边界及其对应的词性、实体类别。序列标注是词法分析的经典建模方式。我们使用基于GRU的网络结构学习输入文本的特征,并将其导入CRF解码层进行序列标注。CRF解码层本质上是将传统CRF中的线性模型替换为非线性神经网络,基于句子级别的似然概率进行解码,这有助于解决标记偏置问题。以下列出模型的要点,具体细节请参考python/train.py代码。

  1. 以one-hot方式表示输入,每个字用一个ID表示;
  2. 通过字表将one-hot序列转换为实向量表示的字向量序列;
  3. 将字向量序列作为双向GRU的输入,学习输入序列的特征表示,得到新的特性表示序列。我们堆叠了两层双向GRU以增强学习能力;
  4. CRF以GRU学习到的特征为输入,以标记序列为监督信号,实现序列标注。

词性和专名类别标签集合如下表,其中词性标签24个(小写字母),专名类别标签4个(大写字母)。需要说明的是,人名、地名、机构名和时间这四个类别,在上表中存在两套标签(PER / LOC / ORG / TIME 和 nr / ns / nt / t),被标记为第二套标签的词,是模型判断为低置信度的人名、地名、机构名和时间词。开发者可以根据这两套标签,在四个类别的准确率和召回率之间做出取舍。

标签含义标签含义标签含义标签含义n普通名词f方位名词s处所名词t时间nr人名ns地名nt机构名nw作品名nz其他专名v普通动词vd动副词vn名动词a形容词ad副形词an名形词d副词m数量词q量词r代词p介词c连词u助词xc其他虚词w标点符号PER人名LOC地名ORG机构名TIME时间

数据格式

训练数据由用户根据实际应用场景组织。数据由两列组成,以制表符分隔。第一列是utf-8编码的中文文本,第二列是对应每个字的标注,以空格分隔。我们采用IOB2标注体系,即以X-B作为类型为X的词的开始,以X-I作为类型为X的词的持续,以O表示不关注的字(事实上,词性、专名联合标注中不存在O)。示例如下:

  • 我们提供了一个完全版的模型以及相关的依赖数据。但由于训练数据量庞大,我们没有发布训练数据,仅在data目录下的train_data和test_data文件中放置少数样本,用于展示输入数据格式。
  • 模型依赖数据包括:
  1. 输入文本的词典,在conf目录下,对应word.dic
  2. 输入文本中特殊字符转换的词典,在conf目录下,对应q2b.dic
  3. 标记标签的词典,在conf目录下,对应tag.dic
  • 在训练和预测阶段,需要进行原始数据的预处理,包括:
  1. 从原始数据文件中抽取句子和标签,构造句子序列和标签序列;
  2. 转换句子序列中的特殊字符;
  3. 根据词典获取词对应的整数索引。
  • 在训练阶段,这些工作由python/train.py调用python/reader.py完成;在预测阶段,由C++代码完成。

安装LAC

安装Paddle

Paddle可以在符合要求的原生Linux环境或docker环境下编译,编译依赖请参考安装文档。对于docker环境,我们建议基于Paddle的Dockerfile构建镜像。

如果Paddle官方发布了符合机器运行环境的镜像,也可以选用,省去以下步骤的工作。

无论是官方镜像还是基于源码的默认编译命令,都不包含Fluid预测库。Fluid预测库的安装需要单独进行(见以下第五步)。

第一步,克隆Paddle代码并切换到v0.14.0版本

注意,当前v0.14.0版本如果开启mkldnn支持,会出现Segmentation Fault。这个问题在后续版本中可能得到修复。在此之前,请在关闭mkldnn支持的情况下编译,具体方法如下。

第二步(可选),构建docker镜像

对于非Linux环境(macOS、Windows),需要构建Paddle的docker镜像用于Paddle的编译和运行(主要是预测部分)。在Linux环境下,也可以选择构建镜像。

Paddle的docker镜像依赖Ubuntu基础镜像,大量软件包基于apt-get安装,因此可以配置Ubuntu镜像以加速这一过程。

第三步,编译Paddle基础库

这一步将产生Paddle的基础库以及python版的wheel包。

如前所述,v0.14.0版本需要关闭mkldnn库的支持。我们直接使用cmake命令完成编译。

编译过程中,与LAC密切相关的几个常用参数如下表所示。WITH_AVX和WITH_MKL选项会根据CPU的检测结果由cmake自动设定,其余参数如果需要设为默认值以外的值,需要手动指定。具体细节可以参考CMakeLists.txt。

选项说明默认值WITH_GPU如果需要CPU环境,请设为OFF。本文档中,LAC是基于CPU环境编译的。ONWITH_FLUID_ONLY仅编译Fluid API,建议设为ON。OFFWITH_AVX是否编译含有AVX指令集的二进制文件,较新的CPU都支持AVX指令集。自动WITH_MKL是否使用MKL数学库,如果为否则使用OpenBLAS。该选项与WITH_AVX绑定,如果WITH_AVX为ON,WITH_MKL也为ON。如果CPU支持AVX2指令集,还会引入Intel的mkldnn库,除非显式设定WITH_MKLDNN为OFF。自动

第四步,安装python包

更多安装细节,如升级现有包等操作,请参考安装文档。

第五步,编译Fluid预测库

Fluid预测库不包含在默认的官方镜像和源码编译产出中,需要单独编译。

Paddle官方也在维护Fluid预测库的预编译包,请看这里。如果有符合机器运行环境的预编译包,也可以尝试直接选用。

在第三步的make成功后,直接继续执行:

基于cmake直接编译时,Fluid预测库的编译产出会生成在build/fluid_install_dir目录。您可以将其拷贝到您喜欢的位置。

如果您使用的是自带基础库和Python包的Paddle官方镜像,或者由于其他原因不需要安装基础库和Python包,那么在第三步的cmake命令之后,直接make -j <num_cpu_cores> inference_lib_dist即可。

编译LAC

LAC依赖Paddle的Fluid预测库。编译、运行环境与Paddle相关环境保持一致,以避免出现意外。LAC本身的编译操作相对简单:

运行LAC

训练部分

训练过程使用python实现。

  1. 准备好数据和字典。请将训练数据放在一个目录下,测试数据放在另一个目录下。如果有多份不同类型的训练语料,可以在训练目录下使用不同的前缀来区分不同的训练数据,比如使用novel_xxx表示小说类的训练语料,使用news_xxx表示新闻类的训练预料,训练支持同时按照一定的比例混合输入各种不同类型的语料。
  2. 查看训练支持的不同选项的含义,可以使用
  1. 查看训练脚本支持的不同选项,通过设置不同的选项,对训练进行定制化。其中以下选项可能较为常用:
  1. 运行命令 python python/train.py ,需要注意:直接运行使用

    鉴于分词、词性标注和专名识别通常作为其他模块的基础依赖,本文提供了 C 语言预测接口,方便用户轻松利用这些功能。

    词性名称、专名类别名称和自定义类别名称的长度限制为 32 个字节。模块内置的词性名称和专名类别名称长度不超过此值,自定义类别名称也不得超过此长度,否则字典加载将失败。

    输出结构中,offsetlength 分别表示该词在输入查询中的字节偏移量和长度,type 表示词的标注类别,type_confidence 表示类别置信度(当前统一为 1)。

    预测流程如下所示:

    1. 初始化,加载字典和模型
    2. 初始化线程变量
    3. 执行预测,获取结果
    4. 释放资源

    示例程序:

    output/demo/lac_demo 是一个多线程演示程序,源代码请参见 test/src/lac_demo.cpp。演示程序的使用方式如下:

    程序从标准输入逐行读取句子,然后给出句子的分析结果。

    示例输入:

    示例输出:

    输出格式为:

    自定义功能:

    基于模型输出的结果,LAC 还支持用户配置自定义专名类型输出。当自定义专名词出现在输入查询中时,如果该词与原始词法分析结果不存在边界冲突,则将用自定义专名类型替换原始标签。修改 conf/customization.dic 即可配置自定义专名。专名类型对应的词写在类型名称下方,专名名称形如 [D:XXX]。例如:

    以输入查询“春天的花开秋天的风以及冬天的落阳”为例,原始输出结果为:

    添加自定义专名后的结果为:

    可见,“春天”“秋天”“冬天”的类别已更改为 [D:season],“风”的类别已更改为 [D:wind]。而自定义专名词“花”虽然出现在输入查询中,但由于其与原始结果“花开”存在边界冲突,因此不会被识别。