-
用戶詞典大小最大可以有多大
-
用戶詞典大小對速度的影響
-
有相同前綴和后綴的詞匯如何區分
-
對比百度分詞的API
問題一:詞典大小
從源碼大小分析,整個jieba分詞的源碼總容量為81MB,其中系統詞典dict.txt
的大小為5.16MB,所以用戶詞典至少可以大於5.16MB,在從詞典中的詞語數量來看,系統詞典的總的詞語數共349047
import pandas as pd import numpy as np import os path = os.getcwd() print(path) dict_path = os.path.join(path, 'medical_dict') #調用pandas的read_csv()方法時,默認使用C engine作為parser engine,而當文件名中含有中文的時候,用C engine在部分情況下就會出錯。所以在調用read_csv()方法時指定engine為Python就可以解決問題了。 res = pd.read_csv(dict_path+'\\部位.txt',sep=' ',header=None,encoding='utf-8',engine='python') res = res.append( pd.read_csv(dict_path+'\\疾病.txt',sep=' ',header=None,encoding='utf-8',engine='python') ) res = res.append( pd.read_csv(dict_path+'\\檢查.txt',sep=' ',header=None,encoding='utf-8',engine='python') ) res = res.append( pd.read_csv(dict_path+'\\手術.txt',sep=' ',header=None,encoding='utf-8',engine='python') ) res = res.append( pd.read_csv(dict_path+'\\葯品.txt',sep=' ',header=None,encoding='utf-8',engine='python') ) res = res.append( pd.read_csv(dict_path+'\\症狀.txt',sep=' ',header=None,encoding='utf-8',engine='python') ) res = res.append( pd.read_csv(dict_path+'\\中葯.txt',sep=' ',header=None,encoding='utf-8',engine='python') ) print(res.count())
0 35885
1 35880
2 35880
將35885個醫療詞典放入,遠比系統詞典小。之后導出為一個用戶詞典,代碼如下:
res[2] = res[1]
res[1] = 883635
print(res.head())
res.to_csv(dict_path+'\\medicaldict.txt',sep=' ',header=False,index=False)
測試語句
#encoding=utf-8 import jieba import jieba.posseg as pseg import os path = os.getcwd() # 添加用戶詞典 jieba.load_userdict(path + "\\medical_dict\\medicaldict.txt") print( path + "\\medical_dict\\medicaldict.txt" ) test_sent = ( "患者1月前無明顯誘因及前驅症狀下出現腹瀉,起初稀便,后為水樣便,無惡心嘔吐,每日2-3次,無嘔血,無腹痛,無畏寒寒戰,無低熱盜汗,無心悸心慌,無大汗淋漓,否認里急后重感,否認蛋花樣大便,當時未重視,未就診。") words = jieba.cut(test_sent) print('/'.join(words))
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\Public\Documents\Wondershare\CreatorTemp\jieba.cache
Loading model cost 0.921 seconds.
Prefix dict has been built succesfully.
D:\code\jiebafenci\jieba\medical_dict\medicaldict.txt
患者/1/月前/無/明顯/誘因/及/前驅/症狀/下/出現/腹瀉/,/起初/稀便/,/后/為/水樣便/,/無/惡心/嘔吐/,/每日/2/-/3/次/,/無/嘔血/,/無/腹痛/,/無/畏寒/
寒戰/,/無/低熱/盜汗/,/無/心悸/心慌/,/無/大汗淋漓/,/否認/里急后重/感/,/否認/蛋/花樣/大便/,/當時/未/重視/,/未/就診/。
結果正常,判別一條症狀的響應速度快,jieba分詞是足以將所有的醫療詞匯放入,對於性能的影響可以在進一步分析。
問題二:詞典大小對效率的影響
-
35885個詞語,1條測試語句
load time: 1.0382411479949951s
cut time: 0.0s
-
71770個詞語,1條測試語句
load time: 1.4251623153686523s
cut time: 0.0s
-
1148160個詞語
load time: 7.892921209335327s
cut time: 0.0s
逐漸變慢了
-
2296320個詞語
load time: 15.106632471084595s
cut time: 0.0s
在本機已經開始變得很慢了
-
4592640個詞語
load time: 30.660043001174927s
cut time: 0.0s
-
9185280個詞語
load time: 56.30760192871094s
-
18370560個詞語
load time: 116.30s
制作為折線圖如上,基本上詞語大小和加載速度呈正比。但是加載的詞典一般保留在內存中,對內存和I/O負擔較大。
之后將2220條病史數據導入后,對分詞處理時間依然沒有什么影響,在0.1s以內,分詞時間可以忽略。
問題三:有相同前綴和后綴的詞匯如何區分
-
關於無尿急、尿頻、尿痛,在jieba分詞導入用戶詞典后是能正確區分的,相關病例如下
/患者/3/小時/前/無/明顯/誘因/出現/上/腹部/疼痛/,/左/上腹/為主/,/持續性/隱痛/,/無/放射/,/無/惡心/及/嘔吐/,/無/泛酸/及/噯氣/,/無/腹脹/及/腹瀉/,/無/咳嗽/及/咳痰/,/無/胸悶/及/氣急/,/無/腰酸/及/腰疼/,/無/尿急/、/尿頻/及/尿痛/,/無/頭暈/,/無/黒/曚/,/無/畏寒/及/發熱/,/無尿/黃/,/無/口苦/,/來/我院/求治/。
但是無尿黃划分成了無尿/黃,在查找用戶詞典后,發現是詞典中沒有尿黃的症狀,為詞典問題,便跳過處理。但是在症狀中確實同時存在無尿和尿頻,初步分析可能是詞語在詞典中的順序,或者是jieba分詞系統內部的分詞策列導致,現在分析第一種可能,在詞典中無尿在14221行,尿頻在13561行,現在將無尿放在第一行,看分詞結果。結果仍然為無/尿頻,所以結果為是jieba分詞內部的算法策略,當兩個詞語的詞頻相同是,后匹配的詞語優先,比如在詞語匹配中尿頻比無尿后匹配,所以最后區分尿頻,這與正確的分法也相匹配。
-
再比如腰部酸痛,在部位中有腰部這個詞語,在症狀中也有腰部酸痛這個詞語,測試jieba分詞會如何區分
測試詞典:
腰部 883635
酸痛 883635
腰部酸痛 883635
測試結果:
腰部酸痛
將詞典順序交換后,並將腰部和疼痛的詞頻都設置成大於883635的值后,結果仍然是腰部酸痛,所以可以得出jieba分詞更傾向於分長度更長的詞語,即使短的詞語的詞頻較大也會優先分長度更長的。而我去向自己學醫的同學了解后,他也認為分成長詞更合理,所以也不用處理。
-
在查看病例中,發現很多病例中存在方位名 + 部位名的詞語,並且應該分成一個詞語,如下代碼實現添加方位名+部位名的詞典,如詞典中已經存在,便跳過。
res = pd.read_csv(dict_path+'\\部位.txt',sep=' ',header=None,encoding='utf-8',engine='python') direct = ['上','下','左','右','前','后'] print(res[0].head()) resum = res[0].count() print(resum) result = res[0] # 在部位名前加上方位名 for item in res[0].tolist(): if(item[0] in direct): continue else: temp = Series(['左' + item, '右' + item], index = [resum+1,resum+2]) resum = resum + 2 result = result.append(temp) print(result.tail()) df = pd.DataFrame(result) print(df.describe())
百度分詞
github地址 : https://github.com/baidu/lac/
實現代碼
from LAC import LAC # 裝載分詞模型 lac = LAC(mode='seg') # 單個樣本輸入,輸入為Unicode編碼的字符串 text = u"LAC是個優秀的分詞工具" seg_result = lac.run(text) # 批量樣本輸入, 輸入為多個句子組成的list,平均速率會更快 texts = [u"腰部酸痛"] lac.load_customization('userdict.txt', sep=None) seg_result = lac.run(texts) print(seg_result)
用戶詞典只需要添加詞語和詞性即可。經過測試得到結論:
1.百度分詞無詞頻的概念,但是也更傾向於分長度更長的詞語。