|
在本章以及下面幾章,我將詳細(xì)介紹一下使用prolog設(shè)計(jì)專家系統(tǒng)的技術(shù)。首先讓我們來看看什么是專家系統(tǒng),以及它的基本設(shè)計(jì)方法和技術(shù),然后再使用prolog設(shè)計(jì)幾個(gè)微型專家系統(tǒng)。 什么是專家系統(tǒng) 專家系統(tǒng)是人工智能最重要的應(yīng)用之一,它的目的是讓電腦在某種程度上幫助或者替代某個(gè)領(lǐng)域的專家解決問題。例如醫(yī)療診斷系統(tǒng)、投資風(fēng)險(xiǎn)分析系統(tǒng)、家居設(shè)計(jì)系統(tǒng)等等。 一個(gè)典型的專家系統(tǒng)的構(gòu)成方式如下圖所示:
Domain Expert就是某個(gè)領(lǐng)域的專家,他提供原始的知識(shí)。Knowledge Engineer是把專家的知識(shí)翻譯成電腦所能夠識(shí)別的知識(shí)的工程師。某領(lǐng)域的專家把他所知道的知識(shí)告訴knowlegde engineer以后,由knowlegde engineer對(duì)這些知識(shí)進(jìn)行處理,最后做成知識(shí)庫knowledge base。System Engineer是設(shè)計(jì)專家系統(tǒng)的程序員,他的主要任務(wù)是編寫專家系統(tǒng)的推理機(jī)構(gòu)inferface engine,和用戶界面user interface。用戶使用用戶界面和專家系統(tǒng)打交道,他和專家系統(tǒng)之間的交流的一些信息由工作空間working storage儲(chǔ)存。推理機(jī)構(gòu)根據(jù)用戶信息和知識(shí)庫中的信息為用戶提供服務(wù)。 在設(shè)計(jì)專家系統(tǒng)時(shí)候有目標(biāo)驅(qū)動(dòng)和數(shù)據(jù)驅(qū)動(dòng)兩種方式。下面我們通過實(shí)例來說明一下如何使用prolog編寫目標(biāo)驅(qū)動(dòng)的專家系統(tǒng)。 一個(gè)可以識(shí)別鳥類的專家系統(tǒng) 這個(gè)系統(tǒng)的目的是通過用戶對(duì)某種鳥類的描述,推斷出用戶描述的是何種鳥。由于prolog的規(guī)則就是一種非常好的表達(dá)知識(shí)的方法,而其內(nèi)建的回溯功能和模式匹配功能則是很好的推理機(jī)構(gòu),所以使用prolog來編寫這樣的專家系統(tǒng)是再容易不過的了。 首先讓我們來看看如何是使用prolog的規(guī)則來表達(dá)知識(shí)吧。我們可以從鳥類專家那里得到如下的知識(shí): 如果某種鳥是屬于信天翁科,并且其顏色是白色的,那么這種叫就是laysan信天翁。(我是翻譯的外文教材,所以這里關(guān)于鳥類的知識(shí)翻譯的并不是太準(zhǔn)確) 當(dāng)然我們要用英語來表這個(gè)規(guī)則: IF 如果使用prolog的規(guī)則來表達(dá)就是: bird(laysan_albatross) :- 同樣我們還可以加入下面的規(guī)則: bird(laysan_albatross):- bird(black_footed_albatross):- bird(whistling_swan) :- bird(trumpeter_swan) :- 為了能夠讓這些規(guī)則能夠分辨不同的鳥類,我們必須儲(chǔ)存關(guān)于某種鳥的特定的信息。例如,如果我們加入下面兩個(gè)事實(shí)的話: family(albatross). 然后在解釋器中進(jìn)行如下的詢問: - bird(X). 很自然的我們就得到了答案。 現(xiàn)在我們看到了一個(gè)再簡(jiǎn)單不過的專家系統(tǒng)了。他具備了前面所說的專家系統(tǒng)的幾個(gè)構(gòu)造部分。 四條關(guān)于識(shí)別鳥的規(guī)則就是知識(shí)庫knowledge base。 兩條關(guān)于某種鳥的特性的事實(shí)就是工作空間working storage中存儲(chǔ)的信息。 prolog的內(nèi)建的模式匹配和回溯功能就是推理機(jī)構(gòu)。 prolog的解釋器就是用戶界面。 當(dāng)然,上面的這四個(gè)部分都還只是雛形,下面我們就要分解介紹如何慢慢的添加功能。 增加層次關(guān)系 僅僅使用上面的四條知識(shí)構(gòu)成專家系統(tǒng)的知識(shí)結(jié)構(gòu)是遠(yuǎn)遠(yuǎn)不夠的。下面我們就來添加一些新的知識(shí)。動(dòng)物界為動(dòng)物分了科、目、屬、種、類等幾個(gè)層次,這些層次構(gòu)成一個(gè)樹狀結(jié)構(gòu),下面的幾條規(guī)則就描述了其中的一些層次結(jié)構(gòu)。 order(tubenose) :- order(waterfowl) :- family(albatross) :- family(swan) :-
其中的第二個(gè)規(guī)則:order的中文意思是動(dòng)物學(xué)的目,waterfowl的意思是水鳥,所以第二個(gè)規(guī)則描述的就是,水鳥這個(gè)目的動(dòng)物具有“腳有蹼”“bill扁平”這兩個(gè)特點(diǎn)。 再解釋一下最后一個(gè)規(guī)則,他的意思是天鵝這個(gè)科的的特點(diǎn)是:“屬于水鳥目”“頸部很長(zhǎng)”“顏色是白色”“飛行起來比較沉重”。 注意前面我們bird的規(guī)則中使用了family,而在此對(duì)family的規(guī)則進(jìn)行了定義,定義family的過程中,又使用了order。作為有強(qiáng)大回溯功能的prolog可以很容易的把這些規(guī)則串起來,而不需要我們做更多的工作。下面我們來看一個(gè)例子。 假如我們?cè)谙到y(tǒng)中添加了如下的描述鳥的事實(shí): nostrils(external_tubular). 那么我們就可以用來識(shí)別具有這些特征的是什么鳥了。 - bird(X). 更加復(fù)雜的規(guī)則 要識(shí)別加拿大鵝就需要比較復(fù)雜的規(guī)則。因?yàn)榧幽么簌Z夏天在加拿大度過,而冬天在美國度過。我們?cè)谧R(shí)別的時(shí)候需要知道是在什么地方,什么時(shí)候看到這種鳥的。在此我們僅需要加入兩個(gè)規(guī)則來描述它就行了。 bird(canada_goose):- bird(canada_goose):- 我們?cè)偌尤胍恍╆P(guān)于地方的謂詞: country(united_states):- country(united_states):- country(united_states):- country(united_states):- country(canada):- province(ontario). country(canada):- province(quebec). region(new_england):- region(south_east):- state(X), member(X, [florida, mississippi, ....]). 還有許多需要多個(gè)規(guī)則的鳥類。例如雄野鴨的頭是綠色的,而雌野鴨是雜褐色的。 bird(mallard):- family(duck), voice(quack), head(green). bird(mallard):- family(duck), voice(quack), color(mottled_brown). 好了,作為一個(gè)例子,我們的關(guān)于鳥類的知識(shí)夠多的了。只要你手上有一本這方面的專業(yè)書籍,你應(yīng)該很容易的把書上的知識(shí)翻譯成prolog的規(guī)則吧。 用戶界面 前面我們一直是使用prolog的事實(shí)來儲(chǔ)存有關(guān)用戶掌握的信息,作為一個(gè)真正的專家系統(tǒng),系統(tǒng)應(yīng)該主動(dòng)的向用戶提問以收集信息,而不是讓用戶自己把所有的信息手工輸入。 所以這里當(dāng)我們遇到需要向用戶收集信息的時(shí)候,就應(yīng)該向用戶提出問題。 前面的有關(guān)鳥的屬性都是需要從用戶那里獲得的信息。所以我們就把他們改寫成下面這種規(guī)則: eats(X):- ask(eats, X). ask(Attr, Val):- write(Attr:Val), write(‘? ‘), read(yes). 有了上面的這些規(guī)則,當(dāng)系統(tǒng)需要尋找color(white)這個(gè)目標(biāo)的時(shí)候,他就會(huì)調(diào)用ask規(guī)則,如果ask(color,white)目標(biāo)成立的話,那么color(white)就成功了。 ask/2中的最后一個(gè)目標(biāo)read(yes),只有當(dāng)用戶輸入yes的時(shí)候才成功,而用戶輸入別的東西都會(huì)是失敗。 現(xiàn)在我們不需要事先添加用戶信息就可以運(yùn)行了,系統(tǒng)會(huì)在需要的時(shí)候?qū)τ脩暨M(jìn)行詢問。下面是一次對(duì)話的例子: - bird(X). 這里還有一個(gè)問題,如果用戶最后一個(gè)問題回答no的話,那么bird(laysan_albatross)規(guī)則就會(huì)失敗,然后回溯,將會(huì)測(cè)試下一個(gè)規(guī)則bird(black_footed_albatross),它的第一個(gè)子目標(biāo)又會(huì)引起系統(tǒng)詢問一些以前曾經(jīng)詢問過的問題。這的確是個(gè)比較笨的系統(tǒng),下面我們將介紹如何保存詢問的信息,以免重復(fù)詢問。 記住答案 我們使用新的謂詞known/3來記住用戶對(duì)問題的回答。這個(gè)謂詞的子句不是直接寫在程序中的,而是通過assert動(dòng)態(tài)的加入到系統(tǒng)中的,這也就是專家系統(tǒng)的工作空間working storage。 每次調(diào)用ask謂詞要做的第一件事情,就是檢查known謂詞是否已經(jīng)保存了這個(gè)問題的信息。如果還沒有保存過這樣的問題的信息,就會(huì)在用戶回答以后,把回答的答案加入到系統(tǒng)中。known/3的三個(gè)參數(shù)分別是yes/no,屬性,屬性值。 新版本的ask謂詞如下: ask(A, V):- ask(A, V):- ask(A, V):- 具有多值的回答 我們還可以對(duì)known謂詞進(jìn)行改進(jìn)。到目前為止,ask謂詞所詢問的問題都是是非問題。這意味著用戶可能會(huì)對(duì)color-white和color-black這樣的問題同時(shí)回答yes,這顯然是不合理的,當(dāng)系統(tǒng)知道color-white是真的時(shí)候,就應(yīng)該同時(shí)知道color-black是假。這就是說color屬性只能是單值的,不過對(duì)于voice這樣的屬性就可以多值的。所以我們?cè)趯<蚁到y(tǒng)中應(yīng)該對(duì)這些屬性進(jìn)行說明。 我們使用最簡(jiǎn)單的方法來解決這個(gè)問題---加一個(gè)用來描述屬性的謂詞。 multivalued(voice). 這兩個(gè)句子說明voice和feed屬性可以是多值的。 同時(shí)我們需要對(duì)ask謂詞進(jìn)行修改: ask(A, V):- 我們添加上面一條ask子句,它應(yīng)該放在其他ask子句之前。這個(gè)子句首先檢查屬性A是否為多值屬性,如果不是,就在已知的屬性值中查找是否已經(jīng)有其他的值, 如果有的話,就不需要詢問用戶,而直接失敗了。 例如,如果用戶已經(jīng)對(duì)size-large這個(gè)問題回答了yes,系統(tǒng)就不會(huì)詢問size-small這樣的問題了。 用戶菜單 我們可以進(jìn)一步的改進(jìn)用戶的界面,例如可以添加讓用戶選擇答案的菜單功能。 我們使用menuask謂詞來完成這個(gè)功能。它和ask很相像,不過多了一個(gè)用來保存所有可能的屬性值的列表參數(shù)。把原來的ask謂詞出現(xiàn)的地方用menuask來替代: size(X):- menuask(size, X, [large, plump, medium, small]). menuask的具體程序如下: menuask(A, V, MenuList) :- check_val(X, A, V, MenuList) :- %如果用戶輸入的值在列表中可以找到。 check_val(X, A, V, MenuList) :- %如果找不到。 這是一個(gè)最最簡(jiǎn)單的menuask的例子,用戶需要輸入屬性值的內(nèi)容,而不能通過輸入1、2、3或者是a、b、c來選擇屬性值。 一個(gè)簡(jiǎn)單的外殼程序 很明顯這個(gè)識(shí)別鳥類的專家系統(tǒng)由兩個(gè)完全不同的部分組成,一個(gè)是知識(shí)庫,另一個(gè)是控制用戶界面的。 我們應(yīng)該盡量把這兩部分分離開來,這樣我們就可以制作出一個(gè)外殼程序,使用這個(gè)外殼程序和不同的知識(shí)庫聯(lián)接,就可以快速的開發(fā)不同的專家系統(tǒng)了。 為了能夠把這兩部分分開,就要定義統(tǒng)一的接口。由于不同的專家系統(tǒng)要完成的目標(biāo)不一樣,例如識(shí)別鳥的系統(tǒng)的目標(biāo)是bird(X),而識(shí)別魚的系統(tǒng)則是fish(X),因此在每個(gè)知識(shí)庫中都定一個(gè)相同的最頂層目標(biāo)top_goal(X)。對(duì)于識(shí)別鳥的系統(tǒng)這個(gè)目標(biāo)為: top_goal(X):-bird(X). 在外殼程序中我們可以定義solve謂詞做一些初始化工作,以及調(diào)用知識(shí)庫的頂層目標(biāo)top_goal: solve :- solve :- 內(nèi)部謂詞abolish是用來刪除系統(tǒng)中所有的known子句的。這樣用戶就可以使用solve來解決不同的問題,而不至于把兩次對(duì)話的內(nèi)容搞混淆。 由于一開始系統(tǒng)中沒有known子句,所以需要使用define來定義一下,這樣系統(tǒng)再找不到known子句的時(shí)候就不會(huì)報(bào)告錯(cuò)誤了。不同的prolog系統(tǒng)的這種內(nèi)部謂詞不一定相同。 現(xiàn)在總結(jié)一下: solve ask menuask謂詞都是外殼程序中的謂詞,也就是說它們對(duì)于所有的類似的專家系統(tǒng)都是相同的。 top_goal bird order family region size color eats wings multivalue這樣的謂詞都是屬于知識(shí)庫的謂詞,它們是和具體的知識(shí)掛鉤的。top_goal是外殼程序和知識(shí)庫之間的橋梁。 如果我們把這些謂詞分別保存在不同的文件中,例如外殼程序保存在文件native中,而鳥類的知識(shí)庫保存在birds.kb中的話,我們只要在解釋器中進(jìn)行如下的對(duì)話就可以使用專家系統(tǒng)了。 - consult(native). - consult(‘birds.kb‘). - solve. 命令循環(huán) 我們還可以增強(qiáng)外殼程序的功能,增加一個(gè)叫做go的謂詞,go可以識(shí)別三種命令:load consult和quit。 load命令用來調(diào)入某個(gè)知識(shí)庫,consult命令用來調(diào)用知識(shí)庫的top_goal從而開始對(duì)話,quit用來退出外殼程序。 下面是go謂詞的具體程序: go :- greeting :- do(load) :- load_kb, !. do(consult) :- solve, !. do(quit). do(X) :- go謂詞使用repeat循環(huán)不停的從用戶取得命令。do謂詞用來識(shí)別用戶的命令。這里的load_kb謂詞的具體程序如下: load_kb :- 我們還可以增加一些其他的外殼命令,例如:help,用來顯示所有的命令的使用方法,list用來列出所有的known子句以供調(diào)試之用。 最后我們的專家系統(tǒng)和用戶之間的對(duì)話如下: - consult(native). - go. 通過使用外殼程序,我們可以屏蔽一些prolog編程的難點(diǎn)。讓開發(fā)人員在編寫專家系統(tǒng)的時(shí)候只需要把注意力集中在知識(shí)庫的表達(dá)上面,而使用prolog表達(dá)知識(shí)庫是很容易的,就和我們平時(shí)說話沒有什么兩樣。 到這里,你應(yīng)該對(duì)專家系統(tǒng)的編寫有個(gè)初步的了解了吧,下一章我們將研究一些比較深的專家系統(tǒng)的知識(shí)了。 (由于本章介紹的專家系統(tǒng)還只是雛形,所以沒有提供完整的程序,你可以自己把上面的程序片斷拼湊起來,在解釋器中測(cè)試一下。) |
|
|