人工智能、应用、程序

来源:互联网 发布:客家话输入软件 编辑:程序博客网 时间:2024/05/22 12:51

人工智能



人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。 人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大,可以设想,未来人工智能带来的科技产品,将会是人类智慧的“容器”。
人工智能是对人的意识、思维的信息过程的模拟。人工智能不是人的智能,但能像人那样思考、也可能超过人的智能。


================

文本分类



  自动文本分类(Automatic Text Categorization),或者简称为文本分类,是指计算机将一篇文章归于预先给定的某一类或某几类的过程。


  文本分类是指按照预先定义的主题类别,为文档集合中的每个文档确定一个类别.文本分类是文本挖掘的一个重要内容。


  所谓文本分类,是指对所给出的文本,给出预定义的一个或多个类别标号,对文本进行准确、高效的分类.它是许多数据管理任务的重要组成部分。


  文本分类是指按预先指定的标准对文档进行归类这样用户不仅可以方便地浏览文档而且可以通过类别来查询所需的文档。


  文本分类是指在给定的分类体系下,根据文语义元是统计语义方法中的原子,是不可分本的内容自动确
定文本类别的过程.当前的文本割的最小单位,在文本分类中语义元是词。


  文本分类(Text categorization)是指在给定分类体系下,根据文本内容自动确定文本类别的过程
.20世纪90年代以前,占主导地位的文本分类方法一直是基于知识工程的分类方法,即由专业人员手工进
行分类.人工分类非常费时,效率非常低.90年代以来,众多的统计方法和机器学习方法应用于自动文本
分类,文本分类技术的研究引起了研究人员的极大兴趣.目前在国内也已经开始对中文文本分类进行研究
,并在信息检索、Web文档自动分类、数字图书馆、自动文摘、分类新闻组、文本过滤、单词语义辨析以
及文档的组织和管理等多个领域得到了初步的应用.


================


图像分类



图像分类,根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法。它利
用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,以代替
人的视觉判读。


分类方法
基于色彩特征的索引技术
色彩是物体表面的一种视觉特性,每种物体都有其特有的色彩特征,譬如人们说到绿色往往是和树木或草原
相关,谈到蓝色往往是和大海或蓝天相关,同一类物体往拍几有着相似的色彩特征,因此我们可以根据色彩
特征来区分物体.用色彩特特征进行图像分类一可以追溯到Swain和Ballard提出的色彩直方图的方法.由于
色彩直方图具有简单且随图像的大小、旋转变化不敏感等特点,得到了研究人员的厂泛关注,目前几乎所有
基于内容分类的图像数据库系统都把色彩分类方法作为分类的一个重要手段,并提出了许多改进方法,归纳
起主要可以分为两类:全局色彩特征索引和局部色彩特征索引。


基于纹理的图像分类技术
纹理特征也是图像的重要特征之一,其本质是刻画象素的邻域灰度空间分布规律由于它在模式识别和计算
机视觉等领域已经取得了丰富的研究成果,因此可以借用到图像分类中。
在70年代早期,Haralick等人提出纹理特征的灰度共生矩阵表示法(eo一oeeurrenee matrix 
representation),这个方法提取的是纹理的灰度级空间相关性(gray level Spatial dependenee),它首先
基于象素之间的距离和方向建立灰度共生矩阵,再由这个矩阵提取有意义的统计量作为纹理特征向量。基
于一项人眼对纹理的视觉感知的心理研究,Tamuar等人提出可以模拟纹理视觉模型的6个纹理属性,分别是
粒度,对比度,方向性,线型,均匀性和粗糙度。QBIC系统和MARS系统就采用的是这种纹理表示方法。
在90年代初期,当小波变换的理论结构建一认起来之后,许多研究者开始研究
如何用小波变换表示纹理特征。smiht和chang利用从小波子带中提取的统计量(平均值和方差)作为纹理特
征。这个算法在112幅Brodatz纹理图像中达到了90%的准确率。为了利用中间带的特征,Chang和Kuo开发出
一种树型结构的小波变化来进一步提高分类的准确性。还有一些研究者将小波变换和其他的变换结合起来
以得到更好的性能,如Thygaarajna等人结合小波变换和共生矩阵,以兼顾基于统计的和基于变换的纹理分
析算法的优点。


基于形状的图像分类技术
形状是图像的重要可视化内容之一在二维图像空间中,形状通常被认为是一条封闭的轮廓曲线所包围的区
域,所以对形状的描述涉及到对轮廓边界的描述以及对这个边界所包围区域的描述.目前的基于形状分类方
法大多围绕着从形状的轮廓特征和形状的区域特征建立图像索引。关于对形状轮廓特征的描述主要有:直
线段描述、样条拟合曲线、傅立叶描述子以及高斯参数曲线等等。
实际上更常用的办法是采用区域特征和边界特征相结合来进行形状的相似分类.如Eakins等人提出了一组
重画规则并对形状轮廓用线段和圆弧进行简化表达,然后定义形状的邻接族和形族两种分族函数对形状进
行分类.邻接分族主要采用了形状的边界信息,而形状形族主要采用了形状区域信息.在形状进行匹配时,除
了每个族中形状差异外,还比较每个族中质心和周长的差异,以及整个形状的位置特征矢量的差异,查询判
别距离是这些差异的加权和。


基于空间关系的图像分类技术
在图像信息系统中,依据图像中对象及对象间的空间位置关系来区别图像库中的不同图像是一个非常重要
的方法。因此,如何存贮图像对象及其中对象位置关系以方便图像的分类,是图像数据库系统设计的一个重
要问题。而且利用图像中对象间的空间关系来区别图像,符合人们识别图像的习惯,所以许多研究人员从图
像中对象空间位置关系出发,着手对基于对象空间位置关系的分类方法进行了研究。早在1976年,Tanimoto
提出了用像元方法来表示图像中的实体,并提出了用像元来作为图像对象索引。随后被美国匹兹堡大学
chang采纳并提出用二维符号串(2D一String)的表示方法来进行图像空间关系的分类,由于该方法简单,并
且对于部分图像来说可以从ZD一String重构它们的符号图,因此被许多人采用和改进,该方法的缺点是仅用
对象的质心表示空间位置;其次是对于一些图像来
说我们不能根据其ZD一string完个重构其符号图;再则是上述的空间关系太简单,实际中的空间关系要复杂
得多。,针对这些问题许多人提出了改进力一法。Jungert根据图像对象的最小包围盒分别在:x轴方向和y
轴上的投影区间之间的交叠关系来表示对象之间的空间关系,随后Cllallg和Jungert等人又提出了广义ZD
一string(ZDG一String)的方法,将图像对象进一步切分为更小的子对象来表示对象的空间关系,但是该方
法不足之处是当图像对象数日比较多且空间关系比较复杂时,需要切分的子对象的数目很多,存储的开销太
大,针对此Lee和Hsu等人提出了ZDC一string的方一法,它们采用Anell提出的13种时态间隔关系并应用到空
间投影区问上来表达空间关系。在x轴方向和y轴方向的组合关系共有169种,他提出了5种基本关系转换法
则,在此基础上又提出了新的对象切分方法。采用
ZDC一string的方法比ZDG一string切分子对象的数目明显减少。为了在空间关系中保留两个对象的相对空
间距离和对象的大小,Huang等人提出了ZDC书string的方法提高符号图的重构精度,并使得对包含对象相对
大小、距离的符号图的推理成为可能。上述方法都涉及到将图像对象进行划分为子对象,且在用符号串重
构对象时处理时间的开销都比较大,为解决这些方法的不足,Lee等人又提出了ZDB一String的方法,它不要
求对象进一步划分,用对象的名称来表示对象的起点和终点边界。为了解决符号图的重构问题,Chin一
ChenCllang等人提出了面向相对坐标解决符号图的重构问题,Chin一ChenChang等人提出了面向相对坐标符
号串表示(RCOS串),它们用对象最小外接包围盒的左下角坐标和右上角坐标来表示对象之间的空间关系.
对于对象之间的空间关系采用Allen提出的13种区间表示方法。实际上上述所有方法都不是和对象的方位
无关,为此Huang等人又提出了RSString表示方法。虽然上述各种方法在对图像对象空间信息的分类起到过
一定作用,由于它们都是采用对象的最小外接矩形来表示一个对象空间位置,这对于矩形对象来说是比较合
适的,但是当两个对象是不规则形状,且它们在空间关系上是分离时,它们的外接矩形却存在着某种包含和
交叠,结果出现对这些对象空间关系的错误表示。用上述空间关系进行图像分类都是定性的分类方一法,将
图像的空间关系转换为图像相似性的定量度量是一个较为困难的事情。Nabil综合ZD一String方法和二维
平面中对象之间的点集拓扑关系。提出了ZD一PIR分类方法,两个对象之间的相似与否就转换为两个图像的
ZD一PIR图之间是否同构。ZD一PIR中只有图像对象之间的空间拓扑关系具有旋转不变性,在进行图像分类
的时候没有考虑对象之间的相对距离。

