标签归档:中文分词

百度 LAC 2.0 极速体验,这是一个值得拥有的中文词法分析工具

关于中文词法分析(中文分词、词性标注、命名实体识别)相关的工具,我们在之前已经多次提到过百度LAChttps://github.com/baidu/lac),除了在易用性上稍弱外,其他方面,特别是NER在横向对比中还是很亮眼的。最近百度NLP发布了LAC2.0:开源!我知道你不知道,百度开源词法LAC 2.0帮你更懂中文,看完文章的第一感受就是易用性大大加强了,之前需要通过PaddleNLP或者PaddleHub调用lac,现在 "pip install lac" 后即可直接调用,相当方便。所以花了一点时间,把 LAC2.0 单独作为一个接口部署在AINLP公众号的自然语言处理工具测试平台了,感兴趣的同学可以关注AINLP公众号,通过公众号对话测试,输入"LAC 中文文本"直接获取百度LAC的中文文词、词性标注、NER识别结果:

关于百度LAC,首先看一下官方主页的介绍:

LAC全称Lexical Analysis of Chinese,是百度自然语言处理部研发的一款联合的词法分析工具,实现中文分词、词性标注、专名识别等功能。该工具具有以下特点与优势:

效果好:通过深度学习模型联合学习分词、词性标注、专名识别任务,整体效果F1值超过0.91,词性标注F1值超过0.94,专名识别F1值超过0.85,效果业内领先。
效率高:精简模型参数,结合Paddle预测库的性能优化,CPU单线程性能达800QPS,效率业内领先。
可定制:实现简单可控的干预机制,精准匹配用户词典对模型进行干预。词典支持长片段形式,使得干预更为精准。
调用便捷:支持一键安装,同时提供了Python、Java和C++调用接口与调用示例,实现快速调用和集成。
支持移动端: 定制超轻量级模型,体积仅为2M,主流千元手机单线程性能达200QPS,满足大多数移动端应用的需求,同等体积量级效果业内领先。

LAC 2.0 的使用还是很方便的,官方文档很清晰,可以直接参考,以下是在 Ubuntu 16.04, Python 3.6.8 环境下安装测试,这里是在 virtualenv 虚拟环境下通过 pip install lac 安装,安装完成后可以在命令行中直接输入lac进行体验:

(venv) textminer@textminer:~/nlp_tools/baidu_lac$ lac
我爱自然语言处理
我/r 爱/v 自然语言处理/nz
百度LAC是一个中文词法分析工具
百度/ORG LAC/nz 是/v 一个/m 中文/nz 词法/n 分析/vn 工具/n
习近平致信祝贺哈尔滨工业大学建校100周年
习近平/PER 致信/v 祝贺/v 哈尔滨工业大学/ORG 建校/v 100周年/m
新华社北京67日电  中共中央总书记、国家主席、中央军委主席习近平7日致信祝贺哈尔滨工业大学建校100周年,向全校师生员工和校友致以热烈的祝贺和诚挚的问候。
新华社/ORG 北京/LOC 67日/TIME 电/n  /w  /w 中共中央/ORG 总书记/n 、/w 国家主席/n 、/w 中央军委/ORG 主席/n 习近平/PER 7日/TIME 致信/v 祝贺/v 哈尔滨工业大学/ORG 建校/v 100周年/m ,/w 向/p 全校/n 师生/n 员工/n 和/c 校友/n 致以/v 热烈/a 的/u 祝贺/vn 和/c 诚挚/a 的/u 问候/vn 。/w

如果只需要测试中文分词结果,输入'lac --segonly'即可。LAC的代码调用也很方便:

(venv) textminer@textminer:~/nlp_tools/baidu_lac$ ipython
Python 3.6.8 (default, May  7 2019, 14:58:50) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.15.0 -- An enhanced Interactive Python. Type '?' for help.
 
In [1]: from LAC import LAC                                                                            
 
# 如果只需要中文分词功能,设置'seg'模式,加载中文分词模型
In [2]: lac = LAC(mode='seg')                                                                          
 
# 单个样本调用
In [3]: text = '我爱自然语言处理'                                                                      
 
In [4]: result = lac.run(text)                                                                         
 
In [5]: print(result)                                                                                  
['我', '爱', '自然语言处理']
 
# 批量样本调用
In [6]: texts = ['我爱自然语言处理', '百度LAC是一个不错的中文词法分析工具', 'AINLP@我爱自然语言处理']  
 
In [7]: result = lac.run(texts)                                                                        
 
In [8]: print(result)                                                                                 
[['我', '爱', '自然语言处理'], ['百度', 'LAC', '是', '一个', '不错', '的', '中文', '词', '法', '分析', '工具'], ['AINLP', '@', '我', '爱', '自然语言处理']]

如果需要使用LAC的词性标注与命名实体识别功能,可以调用的时候设置为'lac'模式,加载LAC模型:

In [11]: lac = LAC(mode='lac')                                                                         
 
In [12]: text = '我爱自然语言处理'                                                                     
 
In [13]: result = lac.run(text)                                                                        
 
In [14]: print(result)                                                                                 
[['我', '爱', '自然语言处理'], ['r', 'v', 'nz']]
 
In [15]: texts = ['我爱哈尔滨工业大学', '2020年6月7日哈工大迎来百年校庆']                              
 
In [16]: result = lac.run(texts)                                                                       
 
