一、k-NN法
这种概率密度函数估计的方法是这样的:在以特征向量x为中心的一个邻域里,固定落入邻域中的样本的个数k(n)。这可以通过下面的方法实现:在一个合适的距离尺度下,逐渐增大包围x点的区域体积,直到有k个样本点落入这个区域中。这就是x周围离它最近的k(n)个样本。在这k(n)个样本中,数量最多的种类就可以看作样本x的类型。当然k的选取也很重要。随着k的增加,k-NN的错误率将逐渐贴近贝叶斯错误率。
在进行k-NN聚类之前首先要对Gabor变换的结果数据归一化,以确保结果运算的有效性。具体说就是让每个测量数据的取值在[0, 1]或[-1, 1]之间。举例来说:假设有两类数据,一类数据的中心位于坐标(-1, 10000)处,另一类数据的中心位于(0,9996)处,有一待测样本,坐标值是(-1,9997),它应当属于拿类呢?如果计算欧氏距离的化,该样本属于第二类。但仔细分析可知,该样本应当属于第一类,因为纵坐标的值过于大(其实待测样本的纵坐标只比训练样本有万分之几的变化,完全可以忽略不计)。现在我们将纵坐标缩小10000倍,归一到[-1, 1]上,则两类待测样本坐标变为(-1,1)和(0,0.9996),待测样本坐标为(-1,0.9997),显然属于第一类。
至于k-NN的代码实现相对来说比较简单。我采用了链表的方式。链表为有序定长的链表,设x为待测样本,依次计算x与p个训练样本的距离(我采用的是欧氏距离)。将该结果依次和链表中各元素比较,如果小于某一节点,则将新结果插入到该节点之前,并删除链表中最后一个节点。这样,当完成x与所有p个训练样本的距离计算后,链表中就记录了和它最近的k个样本。我们通过判别这k个样本中数量最多的种类完成对x类型的估计。
代码相对简单,这里就不再占用空间贴代码了。下面我们看看SVM分类。
二、SVM
SVM分类器通常具有较高的分类精度。我这里不想过多的去说SVM是怎么回事,只是提供一种使用SVM进行判别的方法。我使用的是开源的LibSVM实现SVM分类。Google上输入LIBSVM可以很容易的找到代码下载。我使用的是C#版(不过是2.6版),也可以使用C++的2.81版。下面我说说如何使用2.81版中带的编译好的程序完成聚类工作。该版本支持多类判别。
1、数据准备工作
首先对Gabor变换结果进行处理,生成符合SVM处理规范的文本格式。关于格式的更多说明可以参考软件使用手册。另外此步可以不用归一化,因为LibSVM工具中提供了scale工具,可以自动完成数据的归一化处理工作。
2、程序配置工作
LibSVM 2.81版下载下来后并不能直接操作,还需要一些辅助工作,否则在默认判别的方式下工作判别精度可能非常低。关于此方面的更多内容可以参考《A Practical Guide to Support Vector Classification》一文,该PDF文档可以从LibSVM的网站上下载到。
在使用LibSVM之前首先要安装Pathon,Pathon 2.4可以从Pathon的网站上下载到。
紧接着就是需要装“pgnuplot.exe”,LibSVM使用它完成参数搜索时的绘图工作,该程序没有包含在LibSVM 2.81版的压缩包中,需要自己到网上搜索并下载。另外在LibSVM 2.81中grid.py代码里默认pgnuplot.exe的路径是“c:\tmp\gnuplot\bin\pgnuplot.exe”,你可以将“pgnuplot.exe”放到该路径下或修改grid.py代码指向你自己的路径。
所有这些准备工作完成后,就可以进行SVM分类工作了。
3、SVM分类
使用SVM分类可以执行“libsvm-2.81\tools”目录下的easy.py程序,该程序提供了一套默认的、精度较高的SVM分类算法。
在DOS窗口下输入:C:\Python\Python easy.py Train.txt Test.txt就可以利用Train.txt中的数据进行训练,然后对Test.txt中的数据进行判别。
*** 结果 ***
本人采集了多人的笔迹,经过纹理制作、Gabor变换提取出了相应的特征。在使用KNN与SVM对待测样本进行聚类时均取得了较高的识别精度。通过优化,10人笔迹的测试精度可以达到100%,效果还是很不错的。