如何從頭開始編一個拼音輸入法?
輸入法程序與操作系統交互多。即使利用現有框架,起步時也有諸多障礙,如:
* 需要學習輸入法框架的 API;不同系統的輸入法框架有較大差異,可能會涉及一些系統底層的細節
* 調試困難;Windows 的輸入法以 DLL 注入方式加載,需要事先注冊到系統,且不可運行時替換 (hot-swap);Mac OS 對輸入法做超時控制,難以利用斷點單步調試
我的建議是,在理解輸入法工作原理的基礎上,先寫一個邏輯純粹的、在命令行上以 REPL (Read-eval-print loop) 方式工作的輸入法原型。
比方說,首先實現輸入一串編碼、查詞典、輸出查詢結果。
如果是做拼音輸入法,可進一步在詞典查詢基礎上完成詞組、語句的轉換。
然後,再增加選字、編輯等功能鍵的處理邏輯。
不可顯示爲字元的按鍵,可通過轉義序列模擬,例如 `rime_api_console` 採用 花括弧+IBus鍵名 表示任意的按鍵:`shuruufa{Left}{Left}{BackSpace}{End}`
https://github.com/lotem/librime/blob/master/tools/rime_api_console.cc#L144
這樣做的好處是可以將測試用的按鍵序列保存爲文本,通過輸入重定向重放測試場景:
```
$ rime_api_console &< test_key_sequence.txt
```
原型將輸入法所需邏輯完全實現後,即可集成到真實的輸入法框架,完善用戶介面等等。
最後,藉機宣傳一下 RIME:
RIME/中州韻輸入法引擎,是一套跨平臺的輸入法演算法框架,即在輸入法與操作系統介面之上封裝了一套輸入法常用的演算法和邏輯組件,允許用戶以 YAML 文檔格式自定義輸入方案和碼表,快速建立拼音、注音、五筆及類似形態的輸入法。對於需要特殊邏輯的輸入法,可通過編程擴展該框架,使開發者只須專注於相關邏輯。目前這一框架的不足是介面尚未完全定型、缺少開發文檔。
其他可供參考的開源項目有:* [SunPinyin](http://code.google.com/p/sunpinyin/)
* [libpinyin](https://github.com/libpinyin/libpinyin)
* [OpenVanilla](http://openvanilla.org/)
* [BYVoid:基於統計語言模型的拼音輸入法](http://www.byvoid.com/blog/slm_based_pinyin_ime)
說個簡單的實現方案
對於全拼來說:
1. 首先是要做拼音切分,切分方案n種(前綴,聲母韻母),比如 nihao ,切分成ni"hao
2.根據切分出來的出來的[ni"hao],查出來候選詞。這個怎麼查,假設你已經有了一個詞典,然後用查字典的方法,查到[你好][利好][擬好]等候選詞。然後要排序是吧,哪個要放在第一位,哪個要放第二位什麼的。
3.the end
-------------------------------------
1. 針對拼音切分,你需要存儲所有的拼音吧。怎麼存儲這個拼音啊,一般習慣上用trie樹去存儲,順便可以做拼音切分。
2. 當然假設你有一個詞典,怎麼通過切分出來的拼音去找詞,依然可以用trie樹的方案,去存儲。至於排序,可以給每個詞,比如[你好]給個權值10,[利好]給個8什麼的。
-------------------------------------
下面說,這個詞典,怎麼做出來的呢?那個權值怎麼得出來呢?
簡單的想,去統計這些詞,比如[你好]這個詞在整個歷史中出現的次數噻。這個時候你可以用現有的無詞頻的字典去統計非常龐大的語料庫(涉及到分詞什麼的,如果要快速規則分詞,需要用到double array trie,如果用統計學習方法分詞,要學習相關理論)。當然有發現新詞的方法可以參考。甚至不用現有的詞典,有ngram的方法,去做,做一個詞典出來也是可以的。這個時候,你得到的數據,是很粗糙的。需要平滑什麼的(當然因為數據的稀疏性啊,別看你的詞典挺大的,其實很稀疏的)。
ok,辛辛苦苦做了一個詞典出來,下面就是用啊。配合拼音,就可以簡單的做個稍微智能的輸入法了。
---------------------------------------
你以為到此就結束了嗎?
你需要輸入法能夠糾錯吧,你需要輸入法能夠支持長整句的輸入吧。你需要自己的輸入法能用吧
輸入法長整句輸入輸入法裡面的一個難題。
比如你敲個[shurufachangzhengju] 拼音切分成[shu"ru"fa"chang"zheng"ju](當然可以切成多種)
但是你的詞典裡面沒有[輸入法長整句]這個詞啊。
最近看到兩種實現長整句輸入的方案
一個是基於隱馬可夫模型的
比如拼音切分成[shu"ru"fa"chang"zheng"ju]
針對每一個拼音:比如shu,有書、數、樹等候選字。ru有如、路、入等候選
那麼怎麼選擇比較好的那個呢?
也就是計算出p(輸入法長整句|shu"ru"fa"chang"zheng"ju) (概率) ,這是一個典型的隱馬可夫模型可以做的事情。使用維比特演算法,就可以求解。不過這個是基於字的。
使用HMM實現簡單拼音輸入法
一個是維比特網格演算法實現
sunpinyin的實現方式。
這個是基於詞的,找到所有可能的片語成的前向網路,然後求出那個路徑最優。不多說。看sunpinyin的文章。
https://code.google.com/p/sunpinyin/wiki/CodeTourOfIME
好吧,去找找資料看別人怎麼實現,是用hmm還是其他。。
推薦這個,sunpinyin 的實現,看一看
------------------------------
然後到能用的一個輸入法,各個平台,各個框架,選個。把上面的思想實現下。
輸入法有很多瑣碎的事情要做,各種優化什麼的。看著都頭大額。
用字級別的 Markov 鏈就能得到相當好的輸入效果
比如
語料庫是 S1 論壇 10 年的總語料,大小 7.5G,用三字組處理。
語料庫是 S1 論壇 10 年的總語料,大小 7.5G,用三字組處理。TSF(Text Service Framework)簡介
http://msdn.microsoft.com/en-us/library/windows/desktop/ms629032(v=vs.85).aspx
讀完你就會了。
小語種,死亡語言多平台實現是市場空白啊
我覺得引擎是重中之重的地方。引擎出詞分為兩個部門:1 unigram 2 bigram 這兩個部分。unigram不用解釋,直接大量的文本統計,bigram是幹什麼用的呢?比如說:不用 解釋 0.89 這個就是一個bigram,在統計bigram的時候需要做平滑,這個地方需要注意,訓練這個模型是關鍵,因為bigram統計完大約有上億條,你需要篩選出400萬的bigram對(這個地方是技術之所在)。模型統計好了,用戶輸入拼音串是簡拼和全拼混合的,這個時候有兩種做法,第一是將拼音轉換為全拼(搜狗輸入法,百度輸入法,QQ輸入法是這種設計),第二是直接簡拼和全拼混合(這個時候詞典得採用聲母+韻母共同命中的方法查詢)(WI輸入法,阿里拼音都是這樣的設計)然後就是所謂的拼音切分等流程。。。。。。。。。。。。。。。。。。。。不多說了。。。。。。。。呵呵呵。。。。。。
在有系統介面的環境下,輸入法其實是個很簡單的玩藝,可以簡單的分成平台相關的系統介面部分和平台無關的輸入法引擎。
系統介面部分通常是按系統規定提供的一組回調,系統在把鍵盤事件發給應用程序之前,先讓輸入法做一下轉換;一般也會有跟當前輸入窗口通信的介面,除了方便輸入法直接把轉換好的字詞發送給輸入窗,還可以實現on-the-spot方式處理候選字。這一塊照著系統文檔寫就好了,都不一定要很懂這個操作系統的編程的。
Windows : About Input Method Manager (Windows)
Xorg:The Input Method Protocol
XIM協議的原理及其實現
Mac OS X:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/InputMethodKitFrameworkRef/_index.html
例子 NumberInput_IMKit_Sample
Android:
指南:Creating an Input Method
參考: InputMethodManager
例子:Samples | Android Developers
贊了 @弓辰 和 @安岩 的回答,個人做點兒補充。
我們做輸入法(初級版本)的思路是:將字詞的編碼、頻率、聯想字詞等內容做到資料庫(DB)里,使用SQL查詢語句完成「編碼-&>字詞」的檢索,注意這裡的語句優化,再配合適當的數據結構和緩存,就可以做出一個能湊合著用的拼音輸入法啦。
如果要較好地支持長整句輸入等高級特性,做得更智能,確實需要學習學習HMM隱馬可夫模型、Viterbi維特比演算法等知識,推薦你閱讀吳軍博士的《數學之美》(書中還介紹了其他NLP自然語言處理的數學模型)。
拼音編碼表,你可以從極品五筆輸入法(它也支持拼音)導出數據來。詞語頻率數據,可以在 語料庫在線--資源共享 下載到。這些在構建詞典的時候,能夠幫你節省不少工夫。--------------------------------------------------
順手貼個我們的設計圖,宣傳一下
推薦閱讀: