夏 添
同濟大學軟件學院,上海 201804
自然語言理解
——原理與工具的介紹
夏 添
同濟大學軟件學院,上海 201804
自然語言理解一直是一個很大很麻煩的問題,本文討論了自然語言理解的基本概念,以及幾個實現自然實現方法的討論。最后,提出一個叫做nltk的工具,并介紹這個工具如何使得開發自然語言理解應用更加迅速
自然語言理解;規則;nltk
如何來理解自然語言呢?怎樣才能讓機器理解自然語言呢?這是自然語言理解,特別是計算語言學要講的問題。
“理解”是什么意思?事實我們常常說,“我明白了你的意思”。一個人說這句話的意思實際上時說,他可以利用你剛告訴他的東西進行事情推理和利用了。實際上,對于計算機來說,機器明白了人的意思實際上說,機器可以利用人用自然語言輸入的信息進行計算。
那么如何進行映射呢?這里可以參考下編譯原理,編譯原理通過一個開始符號一步步往下推導,一直到一個非終結符號都沒有的情況,這個時候一個句子就算是解析完成了,而解析出來的句子通過一些符號運算,最終可以映射成計算機可以理解的機器語言。
那么該如何轉換呢?比較直觀的想法就是使用編譯原理技術,使用一個開始符號 S,然后一步步推導到每個單詞(這里的單詞實際上就是終結符號)。然后對于每次歸約,使用action來操作,最終映射成電腦所能理解的sql。對于一個像c語言的語法解析器來說,它在很大的程度上依賴于用戶—也就是程序員—對于語言的理解,像那個if else 語法,不管你怎么對齊,else也就只能和最近的一個if組成一個句子。但自然語言的情況就復雜得多了。在現實的生活中,不但有一詞多義的多義的情況,而且就是對于同一句話,斷句不同都會造成非常不同的效果。比如說對于like這個詞來說,在不同的情況就有不同的意思。We like flying 和you are like your mom.的時候就分別是喜歡和像的意思。如何區分?我們可以根據搭配來解決這個問題。對于像is like 這種情況我們可以給like的“像”意思一個比較高的概率,而在另一種情況則給“喜歡”一個比較高的概率,這樣,碰到不同的搭配就可以有不同意思理解。這個這種方法可以參考《統計自然語言處理基礎》中的馬可夫鏈。馬可夫鏈就是就是根據概率狀態轉移模型來分析在什么樣的情況下,使用哪個表達方式更好。
當然,在分析一句話的時候,我們可能會碰到大量的重復情況,比如說,對于“I see a boy on the chair,使用普通分析技術,必定是先分析掉“I” “see”
“a boy on the chair ”再繼續分析“I see a boy”“on the chair ”。對于一個比較大型的系統來說,時間上可能會非常吃不消。而在自然語言理解中,我們一般可以這樣做在分析一個句子的時候,不是每次只規約一種情況,而是把所有可規約的情況都規約出來,然后再繼續分析,這樣緩存的結果就是,我們不必要每次都回溯到開始符號s來重新分析,而是在分析到每個詞的時候更新一下當前分析句子的狀態就可以了。經過統計,使用這中技術的系統比不使用的要快5 000倍~100 000倍,當然,同時因為緩存中間結果,系統開銷也大得多。
但是,如何才能句子的意思進行理解呢?我們回到我開始的那個問題。對于像下面一個對話:
a.Which country is Athens in? b.Greece
來說,我們可以使用下面的規則來進行
% start S
S[SEM=(?np + WHERE + ?vp)] -> NP[SEM=?np] VP[SEM=?vp]
VP[SEM=(?v + ?pp)] -> IV[SEM=?v] PP[SEM=?pp]
VP[SEM=(?v + ?ap)] -> IV[SEM=?v] AP[SEM=?ap]
NP[SEM=(?det + ?n)] -> Det[SEM=?det] N[SEM=?n]
PP[SEM=(?p + ?np)] -> P[SEM=?p] NP[SEM=?np]
AP[SEM=?pp] -> A[SEM=?a] PP[SEM=?pp]
NP[SEM='Country="greece"'] -> 'Greece'
NP[SEM='Country="china"'] -> 'China'
Det[SEM='SELECT'] -> 'Which' | 'What'
N[SEM='City FROM city_table'] -> 'cities'
IV[SEM=''] -> 'are'
A[SEM=''] -> 'located'
P[SEM=''] -> 'in'
其中,s是代表開始符號,后面的則是一個個的推導符號。而中間最關鍵的地方就是那個sem特征,這個特征可以幫助分析器在規約的時候將一個簡單的句子分析成相應的sql.
除了有基礎的理論之外,實現自然語言理解系統也很重要。出于效率的情況,真正的系統可能使用分布式計算,然后在每個節點上使用像c++這樣的語言來進行計算。但是對于像c++這樣的語言,可能在開發與調試上需要大量的時間和極度的細致,這對于新應用的研究工作來說是不太合適的。在這種情況,使用基于python的nltk會比較好一些。
Nltk的全稱是”自然語言工具包”,可以再google code上找到這個開源項目。目前的最新版本是2.0b9。這個工具支持了很多關于自然語言理解方面的技術,是一個比較好的開發框架。
我們可以使用這個工具來簡單的對上面的情況進行一些講解,首先,我們可以先以上面第2節提到的規則作為一個模板來寫一個文法文件,它的后綴名是.fcfg(比如a.fcfg)。nltk在處理的時候會根據你所提供文法文件來裝入相應的規則。我們可以進行類似如下的操作
>>> from nltk import load_parser
>>> cp = load_parser('grammars/book_grammars/sql0.fcfg')
>>> query = 'What cities are located in China'
>>> trees = cp.nbest_parse(query.split())
>>> answer = trees[0].node['sem']
>>> q = ' '.join(answer)
>>> print q
SELECT City FROM city_table WHERE Country="china"
注意上面的操作,我們通過load_parser方法裝入語法文件,然后再使用nbestparser就可以實現這些操作了。
從目前的情況的看,自然語言理解不管在從學術研究到商業市場的各個領域都有比較迫切和強烈的需求,它本身也涵蓋了從人工智能,數據挖掘等非常廣泛的領域,而且對于理論和技術的要求都比較高。目前來說,nltk應該算是比較成熟和穩定的工具,值得在各個研究和實際的應用中使用
TP31
A
1674-6708(2010)30-0243-02