模式识别实验报告.docx
- 文档编号:7188988
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:23
- 大小:137.74KB
模式识别实验报告.docx
《模式识别实验报告.docx》由会员分享,可在线阅读,更多相关《模式识别实验报告.docx(23页珍藏版)》请在冰豆网上搜索。
模式识别实验报告
武汉大学国际软件学院
实验报告
课程名称模式识别导论
专业年级2015级
姓名宁佳星
学号2015302580323
协作者
实验学期2017-2018学年上学期
课堂时数0课外时数12
填写时间2017年11月12日
实验概述
【实验项目名称】:
模式识别作业1
【实验目的】:
1、请编写程序实现混合类型属性差异性矩阵计算
2、请编写程序实现近邻聚类算法或者最大最小距离聚类算法
3、请编写程序实现层次聚类算法
4、请编写程序实现K-means或者K-中心点聚类算法
5、请编写程序实现ISODATA算法
6、使用统一的测试数据观察不同算法的聚类结果,并讨论为什么
【实验环境】(使用的软件):
●Windiws7
●VisualStudio2017
【参考资料】:
●《模式识别作业1》
●模式识别PPT
●网络索引
实验内容
【实验方案设计】:
1、编写程序实现混合类型属性差异性矩阵计算
//矩阵三元组之矩阵相加相乘
...
#defineMAXSIZE12500//最大非零元素
...
voidInputMatrix(TSMatrix&T)//输入t个非零元素
{
...
}
...
voidTransposeSMatrix(TSMatrixM,TSMatrix&T)//矩阵的转置
{
...
}
...
voidAddMastrix(TSMatrixM,TSMatrixT,TSMatrix&Q)//矩阵相加
{
...
}
...
//for循环复制剩余元素
...
voidMultiply(TSMatrixM,TSMatrixT,TSMatrix&Q)//矩阵相乘
{
...
int*rowSize=newint[T.mu+1];//存放每行非零元素的个数
int*rowStart=newint[T.mu+2];//矩阵每行在三元组开始位置
int*temp=newint[T.nu+1];//存放结果矩阵中每行的计算结果
...
while(Current<=M.tu)
{
ROWM=M.data[Current].row;//当前三元组数据中元素的行号
...
while(Current<=M.tu&&ROWM==M.data[Current].row)
{
COLM=M.data[Current].col;//当前元素的列号,方便与T矩阵的行号相乘
for(i=rowStart[COLM];i ... } } ... 2、编写程序实现近邻聚类算法或者最大最小距离聚类算法 //最大最小距离聚类算法 ... constintN=15;//设置样本点个数 ... voidmain(void) { ... floats[2][N]={{0,1,0,-1,0,10,11,9,10,10,-10,-11,-9,-10,-10}, {0,0,1,0,-1,0,0,0,1,-1,0,0,0,1,-1}};//输入样本点 ... center[0]=0;//firstcenter ... center[1]=index;//secondcenter ... //求出所有中心,finalarraymin[]isstilluseful while(theshold>theta*D12) { ... //min-operate for(j=0;j { ... } ... if(max>theta*D12){k++;center[k]=index;}//addacenter theshold=max;//preparetoloopnexttime } ... } 3、编写程序实现层次聚类算法 //实现层次聚类算法 ... //计算两个样本点之间的欧几里得距离 doubleCAgeneCluster: : getDistance(sDataPointdpA,sDataPointdpB) { ... } list : initialCluster(list { ... { sDataPointtempDataPoint=*iter;//取出数据, ... tempCluster.clusterLabel=i;//初始类簇号为各原数据顺序号 tempCluster.datapointList->push_back(tempDataPoint); //每一个数据为一类 originalClusters->push_back(tempCluster);//originalClusters为类簇序列 ... } ... } list : mergeCluster(list { ... intnBreak=0;//计算找到的次数,以提前退出循环,节省时间 if(mergeIndexA! =mergeIndexB)//分属于不同的类簇,则合并. {//将cluster[mergeIndexB]中的DataPoint加入到cluster[mergeIndexA] for(list : iteratoriter=clusters->begin();iter! =clusters->end();iter++) {//把mergeIndexA所在类簇提取出来。 tempCluster=*iter;//以下程序找出mergeIndexAandB所在类簇,并从链表中删除B类簇。 if(tempCluster.clusterLabel==mergeIndexA) { nBreak++;//计算找到的次数,以提前退出循环,节省时间 tempClusterA=*iter; }//endforif(tempCluster.clusterLabel==mergeIndexA) if(tempCluster.clusterLabel==mergeIndexB) {//并从链表中删除B类簇。 tempClusterB=*iter; nBreak++;//计算找到的次数,以提前退出循环,节省时间 ... if(nBreak==2) {//找到两个类簇,则提前退出循环,节省时间。 nBreak=0; break; } } ... dpA=tempClusterA.datapointList;//把clusterA中的数据集提取出来。 ... for(list : iteratoriter=dpB->begin();iter! =dpB->end();iter++) {//取出数据 dpA->push_back(*iter);//把B中数据存入到A. } ... } ... } list : startAnalysis(list { ... originalClusters=initialCluster(dataPoints);//数据集初始化;//originalClusters为类簇序列 ...printCluster(originalClusters);//打印聚类情况 ... while(finalClusters->size()>ClusterNum)//聚类数为ClusterNum { doubleminDist=9999999.9999;//maxvalue ... { ... if(iIter! =jIter) { ... dataPointsA=ClusterA.datapointList;//类簇中的数据集 clusterLabelA=ClusterA.clusterLabel;//类簇标号 dataPointsB=ClusterB.datapointList;//类簇中的数据集 clusterLabelB=ClusterB.clusterLabel;//类簇标号 for(list : iteratoriterdpA=dataPointsA->begin();iterdpA! =dataPointsA->end();iterdpA++) { ... if(tempDis { minDist=tempDis;//每次都是距离最小的两个合并。 ... } ... } cout<<"mergeIndexA="< finalClusters=mergeCluster(finalClusters,mergeIndexA,mergeIndexB);//mergeIndexA,B是类簇标号 printCluster(originalClusters);//打印聚类情况 } ... } ... 4、编写程序实现K-means或者K-中心点聚类算法 //K-means聚类算法 ... constintNUM=3;//定义划分簇的数目 //数据向量表示 ... //计算距离的平方 doublegetDist(VectA,VectB) { ... } //计算每个簇的中心,平均距离表示 VectgetMeansC(vector { ... for(inti=0;i { ... } Vectc; ... } //获取算法的准则函数值,当准则函数收敛时算法停止 doublegetE(vector { ... for(inti=0;i { ... } ...} intsearchMinC(Vectt,Vectmeans[],intn,double*D) { ... for(inti=1;i { ... } ... } //找最优的种子点 voidFind(vector { ... for(inti=1;i { ... for(intj=0;j { ... } ... for(intj=0;j { ... } } ...} voidkMeans(vector { ... newE=getE(classes,means);//计算当前准则函数值 for(inti=0;i ... while(fabs(newE-oldE)>=1) { for(inti=0;i { ... } ... } //输出最终结果 for(inti=0;i { ... } //每个类的中心点坐标 for(inti=0;i ... } ... 5、编写程序实现ISODATA算法 //ISODATA算法 ... #defineiniClusters5//初始类聚的个数 ...//定义6个使用的参数 structArgs { intexpClusters;//期望得到的聚类数 intthetaN;//聚类中最少样本数 intmaxIts;//最大迭代次数 intcombL;//每次迭代允许合并的最大聚类对数 doublethetaS;//标准偏差参数 doublethetaC;//合并参数 }args; //定义二维点,这里假设是二维的特征,当然可以推广到多维 structPoint { doublex,y; }; //需要合并的两个类聚的信息,包括两个类聚的id和距离 structMergeInfo { intu,v; doubled;//类聚u中心与类聚v中心的距离 }; //定义比较函数 boolcmp(MergeInfoa,MergeInfob) { returna.d } //计算两点之间距离 doubledist(PointA,PointB) { returnsqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)); } structCluster { intnSamples;//样本点的个数 doubleavgDist;//样本点到样本中心的平均距离 Pointcenter;//样本中心 Pointsigma;//样本与中心的标准差 vector //计算该聚类的中心,即该类的均值 voidcalMean() { ... } //计算该类样本点到该聚类中心得平均距离 voidcalDist() { ... } //计算样本与中心的标准差 voidcalStErr() { ... } }; //获取数据 voidgetData(Pointp[],intn) { ... } //设置参数的值 voidsetArgs() { ... } //寻找点t距离最近的类的中心对应的id intFindIdx(vector { ... } //二分法寻找距离刚好小于thetaC的两个类聚的index intFindPos(MergeInfo*info,intn,doublethetaC) { ... } ... voidISOData(Pointp[],intn) { ... intnClusters=iniClusters;//初始化类聚个数 //初始化nClusters个类,设置相关数据 ... boolisLess=false;//标志是否有类的数目低于thetaN while (1) { //先清空每一个聚类 for(inti=0;i { ... } //将所有样本划分到距离类聚中心最近的类中 ... intk=0;//记录样本数目低于thetaN的类的index for(inti=0;i { if(c.at(i).data.size() { isLess=true;//说明样本数过少,该类应该删除 ... } } //如果有类的样本数目小于thetaN if(isLess) { ... } //重新计算均值和样本到类聚中心的平均距离 for(inti=0;i { ... } //计算总的平均距离 ... //分裂操作 if(nClusters<=args.expClusters/2) { ... for(inti=0;i { //计算该类的标准偏差 c.at(i).calStErr(); //计算该类标准差的最大分量 doublemt=c.at(i).sigma.x>c.at(i).sigma.y? c.at(i).sigma.x: c.at(i).sigma.y; maxsigma.push_back(mt); } ... { nClusters++; ClusternewCtr;//新的聚类中心 //获取新的中心 ... //改变老的中心 ... } ... } //合并操作 if(nClusters>=2*args.expClusters||(iter&1)==0) { intsize=nClusters*(nClusters-1); //需要合并的聚类个数 ... //进行排序 sort(info,info+cnt,cmp); //找出info数组中距离刚好小于thetaC的index,那么index更小的更应该合并 intiPos=FindPos(info,cnt,args.thetaC); //用于指示该位置的样本点是否已经合并 bool*flag=newbool[nClusters]; memset(flag,false,sizeof(bool)*nClusters); //用于标记该位置的样本点是否已经合并删除 bool*del=newbool[nClusters]; memset(del,false,sizeof(bool)*nClusters); //记录合并的次数 intnTimes=0; for(inti=0;i<=iPos;i++) { ... //确保同一个类聚只合并一次 if(! flag[u]&&! flag[v]) { nTimes++; //如果一次迭代中合并对数多于combL,则停止合并 if(nTimes>bL)break; //将数目少的样本合并到数目多的样本中 if(c.at(u).nSamples ... } //删除合并后的聚类 vector : iteratorid=c.begin(); ... //合并多少次就删除多少个 ... } ... } intmain() ... 6、用统一的测试数据观察不同算法的聚类结果,并讨论为什么 1中矩阵运算的试验数据见下图(结果) 2-5中使用同同样的样本点数据测试,详情见下图,分析见小结 相关数据: 【结论】(结果): 1、编写程序实现混合类型属性差异性矩阵计算 2、编写程序实现近邻聚类算法或者最大最小距离聚类算法 3、编写程序实现层次聚类算法 4、编写程序实现K-means或者K-中心点聚类算法 5、编写程序实现ISODATA算法 【小结】: ●实验要求算法基本实现,经完善后可正常运行计算 ●关于2-5中不同算法对相同数据的运算得到了略有有差别的结果 ●聚类的目标是使同一类对象的相似度尽可能地大;不同类对象之间的相似度尽可能地小 ●不同算法的根本思想具有一定的差异,因此导致了计算结果的差异 ●例如层次聚类 ●优点: 适用于任意形状和任意属性的数据集;灵活控制不同层次的聚类粒度,强聚类能力 ●缺点: 大大延长了算法的执行时间,不能回溯处理 ●例如K-means算法 ●优点: 应用广泛;收敛速度快;能扩展以用于大规模的数据集 ●缺点: 倾向于识别凸形分布、大小相近、密度相近的聚类;中心选择和噪声聚类对结果影响大 ●ISODATA算法是一种常用的聚类分析方法,是一种非监督学习方法。 ISODATA算法通过设置初始参数而引入人机对话环节,并使用归并和分裂等机制,当两类聚中心小于某个阀值时,将它们合并为一类。 当某类的标准差大于某一阀值时或其样本数目超过某一阀值时,将其分裂为两类,在某类样本数目小于某一阀值时,将其取消。 这样根据初始类聚中心和设定的类别数目等参数迭代,最终得到一个比较理想的分类结果。 指导教师评语及成绩 【评语】: 成绩: 指导教师签名: 批阅日期: 附件: 实验报告说明 1.实验项目名称: 要用最简练的语言反映实验的内容。 要求与实验指导书中相一致。 2.实验目的: 目的要明确,要抓住重点,符合实验任务书中的要求。 3.实验环境: 实验用的软硬件环境(配置)。 4.实验方案设计(思路、步骤和方法等): 这是实验报告极其重要的内容。 包括概要设计、详细设计和核心算法说明及分析,系统开发工具等。 应同时提交程序或设计电子版。 对于设计型和综合型实验,在上述内容基础上还应该画出流程图、设计思路和设计方法,再配以相应的文字
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 模式识别 实验 报告