In [17]: print(result)                                                                                 
[[['我', '爱', '哈尔滨工业大学'], ['r', 'v', 'ORG']], [['2020年6月7日', '哈工大', '迎来', '百年', '校庆'], ['TIME', 'ORG', 'v', 'm', 'n']]]

这里的输出格式为(word_list, tags_list),对应每个句子的切词结果word_list和每个词的对应词性标注的tags_list,其所用的词性标记集如下,包括4个常用的专名类别(PER, LOC, ORG, TIME):

此外,LAC的词典定制化和模型增量训练功能也相当友好,这对于有在实际业务需求的团队就非常有帮助,可以基于自己的业务需求和领域词典数据定制一个面向自身业务的中文词法分析模型,以下以词典定制化为例,我们添加了一个自定义词典 mydict.txt, 内容如下:

锦江石材/ORG
正式成立

以下是加载自定义词典前后的结果对比:

In [24]: text = "锦江石材正式成立了"                                                                   
 
In [25]: result = lac.run(text)                                                                        
# 没有干预的结果
In [26]: print(result)                                                                                 
[['锦江', '石材', '正式', '成立', '了'], ['LOC', 'n', 'ad', 'v', 'xc']]
 
In [27]: lac.load_customization('mydict.txt')                                                          
 
In [28]: result = lac.run(text)                                                                        
 
# 干预后的结果
In [29]: print(result)                                                                                 
[['锦江石材', '正式成立', '了'], ['ORG', 'v', 'xc']]

至于模型增量训练,留给感兴趣的同学自己尝试了,这个功能很有用,可以参考LAC官方文档说明,很清晰。

最后需要说明一下本文主要参考了百度LAC的官方文档:
https://github.com/baidu/lac

关于LAC2.0的更详细介绍,可以参考:
开源!我知道你不知道,百度开源词法LAC 2.0帮你更懂中文

我们之前写得三篇关于百度NLP工具的相关文章,也可以对比参考和测试LAC1.x版本:

百度深度学习中文词法分析工具LAC试用之旅
来,试试百度的深度学习情感分析工具
中文命名实体识别工具(NER)哪家强?

中文命名实体识别工具(NER)哪家强?

自去年以来,在AINLP公众号上陆续给大家提供了自然语言处理相关的基础工具的在线测试接口,使用很简单,关注AINLP公众号,后台对话关键词触发测试,例如输入 “中文分词 我爱自然语言处理”,“词性标注 我爱NLP”,“情感分析 自然语言处理爱我","Stanza 52nlp" 等,具体可参考下述文章:

五款中文分词工具在线PK: Jieba, SnowNLP, PkuSeg, THULAC, HanLP
中文分词工具在线PK新增:FoolNLTK、LTP、StanfordCoreNLP
Python中文分词工具大合集:安装、使用和测试
八款中文词性标注工具使用及在线测试
百度深度学习中文词法分析工具LAC试用之旅
来,试试百度的深度学习情感分析工具
AINLP公众号新增SnowNLP情感分析模块
斯坦福大学NLP组Python深度学习自然语言处理工具Stanza试用

既然中文分词、词性标注已经有了,那下一步很自然想到的是命名实体识别(NER,Named-entity recognition)工具了,不过根据我目前了解到的情况,开源的中文命名实体工具并不多,这里主要指的是一些成熟的自然语言处理开源工具,不是github上一些学习性质的代码。目前明确有NER标记的包括斯坦福大学的NLP组的Stanza,百度的Paddle Lac,哈工大的LTP,而其他这些测试过的开源NLP基础工具,需要从词性标注结果中提取相对应的专有名词,也算是一种折中方案。

在之前这些可测的工具中,除了斯坦福大学的Stanza和CoreNLP有一套词性标记外,LTP使用的是863词性标注集,其他包括Jieba,SnowNLP,PKUSeg,Thulac,HanLP,FoolNLTK,百度Lac等基础工具的词性标注集主要是以人民日报标注语料中的北京大学词性标注集(40+tags)为蓝本:

