一、介绍
人工神经网络(Artificial Neural Network,ANN)简称神经网络(Neural Network,NN)或类神经网络,是一种模仿生物神经网络的结构和功能的数学模型或计算模型,用于对函数进行估计或近似。
MLP神经网络是一种基于神经网络、动态的分类器。MLP分类器使用神经网络来推导能将类别区分开来的超平面。使用超平面进行分割,如果只有两个类别,超平面会将各特征向量分为两类。如果类别的数量不止两个,就应当选择与特征向量距离最大的那个超平面作为分类平面。神经网络可能是单层的,也可能是多层的。如果特征向量不是线性可分的,则可以使用更多层的神经网络。
MLP神经网络主要由输入层、隐藏层、输出层构成。当隐藏层只有一层时,该网络为两层神经网络,因为输入层未做任何变换,可以不看做单独一层。实际中,网络输入层的每个神经元代表了一个特征,输入层个数代表了分类类别个数,而隐藏层层数以及隐藏层神经元由人工设定。
多层神经网络的典型结构是一层输入单元层、一层或多层隐藏节点层、一层输出单元层。理论上如果隐藏层的节点数足够多,那么只需要一层隐藏层就可以解决所有分类问题。
在神经网络的每一个节点或者处理单元内,都有算子根据前一层的计算结果来计算特征向量的线性相关关系。MLP分类器可以用于通用特征的分类、图像分割、OCR等。
设计一个神经网络时,输入层与输出层的节点数往往是固定的,隐藏层则可以自由指定。神经网络结构图中的拓扑与箭头代表着预测过程时数据的流向。结构图中的每个连接线对应一个不同权重(权值),这是需要训练得到的。
x0~xn为神经元输入参数,w0~wn为神经元连接线上的权值,∑和激活函数为神经元的输入和输出之间的函数关系。
二、神经网络的创建和应用
1、定义神经网络结构
神经网络的创建,首先需要确定输入的特征数量和输出的分类类别,还要确定神经网络的结构,即指定输入层、隐藏层、输出层的大小。在设计一个神经网络时,输入层的节点数需要与特征的维度匹配,输出层的节点数要与目标的维度匹配。而中间层的节点数,却是由设计者指定的。其中节点数设置的多与少,会影响到整个模型的效果。一般根据经验来设置,可以预先设定几个可选值,进行切换来查看整个模型的最终效果。
2、神经网络训练
创建神经网络关键是通过训练过程,来寻找合适的权重矩阵
①采集训练样本,提取训练的特征值,并对其类别进行标注。
②给神经网络权重矩阵赋一个初始值,用这个矩阵对训练样本进行预测,通过损失函数(损失函数是计算输出值与真实值之间误差的函数,可以有不同的定义方式),观察预测结果和训练样本的标注值的差,根据结果来更新权重矩阵,直到预测结果和实际结果相差最小,即损失函数的值最小时停止。此时得到的权重矩阵的模型就是训练好的神经网络模型了。
3、应用神经网络进行预测和分类
提取预测的样本的特征,输入到神经网络的输入层,神经网络运行后,在输出层得到预测或分类结果。
三、常见的神经网络类型
1、BP神经网络
2、RBF(径向基)神经网络
3、自组织神经网络
4、反馈神经网络
四、Halcon中MLP神经网络的算子
Classification / Neural Nets 创建基于神经网络的MLP分类器,可以用于分类或者进行回归运算。包括3层,一层输入层,一层隐藏单元层,一层输出层。 create_class_mlp( : : NumInput, NumHidden, NumOutput, OutputFunction, Preprocessing, NumComponents, RandSeed : MLPHandle) NumInput:输入参数,输入层的神经元数量,指明用于训练和分类的特征空间的维度数(例如圆度,矩形度、面积等有明显特征的,可以来区分实际图像中的内容)。默认20,建议值【 1, 2, 3, 4, 5, 8, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100】,范围≥1。 NumHidden:输入参数,表示神经网络中隐藏层的神经元数量。默认10,建议值【1, 2, 3, 4, 5, 8, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 150】,范围≥1。 该值会明显影响分类结果,该值的取值范围与NumInput和NumOutput相似。NumHidden值取的越小,用于分类的超平面就越简单,有时能得到更理想的结果;如果该值取得太大,反而会有过拟合的可能,如可能会把噪声点也用于训练分类器的边界,这样的分类时,如果待检测对象不包含这些非关键的点,有可能会分类失败。 NumOutput:输入参数,表示输出层的神经元数量(意思就是实际计算后的结果会是哪几个)。默认5,建议值【1, 2, 3, 4, 5, 8, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 150】,范围≥1。 OutputFunction:输入参数,表示输出层的需要使用哪个函数。默认【'softmax'】,列表【'linear', 'logistic', 'softmax'】。 绝大多数情况下,输出函数都可以选'softmax'。'logistic'用于处理多个逻辑独立的属性的分类问题,这种情况非常少见。'linear'用于最小二乘法,而不是用于分类,因此可以忽略。 Preprocessing:输入参数,特征值预处理方法,即在训练和分类之前对特征向量进行预处理。预处理可以加快训练或者分类的速度,有时也有助于提升分类的准确率。默认'normalization'。 列表【 'canonical_variates'只能在OutputFunction参数设置为'softmax'时使用,用于特征向量线性可分的情况。这种方法也称为线性判别分析法,它将特征向量归一化,并对归一化特征向量进行变换,使其在某个特征空间的所有分类中都得到一个相关关系。同时,这种变量最大化区分了每个分类的均值,在特征向量为线性可分时推荐使用。 'none'不会进行任何预处理。 'normalization'大多数情况下选择此项,表示将特征向量归一化为0到1之间的数。这种处理既不会改变特征向量的长度,又能够有效提升速度,因此是预处理的首选。 'principal_components'如果特征向量是和高度相关的,并且又希望处理速度非常快,可以选择此项。这种方式基于主成分分析法,它降低了特征向量的维度,对特征向量进行归一化和额外的变换,使协方差矩阵变成对角矩阵。这样做可以减少数据量,且不会损失大量的信息。 】。 NumComponents:输入参数,特征值预处理参数,即被变换的特征个数 。默认10,建议值【 1, 2, 3, 4, 5, 8, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100】,范围≥1。 在Preprocessing选择'canonical_variates'或'principal_components'时使用此项。因为这两种预处理方法可能会减少特征空间的维度,此参数就表示减少后的特征向量的维度数。 RandSeed:输入参数,神经网络初始参数随机数。用于初始化MLP中的权重值,该值表示随机种子数。默认42。 MLPHandle:输出参数,输出神经网络句柄。用于后续对分类器进行各种操作,如调用、修改、删除等。 |
Classification / Neural Nets 将单个样本添加到MLP分类器中。 由于基于多层神经网络的MLP分类器需要大量的训练样本,因此在训练时,可以连续调用此算子,将不同的训练样本添加进分类器。 add_sample_class_mlp( : : MLPHandle, Features, Target : ) MLPHandle:输入参数,神经网络句柄。用于把样本添加进指定的分类器。 Features:输入参数,准备要训练样本的特征值。该向量类似于一个数组,其中的每一个值表示一种特征,其维度应当与create_class_mlp算子中OutputFunction的值相同。如果这个算子用于分类,相应的create_class_mlp算子中NumInput的值相同。这里特征向量是real类型,如果要传入的特征是int类型的,需要先进行转换。 Target:输入参数,训练样本所属类别。其维度数应当与create_class_mlp算子中NumOutput的值相同。如果这个算子用于分类,相应的create_class_mlp算子中OutputFunction值为'softmax',那么Target向量的取值可以为0.0或者1.0。这其中只有一个元素取1.0,该元素的序号表示目标所属的种类,确切来说,表示的是某个分类的ID代号。OutputFunction值为其他两种情况的,因为与分类关联不大。 |
Classification / Neural Nets 将训练样本添加进分类器之后,接下来将进行样本的训练。训练MLP模型,首先要确定MLP神经网络的一些参数,因此可能需要大量的样本。这是一个复杂的训练过程。 train_class_mlp( : : MLPHandle, MaxIterations, WeightTolerance, ErrorTolerance : Error, ErrorLog) MLPHandle:输入参数,MLP神经网络的句柄。该句柄与之前的create_class_mlp算子和add_sample_class_mlp算子中的MLPHandle句柄是一脉相承的,用于分类器的标识和调用。 MaxIterations:输入参数,优化算法的最大迭代次数。默认200,建议值【 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300】。多数情况下,算法会在迭代了MaxIterations次后结束,因此该值设置100~200是够用的。 WeightTolerance:输入参数,两次优化迭代后得到的权值差的阈值,即优化算法的两次迭代之间的权重差异阈值。如果权重小于该值,优化算法将终止。默认1.0,一般无需改变。建议值【1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001】,范围≥1.0e-8。 ErrorTolerance:输入参数,两次优化迭代后神经网络输出值的平均误差的阈值,即优化算法的两次迭代之间的误差均值的阈值。如果均值小于该值,优化算法也会终止。默认0.01,一般无需改变。建议值【1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001】,范围≥1.0e-8。 Error:输出参数,在最佳权重下训练后得到的神经网络输出值的平均误差。 ErrorLog:输出参数,每次迭代的错误日志。该参数将MLP的训练数据的平均误差作为迭代次数返回。该参数用于判断是否应使用不同的RandSeed对同样的样本进行二次训练。如果把ErrorLog看作一个函数曲线,那它应当在开始时急剧下降,然后越来越平稳。如果ErrorLog从头到尾都走势陡峭,那么通常需要重新调用一次train_class_mlp算子。 |
Classification / Neural Nets 用于评估一个特征向量属于某个类别的概率。如果只有两个可能的类,则不需要评估,因为在最终分类时也需要计算特征向量属于某个分类的概率。 evaluate_class_mlp( : : MLPHandle, Features : Result) MLPHandle:输入参数,MLP神经网络分类器的句柄,即train_class_mlp算子创建的句柄。 Features:输入参数,输入的待评估的特征向量。这里的特征向量应当和add_sample_class_mlp算子中的训练样本的特征向量相同。 Result:输出参数,有神经网络MLP评估后输出的结果。这里的结果取决于create_class_mlp算子中OutputFunction参数的值。如果该参数的值是softmax,则返回Result就是属于每个分类的概率值,这是大多数情况;如果该参数的值不是softmax,则属于比较少见的情况或者是与分类无关的情况。 |
Classification / Neural Nets (完成了分类器的创建和训练后)对未知对象进行分类了。使用训练过程中学习到的分类边界对特征向量进行分类。 备注:只有create_class_mlp算子中OutputFunction参数值是softmax时,才会用到该算子。 classify_class_mlp( : : MLPHandle, Features, Num : Class, Confidence) MLPHandle:输入参数,输入神经网络句柄。即create_class_mlp算子创建的句柄。句柄包含分类器所需的全部分类信息。 Features:输入参数,输入训练样本的特征向量(值)。这里的特征向量应当和add_sample_class_mlp算子中的训练样本的特征向量相同。 Num:输入参数,识别的目标数,即指定要寻找的最佳分类的数量。如果指定1,表示只寻找概率分数最高的那个类别;如果为2,表示返回两个概率比较高的分类。如果类别重叠时可以这样指定。 Class:输出参数,识别目标类型,即返回MLP分类器对特征向量的分类结果。这个结果的数量与Num参数值有关。如果Num设定为1,那么就返回一个最高概率对应的分类;如果Num为2,那么Class的第一个值为概率最高的分类,第二个值为概率第二高的分类。 Confidence:输出参数,分类的置信度。注意:由于这里采用MLP神经网络的计算方式,因此置信度的值可能受异常值的影响比较大。 |
Classification / Neural Nets 释放MLP分类器的内存资源。(MLPHandle变成无效) clear_class_mlp( : : MLPHandle : ) |
read_image(Image, 'D:/Documents/Desktop/2000.png')
rgb3_to_gray(Image, Image, Image, ImageGray)
threshold(ImageGray, Region, 0, 128)
connection(Region, ConnectedRegions1)
closing_circle(Region,RegionClosing, 10)
connection(RegionClosing, ConnectedRegions)
intersection(ConnectedRegions, ConnectedRegions1, T1)
sort_region(T1,SortedRegions,'character','true', 'row')
count_obj(SortedRegions, Number)
TrainingNames:=['江','沪','赣','鄂']
*创建MLP分类器
create_class_mlp(10,8,4,'softmax', 'normalization', 3, 42, MLPHandle)
*10对应的是[Areareal,EulerNumberreal,Roundness,Sides,PSI1,PSI2,PSI3,PSI4,NumConnectedreal,NumHolesreal]这10个参数,8是隐藏参数,4是['江','沪','赣','鄂']这4个参数
*利用循环江10个参数放到Features元组中。
for i:=1 to Number by 1
select_obj(SortedRegions, YZ, i)
dev_display(YZ)
*在这里元组只接受real类型,所以这里要对int类型进行格式转换
euler_number(YZ,EulerNumber)
tuple_real(EulerNumber,EulerNumberreal)
area_holes(YZ, Area)
tuple_real(Area,Areareal)
connect_and_holes(YZ, NumConnected, NumHoles)
tuple_real(NumConnected,NumConnectedreal)
tuple_real(NumHoles,NumHolesreal)
roundness(YZ,Distance, Sigma, Roundness, Sides)
moments_region_central_invar(YZ,PSI1, PSI2, PSI3, PSI4)
Features:=[Areareal,EulerNumberreal,Roundness,Sides,PSI1,PSI2,PSI3,PSI4,NumConnectedreal,NumHolesreal]
add_sample_class_mlp(MLPHandle,Features,i-1)
endfor
stop()
K:=TrainingNames[0]
*开始对上面的样本进行训练
train_class_mlp(MLPHandle, 200, 1, 0.01, Error, ErrorLog)
*释放分类器
clear_samples_class_mlp(MLPHandle)
*读取实例图像,并整理参数放入Features元组中
read_image(Image2,'D:/Documents/Desktop/江.png')
rgb1_to_gray(Image2, GrayImage2)
threshold(GrayImage2,Region2,0,128)
euler_number(Region2,EulerNumber)
tuple_real(EulerNumber,EulerNumberreal)
area_holes(YZ, Area)
tuple_real(Area,Areareal)
connect_and_holes(YZ, NumConnected, NumHoles)
tuple_real(NumConnected,NumConnectedreal)
tuple_real(NumHoles,NumHolesreal)
roundness(Region2,Distance2,Sigma2, Roundness2, Sides2)
moments_region_central_invar(Region2,PSI11, PSI21, PSI31, PSI41)
Features:=[Areareal,EulerNumberreal,Roundness,Sides,PSI11,PSI21,PSI31,PSI41,NumConnectedreal,NumHolesreal]
*对新的Features元组里的内容进行分类并显示,这里的3一般为1,3是为了对结果排序进行查看并修改程序是否理想
classify_class_mlp(MLPHandle,Features,3,Class,Confidence)
disp_message(200000,TrainingNames[Class],'window',12, 12, 'black', 'true')
*结果:赣不怎对的上,懒得折腾了