Halcon学习笔记之支持向量机(一)
例程:class_overlap_svm.hdev
说明:这个例程展示了如何用一个支持向量机来给一幅二维的图像进行分类。使用二维数据的原因是因为它可以很容易地联想成为区域和图像。本例程中使用了三个互相重叠的类(由二维平面三个不同颜色的像素点集组成)。三类不同颜色的像素点作为样本,将那些样本代入支持向量机进行训练。选取像素在二维平面的坐标作为特征向量,使支持向量机对这个二维特征区域进行分类。在结果中我们可以看到,支持向量机会将特性区域(也就是整个二维平面)中每一个的像素点分割为这三个类中的一类。因此,即使远离受训练的样本区域的像素点也将其归类到三个类别之一。
在本例程中最主要的就是展示不同的误差容忍参数Nu对分类的影响。参数Nu的可以理解成支持向量机对样本分类过程中存在重叠的部分分类时的判定错误样本的容忍比率。在分类时,样本质量并不一定理想,部分样本可能落入了本该属于其他类型的特征空间内,如图1中重叠部分的样本。针对这部分重叠区域,是无法对其进行很好的分类的,部分样本最终会作为错误的样本点被划分到其它区域中,如下图中三张分类效果图,无论分类好坏,重叠区域的部分样本都可能落入其它类型的空间。其中参数Nu就是对错误样本所占比例的容忍的上限,Nu取值太小或者太大对最终分类的效果都会造成影响,Nu的取值需要大于错误样本所占的比例。
下图1中展示了三个不同类型的训练样本点集在二维的特征空间的分布状况,从图中可以看到在图像中心位置部分,三类样本有重叠,Nu取值的关键就在于对这部分样本的处理。
图1.红、绿、蓝三个训练样本集
下面三张图展示了Nu取值0.01、0.18和0.25时的效果图。在训练过程中,三个样本集训练的参数都是相同的,因此区别就在于样本集的参数设置。图2中Nu选择太小,导致完全错误分类;图3中Nu值偏小,导致二维特征空间划分时少量的错误样本干扰了整个空间的分类;图4中参数选择刚刚好,二维特征空间分类效果也很完美。
在这里,很多人会问,如果误差容忍选取一个较小值,为何最终分类结果中特征空间划分效果反而差,样本落入其它空间的比例更多。这里仅说明一下我的个人理解,如有错误,希望大神指正:
从Halcon的代码中我们可以看到,支持向量机学习有两个过程——构造和训练。在构造过程中,Nu值作为对样本的优化负责选取三类样本中相对独立的成分,部分有争议的样本将根据参数Nu在此过程中被排除在外,不作为后面训练时的样本。因此,在参加训练之前,Nu作为对样本的优化参数,起到分离错误样本的作用。当然,如果Nu取值太大,也许在这个筛选过程中,提取到的样本并不能够有效表示该类样本空间,那么最终在分类时也会造成错误。
而在训练过程中,支持向量机将根据训练参数求最优平面划分特征空间。如果训练样本理想,那么求得的最优平面就能很好划分,如图4所示;而如果训练样本本身存在很大争议,那么在训练过程中,算法无法很简单地求得一个最优解,那么只能将原本低维的样本点映射到高维进行分类,如果本身样本存在很大问题,那么即使最终求得的解还是无法正确划分特征空间。如图1,由于本身样本的问题,导致求得的最终解在实际识别效果中表现糟糕。
图2.Nu参数取值0.01时的分类效果
图3.Nu参数取值0.18时的分类效果
图4.Nu参数取值0.25时的分类效果
*下面部分为对Hdevelop环境的设置,这里不着重介绍 dev_close_window() dev_open_window(0,0,600,600,’black’,WindowHandle) dev_set_part(0,0,199,199) get_system(‘operating_sysytem’,OS) if(OS{0:2} = ‘Win’) set_font(WindowHandle,’-Courier New-18-*-*-*-*-1-’) //设置输出文本的字体 else set_font(WindowHandle,’-adobe-courier-bold-r-normal—25-*-*-*-*-*-*-*’) endif dev_updata_pc(‘off’) dev_updata_window(‘off’) dev_updata_var(‘off’) *以下代码用于构造三个样本集:构造三个样本区域;构造白噪声图像;分割白噪声图像;分别与样本区域进行与运算得到样本集 gen_ellipse(RegionClass1,60,60,rad(-45),60,40) gen_ellipse(RegionClass2,70,70,130,rad(-145),70,30) gen_ellipse(RegionClass3,140,100,rad(100),55,40) //产生一个椭圆。 //参数说明:产生的椭圆(RegionClassx) //椭圆中心坐标(140,100) //椭圆长轴的方向(rad(100)) //椭圆的长轴(55) //椭圆的短轴(40) gen_image_const(Image,’byte’,200,200) //一幅固定大小固定灰度的图像 //参数说明:生成的图片(Image) //图片格式(’byte’) //图片大小(200,200) add_noise_white(Image,ImageNoise1,60) add_noise_white(Image,ImageNoise2,60) add_noise_white(Image,ImageNoise3,60) //加入白噪声,幅度为60 threshold(ImageNoise1,RegionNoise1,40,255) threshold(ImageNoise2,RegionNoise2,40,255) threshold(ImageNoise3,RegionNoise3,40,255) //利用全局阈值分割图像 intersection(RegionClass1,RegionNoise1,SampleClass1) intersection(RegionClass1,RegionNoise2,SampleClass2) intersection(RegionClass1,RegionNoise3,SampleClass3)//计算两个区域的交叉(区域的与运算) //参数说明:两个区域(RegionClassx,RegionNoisex) //交叉的区域(SampleClassx) *用三种颜色显示三个不同类型的样本集 dev_clear_window() dev_set_color(‘red’) dev_display(SampleClass1) dev_set_color(‘green’) dev_display(SampleClass2) dev_set_color(‘blue’) dev_display(SampleClass3) dev_set_color(‘white’) set_tposition(WindowHandle,5,5) //设置文本的光标位置 write_string(WindowHandle,’Training samples of the 3 classes ’)//在屏幕的已设定的光标位置输出字符串 stop()
classify_2d_feature_space(SampleClass1,SampleClass2,SampleClass3,RegionClass1,RegionClass2,RegionClass3,WindowHandle,’rbf’,0.05,0.01)//利用支持向量机进行分类,这是一个外部过程,具体不进行详细介绍 set_tposition(WindowHandle,188,5) //光标位置(188,5) write_string(WindowHandle,’Nu = 0.01 : Wrong classification’) stop()
classify_2d_feature_space(SampleClass1,SampleClass2,SampleClass3,RegionClass1,RegionClass2,RegionClass3,WindowHandle,’rbf’,0.05,0.18)//同样是利用SVM进行分类,只是Nu参数改为0.18 set_tposition(WindowHandle,188,5) write_string(WindowHandle,’Nu = 0.18 : Overfitting’) stop()
classify_2d_feature_space(SampleClass1,SampleClass2,SampleClass3,RegionClass1,RegionClass2,RegionClass3,WindowHandle,’rbf’,0.05,0.25)//同样是利用SVM进行分类,只是Nu参数改为0.25 set_tposition(WindowHandle,188,5) write_string(WindowHandle,’Nu = 0.25 : ’Good generalization’)