代码 名称 帮助记忆的诠释
Ag 形语素 形容词性语素。 形容词代码为 a ,语素代码 g 前面置以 A。
a 形容词 取英语形容词 adjective 的第 1 个字母。
ad 副形词 直接作状语的形容词。 形容词代码 a 和副词代码 d 并在一起。
an 名形词 具有名词功能的形容词。 形容词代码 a 和名词代码 n 并在一起。
b 区别词 取汉字“别”的声母。
c 连词 取英语连词 conjunction 的第 1 个字母。
Dg 副语素 副词性语素。 副词代码为 d ,语素代码 g 前面置以 D。
d 副词 取 adverb 的第 2 个字母 ,因其第 1 个字母已用于形容词。
e 叹词 取英语叹词 exclamation 的第 1 个字母。
f 方位词 取汉字“方” 的声母。
g 语素 绝大多数语素都能作为合成词的“词根”,取汉字“根”的声母。 由于实际标注时 ,一定
标注其子类 ,所以从来没有用到过 g。
h 前接成分 取英语 head 的第 1 个字母。
i 成语 取英语成语 idiom 的第 1 个字母。
j 简称略语 取汉字“简”的声母。
k 后接成分
l 习用语 习用语尚未成为成语 ,有点“临时性”,取“临”的声母。
m 数词 取英语 numeral 的第 3 个字母 ,n ,u 已有他用。
Ng 名语素 名词性语素。 名词代码为 n ,语素代码 g 前面置以 N。
n 名词 取英语名词 noun 的第 1 个字母。
nr 人名 名词代码 n 和“人(ren) ”的声母并在一起。
ns 地名 名词代码 n 和处所词代码 s 并在一起。
nt 机构团体 “团”的声母为 t,名词代码 n 和 t 并在一起。
nx 非汉字串
nz 其他专名 “专”的声母的第 1 个字母为 z,名词代码 n 和 z 并在一起。
o 拟声词 取英语拟声词 onomatopoeia 的第 1 个字母。
p 介词 取英语介词 prepositional 的第 1 个字母。
q 量词 取英语 quantity 的第 1 个字母。
r 代词 取英语代词 pronoun 的第 2 个字母,因 p 已用于介词。
s 处所词 取英语 space 的第 1 个字母。
Tg 时语素 时间词性语素。时间词代码为 t,在语素的代码 g 前面置以 T。
t 时间词 取英语 time 的第 1 个字母。
u 助词 取英语助词 auxiliary 的第 2 个字母,因 a 已用于形容词。
Vg 动语素 动词性语素。动词代码为 v。在语素的代码 g 前面置以 V。
v 动词 取英语动词 verb 的第一个字母。
vd 副动词 直接作状语的动词。动词和副词的代码并在一起。
vn 名动词 指具有名词功能的动词。动词和名词的代码并在一起。
w 标点符号
x 非语素字 非语素字只是一个符号,字母 x 通常用于代表未知数、符号。
y 语气词 取汉字“语”的声母。
z 状态词 取汉字“状”的声母的前一个字母。

其中HanLp增加了更细粒度的词性标注集,具体可参考:https://www.hankcs.com/nlp/part-of-speech-tagging.html

HanLP使用的HMM词性标注模型训练自2014年人民日报切分语料,随后增加了少量98年人民日报中独有的词语。所以,HanLP词性标注集兼容《ICTPOS3.0汉语词性标记集》,并且兼容《现代汉语语料库加工规范——词语切分与词性标注》。

另外百度词法分析工具Lac使用的词性标注集中特别加了一套强相关的专名类别标签:

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

哈工大LTP的命名实体标注集没有提取“时间”,具体参考如下:

https://ltp.readthedocs.io/zh_CN/latest/appendix.html

NE识别模块的标注结果采用O-S-B-I-E标注形式,其含义为

标记 含义
O 这个词不是NE
S 这个词单独构成一个NE
B 这个词为一个NE的开始
I 这个词为一个NE的中间
E 这个词位一个NE的结尾

LTP中的NE 模块识别三种NE,分别如下:

标记 含义
Nh 人名
Ni 机构名
Ns 地名

基于上述观察,我决定采用这种方案做中文命名实体工具测试接口:对于斯坦福Stanza的NER结果直接保留,对于 Baidu Lac 结果则保留强置信度的人名(PER)、地名(LOC)、机构名(ORG)、时间(TIME)提取结果,对于哈工大LTP的NER结果做个人名(Nh=>PER)、地名(Ns=>LOC)和机构名(Ni=>ORG)的映射,对于其他几个工具,去除斯坦福的老NLP工具CoreNLP,其他NLP工具则保留nr、ns、nt、t、nz这几个提取工具,并做了标记映射人名(nr=>PER),地名(ns=>LOC),机构名(nt=>ORG),时间(t=>TIME)。下面是几组测试结果,欢迎关注AINLP公众号试用,结果仅供参考,毕竟除了斯坦福Stanza、Baidu Lac以及哈工大LTP外,其他几个工具的“NER命名实体识别”功能是“强加”的,在实际使用中,可以根据需求采用:

斯坦福大学NLP组Python深度学习自然语言处理工具Stanza试用

众所周知,斯坦福大学自然语言处理组出品了一系列NLP工具包,但是大多数都是用Java写得,对于Python用户不是很友好。几年前我曾基于斯坦福Java工具包和NLTK写过一个简单的中文分词接口:Python自然语言处理实践: 在NLTK中使用斯坦福中文分词器,不过用起来也不是很方便。深度学习自然语言处理时代,斯坦福大学自然语言处理组开发了一个纯Python版本的深度学习NLP工具包:Stanza - A Python NLP Library for Many Human Languages,前段时间,Stanza v1.0.0 版本正式发布,算是一个里程碑:

Stanza 是一个纯Python实现的自然语言处理工具包,这个区别于斯坦福大学自然语言处理组之前一直维护的Java实现 CoreNLP 等自然语言处理工具包,对于Python用户来说,就更方便调用了,并且Stanza还提供了一个Python接口可用于CoreNLP的调用 ,对于一些没有在Stanza中实现的NLP功能,可以通过这个接口调用 CoreNLP 作为补充。 Stanza的深度学习自然语言处理模块基于PyTorch实现,用户可以基于自己标注的数据构建更准确的神经网络模型用于训练、评估和使用,当然,如果有GPU机器加持,速度可以更快。Stanza目前支持66种语言的文本分析,包括自动断句、Tokenize(或者分词)、词性标注和形态素分析、依存句法分析以及命名实体识别。

To summarize, Stanza features:

Native Python implementation requiring minimal efforts to set up;
Full neural network pipeline for robust text analytics, including tokenization, multi-word token (MWT) expansion, lemmatization, part-of-speech (POS) and morphological features tagging, dependency parsing, and named entity recognition;
Pretrained neural models supporting 66 (human) languages;
A stable, officially maintained Python interface to CoreNLP.

