实验报告
——人工智能课程设计报告
智能1001班
傅宝林
0909101217
2013.6.18
1内容提要
此系统采用专家系统的规则库-推理机技术原理,以医学诊断为背景,旨在作出一个简单的辅助诊断专家系统。
系统的框架及界面采用的是Java语言,调用XML里保存的知识库和规则库。
此小型的专家系统以肺结核、哮喘、食管癌、骨折等疾病的诊断为例,展示了一个小型专家系统是如何构建的。
目录
1内容提要……………………………………………………………2
2目的和意义…………………………………………………………4
3系统的主要内容和功能……………………………………………5
4设计流程及描述……………………………………………………6
5课程设计体会………………………………………………………21
6参考文献……………………………………………………………22
2目的和意义
(1)加深理解专家系统的结构及开发过程。
(2)初步掌握知识获取的基本方法。
(3)掌握产生式规则知识表示方法及其编程实现方法。
(4)初步掌握知识库的组建方法。
3系统的主要内容和功能
系统主要以问答的形势询问病情症状,操作者只需要回答YES或NO。当一趟询问完成后,系统会基于以上询问得出的事实推理出最终的诊断结果。
功能见以下截图1、2.
图1 问询界面
图2 诊断结果界面
4设计流程及描述
1) 需求分析
本设计需要用高级语言编写框架及调用外部的规则库与知识库。方便起见,用java语言编写框架,用XML文件保存。
2) 知识获取与知识表示
知识获取通过医学临床专业的同学及医学诊断专业书籍,确保专家系统的专家性。
知识的表示采用的是xml语言,把事实与规则一条条保存。
3) 知识库的组建
知识库分事实库和规则库组建。疾病诊断因为有的病有交叉的症状,所以逻辑上,从症状到诊断的过程是对一颗二叉树的搜索,当问题回答的是YES时,就进行深度优先搜索,当回答NO时,就转到兄弟节点。对于无关的疾病,则回到根节点重新对下一颗子树进行搜索。得到一种疾病的确诊就是result,得到这个叶子节点前遍历过的节点组成了reasons.
4) 推理机制选择/编制
采用的是问题引导式推理。在规则库里写的其实不是真正的规则。真正的规则蕴含在问题及前提里。为了不让“专家”问无用的问题,每个问题都是以某个问题的答案为前提的。这样组成了内部的因果关系,所以真正的推理规则只与某一趟提问的最后一个问题的答案得出的事实有关。
5) 程序清单
package 专家系统_V2;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.LineBorder;
public class MainFrame extends JFrame{
/**
* 主界面类
* @param args
*/
public static void main(String[] args) {
MainFrame main = new MainFrame();
main.myShow();
}
private void myShow() {
exe = new Execution();
exe.init();
this.setTitle(exe.expert_name+"专家系统");
this.setSize(380, 250);
this.setDefaultCloseOperation(3);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
JPanel jp_center = new JPanel();
jp_center.setBackground(Color.white);
jp_center.setPreferredSize(new Dimension(380,250));
jp_center.setLayout(null);
jl = new JLabel();
jl.setText("请回答下列问题:");
jl.setFont(new Font(Font.DIALOG,Font.BOLD,25));
jl.setForeground(Color.blue);
jl.setBounds(10, 10, 200, 30);
jta=new JTextArea();
JScrollPane js=new JScrollPane(jta);
jta.setEditable(false);
jta.setBorder(new LineBorder(Color.black));
jta.setLineWrap(true);
jta.setFont(new Font(Font.DIALOG,Font.BOLD,20));
js.setBounds(20, 50, 330, 100);
jb1 = new JButton("YES");
jb1.setBounds(100, 170, 60, 30);
jb1.addActionListener(l);
jb2 = new JButton("NO");
jb2.setBounds(200, 170, 60, 30);
jb2.addActionListener(l);
jp_center.add(jl);
jp_center.add(js);
jp_center.add(jb1);
jp_center.add(jb2);
this.add(jp_center,BorderLayout.CENTER);
problem=this.initProblem();
this.setVisible(true);
}
private Problem initProblem(){
for(int i=0;i<exe.problems.size();i++){
Problem problem = exe.problems.get(i);
if(problem.getPremise()==null||problem.getPremise().isIstrue()){
if(problem.getPremise()!=null){
problem.getPremise().setIstrue(false);
}
jta.setText(problem.getContext());
exe.problems.remove(problem);
return problem;
}
}
jb1.setEnabled(false);
jb2.setEnabled(false);
return null;
}
private Execution exe;
private JButton jb1,jb2;
private JTextArea jta ;
private JLabel jl;
private Problem problem;
private Action l = new Action();
class Action implements ActionListener{
public void actionPerformed(ActionEvent e) {
if("YES".equals(e.getActionCommand())){
if(null!=problem.getAnswer_YES()){
problem.getAnswer_YES().setIstrue(true);
}
}else if("NO".equals(e.getActionCommand())){
System.out.println("aaa");
if(null!=problem.getAnswer_NO()){
System.out.println("aaa");
problem.getAnswer_NO().setIstrue(true);
}
}
exe.allReasoning();
problem=initProblem();
if(problem==null){
ArrayList<Fact> facts=exe.start();
String result="";
for(int i=0,n=1;i<facts.size();i++){
String des = facts.get(i).getDescribe();
if(!"null".equals(des)){
result+=i+1+"."+des+"\n";
n++;
}
}
jl.setText("推理结果如下:");
jta.setText(result);
jb1.setEnabled(false);
jb2.setEnabled(false);
return;
}
}
}
}
package 专家系统_V2;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class Execution {
public boolean init(){
try {
this.initXML(this.getPath());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
this.exit(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
} catch (NullPointerException e){
this.exit("找不到相应的xml文件,请检查xml文件名是否符合规范");
}
return false;
}
private void initXML(String file) throws ParserConfigurationException, SAXException, IOException{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc=null;
try{
doc = builder.parse(new File(file));
}catch(Exception e){
this.exit(e.getMessage());
}
Element root = doc.getDocumentElement(); // 获取根元素
expert_name=root.getAttribute("name"); //取得名字
//获取事实fact
NodeList allfacts = root.getElementsByTagName("facts");
NodeList onefacts = ((Element)allfacts.item(0)).getElementsByTagName("fact");
for(int i=0;i<onefacts.getLength();i++){
Element onefact = (Element)onefacts.item(i);
Fact fact = new Fact();
try{
fact.setName(onefact.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());
fact.setDescribe(onefact.getElementsByTagName("describe").item(0).getFirstChild().getNodeValue());
}catch(NullPointerException e){
this.exit("fact中缺少相应标签");
}
facts.put(fact.getName(), fact);
}
//获取推理reasoning
NodeList allreasonings = root.getElementsByTagName("reasonings");
NodeList onereasonings = ((Element)allreasonings.item(0)).getElementsByTagName("reasoning");
for(int i=0;i<onereasonings.getLength();i++){
Element onereasoning = (Element)onereasonings.item(i);
Reasoning reasoning = new Reasoning();
NodeList reasons = onereasoning.getElementsByTagName("reason");
if(reasons.getLength()==0){
this.exit("reasoning中不可以缺少reason标签");
}
for(int j=0;j<reasons.getLength();j++){
String name=reasons.item(j).getFirstChild().getNodeValue();
if(facts.get(name)!=null){
reasoning.getReason().add(facts.get(name));
}else{
this.exit("reason标签内容不正确,没有对应事实");
}
}
NodeList results = onereasoning.getElementsByTagName("result");
if(results.getLength()==0){
this.exit("reasoning中不可以缺少result标签");
}
for(int j=0;j<results.getLength();j++){
String name=results.item(j).getFirstChild().getNodeValue();
if(facts.get(name)!=null){
reasoning.getResult().add(facts.get(name));
}else{
this.exit("result标签内容不正确,没有对应事实");
}
}
reasonings.add(reasoning);
}
//获取问题problem
NodeList allproblems = root.getElementsByTagName("problems");
NodeList oneproblems = ((Element)allproblems.item(0)).getElementsByTagName("problem");
for(int i=0;i<oneproblems.getLength();i++){
Element oneproblem = (Element)oneproblems.item(i);
Problem problem = new Problem();
problem.setContext(oneproblem.getElementsByTagName("context").item(0).getFirstChild().getNodeValue());
try{problem.setPremise(facts.get(oneproblem.getElementsByTagName("premise").item(0).getFirstChild().getNodeValue()));
}catch(Exception e){}
try{problem.setAnswer_YES(facts.get(oneproblem.getElementsByTagName("answer_YES").item(0).getFirstChild().getNodeValue()));
}catch(Exception e){}
try{problem.setAnswer_NO(facts.get(oneproblem.getElementsByTagName("answer_NO").item(0).getFirstChild().getNodeValue()));
}catch(Exception e){}
problems.add(problem);
}
}
public void allReasoning(){
boolean proceed=true;
while(proceed){
proceed=false;
for(Reasoning reasoning:reasonings){
reasoning.startReasoning();
if(reasoning.startReasoning()){
proceed=true;
}
}
}
}
public ArrayList<Fact> start(){
// this.allReasoning();
ArrayList<Fact> reallyFacts = new ArrayList<Fact>();
for(Fact fact:facts.values()){
if(fact.isIstrue()){
reallyFacts.add(fact);
}
}
return reallyFacts;
}
private void exit(String passage){
JOptionPane.showMessageDialog(null, passage);
System.exit(0);
}
//查找当前路径
private String getPath(){
String myPath=null;
try {
myPath=URLDecoder.decode(Execution.class.getProtectionDomain().getCodeSource().getLocation().getFile(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String path=myPath.substring(1,myPath.lastIndexOf("/")+1)+"XML/配置文件.xml";
return path;
}
public HashMap<String,Fact> facts = new HashMap<String,Fact> ();
public ArrayList<Reasoning> reasonings = new ArrayList<Reasoning>();
public ArrayList<Problem> problems = new ArrayList<Problem>();
public String expert_name;
}
package 专家系统_V2;
/**
* 存放事实的类
* @author liguanyi
*
*/
public class Fact {
private String name; //名字
private boolean istrue=false; //是否成立
private String describe; //事实相应表述
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isIstrue() {
return istrue;
}
public void setIstrue(boolean istrue) {
this.istrue = istrue;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
}
package 专家系统_V2;
import java.util.ArrayList;
//表示推理
public class Reasoning {
private ArrayList<Fact> reason = new ArrayList<Fact>(); //前提事实
private ArrayList<Fact> result = new ArrayList<Fact>(); //结果事实
public ArrayList<Fact> getReason() {
return reason;
}
public void setReason(ArrayList<Fact> reason) {
this.reason = reason;
}
public ArrayList<Fact> getResult() {
return result;
}
public void setResult(ArrayList<Fact> result) {
this.result = result;
}
public boolean startReasoning(){
if(reason.size()==0){
return false;
}
for(Fact fact:reason){
if(!fact.isIstrue()){
return false;
}
}
for(Fact fact:reason){
fact.setIstrue(false);
}
for(Fact fact:result){
fact.setIstrue(true);
}
return true;
}
}
package 专家系统_V2;
public class Problem {
private Fact premise;
private String context;
private Fact answer_YES; //结果
private Fact answer_NO; //结果
public Fact getPremise() {
return premise;
}
public void setPremise(Fact premise) {
this.premise = premise;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public Fact getAnswer_YES() {
return answer_YES;
}
public void setAnswer_YES(Fact answerYES) {
answer_YES = answerYES;
}
public Fact getAnswer_NO() {
return answer_NO;
}
public void setAnswer_NO(Fact answerNO) {
answer_NO = answerNO;
}
}
以下是XML文件(保存事实库和规则库)中部分内容
<all name="疾病诊断">
<facts>
<fact>
<name>fact1</name>
<describe>咳嗽</describe>
</fact>
<fact>
<name>fact2</name>
<describe>胸痛</describe>
</fact>
<fact>
<name>fact3</name>
<describe>盗汗</describe>
</fact>
<fact>
<name>fact4</name>
<describe>食欲不振</describe>
</fact>
<fact>
<name>fact5</name>
<describe>消瘦</describe>
</fact>
<fact>
<name>fact6</name>
<describe>午后低热</describe>
</fact>
<fact>
<name>fact7</name>
<describe>肺结核</describe>
</fact>
<fact>
<name>fact9</name>
<describe>呼吸困难</describe>
</fact>
<fact>
<name>fact10</name>
<describe>胸腔积液</describe>
</fact>
<fact>
<name>fact11</name>
<describe>伴有哮鸣音的呼吸困难</describe>
</fact>
<fact>
<name>fact12</name>
<describe>发作性胸闷咳嗽</describe>
</fact>
<fact>
<name>fact13</name>
<describe>哮喘</describe>
</fact>
<fact>
<name>fact14</name>
<describe>不盗汗</describe>
</fact>
<fact>
<name>fact15</name>
<describe>不咳嗽</describe>
</fact>
<fact>
<name>fact16</name>
<describe>没有伴有哮鸣音的呼吸困难</describe>
</fact>
<fact>
<name>fact17</name>
<describe>上腹痛</describe>
</fact>
<fact>
<name>fact18</name>
<describe>节律性、周期性疼痛</describe>
</fact>
<fact>
<name>fact19</name>
<describe>灼疼</describe>
</fact>
<fact>
<name>fact20</name>
<describe>钝痛</describe>
</fact>
<fact>
<name>fact21</name>
<describe>消化性溃疡</describe>
</fact>
<fact>
<name>fact22</name>
<describe>上腹不痛</describe>
</fact>
<fact>
<name>fact23</name>
<describe>胸骨后不适</describe>
</fact>
<fact>
<name>fact24</name>
<describe>灼烧感</describe>
</facts>
<reasonings>
<reasoning>
<reason>fact6</reason>
<result>fact7</result>
</reasoning>
<reasoning>
<reason>fact9</reason>
<result>fact10</result>
</reasoning>
<reasoning>
<reason>fact12</reason>
<result>fact13</result>
</reasoning>
<reasoning>
<reason>fact20</reason>
<result>fact21</result>
</reasoning>
<reasoning>
<reason>fact27</reason>
<result>fact28</result>
</reasoning>
<reasoning>
<reason>fact32</reason>
<result>fact33</result>
</reasoning>
<reasoning>
<reason>fact43</reason>
<result>fact44</result>
</reasoning>
<reasoning>
<reason>fact47</reason>
<result>fact48</result>
</reasoning>
</reasonings>
<problems>
<problem>
<context>是否咳嗽?</context>
<answer_YES>fact1</answer_YES>
<answer_NO>fact15</answer_NO>
</problem>
<problem>
<premise>fact1</premise>
<context>是否胸痛?</context>
<answer_YES>fact2</answer_YES>
</problem>
<problem>
<premise>fact2</premise>
<context>是否盗汗?</context>
<answer_YES>fact3</answer_YES>
<answer_NO>fact14</answer_NO>
</problem>
<problem>
<premise>fact14</premise>
<context>是否呼吸困难?</context>
<answer_YES>fact9</answer_YES>
</problem>
<problem>
<premise>fact3</premise>
<context>食欲不振?</context>
<answer_YES>fact4</answer_YES>
</problem>
<problem>
<premise>fact4</premise>
<context>消瘦?</context>
<answer_YES>fact5</answer_YES>
</problem>
<problem>
<premise>fact5</premise>
<context>午后低热?</context>
<answer_YES>fact6</answer_YES>
</problem>
<problem>
<context>伴有哮鸣音的呼吸困难?</context>
<answer_YES>fact11</answer_YES>
</problem>
<problem>
<premise>fact11</premise>
<context>是否有发作性胸闷咳嗽?</context>
<answer_YES>fact12</answer_YES>
</problem>
<problem>
<premise>fact14</premise>
<context>呼吸困难?</context>
<answer_YES>fact9</answer_YES>
6) 程序测试与调试
遇到两个问题:1问多余的问题,通过给某些问题加前提解决了这个问题;2把一些得出的中间事实作为最终推理结果列了出来,解决方案:修改规则库,把实际蕴含在问题过程中的推理省掉,只保留最后的条件与结果。
5课程设计体会
本次课程设计加深了我对上学期所学的人工智能知识的认识与熟练运用。具体的:
(1)深入理解了专家系统的结构及开发过程。
(2)初步掌握了知识获取的基本方法。
(3)掌握了产生式规则知识表示方法及其编程实现方法。
(4)初步掌握了知识库的组建方法。
在小组中我负责知识的获取与知识库的组建。因为做的是疾病诊断专家系统,所以必须具备疾病诊断的专家知识,为此询问临床专业的同学以及查找相关的专业书籍。体会到了学科交叉的意义所在。现在的一些事情,单一的专业知识背景是无法完成的。
知识库的组建比较麻烦和枯燥,但是又必须细心,培养了我的一丝不苟的精神。
总而言之,本次课程设计收获颇丰。
6参考文献
[1] 蔡自兴, 徐光祐. 人工智能及其应用. 北京: 清华大学大学出版社,20##
[2] 严蔚敏. 数据结构:c语言版.北京:清华大学出版社,20##
[3] 蔡自兴. 高级专家系统:原理、设计及应用.北京:科学出版社,2005.
[4] 杜晖. 决策支持与专家系统.北京:电子工业出版社,2007.
[5] 陆再英,钟南山. 内科学. 北京:人民卫生出版社, 20##
农业专家系统实验报告课程农业专家系统行政班级09农信姓名王雪学号0908074115一实验目的加深对知识表示方法的理解与认识掌握知…
武夷学院实验报告数学与计算机系专家系统设计一目的要求进入实验机房加深学生了解智能专家系统的概念如自动分类诊断和预测等系统使学生掌握…
学生实验报告科目名称人工智能实验项目名称专家系统专业名称计算机科学与技术班学级计算机一班号20xx24020xx5学生姓名高修教师…
鸡病诊断专家系统实验报告一实验目的1加深理解专家系统的结构原理与实际应用2初步掌握知识获取的基本方法3掌握产生式规则知识表示方法及…
天津农学院计算机科学与信息工程系农业专家系统教学实习报告实习名称农业专家系统专业软件工程班级20xx级1班学号1234567123…
会计信息系统课程实验指导书(供会计专业本科和会计双学位学生用)学号:姓名:XXX班级:会计S10-03班编写单位:河南理工大学经济…
农业专家系统实验报告课程农业专家系统行政班级09农信姓名王雪学号0908074115一实验目的加深对知识表示方法的理解与认识掌握知…
人工智能导论上机实验指导书基于人工智能的状态空间搜索策略研究八数码问题求解一实验软件TC20或VC60编程语言或其它编程语言二实验…