图像空间
图像空间的分类方法—利用图像的灰度,颜色,纹理,形状,位置等底层特征对图像进行分类;例如:
[1]利用灰度直方图特征对图像进行分类;
[2]利用纹理特征对图像进行分类;
[3]采用纹理,边缘和颜色直方图混合特征对图像进行分类 ;
[1],[2],[3]均采用SVM作为分类器.
[4]用矩阵表示图像,矩阵元素是相应象素的灰度值,然后用SVD和PCA方法抽取图像特征,BP网络作为分类器
.
图像空间的分类方法的共同缺点是数据量大,计算复杂性高,但分类精度一般比较理想.


特征空间
特征空间的分类方法—首先将原图像经过某种变换如K-L变换,小波变换等变换到特征空间,然后在特征空
间提取图像的高层特征以实现图像的分类.这类分类方法尤以纹理图像分类和遥感图像分类最多.以下是常
见的纹理分类方法,基本上都用到了高波过滤器。
[1]Support vector machine classifier Gabor filters and wavelet transform;
[2]Multiple neural network classifiers Gabor filters;
[3]Bayesian network classifier Gabor filters and Statistical features;
[4]Support vector machine classifier Gabor filters
特征空间的分类方法可降低数据维数,降低计算复杂性,但问题相关性较强,与特征提取的方法和效果有很大关系.


================


两种图像分类算法和matlab源代码


文章主要内容:
第一种图像分类算法:
极光作为太阳风与地球磁层相互作用产生的典型电离层踪迹,其形态和变化过程对研究空间天气活动极为
重要。日侧冕状极光作为极光一种重要形态,能够反映磁正午时期太阳风和地球磁层相互作用的过程。因
此,研究各类日侧冕状极光对分析空间天气活动,电离层及其动态特征具有重要意义。本文提出了一种新的
基于静态极光图像分类的极光特征提取方法,利用X-GLAMs提取极光原始图像的纹理特征。结合极光纹理特
点,X-GLAM选取典型邻域点组成新的邻域机制。在分类阶段,利用支持向量机(SVM)学习极光纹理类别模型,
然后将给定的极光纹理特征分类到之前学习的类别模型中去。实验结果显示,基于X-GLAMs特征的日侧极光
图像分类算法在处理复杂的冕状极光时获得了很好的效果。针对大规模待处理的极光样本数据,本文提出
了一种基于特征选择的日侧极光分类算法。为了降低噪声影响并解决特征维度过高的问题,引入ReliefF算
法对X-GLAMs特征进行选择,进一步筛选出有效的特征向量。本文提出的特征选择方法在保证计算精度的前
提下,一定程度上减小了实验运行速度,为大规模处理极光样本数据创造了基础。

第二种图像分类算法:


极化SAR能够同时获得目标区域的多通道与高分辨率数据,可更好的揭示目标的物理散射特性,因此,极化
SAR图像的特征提取与目标分类在解释雷达图像和目标识别方面起着十分重要的作用。充分利用极化信息,
可更加准确地理解目标散射机理,从而带来更好的SAR图像分类结果。本文根据极化SAR数据的特点,结合子
孔径分析技术,进行了极化SAR图像目标分类算法的研究,主要工作如下:1.总结了目前常用的极化SAR图像
分类算法及其存在的问题。在此基础上,将AdaBoost算法与极化通道所携带的信息相结合,对极化SAR图像
进行监督分类,在已知场景类别数的情况下,该方法能够加快收敛速度,改善分类效果;2.研究了基于子孔径
分析的极化散射机理与特征提取方法。首先从时频分解的角度对方位向子孔径进行了分析,对场景中存在
的各向异性散射行为和布拉格谐振现象进行了讨论。针对场景中的非平稳目标,分析了已有的极大似然比
非平稳目标检测算法,还研究了一种基于熵值与平均散射机理角的联合向量检测非平稳目标的方法。通过
该方法可以对方位向频谱中的非平稳散射行为进行定位,最终消除非平稳散射在全孔径中的影响;3.对目标
的极化分解方法与基于极化分解的极化SAR图像分类方法进行了研究与仿真试验。如Pauli分解、Krogager
分解、H/α分类、H/A/α分类、H/α/Wishart分类、H/A/α/Wishart分类和基于Freeman-Wishart的极化
SAR图像分类等。在此基础上,改进了基于AdaBoost算法的极化SAR图像分类方法,将Pauli分解与AdaBoost
算法的优势得以发挥,该方法既解决了AdaBoost算法需要知道场景先验知识的缺点,同时还能改善分类效果
、提高收敛速度;4.改进了基于全孔径数据的极化SAR图像分类方法,得到三种基于子孔径的极化SAR图像分
类算法并进行了仿真试验:一是非平稳目标检测与H/α分类相结合的极化SAR图像分类;二是子孔径分解与
H/α/Wishart迭代分类相结合的极化SAR图像分类;三是结合Freeman分解与子孔径散射特性的极化SAR图像
分类。仿真试验表明,结合子孔径分析与极化分解的极化SAR图像分类,能够在一定程度上改善分类效果、
增加分类精细度、提高收敛速度,在实际的SAR图像分类应用中具有很大的价值。


