pyhanlp 停用词与用户自定义词典
hanlp的詞典模式
之前我們看了hanlp的詞性標注,現在我們就要使用自定義詞典與停用詞功能了,首先關于HanLP的詞性標注方式具體請看HanLP詞性標注集。
其核心詞典形式如下:
自定義詞典
自定義詞典有多種添加模式,首先是展示的一個小例子,展示了詞匯的動態增加與強行插入,刪除等。更復雜的內容請參考后邊的第二段代碼。
簡單的例子
from pyhanlp import *text = "攻城獅逆襲單身狗,迎娶白富美,走上人生巔峰" # 怎么可能噗哈哈!print(HanLP.segment(text))CustomDictionary = JClass("com.hankcs.hanlp.dictionary.CustomDictionary") CustomDictionary.add("攻城獅") # 動態增加 CustomDictionary.insert("白富美", "nz 1024") # 強行插入 #CustomDictionary.remove("攻城獅"); # 刪除詞語(注釋掉試試) CustomDictionary.add("單身狗", "nz 1024 n 1")# 展示該單詞詞典中的詞頻統計 展示分詞 print(CustomDictionary.get("單身狗")) print(HanLP.segment(text))# 增加用戶詞典,對其他分詞器同樣有效 # 注意此處,CRF分詞器將單身狗分為了n 即使單身狗:"nz 1024 n 1" CRFnewSegment = HanLP.newSegment("crf") print(CRFnewSegment.seg(text)) [攻城獅, 逆襲, 單身狗, ,, 迎娶, 白富美, ,, 走上, 人生, 巔峰] nz 1024 n 1 [攻城獅, 逆襲, 單身狗, ,, 迎娶, 白富美, ,, 走上, 人生, 巔峰] [攻城, 獅逆襲, 單身狗, ,, 迎娶, 白富美, ,, 走, 上, 人生, 巔峰]復雜的例子
""" 演示自定義詞性,以及往詞典中插入自定義詞性的詞語!!!由于采用了反射技術,用戶需對本地環境的兼容性和穩定性負責!!!TO-DO 如果使用了動態詞性之后任何類使用了switch(nature)語句,必須注冊每個類 """ # 對于系統中已有的詞性,可以直接獲取 Nature = JClass("com.hankcs.hanlp.corpus.tag.Nature") pc_nature = Nature.fromString("n") print(pc_nature) # 此時系統中沒有"電腦品牌"這個詞性 pc_nature = Nature.fromString("電腦品牌") print(pc_nature) # 我們可以動態添加一個 pc_nature = Nature.create("電腦品牌"); print(pc_nature) # 可以將它賦予到某個詞語 LexiconUtility = JClass("com.hankcs.hanlp.utility.LexiconUtility") LexiconUtility.setAttribute("蘋果電腦", pc_nature) # 或者 LexiconUtility.setAttribute("蘋果電腦", "電腦品牌 1000") # 它們將在分詞結果中生效 term_list = HanLP.segment("蘋果電腦可以運行開源阿爾法狗代碼嗎") print(term_list) for term in term_list:if term.nature == pc_nature:print("找到了 [{}] : {}\n".format(pc_nature, term.word))# 還可以直接插入到用戶詞典 CustomDictionary = JClass("com.hankcs.hanlp.dictionary.CustomDictionary") CustomDictionary.insert("阿爾法狗", "科技名詞 1024") StandardTokenizer = JClass("com.hankcs.hanlp.tokenizer.StandardTokenizer") StandardTokenizer.SEGMENT.enablePartOfSpeechTagging(True) # 依然支持隱馬詞性標注 term_list = HanLP.segment("蘋果電腦可以運行開源阿爾法狗代碼嗎") print(term_list) n None 電腦品牌 [蘋果電腦/電腦品牌, 可以/v, 運行/vn, 開源/v, 阿爾法/nrf, 狗/n, 代碼/n, 嗎/y] 找到了 [電腦品牌] : 蘋果電腦[蘋果電腦/電腦品牌, 可以/v, 運行/vn, 開源/v, 阿爾法狗/科技名詞, 代碼/n, 嗎/y]關于自定義詞典的說明(原作者的原文)
- 說明
- CustomDictionary是一份全局的用戶自定義詞典,可以隨時增刪,影響全部分詞器。另外可以在任何分詞器中關閉它。通過代碼動態增刪不會保存到詞典文件。
- 中文分詞≠詞典,詞典無法解決中文分詞,Segment提供高低優先級應對不同場景,請參考FAQ。
- 追加詞典
- CustomDictionary主詞典文本路徑是data/dictionary/custom/CustomDictionary.txt,用戶可以在此增加自己的詞語(不推薦);也可以單獨新建一個文本文件,通過配置文件CustomDictionaryPath=data/dictionary/custom/CustomDictionary.txt; 我的詞典.txt;來追加詞典(推薦)。
- 始終建議將相同詞性的詞語放到同一個詞典文件里,便于維護和分享。
- 詞典格式
- 每一行代表一個單詞,格式遵從[單詞] [詞性A] [A的頻次] [詞性B] [B的頻次] ... 如果不填詞性則表示采用詞典的默認詞性。
- 詞典的默認詞性默認是名詞n,可以通過配置文件修改:全國地名大全.txt ns;如果詞典路徑后面空格緊接著詞性,則該詞典默認是該詞性。
- 在統計分詞中,并不保證自定義詞典中的詞一定被切分出來。用戶可在理解后果的情況下通過Segment#enableCustomDictionaryForcing強制生效。
- 關于用戶詞典的更多信息請參考詞典說明一章(請看本文最后)。
停用詞
關于停用詞,我同樣先給出了一個簡單的例子,你可以使用這個例子來完成你所需要的功能。要注意的一點是,因為java中的類所返回的數據類型與Python不統一,所以當你使用不同的函數的時候,一定要先檢查輸出結果在Python中的類型,不然可能會出現意想不到的問題。
假如你想了解更多,可以看第二個更復雜的例子。
簡單的例子
# 使用停用詞的簡單例子text = "小區居民有的反對喂養流浪貓" CRFnewSegment = HanLP.newSegment("crf") term_list = CRFnewSegment.seg(text) # BasicTokenizer = SafeJClass("com.hankcs.hanlp.tokenizer.BasicTokenizer") # term_list = BasicTokenizer.segment(text)CoreStopWordDictionary = JClass("com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary") CoreStopWordDictionary.apply(term_list) HanLP.Config.ShowTermNature = Falseprint(term_list) print([i.word for i in term_list]) [小區, 居民, 反對, 養, 流, 浪, 貓] ['小區', '居民', '反對', '養', '流', '浪', '貓']復雜的例子
# 停用詞# 在import pyhanlp之前編譯自己的Java class,并放入pyhanlp/static中 import osfrom pyhanlp.static import STATIC_ROOT, HANLP_JAR_PATHjava_code_path = os.path.join(STATIC_ROOT, 'MyFilter.java') with open(java_code_path, 'w') as out:java_code = """ import com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary; import com.hankcs.hanlp.dictionary.stopword.Filter; import com.hankcs.hanlp.seg.common.Term;public class MyFilter implements Filter {public boolean shouldInclude(Term term){if (term.nature.startsWith('m')) return true; // 數詞保留return !CoreStopWordDictionary.contains(term.word); // 停用詞過濾} } """out.write(java_code) os.system('javac -cp {} {} -d {}'.format(HANLP_JAR_PATH, java_code_path, STATIC_ROOT)) # 編譯結束才可以啟動hanlpCoreStopWordDictionary = JClass("com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary") Filter = JClass("com.hankcs.hanlp.dictionary.stopword.Filter") Term = JClass("com.hankcs.hanlp.seg.common.Term") BasicTokenizer = JClass("com.hankcs.hanlp.tokenizer.BasicTokenizer") NotionalTokenizer = JClass("com.hankcs.hanlp.tokenizer.NotionalTokenizer")text = "小區居民有的反對喂養流浪貓,而有的居民卻贊成喂養這些小寶貝" # 可以動態修改停用詞詞典 CoreStopWordDictionary.add("居民") print(NotionalTokenizer.segment(text)) CoreStopWordDictionary.remove("居民") print(NotionalTokenizer.segment(text))# 可以對任意分詞器的結果執行過濾 term_list = BasicTokenizer.segment(text) print(term_list) CoreStopWordDictionary.apply(term_list) print(term_list)# 還可以自定義過濾邏輯 MyFilter = JClass('MyFilter') CoreStopWordDictionary.FILTER = MyFilter() print(NotionalTokenizer.segment("數字123的保留")) # “的”位于stopwords.txt所以被過濾,數字得到保留 [小區/n, 反對/v, 喂養/v, 流浪貓/nz, 贊成/v, 喂養/v, 小寶貝/nz] [小區/n, 居民/n, 反對/v, 喂養/v, 流浪貓/nz, 居民/n, 贊成/v, 喂養/v, 小寶貝/nz] [小區/n, 居民/n, 有/vyou, 的/ude1, 反對/v, 喂養/v, 流浪貓/nz, ,/w, 而/cc, 有的/rz, 居民/n, 卻/d, 贊成/v, 喂養/v, 這些/rz, 小寶貝/nz] [小區/n, 居民/n, 反對/v, 喂養/v, 流浪貓/nz, 居民/n, 贊成/v, 喂養/v, 小寶貝/nz] [數字/n, 123/m, 保留/v]詞典說明(原作者原文)
本章詳細介紹HanLP中的詞典格式,滿足用戶自定義的需要。HanLP中有許多詞典,它們的格式都是相似的,形式都是文本文檔,隨時可以修改。
基本格式
詞典分為詞頻詞性詞典和詞頻詞典。
- 詞頻詞性詞典(如CoreNatureDictionary.txt)
- 每一行代表一個單詞,格式遵從[單詞] [詞性A] [A的頻次] [詞性B] [B的頻次] ...。
- 支持省略詞性和頻次,直接一行一個單詞。
- .txt詞典文件的分隔符為空格或制表符,所以不支持含有空格的詞語。如果需要支持空格,請使用英文逗號,分割的純文本.csv文件。在使用Excel等富文本編輯器時,則請注意保存為純文本形式。
- 詞頻詞典(如CoreNatureDictionary.ngram.txt)
- 每一行代表一個單詞或條目,格式遵從[單詞] [單詞的頻次]。
- 每一行的分隔符為空格或制表符。
少數詞典有自己的專用格式,比如同義詞詞典兼容《同義詞詞林擴展版》的文本格式,而轉移矩陣詞典則是一個csv表格。
下文主要介紹通用詞典,如不注明,詞典特指通用詞典。
數據結構
Trie樹(字典樹)是HanLP中使用最多的數據結構,為此,我實現了通用的Trie樹,支持泛型、遍歷、儲存、載入。
用戶自定義詞典采用AhoCorasickDoubleArrayTrie和二分Trie樹儲存,其他詞典采用基于雙數組Trie樹(DoubleArrayTrie)實現的AC自動機AhoCorasickDoubleArrayTrie。關于一些常用數據結構的性能評估,請參考wiki。
儲存形式
詞典有兩個形態:文本文件(filename.txt)和緩存文件(filename.txt.bin或filename.txt.trie.dat和filename.txt.trie.value)。
- 文本文件
- 采用明文儲存,UTF-8編碼,CRLF換行符。
- 緩存文件
- 就是一些二進制文件,通常在文本文件的文件名后面加上.bin表示。有時候是.trie.dat和.trie.value。后者是歷史遺留產物,分別代表trie樹的數組和值。
- 如果你修改了任何詞典,只有刪除緩存才能生效。
修改方法
HanLP的核心詞典訓練自人民日報2014語料,語料不是完美的,總會存在一些錯誤。這些錯誤可能會導致分詞出現奇怪的結果,這時請打開調試模式排查問題:(本文作者FontTian注:在本文動筆前,原詞典一進變為了9970萬版本的最大中文語料。但是詞典說明中原作者沒改)
HanLP.Config.enableDebug();- 核心詞性詞頻詞典
- 比如你在data/dictionary/CoreNatureDictionary.txt中發現了一個不是詞的詞,或者詞性標注得明顯不對,那么你可以修改它,然后刪除緩存文件使其生效。
- 目前CoreNatureDictionary.ngram.txt的緩存依賴于CoreNatureDictionary.txt的緩存,修改了后者之后必須同步刪除前者的緩存,否則可能出錯
- 核心二元文法詞典
- 二元文法詞典data/dictionary/CoreNatureDictionary.ngram.txt儲存的是兩個詞的接續,如果你發現不可能存在這種接續時,刪掉即可。
- 你也可以添加你認為合理的接續,但是這兩個詞必須同時在核心詞典中才會生效。
- 命名實體識別詞典
- 基于角色標注的命名實體識別比較依賴詞典,所以詞典的質量大幅影響識別質量。
- 這些詞典的格式與原理都是類似的,請閱讀相應的文章或代碼修改它。
總結
以上是生活随笔為你收集整理的pyhanlp 停用词与用户自定义词典的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pyhanlp 分词与词性标注
- 下一篇: pyhanlp 提取关键词、自动摘要