nlp之分詞算法

1.前向最大匹配算法


例子:我們經(jīng)常有意見分歧
詞典:['我們', '經(jīng)常', '有', '有意見', '意見', '分歧']

對于上面的例子我們應(yīng)用前向最大匹配算法怎么分詞呢,步驟如下:

  • 確定最大長度max_len, 也就是說我們是在max_len這個(gè)長度內(nèi)尋找匹配的字符串,這里我們不妨令max_len=5。
  • 將例子分割為[我們經(jīng)常有] 意見分歧,看前面5個(gè)詞'我們經(jīng)常有'是否在詞典庫中,我們查看發(fā)現(xiàn)不在。
  • 接著分割為[我們經(jīng)常] 有意見分歧,看這4個(gè)詞'我們經(jīng)常'是否在詞典庫中,查看發(fā)現(xiàn)依然不在。
  • 繼續(xù)分割為[我們經(jīng)] 常有意見分歧,看這3個(gè)詞'我們經(jīng)'是否在詞典庫中,查看發(fā)現(xiàn)不在。
  • 繼續(xù)分割為[我們] 經(jīng)常有意見分歧,看這2個(gè)詞'我們'是否在詞典庫中,查看發(fā)現(xiàn)在詞典庫,那么'我們'就被分割出來,原例子變成我們 | 經(jīng)常有意見分歧。
  • 然后從'經(jīng)'字開始往后數(shù)max_len個(gè)單詞重復(fù)前面步驟。
  • 最后分割完的句子為我們 | 經(jīng)常 | 有意見 | 分歧。

python實(shí)現(xiàn)如下:

s = '我們經(jīng)常有意見分歧'
dic = ['我們', '經(jīng)常', '有', '有意見', '意見', '分歧']

def forward_max_seg(s, dic, max_len):
    p1, p2 = 0, min(max_len-1, len(s)-1)
    res = []
    while p1 <= p2:
        if s[p1:p2+1] in dic:
            res.append(s[p1:p2+1])
            p1 = p2 + 1
            p2 = min(p1 + max_len-1, len(s)-1)
        else:
            p2 -= 1
    return res

res = forward_max_seg(s, dic, 5)
print('|'.join(res))

輸出為:

我們|經(jīng)常|有意見|分歧

2.后向最大匹配算法


例子:我們經(jīng)常有意見分歧
詞典:['我們', '經(jīng)常', '有', '有意見', '意見', '分歧']

后向匹配跟前向匹配方向相反,過程如下:

  • 同樣需要確定最大長度max_len, 這里我們也令max_len=5。
  • 從后往前看將例子分割為我們經(jīng)常 [有意見分歧],看后面5個(gè)詞'有意見分歧'是否在詞典庫中,我們查看發(fā)現(xiàn)不在。
  • 接著分割為我們經(jīng)常有 [意見分歧],看這4個(gè)詞'意見分歧'是否在詞典庫中,查看發(fā)現(xiàn)依然不在。
  • 繼續(xù)分割為我們經(jīng)常有意 [見分歧],看這3個(gè)詞'見分歧'是否在詞典庫中,查看發(fā)現(xiàn)不在。
  • 繼續(xù)分割為我們經(jīng)常有意見 [分歧],看這2個(gè)詞'分歧'是否在詞典庫中,查看發(fā)現(xiàn)在詞典庫,那么'分歧'就被分割出來,原例子變成我們經(jīng)常有意見 | 分歧。
  • 然后從'見'字開始往前數(shù)max_len個(gè)單詞重復(fù)前面步驟。
  • 最后分割完的句子為我們 | 經(jīng)常 | 有意見 | 分歧。
    python實(shí)現(xiàn)如下:
def backward_max_seg(s, dic, max_len):
    p1, p2 = max(len(s)-max_len, 0), len(s)-1
    res = []
    while p1 <= p2:
        if s[p1:p2+1] in dic:
            res.insert(0, s[p1:p2+1])
            p2 = p1-1
            p1 = max(p2-max_len+1, 0)
        else:
            p1 += 1
    return res
res = backward_max_seg(s, dic, 5)
print('|'.join(res))

輸出:

我們|經(jīng)常|有意見|分歧

3.雙向最大匹配法

算法流程:
比較正向最大匹配和反向最大匹配結(jié)果:

  • 如果分詞數(shù)量結(jié)果不同,那么取分詞數(shù)量較少的那個(gè)
  • 如果分詞數(shù)量結(jié)果相同:
    • 分詞結(jié)果相同,可以返回任何一個(gè)
    • 分詞結(jié)果不同,返回單字?jǐn)?shù)比較少的那個(gè)

上面的例子兩種分法一致,所以選任何一個(gè)都可以,下面看另一個(gè)例子:

例子:北京大學(xué)生前來應(yīng)聘
詞典:['北京大學(xué)', '北京', '大學(xué)生','生前', '來', '應(yīng)聘']

正向匹配最終切分結(jié)果為:北京大學(xué) | 生前 | 來 | 應(yīng)聘,分詞數(shù)量為 4,單字?jǐn)?shù)為 1
反向匹配最終切分結(jié)果為:”北京 | 大學(xué)生 | 前來 | 應(yīng)聘,分詞數(shù)量為 4,單字?jǐn)?shù)為 0