matlab主程序:
function [BESTX,BESTY,ALLX,ALLY]=ImageClassify(K,N,Pm,LB,UB,D,c,m)
% 轻风论文网原创作品,转载请注明
M=length(LB);
farm=zeros(M,N);
for i=1:M
x=unifrnd(LB(i),UB(i),1,N);
farm(i,:)=x;
end
ALLX=cell(K,1);
ALLY=zeros(K,N);
BESTX=cell(K,1);
BESTY=zeros(K,1);
k=1;
while k<=K
newfarm=zeros(M,2*N);
Ser=randperm(N);
A=farm(:,Ser(1));
B=farm(:,Ser(2));
P0=unidrnd(M-1);
a=[A(1:P0,:);B((P0+1):end,:)];
b=[B(1:P0,:);A((P0+1):end,:)];
newfarm(:,2*N-1)=a;
newfarm(:,2*N)=b;
for i=1:(N-1)
A=farm(:,Ser(i));
B=farm(:,Ser(i+1));
P0=unidrnd(M-1);
a=[A(1:P0,:);B((P0+1):end,:)];
b=[B(1:P0,:);A((P0+1):end,:)];
newfarm(:,2*i-1)=a;
newfarm(:,2*i)=b;
end
FARM=[farm,newfarm];
SER=randperm(3*N);
FITNESS=zeros(1,3*N);
fitness=zeros(1,N);
for i=1:(3*N)
Beta=FARM(:,i);
FITNESS(i)=FIT(Beta,D,c,m);
end
for i=1:N
f1=FITNESS(SER(3*i-2));
f2=FITNESS(SER(3*i-1));
f3=FITNESS(SER(3*i));
if f1<=f2&&f1<=f3
farm(:,i)=FARM(:,SER(3*i-2));
fitness(:,i)=FITNESS(:,SER(3*i-2));
elseif f2<=f1&&f2<=f3
farm(:,i)=FARM(:,SER(3*i-1));
fitness(:,i)=FITNESS(:,SER(3*i-1));
else
farm(:,i)=FARM(:,SER(3*i));
fitness(:,i)=FITNESS(:,SER(3*i));
end
end
X=farm;
Y=fitness;
ALLX{k}=X;
ALLY(k,:)=Y;
minY=min(Y);
pos=find(Y==minY);
BESTX{k}=X(:,pos(1));
BESTY(k)=minY;
for i=1:N
if Pm>rand&&pos(1)~=i
AA=farm(:,i);
BB=GM(AA,LB,UB);
farm(:,i)=BB;
end
end


================

机器视觉产品农业应用



    自动化产业的迅猛发展,带动了机器视觉产品在各个行业领域内的应用;农业是我国生存之本,怎样
更好的提高农业生产效率及生产质量,一直是国家领导人关心的头等问题,


    机器视觉产品在农业生产中的应用主要有: 


   1、瓜果品质的无损检测中的应用;通过图像采集卡,采集瓜果的形态,颜色等特征,将采集结果传送
给分析处理系统,根据处理结果判断瓜果是否为有损产品。 


   2、烤烟烟叶质量检测中的应用;对大量烟叶样本进行颜色分析,可得到各类样本颜色特征值的分布情
况,采用轮廓跟踪算法对烟叶的整体图像外型轮廓进行提取,采用链码表示法进行描述。最后通过烟叶对
光的透过特性对叶片结构和身份特征进行综合提取和描述。 


  3、谷物识别与分级中的应用;对大米、小麦、玉米以及其他谷物的识别和分级,例如根据应力裂纹、
形态、染色后颜色特征等,应用神经网络、高速滤波等技术来进行识别和分类。 


  4、农副产品的出厂质量检测,如包装、缺损,对肉类、各种农副产品、蔬菜、瓜果产品的出厂包装、
质量合格检测等。 


  5、在农业机械中的应用;农产品分选机械是机器视觉技术在农业机械中应用最早、最多的一个方面,
主要是利用该项技术进行无损检测,即利用农产品表面所反映出的一些基本物理特性对产品按—定的标准
进行质量评估和分级。主要用于在农产品加工过程中进行品质自动检测及反馈控制。 


  6、机器视觉技术在农业生产自动化中的应用;在动植物的生长过程中,根据对其生长情况的精确自动
地进行监测,可以有效的控制动植物的生长环境,以满足动植物生产所需。 


    机器视觉在农业方面的应用检测还有很多,由于我国是人口大国,以农业为基础,许多专家致力于农
业生产方面的研究,机器视觉在农业机械方面的应用已取得了长足的进步;在国内,又以陕西维视数字图
像技术有限公司生产的机器视觉产品盛名,其在视觉检测、测量、图像识别、视觉定位等方面具有领先水
平,生产的产品如图像采集卡,流媒体采集卡,VGA采集卡等都在农业检测方面取得了良好的成绩,备受
用户青睐。


================


五大最成功人工智能技术应用



电脑“深蓝”击败国际象棋第一人


所谓人工智能,就是要实现所有目前还无法不借助人类智慧才能实现的任务的集合。或许“人工智能”听起来总让人想起科幻小说或者科幻电影中的那些聪明的robot,很有趣,但却缺乏真实感。可实际上机器人外形只不过是人工智能的容器之一,人工智能很早之前就以多种形态出现在生活之中。


沃森:击败最强大脑的人工智能


如果说深蓝只体现于对弈的人工智能并不算足够智能的话,那么另一款人工智能程序“沃森”,则能够符合大众对“智能”的认知。在一档类似于“最强大脑”的综艺节目《危险边缘》中,沃森击败了两位最高纪录保持者,获得百万奖金。问答过程中,沃森在无人类协助的情况下,独自完成对自然语言的分析,并且以远超人类的速度完成抢答。


人工智能程序沃森的特点在于对大数据迅速、准确的分析,于是现今IBM正将其运用于医学领域。病人向沃森上传自己的病况与症状,沃森则根据该情况分析患者最有可能患上的疾病种类,并提供医治方法。今后该程序还可运用在更多特定环境中,为用户提供各种紧急情况的应对方法。


谷歌搜索:隐藏最深的人工智能


2002年,尚未成为谷歌CEO的拉里·佩奇曾在回答凯文·凯利“为什么谷歌要做免费搜索”的提问时,回答道,“不,我们在做人工智能”。实际上,谷歌搜索正是一种完善人工智能的尝试:用户在谷歌上的每一次搜索,都是在辅导人工智能进行深度学习。




谷歌搜索在表面上只是一款搜索引擎,但其引擎的机理和很多人工智能程序相同:以并行计算、大数据及更深层次算法为基础,完成对数据、问题的智能化分析。或许很多谷歌用户都能感受到,谷歌搜索正变得越来越“聪明”,越来越“懂你”,而赋予其这种学习能力的,正是人工智能。


谷歌无人驾驶汽车:即将到来的人工智能


前方红灯需要停车;左转弯时注意行人与后方汽车;前方汽车急停需要迅速踩刹车……诸如此类复杂且参考因素众多的驾驶问题,只有人类才能妥善解决。不过这个情况马上就会迎来改变,因为Google的无人驾驶车将于2020年正式上市。人工智能正在取代人类的工作,解放人类的双手。




