pyhanlp 分词与词性标注
pyhanlp中的分詞器簡介
pyhanlp實現的分詞器有很多,同時pyhanlp獲取hanlp中分詞器也有兩種方式
第一種是直接從封裝好的hanlp類中獲取,這種獲取方式一共可以獲取五種分詞器,而現在默認的就是第一種維特比分詞器
- 維特比 (viterbi):效率和效果的最佳平衡。也是最短路分詞,HanLP最短路求解采用Viterbi算法
- 雙數組trie樹 (dat):極速詞典分詞,千萬字符每秒(可能無法獲取詞性,此處取決于你的詞典)
- 條件隨機場 (crf):分詞、詞性標注與命名實體識別精度都較高,適合要求較高的NLP任務
- 感知機 (perceptron):分詞、詞性標注與命名實體識別,支持在線學習
- N最短路 (nshort):命名實體識別稍微好一些,犧牲了速度
第二種方式是使用JClass直接獲取java類,然后使用。這種方式除了獲取上面的五種分詞器以外還可以獲得一些其他分詞器,如NLP分詞器,索引分詞,快速詞典分詞等等
兩種使用方式的對比
第一種是使用作者給的HanLP直接獲取分詞器,直接segment() 會獲取 默認的標準分詞器也就是維特比分詞器,也**可以使用newSegment函數,傳入上面的分詞器英文名稱來獲取新的分詞器,如使用HanLP.newSegment("crf")來獲取CRF分詞器。**第二種方式是使用JClass從java中獲取我們想要的類,好在這兩種方式都比較方便。除此之外要注意的是,在pyhanlp中還給出了SafeJClass類,其為JClass的線程安全版,你也可以使用SafeClass來代替JClass。不過好在HanLP中的很多類本身已經實現了線程安全,因此許多時候兩者是可以相互替代的。
from pyhanlp import * # 第一個demoprint(HanLP.segment("你好,歡迎使用HanLP漢語處理包!接下來請從其他Demo中體驗HanLP豐富的功能~"))# HanLP詞性標注集: http://www.hankcs.com/nlp/part-of-speech-tagging.html#h2-8 [你好/vl, ,/w, 歡迎/v, 使用/v, HanLP/nx, 漢語/gi, 處理/vn, 包/v, !/w, 接下來/vl, 請/v, 從/p, 其他/rzv, Demo/nx, 中/f, 體驗/v, HanLP/nx, 豐富/a, 的/ude1, 功能/n, ~/nx] # 標準分詞 text = ("舉辦紀念活動銘記二戰歷史,不忘戰爭帶給人類的深重災難,是為了防止悲劇重演,確保和平永駐;記二戰歷史,更是為了提醒國際社會,需要共同捍衛二戰勝利成果和國際公平正義,必須警惕和抵制在歷史認知和維護戰后國際秩序問題上的倒行逆施。" )BasicTokenizer = JClass("com.hankcs.hanlp.tokenizer.BasicTokenizer") print(BasicTokenizer.segment(text))import time start = time.time() for i in range(100000):HanLP.segment(text) cost_time = time.time() - start print("HanLP.segment :%.2f字每秒" % (len(text) * 100000 / cost_time))start = time.time() for i in range(100000):BasicTokenizer.segment(text) cost_time = time.time() - start print("BasicTokenizer.segment :%.2f字每秒" % (len(text) * 100000 / cost_time)) [舉辦/v, 紀念活動/nz, 銘記/v, 二戰/n, 歷史/n, ,/w, 不忘/v, 戰爭/n, 帶給/v, 人類/n, 的/ude1, 深重/a, 災難/n, ,/w, 是/vshi, 為了/p, 防止/v, 悲劇/n, 重演/v, ,/w, 確保/v, 和平/n, 永駐/nz, ;/w, 記/v, 二戰/n, 歷史/n, ,/w, 更是/d, 為了/p, 提醒/v, 國際/n, 社會/n, ,/w, 需要/v, 共同/d, 捍衛/v, 二戰/n, 勝利/vn, 成果/n, 和/cc, 國際/n, 公平/a, 正義/n, ,/w, 必須/d, 警惕/v, 和/cc, 抵制/v, 在/p, 歷史/n, 認知/vn, 和/cc, 維護/v, 戰后/t, 國際/n, 秩序/n, 問題/n, 上/f, 的/ude1, 倒行逆施/vl, 。/w] HanLP.segment :1518389.32字每秒 BasicTokenizer.segment :2415039.64字每秒僅僅從剛剛的結果看,可能會不太理解為同一個分詞器性能差距這么大?難道是因為中間代碼的調度問題,其實也不是。將兩段代碼前后互換之后,發現無論兩者怎么排列,總是在前的速度較慢,在后的較快,因此應該是內存的問題,第二次調用時減少了部分內存的調動。所以同一個分詞器才會出現,第二次總比第一次快的現象。
標準分詞
- 說明
- HanLP中有一系列“開箱即用”的靜態分詞器,以Tokenizer結尾,在接下來的例子中會繼續介紹。
- HanLP.segment其實是對StandardTokenizer.segment的包裝。
- 分詞結果包含詞性,每個詞性的意思請查閱《HanLP詞性標注集》。
- 算法詳解
- 《詞圖的生成》
單獨獲取詞性或者詞語
如你所見的是,前面print的結果是[詞語/詞性,詞語/詞性,/詞語/詞性…]的形式,那么如果我們只想獲取詞語,或者詞性應該怎么辦呢?
方法也很簡單。使用HanLP.Config.ShowTermNature = False修改配置,使其不顯示詞性即可。
如果想要只獲取詞性也是可以的,因為原分詞器返回的是Java中的ArrayList屬性,list中的每個單元都是一個term類,因此我們也可以通過獲取term中的word字段來直接獲取詞語,或者nature屬性,直接獲取詞性。這一特征,我們在之后也會用到。
因為HanLP中是默認開啟詞性標注的,所以在這里我取名為分詞與詞性標注,但是因為篇幅原因這里沒有對詞性標注作過多解釋,詳細內容請看“詞性標注(正篇)”
HanLP.Config.ShowTermNature = False text = "小區居民有的反對喂養流浪貓" CRFnewSegment = HanLP.newSegment("crf") term_list = CRFnewSegment.seg(text) print(term_list) HanLP.Config.ShowTermNature = TrueCRFnewSegment = HanLP.newSegment("crf") term_list = CRFnewSegment.seg(text) print(term_list) print([str(i.word) for i in term_list]) print([str(i.nature) for i in term_list]) [小區, 居民, 有的, 反對, 喂, 養, 流, 浪, 貓] [小區/n, 居民/n, 有的/r, 反對/v, 喂/v, 養/v, 流/v, 浪/n, 貓/v] ['小區', '居民', '有的', '反對', '喂', '養', '流', '浪', '貓'] ['n', 'n', 'r', 'v', 'v', 'v', 'v', 'n', 'v']其他分詞器的代碼實現與速度對比
到這里,分詞與詞性標注的主要功能其實已經講的差不多了,后邊是其他分詞器的代碼展示以及部分其他內容,本人建議最起碼通讀一遍,如果只想獲取詞性或者詞語的話可以按照剛剛的寫法進行修改,如果需要了解原理則可以點開相應鏈接。
NLP 分詞
- 說明
- NLP分詞NLPTokenizer會執行詞性標注和命名實體識別,由結構化感知機序列標注框架支撐。
- 默認模型訓練自9970萬字的大型綜合語料庫,是已知范圍內全世界最大的中文分詞語料庫。語料庫規模決定實際效果,面向生產環境的語料庫應當在千萬字量級。歡迎用戶在自己的語料上訓練新模型以適應新領域、識別新的命名實體。
索引分詞
- 說明
- 索引分詞IndexTokenizer是面向搜索引擎的分詞器,能夠對長詞全切分,另外通過term.offset可以獲取單詞在文本中的偏移量。
- 任何分詞器都可以通過基類Segment的enableIndexMode方法激活索引模式。
最短路分詞&N最短路分詞(寫法一)
- 說明
- N最短路分詞器NShortSegment比最短路分詞器慢,但是效果稍微好一些,對命名實體識別能力更強。
- 一般場景下最短路分詞的精度已經足夠,而且速度比N最短路分詞器快幾倍,請酌情選擇。
- 算法詳解
- 《N最短路徑的Java實現與分詞應用》
最短路分詞&N最短路分詞(寫法二)
# 最短路分詞&N最短路分詞NShortSegment = JClass("com.hankcs.hanlp.seg.NShort.NShortSegment") Segment = JClass("com.hankcs.hanlp.seg.Segment") ViterbiSegment = JClass("com.hankcs.hanlp.seg.Viterbi.ViterbiSegment")nshort_segment = NShortSegment().enableCustomDictionary(False).enablePlaceRecognize(True).enableOrganizationRecognize(True) shortest_segment = ViterbiSegment().enableCustomDictionary(False).enablePlaceRecognize(True).enableOrganizationRecognize(True)for sentence in sentences:print("N-最短分詞:{} \n最短路分詞:{}".format(nshort_segment.seg(sentence), shortest_segment.seg(sentence)))print("\n==========||==========\n")print("下面對最短路徑分詞器與N最短路徑分詞器進行速度對比") import time pressure = 10000start = time.time() for i in range(pressure):nshort_segment.seg(text) cost_time = time.time() - start print("nshort_segment分詞速度:%.2f字每秒" % (len(text) * pressure / cost_time))start = time.time() for i in range(pressure):shortest_segment.seg(text) cost_time = time.time() - start print("shortest_segment分詞速度:%.2f字每秒" % (len(text) * pressure / cost_time)) N-最短分詞:[今天/t, ,/w, 劉志軍/nr, 案/ng, 的/ude1, 關鍵/n, 人物/n, ,/w, 山西/ns, 女/b, 商人/nnt, 丁書苗/nr, 在/p, 市二中院/nt, 出庭/vi, 受審/vi, 。/w] 最短路分詞:[今天/t, ,/w, 劉志軍/nr, 案/ng, 的/ude1, 關鍵/n, 人物/n, ,/w, 山西/ns, 女/b, 商人/nnt, 丁書苗/nr, 在/p, 市/n, 二中院/nt, 出庭/vi, 受審/vi, 。/w] N-最短分詞:[江西省監獄管理局/nt, 與/cc, 中國/ns, 太平洋/ns, 財產保險股份有限公司南昌中心支公司/nt, 保險/n, 合同/n, 糾紛案/nz] 最短路分詞:[江西省監獄管理局/nt, 與/cc, 中國/ns, 太平洋/ns, 財產保險股份有限公司南昌中心支公司/nt, 保險/n, 合同/n, 糾紛案/nz] N-最短分詞:[新北商貿有限公司/nt] 最短路分詞:[新北商貿有限公司/nt]==========||==========下面對最短路徑分詞器與N最短路徑分詞器進行速度對比 nshort_segment分詞速度:140187.31字每秒 shortest_segment分詞速度:321353.36字每秒CRF分詞
- 說明
- CRF對新詞有很好的識別能力,但是開銷較大。
- 算法詳解
- 《CRF中文分詞、詞性標注與命名實體識別》
極速詞典分詞
- 說明
- 極速分詞是詞典最長分詞,速度極其快,精度一般。
- 在i7-6700K上跑出了4500萬字每秒的速度。
- 算法詳解
- 《Aho Corasick自動機結合DoubleArrayTrie極速多模式匹配》
viterbi 維特比分詞
ViterbiNewSegment = HanLP.newSegment("viterbi")for sentence in sentence_array:term_list = ViterbiNewSegment.seg(sentence)print(term_list)import time pressure = 10000start = time.time() for i in range(pressure):ViterbiNewSegment.seg(text) cost_time = time.time() - start print("ViterbiNewSegment 分詞速度:%.2f字每秒" % (len(text) * pressure / cost_time)) [HanLP/nx, 是/vshi, 由/p, 一系列/b, 模型/n, 與/cc, 算法/n, 組成/v, 的/ude1, Java/nx, 工具包/n, ,/w, 目標/n, 是/vshi, 普及/v, 自然語言處理/nz, 在/p, 生產/vn, 環境/n, 中的/v, 應用/vn, 。/w] [鐵/n, 桿/w, 部/q, 隊/n, 憤/w, 怒/vg, 情/n, 緒/n, 集/q, 結/n, /w, 馬/nz, 英/b, 九/m, 腹/ng, 背/v, 受/v, 敵/w] [馬/nz, 英/b, 九/m, 回/v, 應/w, 連/n, 勝/nz, 文/ng, “/w, 丐/n, 幫/nz, 說/v, ”/w, :/w, 稱/v, 黨/w, 內/nz, 同志/n, 談話/n, 應/w, 謹/n, 慎/ag] [高錳酸鉀/nf, ,/w, 強氧化劑/gc, ,/w, 紫紅色/n, 晶體/n, ,/w, 可/v, 溶于/v, 水/n, ,/w, 遇/v, 乙醇/n, 即/v, 被/pbei, 還原/vi, 。/w, 常用/a, 作/v, 消毒劑/n, 、/w, 水/n, 凈化/vn, 劑/q, 、/w, 氧化劑/n, 、/w, 漂白劑/n, 、/w, 毒氣/n, 吸收劑/nz, 、/w, 二氧化碳/n, 精制/v, 劑/q, 等/udeng, 。/w] [《/w, 夜晚/n, 的/ude1, 骰子/n, 》/w, 通過/p, 描述/v, 淺草/nz, 的/ude1, 舞女/n, 在/p, 暗夜/nz, 中/f, 扔/v, 骰子/n, 的/ude1, 情景/n, ,/w, 寄托/v, 了/ule, 作者/nnt, 對/p, 庶民/n, 生活區/n, 的/ude1, 情感/n] [這個/rz, 像/v, 是/vshi, 真的/d, [/w, 委屈/a, ]/w, 前面/f, 那個/rz, 打扮/v, 太/d, 江戶/ns, 了/ule, ,/w, 一點/m, 不/d, 上品/n, .../w, @hankcs/nx] [鼎泰豐/nz, 的/ude1, 小籠/nf, 一點/m, 味道/n, 也/d, 沒有/v, .../w, 每樣/nz, 都/d, 淡淡的/z, .../w, 淡淡的/z, ,/w, 哪/ry, 有/vyou, 食堂/n, 2/m, A/nx, 的/ude1, 好/a, 次/qv] [克里斯蒂娜/nr, ·/w, 克/q, 羅爾/nr, 說/v, :/w, 不/d, ,/w, 我/rr, 不是/c, 虎媽/nz, 。/w, 我/rr, 全家/n, 都/d, 熱愛/v, 音樂/n, ,/w, 我/rr, 也/d, 鼓勵/v, 他們/rr, 這么/rz, 做/v, 。/w] [今日/t, APPS/nx, :/w, Sago/nx, /w, Mini/nx, /w, Toolbox/nx, 培養/v, 孩子/n, 動手/vi, 能力/n] [財政部/nt, 副部長/nnt, 王保安/nr, 調任/v, 國家/n, 統計局/nis, 黨組/nis, 書記/nnt] [2.34/m, 米/q, 男子/n, 娶/v, 1.53/m, 米/q, 女/b, 粉絲/nf, /w, 稱/v, 夫妻/n, 生活/vn, 沒問題/nz] [你/rr, 看過/v, 穆赫/nr, 蘭道/nr, 嗎/y] [國辦/vn, 發布/v, 網絡/n, 提速/vn, 降/v, 費/n, 十四/m, 條/q, 指導/vn, 意見/n, /w, 鼓勵/v, 流量/n, 不/d, 清零/nz] [樂/a, 視/vg, 超級/b, 手機/n, 能否/v, 承載/v, 賈布斯/nr, 的/ude1, 生態/n, 夢/n] ViterbiNewSegment 分詞速度:233386.22字每秒感知器分詞
PerceptronNewSegment = HanLP.newSegment("perceptron")for sentence in sentence_array:term_list = PerceptronNewSegment.seg(sentence)print(term_list)import time pressure = 10000start = time.time() for i in range(pressure):PerceptronNewSegment.seg(text) cost_time = time.time() - start print("PerceptronNewSegment 分詞速度:%.2f字每秒" % (len(text) * pressure / cost_time)) [HanLP/nx, 是/v, 由/p, 一系列/n, 模型/n, 與/c, 算法/n, 組成/v, 的/u, Java/nx, 工具包/n, ,/w, 目標/n, 是/v, 普及/v, 自然語言處理/v, 在/p, 生產環境/l, 中的/u, 應用/vn, 。/w] [鐵桿/n, 部隊/n, 憤怒/vn, 情緒/n, 集結 馬英九/vn, 腹背受敵/Ng] [馬英九/nr, 回應/v, 連勝文/n, “/w, 丐幫/n, 說/v, ”/w, :/v, 稱/v, 黨內/s, 同志/n, 談話/v, 應/v, 謹慎/a] [高錳酸鉀/nr, ,/w, 強/a, 氧化劑/n, ,/w, 紫紅色/n, 晶體/n, ,/w, 可/v, 溶于/v, 水/n, ,/w, 遇/v, 乙醇/n, 即/d, 被/p, 還原/v, 。/w, 常用/d, 作/v, 消毒劑/n, 、/w, 水/n, 凈化劑/n, 、/w, 氧化劑/n, 、/w, 漂白劑/n, 、/w, 毒氣/n, 吸收/v, 劑/n, 、/w, 二氧化碳/n, 精/a, 制劑/n, 等/u, 。/w] [《/w, 夜晚/t, 的/u, 骰子/n, 》/w, 通過/p, 描述/v, 淺草/n, 的/u, 舞女/n, 在/p, 暗夜/t, 中/f, 扔/v, 骰子/n, 的/u, 情景/n, ,/w, 寄托/v, 了/u, 作者/n, 對/p, 庶民/n, 生活區/n, 的/u, 情感/n] [這個/r, 像/n, 是/v, 真的/d, [/w, 委屈/vn, ]/w, 前面/f, 那個/r, 打扮/v, 太/d, 江戶/a, 了/y, ,/w, 一點/m, 不/d, 上品/v, ...@hankcs/Ng] [鼎泰豐/nr, 的/u, 小籠/n, 一點/m, 味道/n, 也/d, 沒有/v, ...每樣/r, 都/d, 淡淡/z, 的/u, ...淡淡/z, 的/u, ,/w, 哪/r, 有/v, 食堂/n, 2/m, A/nx, 的/u, 好/a, 次/Bg] [克里斯蒂娜·克羅爾/nr, 說/v, :/v, 不/d, ,/w, 我/r, 不是/c, 虎媽/n, 。/w, 我/r, 全家/n, 都/d, 熱愛/v, 音樂/n, ,/w, 我/r, 也/d, 鼓勵/v, 他們/r, 這么/r, 做/v, 。/w] [今日/t, APPS/nx, :/v, Sago Mini Toolbox/nx, 培養/v, 孩子/n, 動手/v, 能力/n] [財政部/nt, 副部長/n, 王保安/nr, 調任/v, 國家統計局/nt, 黨組/n, 書記/n] [2.34/m, 米/q, 男子/n, 娶/v, 1.53/m, 米/q, 女/b, 粉絲 稱夫妻/n, 生活/vn, 沒問題/n] [你/r, 看過/v, 穆赫蘭道/n, 嗎/y] [國辦/j, 發布/vn, 網絡/n, 提速/v, 降費/n, 十四/m, 條/q, 指導/v, 意見 鼓勵/v, 流量/n, 不/d, 清零/a] [樂/a, 視/Vg, 超級/b, 手機/n, 能否/v, 承載/v, 賈布斯/nr, 的/u, 生態/n, 夢/n] PerceptronNewSegment 分詞速度:58435.77字每秒特殊的:HMM2 分詞
hmm2 不同于CRF,一開始在廢除之后并沒有替代的函數,但是源代碼中依舊保留了這接口,這是一個BUG,不過在我寫這個用戶指南期間,我已經報告了這個錯誤。在文章發表前,原作者已經修復了該問題。但是這事很有意思,所以還是留下了記錄(當然現在的報錯已經不一樣了)。同時在這里也希望如果之后有人在發現錯誤之后,能夠報告錯誤為開源社區作出貢獻,而不僅僅是做一個受益者。
HMM2newSegment = HanLP.newSegment("hmm2")for sentence in sentence_array:term_list = HMM2newSegment.seg(sentence)print(term_list)import time pressure = 10000start = time.time() for i in range(pressure):HMM2newSegment.seg(text) cost_time = time.time() - start print("HMM2newSegment 分詞速度:%.2f字每秒" % (len(text) * pressure / cost_time)) ---------------------------------------------------------------------------java.lang.IllegalArgumentExceptionPyRaisableTraceback (most recent call last)<ipython-input-15-3cf032a3824c> in <module>() ----> 1 HMM2newSegment = HanLP.newSegment("hmm2")2 3 for sentence in sentence_array:4 term_list = HMM2newSegment.seg(sentence)5 print(term_list)java.lang.IllegalArgumentExceptionPyRaisable: java.lang.IllegalArgumentException: 發生了異常:java.lang.IllegalArgumentException: HMM分詞模型[ /home/fonttian/anaconda3/lib/python3.6/site-packages/pyhanlp/static/data/model/segment/HMMSegmentModel.bin ]不存在at com.hankcs.hanlp.seg.HMM.HMMSegment.<init>(HMMSegment.java:51)at com.hankcs.hanlp.seg.HMM.HMMSegment.<init>(HMMSegment.java:36)at com.hankcs.hanlp.HanLP.newSegment(HanLP.java:680)總結
以上是生活随笔為你收集整理的pyhanlp 分词与词性标注的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第八九章 正态分布与超越正态
- 下一篇: pyhanlp 停用词与用户自定义词典