因此選擇反向匹配的結(jié)果作為最終結(jié)果

最大匹配算法缺點(diǎn):

  • 找到的是局部最優(yōu)解
  • 嚴(yán)重依賴于max_len的大小,當(dāng)max_len特別大時(shí),效率會(huì)很低
  • 無法考慮語義信息

3. 考慮語義的分割-維特比(viterbi)算法

例子:經(jīng)常有意見分歧
詞典:['有', '有意見', '意見', '分歧', '見', '意']

前面講到最大匹配算法是無法考慮語義信息的,那么如果要考慮語義信息應(yīng)該怎么做呢?
最直接的想法是分成兩步,step1:將句子的所有可能分割方式分割出來,step2:選出這些分法中哪個(gè)最好最合乎常理的,過程表示如下:


語義分割過程示意圖

比如step1得到了所有可能的分割:
s1 = 經(jīng)常 | 有 | 意見 | 分歧
s2 = 經(jīng)常 | 有| 意 | 見 | 分歧
s3 = 經(jīng)常 | 有意見 | 分歧
......
那么step2如何選出最好的呢,,最簡單的一種方式是 unigram,拿s1和s2的比較舉例:
p(s1) = p(經(jīng)常, 有, 意見,分歧) = p(經(jīng)常)p(有)p(意見)p(分歧)
p(s2) = p(經(jīng)常, 有, 意, 見,分歧) = p(經(jīng)常)p(有)p(意)p(見)p(分歧)
就是比較p(s1)和p(s2)哪個(gè)大,選擇大的那個(gè)。
即使我們使用最簡單的unigram,我們也會(huì)發(fā)現(xiàn)這種做法進(jìn)行了大量的重復(fù)性工作,效率很低。那么怎么解決效率問題呢,一種途徑就是將兩步合并,用DP(動(dòng)態(tài)規(guī)劃)進(jìn)行優(yōu)化,提升效率,也就是接下來要講的維特比算法。

例子:經(jīng)常有意見分歧
詞典: ['經(jīng)常', '經(jīng)', '有', '有意見', '意見', '分歧', '見', '意', '見分歧', '分']
概率:[0.1, 0.05, 0.1, 0.1, 0.2, 0.2, 0.05, 0.05, 0.05, 0.1]
-log(概率):[2.3, 3, 2.3, 2.3, 1.6,1.6, 3, 3, 3, 2.3]

維特比算法示意圖

算法流程:
用圖來表示,邊權(quán)重表示這個(gè)這個(gè)字的-log概率,遍歷詞典,將各概率標(biāo)注如下圖,將未出現(xiàn)的詞用較大的數(shù)表示,這里用20表示。因?yàn)槭褂?log,這里權(quán)重和最小也就是原概率乘積最大問題。原問題為:找到一種劃分使得這種劃分的概率乘積最大,那么現(xiàn)在原問題就轉(zhuǎn)化成找到一條路徑從節(jié)點(diǎn)1到節(jié)點(diǎn)8,使權(quán)重和最小,就能用DP解決。

DP算法流程:
做如下定義:
f(8):從節(jié)點(diǎn)1到節(jié)點(diǎn)8的最短路徑
f(7):從節(jié)點(diǎn)1到節(jié)點(diǎn)7的最短路徑
......
那么
f(8) = min(f(7)+20, f(6)+1.6, f(5)+3)
f(7) = f(6)+2.3
f(6) = min(f(5)+3, f(4)+1.6, f(3)+2.3)
......

4 分詞工具

jieba分詞:https://github.com/fxsjy/jieba
SnowNLP分詞:https://github.com/isnowfy/snownlp
LTP: http://www.ltp-cloud.com/
HanNLP分詞: https://github.com/hankcs/HanLP/

reference:
[1] https://blog.csdn.net/selinda001/article/details/79345072
[2] https://www.bilibili.com/video/av86991001?p=21

未完待續(xù).....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載請注明:終小南 ? 中文分詞算法總結(jié) 什么是中文分詞眾所周知,英文是以 詞為單位的,詞和詞之間是靠空格隔開,而...
    kirai閱讀 10,105評論 3 24
  • 簡介 NLP的底層任務(wù)由易到難大致可以分為詞法分析、句法分析和語義分析。分詞是詞法分析(還包括詞性標(biāo)注和命名實(shí)體識(shí)...
    郭少悲閱讀 6,710評論 0 4
  • 分詞 Segmentation 分詞可以認(rèn)為是已經(jīng)解決的問題 分詞工具 Segmentation Tools 分...
    在努力的Jie閱讀 582評論 0 2
  • 算法技術(shù)解構(gòu) 1、Python基礎(chǔ)知識(shí) (1)IPythonIPython的開發(fā)者吸收了標(biāo)準(zhǔn)解釋器的基本概念,在此...
    shenciyou閱讀 5,888評論 0 10
  • 更好的閱讀體驗(yàn)請?zhí)D(zhuǎn)至分詞算法綜述[https://xv44586.github.io/2019/10/22/cu...
    小蛋子閱讀 1,960評論 1 9

友情鏈接更多精彩內(nèi)容