python基於隱馬爾可夫模型實現中文拼音輸入

來源:互聯網
上載者:User
在網上看到一篇關於隱馬爾科夫模型的介紹,覺得簡直不能再神奇,又在網上找到大神的一篇關於如何用隱馬爾可夫模型實現中文拼音輸入的部落格,無奈大神沒給可以啟動並執行代碼,只能純手動網上找到了結巴分詞的詞庫,根據此訓練得出隱馬爾科夫模型,用維特比演算法實現了一個簡單的拼音IME。githuh地址:https://github.com/LiuRoy/Pinyin_Demo

原理簡介隱馬爾科夫模型

抄一段網上的定義:

隱馬爾可夫模型 (Hidden Markov Model) 是一種統計模型,用來描述一個含有隱含未知參數的馬爾可夫過程。其痛點是從可觀察的參數中確定該過程的隱含參數,然後利用這些參數來作進一步的分析。

拼音IME中可觀察的參數就是拼音,隱含的參數就是對應的漢字。

viterbi演算法

參考https://zh.wikipedia.org/wiki/維特比演算法,思想是動態規劃,代碼比較簡單就不贅述。

代碼解釋

model定義

代碼見model/table.py檔案,針對隱馬爾科夫的三個機率矩陣,分別設計了三個資料表格儲存體。這樣的好處很明顯,漢字的轉移機率矩陣是一個非常大的疏鬆陣列,直接檔案儲存體佔用空間很大,並且載入的時候也只能一次性讀入記憶體,不僅記憶體佔用高而且載入速度慢。此外資料庫的join操作非常方便viterbi演算法中的機率計算。

資料表定義如下:

class Transition(BaseModel):  __tablename__ = 'transition'  id = Column(Integer, primary_key=True)  previous = Column(String(1), nullable=False)  behind = Column(String(1), nullable=False)  probability = Column(Float, nullable=False)class Emission(BaseModel):  __tablename__ = 'emission'  id = Column(Integer, primary_key=True)  character = Column(String(1), nullable=False)  pinyin = Column(String(7), nullable=False)  probability = Column(Float, nullable=False)class Starting(BaseModel):  __tablename__ = 'starting'  id = Column(Integer, primary_key=True)  character = Column(String(1), nullable=False)  probability = Column(Float, nullable=False)

模型產生

代碼見train/main.py檔案,裡面的initstarting,initemission,init_transition分別對應於產生隱馬爾科夫模型中的初始機率矩陣,發射機率矩陣,轉移機率矩陣,並把產生的結果寫入sqlite檔案中。訓練用到的資料集是結巴分詞裡的詞庫,因為沒有訓練長句子,最後啟動並執行結果也證明只能適用於短句輸入。

初始機率矩陣

統計初始化機率矩陣,就是找出所有出現在詞首的漢字,並統計它們出現在詞首的次數,最後根據上述資料算出這些漢字出現在詞首的機率,沒統計的漢字就認為出現在詞首的機率是0,不寫入資料庫。有一點注意的是為了防止機率計算的時候因為越算越小導致電腦無法比較,所有的機率都進行了自然對數運算。統計的結果如下:

轉移機率矩陣

此處用到的是最簡單的一階隱馬爾科夫模型,即認為在一個句子裡,每個漢字的出現只和它前面的的一個漢字有關,雖然簡單粗暴,但已經可以滿足大部分情況。統計的過程就是找出字典中每個漢字後面出現的漢字集合,並統計機率。因為這個機率矩陣非常的大,逐條資料寫入資料庫過慢,後續可以最佳化為批量寫入,提高訓練效率。結果如下:

展示的一後面出現機率最高的十個字,也挺符合日常習慣。

發射機率矩陣

通俗點就是統計每個漢字對應的拼音以及在日常情況下的使用機率,已暴舉例,它有兩個讀音:bao和pu,痛點就是找bao和pu出現的機率。此處統計用到了pypinyin模組,把字典中的短語轉換為拼音後進行機率統計,但是某些地方讀音也不完全正確,最後啟動並執行IME會出現和拼音不匹配的結果。統計結果如下:

viterbi實現

代碼建input_method/viterbi.py檔案,此處會找到最多十個局部最優解,注意是十個局部最優解而不是十個全域最優解,但是這十個解中最優的那個是全域最優解,代碼如下:

def viterbi(pinyin_list):  """  viterbi演算法實現IME  Aargs:    pinyin_list (list): 拼音列表  """  start_char = Emission.join_starting(pinyin_list[0])  V = {char: prob for char, prob in start_char}  for i in range(1, len(pinyin_list)):    pinyin = pinyin_list[i]    prob_map = {}    for phrase, prob in V.iteritems():      character = phrase[-1]      result = Transition.join_emission(pinyin, character)      if not result:        continue      state, new_prob = result      prob_map[phrase + state] = new_prob + prob    if prob_map:      V = prob_map    else:      return V  return V

結果展示

運行input_method/viterbi.py檔案,簡單的展示一下運行結果:

問題統計:

統計字典產生轉移矩陣寫入資料庫的速度太慢,運行一次要將近十分鐘。發射機率矩陣資料不準確,總有一些漢字的拼音不匹配。訓練集太小,實現的IME不適用於長句子。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.