之前需要做一個(gè)中文命名實(shí)體識(shí)別的api檩帐,看完了一些相關(guān)論文以后覺(jué)得短時(shí)間內(nèi)自己實(shí)現(xiàn)不大現(xiàn)實(shí)患久,于是找了一些開(kāi)源工具厚骗,其中哈工大的LTP效果是很好的示启,但是免費(fèi)使用限流量,需要給錢才行领舰; NLPIR的pynlpir似乎還不能支持命名實(shí)體識(shí)別等復(fù)雜工作夫嗓,只能做一些分詞之類;最后還剩下Hanlp冲秽,感謝Hanlp的作者h(yuǎn)ancks無(wú)私的將代碼開(kāi)源舍咖,還提供了那么詳細(xì)的文檔。
pyhanlp只有少數(shù)功能锉桑,其他復(fù)雜一點(diǎn)的功能需要使用python調(diào)用java代碼來(lái)實(shí)現(xiàn)排霉。
以下是api的模型部分,大多是照著文檔寫(xiě)成的民轴。
python調(diào)用java需要jpype庫(kù)攻柠,具體安裝請(qǐng)參考之前的博客:jpype安裝的簡(jiǎn)便方法
# -*- coding: utf-8 -*-
"""
Created on Thu May 10 09:19:55 2018
@author: wang小堯
"""
import jpype
#路徑
jvmPath = jpype.getDefaultJVMPath() # 獲得系統(tǒng)的jvm路徑
ext_classpath = r"./ner/hanlp\hanlp-1.6.3.jar:./ner/hanlp"
jvmArg = '-Djava.class.path=' + ext_classpath
jpype.startJVM(jvmPath, jvmArg, "-Xms1g", "-Xmx1g")
#繁體轉(zhuǎn)簡(jiǎn)體
def TraditionalChinese2SimplifiedChinese(sentence_str):
HanLP = jpype.JClass('com.hankcs.hanlp.HanLP')
return HanLP.convertToSimplifiedChinese(sentence_str)
#切詞&命名實(shí)體識(shí)別與詞性標(biāo)注(可以粗略識(shí)別)
def NLP_tokenizer(sentence_str):
NLPTokenizer = jpype.JClass('com.hankcs.hanlp.tokenizer.NLPTokenizer')
return NLPTokenizer.segment(sentence_str)
#地名識(shí)別,標(biāo)注為ns
def Place_Recognize(sentence_str):
HanLP = jpype.JClass('com.hankcs.hanlp.HanLP')
segment = HanLP.newSegment().enablePlaceRecognize(True)
return HanLP.segment(sentence_str)
#人名識(shí)別,標(biāo)注為nr
def PersonName_Recognize(sentence_str):
HanLP = jpype.JClass('com.hankcs.hanlp.HanLP')
segment = HanLP.newSegment().enableNameRecognize(True)
return HanLP.segment(sentence_str)
#機(jī)構(gòu)名識(shí)別,標(biāo)注為nt
def Organization_Recognize(sentence_str):
HanLP = jpype.JClass('com.hankcs.hanlp.HanLP')
segment = HanLP.newSegment().enableOrganizationRecognize(True)
return HanLP.segment(sentence_str)
#標(biāo)注結(jié)果轉(zhuǎn)化成列表
def total_result(function_result_input):
x = str(function_result_input)
y = x[1:len(x)-1]
y = y.split(',')
return y
#時(shí)間實(shí)體
def time_result(total_result):
z = []
for i in range(len(total_result)):
if total_result[i][-2:] == '/t':
z.append(total_result[i])
return z
#Type_Recognition 可以選 ‘place’,‘person’,‘organization’三種實(shí)體,
#返回單一實(shí)體類別的列表
def single_result(Type_Recognition,total_result):
if Type_Recognition == 'place':
Type = '/ns'
elif Type_Recognition == 'person':
Type = '/nr'
elif Type_Recognition == 'organization':
Type = '/nt'
else:
print ('請(qǐng)輸入正確的參數(shù):(place后裸,person或organization)')
z = []
for i in range(len(total_result)):
if total_result[i][-3:] == Type:
z.append(total_result[i])
return z
#把單一實(shí)體結(jié)果匯總成一個(gè)字典
def dict_result(sentence_str):
sentence = TraditionalChinese2SimplifiedChinese(sentence_str)
total_dict = {}
a = total_result(Place_Recognize(sentence))
b = single_result('place',a)
c = total_result(PersonName_Recognize(sentence))
d = single_result('person',c)
e = total_result(Organization_Recognize(sentence))
f = single_result('organization',e)
g = total_result(NLP_tokenizer(sentence))
h = time_result(g)
total_list = [i for i in [b,d,f,h]]
total_dict.update(place = total_list[0],person = total_list[1],organization = total_list[2],time = total_list[3])
jpype.shutdownJVM()#關(guān)閉JVM虛擬機(jī)
return total_dict
#測(cè)試
test_sentence="2018年武勝縣新學(xué)鄉(xiāng)政府大樓門前鑼鼓喧天,6月份藍(lán)翔給寧夏固原市彭陽(yáng)縣紅河鎮(zhèn)捐贈(zèng)了挖掘機(jī),中國(guó)科學(xué)院計(jì)算技術(shù)研究所的宗成慶教授負(fù)責(zé)教授自然語(yǔ)言處理課程,而他的學(xué)生現(xiàn)在正在香港看肉蒲團(tuán)"
print (dict_result(test_sentence))
識(shí)別結(jié)果:
{'place': [' 武勝縣/ns', ' 寧夏/ns', ' 固原市/ns', ' 彭陽(yáng)縣/ns', ' 紅河鎮(zhèn)/ns', ' 香港/ns'], 'person': [' 宗成慶/nr'], 'organization': [' 藍(lán)翔/nt', ' 中國(guó)科學(xué)院計(jì)算技術(shù)研究所/nt'], 'time': ['2018年/t', ' 6月份/t', ' 現(xiàn)在/t']}
遇到的問(wèn)題:
在弄這個(gè)api時(shí)遇到了一些問(wèn)題瑰钮,就是當(dāng)我打開(kāi)java虛擬機(jī)JVM,功能正常使用完關(guān)閉了JVM微驶,但是再打開(kāi)的時(shí)候就會(huì)報(bào)錯(cuò)浪谴,所以得一直保持一個(gè)JVM一直打開(kāi)的狀態(tài),或者重啟kernel才行因苹。網(wǎng)上找了找也沒(méi)能找到靠譜的解決方案苟耻,這個(gè)問(wèn)題只有以后慢慢解決了。如果有人知道如何處理容燕,可以給我發(fā)私信梁呈。