實體知識+字典樹輔助jieba的分詞(並對三國演義進行簡單分析)

  • 2019 年 10 月 30 日
  • 筆記

在做中文NLP的時候,分詞可謂是基礎中的基礎。然而這個基礎部分的內容直到今天還是讓人不省心,在實際應用中【尤其是在人名等實體的識別上】總是顯得漏洞百出。下面以python上比較流行的一個中文分詞庫jieba為例,看看它的一次表現:

import jieba  print(" ".join(jieba.cut("""玄德謝別二客,便命良匠打造雙股劍。  雲長造青龍偃月刀,又名「冷艷鋸」,重八十二斤。  張飛造丈八點鋼矛。各置全身鎧甲。  共聚鄉勇五百餘人,來見鄒靖。鄒靖引見太守劉焉。""")))

玄德謝 別二客 , 便命 良匠 打造 雙股 劍 。 雲長造 青龍 偃月 刀 , 又名 「 冷艷 鋸 」 , 重 八十二斤 。 張飛 造丈 八點 鋼矛 。 各置 全身 鎧甲 。 共聚 鄉勇 五百餘 人 , 來見 鄒靖 。 鄒靖引 見 太守 劉焉 。

這裡它犯了多次錯誤(「玄德謝」,」雲長造」,」鄒靖引」),並且對同一人名也會有前後不一致的情況(「鄒靖」,」鄒靖引」)。假設我要對文章中的人物出場頻次進行統計,那麼基於這種分詞的方法看來是完全靠不住的。

這時我就有一種想法:如果能夠基於現有的知識(三國演義中已知的人名和字號),對分詞結果再進行一次干預,矯正其中的結果,是不是就可以解決這個問題了呢?

這個想法還有一個另外的好處:在古文中,同一個人物會以姓名、字號甚至是代稱等多種不同形式出現,而我們希望在統計時能夠把它們歸入同一個人(實體)名下。實體知識就能夠幫助我們完成這種歸化。『

實踐證明這個想法是可行的。其主要思路是,利用字典樹(Trie)預先掃描文本,並把識別到的實體替換為一個標準詞(這裡我用了」人佔位符」),再使用jieba的add_word使得標準詞一定會被分詞器識別出來,最後再在分詞結果中把標準詞按照位置換回原文或者標準實體名。

首先簡單提一下這裡用python構建字典樹的思路。這裡採用嵌套字典的形式【與這篇文章的結構相似:飄逸的python – 實現trie樹】。但是與上面不同的一點是,這裡為了匹配到實體,我們要在字典樹的葉結點[這裡我起名為leaf]上掛上實體【或者多個實體,如果他們共享一個名字的話】,大致是這樣:

>>> trie["劉"]["備"]  {'leaf':{'劉備'}}  >>> trie["玄"]["德"]  {'leaf':{'劉備'}}  >>> trie["子"]["上"]      #數據庫中有兩個人字「子上」  {'leaf': {'司馬昭', '紀陟'}}

下面還是用我喜歡的jupyter notebook展開具體思路:

src="https://nbviewer.jupyter.org/github/blmoistawinde/simpleSanGuoNLP/blob/master/demo_KGsegmenter.ipynb?flush_cache=true" width="720" height="2000">