试用了一下Stanza,还是很方便的,官方文档很清晰,可以直接参考。简单记录一下中英文模块的安装和使用,以下是在Ubuntu16.04, Python 3.6.8 环境下,请注意,Stanza需要Python3.6及以上的版本,如果低于这个版本,用 pip install stanza 安装的stanza非斯坦福大学NLP组的Stanza。

安装Stanza的方法有多种,这里是virtualenv虚拟环境下通过 pip install stanza 安装stanza及其相关依赖的,具体可以参考Stanza的安装文档:https://stanfordnlp.github.io/stanza/installation_usage.html

安装完成后,可以尝试使用,不过使用某种语言的NLP工具包时,还需要先下载相关的打包模型,这个在第一次使用时会有提示和操作,以后就无需下载了,我们先从斯坦福官方的例子走起,以英文为例:

In [1]: import stanza                                                                             
 
# 这里因为已经下载过英文模型打包文件,所以可以直接使用,如果没有下载过,初次使用会有一个下载过程
In [2]: stanza.download('en')                                                                     
Downloading https://raw.githubusercontent.com/stanfordnlp/stanza-resources/master/resources_1.0.0.Downloading https://raw.githubusercontent.com/stanfordnlp/stanza-resources/master/resources_1.0.0.json: 116kB [00:00, 154kB/s]
2020-04-11 23:13:14 INFO: Downloading default packages for language: en (English)...
2020-04-11 23:13:15 INFO: File exists: /home/textminer/stanza_resources/en/default.zip.
2020-04-11 23:13:19 INFO: Finished downloading models and saved to /home/textminer/stanza_resources.
 
# Pipeline是Stanza里一个重要的概念
In [3]: en_nlp = stanza.Pipeline('en')                                                            
2020-04-11 23:14:27 INFO: Loading these models for language: en (English):
=========================
| Processor | Package   |
-------------------------
| tokenize  | ewt       |
| pos       | ewt       |
| lemma     | ewt       |
| depparse  | ewt       |
| ner       | ontonotes |
=========================
 
2020-04-11 23:14:28 INFO: Use device: gpu
2020-04-11 23:14:28 INFO: Loading: tokenize
2020-04-11 23:14:30 INFO: Loading: pos
2020-04-11 23:14:30 INFO: Loading: lemma
2020-04-11 23:14:30 INFO: Loading: depparse
2020-04-11 23:14:31 INFO: Loading: ner
2020-04-11 23:14:32 INFO: Done loading processors!
 
In [5]: doc = en_nlp("Barack Obama was born in Hawaii.")                                          
 
In [6]: print(doc)                                                                                
[
  [
    {
      "id": "1",
      "text": "Barack",
      "lemma": "Barack",
      "upos": "PROPN",
      "xpos": "NNP",
      "feats": "Number=Sing",
      "head": 4,
      "deprel": "nsubj:pass",
      "misc": "start_char=0|end_char=6"
    },
    {
      "id": "2",
      "text": "Obama",
      "lemma": "Obama",
      "upos": "PROPN",
      "xpos": "NNP",
      "feats": "Number=Sing",
      "head": 1,
      "deprel": "flat",
      "misc": "start_char=7|end_char=12"
    },
    {
      "id": "3",
      "text": "was",
      "lemma": "be",
      "upos": "AUX",
      "xpos": "VBD",
      "feats": "Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin",
      "head": 4,
      "deprel": "aux:pass",
      "misc": "start_char=13|end_char=16"
    },
    {
      "id": "4",
      "text": "born",
      "lemma": "bear",
      "upos": "VERB",
      "xpos": "VBN",
      "feats": "Tense=Past|VerbForm=Part|Voice=Pass",
      "head": 0,
      "deprel": "root",
      "misc": "start_char=17|end_char=21"
    },
    {
      "id": "5",
      "text": "in",
      "lemma": "in",
      "upos": "ADP",
      "xpos": "IN",
      "head": 6,
      "deprel": "case",
      "misc": "start_char=22|end_char=24"
    },
    {
      "id": "6",
      "text": "Hawaii",
      "lemma": "Hawaii",
      "upos": "PROPN",
      "xpos": "NNP",
      "feats": "Number=Sing",
      "head": 4,
      "deprel": "obl",
      "misc": "start_char=25|end_char=31"
    },
    {
      "id": "7",
      "text": ".",
      "lemma": ".",
      "upos": "PUNCT",
      "xpos": ".",
      "head": 4,
      "deprel": "punct",
      "misc": "start_char=31|end_char=32"
    }
  ]
]
 
In [7]: print(doc.entities)                                                                       
[{
  "text": "Barack Obama",
  "type": "PERSON",
  "start_char": 0,
  "end_char": 12
}, {
  "text": "Hawaii",
  "type": "GPE",
  "start_char": 25,
  "end_char": 31
}]

Pipeline是Stanza里的一个重要概念:

可以通过pipeline预加载不同语言的模型,也可以通过pipeline选择不同的处理模块,还可以选择是否使用GPU,这里我们再试试中文模型:

In [9]: import stanza                                                                             
 
