中文NLP(1) -- 开源工具 ltp 和 stanford

完整的代码和模型文件可在我的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值