与谷歌无人驾驶汽车高价值对应的,是复杂的分析程式:利用传感器、雷达、摄像机、激光测距仪、GPS等获得路况信息,再交由系统分析,获得应对措施,再传达至汽车的各项零部件……其复杂繁琐程度可见一斑。虽然谷歌汽车暂时尚未能完全实现汽车自动驾驶,但相信随着人工智能技术的发展,人工智能完全接替人力操作的未来并不遥远。


QVM:最安全也&最冷门的人工智能


国内也有颇多厂商开始利用人工智能技术为大众服务,其中成熟度较高的则是安全领域中的一款杀毒引擎:360 QVM引擎。QVM引擎在病毒库中寻找病毒演化规律并归纳成算法,尔后利用人工智能技术的学习功能将其掌握,最终QVM引擎将能够自主识别病毒库中的样本及病毒库中并不存在的样本“进化版”。据了解,人工智能引擎QVM被归为第三代杀毒引擎,其病毒检出率已远超前两代引擎的总和,且查杀速度至少提高一倍。


在反病毒领域,QVM的价值并不仅体现在其快速、准确的识别、查杀病毒能力,还有将人工智能技术与杀毒软件结合的想法:首先通过对病毒样本的分析和分类形成样本向量和向量机,然后建立一个机器学习的决策机模型,利用决策树和向量机对大量样本进行学习,从而识别恶意程序或非恶意程序;并且病毒库中的样本越多,QVM引擎的查杀将越快、越精确。运用人工智能技术的QVM引擎,正在重新定义杀毒软件的历史。


苹果Siri:为你解决问题的人工智能


相比于冷冰冰的的病毒引擎,人们对有“感情”的Siri明显更有兴趣。Siri用到的技术同样基于人工智能以及云计算:通过与用户交互获取用户需求,将自然语言转化为“真实含义”,交由知识库分析、检索所需结果,最终再转换为自然语言回答给用户。短短数秒之内,Siri就能将用户需求转化为多不同的表述方式并完成在海量数据中的搜索。


Siri对人类生活产生的影响无需赘述,从最初的聊天解闷,到后来能有效的帮助主人搜索并解决问题,现今Siri俨然成为最合格的“私人助理”。在并不遥远的未来,以Siri为代表的人工智能语音识别技术亦将有着更大的发展:类似于“沃森”的医疗求助、车载导航乃至教育领域都可以利用该技术来达到解放人力的目的。


================


人工智能基本方法及程序设计



第1章状态图搜索 
  1.1状态图 
  1.2状态图搜索方式 
  1.3状态图搜索算法 
  1.4状态图搜索程序设计 


  第2章树式状态图搜索 
  2.1穷举式搜索 
  2.2启发式搜索 


  第3章加权状态图搜索 
  3.1加权状态图与代价树 
  3.2最小代价优先法 
  3.3 A与A算法 


  第4章与或图搜索 
  4.1与或图 
  4.2与或图搜索 


  第5章博弈树搜索 
  5.1博弈的基本概念 
  5.2博弈树的基本概念 
  5.3极小极大搜索法 
  5.4一字棋游戏 


  第6章遗传算法 
  6.1遗传算法中相关基本概念 
  6.2遗传操作 
  6.3基本遗传算法 
  6.4遗传算法应用举例 
  6.5遗传算法程序设计 


  第7章基于产生式规则的机器推理 
  7.1产生式规则 
  7.2产生式系统 
  7.3简单的产生式系统程序设计 


  第8章决策树学习 
  8.1机器学习概述 
  8.2决策树学习概述 
  8.3 ID3算法 
  8.4 ID3算法程序设计 


  第9章神经网络学习 
  9.1神经网络概述 
  9.2神经网络学习概述 
  9.3 BP神经网络 
  9.4 BP算法程序设计 


================

人工智能算法实现:A*算法c语言





A*算法,A*(A-Star)算法是一种静态路网中求解最短路最有效的方法。估价值与实际值越接近,估价函数取得就越好。


A*[1](A-Star)算法是一种静态路网中求解最短路最有效的方法。


公式表示为: f(n)=g(n)+h(n),


其中 f(n) 是从初始点经由节点n到目标点的估价函数,


g(n) 是在状态空间中从初始节点到n节点的实际代价,


h(n) 是从n到目标节点最佳路径的估计代价。


保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:


估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。


如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。




方法/步骤
估价值与实际值越接近,估价函数取得就越好
例如对于几何路网来说,可以取两节点间欧几理德距离(直线距离)做为估价值,即f=g(n)+sqrt((dx-nx)*(dx-nx)+(dy-ny)*(dy-ny));这样估价函数f在g值一定的情况下,会或多或少的受估价值h的制约,节点距目标点近,h值小,f值相对就小,能保证最短路的搜索向终点的方向进行。明显优于Dijkstra算法的毫无方向的向四周搜索。
conditions of heuristic
Optimistic (must be less than or equal to the real cost)
As close to the real cost as possible
详细内容:
创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
算起点的估价值;
将起点放入OPEN表;


A star算法在静态路网中的应用,以在地图中找从开始点 s 到e点的最短行走路径为例:
首先定义数据结构
#define MAPMAXSIZE 100 //地图面积最大为 100x100 
#define MAXINT 8192 //定义一个最大整数, 地图上任意两点距离不会超过它 
#define STACKSIZE 65536 //保存搜索节点的堆栈大小 
#define tile_num(x,y) ((y)*map_w+(x)) //将 x,y 坐标转换为地图上块的编号 
#define tile_x(n) ((n)%map_w) //由块编号得出 x,y 坐标 
#define tile_y(n) ((n)/map_w) 
// 树结构, 比较特殊, 是从叶节点向根节点反向链接 
typedef struct node *TREE; 
struct node {
int h;
int tile;
TREE father;
};
typedef struct node2 *LINK;
struct node2 {
TREE node;
int f;
LINK next;
};
LINK queue; // 保存没有处理的行走方法的节点 
TREE stack[STACKSIZE]; // 保存已经处理过的节点 (搜索完后释放) 
int stacktop;
char map[][6]={{'x','x','x','x','x','x'},
               {'x','e',' ',' ',' ','x'},
               {'x','x',' ','x',' ','x'},
               {'x','x',' ',' ',' ','x'},
               {'x','x','x','x','s','x'},
               {'x','x','x','x','x','x'} };//地图数据 
int dis_map[MAPMAXSIZE][MAPMAXSIZE];//保存搜索路径时,中间目标地最优解 
int map_w,map_h;//地图宽和高 
int start_x,start_y,end_x,end_y; //地点,终点坐标 
// 路径寻找主函数 
void findpath(int *path)
{
 //printf("%d,%d,%d,%d",start_x,start_y,end_x,end_y); 
TREE root;
int i,j;
stacktop=0;
for (i=0;i<map_h;i++)
for (j=0;j<map_w;j++)
dis_map[i][j]=MAXINT;
init_queue();
root=(TREE)malloc(sizeof(*root));
root->tile=tile_num(start_x,start_y);
root->h=0;
root->father=NULL;
enter_queue(root,judge(start_x,start_y));
for (;;) {
int x,y,child;
TREE p;
root=get_from_queue();
if (root==NULL) {
*path=-1;
return;
}
x=tile_x(root->tile);
y=tile_y(root->tile);
if (x==end_x && y==end_y) break;// 达到目的地成功返回 
child=trytile(x,y-1,root);//尝试向上移动 
child&=trytile(x,y+1,root);//尝试向下移动 
child&=trytile(x-1,y,root);//尝试向左移动 
child&=trytile(x+1,y,root);//尝试向右移动 
if (child!=0)
pop_stack();// 如果四个方向均不能移动,释放这个死节点 
}
// 回溯树,将求出的最佳路径保存在 path[] 中 
for (i=0;root;i++) {
path[i]=root->tile;
root=root->father;
//printf("pathis %d",path[i]);
}
path[i]=-1;
freetree();
}
// 估价函数,估价 x,y 到目的地的距离,估计值必须保证比实际值小 
int judge(int x,int y)

