HanLP分詞工具中的ViterbiSegment分詞流程


本篇文章將重點講解HanLP的ViterbiSegment分詞器類,而不涉及感知機和條件隨機場分詞器,也不涉及基於字的分詞器由於這些分詞器都不是咱們在實踐中經常使用的,並且ViterbiSegment也是做者直接封裝到HanLP類中的分詞器,做者也推薦使用該分詞器,同時文本分類包以及其餘一些天然語言處理任務包中的分詞器也都間接使用了ViterbiSegment分詞器。java

今天的文章還會介紹各分詞詞典文件的使用位置以及做用,相信小夥伴們看了今天的文章應該不會再在github上提出干預自定義不生效的問題了進入正題,本篇的內容比較多,建議收藏後再細讀。git

1. 分詞器配置變量github

分詞器的相關配置定義在Config.java類中,這裏咱們將分詞相關的全部配置變量列於下表多線程

 

圖1.jpg

這種配置類何時實例化呢,不用想確定是分詞開始前就會實例化,拿HanLP類中的ViterbiSegment分詞類舉例。該類的繼承關係用以下圖所示:ide

 圖2.jpg

由繼承關係圖能夠看到,只要實例化ViterbiSegment則首先會執行Segment()初始化,在該方法中實例化分詞器配置對象config。這些配置變量都是公有變量,所以能夠在ViterbiSegment類實例化爲對象後直接在外部修改。那麼何時來使用這些配置變量呢,固然是在分詞的時候,具體是哪一個類的哪一個方法呢,固然是ViterbiSegment類的List<Term> segSentence(char[] sentence)方法。學習

另外請注意上邊的3個類,全部ViterbiSegment的分詞方法都集中在這3個類中。spa

2. 詞典的使用條件和前後順序(也介紹分詞流程)線程

咱們知道了詞典配置變量使用的位置後,就能夠肯定每一個詞典的使用條件了以及每一個詞典的使用順序對象

1. 詞語粗分繼承

1)構建詞圖

對應方法爲void generateWordNet(final WordNet wordNetStorage),在此方法中系統使用CoreNatureDictionary.txt文件切分出全部可能的分詞路徑。此時若是配置變量useCustomDictionary爲true,則將CustomDictionary.txt中的詞也考慮進來,說明CustomDictionary.txt優先級會高。另外你們能夠看到CoreNatureDictionary.txt實際上也充當了隱馬詞性標註的發射矩陣,裏邊某些多詞性詞也列出了詞性序列以及各詞性對應的頻次。

2)用戶定製詞典干預

若是配置變量useCustomDictionary爲true,即須要使用CustomDictionary.txt進行干預,則執行下邊對應的方法,不然跳過該步驟。用戶詞典干預根據是否進行全切分有兩種不一樣方法:當配置變量indexMode>0時,即系統處於全切分模式時,對應方法爲

 

List<Vertex> combineByCustomDictionary(List<Vertex> vertexList, DoubleArrayTrie<CoreDictionary.Attribute> dat, final WordNet wordNetAll),

 

若是indexMode=0,即系統處於普通分詞模式,對應方法爲

 

List<Vertex> combineByCustomDictionary(List<Vertex> vertexList, DoubleArrayTrie<CoreDictionary.Attribute> dat)。

 

從調用的方法咱們不難看出,全切分時系統會根據CustomDictionary.txt添加分詞路徑。而普通切分時,系統會根據CustomDictionary.txt合併路徑。這也就是爲何有的時候明明已經在CustomDictionary.txt中添加了新詞卻不生效的緣由,由於一旦根據CoreNatureDictionary.txt構建了詞圖就不會再有新的路徑插到已有分詞路徑中間,此時就去查找並修改CoreNatureDictionary.txt中的相關字或詞吧。

 

3)維特比選擇最優路徑

對應方法爲List<Vertex> viterbi(WordNet wordNet),至此就獲得了一個粗分的分詞結果。須要注意HanLP的Viterbi分詞只是用viterbi方法求解最優路徑,並非隱馬。

3. 數字識別

若是配置變量numberQuantifierRecognize爲true,則在粗分結果的基礎上進行數字合併操做,不然直接跳過該步。對應方法爲

void mergeNumberQuantifier(List<Vertex> termList, WordNet wordNetAll, Config config)。

