文章目录
- LTP介绍
- 分句
- 分词
- 加载外部词典
- 个性化分词
- 词性标注
- 命名实体识别NER
- 依存句法分析
- 语义角色标注
LTP介绍
官网:https://ltp.ai/
下载可以到官网的下载专区:https://ltp.ai/download.html
语言技术平台(Language Technology Platform,LTP
):是哈工大社会计算与信息检索研究中心历时十年研制的一整套开放中文自然语言处理系统。提供了一整套自底向上的丰富、高效、高精度的中文自然语言处理模块 (包括词法、句法、语义等5项中文处理核心技术)。
本文使用的LTP
版本是ltp_data_v3.4.0
pyltp
版本是0.4.0
分句
from pyltp import SentenceSplitter
sent = "知识图谱按照功能和应用场景可以分为通用知识图谱和领域知识图谱。其中通用知识图谱面向的是通用领域,强调知识的广度,形态通常为结构化的百科知识,\
针对的使用者主要为普通用户;领域知识图谱则面向某一特定领域,强调知识的深度,通常需要基于该行业的数据库进行构建,针对的使用者为行业内的从业人员以及潜在的业内人士等。"
sents = SentenceSplitter.split(sent)
output_split_sen = '\n'.join(sents)
print(output_split_sen)
知识图谱按照功能和应用场景可以分为通用知识图谱和领域知识图谱。
其中通用知识图谱面向的是通用领域,强调知识的广度,形态通常为结构化的百科知识, 针对的使用者主要为普通用户;
领域知识图谱则面向某一特定领域,强调知识的深度,通常需要基于该行业的数据库进行构建,针对的使用者为行业内的从业人员以及潜在的业内人士等。
分词
import os
from pyltp import Segmentor
# 分词模型的路径
LTP_DATA_DIR = 'E:/ltp_data_v3.4.0'
cws_model_path = os.path.join(LTP_DATA_DIR, 'cws.model')
# 实例化
segmentor = Segmentor()
# 加载分词模型
segmentor.load(cws_model_path)
# 分词
# words返回值类型是native的VectorOfString类型,可以使用list转换成Python的列表类型
words = segmentor.segment("你认为人工智能、机器学习和深度学习的关系是什么?")
# 输出
output_split_words = '|'.join(words)
print(list(words))
print(output_split_words)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_24988/3875451578.py in <module>
6 cws_model_path = os.path.join(LTP_DATA_DIR, 'cws.model')
7 # 实例化
----> 8 segmentor = Segmentor()
9 # 加载分词模型
10 segmentor.load(cws_model_path)
TypeError: __init__(): incompatible constructor arguments. The following argument types are supported:
1. pyltp.Segmentor(model_path: str, lexicon_path: str = None, force_lexicon_path: str = None)
Invoked with:
直接使用会报错,因为目前的pyltp版本是0.4.0,版本过高,此时分词的写法已经发生改变。
最新的写法是将实例化和加载分词模型合并起来。后面的词性标注等方法也是如此。如果版本较低,写的方法就不用改变。
import os
from pyltp import Segmentor
# 分词模型的路径
LTP_DATA_DIR = 'E:/ltp_data_v3.4.0'
cws_model_path = os.path.join(LTP_DATA_DIR, 'cws.model')
# 实例化
segmentor = Segmentor(cws_model_path)
# 分词
# words返回值类型是native的VectorOfString类型,可以使用list转换成Python的列表类型
words = segmentor.segment("你认为人工智能、机器学习和深度学习的关系是什么?")
# 输出
output_split_words = '|'.join(words)
print(list(words))
print(output_split_words)
['你', '认为', '人工智能', '、', '机器', '学习', '和', '深度', '学习', '的', '关系', '是', '什么', '?']
你|认为|人工智能|、|机器|学习|和|深度|学习|的|关系|是|什么|?
加载外部词典
特有名词,比如机器学习、深度学习等词语不应该分开,所以可以将它们放在特有名词的外部词典中进行加载。
- 旧版本写法
segmentor_1 = Segmentor()
# 加载模型,第二个参数是外部词典文件路径
segmentor_1.load_with_lexicon(cws_model_path, 'dict.txt')
words_1 = segmentor_1.segment('你会机器学习中的随机森林吗')
output_split_words_1 = '|'.join(words_1)
print(list(output_split_words_1))
print(output_split_words_1)
segmentor.release()
- 新版本写法
# 加载模型,第二个参数是外部词典文件路径
segmentor_1 = Segmentor(cws_model_path,lexicon_path='dict.txt')
words_1 = segmentor_1.segment("你认为人工智能、机器学习和深度学习的关系是什么?")
output_split_words_1 = '|'.join(words_1)
print(list(output_split_words_1))
print(output_split_words_1)
segmentor.release()
['你', '|', '认', '为', '|', '人', '工', '智', '能', '|', '、', '|', '机', '器', '学', '习', '|', '和', '|', '深', '度', '学', '习', '|', '的', '|', '关', '系', '|', '是', '|', '什', '么', '|', '?']
你|认为|人工智能|、|机器学习|和|深度学习|的|关系|是|什么|?
个性化分词
pyltp还支持个性化分词:个性化分词为了解决测试数据切换到如小说、财经等不同于新闻领域的领域。 在切换到新领域时,用户只需要标注少量数据。 个性化分词会在原有新闻数据基础之上进行增量训练。 从而达到即利用新闻领域的丰富数据,又兼顾目标领域特殊性的目的。
# 个性化分词
from pyltp import CustomizedSegmentor
customized_segmentor = CustomizedSegmentor()
# 加载模型,第二个参数是您的增量模型路径
customized_segmentor.load(cws_model_path, '/path/to/your/customized_model')
words_2 = customized_segmentor.segment('你会机器学习中的随机森林吗')
print('\t'.join(words_2))
customized_segmentor.release()
# 个性化分词
from pyltp import CustomizedSegmentor
customized_segmentor = CustomizedSegmentor()
# 加载模型,第二个参数是您的增量模型路径
customized_segmentor.load(cws_model_path, '/path/to/your/customized_model')
words_2 = customized_segmentor.segment('你会机器学习中的随机森林吗')
print('\t'.join(words_2))
customized_segmentor.release()
词性标注
from pyltp import Postagger
# 词性标注模型路径,模型名称为`pos.model`
pos_model_path = os.path.join(LTP_DATA_DIR, 'pos.model')
postagger = Postagger(pos_model_path) # 初始化实例
postags = postagger.postag(words)
postags_1 = postagger.postag(words_1) # 词性标注
print( '\t'.join(postags))
print( '\t'.join(postags_1))
postagger.release() # 释放模型
['你', '认为', '人工智能', '、', '机器', '学习', '和', '深度', '学习', '的', '关系', '是', '什么', '?']
你|认为|人工智能|、|机器|学习|和|深度|学习|的|关系|是|什么|?
r v n wp n v c n v u n v r wp
如果添加了新的分词字典,那么当其进行词性标注时,会出现错误,如将“机器学习”误认为动词,因此词性标注时也可以使用外部词典:词性标注外部词典同样为一个文本文件,每行指定一个词,第一列指定单词,第二列之后指定该词的候选词性(可以有多项,每一项占一列),列与列之间用空格区分。
# 词性标注模型路径,模型名称为`pos.model`
pos_model_path = os.path.join(LTP_DATA_DIR, 'pos.model')
postagger_1 = Postagger(pos_model_path,lexicon_path='dict.txt') # 初始化实例,加载模型
# 标注结果
postags_2 = postagger_1.postag(words_1) # 词性标注
print(list(postags_2))
postagger_1.release() # 释放模型
['你', '认为', '人工智能', '、', '机器学习', '和', '深度学习', '的', '关系', '是', '什么', '?']
你|认为|人工智能|、|机器学习|和|深度学习|的|关系|是|什么|?
['r', 'v', 'n', 'wp', 'n', 'c', 'n', 'u', 'n', 'v', 'r', 'wp']
命名实体识别NER
B、I、E、S
位置标签和实体类型标签之间用一个横线 - 相连;O
标签后没有类型标签。
- 旧版本写法
from pyltp import NamedEntityRecognizer
import os
LTP_DATA_DIR = 'E:/ltp_data_v3.4.0'
# 命名实体识别模型路径,模型名称为`ner.model`
ner_model_path = os.path.join(LTP_DATA_DIR, 'ner.model')
recognizer = NamedEntityRecognizer()
recognizer.load(ner_model_path)
# 命名实体识别
words_4 = ['奥巴马','住','在','纽约']
postags_4 = ['nh','v','r','ns']
netags = recognizer.recognize(words_4, postags_4)
print( '\t'.join(netags))
recognizer.release()
- 新版本写法
from pyltp import NamedEntityRecognizer
import os
LTP_DATA_DIR = 'E:/ltp_data_v3.4.0'
# 命名实体识别模型路径,模型名称为`ner.model`
ner_model_path = os.path.join(LTP_DATA_DIR, 'ner.model')
recognizer = NamedEntityRecognizer(ner_model_path)
# 命名实体识别
words_4 = ['奥巴马','住','在','纽约']
postags_4 = ['nh','v','r','ns']
netags = recognizer.recognize(words_4, postags_4)
print('\t'.join(words_4))
print('\t'.join(postags_4))
print( '\t'.join(netags))
recognizer.release()
奥巴马 住 在 纽约
nh v r ns
S-Nh O O B-Ns
依存句法分析
- 旧版本写法
# 依存句法分析模型路径,模型名称为`parser.model`
par_model_path = os.path.join(LTP_DATA_DIR, 'parser.model')
parser = Parser()
parser.load(par_model_path)
# 句法分析
arcs = parser.parse(words_4, postags_4)
print("\t".join("%d:%s" % (arc.head, arc.relation) for arc in arcs))
parser.release()
- 新版本写法
from pyltp import Parser
import os
LTP_DATA_DIR = 'E:/ltp_data_v3.4.0'
# 依存句法分析模型路径,模型名称为`parser.model`
par_model_path = os.path.join(LTP_DATA_DIR, 'parser.model')
parser = Parser(par_model_path)
# 句法分析
words_4 = ['奥巴马','住','在','纽约']
postags_4 = ['nh','v','r','ns']
arcs = parser.parse(words_4, postags_4)
print("\t".join("%d:%s" % (arc[0], arc[1]) for arc in arcs))
parser.release()
2:SBV 0:HED 2:CMP 3:POB
其中,words_4
和 postags_4
分别为分词和词性标注的结果。同样支持Python
原生的list
类型。
- 旧版本
arc.head
表示依存弧的父节点词的索引。ROOT
节点的索引是0
,第一个词开始的索引依次为1、2、3…
。
arc.relation
表示依存弧的关系。
那么,2:SBV
就表示当前词“奥巴马”和第二个词也就是“住”是主谓关系。
语义角色标注
注意:对windows
系统此处模型加载必须为pisrl_win.model
,下载地址在官网下载界面http://model.scir.yunfutech.com/server/3.4.0/pisrl_win.model。
- 旧版本写法
from pyltp import SementicRoleLabeller
srl_model_path = os.path.join(LTP_DATA_DIR, 'pisrl_win.model')
labeller = SementicRoleLabeller()
labeller.load(srl_model_path)
# arcs 使用依存句法分析的结果
roles = labeller.label(words_4, postags_4, 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() # 释放模型
- 新版本写法
from pyltp import Parser
import os
LTP_DATA_DIR = 'E:/ltp_data_v3.4.0'
# 依存句法分析模型路径,模型名称为`parser.model`
par_model_path = os.path.join(LTP_DATA_DIR, 'parser.model')
parser = Parser(par_model_path)
# 句法分析
words_4 = ['奥巴马','住','在','纽约']
postags_4 = ['nh','v','r','ns']
arcs = parser.parse(words_4, postags_4)
from pyltp import SementicRoleLabeller
srl_model_path = os.path.join(LTP_DATA_DIR, 'pisrl_win.model')
labeller = SementicRoleLabeller(srl_model_path)
# arcs 使用依存句法分析的结果
roles = labeller.label(words_4, postags_4, arcs) # 语义角色标注
# 打印结果
for role in roles:
print (role)
labeller.release() # 释放模型
第一个词开始的索引依次为0、1、2…
返回结果 roles
是关于多个谓词的语义角色分析的结果。由于一句话中可能不含有语义角色,所以结果可能为空。
role.index
代表谓词的索引。role.arguments
代表关于该谓词的若干语义角色。arg.name
表示语义角色类型。arg.range.start
表示该语义角色起始词位置的索引。arg.range.end
表示该语义角色结束词位置的索引。