int distance;
distance=abs(end_x-x)+abs(end_y-y);
return distance;
}
// 尝试下一步移动到 x,y 可行否 
int trytile(int x,int y,TREE father)
{
TREE p=father;
int h;
if (map[y][x]=='x') return 1; // 如果 (x,y) 处是障碍,失败 
while (p) {
if (x==tile_x(p->tile) && y==tile_y(p->tile)) return 1; //如果 (x,y) 曾经经过,失败 
p=p->father;
}
h=father->h+1;
if (h>=dis_map[y][x]) return 1;// 如果曾经有更好的方案移动到 (x,y) 失败 
dis_map[y][x]=h;// 记录这次到 (x,y) 的距离为历史最佳距离 
// 将这步方案记入待处理队列 
p=(TREE)malloc(sizeof(*p));
p->father=father;
p->h=father->h+1;
p->tile=tile_num(x,y);
enter_queue(p,p->h+judge(x,y));
return 0;
}


打开c语言编译器,输入我们的运行代码,编译,运行如下,打印出地图如下图:
人工智能算法实现:[1]A*算法c语言
人工智能算法实现:[1]A*算法c语言
点任意键进行运行找静态路网
人工智能算法实现:[1]A*算法c语言
人工智能算法实现:[1]A*算法c语言
人工智能算法实现:[1]A*算法c语言
说明:找到路后会存到一个数组中去,我们为了显示这个过程可以运用打印函数打印出来代码如下
void printpath(int *path)
{
int i;
//printf("-44444444444444");
for (i=0;path[i]>=0;i++) {
gotoxy(tile_x(path[i])+1,tile_y(path[i])+1);
printf("-");
Sleep(2000);         
}
printf("\n");
printf("\n");
printf("走迷宫完成");
}
整个程序的代码如下:
#include<windows.h>
#include"stdio.h"
#include<conio.h>
#include"assert.h" 
#include"stdlib.h"
#define MAPMAXSIZE 100 //地图面积最大为 100x100 
#define MAXINT 8192 //定义一个最大整数, 地图上任意两点距离不会超过它 
#define STACKSIZE 65536 //保存搜索节点的堆栈大小 
#define tile_num(x,y) ((y)*map_w+(x)) //将 x,y 坐标转换为地图上块的编号 
#define tile_x(n) ((n)%map_w) //由块编号得出 x,y 坐标 
#define tile_y(n) ((n)/map_w) 
// 树结构, 比较特殊, 是从叶节点向根节点反向链接 
typedef struct node *TREE; 
struct/*designde by 1wangxiaobo@163.com*/ node {
int h;
int tile;
TREE father;
};
typedef struct /*designde by 1wangxiaobo@163.com*/node2 *LINK;
struct node2 {
TREE node;
int f;/*designde by 1wangxiaobo@163.com*/
LINK next;
};
LINK queue; // 保存没有处理的行走方法的节点 
TREE stack[STACKSIZE]; // 保存已经处理过的节点 (搜索完后释放) 
int stacktop;
char map[][6]={{'x','x','x','x','x','x'},
               {'x','e',' ',' ',' ','x'},
               {'x','x',' ','x',' ','x'},
               {'x','x',' ',' ',' ','x'},
               {'x','x','x','x','s','x'},
               {'x','x','x','x','x','x'} };//地图数据 
int dis_map/*designde by 1wangxiaobo@163.com*/[MAPMAXSIZE][MAPMAXSIZE];//保存搜索路径时,中间目标地最优解 
int map_w,map_h;//地图宽和高 
int start_x,start_y,end_x,end_y; //地点,终点坐标 
void gotoxy(int x ,int y)
{
HANDLE a;
COORD zb;
zb.X =x-1;
zb.Y =y-1;
a= GetStdHandle(STD_OUTPUT_HANDLE/*designde by 1wangxiaobo@163.com*/);
SetConsoleCursorPosition(a,zb);
}
// 初始化队列 
void init_queue()

queue=(LINK)malloc(sizeof(*queue));
queue->node=NULL;
queue->f=-1;
queue->next=(LINK)/*designde by 1wangxiaobo@163.com*/malloc(sizeof(*queue));
queue->next->f=MAXINT;
queue->next->node=NULL;
queue->next->next=NULL;

// 待处理节点入队列, 依靠对目的地估价距离插入排序 
void enter_queue(TREE node,int f)

LINK p=queue,father,q;
while(f>p->f) {
father=p;
p=p->next/*designde by 1wangxiaobo@163.com*/;
assert(p);

q=(LINK)malloc(sizeof(*q));
assert(queue);
q->f=f,q->node=node,q->next=p;
father->next=q;

// 将离目的地估计最近的方案出队列 
TREE get_from_queue()

TREE bestchoice=queue->next->node;
LINK next=queue->next->next;
/*designde by 1wangxiaobo@163.com*/free(queue->next);
queue->next=next;
stack[stacktop++]=bestchoice;
assert(stacktop<STACKSIZE);
return /*designde by 1wangxiaobo@163.com*/bestchoice;

// 释放栈顶节点 
void pop_stack()

free(stack[--stacktop]);
}
// 释放申请过的所有节点 
void freetree()