# 测试一下中文模型(因为我这边中文模型已经下载过了,所以跳过download环节)
In [10]: zh_nlp = stanza.Pipeline('zh')                                                           
2020-04-12 11:32:47 INFO: "zh" is an alias for "zh-hans"
2020-04-12 11:32:47 INFO: Loading these models for language: zh-hans (Simplified_Chinese):
=========================
| Processor | Package   |
-------------------------
| tokenize  | gsdsimp   |
| pos       | gsdsimp   |
| lemma     | gsdsimp   |
| depparse  | gsdsimp   |
| ner       | ontonotes |
=========================
 
2020-04-12 11:32:48 INFO: Use device: gpu
2020-04-12 11:32:48 INFO: Loading: tokenize
2020-04-12 11:32:49 INFO: Loading: pos
2020-04-12 11:32:51 INFO: Loading: lemma
2020-04-12 11:32:51 INFO: Loading: depparse
2020-04-12 11:32:53 INFO: Loading: ner
2020-04-12 11:32:54 INFO: Done loading processors!
 
In [11]: text = """英国首相约翰逊6日晚因病情恶化,被转入重症监护室治疗。英国首相府发言人说,目前约
    ...: 翰逊意识清晰,将他转移到重症监护室只是预防性措施。发言人说,约翰逊被转移到重症监护室前已
    ...: 安排英国外交大臣拉布代表他处理有关事务。"""                                              
 
In [12]: doc = zh_nlp(text)  
 
In [13]: for sent in doc.sentences: 
    ...:     print("Sentence:" + sent.text) # 断句
    ...:     print("Tokenize:" + ' '.join(token.text for token in sent.tokens)) # 中文分词
    ...:     print("UPOS: " + ' '.join(f'{word.text}/{word.upos}' for word in sent.words)) # 词性标注(UPOS)
    ...:     print("XPOS: " + ' '.join(f'{word.text}/{word.xpos}' for word in sent.words)) # 词性标注(XPOS)
    ...:     print("NER: " + ' '.join(f'{ent.text}/{ent.type}' for ent in sent.ents)) # 命名实体识别
    ...:                                                                                          
Sentence:英国首相约翰逊6日晚因病情恶化,被转入重症监护室治疗。
Tokenize:英国 首相 约翰逊 6 日 晚因 病情 恶化 , 被 转入 重症 监护 室 治疗 。
UPOS: 英国/PROPN 首相/NOUN 约翰逊/PROPN 6/NUM 日/NOUN 晚因/NOUN 病情/NOUN 恶化/VERB ,/PUNCT 被/VERB 转入/VERB 重症/NOUN 监护/VERB 室/PART 治疗/NOUN 。/PUNCT
XPOS: 英国/NNP 首相/NN 约翰逊/NNP 6/CD 日/NNB 晚因/NN 病情/NN 恶化/VV ,/, 被/BB 转入/VV 重症/NN 监护/VV 室/SFN 治疗/NN 。/.
NER: 英国/GPE 约翰逊/PERSON 6日/DATE
Sentence:英国首相府发言人说,目前约翰逊意识清晰,将他转移到重症监护室只是预防性措施。
Tokenize:英国 首相 府 发言 人 说 , 目前 约翰逊 意识 清晰 , 将 他 转移 到 重症 监护 室 只 是 预防 性 措施 。
UPOS: 英国/PROPN 首相/NOUN 府/PART 发言/VERB 人/PART 说/VERB ,/PUNCT 目前/NOUN 约翰逊/PROPN 意识/NOUN 清晰/ADJ ,/PUNCT 将/ADP 他/PRON 转移/VERB 到/VERB 重症/NOUN 监护/VERB 室/PART 只/ADV 是/AUX 预防/VERB 性/PART 措施/NOUN 。/PUNCT
XPOS: 英国/NNP 首相/NN 府/SFN 发言/VV 人/SFN 说/VV ,/, 目前/NN 约翰逊/NNP 意识/NN 清晰/JJ ,/, 将/BB 他/PRP 转移/VV 到/VV 重症/NN 监护/VV 室/SFN 只/RB 是/VC 预防/VV 性/SFN 措施/NN 。/.
NER: 英国/GPE 约翰逊/PERSON
Sentence:发言人说,约翰逊被转移到重症监护室前已安排英国外交大臣拉布代表他处理有关事务。
Tokenize:发言 人 说 , 约翰逊 被 转移 到 重症 监护 室 前 已 安排 英国 外交 大臣 拉布 代表 他 处理 有关 事务 。
UPOS: 发言/VERB 人/PART 说/VERB ,/PUNCT 约翰逊/PROPN 被/VERB 转移/VERB 到/VERB 重症/NOUN 监护/VERB 室/PART 前/ADP 已/ADV 安排/VERB 英国/PROPN 外交/NOUN 大臣/NOUN 拉布/PROPN 代表/VERB 他/PRON 处理/VERB 有关/ADJ 事务/NOUN 。/PUNCT
XPOS: 发言/VV 人/SFN 说/VV ,/, 约翰逊/NNP 被/BB 转移/VV 到/VV 重症/NN 监护/VV 室/SFN 前/IN 已/RB 安排/VV 英国/NNP 外交/NN 大臣/NN 拉布/NNP 代表/VV 他/PRP 处理/VV 有关/JJ 事务/NN 。/.
NER: 约翰逊/PERSON 英国/GPE 拉布/PERSON

