NLP入门(六) pyltp的介绍与使用 转自:jclian91

NLP入门(六) pyltp的介绍与使用 转自:jclian91

原文链接:https://segmentfault.com/a/1190000018081013

  1. pyltp的简介

    语言技术平台(LTP)经过哈工大社会计算与信息检索研究中心 11 年的持续研发和推广, 是国内外最具影响力的中文处理基础平台。它提供的功能包括中文分词、词性标注、命名实体识别、依存句法分析、语义角色标注等。

    语言技术平台架构

    pyltp 是 LTP 的 Python 封装,同时支持Python2和Python3版本。Python3的安装方法为:

    pip3 install pyltp
    

    在使用该模块前,需要下载完整的模型文件,文件下载地址为:https://pan.baidu.com/share/l... 。pyltp 的所有输入的分析文本和输出的结果的编码均为 UTF-8。模型的数据文件如下:

    模型数据

    其中,cws.model用于分词模型,lexicon.txt为分词时添加的用户字典,ner.model为命名实体识别模型,parser.model为依存句法分析模型,pisrl.model为语义角色标注模型,pos为词性标注模型。

    pyltp的使用

    pyltp的使用示例项目结构如下:

    示例项目

    分句

    分句指的是将一段话或一片文章中的文字按句子分开,按句子形成独立的单元。示例的Python代码sentenct_split.py如下:

    # -*- coding: utf-8 -*-
    
    from pyltp import SentenceSplitter
    
    # 分句
    doc = '据韩联社12月28日反映,美国防部发言人杰夫·莫莱尔27日表示,美国防部长盖茨将于2011年1月14日访问韩国。' \
          '盖茨原计划从明年1月9日至14日陆续访问中国和日本,目前,他决定在行程中增加对韩国的访问。莫莱尔表示,' \
          '盖茨在访韩期间将会晤韩国国防部长官金宽镇,就朝鲜近日的行动交换意见,同时商讨加强韩美两军同盟关系等问题,' \
          '拟定共同应对朝鲜挑衅和核计划的方案。'
    sents = SentenceSplitter.split(doc)  # 分句
    
    
    for sent in sents:
        print(sent)
    

    输出结果如下:

    据韩联社12月28日反映,美国防部发言人杰夫·莫莱尔27日表示,美国防部长盖茨将于2011年1月14日访问韩国。
    盖茨原计划从明年1月9日至14日陆续访问中国和日本,目前,他决定在行程中增加对韩国的访问。
    莫莱尔表示,盖茨在访韩期间将会晤韩国国防部长官金宽镇,就朝鲜近日的行动交换意见,同时商讨加强韩美两军同盟关系等问题,拟定共同应对朝鲜挑衅和核计划的方案。
    
    分词

    分词指的是将一句话按词语分开,按词语形成独立的单元。示例的Python代码words_split.py如下:

    # -*- coding: utf-8 -*-
    
    
    import os
    from pyltp import Segmentor
    
    cws_model_path = os.path.join(os.path.dirname(__file__), 'data/cws.model')  # 分词模型路径,模型名称为`cws.model`
    lexicon_path = os.path.join(os.path.dirname(__file__), 'data/lexicon.txt')  # 参数lexicon是自定义词典的文件路径
    
    segmentor = Segmentor()
    segmentor.load_with_lexicon(cws_model_path, lexicon_path)
    
    sent = '据韩联社12月28日反映,美国防部发言人杰夫·莫莱尔27日表示,美国防部长盖茨将于2011年1月14日访问韩国。'
    words = segmentor.segment(sent)  # 分词
    
    print('/'.join(words))
    
    segmentor.release()
    

    输出的结果如下:

    据/韩联社/12月/28日/反映/,/美/国防部/发言人/杰夫·莫莱尔/27日/表示/,/美/国防部长/盖茨/将/于/2011年/1月/14日/访问/韩国/。
    
    词性标注

    词性标注指的是一句话分完词后,制定每个词语的词性。示例的Python代码postagger.py如下:

    # -*- coding: utf-8 -*-
    
    import os
    from pyltp import Segmentor, Postagger
    
    # 分词
    cws_model_path = os.path.join(os.path.dirname(__file__), 'data/cws.model')  # 分词模型路径,模型名称为`cws.model`
    lexicon_path = os.path.join(os.path.dirname(__file__), 'data/lexicon.txt')  # 参数lexicon是自定义词典的文件路径
    
    segmentor = Segmentor()
    segmentor.load_with_lexicon(cws_model_path, lexicon_path)
    
    sent = '据韩联社12月28日反映,美国防部发言人杰夫·莫莱尔27日表示,美国防部长盖茨将于2011年1月14日访问韩国。'
    words = segmentor.segment(sent)  # 分词
    
    # 词性标注
    pos_model_path = os.path.join(os.path.dirname(__file__), 'data/pos.model')  # 词性标注模型路径,模型名称为`pos.model`
    
    postagger = Postagger()  # 初始化实例
    postagger.load(pos_model_path)  # 加载模型
    postags = postagger.postag(words)  # 词性标注
    
    for word, postag in zip(words, postags):
        print(word, postag)
    
    # 释放模型
    segmentor.release()
    postagger.release()
    
    '''
    词性标注结果说明
    https://ltp.readthedocs.io/zh_CN/latest/appendix.html#id3
    '''
    

    输出结果如下:

    据 p
    韩联社 ni
    12月 nt
    28日 nt
    反映 v
    , wp
    美 j
    国防部 n
    发言人 n
    杰夫·莫莱尔 nh
    27日 nt
    表示 v
    , wp
    美 j
    国防部长 n
    盖茨 nh
    将 d
    于 p
    2011年 nt
    1月 nt
    14日 nt
    访问 v
    韩国 ns
    。 wp
    

    词性标注结果可参考网址:https://ltp.readthedocs.io/zh...

    命名实体识别

    命名实体识别(NER)指的是识别出一句话或一段话或一片文章中的命名实体,比如人名,地名,组织机构名。示例的Python代码ner.py如下:

    # -*- coding: utf-8 -*-
    
    import os
    from pyltp import Segmentor, Postagger
    
    # 分词
    cws_model_path = os.path.join(os.path.dirname(__file__), 'data/cws.model')  # 分词模型路径,模型名称为`cws.model`
    lexicon_path = os.path.join(os.path.dirname(__file__), 'data/lexicon.txt')  # 参数lexicon是自定义词典的文件路径
    
    segmentor = Segmentor()
    segmentor.load_with_lexicon(cws_model_path, lexicon_path)
    
    sent = '据韩联社12月28日反映,美国防部发言人杰夫·莫莱尔27日表示,美国防部长盖茨将于2011年1月14日访问韩国。'
    words = segmentor.segment(sent)  # 分词
    
    # 词性标注
    pos_model_path = os.path.join(os.path.dirname(__file__), 'data/pos.model')  # 词性标注模型路径,模型名称为`pos.model`
    
    postagger = Postagger()  # 初始化实例
    postagger.load(pos_model_path)  # 加载模型
    postags = postagger.postag(words)  # 词性标注
    
    
    ner_model_path = os.path.join(os.path.dirname(__file__), 'data/ner.model')   # 命名实体识别模型路径,模型名称为`pos.model`
    
    from pyltp import NamedEntityRecognizer
    recognizer = NamedEntityRecognizer() # 初始化实例
    recognizer.load(ner_model_path)  # 加载模型
    # netags = recognizer.recognize(words, postags)  # 命名实体识别
    
    
    # 提取识别结果中的人名,地名,组织机构名
    
    persons, places, orgs = set(), set(), set()
    
    
    netags = list(recognizer.recognize(words, postags))  # 命名实体识别
    print(netags)
    # print(netags)
    i = 0
    for tag, word in zip(netags, words):
        j = i
        # 人名
        if 'Nh' in tag:
            if str(tag).startswith('S'):
                persons.add(word)
            elif str(tag).startswith('B'):
                union_person = word
                while netags[j] != 'E-Nh':
                    j += 1
                    if j < len(words):
                        union_person += words[j]
                persons.add(union_person)
        # 地名
        if 'Ns' in tag:
            if str(tag).startswith('S'):
                places.add(word)
            elif str(tag).startswith('B'):
                union_place = word
                while netags[j] != 'E-Ns':
                    j += 1
                    if j < len(words):
                        union_place += words[j]
                places.add(union_place)
        # 机构名
        if 'Ni' in tag:
            if str(tag).startswith('S'):
                orgs.add(word)
            elif str(tag).startswith('B'):
                union_org = word
                while netags[j] != 'E-Ni':
                    j += 1
                    if j < len(words):
                        union_org += words[j]
                orgs.add(union_org)
    
        i += 1
    
    print('人名:', ','.join(persons))
    print('地名:', ','.join(places))
    print('组织机构:', ','.join(orgs))
    
    
    # 释放模型
    segmentor.release()
    postagger.release()
    recognizer.release()
    

    输出的结果如下:

    ['O', 'S-Ni', 'O', 'O', 'O', 'O', 'B-Ni', 'E-Ni', 'O', 'S-Nh', 'O', 'O', 'O', 'S-Ns', 'O', 'S-Nh', 'O', 'O', 'O', 'O', 'O', 'O', 'S-Ns', 'O']
    人名: 杰夫·莫莱尔,盖茨
    地名: 美,韩国
    组织机构: 韩联社,美国防部
    

    命名实体识别结果可参考网址:https://ltp.readthedocs.io/zh...

    依存句法分析

    依存语法 (Dependency Parsing, DP) 通过分析语言单位内成分之间的依存关系揭示其句法结构。 直观来讲,依存句法分析识别句子中的“主谓宾”、“定状补”这些语法成分,并分析各成分之间的关系。示例的Python代码parser.py代码如下:

    # -*- coding: utf-8 -*-
    
    import os
    from pyltp import Segmentor, Postagger, Parser
    
    # 分词
    cws_model_path = os.path.join(os.path.dirname(__file__), 'data/cws.model')  # 分词模型路径,模型名称为`cws.model`
    lexicon_path = os.path.join(os.path.dirname(__file__), 'data/lexicon.txt')  # 参数lexicon是自定义词典的文件路径
    
    segmentor = Segmentor()
    segmentor.load_with_lexicon(cws_model_path, lexicon_path)
    
    sent = '据韩联社12月28日反映,美国防部发言人杰夫·莫莱尔27日表示,美国防部长盖茨将于2011年1月14日访问韩国。'
    words = segmentor.segment(sent)  # 分词
    
    # 词性标注
    pos_model_path = os.path.join(os.path.dirname(__file__), 'data/pos.model')  # 词性标注模型路径,模型名称为`pos.model`
    
    postagger = Postagger()  # 初始化实例
    postagger.load(pos_model_path)  # 加载模型
    postags = postagger.postag(words)  # 词性标注
    
    
    # 依存句法分析
    par_model_path = os.path.join(os.path.dirname(__file__), 'data/parser.model')  # 模型路径,模型名称为`parser.model`
    
    parser = Parser() # 初始化实例
    parser.load(par_model_path)  # 加载模型
    arcs = parser.parse(words, postags)  # 句法分析
    
    rely_id = [arc.head for arc in arcs]  # 提取依存父节点id
    relation = [arc.relation for arc in arcs]  # 提取依存关系
    heads = ['Root' if id == 0 else words[id-1] for id in rely_id]  # 匹配依存父节点词语
    
    for i in range(len(words)):
        print(relation[i] + '(' + words[i] + ', ' + heads[i] + ')')
    
    # 释放模型
    segmentor.release()
    postagger.release()
    parser.release()
    

    输出结果如下:

    ADV(据, 表示)
    SBV(韩联社, 反映)
    ATT(12月, 28日)
    ADV(28日, 反映)
    POB(反映, 据)
    WP(,, 据)
    ATT(美, 国防部)
    ATT(国防部, 发言人)
    ATT(发言人, 杰夫·莫莱尔)
    SBV(杰夫·莫莱尔, 表示)
    ADV(27日, 表示)
    HED(表示, Root)
    WP(,, 表示)
    ATT(美, 国防部长)
    ATT(国防部长, 盖茨)
    SBV(盖茨, 访问)
    ADV(将, 访问)
    ADV(于, 访问)
    ATT(2011年, 14日)
    ATT(1月, 14日)
    POB(14日, 于)
    VOB(访问, 表示)
    VOB(韩国, 访问)
    WP(。, 表示)
    

    依存句法分析结果可参考网址:https://ltp.readthedocs.io/zh...

    语义角色标注

    语义角色标注是实现浅层语义分析的一种方式。在一个句子中,谓词是对主语的陈述或说明,指出“做什么”、“是什么”或“怎么样,代表了一个事件的核心,跟谓词搭配的名词称为论元。语义角色是指论元在动词所指事件中担任的角色。主要有:施事者(Agent)、受事者(Patient)、客体(Theme)、经验者(Experiencer)、受益者(Beneficiary)、工具(Instrument)、处所(Location)、目标(Goal)和来源(Source)等。示例的Python代码rolelabel.py如下:

    # -*- coding: utf-8 -*-
    
    import os
    from pyltp import Segmentor, Postagger, Parser, SementicRoleLabeller
    
    # 分词
    cws_model_path = os.path.join(os.path.dirname(__file__), 'data/cws.model')  # 分词模型路径,模型名称为`cws.model`
    lexicon_path = os.path.join(os.path.dirname(__file__), 'data/lexicon.txt')  # 参数lexicon是自定义词典的文件路径
    
    segmentor = Segmentor()
    segmentor.load_with_lexicon(cws_model_path, lexicon_path)
    
    sent = '据韩联社12月28日反映,美国防部发言人杰夫·莫莱尔27日表示,美国防部长盖茨将于2011年1月14日访问韩国。'
    words = segmentor.segment(sent)  # 分词
    
    # 词性标注
    pos_model_path = os.path.join(os.path.dirname(__file__), 'data/pos.model')  # 词性标注模型路径,模型名称为`pos.model`
    
    postagger = Postagger()  # 初始化实例
    postagger.load(pos_model_path)  # 加载模型
    postags = postagger.postag(words)  # 词性标注
    
    # 依存句法分析
    par_model_path = os.path.join(os.path.dirname(__file__), 'data/parser.model')  # 模型路径,模型名称为`parser.model`
    
    parser = Parser() # 初始化实例
    parser.load(par_model_path)  # 加载模型
    arcs = parser.parse(words, postags)  # 句法分析
    
    # 语义角色标注
    srl_model_path = os.path.join(os.path.dirname(__file__), 'data/pisrl.model')  # 语义角色标注模型目录路径
    labeller = SementicRoleLabeller() # 初始化实例
    labeller.load(srl_model_path)  # 加载模型
    roles = labeller.label(words, postags, arcs)  # 语义角色标注
    
    # 打印结果
    for role in roles:
        print(words[role.index], end=' ')
        print(role.index, "".join(["%s:(%d,%d)" % (arg.name, arg.range.start, arg.range.end) for arg in role.arguments]))
    
    # 释放模型
    segmentor.release()
    postagger.release()
    parser.release()
    labeller.release()
    

    输出结果如下:

    反映 4 A0:(1,1)A0:(2,3)
    表示 11 MNR:(0,5)A0:(6,9)TMP:(10,10)A1:(13,22)
    访问 21 A0:(13,15)ADV:(16,16)TMP:(17,20)A1:(22,22)
    

    总结

    本文介绍了中文NLP的一个杰出工具pyltp,并给出了该模块的各个功能的一个示例,希望能给读者一些思考与启示。本文到此结束,感谢大家阅读~

posted @ 2021-04-11 16:53  小杨的冥想课  阅读(357)  评论(0编辑  收藏  举报