int i;
LINK p;
for (i=0;i<stacktop;i++)
free(stack);
while /*designde by 1wangxiaobo@163.com*/(queue) {
p=queue;
free(p->node);
queue=queue->next;
free(p);


// 估价函数,估价 x,y 到目的地的距离,估计值必须保证比实际值小 
int judge(int x,int y)

int distance;
distance=abs(end_x-x)+abs(end_y-y);
return distance;
}
// 尝试下一步移动到 x,y 可行否 
int trytile(int/*designde by 1wangxiaobo@163.com*/ x,int y,TREE father)
{
TREE p=father;
int h;
if (map[y][x]=='x') return 1; // 如果 (x,y) 处是障碍,失败 
while (p) {
/*designde by 1wangxiaobo@163.com*/if (x==tile_x(p->tile) && y==tile_y(p->tile)) return 1; //如果 (x,y) 曾经经过,失败 
p=p->father;
}
h=father->h+1;
if (h>=dis_map[y][x]) return 1;// 如果曾经有更好的方案移动到 (x,y) 失败 
dis_map[y][x]=h;// 记录这次到 (x,y) 的距离为历史最佳距离 
// 将这步方案记入待处理队列 
p=(TREE)malloc(sizeof(*p));
p->father=father;
p->h=father->h+1;
p->tile=tile_num(x,y);
enter_queue(p,p->h+judge(x,y));
return 0;
}
// 路径寻找主函数 
void findpath(int *path)
{
 //printf("%d,%d,%d,%d",start_x,start_y,end_x,end_y); 
TREE root;
int i,j;
stacktop=0;
for (i=0;i<map_h;i++)
for (j=0;j<map_w;j++)
dis_map[i][j/*designde by 1wangxiaobo@163.com*/]=MAXINT;
init_queue();
root=(TREE)malloc(sizeof(*root));
root->tile=tile_num(start_x,start_y);
root->h=0;
root->father=NULL;
enter_queue(root,judge(start_x,start_y));
for (;;) {
int x,y,child;
TREE p;
root=get_from_queue();
if (root==NULL) {
*path=-1;
return;
}
x=tile_x(root->tile);
y=tile_y(root->tile);
if (x==end_x && y==end_y) break;// 达到目的地成功返回 
child=trytile(x,y-1,root);//尝试向上移动 
child&=trytile(x,y+1,root);//尝试向下移动 
child&=trytile(x-1,y,root);//尝试向左移动 
child&=trytile(x+1,y,root);//尝试向右移动 
if (child!=0)
pop_stack();// 如果四个方向均不能移动,释放这个死节点 
}
// 回溯树,将求出的最佳路径保存在 path[] 中 
for (i=0;root;i++) {
path[i]=root->tile;
root=root->father;
//printf("pathis %d",path[i]/*designde by 1wangxiaobo@163.com*/);
}
path[i]=-1;
freetree();
}
void printpath(int *path)
{
int i;
//printf("-44444444444444");
for (i=0;path[i]>=0;i++) {
gotoxy(tile_x(path[i])+1,tile_y(path[i])+1);
printf("-");
Sleep(2000);         
}
printf("\n");
printf("\n");
printf("走迷宫完成");
}
void readmap()
{ printf("走迷宫,s是起始点 e是终点  按任意键开始");
getchar();
//FILE *f;
int i,j;
//f=fopen("2.c","r");
//assert(f);
//scanf("%d%d",&map_w,&map_h);
map_w=map_h=6;
for (i=0;i<map_h;i++)
//fgets(&map[i][0],map_w+1,f);
//fclose(f);
start_x=-1,end_x=-1;
for (i=0;i<map_h;i++)
for (j=0;j/*designde by 1wangxiaobo@163.com*/<map_w;j++) {
if (map[i][j]=='s') map[i][j]=' ',start_x=j,start_y=i;
if (map[i][j]=='e') map[i][j]=' ',end_x=j,end_y=i;
}
assert(start_x>=0 && end_x>=0);
//printf("%d,%d,%d,%d",start_x,start_y,end_x,end_y);
}
void showmap()
{
int i,j;
system("cls");
for (i=0;i<map_h;i++) {
gotoxy(1,i+1);
for (j=0;j<map_w;j++)
if (map[i][j]!=' ') printf("x");
else printf(" ");
}
gotoxy(end_x+1,end_y+1);
printf("e");
gotoxy(start_x+1,start_y+1);
printf("s");
}
int main()
{
 system(" A*算法试验程序");//设置cmd窗口标题
 printf("………… A*算法试验程序,…………");
int path[MAXINT];
readmap();
showmap();
Sleep(2000);
findpath(path);
printpath(path);
getchar();
system("pause");
return 0;
}
END


为了使的程序可以慢慢的打印出来动态的运行效果 加了Sleep(2000);
================


BP神经网络C语言程序  



BP的C语言版,


#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
#include<time.h>


#define MAXWEIGHT   ((float)0.3)
#define SCALEWEIGHT ((float)32767)
#define nInputNodes   4    
#define nHiddenNodes  8    
#define nOutputNodes  3   
#define nPatterns     15
#define nIterations   5000


#define ESC           27
#define ERRORLEVEL    0.0001
#define ITEMS         8


typedef  float *PFLOAT;
typedef  PFLOAT VECTOR;
typedef  PFLOAT *MATRIX;


void     VectorAllocate(VECTOR *vector,int nCols);
void     AllocateCols(PFLOAT matrix[],int nRows,int nCols);
void     MatrixAllocate(MATRIX *pmatrix,int nRows,int nCols);
void     MatrixFree(MATRIX matrix,int nRows);


MATRIX   out0;
MATRIX   out1;
MATRIX   delta1;
MATRIX   delw1;
MATRIX   w1;
MATRIX   out2;
MATRIX   delta2;
MATRIX   delw2;
MATRIX   w2;
MATRIX   target;
//VECTOR   PatternID;


