“人工智能”实验报告专业:班级:学号:姓名:2017年4月日实验一搜索策略(一)实验内容1.熟悉和掌握启发式搜索的定义、估价函数和算法过程;比较不同算法的性能。
2.修改八数码问题或路径规划问题的源程序,改变其启发函数定义,观察结果的变化,分析原因。
(二)实验思路1.利用已有程序“search.jar”,利用已有的“简单搜索树”图或自行构建一个图,选择DFS/BFS/Lowest Cost First/Best-First/Heuristic Depth First/A*等不同的搜索策略,观察程序运行中,OPEN表和CLOSED表的变化,观察搜索过程的变化,理解各个算法的原理。
2.任选八数码问题或路径规划问题的源程序,思考程序如何解决该问题,并对其启发函数进行修改,观察结果的变化,并分析原因(三)程序清单此处我选择了路径规划问题:由于篇幅原因,只附上启发函数的定义部分。
原启发函数:float MapSearchNode::GoalDistanceEstimate( MapSearchNode &nodeGoal ) {float xd = fabs(float(((float)x - (float)nodeGoal.x)));float yd = fabs(float(((float)y - (float)nodeGoal.y)));return (xd + yd);}第一次修改后的启发函数:float MapSearchNode::GoalDistanceEstimate( MapSearchNode &nodeGoal ) {float xd = fabs(float(((float)x - (float)nodeGoal.x)));float yd = fabs(float(((float)y - (float)nodeGoal.y)));float d=sqrt(xd*xd+yd*yd);return d;}第二次修改后的启发函数:float MapSearchNode::GoalDistanceEstimate( MapSearchNode &nodeGoal ) {float xd = fabs(float(((float)x - (float)nodeGoal.x)));float yd = fabs(float(((float)y - (float)nodeGoal.y)));float d=3*sqrt(xd*xd+yd*yd);return d;}第三次修改后的启发函数:float MapSearchNode::GoalDistanceEstimate( MapSearchNode &nodeGoal ) {float xd = fabs(float(((float)x - (float)nodeGoal.x)));float yd = fabs(float(((float)y - (float)nodeGoal.y)));float d=xd*xd+yd*yd;return d;}(四)运行结果说明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.7f(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.7f(Node2)= g(Node2) +h(Node2)=34.2+100.0=134.2显然f(Node1)<f(Node2),因此由A*算法,我们选择Node1图四③在图四中,我修改了Node2的当前路径值,其他不变f(Node1)= g(Node1) +h(Node1)=26.9+56.8=83.7f(Node2)= g(Node2) +h(Node2)=100.0+31.5=131.5显然f(Node1)<f(Node2),因此由A*算法,我们选择Node1经过上述简单实验论证,我们可以发现,A*算法的确是根据f(n)的值来进行搜索的2.对实验内容2的说明实验内容2我一共做了三次启发函数值的修改①float d=sqrt(xd*xd+yd*yd);②float d=3*sqrt(xd*xd+yd*yd);③float d=xd*xd+yd*yd;图五图五是未进行修改的结果,此时路径经过22个点,搜索了23个点未进行修改,原程序采用的是曼哈顿距离(Manhattan distance):也就是在一个可以向四个方向移动的方向网格中采用的距离,本问题移动方向也只有四个方向,可以说采用曼哈顿距离是当前我所知道中最好的解决方法图六图六是修改成欧几里得距离的结果,对应①情况很显然,这样进行修改,使得搜索次数变多,没有修改前表现良好(同时采用sqrt函数也增加了计算时间),原因我想主要为欧几里得距离表示允许沿任何角度移动,而当前问题只有四个方向,且当前问题的地图直线距离上的障碍物太多。
图七图七对应②③情况,②:欧几里得距离乘上了移动代价D(此处设为3,多次尝试发现设为3或更大之后,搜索次数表现更好),个人理解为移动代价增大使得h(n)比重增大③:既然我们乘上了移动代价D,而且代价>3后搜索次数表现良好,为什么我们不把sqrt函数去掉,采用平方后的欧几里得距离呢?这样不是省去了平方根的耗时计算吗?我认为这样有一个很严重的问题,它会导致启发式函数的估价值过高,也就是h(n)过高,有退化成Gready Best-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 <iostream>#include <stdlib.h>using namespace std;const unsigned int nTests =4; //训练数据的数量const unsigned int nInputs =2; //输入端的数量const double alpha =0.3; //学习参数double weight1[nInputs]={0.0};double weight2[nInputs]={0.0};double b=-0.8; //阈值设为-0.8struct slp{double inputs[nInputs];double output;};//计算输出值double compute(double *inputs,double * weights,double b){double sum =0.0;for (int i = 0 ; i < nInputs; ++i){sum += weights[i]*inputs[i];}//biassum +=b;return sum;}int main(){/**正确的“与”操作,“或”操作的训练数据,也就是所谓的“target”*/slp yu[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}};slp huo[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}};bool bLearningOK = false;int count1=0;//感知器“与”操作学习算法while(!bLearningOK){bLearningOK = true;for (int i = 0 ; i < 4 ; i++){double output = 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<<"请重设参数"<<endl;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<<"请重设参数"<<endl;exit(0);}}}}}bLearningOK = false;int count2=0;//感知器“或”操作学习算法while(!bLearningOK){bLearningOK = true;//第一种情况要求小于0double output = compute(huo[0].inputs,weight2,b);while(output>=0){//cout<<output;weight2[0]=weight2[0]+alpha*(huo[0].output-output)*huo[0].inputs[0];weight2[1]=weight2[1]+alpha*(huo[0].output-output)*huo[0].inputs[1];output = compute(huo[0].inputs,weight2,b);count2 ++;if(count2 >500){cout<<"请重设参数"<<endl;exit(0);}}for (int i = 1 ; i < 4 ; i++){double output = compute(huo[i].inputs,weight2,b);while(output<0){weight2[0]=weight2[0]+alpha*(huo[i].output-output)*huo[i].inputs[0];weight2[1]=weight2[1]+alpha*(huo[i].output-output)*huo[i].inputs[1];output = compute(huo[i].inputs,weight2,b);count2 ++;if(count2 >500){cout<<"请重设参数"<<endl;exit(0);}}}}cout<<"学习数据:"<<endl;for(int w = 0 ; w < nInputs ; ++w){cout<<"yu_weight"<<w<<":"<<weight1[w] <<endl;}cout<<"\n";for (int i = 0 ;i < nTests ; ++i){cout<<"yu_rightresult:"<<yu[i].output<<"\t";cout<<"yu_caculateresult:" << compute(yu[i].inputs,weight1,b)<<endl;}for(int w = 0 ; w < nInputs ; ++w){cout<<"huo_weight"<<w<<":"<<weight2[w] <<endl;}cout<<"\n";for (int i = 0 ;i < nTests ; ++i){cout<<"huo_rightresult:"<<huo[i].output<<"\t";cout<<"huo_caculateresult:" << compute(huo[i].inputs,weight2,b)<<endl;}cout<<endl<<"学习完毕,请输入两个值:"<<endl;double test[2];cin>>test[0]>>test[1];double yu_result;double huo_result;if(compute(test,weight1,b)>0)yu_result=1;elseyu_result=0;if(compute(test,weight2,b)>0)huo_result=1;elsehuo_result=0;cout<<"与操作结果:"<<yu_result<<endl;cout<<"或操作结果:"<<huo_result<<endl;return 0;}(四)运行结果说明1.先对第一个实验内容进行说明,此处我选择了异或问题进行实验图十一①图十一展示了未经训练的情况。