人工智能实验报告
题 目:基于web动物识别系统
院 系:计算机科学与技术系
专 业:计算机科学与技术专业
学 号:071221139
学生姓名:张莲舟
日期:20##-4-21
一、 实验题目:
基于web的动物识别系统
二、 实验目的
理解和掌握产生式知识表示方法及产生式系统的基本过程,能够利用Web编程技术建立一个基于产生式知识表示的简单的智能系统。
三、 实验要求
(1) 以本书第2章动物识别产生式系统的规则为知识库(可增加规则),采用正向推理或逆向推理方式。
(2) 以选定的数据库管理系统建立知识库,用选定的网络编程语言按B/S模式开发一个具有解释功能的智能系统。
(3) 提交完整的软件系统和相关文档,包括源程序和可执行程序。
四、 实验环境
(1) 硬件环境:网络环境中的微型计算机。
(2) 软件环境:WindowsXP及以上操作系统,本实验采用ASP.net的框架结构,编程语言为C#,编程环境为Microsoft Visual Studio2008。采用的数据库管理软件为Microsoft Office Access2007。
五、 实验原理
1 产生式表示法:
1.1事实
1.1.1事实的定义
事实是断言一个语言变量的值或断言多个语言变量之间关系的陈述句。语言变量的值或语言变量之间的关系可以是数字、词等。
例如:“雪是白的”,其中“雪”是语言变量,“白的”是语言变量的值
1.1.2事实的表示
l 确定性知识,事实可用如下三元组表示:
(对象,属性,值)或(关系,对象1,对象2)
其中,对象就是语言变量。例如:
(snow, color, white) 或(雪,颜色,白)
(love, Wang Feng, country) 或(热爱,王峰,祖国)
l 非确定性知识,事实可用如下四元组表示:
(对象,属性,值,可信度因子)
其中,“可信度因子”是指该事实为真的相信程度。可用[0,1]之间的一个实数来表示。
1.2规则的表示
规则描述的是事物间的因果关系。规则的产生式表示形式常称之为产生式规则,简称产生式或规则。其基本形式为:P->Q或者IF P THEN Q。
其中,P是产生式的前提,也称为前件,它给出了该产生式可否使用的先决条件,由事实的逻辑组合来构成。Q是一组结论或操作,也称为产生式的后件,它指出了当前提P满足时,应该推出的结论或应该执行的操作。
产生式的含义为:如果前提P满足,则可以推出结论Q或执行Q的操作。
2 产生式系统的基本结构:
一个产生式系统的基本结构包括综合数据库、规则库和控制系统这三个主要部分。控制系统用来控制整个产生式系统的运行,实现对问题的求解。
2.1综合数据库
综合数据库DB(data base)也称为事实库,是一个用来存放与求解问题有关的各种当前信息的数据结构。当某条规则的前提可综合数据库中的已知事实相匹配时,该规则将被激活,并放入综合数据库成为后面推理的已知事实。
2.2规则库
规则库RB(rule base)是一个用来存放与求解问题有关的所有规则的集合,也称为知识库KB(knowledge base)。它包含了将问题从初始状态转换成目标状态所需的所有变换规则。规则库是产生式系统进行问题求解的基础。
2.3控制系统
控制系统(control system)也称为推理机,其主要工作如下:
A. 按一定的策略从规则库中选择规则与综合数据库中的已知事实进行匹配。
B. 当匹配成功的规则多余一条时,按照某种策略选择一条执行。
C. 对于要执行的规则,如果该规则的后件不是问题的目标,则若其为结论,将其加入综合数据库中,若其为操作,则执行这些操作。
D. 若规则的后件满足问题的结束条件,则停止推理。
E. 在求解过程中,记住应用过的规则序列,以便最终可以给出解路径。
3 产生式系统的类型:
这里介绍按推理方向分类:
3.1正向推理产生式系统
也称数据驱动方式,它是从初始状态出发,朝着目标状态前进,正向使用规则的一种推理方法。所谓正向使用规则,是指以问题的初始状态作为初始综合数据库,仅当综合数据库中的事实满足某条规则的前提时,该规则才被使用。
优点:简单明了,且能求出所有解
缺点:执行效率较低,原因是使用规则具有一定的盲目性。
3.2逆向推理产生式系统
也称目标驱动方式,它是从目标(作为假设)状态出发,朝着初始状态前进,反向使用规则的一种推理方法。所谓逆向使用规则,是指以问题的目标状态作为初始综合数据库,仅当综合数据库中的事实满足某条规则的后件时,该规则才被使用。
优点:不使用与问题无关的规则。因此,对那些目标明确的问题,使用反向推理方式是一种最佳选择。
3.3双向推理产生式系统
双向推理是把正向推理和反向推理结合起来使用的一种推理方式。它需要把问题的初始状态和目标状态合并到一起构成综合数据库。
六、 实验正文
1. 引言
正文部分将分为软件需求分析、概要设计、详细设计、编码和测试五个部分来阐述本软件。
在需求分析将具体阐述为什么要设计该软件;概要设计将介绍软件的基本设计,包括基本处理流程、系统的组织结构、模块化分、功能分配、接口设计、数据结构设计等;详细设计将在概要设计的基础上进一步描述具体模块涉及到的主要算法、类的层次结构及调用关系以及对每个模块的详细考虑;编码阶段将阐述对目标系统的功能、性能、接口、界面方面的要求;测试阶段将给出一些用以测试的破坏性输入用以判断该系统的鲁棒性如何。
2. 软件需求分析
2.1综合描述
2.1.1产品的状况
在现代的应用中,动物识别之类的人工智能软件已经很多,本产品为测试人工智能产生式系统的基本实现方法及流程而编写,一个试验型软件。
2.1.2产品的功能
本产品是基于B/S架构的动物识别系统,采用正向推导的产生是系统,用户可以通过访问该网站,给出自己的查询条件,以查找到符合条件的动物,并查看该动物的照片。若对结果不满意,也可以将自己的查询添加为规则,此时需要给出动物的名称。
2.1.3用户类和特性
本软件的用户没有特定人群,只要有一定的上网条件和熟悉Windows操作系统并懂得如何使用网页浏览器的用户均可使用。
2.1.4运行环境
2.1.4.1硬件环境:微型计算机。
2.1.4.2操作系统和版本:WindowsXP及以上版本。
2.1.4.3支撑环境:ASP.net架构,Microsoft Office Access2007,IE浏览器7.0及以上
2.1.5设计和实现上的限制
由于本软件属于测试型软件,只能实现很少的动物的识别,因此对数据库的大数据量的支持要求不高,故采用Access。
2.2外部接口需求
2.2.1用户界面
将采用标准的图形用户界面,并做到与动物识别这个主题的切合,给人不要太过死板,以图为多,制作出清新宜人的风格。
将采用到的软件组件:
ü 单选框
ü 普通按钮
ü 文本框
ü 标签
ü 图片空间
文字、图片、按钮均为居中对齐,单选框为居左对齐。
2.2.2通信接口
Web浏览器
2.3系统功能需求
2.3.1输入/输出数据
数据名称:choice
数据含义:用户对每一个属性的选择(是/否/不清楚)
数据类型:bool逻辑型
数据格式:ture/false(表示选了还是没选)
数据约束:由于空间本身的限制,用户只能输入逻辑值true/false
2.4其它非功能需求
2.4.1性能需求
2.4.1.1响应时间:需要在1秒~2秒之内给出结果
2.4.1.2容量需求:若要改造成一个很使用的软件,必须存储很多种动物的图片,磁盘空间要足够大,至少10G。
2.4.2安全性需求
不能添加一些侵犯他人、侵犯中国的规则,即人名和国家名不可以作为规则输入。
2.5词汇表
AI:Artificial Intelligence人工智能
DB:data base 综合数据库
RB:rule base 规则库
Control system:控制系统
2.6数据定义
2.7分析模型
2.7.1程序流程图
3. 软件概要设计
3.1系统功能设计
3.2数据库设计
数据库一共有两张表,一张为事实表animalTruth,一张为规则表animalRule。详细设计如下:
3.2.1 AnimalTruth表:
其中把所有规则的前件和后件都作为事实添加进来,还有其他一些已知的事实,如动物的属性。Truth为具体的事实名,因此为文本,truthAttribute用来标记该事实的类型,为1表示为具体的动物,为2为动物种类属于中间结果,为3表示动物的属性,只能作为前件使用。
具体如下图所示:(下图为示意图,只是数据库的一部分)
3.2.2 animalRule表
其中ruleIndex表示第几条规则,ruleCon表示该条规则的后件在animalTruth表中的ID,rulePre表示该条规则的某一个前件在animalTruth表中的ID。也就是说一条规则肯能占有多行。
具体如下图所示:(下图为示意图,只是数据库的一部分)
4. 软件详细设计
4.1支撑环境
4.1.1数据库管理系统
ü 产品名称以及发行厂商:
Microsoft Office Access2007
Microsoft Company
ü 版本号
2007版
ü 语言或代码级
必须支持中文字符集
ü 安装位置
请将其安装在D:\animal\下。
4.2 部件详细设计
4.2.1模块1.预处理模块
部件名称:预处理模块(PrePrecessing);
部件调用者:主界面用户界面模块;
部件被调用者:查询模块;
部件入口参数:动物的1~19个属性每个属性三个选框(rbyes、rbno、rbuknown)的选择情况(true/false);
部件出口参数:int choice[41];
流程描述:当点击“开始查询”按钮,检查一共19*3=57个选框的选择情况,choice的第0~17个元素对应rbyes1~rbyes18,第18~35个元素对应rbno1~rbno18,若rbyes19=true,则choice第36个元素对应rbyes19。Choice中的值并不是bool值,而是若选择为true,则为该属性对应在数据库中的ID号,若选择为false,则为0。
性能要求:点击后里可执行,但是灵活度不够。
4.2.2模块2.查询模块
部件名称:查询模块(Searching);
部件调用者:预处理模块;
部件入口参数:int choice[41];
部件出口参数:int resultID;int conNum;string analysis;
流程描述:开始查询,首先通过函数getRuleNum()获取数据库中规则的总数,然后从第一条到最后一条规则逐条读出,首先判断当前规则的后件是否在choice中,若是则读取下一条,若否继续判断当前规则的前件是否全部在choice[]中,若是,analysis加上该规则,判断后件是否属性为1,若是则将其设为结果,若不是则将后件加入choice[]的后5个空位中。然后继续分析下一条规则。这里的choice是放在一个栈stack里面传输到要跳转的页面的。
性能要求:主要是数据库的查询操作,可能会花费一定的时间。
4.2.3模块3.加规则模块
部件名称:加规则模块(AddRule);
部件入口参数:int choice[41];动物名称;
流程描述:首先判断有没有输入动物的名称,若没有提示输入。先在animalTruth中插入输入的动物的名称,truthAttribute为1。然后查询该条记录的ID,作为插入过则的后件ruleCon。然后得到现有一共多少条规则,加1作为要插入的ruleIndex,将stack中的值一一取出,作为rulePre,插入到animalRule中去,提示插入成功。
性能要求:主要是数据库的插入操作,因为要插入的行数不多,因此速度很快。
5. 软件编码
5.1数据库配置:
首先,在App_Data文件夹下加入数据库文件animal.accdb,然后在Web.config文件中的appSeting中加入以下代码:
<appSettings>
<add key="ConString" value="Provider=Microsoft.ACE.OLEDB.12.0;Data Source="/>
<add key="dbPath" value="~/App_Data/animal.accdb"/>
</appSettings>
在代码中取出连接数据库的字符串:(在HelpUtility.cs文件中)
public static string GetConnectionString()
{
string conString = "";
if (ConfigurationManager.ConnectionStrings.Count > 0)
{
conString = System.Configuration.ConfigurationManager.AppSettings["ConString"].ToString()+System.Web.HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["dbPath"].ToString());
}
return conString;//EncryptUtil.DESEncrypt.Decrypt(conString);
}
5.1查询主要用到的函数
/// <summary>
/// 获取一共有多少条已知规则
/// </summary>
/// <returns></returns>
int getRuleNum()
{
DataTable dt = new DataTable();
string sql = "select * from animalRule";
try
{
using (DBFunction dbfun = new DBFunction(DBTransactionType.NonTran))
{
dt = dbfun.ExecForQuery(sql);
}
}
catch (Exception ex)
{
throw new AnException("获取规则表失败",ex);
}
int sum=dt.Rows.Count;
return Convert.ToInt32(dt.Rows[sum-1]["ruleIndex"].ToString());
}
/// <summary>
/// 获取第ruleIndex条规则
/// </summary>
/// <param name="ruleIndex"></param>
/// <returns></returns>
DataTable getRule(int ruleIndex)
{
DataTable dt = new DataTable();
string sql = string.Format("select * from animalRule where ruleIndex={0}", ruleIndex);
try
{
using (DBFunction dbfun = new DBFunction(DBTransactionType.NonTran))
{
dt = dbfun.ExecForQuery(sql);
}
}
catch (Exception ex)
{
throw new AnException("获取单条规则失败", ex);
}
return dt;
}
/// <summary>
/// 判断中间结果是否已经在choice中
/// </summary>
/// <param name="ruleCon"></param>
/// <returns></returns>
bool midIn(int ruleCon)
{
for (int i = 36; i < 41; i++)
{
if (choice[i] == ruleCon)
return true;
}
return false;
}
/// <summary>
/// 判断该前键是否在choice里
/// </summary>
/// <param name="rulePre"></param>
/// <returns></returns>
bool preIn(int rulePre)
{
for (int i = 0; i < 41; i++)
{
if (choice[i] == rulePre)
return true;
}
return false;
}
/// <summary>
/// 去事实表中找到关于结果的信息
/// </summary>
/// <param name="ruleCon"></param>
/// <returns></returns>
DataTable getResult(int ruleCon)
{
DataTable dt = new DataTable();
string sql = string.Format("select * from animalTruth where truthID={0}", ruleCon);
try
{
using (DBFunction dbfun = new DBFunction(DBTransactionType.NonTran))
{
dt = dbfun.ExecForQuery(sql);
}
}
catch (Exception ex)
{
throw new AnException("获取结果失败", ex);
}
return dt;
}
5.2插入新规则所用到的函数
/// <summary>
/// 获取刚插入的动物的ID号
/// </summary>
/// <returns></returns>
int getAnimalID(string animal)
{
DataTable dt = new DataTable();
string sql = string.Format("select * from animalTruth where truth='{0}'", animal);
try
{
using (DBFunction dbfun = new DBFunction(DBTransactionType.NonTran))
{
dt = dbfun.ExecForQuery(sql);
}
}
catch (Exception ex)
{
throw new AnException("获取规则表失败", ex);
}
return Convert.ToInt32(dt.Rows[0]["truthID"].ToString());
}
/// <summary>
/// 插入新添加的动物
/// </summary>
/// <param name="choice"></param>
void addAnimal(string animal)
{
string sql = string.Format("insert into animalTruth (truth,truthAttribute) values('{0}',1)", animal);
try
{
using (DBFunction dbfun = new DBFunction(DBTransactionType.NonTran))
{
dbfun.ExecForNonQuery(sql);
}
}
catch (Exception ex)
{
throw new AnException("插入动物失败", ex);
}
}
/// <summary>
/// 插入新规则
/// </summary>
/// <param name="index"></param>
/// <param name="con"></param>
/// <param name="choice"></param>
void addRule(int index, int con, int choice)
{
string sql = string.Format("insert into animalRule (ruleIndex,ruleCon,rulePre) values({0},{1},{2})", index, con, choice);
try
{
using (DBFunction dbfun = new DBFunction(DBTransactionType.NonTran))
{
dbfun.ExecForNonQuery(sql);
}
}
catch (Exception ex)
{
throw new AnException("插入规则失败", ex);
}
}
5.3第三方代码(An.core,An.DataAccess)
主要用到的是DBfunction.cs(用于连接数据库的实际操作)
using System;
using System.Collections.Generic;
using System.Text;
using An.Core;
using System.Data;
using System.Data.OleDb;
namespace An.DataAccess
{
/// <summary>
/// 数据库事务的类型
/// </summary>
public enum DBTransactionType
{
/// <summary>
/// 使用数据库事务
/// </summary>
WithTran,
/// <summary>
/// 不使用数据库事务
/// </summary>
NonTran
}
/// <summary>
/// 执行数据查询和非查询操作
/// </summary>
public class DBFunction : IDisposable
{
OleDbConnection _con = null;
OleDbTransaction _tran = null;
OleDbCommand _cmd = null;
private bool _hasError = false;
public DBFunction(DBTransactionType tranType)
{
string conString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= D:\animal\animal.accdb";
_con = new OleDbConnection(conString);
try
{
_con.Open();
_cmd = _con.CreateCommand();
if (tranType == DBTransactionType.WithTran)
{
//使用连接对象的BeginTransaction()方法,开启一个事务
_tran = _con.BeginTransaction();
//设置命令对象的事务范围
_cmd.Transaction = _tran;
}
}
catch (Exception ex)
{
ApplicationLog.WriteError(ex.Message);
_hasError = true;
throw ex;
}
}
/// <summary>
/// 执行查询
/// </summary>
/// <param name="OleDbQueryString">用于查询的OleDb语句</param>
/// <returns>返回DataTable</returns>
public DataTable ExecForQuery(string OleDbQueryString)
{
try
{
DataTable dt = new DataTable();
_cmd.CommandText = OleDbQueryString;
using (OleDbDataAdapter dapt = new OleDbDataAdapter(_cmd))
{
dapt.Fill(dt);
}
return dt;
}
catch (Exception ex)
{
ApplicationLog.WriteError(ex.Message);
_hasError = true;
throw ex;
}
}
/// <summary>
/// 执行查询,返回一个标量值,默认为object类型,需要根据使用情况手动转换
/// </summary>
/// <param name="OleDbScalarString"></param>
/// <returns>返回object类型的标量值</returns>
public object ExecForScalar(string OleDbScalarString)
{
try
{
_cmd.CommandText = OleDbScalarString;
object obj = _cmd.ExecuteScalar();
return obj;
}
catch (Exception ex)
{
ApplicationLog.WriteError(ex.Message);
_hasError = true;
throw ex;
}
}
/// <summary>
/// 执行插入、更新、删除操作
/// </summary>
/// <param name="OleDbString">要执行的Insert、Update或Delete语句</param>
public void ExecForNonQuery(string OleDbString)
{
try
{
_cmd.CommandText = OleDbString;
_cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
ApplicationLog.WriteError(ex.Message);
_hasError = true;
throw ex;
}
}
/// <summary>
/// 提交事务,并释放资源
/// </summary>
public void Dispose()
{
try
{
if (_tran != null)
{
if (_hasError == true)
{
_tran.Rollback();
}
else
{
_tran.Commit();
}
_tran.Dispose();
}
}
catch (Exception ex)
{
_tran.Rollback();
ApplicationLog.WriteError(ex.Message);
throw ex;
}
finally
{
if (_cmd != null)
{
_cmd.Dispose();
}
if (_con != null)
{
if (_con.State != ConnectionState.Closed)
{
_con.Close();
}
_con.Dispose();
}
}
}
}
}
6. 软件测试
6.1什么也不选,直接开始查询
没有任何推导过程,也没有任何结果。
6.2针对某条规则,缺少其中的某个条件的输入:
推导过程中不会出现该条规则,同时该条规则若对应的后件是动物,则该动物也不会被作为结果。
6.3添加规则时将随意的字符串输入作为动物名称:
并没有提示,直接添加。
6.4添加规则时不输入任何字符串,直接点击添加:
程序弹出对话框提示请用户输入。
_______________________________________
附:
程序运行截图:
上方是可选的动物属性,每个属性分成是、否、不清楚三个选项,默认情况下选中的是不清楚。一共有19个属性。
下面是规则推导的显示,当点击“开始查询”按钮,就开始规则推导,输出到下方空白处(有一只小长颈鹿图标的地方):
我们选择有皮毛,有奶,有蹄,有暗斑点,有长脖子,有长腿,然后点击开始查询:
(规则推导处出现了多条符合的规则)
看到推导出的结果,然后点击“查看该动物”可以查看刚才推导出来的动物图片。于是页面跳转到动物页面:
你可以点击“继续查询其他动物”返回查询页面。
若根据刚才的推导不能推导出具体的动物则跳转到出错界面,然后该界面下方提示是否要添加该动物的规则,若想添加规则,则在文本框中输入该动物的名称,点击添加。提示添加成功!