void  main()
{
         float eta  =0.15,
               alpha=0.075;
         int nReportErrors=100;
         float ErrorLevel=ERRORLEVEL;
         char  MonitorError=0;
         float error;
         register int h;
         register int i;
         register int j;
         int    p,
                q;
//                r;
  FILE   *fpPattern,
            *fpWeightsOut,
            *fpResults,
            *fpError,
   *fpTest;
   
  
        MatrixAllocate(&out0,  nPatterns,   nInputNodes);
        MatrixAllocate(&out1,  nPatterns,   nHiddenNodes);
        MatrixAllocate(&out2,  nPatterns,   nOutputNodes);
        MatrixAllocate(&delta2,nPatterns,   nOutputNodes);
     MatrixAllocate(&delw2, nOutputNodes, nHiddenNodes+1);
     MatrixAllocate(&w2,    nOutputNodes, nHiddenNodes+1);
        MatrixAllocate(&delta1, nPatterns,   nHiddenNodes);
     MatrixAllocate(&delw1, nHiddenNodes,nInputNodes+1);
     MatrixAllocate(&w1,    nHiddenNodes,nInputNodes+1);
        MatrixAllocate(&target,nPatterns,   nOutputNodes);
//     VectorAllocate(&PatternID,nPatterns);
//初始化权值----------------------------------
   srand((unsigned)time(NULL));
           
   for(h=0;h<nHiddenNodes;h++)
   {
      for(i=0;i<=nInputNodes;i++)
      {
            float frand=rand();
             w1[h][i]=MAXWEIGHT*(1.0-2*frand/SCALEWEIGHT);
        delw1[h][i]=0.0;


   }
   }
    for(j=0;j<nOutputNodes;j++)
      for(h=0;h<=nHiddenNodes;h++)
   {
           float frand=rand();
           w2[j][h]=MAXWEIGHT*(0.1-2*frand/SCALEWEIGHT);
           delw2[j][h]=0.0;


   }
    
//输入训练样本-------------------------------
   if(fpPattern=fopen("input.txt","r"))
   for (p=0;p<nPatterns;p++)
      for (i=0;i<nInputNodes;i++)
  fscanf(fpPattern,"%f",&out0[p][i]); 
  
    for (p=0;p<nPatterns;p++)
      for (i=0;i<nOutputNodes;i++)
  fscanf(fpPattern,"%f",&target[p][i]); 
   
     fpError=fopen("error.txt","w");
    
//开始训练--------------------------------
  fprintf(stderr,nIterations>1 ? "Training...\n":"Testing\n");
   for(q=0;q<nIterations;q++)
   {
      for (p=0;p<nPatterns;p++)
       {
        for (h=0;h<nHiddenNodes;h++)
        {
        float  sum=w1[h][nInputNodes];
           for (i=0;i<nInputNodes;i++)
               sum+=w1[h][i]*out0[p][i];
           out1[p][h]=1.0/(1.0+exp(-sum));
        }


        for(j=0;j<nOutputNodes;j++)
        {
           float sum=w2[j][nHiddenNodes];
           for(h=0;h<nHiddenNodes;h++)
       sum+=w2[j][h]*out1[p][h];
           out2[p][j]=1.0/(1.0+exp(-sum));
        }
        for(j=0;j<nOutputNodes;j++)
           delta2[p][j]=(target[p][j]-out2[p][j])*
    out2[p][j]*(1.0-out2[p][j]);
        for(h=0;h<nHiddenNodes;h++)
        {
           float sum=0.0;
           for(j=0;j<nOutputNodes;j++)
              sum+=delta2[p][j]*w2[j][h];
    delta1[p][h]=sum*out1[p][h]*(1.0-out1[p][h]);
        }
    }///for p
    for(j=0;j<nOutputNodes;j++)
    {
       float dw;
       float sum=0.0;
       for(p=0;p<nPatterns;p++)
          sum+=delta2[p][j];
       dw=eta*sum+alpha*delw2[j][nHiddenNodes];
       w2[j][nHiddenNodes]+=dw;
       delw2[j][nHiddenNodes]=dw;
       for(h=0;h<nHiddenNodes;h++)
       {
          float sum=0.0;
          for(p=0;p<nPatterns;p++)
      sum+=delta2[p][j]*out1[p][h];
          dw        =eta*sum+alpha*delw2[j][h];
          w2[j][h]  +=dw;
          delw2[j][h]=dw;
       }
    }
    for(h=0;h<nHiddenNodes;h++)
    {
       float dw;
       float sum=0.0;
       for(p=0;p<nPatterns;p++)
          sum+=delta1[p][h];
       dw      =eta*sum+alpha*delw1[h][nInputNodes];
       w1[h][nInputNodes]+=dw;
       delw1[h][nInputNodes]=dw;
       for(i=0;i<nInputNodes;i++)
       {
          float sum=0.0;
          for(p=0;p<nPatterns;p++)
             sum+=delta1[p][h]*out0[p][i];


       dw=eta*sum+alpha*delw1[h][i];
          w1[h][i]+=dw;
          delw1[h][i]=dw;
       }
    }
    if(kbhit())
    {
       int c=_getch();
       if((c=toupper(c))=='E')
          MonitorError++;
       else if(c==ESC)
           break;
    }  
    if(MonitorError||(q%nReportErrors==0))
    {
      for(error=0.0,p=0;p<nPatterns;p++)
      {
         for(j=0;j<nOutputNodes;j++)
   {
           float temp=target[p][j]-out2[p][j];
           error+=temp*temp;
   }
   }
    error/=(nPatterns*nOutputNodes);
    fprintf(stderr,"Iteration %5d/%-5d Error %f\r",
             q,nIterations,error);
    MonitorError=0;
    if(q% nReportErrors==0)
     fprintf(fpError,"%d %f\n",q,error);
    if(error<ErrorLevel)
      break;
    }
  }//q
  for(p=0,error=0.0;p<nPatterns;p++)
  {
    for(j=0;j<nPatterns;j++)
    {
       float temp=target[p][j]-out2[p][j];
       error+=temp*temp;
    }
  }
  error/=(nPatterns*nOutputNodes);
  fprintf(stderr,"Iteration %5d/%-5d Error %f\n",q,nIterations,error);
  fprintf(fpError,"\n%d %f\n",q,error);
  fclose(fpError);


  //输出权值-------------------------------
  if((fpWeightsOut=fopen("WeightsOut.txt","w"))==NULL)
  {
     fprintf(stderr,"can't write file %s\n","WeightsOut.txt");
     exit(1);
  }
  for(h=0;h<nHiddenNodes;h++)
      for(i=0;i<=nInputNodes;i++)
        fprintf(fpWeightsOut,"%g%c",w1[h][i],i%ITEMS==ITEMS-1?'\n':' ');
  for(j=0;j<nOutputNodes;j++)
      for(h=0;h<nHiddenNodes;h++)
        fprintf(fpWeightsOut,"%g%c",w2[j][h],j%ITEMS==ITEMS-1?'\n':' ');
  fclose(fpWeightsOut);


//输出训练结果----------------------------------------
  if((fpResults=fopen("Results.txt","w"))==NULL)
  {
    fprintf(stderr,"can't write file %s\n","Results.txt");
    fpResults=stderr;
  }
  for(p=0;p<nPatterns;p++)
  {
      fprintf(fpResults,"%d ",p+1);
      for(j=0;j<nOutputNodes;j++)
         fprintf(fpResults,"%f ",target[p][j]);
   fprintf(fpResults," --  ");


      for(j=0;j<nOutputNodes;j++)
         fprintf(fpResults,"%f ",out2[p][j]);
   fprintf(fpResults,"\n");
  }
  fclose(fpResults);


//--测试数据--------------------------
 printf("Training has complete!\n1.Test data\n2.Exit\n");
  {
   
   int c=getchar();
   if(c=='1') 
    {
    char ftest[64];
    int testnum;
  printf("Please input file name of data!\n");
test:
  scanf("%s",&ftest);
  if((fpTest=fopen(ftest,"r"))==NULL)
  {
   printf("This file %s is not exist",ftest);
   goto test;
  }
  fscanf(fpTest,"%d",&testnum);
        printf("The result of you testing is:\n");
  for(p=0;p<testnum;p++)
  {
  printf("%d : ",p+1);
  for(h=0;h<nInputNodes;h++)
   fscanf(fpTest,"%f",&out0[0][h]);


        for (h=0;h<nHiddenNodes;h++)
        {
        float  sum=w1[h][nInputNodes];
           for (i=0;i<nInputNodes;i++)
               sum+=w1[h][i]*out0[0][i];
           out1[0][h]=1.0/(1.0+exp(-sum));
        }
           
        for(j=0;j<nOutputNodes;j++)
        {
     float sum=w2[j][nHiddenNodes];
           for(h=0;h<nHiddenNodes;h++)
       sum+=w2[j][h]*out1[0][h];
           out2[0][j]=1.0/(1.0+exp(-sum));
     printf("%f ",out2[0][j]);
  }
  printf("\n");
  }
   }
  } 
  MatrixFree(out0,  nPatterns);
  MatrixFree(out1,  nPatterns);
  MatrixFree(delta1,nPatterns);      
  MatrixFree(delw1, nHiddenNodes);                           
  MatrixFree(w1,    nHiddenNodes);
  MatrixFree(out2,  nPatterns);
  MatrixFree(delta2,nPatterns);
  MatrixFree(delw2, nOutputNodes);
  MatrixFree(w2,    nOutputNodes);
  MatrixFree(target,nPatterns);
  
  }


  /*---------------变量分配空间------------------------*/
  void VectorAllocate(VECTOR *vector,int nCols)
  {
     if((*vector=(VECTOR)calloc(nCols,sizeof(float)))==NULL)
      {
        fprintf(stderr,"Sorry!Not enough memory for nodes\n");
        exit(1);
      }
  }
  void AllocateCols(PFLOAT matrix[],int nRows,int nCols)
  {
     int i;
     for(i=0;i<nRows;i++)
       VectorAllocate(&matrix[i],nCols);
  }
  void MatrixAllocate(MATRIX *pmatrix,int nRows,int nCols)
  {
     if((*pmatrix=(MATRIX)calloc(nRows,sizeof(PFLOAT)))==NULL)
     {
       fprintf(stderr,"Sorry!Not enough memory for nodes\n");
       exit(1);
     }
     AllocateCols(*pmatrix,nRows,nCols);
  }
  void MatrixFree(MATRIX matrix,int nRows)
  {
     int i;
     for(i=0;i<nRows;i++)
        free(matrix[i]);
     free(matrix);
  }
