实现了一下动物识别系统---基于专家系统

2019.2.26

主要功能:
1. 功能完善(知识库、综合数据库、推理机)
2. 正向推理、反向推理
3. 知识库可维护(添加、删除、修改)
4. 中间结果可视化(推理中间结果可见)

这次编写代码的时候,思路很清晰,从之前的节奏中跳了出来,先def main() ,之后在main() 中定义各个模块,之后再思考各个模块怎样实现,这样编写代码看起来很合理。
当我编写一个函数的时候,特别是算法部分,如 def Topo() 最好是先想一下自己要怎么做才能完成,而不是直接上手,要想好怎么做,之后再动手

没有UI界面。。因为只是随手做的,而且也没有学PyQt5,只是为了另一件事拿这个熟悉一下专家系统。
后期会更新的, 吧??

  1. 主要说一下问题:
    我觉得主要是难在了新增一条规则时候,需要进行规则的整合管理。
    开始的时候,使用了拓扑排序,但是发现不行,因为同一个结论,如下面rules.txt中的哺乳动物,可以由两种方式推导出来,这样的结构其实不合适用拓扑排序(也可能是我理解不够)

    对于下面这一个规则,就是很简单的 当满足哺乳动物 和 反刍动物的时候,那么就是有蹄类动物

    哺乳动物 反刍动物->有蹄类动物
    
    12265479-963548c2355a9ee5.png
    image.png

    而对于这样两条规则:

    有毛发->哺乳动物
    有奶-> 哺乳动物
    
    12265479-3136122fe0216ed5.png
    image.png

    那么他们的逻辑图应该怎么画呢?这就很迷惑。。
    这样导致了他们的图我不知道怎么画,更不用DAG谈拓扑化了。

    我所使用的方法,则很简单,就是先遍历一遍所有规则,找出其中的baseAttr(也就是基础属性,基础属性意味着他不是被推导出来的,而是先天的属性,如:有毛发);
    然后,不断第二次规则库,当规则满足他的前置条件都在base中,那么就加入到拓扑规则序列中,然后将他的结论也加入到baseAttr中。不断遍历规则库,知道所有的规则都被加入到了拓扑序列中。
    这样就能实现规则的增加了。

  2. 代码

#使用专家系统来构建 动物识别系统

#使用:加入一条规则S,当规则库中已有的node中包含了S的前置条件,才加入到规则库中,否则先跳过
def TopulogyRules(rules):
    basicAttr = set()   #基础属性
    midAttr = set()     #这些中是被推倒出来的结论
    for rule in rules:
        for attr in rule:
            basicAttr.add(attr)
        midAttr.add(rule[-1])
    basicAttr = basicAttr - midAttr     #全部属性 - 中间属性 = 基础属性
    
    rs = rules.copy()
    visited = []
    for i in range(len(rules)):
        visited.append(0)
    newRules = []
    while(len(rs) != 0): 
        for rule in rules:
            if rule in rs:
                s = set(rule[:-1])
                if s <= basicAttr:
                    newRules.append(rule)
                    rs.remove(rule)
                    visited[i] = 1
                    basicAttr.add(rule[-1])
    print(newRules)
    #不断新建base环境,不断向前搜索,不断添加
    return rules

###读入rules.txt,然后拓扑化 rules,返回一个拓扑化之后的 rules
def getRules():
    animalKinds = []
    rules = []
    f = open("./AnimalRecongnizeSystem/rules.txt", 'r', encoding='UTF-8')
    #f = open("./AnimalRecongnizeSystem/data.txt", 'r').read()
    for line in f:
        #print(line, end='')
        line = line.replace("\n","")
        ls = line.split(" ")
        rules.append(ls)
    animalKinds = rules[-1]
    rules.pop()
    rules = TopulogyRules(rules)
    f.close()
    return rules,animalKinds

def getAnimalInfo():
    info = input("请输入动物的特征(空格为分隔符): ")
    basicInfo = info.split(' ')
    return basicInfo

def Inference(rules, basicInfo, animalKinds):
    animal = "茄子"
    for rule in rules:
        set1 = set(rule[:-1])
        set2 = set(basicInfo)
        if set1 <= set2:
            set2.add(rule[-1])
            basicInfo = list(set2)
            if rule[-1] in animalKinds:
                animal = rule[-1]
                break
    print(basicInfo)
    return animal

def showRules():
    pass

def main():
    rules, animalKinds = getRules()
    # print("知识库中的全部规则为:{}".format(rules))
    # print("知识库能推导出的动物种类为:{}".format(animalKinds))
    basicInfo = getAnimalInfo()
    animal = Inference(rules, basicInfo, animalKinds)
    print("你描述的动物是:{}".format(animal))
main()

# 测试用例:身上有暗斑点 黄褐色 长脖子 有长腿 有奶 有蹄
  1. rules.txt
有毛发 哺乳动物
有奶 哺乳动物
有羽毛 鸟
会飞 会下蛋 鸟
吃肉 食肉动物
有犬齿 有爪 眼盯前方 食肉动物
哺乳动物 有蹄 有蹄类动物
哺乳动物 反刍动物 有蹄类动物
哺乳动物 食肉动物 黄褐色 身上有暗斑点 金钱豹
哺乳动物 食肉动物 黄褐色 身上有黑色条纹 虎
有蹄类动物 长脖子 有长腿 身上有暗斑点 长颈鹿
有蹄类动物 身上有黑色条纹 斑马
鸟 长脖子 有长腿 不会飞 有黑白二色 鸵鸟
鸟 会游泳 不会飞 有黑白二色 企鹅
鸟 善飞 信天翁
金钱豹 虎 长颈鹿 斑马 鸵鸟 企鹅 信天翁

猜你喜欢

转载自blog.csdn.net/weixin_33762130/article/details/88210754