天天看點

漫話中文自動分詞和語義識别(上):中文分詞算法

中文分詞的主要困難在于分詞歧義。“結婚的和尚未結婚的”,應該分成“結婚/的/和/尚未/結婚/的”,還是“結婚/的/和尚/未/結婚/的”?人來判斷很容易,要交給計算機來處理就麻煩了。問題的關鍵就是,“和尚未”裡的“和尚”也是一個詞,“尚未”也是一個詞,從計算機的角度看上去,兩者似乎都有可能。對于計算機來說,這樣的分詞困境就叫做“交集型歧義”。

有時候,交集型歧義的“歧義鍊”有可能會更長。“中外科學名著”裡,“中外”、“外科”、“科學”、“學名”、“名著”全是詞,光從詞庫的角度來看,随便切幾刀下去,得出的切分都是合理的。類似的例子數不勝數,“提高産品品質”、“鞭炮聲響徹夜空”、“努力學習文法規則”等句子都有這樣的現象。在這些極端例子下,分詞算法誰優誰劣可謂是一試便知。

最簡單的,也是最容易想到的自動分詞算法,便是“最大比對法”了。也就是說,從句子左端開始,不斷比對最長的詞(組不了詞的單字則單獨劃開),直到把句子劃分完。算法的理由很簡單:人在閱讀時也是從左往右逐字讀入的,最大比對法是與人的習慣相符的。而在大多數情況下,這種算法也的确能僥幸成功。不過,這種算法并不可靠,構造反例可以不費吹灰之力。例如,“北京大學生前來應聘”本應是“北京/大學生/前來/應聘”,卻會被誤分成“北京大學/生前/來/應聘”。

維護一個特殊規則表,可以修正一些很機械的問題,效果相當不錯。例如,“不可能”要劃分成“不/可能”,“會診”後面接“斷”、“療”、“脈”、“治”時要把“會”單獨切出,“的确切”後面是抽象名詞時要把“的确切”分成“的/确切”,等等。

還有一個适用範圍相當廣的特殊規則,這個強大的規則能修正很多交集型歧義的劃分錯誤。首先我們要維護一個一般不單獨成詞的字表,比如“民”、“塵”、“偉”、“習”等等;這些字通常不會單獨劃出來,都要跟旁邊的字一塊兒組成一個詞。在分詞過程中時,一旦發現這些字被孤立出來,都重新考慮它與前面的字組詞的可能。例如,在用最大比對法切分“為人民服務”時,算法會先劃出“為人”一詞,而後發現“民”字隻能單獨成詞了。查表卻發現,“民”并不能單獨劃出,于是考慮進行修正——把“為人”的“人”字配置設定給“民”字。巧在這下“為”和“人民”正好都能成詞,據此便可得出正确的劃分“為/人民/服務”。

不過,上述算法歸根結底,都是在像人一樣從左到右地掃描文字。為了把問題變得更加形式化,充分利用計算機的優勢,我們還有一種與人的閱讀習慣完全不同的算法思路:把句子作為一個整體來考慮,從全局的角度評價一個句子劃分方案的好壞。設計自動分詞算法的問題,也就變成了如何評估分詞方案優劣的問題。最初所用的辦法就是,尋找詞數最少的劃分。注意,每次都比對最長的詞,得出的劃分不見得是詞數最少的,錯誤的貪心很可能會不慎錯過一些更優的路。因而,在有的情況下,最少詞數法比最大比對法效果更好。若用最大比對法來劃分,“獨立自主和平等互利的原則”将被分成“獨立自主/和平/等/互利/的/原則”,一共有 6 個詞;但詞數更少的方案則是“獨立自主/和/平等互利/的/原則”,一共隻有 5 個詞。

當然,最少詞數法也會有踩大便的時候。“為人民辦公益”的最大比對劃分和最少詞數劃分都是“為人/民辦/公益”,而正确的劃分則是“為/人民/辦/公益”。同時,很多句子也有不止一個詞數最少的分詞方案,最少詞數法并不能從中選出一個最佳答案。不過,把之前提到的“不成詞字表”裝備到最少詞數法上,我們就有了一種簡明而強大的算法:

對于一種分詞方案,裡面有多少詞,就罰多少分;每出現一個不成詞的單字,就加罰一分。最好的分詞方案,也就是罰分最少的方案。