================

BP神经网络-- C语言实现



C语言来实现一个简单的单隐藏层的BP神经网络,对于其他C类语言(C#、JAVA等)只需对本文中的代码稍作修改即可移植。
 


一些数据的定义
   首先,我们介绍些下文中描述的程序里面的一些重要数据的定义。


#define Data  820
#define In 2
#define Out 1
#define Neuron 45
#define TrainC 5500
      Data 用来表示已经知道的数据样本的数量,也就是训练样本的数量。In 表示对于每个样本有多少个输入变量; Out 表示对于每个样本有多少个输出变量。Neuron 表示神经元的数量,TrainC 来表示训练的次数。再来我们看对神经网络描述的数据定义,来看下面这张图里面的数据类型都是 double 型。


      d_in[Data][In] 存储 Data 个样本,每个样本的 In 个输入。d_out[Data][Out] 存储 Data 个样本,每个样本的 Out 个输出。我们用邻接表法来表示 图1 中的网络,w[Neuron][In]  表示某个输入对某个神经元的权重,v[Out][Neuron] 来表示某个神经元对某个输出的权重;与之对应的保存它们两个修正量的数组 dw[Neuron][In] 和 dv[Out][Neuron]。数组 o[Neuron] 记录的是神经元通过激活函数对外的输出,OutputData[Out]  存储BP神经网络的输出。


 


程序的执行过程
         在这里,先不考虑具体函数的执行细节,从大体上来介绍程序的执行过程。用伪代码来表示,具体的内容后面一步步介绍,如下:




主函数main{


    读取样本数据 readData();
       初始化BP神经网络  initBPNework(){


            包括数据的归一,神经元的初始化 w[Neuron][In]、v[Out][Neuron]等;
        }
        BP神经网络训练 trainNetwork(){
            do{
                for(i 小于 样本容量 Data){
                    
            计算按照第 i 个样本输入,产生的BP神经网络的输出 computO(i);
                    累记误差精度;
                    反馈调节BP神经网络中的神经元,完成第 i 个样本的学习 backUpdate(i);
                }
            }while(达到训练次数 或者 符合误差精度);
        }


        存储训练好的神经元信息  writeNeuron();
        用一些数据来测试,训练出来的BP神经网络的结果;
        return 0;
}


       以上是处理的流程,对于读取数据、保存数据之类的处理本文将略去这方面内容,突出主干部分。


 


初始化BP神经网络
      初始化主要是涉及两个方面的功能,一方面是对读取的训练样本数据进行归一化处理,归一化处理就是指的就是将数据转换成0~1之间。在BP神经网络理论里面,并没有对这个进行要求,不过实际实践过程中,归一化处理是不可或缺的。因为理论模型没考虑到,BP神经网络收敛的速率问题,一般来说神经元的输出对于0~1之间的数据非常敏感,归一化能够显著提高训练效率。可以用以下公式来对其进行归一化,其中 加个常数A 是为了防止出现 0 的情况(0不能为分母)。


       y=(x-MinValue+A)/(MaxValue-MinValue+A)


      另一方面,就是对神经元的权重进行初始化了,数据归一到了(0~1)之间,那么权重初始化为(-1~1)之间的数据,另外对修正量赋值为0。实现参考代码如下:




void initBPNework(){


    int i,j;
   /*
    找到数据最小、最大值
   */
    for(i=0; i<In; i++){
        Minin[i]=Maxin[i]=d_in[0][i];
        for(j=0; j<Data; j++)
        {
            Maxin[i]=Maxin[i]>d_in[j][i]?Maxin[i]:d_in[j][i];
            Minin[i]=Minin[i]<d_in[j][i]?Minin[i]:d_in[j][i];
        }
    }
    for(i=0; i<Out; i++){
        Minout[i]=Maxout[i]=d_out[0][i];
        for(j=0; j<Data; j++)
        {
            Maxout[i]=Maxout[i]>d_out[j][i]?Maxout[i]:d_out[j][i];
            Minout[i]=Minout[i]<d_out[j][i]?Minout[i]:d_out[j][i];
        }
    }
    /*
    归一化处理
    */
    for (i = 0; i < In; i++)
        for(j = 0; j < Data; j++)
            d_in[j][i]=(d_in[j][i]-Minin[i]+1)/(Maxin[i]-Minin[i]+1);
    for (i = 0; i < Out; i++)
        for(j = 0; j < Data; j++)
            d_out[j][i]=(d_out[j][i]-Minout[i]+1)/(Maxout[i]-Minout[i]+1);
    /*
    初始化神经元
  */
    for (i = 0; i < Neuron; ++i)    
        for (j = 0; j < In; ++j){    
            w[i][j]=(rand()*2.0/RAND_MAX-1)/2;
            dw[i][j]=0;
        }
    for (i = 0; i < Neuron; ++i)    
         for (j = 0; j < Out; ++j){
             v[j][i]=(rand()*2.0/RAND_MAX-1)/2;
              dv[j][i]=0;
         }
}


 
BP神经网络训练
      这部分应当说是整个BP神经网络形成的引擎,驱动着样本训练过程的执行。由BP神经网络的基本模型知道,反馈学习机制包括两大部分,一是BP神经网络产生预测的结果,二是通过预测的结果和样本的准确结果进行比对,然后对神经元进行误差量的修正。因此,我们用两个函数来表示这样的两个过程,训练过程中还对平均误差 e 进行监控,如果达到了设定的精度即可完成训练。由于不一定能够到达预期设定的精度要求,我们添加一个训练次数的参数,如果次数达到也退出训练。实现参考代码如下:


 




void  trainNetwork(){
    int i,c=0;
    do{
        e=0;
        for (i = 0; i < Data; ++i){
            computO(i);
            e+=fabs((OutputData[0]-d_out[i][0])/d_out[i][0]);
            backUpdate(i);
        }
        //printf("%d  %lf\n",c,e/Data);
        c++;
    }while(c<TrainC && e/Data>0.01);
}


 


        其中的函数,computO(i) (O是output缩写)计算BP神经网络预测第 i 个样本的输出也就是第一个过程。backUpdate(i) 是根据预测的第 i 个样本输出对神经网络的权重进行更新,e用来监控误差。


    


================

0 0
原创粉丝点击