如果用户不需要使用命名实体识别、依存句法等功能,可以在模型下载或者预加载阶段或者构建Pipeline时选择自己需要的功能模块处理器,例如可以只选择中文分词和词性标注,或者单一的中文分词功能,这里以“我爱自然语言处理”为例:

 
# 可以在使用时只选择自己需要的功能,这样下载的模型包更小,节约时间,这里因为之前已经下载过全量的中文模型,所以不再有下载过程,只是用于演示
In [14]: stanza.download('zh', processors='tokenize,pos')                                         
Downloading https://raw.githubusercontent.com/stanfordnlp/stanza-resources/master/resources_1.0.0.Downloading https://raw.githubusercontent.com/stanfordnlp/stanza-resources/master/resources_1.0.0.json: 116kB [00:00, 554kB/s]
2020-04-15 07:27:38 INFO: "zh" is an alias for "zh-hans"
2020-04-15 07:27:38 INFO: Downloading these customized packages for language: zh-hans (Simplified_Chinese)...
=======================
| Processor | Package |
-----------------------
| tokenize  | gsdsimp |
| pos       | gsdsimp |
| pretrain  | gsdsimp |
=======================
 
2020-04-15 07:27:38 INFO: File exists: /home/textminer/stanza_resources/zh-hans/tokenize/gsdsimp.pt.
2020-04-15 07:27:38 INFO: File exists: /home/textminer/stanza_resources/zh-hans/pos/gsdsimp.pt.
2020-04-15 07:27:39 INFO: File exists: /home/textminer/stanza_resources/zh-hans/pretrain/gsdsimp.pt.
2020-04-15 07:27:39 INFO: Finished downloading models and saved to /home/textminer/stanza_resources.
 
# 构建Pipeline时选择中文分词和词性标注,对其他语言同理
In [15]: zh_nlp = stanza.Pipeline('zh', processors='tokenize,pos')                                
2020-04-15 07:28:12 INFO: "zh" is an alias for "zh-hans"
2020-04-15 07:28:12 INFO: Loading these models for language: zh-hans (Simplified_Chinese):
=======================
| Processor | Package |
-----------------------
| tokenize  | gsdsimp |
| pos       | gsdsimp |
=======================
 
2020-04-15 07:28:13 INFO: Use device: gpu
2020-04-15 07:28:13 INFO: Loading: tokenize
2020-04-15 07:28:15 INFO: Loading: pos
2020-04-15 07:28:17 INFO: Done loading processors!
 
In [16]: doc = zh_nlp("我爱自然语言处理")                                                         
 
In [17]: print(doc)                                                                               
[
  [
    {
      "id": "1",
      "text": "我",
      "upos": "PRON",
      "xpos": "PRP",
      "feats": "Person=1",
      "misc": "start_char=0|end_char=1"
    },
    {
      "id": "2",
      "text": "爱",
      "upos": "VERB",
      "xpos": "VV",
      "misc": "start_char=1|end_char=2"
    },
    {
      "id": "3",
      "text": "自然",
      "upos": "NOUN",
      "xpos": "NN",
      "misc": "start_char=2|end_char=4"
    },
    {
      "id": "4",
      "text": "语言",
      "upos": "NOUN",
      "xpos": "NN",
      "misc": "start_char=4|end_char=6"
    },
    {
      "id": "5",
      "text": "处理",
      "upos": "VERB",
      "xpos": "VV",
      "misc": "start_char=6|end_char=8"
    }
  ]
]
 
# 这里单独使用Stanza的中文分词器
In [18]: zh_nlp = stanza.Pipeline('zh', processors='tokenize')                                    
2020-04-15 07:31:27 INFO: "zh" is an alias for "zh-hans"
2020-04-15 07:31:27 INFO: Loading these models for language: zh-hans (Simplified_Chinese):
=======================
| Processor | Package |
-----------------------
| tokenize  | gsdsimp |
=======================
 
2020-04-15 07:31:27 INFO: Use device: gpu
2020-04-15 07:31:27 INFO: Loading: tokenize
2020-04-15 07:31:27 INFO: Done loading processors!
 
In [19]: doc = zh_nlp("我爱自然语言处理")                                                         
 
In [20]: print(doc)                                                                               
[
  [
    {
      "id": "1",
      "text": "我",
      "misc": "start_char=0|end_char=1"
    },
    {
      "id": "2",
      "text": "爱",
      "misc": "start_char=1|end_char=2"
    },
    {
      "id": "3",
      "text": "自然",
      "misc": "start_char=2|end_char=4"
    },
    {
      "id": "4",
      "text": "语言",
      "misc": "start_char=4|end_char=6"
    },
    {
      "id": "5",
      "text": "处理",
      "misc": "start_char=6|end_char=8"
    }
  ]
]

在Pipeline构建时,除了选择不同的功能模块处理器外,对于有多个模型可以选择使用的功能模块,也可以指定需要使用哪个模型,另外也可以指定Log级别,这些可以参考官方文档。还有一点,如果你觉得使用GPU没有必要,还可以选择使用CPU:

In [21]: zh_doc = stanza.Pipeline('zh', use_gpu=False)                                            
2020-04-15 07:44:04 INFO: "zh" is an alias for "zh-hans"
2020-04-15 07:44:04 INFO: Loading these models for language: zh-hans (Simplified_Chinese):
=========================
| Processor | Package   |
-------------------------
| tokenize  | gsdsimp   |
| pos       | gsdsimp   |
| lemma     | gsdsimp   |
| depparse  | gsdsimp   |
| ner       | ontonotes |
=========================
 
2020-04-15 07:44:04 INFO: Use device: cpu
2020-04-15 07:44:04 INFO: Loading: tokenize
2020-04-15 07:44:04 INFO: Loading: pos
2020-04-15 07:44:06 INFO: Loading: lemma
2020-04-15 07:44:06 INFO: Loading: depparse
2020-04-15 07:44:08 INFO: Loading: ner
2020-04-15 07:44:09 INFO: Done loading processors!

我将Stanza的中英文模块部署在了AINLP的后台,使用的就是CPU,感兴趣的同学可以关注AINLP公众号,对话测试,Stanza+分析内容触发,会自动判断语言选择不同的Pipeline:

中文自然语言处理相关的开放任务,数据集, 以及当前最佳结果

强烈推荐一个项目:Chinese NLP ,这是由滴滴人工智能实验室所属的自然语言处理团队创建并维护的,该项目非常细致的整理了中文自然语言处理相关任务、数据集及当前最佳结果,相当完备。

项目主页:https://chinesenlp.xyz

Github: https://github.com/didi/ChineseNLP

这个项目里面目前包含了18个中文自然语言处理任务,以及一个其他类别:

每个子任务下面,会详细介绍相关的任务背景、示例、评价指标、相关数据集及当前最佳结果。以中文分词为例,除了我们熟悉的backoff2005数据集外,还有一些其他数据来源:

再看一下机器翻译任务,关于评价指标,描述的相当详细:

直接评估(人工评判)。Amazon Mechnical Turk上的标注人员会看到一个系统生成的翻译和一个人工翻译,然后回答这样一个问题:“系统翻译有多么精确的表达了人工翻译的含义?”

Bleu score (Papineni et al 02 ).

大小写敏感 vs. 大小写不敏感

Brevity penalty 触发条件: 当机器翻译结果短于最短的参考译文 (reference) 或者短于最接近的参考译文 (reference)。

brevity penalty: 一个系数,用来惩罚长度短于参考翻译的机器翻译结果。

标准的Bleu计算流程会先对参考译文和机器翻译结果进行符号化 (tokenizition)。

如果中文是目标 (target) 语言, 则使用字符级别 {1,2,3,4}-gram匹配。

当只有1条人工参考翻译译文时使用Bleu-n4r1评估。

Bleu-n4r4: 词级别 {1,2,3,4}-gram 匹配, 与4条人工参考翻译译文比较

标准Bleu有很多重要的变种:

NIST. Bleu的一种变体,赋予少见的n-gram更高的权重。

TER (Translation Edit Rate). 计算机器翻译与人工参考译文之间的编辑距离 (Edit distance)。