這種算法的效果出人意料的好。“他說的确實在理”是一個很困難的測試用例,“的确”和“實在”碰巧也成詞,這給自動分詞帶來了很大的障礙。但是“确”、“實”、“理”通常都不單獨成詞的,是以很多切分方案都會被扣掉不少分:

他/說/的/确實/在理 (罰分:1+1+1+1+1 = 5 ) 他/說/的确/實/在理 (罰分:1+1+1+2+1 = 6 ) 他/說/的确/實在/理 (罰分:1+1+1+1+2 = 6 )

正确答案勝出。

需要指出的是,這個算法并不需要枚舉所有的劃分可能。整個問題可以轉化為圖論中的最短路徑問題,利用動态規劃效率則會更高。

算法還有進一步加強的餘地。大家或許已經想到了,“字不成詞”有一個程度的問題。“民”是一個不成詞的語素,它是絕對不會單獨成詞的。“鴨”一般不單獨成詞,但在兒歌童謠和科技語體中除外。“見”則是一個可以單獨成詞的語素,隻是平時我們不常說罷了。換句話說,每個字成詞都有一定的機率,每個詞出現的頻率也是不同的。

何不用每個詞出現的機率,來衡量分詞的優劣?于是我們有了一個更标準、更連續、更自動的改進算法:先統計大量真實語料中各個詞出現的頻率,然後把每種分詞方案中各詞的出現機率乘起來作為這種方案的得分。利用動态規劃,不難求出得分最高的方案。

以“有意見分歧”為例,讓我們看看最大機率法是如何工作的。查表可知,在大量真實語料中,“有”、“有意”、“意見”、“見”、“分歧”的出現機率分别是 0.0181 、 0.0005 、 0.0010 、 0.0002 、 0.0001 ,是以“有/意見/分歧”的得分為 1.8×10-9 ,但“有意/見/分歧”的得分隻有 1.0×10-11 ,正确方案完勝。

這裡的假設是,用詞造句無非是随機選詞連在一塊兒,是一個簡單的一進制過程。顯然,這個假設理想得有點不合理,必然會有很多問題。考慮下面這句話:

這/事/的确/定/不/下來

但是機率算法卻會把這個句子分成:

這/事/的/确定/不/下來

原因是,“的”字的出現機率太高了,它幾乎總會從“的确”中掙脫出來。

其實,以上所有的分詞算法都還有一個共同的大缺陷:它們雖然已經能很好地處理交集型歧義的問題,卻完全無法解決另外一種被稱為“組合型歧義”的問題。所謂組合型歧義,就是指同一個字串既可合又可分。比如說,“個人恩怨”中的“個人”就是一個詞,“這個人”裡的“個人”就必須拆開;“這扇門的把手”中的“把手”就是一個詞,“把手擡起來”的“把手”就必須拆開;“學生會宣傳部”中的“學生會”就是一個詞,“學生會主動完成作業”裡的“學生會”就必須拆開。這樣的例子非常多,“難過”、“馬上”、“将來”、“才能”、“過人”、“研究所”、“原子能”都有此問題。究竟是合還是分,還得取決于它兩側的詞語。到目前為止,所有算法對劃分方案的評價标準都是基于每個詞固有性質的,完全不考慮相鄰詞語之間的影響;因而一旦涉及到組合型歧義的問題,最大比對、最少詞數、機率最大等所有政策都不能實作具體情況具體分析。

于是,我們不得不跳出一進制假設。此時,便有了那個 google 黑闆報上提到的統計語言模型算法。對于任意兩個詞語 w1 、 w2 ,統計在語料庫中詞語 w1 後面恰好是 w2 的機率 p(w1, w2) 。這樣便會生成一個很大的二維表。再定義一個句子的劃分方案的得分為 p(∅, w1) · p(w1, w2) · … · p(wn-1, wn) ,其中 w1, w2, …, wn 依次表示分出的詞。我們同樣可以利用動态規劃求出得分最高的分詞方案。這真是一個天才的模型,這個模型一并解決了詞類标注、語音識别等各類自然語言處理問題。

至此,中文自動分詞算是有了一個漂亮而實用的算法。

但是,随便拿份報紙讀讀,你就會發現我們之前給出的測試用例都太理想了,簡直就是用來喂給計算機的。在中文分詞中,還有一個比分詞歧義更令人頭疼的東西——未登入詞。中文沒有首字母大寫,專名号也被取消了,這叫計算機如何辨認人名地名之類的東西?最近十年來,中文分詞領域都在集中攻克這一難關。

