前言

        本文仅限昆明理工大学开设的人工智能导论上机实验的几个重要过程分享。文章部分内容可能有错误,仅代表个人观点。

       以课程老师印发的AI实验指导书02-动物识别专家系统(2021修订)作为题目,本文将用我的视角简单讲解部分理论与程序实现,并感谢给前人文章我带来的启发。

一、问题重述

        用熟悉的语言,编写一个小型专家系统——动物识别系统,分类规则依照13个产生式规则。

二、设计过程

        早期的专家系统的原理就是根据特征分类。比如这13条规则中的rule1:特征是有毛发,那就是哺乳类,毛发就是哺乳类的特征;rule13:特征是鸟类,并且善飞,那就是信天翁,信天翁的特征就是这俩个。这13条产生式规则中有7个物种2个大类2个子类21个特征。

        那就按照获得的特征判断动物物种就行了,简略版流程图如下:

        有了流程图就可以开始设计程序了。

#include <iostream> 

using namespace std;

/*————————————分类规则—————————————— 
r1&&r2:有毛发||有奶		==>哺乳类	(1)
r3&&r4:有羽毛||会飞&&下蛋	==>鸟类 	(2)

r5:1&&(吃肉||犬齿)&&眼睛前视&&有爪	==>食肉类	(3)
r6: 1&&(有蹄||反刍)					==>偶蹄类	(4)

r7 : 3&&黄褐色&&有暗斑点				==>豹 
r8 : 3&&黄褐色&&有黑条纹				==>虎 
r9 : 4&&有长腿&&长颈&&黄褐色&&有暗斑点	==>长颈鹿 
r10: 4&&有白色&&有黑色条纹				==>斑马 
r11: 2&&!会飞&&有长腿&&长颈&&黑白色	==>鸵鸟 
r12: 2&&!会飞&&会游泳&&黑白色			==>企鹅 
r13: 2&&善飞							==>信天翁 

——————————————————————————————*/
/*————————————判断主种类————————————*/
int mainspecies()
{
	int a;
	
	cout << "问:此动物是否有毛发?" ;
	cin >> a;
	if(a != 0) return 1;
	cout << "问:此动物是否有奶?" ;
	cin >> a;
	if(a != 0) return 1;				//判断是否是哺乳动物 
	
	cout << "问:此动物是否会飞并且会下蛋?" ;
	cin >> a;
	if(a != 0)
	{
		cout << "是信天翁!" << endl;	//鸟类会飞只有信天翁 
		return 0;
	}
	cout << "问:此动物是否有羽毛?" ;
	cin >> a;
	if(a != 0) return 2;				//判断是否是其它鸟类 
}

/*————————————判断子种类————————————*/ 

int subcategory()
{
	int a;
	cout << "问:此动物是否有蹄或者反刍?" ;
	cin >> a;
	if(a != 0) return 4;		//有蹄或者反刍就是偶蹄类 
	else return 3; 				//除了偶蹄类的哺乳动物就是食肉类 
}

/*————————————判断哺乳动物———————————*/ 

void mammal(int s)
{
	int a;
	if(s == 3)								//是否是食肉类 
	{
		cout << "问:此动物是否有暗斑点?" ;
		cin >> a;
		if(a != 0)
		{
			cout << "是豹!" << endl;		//有暗斑点的食肉类只有豹 
		}
		else 
		{
			cout << "是虎!" << endl;		//剩下的食肉类只有虎 
		}
	} 
	else									//哺乳动物非食肉类就是偶蹄类 
	{
		cout << "问:此动物是否有长腿?" ;
		cin >> a;
		if(a != 0)
		{
			cout << "是长颈鹿!" << endl;	//有长腿的偶蹄类只有长颈鹿 
		}
		else 
		{
			cout << "是斑马!" << endl;		//剩下的偶蹄类只有斑马 
		}
	} 
}

/*—————————————判断鸟类————————————*/ 

void bird()
{
	int a;
	cout << "问:此动物是否会游泳?" ;
	cin >> a;
	if(a != 0)
	{
		cout << "是企鹅!" << endl;	//不会飞会游泳的鸟只有企鹅 
	}
	else
	{
		cout << "是鸵鸟!" << endl;	//剩下的鸟类只有鸵鸟 
	} 
}

/*—————————————主函数—————————————*/ 

int main()
{
	int species1, species2;
	cout << "SLW专家分类系统(以下输入0代表“否”,否则代表“是”)"  << endl << endl;
	
	species1 = mainspecies();
	
	if(species1 == 2)				//判断鸟类 
	{
		bird();
	} 
	else if(species1 == 1)			//判断哺乳类 
	{
		species2 = subcategory();	//获取哺乳类的子类 
		mammal(species2);			//通过子类判断物种 
	}
	
	return 0;
}

         这是第一版程序,其出现的问题是无论怎么输入(正常的输入)都能由物种被分类出来,因为这个程序中,我设定的大背景是“世界只有这7个物种(食肉类中不是豹就是虎等)”。也因为我对这版程序的这一设定不是很满意,我又重新设计了第二版。

#include <iostream> 
#include <string>

using namespace std;

string s[30];
int feature[30];

