




已閱讀5頁,還剩10頁未讀, 繼續(xù)免費閱讀
版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
Prolog開發(fā)專家系統(tǒng)-解釋專家系統(tǒng)的一個重要的功能就是要能夠解釋它自己的行為。用Prolog開放具體解釋能力的專家系統(tǒng)。解釋專家系統(tǒng)的一個重要的功能就是要能夠解釋它自己的行為。這意味著用戶可以在任何時候詢問系統(tǒng)為什么得出某個結(jié)論,或者為什么提出某個問題。這對于用戶來說是一項重要的功能,有時候用戶只要求知道答案,可是有時候用戶需要知道解釋,而通常的專家系統(tǒng)無法對它的行為做出有說服力的解釋,而只能夠告訴用戶它使用了哪些規(guī)則得出的結(jié)論,至于為什么這些規(guī)則能夠得出這樣的結(jié)論,系統(tǒng)是無法解釋的。例如下面這個例子:汽車能夠啟動么? 不行引擎發(fā)動了么? 是的你問到汽油味道了么?是的建議:等待5秒鐘,然后再試。為什么?因為我使用了這樣的規(guī)則:如果不能夠啟動而且引擎發(fā)動了而且問到汽油味,那么就推薦的等待5秒再試。 很顯然這個專家系統(tǒng)無法解釋其選擇某個規(guī)則的原因,而只能告訴用戶它使用了某種規(guī)則。如果用戶硬要刨根問底的話這個系統(tǒng)就無能為力了。為了讓系統(tǒng)具有真正的解釋功能,我們需要比規(guī)則更多的知識。對每個規(guī)則進行注釋是一個比較好的方法,這種方法將在以后的章節(jié)介紹。還有一種方法就是把更多的知識進行編碼,推理引擎和解釋引擎都同時使用這個知識庫。還有些專家系統(tǒng)的知識庫是屬于經(jīng)驗知識,在這種情況下系統(tǒng)的解釋可以直接使用規(guī)則。像識別鳥類的分類系統(tǒng)就屬于這種情況。鳥類識別系統(tǒng)就能夠使用它的規(guī)則直接進行解釋,例如為什么某種鳥是野鴨,就是因為它具有野鴨的一些特性,而這些特性就是規(guī)則所定義的。識別鳥類并不存在什么高深的理論,而只是根據(jù)某些特點進行分類的。也許對于用戶來說某些解釋是多余的,不過對于開發(fā)人員來說這是十分重要的。這和通常的語言中的跟蹤調(diào)試有些類似。當系統(tǒng)沒有按照預期的效果執(zhí)行的時候,開發(fā)人員可以根據(jù)解釋研究錯誤的產(chǎn)生原因。知識工程師也可以根據(jù)解釋從而設計出更加貼近用戶的知識庫。解釋的種類在一般的專家系統(tǒng)中常用的有4種解釋。1. 報告當前的會話進程。2. 解釋系統(tǒng)是如何得出某個結(jié)論的。3. 解釋為怎么系統(tǒng)向用戶詢問某個問題。4. 解釋為什么某個結(jié)論不成立。在我們上一章介紹的Clam外殼程序中,推理引擎是自己編寫的,所以這些解釋特性并不難加入系統(tǒng)當中。在第一章的原始外殼中沒有推理引擎,而是使用prolog的內(nèi)部引擎,這樣就無法加入新的解釋特性,為了達到這個目的,我們需要編寫自己的推理引擎,而這個引擎的運作方式和prolog相同,也就是說需要使用prolog編寫一個prolog,好在這項工作并不難完成。在Clam中使用解釋首先讓我們看看在Clam中加入了解釋的一個例子,這里沿用了上一章汽車診斷系統(tǒng)。 首先用戶打開對話跟蹤功能,跟蹤的信息使用粗體字表示,跟蹤信息顯示了系統(tǒng)是如何調(diào)用規(guī)則的。注意系統(tǒng)正確的表示出了規(guī)則的嵌套調(diào)用。報告當前的會話進程的解釋:consult, restart, load, list, trace, how, exit:trace onconsult, restart, load, list, trace, how, exit:consultcall rule 1 Does the engine turn over?: nocall rule 2 Are the lights weak?: yesexit rule 2 call rule 3 Is the radio weak?: yesexit rule 3 exit rule 1 call rule 4 fail rule 4call rule 5 fail rule 5call rule 6 fail rule 6problem-battery-cf-75done with problem下面來看看如何解釋為什么要向系統(tǒng)提問。用戶可以在任何時候向推理引擎詢問why,請看這個例子:.Is the radio weak?: whyrule 3 If radio_weak Then battery_bad 50 rule 1 If not turn_over battery_bad Then problem is battery 100 goal problem .這里可以看出來當用戶向系統(tǒng)詢問為什么問is the radio weak這個問題的時候,系統(tǒng)把有關這個問題的幾個規(guī)則列出來了。再來看看how提問,當系統(tǒng)給出了某個結(jié)論的時候,用戶可能想知道是如何得到這個結(jié)論的,這個時候向系統(tǒng)詢問blem-battery-cf-75done with problemconsult, restart, load, list, trace, how, exit:howGoal? problem is batteryproblem is battery was derived from rules: 1 rule 1 If not turn_over battery_bad Then problem is battery 100 在這里列出了能夠直接得到結(jié)論的規(guī)則。如果用戶需要繼續(xù)知道為什么battery_bad的話,就進行下面的詢問:consult, restart, load, list, trace, how, exit:howGoal? battery_badbattery_bad was derived from rules: 3 2 rule 3 If radio_weak Then battery_bad 50 rule 2 If lights_weak Then battery_bad 50 在這里有兩個規(guī)則可以得到battery_bad的結(jié)論,系統(tǒng)把它們都列舉出來了??赐炅耸痉?,該是研究程序的時候了。 跟蹤首先我們來看看如何制作跟蹤功能。這個跟蹤功能可以向用戶報告某個規(guī)則的調(diào)用、退出以及失敗幾個事件。 這里使用謂詞bugdisp來向用戶顯示跟蹤信息,它的參數(shù)是一個要顯示出來的列表。為了讓用戶可以選擇是否打開跟蹤功能,bugdisp首先檢查ruletrace是否為真。因此在我們的外殼程序中就又多了一個打開或者關閉跟蹤功能的命令。然后我們就可以把bugdisp放在任何想要顯示跟蹤信息的地方了。bugdisp(L) :- ruletrace,write_line(L),!.bugdisp(_).write_line() :- nl.write_line(H|T) :-write(H),tab(1),write_line(T).然后我們在外殼程序中加入trace(on)和trace(off)兩個命令。do( trace(X) ) :- set_trace(X), !.set_trace(off) :- ruletrace,retract( ruletrace ).set_trace(on) :-not ruletrace,asserta( ruletrace ). set_trace(_). 現(xiàn)在我們已經(jīng)編寫好了可以顯示跟蹤信息的謂詞了。下面我們就需要把bugdisp放入到適當?shù)胤剑屗@示出跟蹤信息。在上一章介紹的謂詞fg中很容易找到規(guī)則被調(diào)用和規(guī)則成功的地方。下面就是增加了跟蹤功能的fg謂詞。fg(Goal, CurCF) :- rule(N, lhs(IfList), rhs(Goal, CF),bugdisp(call rule, N),prove(N, IfList, Tally),bugdisp(exit rule, N),adjust(CF, Tally, NewCF),update(Goal, NewCF, CurCF, N),CurCF = 100, !. fg(Goal, CF) :- fact(Goal, CF). 當某個規(guī)則的目標滿足fg的目標的時候,這個規(guī)則就被調(diào)用,所以在rule后面加入call rule。當這個規(guī)則的前提都得到證實的時候這個規(guī)則就成功了,因此在prove后面加入exit rule。那么規(guī)則在什么時候失敗呢?在prove失敗的時候,規(guī)則就失敗了,因此我們加入一個處理prove失敗的子句:prove(N, IfList, Tally) :- prov(IfList, 100, Tally), !. prove(N, _, _) :-bugdisp(fail rule, N),fail.注意上面的第二個子句就是新加入的,當?shù)谝粋€子句失敗的時候,就調(diào)用這個子句,它首先顯示失敗信息,然后再失敗?;卮餳ow問題當用戶想知道系統(tǒng)是如何得出某個結(jié)論的時候,可以向系統(tǒng)提問how。實現(xiàn)這種方法有兩個途徑,一種當用戶詢問how的時候重新跟蹤系統(tǒng)的調(diào)用過程,另外一種則是把推理過程直接保存在工作空間中。我們使用后面這種方法。在我們的工作空間中原來的儲存信息格式如下:fact(AV,CF).它只保存了屬性信息和確信度信息,由于現(xiàn)在我們要回答用戶是如何得到某個結(jié)論的,因此我們要加入第三個參數(shù)RuleList,改進后的fact格式如下:fact(AV,CF,RuleList).RuleList用來保存推理出這個fact所使用的規(guī)則列表。這里的RuleList不是整個求解樹,而是是直接推導出這個fact的規(guī)則。fact是使用update謂詞更新的,因此需要改寫update。我們給update新加入一個參數(shù)用來告訴update是哪個規(guī)則引起的update,也就是說是哪個規(guī)則支持的需要更新的這個fact。update(Goal, NewCF, CF, RuleN) :- fact(Goal, OldCF, _), %如果已經(jīng)存在這個fact,combine(NewCF, OldCF, CF),retract( fact(Goal, OldCF, OldRules) ), %就取得原來的rulelist,asserta( fact(Goal, CF, RuleN | OldRules) ), !. %并且添加新的Rule進去。update(Goal, CF, CF, RuleN) :- %否則就是系統(tǒng)中不存在這個fact,asserta( fact(Goal, CF, RuleN) ). %就直接添加入工作空間。調(diào)用update的謂詞fg也要相應的有所改動:fg(Goal, CurCF) :- rule(N, lhs(IfList), rhs(Goal, CF),. update(Goal, NewCF, CurCF, N), %把規(guī)則名傳遞給update。. 下面再來編寫處理用戶的how命令,最簡單的辦法就是把用戶詢問的Goal對應的rulelist給列出來,不過如果我們能夠把規(guī)則的內(nèi)容也顯示出來的話,這樣就更加方便了。how(Goal) :-fact(Goal, CF, Rules),CF 20,pretty(Goal, PG),write_line(PG, was, derived, from, rules: |Rules),nl, list_rules(Rules),fail.how(_). how(not Goal) :- fact(Goal, CF, Rules),CF -20,pretty(not Goal, PG), write_line(PG, was, derived, from, rules: |Rules),nl, list_rules(Rules), fail. pretty謂詞用來把屬性值結(jié)構(gòu)轉(zhuǎn)化為更容易的閱讀的列表。pretty(av(A, yes), A) :- !. pretty(not av(A, yes), not, A) :- !.pretty(av(A, no), not, A) :- !.pretty(not av(A, V), not, A, is, V). pretty(av(A, V), A, is, V). list_rules用來顯示出規(guī)則的內(nèi)容。list_rules(). list_rules(R|X) :-list_rule(R), list_rules(X).list_rule(N) :-rule(N, lhs(Iflist), rhs(Goal, CF), write_line(rule , N),write_line(If),write_ifs(Iflist),write_line(Then),pretty(Goal, PG),write_line( , PG, CF), nl.write_ifs().write_ifs(H|T) :- pretty(H, HP), tab(5), write_line(HP),write_ifs(T). 我們還可以反過來使用pretty,也就是說把用戶輸入的列表,轉(zhuǎn)換為屬性值的結(jié)構(gòu),這樣的話,用戶就不需要知道系統(tǒng)內(nèi)部是如何表達知識的了。how :-write(Goal? ),read_line(X), nl,pretty(Goal, X),how(Goal).最后把how命令加入外殼程序的命令列表:do(how) :- how, !. 上面就是完整的how的編寫過程了。不過它只顯示出直接推導出某個規(guī)則,而這些規(guī)則又是基于其他的規(guī)則或者事實的,如何進一步的推理信息呢?有兩種方法:讓用戶使用how繼續(xù)詢問,讓how命令自動的顯示完整的證明樹。第一項功能已經(jīng)實現(xiàn),如何實現(xiàn)第二個功能呢?我們使用how_lhs把rulelist中的每個規(guī)則作為目標,遞歸的調(diào)用how。當某個目標的rulelist為空的時候,表示這個目標不是由規(guī)則得出的,而是用戶輸入的已知事實,這就是說完成了整個證明樹的搜索過程。list_rules().list_rules(R|X) :-list_rule(R),how_lhs(R), list_rules(X).how_lhs(N) :-rule(N, lhs(Iflist), _),!, how_ifs(Iflist). how_ifs().how_ifs(Goal|X) :- how(Goal), how_ifs(X). 在這里我們回答how提問有3種選擇:只顯示規(guī)則名,顯示規(guī)則的內(nèi)容,顯示完整的搜索樹。回答why提問當系統(tǒng)得出某個結(jié)論之后,用戶可以使用how向它詢問是如何得出這個結(jié)論的。而在系統(tǒng)的用戶的對話過程中,系統(tǒng)為了收集資料會向用戶詢問,這個時候如果用戶感到困惑的時候,可以詢問系統(tǒng)為什么問這個問題。為了回答why問題,我們需要跟蹤推理過程,也就是說要記錄下以前推理一些信息。在推理謂詞中增加一個保存這種信息的參數(shù),就可以很好的解決這個問題。在findgoal和prove中我們增加了一個Hist參數(shù)。findgoal(Goal, CurCF, Hist) :- fg(Goal, CurCF, Hist). fg(Goal, CurCF, Hist) :-.prove(N, IfList, Tally, Hist),.在prove謂詞中,在遞歸調(diào)用findgoal去尋找進一步的解的前面,先把現(xiàn)在所使用的規(guī)則記錄下來。prove(N, IfList, Tally, Hist) :- prov(IfList, 100, Tally, N|Hist), !.prove(N, _, _) :-bugdisp(fail rule, N), v(, Tally, Tally, Hist).prov(H|T, CurTal, Tally, Hist) :-findgoal(H, CF, Hist),min(CurTal, CF, Tal), Tal = 20, prov(T, Tal, Tally, Hist). 我們舉個例子說明一下,當系統(tǒng)需要證明a的時候,它發(fā)現(xiàn)要使用b,c。當它開始著手證明b之前,先把a記錄下來,這樣當用戶詢問系統(tǒng)你為什么要證明b的時候,它就可以告訴用戶:我是要證明a才來證明b的。假如證明b又需要d和e,在在證明d和e之前,先把b記錄下來,而d和e是需要向用戶收集的信息,用戶可能會詢問為什么要問我d和e這樣的問題,這時系統(tǒng)中的歷史列表應該是b,a,系統(tǒng)查詢這個列表就會告訴用戶,我需要證明b,因此詢問d和e,而用戶問為什么要證明b呢,系統(tǒng)就會回答是要證明a。顯然有了這個歷史列表,系統(tǒng)就知道自己為什么要獲得某個屬性的值了。 由于why命令是用戶在和系統(tǒng)的對話的中間詢問的,和原來how命令有些不同。原來的外殼命令help、exit、how等等,都不能在對話中間使用,下面我們就修改原來的程序,讓用戶可以打斷和系統(tǒng)的對話,來做其他的事情。用下面的get_user謂詞替代以前的向用戶詢問的謂詞,這個get_user謂詞允許在對話中間運行why,trace,help命令,當然加入其他的命令也是不困難的。 get_user(X, Hist) :-repeat, write(: ),read_line(X),process_ans(X, Hist).process_ans(why, Hist) :- nl, write_hist(Hist), !, cess_ans(trace, X, _) :- set_trace(X), !, cess_ans(help, _) :- help, !, cess_ans(X, _). % just return users answerwrite_hist() :- nl.write_hist(goal(X)|T) :- write_line(goal, X), !, write_hist(T).write_hist(N|T) :- list_rule(N), !,write_hist(T). 在回答why的時候,不僅僅顯示規(guī)則名,還可以顯示規(guī)則的內(nèi)容。在原始的推理引擎中加入解釋還記得第一章介紹的那個識別鳥類的專家系統(tǒng)么,由于這個專家系統(tǒng)使用的是prolog的推理引擎,所以無法加入解釋功能,為了加入解釋,我們必須使用prolog編寫一個prolog解釋器,這項工作很容易完成。當編寫完成了自己的推理引擎之后,就可以很方便的處理解釋了。推理引擎首先要能夠讀取規(guī)則,在prolog中,子句本身就是prolog的項。內(nèi)部謂詞clause可以讓我們存取規(guī)則。它的兩個參數(shù)分別與子句的頭和內(nèi)容匹配。事實的內(nèi)容就只有目標ture一個。在prolog的語法中,使用“,”隔開規(guī)則的每個子目標,其實在prolog中,規(guī)則的儲存方法和我們看上去的有很大的不同。下面我們舉個例子。對于規(guī)則a:-b,c,d.在prolog中的實際結(jié)構(gòu)是:-(a,&(b,&(c,d).可以看出,這和我們自己定義的數(shù)據(jù)結(jié)構(gòu)信息是相同的。例如我們可能會定義:father(a,b).在這里father就是謂詞,a和b就是參數(shù)。而在規(guī)則中,:-是謂詞,&也是謂詞。這一點在前面的prolog語言介紹中過。有了上面的知識,我們就很容易編寫出遞歸處理每個子目標的程序了。recurse(FirstGoal & RemainingGoals) :- process(FirstGoal),recurse(RemainingGoals).recurse(SingleGoal) :-process(SingleGoal). 這里使用&是為了讀者不把prolog中的兩種逗號搞混淆,一種逗號是用來把謂詞的參數(shù)分開的例如:father(a,b). 另外一種則是用來連接規(guī)則中的兩個子目標的, 表示并且的意思,這種逗號實際上是謂詞。有了可以存取prolog的事實和規(guī)則的方法以后,我們就可以很容易的編寫出處理這些事實和規(guī)則的謂詞了。prove(true) :- !. prove(Goal, Rest) :-clause(Goal, Body), %找到和目標匹配的子句prove(Body), %證明Body部分。prove(Rest). %證明上一層目標的剩余部分。prove(Goal) :-clause(Goal, Body), %找到和目標匹配的子句。prove(Body). %證明這個子句的Body部分。注意,prove謂詞正好模擬了prolog的解題過程。首先他找到頭部和第一個目標匹配某個子句。然后試圖證明這個子句的目標列表。上面的這個解釋器只能夠處理純prolog子句。對于prolog的內(nèi)部謂詞無能為力。因此最后我們加上一條:prove(X):-call(X).用來調(diào)用內(nèi)部謂詞。在我們的這個外殼程序中并不打算使用prolog的內(nèi)部謂詞,不過因為需要調(diào)用ask和menuask這樣的謂詞來和用戶對話,這些謂詞對于上面的解釋器就可以被認為是內(nèi)部謂詞了。和前面的Clam一樣,我們加入?yún)?shù)Hist來回答用戶的why提問。prove(true, _) :- !.prove(Goal, Rest), Hist) :-prov(Goal, (Goal, Rest),prove(Rest, Hist).prov(true, _) :- !.prov(menuask(X, Y, Z), Hist) :- menuask(X, Y, Z, Hist), !.prov(ask(X, Y), Hist) :- ask(X, Y, Hist), !. prov(Goal, Hist) :- clause(Goal, List), prove(List, Goal|Hist). 注意這里的歷史記錄保存的是目標列表,而不是規(guī)則名。下面來修改頂層的謂詞。solve :-abolish(known, 3), define(known, 3),prove(top_goal(X), ),write(The answer is ), write(X), nl.solve :- write(No answer found), nl.處理why提問的程序和clam類似。 get_user(X, Hist) :-repeat,read(X),process_ans(X, Hist), !.p
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 藥品營銷設備管理制度
- 藥品風險自查管理制度
- 藥店醫(yī)療設備管理制度
- 藥店消毒安全管理制度
- 菜園種菜人員管理制度
- 設備人員變更管理制度
- 設備器械使用管理制度
- 設備工藝參數(shù)管理制度
- 設備機構(gòu)維修管理制度
- 設備管理質(zhì)量管理制度
- 安霸A12-凌度A12行車記錄儀使用說明書
- GB/T 41735-2022綠色制造激光表面清洗技術規(guī)范
- MT/T 198-1996煤礦用液壓鑿巖機通用技術條件
- LY/T 1787-2016非結(jié)構(gòu)用集成材
- GB/T 3880.3-2012一般工業(yè)用鋁及鋁合金板、帶材第3部分:尺寸偏差
- GB/T 1503-2008鑄鋼軋輥
- GB/T 12729.1-2008香辛料和調(diào)味品名稱
- GB/T 1228-2006鋼結(jié)構(gòu)用高強度大六角頭螺栓
- GB 4404.3-2010糧食作物種子第3部分:蕎麥
- 【精品】高三開學勵志主題班會課件
- 套管培訓大綱課件
評論
0/150
提交評論