拼音輸入法案例
https://zhuanlan.zhihu.com/p/25132270
https://github.com/LiuRoy/Pinyin_Demo
在網上看到一篇關於隱馬爾科夫模型的介紹,覺得簡直不能再神奇,又在網上找到大神的一篇關於如何用隱馬爾可夫模型實現中文拼音輸入的博客,無奈大神沒給可以運行的代碼,只能純手動網上找到了結巴分詞的詞庫,根據此訓練得出隱馬爾科夫模型,用維特比算法實現了一個簡單的拼音輸入法。githuh地址:LiuRoy/Pinyin_Demo
原理簡介
隱馬爾科夫模型
抄一段網上的定義:
隱馬爾可夫模型 (Hidden Markov Model) 是一種統計模型,用來描述一個含有隱含未知參數的馬爾可夫過程。其難點是從可觀察的參數中確定該過程的隱含參數,然后利用這些參數來作進一步的分析。
拼音輸入法中可觀察的參數就是拼音,隱含的參數就是對應的漢字。
viterbi算法
參考https://zh.wikipedia.org/wiki/維特比算法,思想是動態規划,代碼比較簡單就不贅述。
優化版
https://github.com/fanqingsong/pinyin_input_method
模型訓練
在 corpus 目錄中, 保存了一份 dict.txt, 為刪減版本的jieba詞庫。
此詞庫為默認訓練詞庫。
另外一個為 dict.backup.txt為原來repo的詞庫, 太大,訓練時間太長。 所以調試階段不適用。
模型所在數據庫有也對應兩個 hmm.sqlite hmm.backup.sqlite
運行命令
./bin/run.sh hmm/train.py
viterbi實現
代碼建hmm/viterbi.py文件,此處會找到最多十個局部最優解,注意是十個局部最優解而不是十個全局最優解,但是這十個解中最優的那個是全局最優解,代碼如下:
def viterbi(pinyin_list): """ viterbi算法實現輸入法 Args: pinyin_list (list): 拼音列表 """ # query the char-prob pair # char must in starting table, named as start_char # prob = start_char prob * emit_prob # emit_prob is the probability that start_char emit to the start_pinyin start_pinyin = pinyin_list[0] start_char = Emission.join_starting(start_pinyin) print("------ start_char -------") print(start_char) V = {char: prob for char, prob in start_char} print("------ V -------") print(V) print("\r\n") # let's count from the second pinyin to calc viterbi matrix for i in range(1, len(pinyin_list)): pinyin = pinyin_list[i] print("------ i -------") print(i) print("------ pinyin -------") print(pinyin) prob_map = {} for phrase, prob in V.iteritems(): print("------ phrase -------") print(phrase) print("------ prob -------") print(prob) prev_char = phrase[-1] # only get the most possible next_char, with highest probability result = Transition.join_emission(pinyin, prev_char) print("------ result -------") print(result) if not result: continue # next_prob = transfer probability(pre_char -> next_char) * emission probability(next_char -> pinyin) next_char, next_prob = result print("-------- next_char --------") print(next_char) # make new V of new char path, ie phrase. prob_map[phrase + next_char] = next_prob + prob if prob_map: # update V, in order to do further research V = prob_map else: return V print("\r\n") return V
結果展示
運行文件,簡單的展示一下運行結果:
./bin/run.sh hmm/viterbi.py
輸出
root@xxx:~/win10/mine/pinyin_input_method# ./bin/run.sh hmm/viterbi.py PYTHONPATH=/usr/local/spark/python:/usr/local/spark/python/lib/py4j-0.10.4-src.zip::/root/win10/mine/pinyin_input_method input:duan yu ------ start_char ------- [(u'\u77ed', -8.848355540206123), (u'\u6bb5', -8.848355540206123)] ------ V ------- {u'\u6bb5': -8.848355540206123, u'\u77ed': -8.848355540206123} ------ i ------- 1 ------ pinyin ------- yu ------ phrase ------- 段 ------ prob ------- -8.84835554021 ------ result ------- (u'\u8a89', -0.1840036429769394) -------- next_char -------- 譽 ------ phrase ------- 短 ------ prob ------- -8.84835554021 ------ result ------- (u'\u8bed', 0.0) -------- next_char -------- 語 短語 -8.84835554021 段譽 -9.03235918318 input: bye bye
漢字轉拼音(pypinyin)
https://github.com/mozillazg/python-pinyin
>>> from pypinyin import pinyin, lazy_pinyin, Style >>> pinyin('中心') [['zhōng'], ['xīn']] >>> pinyin('中心', heteronym=True) # 啟用多音字模式 [['zhōng', 'zhòng'], ['xīn']] >>> pinyin('中心', style=Style.FIRST_LETTER) # 設置拼音風格 [['z'], ['x']] >>> pinyin('中心', style=Style.TONE2, heteronym=True) [['zho1ng', 'zho4ng'], ['xi1n']] >>> pinyin('中心', style=Style.TONE3, heteronym=True) [['zhong1', 'zhong4'], ['xin1']] >>> pinyin('中心', style=Style.BOPOMOFO) # 注音風格 [['ㄓㄨㄥ'], ['ㄒㄧㄣ']] >>> lazy_pinyin('中心') # 不考慮多音字的情況 ['zhong', 'xin'] >>> lazy_pinyin('戰略', v_to_u=True) # 不使用 v 表示 ü ['zhan', 'lüe'] # 使用 5 標識輕聲 >>> lazy_pinyin('衣裳', style=Style.TONE3, neutral_tone_with_five=True) ['yi1', 'shang5']
jieba詞庫
https://github.com/fxsjy/jieba/tree/master/jieba
算法
- 基於前綴詞典實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖 (DAG)
- 采用了動態規划查找最大概率路徑, 找出基於詞頻的最大切分組合
- 對於未登錄詞,采用了基於漢字成詞能力的 HMM 模型,使用了 Viterbi 算法
https://raw.githubusercontent.com/fxsjy/jieba/master/jieba/dict.txt
AT&T 3 nz B超 3 n c# 3 nz C# 3 nz c++ 3 nz C++ 3 nz T恤 4 n A座 3 n A股 3 n A型 3 n A輪 3 n AA制 3 n AB型 3 n B座 3 n B股 3 n B型 3 n B超 3 n B輪 3 n BB機 3 n BP機 3 n C盤 3 n C座 3 n C語言 3 n CD盒 3 n CD機 3 n CALL機 3 n D盤 3 n D座 3 n D版 3 n E盤 3 n E座 3 n E化 3 n E通 3 n F盤 3 n F座 3 n G盤 3 n H盤 3 n H股 3 n I盤 3 n IC卡 3 n IP卡 3 n IP電話 3 n IP地址 3 n K黨 3 n K歌之王 3 n N年 3 n O型 3 n PC機 3 n PH值 3 n SIM卡 3 n U盤 3 n VISA卡 3 n Z盤 3 n Q版 3 n QQ號 3 n RSS訂閱 3 n T盤 3 n