中南大学人工智能实验报告_001.docx
《中南大学人工智能实验报告_001.docx》由会员分享,可在线阅读,更多相关《中南大学人工智能实验报告_001.docx(15页珍藏版)》请在冰点文库上搜索。
“人工智能”实验报告
专业:
班级:
学号:
姓名:
2017年4月日
实验一搜索策略
(一)实验内容
1. 熟悉和掌握启发式搜索的定义、估价函数和算法过程;比较不同算法的性能。
2. 修改八数码问题或路径规划问题的源程序,改变其启发函数定义,观察结果的变化,分析原因。
(二)实验思路
1.利用已有程序“search.jar”,利用已有的“简单搜索树”图或自行构建一个图,选择DFS/BFS/LowestCostFirst/Best-First/HeuristicDepthFirst/A*等不同的搜索策略,观察程序运行中,OPEN表和CLOSED表的变化,观察搜索过程的变化,理解各个算法的原理。
2.任选八数码问题或路径规划问题的源程序,思考程序如何解决该问题,并对其启发函数进行修改,观察结果的变化,并分析原因
(三)程序清单
此处我选择了路径规划问题:
由于篇幅原因,只附上启发函数的定义部分。
原启发函数:
floatMapSearchNode:
:
GoalDistanceEstimate(MapSearchNode&nodeGoal)
{
floatxd=fabs(float(((float)x-(float)nodeGoal.x)));
floatyd=fabs(float(((float)y-(float)nodeGoal.y)));
return(xd+yd);
}
第一次修改后的启发函数:
floatMapSearchNode:
:
GoalDistanceEstimate(MapSearchNode&nodeGoal)
{
floatxd=fabs(float(((float)x-(float)nodeGoal.x)));
floatyd=fabs(float(((float)y-(float)nodeGoal.y)));
floatd=sqrt(xd*xd+yd*yd);
returnd;
}
第二次修改后的启发函数:
floatMapSearchNode:
:
GoalDistanceEstimate(MapSearchNode&nodeGoal)
{
floatxd=fabs(float(((float)x-(float)nodeGoal.x)));
floatyd=fabs(float(((float)y-(float)nodeGoal.y)));
floatd=3*sqrt(xd*xd+yd*yd);
returnd;
}
第三次修改后的启发函数:
floatMapSearchNode:
:
GoalDistanceEstimate(MapSearchNode&nodeGoal)
{
floatxd=fabs(float(((float)x-(float)nodeGoal.x)));
floatyd=fabs(float(((float)y-(float)nodeGoal.y)));
floatd=xd*xd+yd*yd;
returnd;
}
(四)运行结果说明
1.首先对实验内容1进行说明
图一
图一展示A*算法的搜索过程(此处的g(n),h(n)由系统自动给定),绿色表示可拓展节点(在OPEN表内),灰色表示已扩展结点(CLOSED表),没有颜色表示未入表,红色代表当前路径
由课上学习我们易知f(n)=g(n)+h(n)
下面我们通过改变g(n),h(n)来验证上式是否成立。
图二
①图二为图一的放大图,我们可以看出
f(Node1)=g(Node1)+h(Node1)=26.9+56.8=83.7
f(Node2)=g(Node2)+h(Node2)=34.2+31.5=65.7
显然f(Node1)>f(Node2),因此由A*算法,我们选择Node2
图三
②在图三中,我修改了Node2的启发值,其他不变
f(Node1)=g(Node1)+h(Node1)=26.9+56.8=83.7
f(Node2)=g(Node2)+h(Node2)=34.2+100.0=134.2
显然f(Node1) 图四
③在图四中,我修改了Node2的当前路径值,其他不变
f(Node1)=g(Node1)+h(Node1)=26.9+56.8=83.7
f(Node2)=g(Node2)+h(Node2)=100.0+31.5=131.5
显然f(Node1)经过上述简单实验论证,我们可以发现,A*算法的确是根据f(n)的值来进行搜索的
2.对实验内容2的说明
实验内容2我一共做了三次启发函数值的修改
①floatd=sqrt(xd*xd+yd*yd);
②floatd=3*sqrt(xd*xd+yd*yd);
③floatd=xd*xd+yd*yd;
图五
图五是未进行修改的结果,此时路径经过22个点,搜索了23个点
未进行修改,原程序采用的是曼哈顿距离(Manhattandistance):
也就是在一个可以向四个方向移动的方向网格中采用的距离,本问题移动方向也只有四个方向,可以说采用曼哈顿距离是当前我所知道中最好的解决方法
图六
图六是修改成欧几里得距离的结果,对应①情况
很显然,这样进行修改,使得搜索次数变多,没有修改前表现良好(同时采用sqrt函数也增加了计算时间),原因我想主要为欧几里得距离表示允许沿任何角度移动,而当前问题只有四个方向,且当前问题的地图直线距离上的障碍物太多。
图七
图七对应②③情况,
②:
欧几里得距离乘上了移动代价D(此处设为3,多次尝试发现设为3或更大之后,搜索次数表现更好),个人理解为移动代价增大使得h(n)比重增大
③:
既然我们乘上了移动代价D,而且代价>3后搜索次数表现良好,为什么我们不把sqrt函数去掉,采用平方后的欧几里得距离呢?
这样不是省去了平方根的耗时计算吗?
我认为这样有一个很严重的问题,它会导致启发式函数的估价值过高,也就是h(n)过高,有退化成GreadyBest-First-Search的危险
实验二推理技术
(一)实验内容
对已有的产生式系统(默认的例子)进行演示,同时可以更改其规则库或(和)事实库,进行正反向推理,了解其推理过程和机制。
自己建造产生式系统(包括规则库和事实库),然后进行推理,即可以自己输入任何的规则和事实,并基于这种规则和事实进行推理。
这为学生亲手建造产生式系统并进行推理提供了一种有效的实验环境。
(二)实验思路
利用已有程序”Tree.jar”,读取现有知识数据库,对默认的例子进行演示,同时改变其规则库,了解其推理过程
(三)程序清单
本实验不需要编程
(四)运行结果说明
图八
①图八展示了推理成功的结果,程序进行的是逆向链接推理。
首先假设这一只动物是虎。
为了检验这个假设,根据规则,要求虎是哺乳动物,食肉动物,黄褐色且身上有黑色条纹。
那么我们首先检验这个动物是否是哺乳动物,由规则库,是哺乳动物的动物必须有毛发,或者有奶。
我们可以发现将哺乳动物替换成有毛发和有奶都无法继续执行下去。
由规则库,我们观察可知虎是哺乳动物,因此消去这一条件。
接下来只剩下了是肉食动物,是黄褐色,身上有黑色条纹。
我们都可以在规则库中发现这些子句,故可以顺利消解,生成NIL,即推理成功
图九-1
②图九-1展示了推理失败的结果
从假设该动物是长颈鹿开始,最终无法得到结果,因为规则库没有相应子句可供消解。
图九-2
图九-2展示了此时规则库中相应子句的情况,可以发现子句前有%存在使得子句无法被使用。
那么现在我们可以对规则库进行修改,使得该推理成功。
图十-1
③图十-1展示了经过修改规则库后,成功的结果
图十-2
图十-2表示修改规则库后的情况,我们可以与图九-2对比,显然仅仅修改了“%”即可。
实验三神经网络
(一)实验内容
1. 通过BP网络各项参数的不同设置,观察BP算法的学习效果。
观察比较BP网络拓朴结构及其它各项参数变化对于训练结果的影响。
观察并分析不同训练数据对相同拓朴结构的BP网络建模的影响。
2. 编写简单的感知器训练算法,实现简单的逻辑运算(与、或)
(二)实验思路
1.利用已有程序“neural.jar”,通过载入已有BP网络,观察BP算法的学习效果,比较各项参数变化对于训练结果的影响。
2.根据课上学习内容,编写简单的感知器训练算法。
(三)程序清单
#include
#include
usingnamespacestd;
constunsignedintnTests=4;//训练数据的数量
constunsignedintnInputs=2;//输入端的数量
constdoublealpha=0.3;//学习参数
doubleweight1[nInputs]={0.0};
doubleweight2[nInputs]={0.0};
doubleb=-0.8;//阈值设为-0.8
structslp
{
doubleinputs[nInputs];
doubleoutput;
};
//计算输出值
doublecompute(double*inputs,double*weights,doubleb)
{
doublesum=0.0;
for(inti=0;i{
sum+=weights[i]*inputs[i];
}
//bias
sum+=b;
returnsum;
}
intmain(){
/*
*正确的“与”操作,“或”操作的训练数据,也就是所谓的“target”
*/
slpyu[nTests]={
{0.0,0.0,0.0},
{0.0,1.0,0.0},
{1.0,0.0,0.0},
{1.0,1.0,1.0}
};
slphuo[nTests]={
{0.0,0.0,0.0},
{0.0,1.0,1.0},
{1.0,0.0,1.0},
{1.0,1.0,1.0}
};
boolbLearningOK=false;
intcount1=0;
//感知器“与”操作学习算法
while(!
bLearningOK)
{
bLearningOK=true;
for(inti=0;i<4;i++)
{
doubleoutput=compute(yu[i].inputs,weight1,b);
while(output>0)
{
weight1[0]=weight1[0]+alpha*(yu[i].output-output)*yu[i].inputs[0];
weight1[1]=weight1[1]+alpha*(yu[i].output-output)*yu[i].inputs[1];
output=compute(yu[i].inputs,weight1,b);
count1++;
if(count1>500){
cout<<"请重设参数"<exit(0);
}
}
if(i==3){
while(output<0){
weight1[0]=weight1[0]+alpha*(yu[i].output-output)*yu[i].inputs[0];
weight1[1]=weight1[1]+alpha*(yu[i].output-output)*yu[i].inputs[1];
output=compute(yu[i].inputs,weight1,b);
count1++;
if(count1>500){
cout<<"请重设参数"<exit(0);
}
}
}
}
}
bLearningOK=false;
intcount2=0;
//感知器“或”操作学习算法
while(!
bLearningOK)
{
bLearningOK=true;
//第一种情况要求小于0
doubleoutput=compute(huo[0].inputs,weight2,b);
while(output>=0){
//cout<