完整的代码和模型文件可在我的GitHub:(代码是 linux 版本,windows 上运行只需要简单调整)
https://github.com/ouprince/pyltp-stanford-nlp
LTP 训练套件:https://ltp.readthedocs.io/zh_CN/latest/train.html
pyltp 使用: https://blog.csdn.net/mebiuw/article/details/52496920
windows 下运行调整如下:将父类 StanfordCoreNLP 中 buildjars 函数中的 : 改成 ; 即可
# -*- coding:utf-8 -*-
import sys
import os
# 定义所有 StanfordNLP 的父类
class StanfordCoreNLP(object):
def __init__(self,jarpath):
self.root = jarpath
self.tempsrcpath = "tempsrc"
self.jarlist = ["ejml-0.23.jar","javax.json.jar","jollyday.jar","joda-time.jar","protobuf.jar",\
"slf4j-api.jar","slf4j-simple.jar","stanford-corenlp-3.9.2.jar","xom.jar"]
self.jarpath = ""
self.buildjars()
def buildjars(self):
for jar in self.jarlist:
self.jarpath += self.root + jar + ":" # 注意如果是 windows 是 ;
def savefile(self,path,sent):
fp = open(path,"w")
fp.write(sent)
fp.close()
def delfile(self,path):
os.remove(path)
# 词性标注
class StanfordPOSTagger(StanfordCoreNLP):
def __init__(self,jarpath,modelpath):
StanfordCoreNLP.__init__(self,jarpath)
self.modelpath = modelpath
self.classfier = "edu.stanford.nlp.tagger.maxent.MaxentTagger" # 词性标注主类
self.delimiter = "/"
self.__buildcmd()
def __buildcmd(self):
self.cmdline = 'java -mx1g -cp "' + self.jarpath + '" ' + self.classfier + ' -model "' + self.modelpath + \
'" -tagSeparator ' + self.delimiter
# 标注句子
def tag(self,sent):
self.savefile(self.tempsrcpath,sent)
tagtxt = os.popen(self.cmdline + ' -textFile ' + self.tempsrcpath,'r').read()
self.delfile(self.tempsrcpath)
return tagtxt
# 标注文件
def tagfile(self,inputpath,output):
os.system(self.cmdline + ' -textFile ' + inputpath + ' > '+ output)
(1) pyltp 使用范例如下
# -*- coding:utf-8 -*-
import sys
import os
from pyltp import Segmentor,Postagger,NamedEntityRecognizer # 分别导入分词,词性标注,实体识别模块
from pyltp import SementicRoleLabeller # 复杂的语义角色标注模块
reload(sys)
sys.setdefaultencoding("utf-8")
# 加载分词模型
model_path = "ltp3.4/cws.model"
if not os.path.exists(model_path):
print "model path is not exists"
sys.exit()
''' 1.分词 '''
segmentor = Segmentor()
segmentor.load_with_lexicon(model_path,"ltp3.3/userdict.txt") # 加载分词模型和用户字典
words = segmentor.segment("在包含问题的所有解的解空间树中")
print "|".join(words)
print "*"*30
''' 2.词性标注 '''
sent = "在 包含 问题 的 所有 解 的 解空间树 中"
words = sent.split()
postagger = Postagger()
postagger.load("ltp3.4/pos.model") # 导入词性标注模型
postags = postagger.postag(words)
for word,postag in zip(words,postags):
print word,postag
print "*" *30
''' 3.实体识别,人名,地名,机构名或其他专有名词 '''
sent = "欧洲 东部 的 罗马尼亚 , 首都 是 布加勒斯特 ,也是 一座 世界性 的 城市"
words = sent.split()
postags = postagger.postag(words) # 需要先词性标注
recognizer = NamedEntityRecognizer()
recognizer.load("ltp3.4/ner.model") # 实体识别模型
netags = recognizer.recognize(words,postags)
for word,netag in zip(words,netags):
print word,netag
print "*" * 30
''' 4.句法依存树句法解析 '''
import nltk
from nltk.tree import Tree # 导入 nltk tree 结构
from nltk.grammar import DependencyGrammar # 导入依存句法包
from nltk.parse import *
from pyltp import Parser
words = "罗马尼亚 的 首都 是 布加勒斯特 。".split()
postags = postagger.postag(words) # 先词性标注
parser = Parser() # 将词性标注和分词结果都加入分析器中进行句法解析
parser.load("ltp3.4/parser.model")
arcs = parser.parse(words,postags)
arclen = len(arcs)
conll = ""
for i in xrange(arclen): # 构建Conll 标准的数据结构
if arcs[i].head == 0:
arcs[i].relation = "ROOT"
conll += "\t"+words[i] +"(" + postags[i] + ")" + "\t" + postags[i] + "\t" + str(arcs[i].head) + "\t" \
+ arcs[i].relation + "\n"
print conll
print "*" * 30
''' 5.最复杂的模块,角色标注模块,需要分词,词性标注,实体识别,句法解析的结果进行进一步分析 '''
sentence = "欧洲东部的罗马尼亚,首都是布加勒斯特,也是一座世界性的城市。"
# 分词
words = " ".join(segmentor.segment(sentence))
wordlist = words.split()
# 词性标注
postags = postagger.postag(wordlist)
# 句法解析
arcs = parser.parse(wordlist,postags)
# 实体识别
netags = recognizer.recognize(wordlist,postags)
# 接下来导入语义角色标注模块
MODEL_DIR = "ltp3.4/pisrl.model"
labeller = SementicRoleLabeller()
labeller.load(MODEL_DIR) # 导入模型
roles = labeller.label(wordlist,postags,netags,arcs)
for role in roles:
print "rel:",wordlist[role.index] # 谓词
for arg in role.arguments:
if arg.range.start != arg.range.end:
print arg.name," ".join(wordlist[arg.range.start:arg.range.end])
else:
print arg.name,wordlist[arg.range.start]
关于 ltp 的标记说明可参考:https://blog.csdn.net/hit_lingo/article/details/42639455
(2) stanford 使用范例如下
# -*- coding:utf-8 -*-
import sys,os
reload(sys)
sys.setdefaultencoding("utf-8")
curdir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(curdir)
from nltk import Tree
''' (1) stanford 中文词性标注 '''
from stanford_postagger.stanford import StanfordPOSTagger
root = os.path.join(curdir,"stanford_corenlp/")
modelpath = os.path.join(root,"models","pos-tagger","chinese-distsim","chinese-distsim.tagger")
st = StanfordPOSTagger(root,modelpath)
seg_sent = "在 包含 问题 的 所有 解 的 解空间 树 中"
tag_list = st.tag(seg_sent)
print tag_list
''' (2) stanford 中文实体识别 '''
from stanford_ner.stanford import StanfordNERTagger
modelpath = os.path.join(root,"models","ner","chinese.misc.distsim.crf.ser.gz")
st = StanfordNERTagger(root,modelpath)
seg_sent = "欧洲 东部 的 罗马尼亚 , 首都 是 布加勒斯特 , 也是 一座 世界性 的 城市"
taglist = st.tag(seg_sent)
print taglist
''' (3) stanford 句法解析之短语结构解析 '''
from stanford_parser.stanford import StanfordParser
modelpath = os.path.join(root,"models","lexparser","chinesePCFG.ser.gz")
opttype = "penn" # 宾州树格式 或者说 短语结构树
parser = StanfordParser(root,modelpath,opttype)
result = parser.parse("罗马尼亚 的 首都 是 布加勒斯特 。")
print result
# 可用 nltk 工具可视化结果
'''
tree = Tree.fromstring(result)
tree.draw()
'''
''' (4) stanford 句法解析之句法依存树 '''
opttype = "typedDependencies" # 句法依存树
parser = StanfordParser(root,modelpath,opttype)
result = parser.parse("罗马尼亚 的 首都 是 布加勒斯特 。")
print result
关于 stanford 标记说明可参考:https://blog.csdn.net/u011847043/article/details/79595225