BLEU-SBP ((Chiang et al 08)[http://aclweb.org/anthology/D08-1064] ). 解决了Bleu的解耦(decomposability) 问题,在Bleu和单词错误率取得一个折中。

HTER. 修改为一个良好的翻译所需要的人工编辑次数 (the number of edits)。

机器翻译相关语料资源方面,也包括我们比较熟悉的联合国语料库和AI Challenger:

其他相关任务感兴趣的同学可以自行参考,这是一个相当不错的了解当前中文NLP相关任务的参考点,感谢建设和维护该项目的同学。

注:原创文章,转载请注明出处及保留链接“我爱自然语言处理”:http://www.52nlp.cn

本文链接地址:中文自然语言处理相关的开放任务,数据集, 以及当前最佳结果 http://www.52nlp.cn/?p=12099

百度深度学习中文词法分析工具LAC试用之旅

之前在调研中文分词词性标注相关工具的时候就发现了百度的深度学习中文词法分析工具:baidu/lac(https://github.com/baidu/lac),但是通过这个项目github上的文档描述以及实际动手尝试源码编译安装发现非常繁琐,缺乏通常中文分词工具的易用性,所以第一次接触完百度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%。

本项目依赖Paddle v0.14.0版本。如果您的Paddle安装版本低于此要求,请按照安装文档中的说明更新Paddle安装版本。如果您使用的Paddle是v1.1以后的版本,请使用该项目的分支for_paddle_v1.1。注意,LAC模块中的conf目录下的很多文件是采用git-lfs存储,使用git clone时,需要先安装git-lfs。

为了达到和机器运行环境的最佳匹配,我们建议基于源码编译安装Paddle,后文也将展开讨论一些编译安装的细节。当然,如果您发现符合机器环境的预编译版本在官网发布,也可以尝试直接选用。

最近发现百度将自己的一些自然语言处理工具整合在PaddleNLP下,文档写得相对清楚多了:

PaddleNLP是百度开源的工业级NLP工具与预训练模型集,能够适应全面丰富的NLP任务,方便开发者灵活插拔尝试多种网络结构,并且让应用最快速达到工业级效果。

PaddleNLP完全基于PaddlePaddle Fluid开发,并提供依托于百度百亿级大数据的预训练模型,能够极大地方便NLP研究者和工程师快速应用。使用者可以用PaddleNLP快速实现文本分类、文本匹配、序列标注、阅读理解、智能对话等NLP任务的组网、建模和部署,而且可以直接使用百度开源工业级预训练模型进行快速应用。用户在极大地减少研究和开发成本的同时,也可以获得更好的基于工业实践的应用效果。

继续阅读

自然语言理解太难了之中文分词八级测试

前几天在微博看到了一个例子:无线电法国别研究

赶紧用AINLP公众号后台的中文分词和词性标注测试功能试了一下八款中文分词词性标注)工具或者模块:

结果如预期一样,大部分中文分词工具翻车了,不过这个例子别说对于中文分词工具,即使人工分词也需要反应一下。这也让我想起了之前转载的杨洋同学整理,刘群老师在微博上发起的#自然语言理解太难了#话题:NLP is hard! 自然语言处理太难了系列

这里基于这个系列以及记录的一些有意思的测试case做个整理,感兴趣的同学可以试试:

来到杨过曾经生活过的地方,小龙女动情地说:“我也想过过过儿过过的生活。”

来到儿子等校车的地方,邓超对孙俪说:“我也想等等等等等过的那辆车。”

赵敏说:我也想控忌忌己不想无忌。

你也想犯范范范玮琪犯过的错吗

对叙打击是一次性行为?

《绿林俊杰》--林俊杰做错了什么?为什么要绿他

一位友好的哥谭市民

校长说衣服上除了校徽别别别的

过几天天天天气不好

看见西门吹雪点上了灯,叶孤城冷笑着说:“我也想吹吹吹雪吹过的灯”,然后就吹灭了灯。

今天多得谢逊出手相救,在这里我想真心感谢“谢谢谢逊大侠出手”

灭霸把美队按在地上一边摩擦一边给他洗脑,被打残的钢铁侠说:灭霸爸爸叭叭叭叭儿的在那叭叭啥呢

姑姑你估估我鼓鼓的口袋里有多少谷和菇!!

“你看到王刚了吗”“王刚刚刚刚走”

张杰陪俩女儿跳格子:俏俏我们不要跳跳跳跳过的格子啦

骑车出门差点摔跤,还好我一把把把把住了

我朋友问父亲:我大大大(大大爷)和我姑姑谁年龄大?朋友爸爸说:你大大大大!

我背有点驼,麻麻说“你的背得背背背背佳
继续阅读

八款中文词性标注工具使用及在线测试

结束了中文分词工具的安装、使用及在线测试,开启中文词性标注在线测试之旅,一般来说,中文分词工具大多数都附带词性标注功能的,这里测试了之前在AINLP公众号上线的8款中文分词模块或者工具,发现它们都是支持中文词性标注的,这里面唯一的区别,就是各自用的词性标注集可能有不同:

以下逐一介绍这八个工具的中文词性标注功能的使用方法,至于安装,这里简要介绍,或者可以参考之前这篇文章:Python中文分词工具大合集:安装、使用和测试,以下是在Ubuntu16.04 & Python3.x的环境下安装及测试。
继续阅读

Python中文分词工具大合集:安装、使用和测试

这篇文章事实上整合了前面两篇文章的相关介绍,同时添加一些其他的Python中文分词相关资源,甚至非Python的中文分词工具,仅供参考。

首先介绍之前测试过的8款中文分词工具,这几款工具可以直接在AINLP公众号后台在线测试,严格的说,它们不完全是纯粹的中文分词工具,例如SnowNLP, Thulac, HanLP,LTP,CoreNLP都是很全面的(中文)自然语言处理工具。安装这些模块其实很简单,只要按官方文档的方法安装即可,以下做个简单介绍,在Python3.x的环境下测试,Ubuntu16.04 或 MacOS 测试成功。

再附加介绍12款其他的中文分词工具或者中文分词模块,最后的两款fnlp和ansj是比较棒的java中文分词工具,貌似还没有python接口,记录一下。这些中文分词工具我没有测试,感兴趣的同学可以动手试试。
继续阅读

中文分词工具在线PK新增:FoolNLTK、HITLTP、StanfordCoreNLP

继续中文分词在线PK之旅,上文《五款中文分词工具在线PK: Jieba, SnowNLP, PkuSeg, THULAC, HanLP》我们选择了5个中文分词开源工具,这次再追加3个,分别是FoolNLTK、哈工大LTP(pyltp, ltp的python封装)、斯坦福大学的CoreNLP(stanfordcorenlp is a Python wrapper for Stanford CoreNLP),现在可以在AINLP公众号测试一下:中文分词 我爱自然语言处理

以下是在Python3.x & Ubuntu16.04 的环境下测试及安装这些中文分词器:
继续阅读

五款中文分词工具在线PK: Jieba, SnowNLP, PkuSeg, THULAC, HanLP

最近玩公众号会话停不下来:玩转腾讯词向量:Game of Words(词语的加减游戏),准备把NLP相关的模块搬到线上,准确的说,搬到AINLP公众号后台对话,所以,趁着劳动节假期,给AINLP公众号后台聊天机器人添加了一项新技能:中文分词线上PK,例如在AINLP公众号后台对话输入:中文分词 我爱自然语言处理,就可以得到五款分词工具的分词结果:

现在的开源中文分词工具或者模块已经很丰富了,并且很多都有一些在封闭测试集上的效果对比数据,不过这仅仅只能展现这些分词工具在这个封闭测试集上的效果,并不能全面说明问题,个人觉得,选择一个适合自己业务的分词器可能更重要,有的时候,还需要加一些私人定制的词库。

这次首先选了5款中文分词工具,严格的来说,它们不完全是纯粹的中文分词工具,例如SnowNLP, Thulac, HanLP都是很全面的中文自然语言处理工具,这次,先试水它们的中文分词模块。安装这些模块其实很简单,只要按官方文档的方法安装即可,以下做个简单介绍,在Python3.x的环境下测试,Ubuntu16.04 或 MacOS 测试成功。
继续阅读