void initial()	//制作输出全特征表 
{
	s[1] = "有毛发";
	s[2] = "有奶";
	s[3] = "有羽毛";
	s[4] = "会飞";
	s[5] = "下蛋";
	s[6] = "吃肉";
	s[7] = "犬齿";
	s[8] = "眼睛前视";
	s[9] = "有爪";
	s[10] = "有蹄";
	s[11] = "反刍";
	s[12] = "黄褐色";
	s[13] = "有暗斑点";
	s[14] = "有黑条纹";
	s[15] = "有长腿";
	s[16] = "有长颈";
	s[17] = "有白色";
	s[18] = "有黑色条纹";
	s[19] = "会游泳";
	s[20] = "黑白色";
	s[21] = "善飞";
	s[22] = "哺乳类";
	s[23] = "鸟类";
	s[24] = "食肉类";
	s[25] = "偶蹄类";
	for(int i = 1; i <= 25; i++)
	{
		cout << i << "." << s[i] << " ";
		feature[i] = 0;
	}		
	cout << "输入对应特征编号启动搜索,输入0结束搜索" << endl;
}

void readfeature()
{
	int x;
	do
	{
		cout << "输入特征编号:";
		cin >> x;
		feature[x] = 1;
	}	
	while(x != 0);			//读取每个特征并保存 
	
	cout << "再次确定特征:";
	for(int i = 1; i <= 25; i++)
	{
		if(feature[i] == 1) cout << s[i] << " ";
	}
	cout << endl << endl;	//确认每个特征 
}

int judgemainspecies()
{
	int x = 30;
	if(feature[1] || feature[2])									//哺乳动物特征 
	{
		x = 22;
		feature[x] = 1; 
		cout << s[1] << " 或 " << s[2] << " 是 " << s[x] << endl;
		if(feature[10] || feature[11])								//偶蹄类特征 
		{
			x = 25;
			feature[x] = 1; 
			cout << s[10] << " 或 " << s[11] << " 是 " << s[x] << endl;
		}
		if((feature[6] || feature[7]) && feature[8] && feature[9])	//食肉类特征 
		{
			if(x != 22)
			{
				cout << "特征重复,分类出错!" << endl;
				return 0;
			}
			x = 24;
			feature[x] = 1; 
			cout << s[6] << " 或 " << s[7] << " 且 " << s[8] << " 且 " << s[9] << " 是 " << s[x] << endl;
		}
	}
	if(feature[4] && feature[5] || feature[3])						//鸟类特征 
	{
		if(x != 30)
		{
			cout << "特征重复,分类出错!" << endl;
			return 0;
		}
		x = 23;
		feature[x] = 1; 
		cout << s[4] << " 且 " << s[5] << " 或 " << s[3] << " 是 " << s[x] << endl;
	}
	return x;
}

int judgespecies()
{
	int x = 0;
	if(feature[12] && feature[13] && feature[24])	//豹的特征 
	{
		x = 1;
		cout << s[24] << " 且 " << s[12] << " 且 " << s[13] << " 是豹" << endl;
	}
	
	if(feature[12] && feature[14] && feature[24])	//虎的特征 
	{
		x = 1;
		cout << s[24] << " 且 " << s[12] << " 且 " << s[14] << " 是虎" << endl;
	}
	
	if(feature[12] && feature[13] && feature[15] && feature[16] && feature[25])		//长颈鹿的特征 
	{
		x = 1;
		cout << s[25] << " 且 " << s[12] << " 且 " << s[13] << " 且 " << s[15] << " 且 " << s[16] << " 是长颈鹿" << endl;
	}
	
	if(feature[17] && feature[18] && feature[25])	//斑马的特征 
	{
		x = 1;
		cout << s[25] << " 且 " << s[17] << " 且 " << s[18] << " 是斑马" << endl;
	}
	
	if((!feature[4]) && feature[15] && feature[16] &&  feature[20] && feature[23])	//鸵鸟的特征 
	{
		x = 1;
		cout << s[23] << " 且 不" << s[4] << " 且 " << s[15] << " 且 " << s[16] << " 且 " << s[20] << " 是鸵鸟" << endl;
	}
	
	if((!feature[4]) && feature[19] &&  feature[20] && feature[23])					//企鹅的特征 
	{
		x = 1;
		cout << s[23] << " 且 不" << s[4] << " 且 " << s[19] << " 且 " << s[20] << " 是企鹅" << endl;
	}
		
	if(feature[21] && feature[23])					//信天翁的特征 
	{
		x = 1;
		cout << s[23] << " 且 " << s[21] << " 是信天翁" << endl;
	}
	return x;
}

int main() 
{
	
	initial(); 		//初始化分类系统 
	
	readfeature();	//获取特征 
	
	int species = judgemainspecies();
	if(species == 0) return 0;	//获取大类 
	if(species == 30)
	{
		cout << "特征不足,分类失败!" << endl;
		return 0;
	} 
	//cout << species;
	species = judgespecies();	//获取动物种类 
	
	if(!species)				//获取失败 
		cout << "特征不足,分类失败!" << endl; 
	
	return 0;
}

        当然第二版程序也有其不足的地方,比如没有界面、没有输出格式的优化等。

        两个程序都能完成分类的目标,原理就是根据不同的特征找到相应的物种。这种专家系统的最大的特征就是找到需要分类的特征,根据特征判断。要想扩大专家系统的分类范围,需要扩大判断特征的范围、判断特征的组合范围等,工程量较庞大。

结论

      全文全部是本人一个人完成,存在错误,允许指正,不允许因为本人专业程度低而出现对本人的诋毁、骂人等现象。

        技术是开拓、完善、传承的过程。开拓的过程是艰苦,完善的过程是漫长的,传承的过程是延续的。愿技术能在传承的基础上开拓,能在开拓的道路上完善,能在完善的成果中继承,生生不息,永无止尽!

        全部实验内容已放至百度云盘百度网盘,提取码slwk。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。