在漢語的未定義詞中,中國人名的規律是最強的了。根據統計,漢語姓氏大約有 1000 多個,其中“王”、“陳”、“李”、“張”、“劉”五大姓氏的覆寫率高達 32% ,前 400 個姓氏覆寫率高達 99% 。人名的用字也比較集中,“英”、“華”、“玉”、“秀”、“明”、“珍”六個字的覆寫率就有 10.35% ,最常用的 400 字則有 90% 的覆寫率。雖然這些字分布在包括文言虛詞在内的各種詞類裡,但就用字的感情色彩來看,人名多用褒義字和中性字,少有不雅用字,是以規律性還是非常強的。根據這些資訊,我們足以計算一個字元串能成為名字的機率,結合預先設定的門檻值便能很好地識别出可能的人名。

可是,如何把人名從句子中切出來呢?換句話說,如果句中幾個連續字都是姓名常用字,人名究竟應該從哪兒取到哪兒呢?人名以姓氏為左邊界,相對容易判定一些。人名的右邊界則可以從下文的提示确定出來:人名後面通常會接“先生”、“同志”、“校長”、“主任”、“醫生”等身份詞,以及“是”、“說”、“報道”、“參加”、“通路”、“表示”等動作詞。

但麻煩的情況也是有的。一些高頻姓氏本身也是經常單獨成詞的常用字,例如“于”、“馬”、“黃”、“常”、“高”等等。很多反映時代性的名字也是本身就成詞的,例如“建國”、“建設”、“國慶”、“躍進”等等。更讨厭的就是那些整個名字本身就是常用詞的人了,他們會徹底打亂之前的各種模型。如果分詞程式也有智能的話,他一定會把所有叫“高峰”、“汪洋”的人拖出去斬了;要是聽說了有人居然敢叫“令計劃”,估計直接就崩潰了。

還有那些恰好與上下文組合成詞的人名,例如:

費孝通向人大常委會送出書面報告

鄧穎超生前使用過的物品

這就是最考驗分詞算法的句子了。

相比之下,中國地名的用字就分散得多了。北京有一個地方叫“臭泥坑”,網上搜尋“臭泥坑”,第一頁全是“臭泥坑地圖”、“臭泥坑附近酒店”之類的資訊。某年《重慶晨報》刊登停電通知,上面赫然印着“停電範圍包括沙坪壩區的犀牛屙屎和犀牛屙屎抽水”,讀者紛紛去電投訴印刷錯誤。記者仔細一查,你猜怎麼着,印刷并無錯誤,重慶真的就有叫“犀牛屙屎”和“犀牛屙屎抽水”的地方。

好在,中國地名數量有限,這是可以枚舉的。中國地名委員會編寫了《中華人民共和國地名錄》,收錄了從高原盆地到橋梁電站共 10 萬多個地名,這讓中國地名的識别便利了很多。

真正有些困難的就是識别機構名了,雖然機構名的字尾比較集中,但左邊界的判斷就有些難了。更難的就是品牌名了。如今各行各業大打創意戰,品牌名可以說是無奇不有,而且經常本身就包含常用詞,更是給自動分詞添加了不少障礙。

最難識别的未登入詞就是縮略語了。“高數”、“抵京”、“女單”、“發改委”、“北醫三院”都是比較好認的縮略語了,有些縮略語搞得連人也是丈二和尚摸不着頭腦。你能猜到“人影辦”是什麼機構的簡稱嗎?打死你都想不到,是“人工影響天氣辦公室”。

漢語中構造縮略語的規律很詭異,目前也沒有一個定論。初次聽到這個問題,幾乎每個人都會做出這樣的猜想:縮略語都是選用各個成分中最核心的字,比如“安全檢查”縮成“安檢”,“人民警察”縮成“民警”等等。不過,反例也是有的,“郵政編碼”就被縮成了“郵編”,但“碼”無疑是更能概括“編碼”一詞的。當然,這幾個縮略語已經逐漸成詞,可以加進詞庫了;不過新近出現的或者臨時構造的縮略語該怎麼辦,還真是個大問題。

說到新詞,網絡新詞的大量出現才是分詞系統真正的敵人。這些新詞彙的來源千奇百怪,幾乎沒有固定的産生機制。要想實作對網絡文章的自動分詞,目前來看可以說是相當困難的。革命尚未成功,分詞算法還有很多進步的餘地。

繼續閱讀