4. 實體識別

配置變量ner爲true時,則須要進行各類實體的識別,繼續向下執行。須要注意該變量受其餘實體識別變量影響,只要其餘任意實體配置變量爲true,則ner就會爲true。若是ner爲false,則跳過下邊各項實體識別繼續詞性標註環節。

1)中國人名識別

執行此步,配置變量nameRecognize必須爲true。調用方法爲

PersonRecognition.recognition(vertexList, wordNetOptimum, wordNetAll)。人名使用隱馬,所以有轉移矩陣nr.tr.txt和發射矩陣nr.txt。因爲HanLP不提供訓練語料,咱們本身也很可貴到有角色標註的語料,所以咱們通常只修改nr.txt文件,刪除nr.txt.bin文件後生效。

2)音譯人名識別

執行此步,配置變量translatedNameRecognize必須爲true。調用方法爲

TranslatedPersonRecognition.recognition(vertexList, wordNetOptimum, wordNetAll)。須要注意音譯人名的識別沒有用隱馬,就是匹配分詞法。涉及到的詞典爲nrf.txt,若是用戶修改該詞典,則須要刪除nrf.txt.trie.dat使其生效。

3)日本人名識別

執行此步,配置變量japaneseNameRecognize必須爲true。調用方法爲

JapanesePersonRecognition.recognition(vertexList, wordNetOptimum, wordNetAll)。須要注意日本人名的識別沒有用隱馬,就是匹配分詞法。涉及到的詞典爲nrj.txt,若是用戶修改該詞典,則須要刪除nrj.txt.trie.dat和nrj.txt.value.dat使其生效。

4)地名識別

執行此步,配置變量placeRecognize必須爲true。調用方法爲

PlaceRecognition.recognition(vertexList, wordNetOptimum, wordNetAll)。地名使用隱馬,所以有轉移矩陣ns.tr.txt和發射矩陣ns.txt。因爲HanLP不提供訓練語料,咱們本身也很可貴到有角色標註的語料,所以咱們通常只修改ns.txt文件,刪除ns.txt.bin文件後生效。

5)機構名識別

執行此步,配置變量organizationRecognize必須爲true。調用方法爲

OrganizationRecognition.recognition(vertexList, wordNetOptimum, wordNetAll)。注意這裏在調用機構名識別以前先進行了一次識別,也就是層疊隱馬,而人名和地名的識別就是普通的隱馬。機構名的識別使用層疊隱馬,涉及的文件有轉移矩陣nt.tr.txt和發射矩陣nt.txt。因爲HanLP不提供訓練語料,咱們本身也很可貴到有角色標註的語料,所以咱們通常只修改nt.txt文件,刪除ns.txt.bin文件後生效。機構名的識別須要人名地名識別具備較高準確率。

至此,分詞流程已所有介紹了。

還須要注意下邊的內容

 

其餘沒有在系統中使用的詞典有

機構名詞典.txt

全國地名大全.txt

人名詞典.txt

上海地名.txt

現代漢語補充詞庫.txt

這些詞典是對系統中的詞典的更新記錄,若是你添加了新的人名、地名、機構名能夠在這裏添加保存。

另外,若是須要添加人名、地名、機構名能夠直接在CoreNatureDictionary.txt中添加,最好是3字以上實體,

若是要去掉錯誤識別的命名實體能夠直接在相應的nr.txt,ns.txt,nt.txt中添加。

3. 多線程分詞

HanLP的ViterbiSegment分詞器類是支持多線程的,線程數量由配置變量threadNumber決定的,該變量默認爲1。HanLP做者說ViterbiSegmet分詞效率最高的緣由確定也有ViterbiSegment分詞器支持多線程分詞這個因素。另外因爲ViterbiSegment分詞器內部所具備的相關命名實體功能,所以這些命名實體識別的效率也會很高。在哪裏實現的多線程分詞呢,在Segment類的List<Term> seg(String text)這個方法中實現的,須要注意HanLP的多線程分詞指的是一次輸入了一個長文本,而不是一次處理多個輸入文本。

本文分享自 baiziyu 的專欄,正文內容已經作了部分修改,便於你們閱讀,歡迎一塊兒交流學習!

相關文章
相關標籤/搜索