用Python實現一個動物識別專家系統--人工智能

  • 考察 產生式系統
  • 求點贊,給作者一點分享的鼓勵
  • 代碼沒寫GUI,因爲不喜歡這玩意,直接在終端中進行人機交互。使用代碼之前,請根據自身情況對字符編碼、文件路徑進行修改
  • 代碼寫的很爛,以後有能力了再把算法加進去優化代碼吧

產生式系統

  • 規則庫:用於描述相應領域內知識的產生式系統
  • 綜合數據庫,又稱爲事實庫、上下文、黑板:一個用於存放問題求解過程中各種當前信息的數據結構
  • 控制系統,又稱推理機構:由一組程序組成,負責整個產生式系統的運行,實現對問題的求解

控制系統:

  1. 從規則庫中選擇前提與綜合數據庫中的已知事實進行匹配
  2. 匹配成功的規則可能不止一條,進行衝突消解 (出題者對題目進行過設置,沒有出現衝突)
  3. 執行某一規則時,如果其右部是一個或多個結論,則把這些結論加入到綜合數據庫中;如果其右部是一個或多個操作,則執行這些操作
  4. 對不確定性知識,在執行每一條規則時還要按一定算法計算結論的不確定性 (由於只是考察產生式系統,出題者對題目進行過簡化,題目中沒有涉及這部分內容)
  5. 檢查綜合數據庫中是否包含了最終結論,決定是否停止系統的運行

第一問

先根據題圖,創建規則庫(使用了一個文本文件)

if 有毛髮 then 哺乳動物
if 有乳 then 哺乳動物
if 吃肉 then 食肉動物
if 有犬齒 and 有爪 and 眼向前方 then 食肉動物
if 哺乳動物 and 有蹄 then 有蹄類
if 哺乳動物 and 反芻動物 then 有蹄類
if 哺乳動物 and 食肉動物 and 黃褐色 and 暗斑點 then 豹子
if 哺乳動物 and 食肉動物 and 黃褐色 and 黑條紋 then 老虎
if 有蹄類 and 長脖子 and 長腿 and 暗斑點 then 長頸鹿 
if 有蹄類 and 黑條紋 then 斑馬

代碼:

rules = {} # 以字典形式存儲規則


"""
讀取規則庫文件中規則,並存放在rules字典中
    - 字典的鍵:前提
    - 字典的值:結論 
"""
def readRules(filePath):
    global rules
    for line in open(filePath, mode = 'r', encoding = 'utf-8'):
        line = line.replace('if', '').strip()
        temp = line.split(' then ')
        premise = temp[0]
        conclusion = temp[1]
        rules[premise] = conclusion

"""
2. 推理機用這些事實(即:facts變量),依次與知識庫中的規則的前提匹配
    - 注意:匹配成功的規則可能不止一條,進行衝突消解(本代碼沒有這個功能)
    - 代碼很簡單,沒有對綜合數據庫進行設置
3. 若某規則的前提全被事實滿足,則規則可以得到運用
4. 規則的結論部分作爲新的事實存儲
5. 用更新過的事實再與其它規則的前提匹配,直到不再有可匹配的規則爲止
"""
def matchRules(facts): 
    print()
    # 循環匹配
    isEnd = False
    def loop():
        global rules
        nonlocal facts, isEnd
        rules_copy = rules.copy()
        i = 0
        for premise in rules:
            flag = True
            # print(premise+ ':' + rules[premise])
            pre = premise.split(' and ')
            for p in pre:
                if p in facts:
                    pass
                else:
                    flag = False
            if(flag):
                print('該動物:' + premise + ' -> ' + rules[premise])
                for p in pre:
                    facts = facts.replace(p, ' ')
                facts = facts + rules[premise]
                rules_copy.pop(premise)
            else:
                i += 1
        if i == len(rules):
            isEnd = True
        rules = rules_copy

    # 是否推導出最終結論     
    while(not isEnd):
        loop()

    
"""
1. 用戶通過人機界面輸入一批事實
"""
def ui():
    print('----')
    print('--------動物識別系統--------')
    print('----')
    print('注意!請按照規則庫中的前提來闡述事實', end='\n\n')
    facts = input('請輸入事實:')
    matchRules(facts)


def main():
    filePath = r'動物識別系統/rules.txt'
    readRules(filePath)
    ui()
    


if __name__ == '__main__':
    main()

人機交互示例:

----
--------動物識別系統--------
----
注意!請按照規則庫中的前提來闡述事實

請輸入事實:該動物有暗斑點、長脖子、長腿、有乳、有蹄。

該動物:有乳 -> 哺乳動物
該動物:哺乳動物 and 有蹄 -> 有蹄類
該動物:有蹄類 and 長脖子 and 長腿 and 暗斑點 -> 長頸鹿

第二問

把規則庫換成以下規則,在看看系統的執行情況:

  1. 有毛髮的動物是哺乳類;
  2. 有奶的動物是哺乳類;
  3. 有羽毛的動物是鳥類;
  4. 若動物會飛且生蛋,則它是鳥類;
  5. 吃肉的哺乳類稱爲食肉動物;
  6. 犬牙利爪,眼睛向前的是食肉類;
  7. 反芻食物的哺乳類是有蹄類;
  8. 有蹄的哺乳類是有蹄類;
  9. 黃褐色有黑色條紋的食肉類是老虎;
  10. 黃褐色有暗斑點的食肉類是金錢豹;
  11. 長腿長脖有黃褐色暗斑點的有蹄類是長頸鹿;
  12. 有黑白條紋的有蹄類是斑馬;
  13. 不會飛腿長脖黑白色的鳥是鴕鳥;
  14. 不會飛善游泳黑白色的鳥是企鵝;
  15. 善飛的鳥是信天翁.

把規則庫重新寫一遍就可以了,或者你再新建一個文本文件

if 有毛髮 then 哺乳類
if 有奶 then 哺乳類
if 有羽毛 then 鳥類
if 會飛 and 生蛋 then 鳥類
if 吃肉 and 哺乳類 then 食肉動物
if 犬牙 and 利爪 and 眼睛向前 then 食肉類
if 哺乳類 and 反芻食物 then 有蹄類
if 哺乳類 and 有蹄 then 有蹄類
if 食肉類 and 黃褐色 and 黑色條紋 then 老虎
if 食肉類 and 黃褐色 and 暗斑點 then 金錢豹
if 有蹄類 and 長脖 and 長腿 and 黃褐色 and 暗斑點 then 長頸鹿 
if 有蹄類 and 黑白條紋 then 斑馬
if 鳥 and 不會飛 and 長脖子 and 長腿 and 黑白色 then 鴕鳥
if 鳥 and 不會飛 and 善游泳 and 黑白色 then 企鵝
if 鳥 and 善飛 then 信天翁
  • 最後吐槽一句,產生式系統是真的傻,如果不對輸入進行模糊判斷,嘁嘁嘁(我沒有這樣搞,因爲搞不好,以後有能力了再加上)

  • 所以呢,我這垃圾代碼,執行時輸入一系列事實之前需要先看看規則庫的的前提;不然,你在事實中輸入’有奶‘,而規則庫中是’有乳‘,俺這代碼可不認你的’有奶‘

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章