考虑二维平面,找出一条线将两类样本划分开,其中最好的一条是红线(因为它使得两类样本的间隔r更大),这一条线对于不安分的样本点扰动容忍性更强。
推广到n维空间,存在一条超平面。截距为b(原点到超平面的距离),法向量为w(垂直于超平面的n维向量)。
根据点到超平面的距离公式,距离r为
假设超平面能使样本正确分类,则样本集D中有一点(xi,yi=+1)位于超平面上面,那么超平面可以向上平移1个距离,得到上边界
同样的样本集D中有一点(xi,yi=-1)位于超平面下面,那么超平面可以向下平移1个距离,得到下边界
上边界和下边界之间的距离如果达到最大,即说明中间这一条超平面就是选择正确的那一条分类平面
而我们从样本集D中找到的这两个点(xi,yi=+1)和(xi,yi=-1)能够使得距离r最大,则这两个点被称为“支持向量”,找到这些样本点之后去计算得到w和b得到的超平面被称为“支持向量机”。其中两个不同类的点到超平面的距离值和为
接下来就是一个找最大距离的规划问题
可以转化为我们更加熟悉的二次规划问题
这是一个典型的凸二次规划问题,这里用对偶问题求解,用拉格朗日乘子法得到其对偶问题,首先其拉格朗日函数为
L分别对w和b求偏导,当w和b的偏导为0可求w的表达式
可以看到w可以由y、x、α得到,再将w带回拉格朗日函数消去w和b,再将约束变性,就求到其对偶问题
其中约束条件和目标函数中只有α这一个未知参数,求解出α后再带回w表达式可以将w和b都求出来,同时α带回原问题的约束条件并整合对偶问题的约束条件,得到最终超平面公式
观察约束条件,对于任意的样本点(xi,yi),如果αi=0,则点(xi,yi)在超平面公式f(x)中无效即对分类平面的产生不会有影响。如果αi>0,则点(xi,yi)根据约束3必有yi*f(xi)=1。这说明分类平面的产生只与支持向量有关。
拉格朗日乘子法和KKT条件:
(1)无约束
min f(x)
通常对f(x)求极值,获取最优质候选,再在候选值中验证。如果是凸函数可以保证极值点得到最优质。
(2)等式约束
min f(x)
s.t. h(x)=0 ;i=0,2..,n
通常使用拉格朗日乘子法,求L(a,x)=f(x)+a*h(x),分别对参数a、b求导
(3)不等式约束
min f(x)
s.t. h(x)=0 ;i=0,2..,n
g(x)<=0;i=0,2..,n
通常使用拉格朗日乘子法,求L(a,x,b)=f(x)+a*g(x)+b*h(x),其中kkt条件要求最优值满足下列条件
L(a,b,x)对x求导为0
h(x)=0
a*g(x)=0
直接求三个方程就能取到最优解
Svm模型求解:
回到求解之前,其对偶问题为
这是一个典型的二次规划问题,用常规方法求解计算规模正比于训练样本数,用更加高效的smo算法求解。
Smo算法:
需要求解的最优化问题
其中目标函数变量为(α1,α2,α3,.....,αn),每个实例(xi,yi)对应一个αi。
其基本思路是:如果所有变量(α1,α2,α3,.....,αn)都满足此最优化问题的KKT条件,那么这个最优化问题的解就得到了。
SMO算法的目标是求解满足KKT条件的(α1,α2,α3,.....,αn)。方法是选择两个变量,固定其他变量,针对这两个变量构建一个二次规划的子问题。
这个二次规划子问题关于这两个变量的解更接近原始二次规划问题的解,因为这会使得原始二次规划问题的目标函数值变得更小。
二次规划子问题有两个变量,一个是主动变量,其为违反KKT条件最严重的那一个,另一个被动变量,由主动变量依据约束条件自动确定。
如此,SMO算法将原问题不断分解为子问题并对子问题求解,进而达到求解原问题的目的。
观察约束条件:
可知α1和α2可以相互表示,则固定 α3~ αn,其二次规划问题为:
首先分析约束条件,用α2表示α1,找出α1和α2满足的取值范围,在此范围内求解α2的最优值也即是得到α1的最优值。这样一对α就得到一次更新。
然后我们寻找下一对α,在寻找时,SMO先选取违背KKT条件程度最大的变量,第二个变量选择使目标函数值增大最快的变量。
SMO使用了一个启发式的方法,当确定了第一个变量后,选择使两个变量对应样本之间最大的变量作为第二个变量。
直观来说,更新两个差别很大的变量,比起相似的变量,会带给目标函数更大的变化。
间隔的定义也可以借用偏差函数:
我们要找的i也就是使α对于来说使|Ei-Ej|最大的αj
核函数:
假如线性不可分,正负样本相互交叉,即找不到任何一条平面将样本分类,解决的方法就是用一定规则把这些样本映射到更高纬的特征空间中,再寻找分类超平面。核函数就是这一类映射函数,常用的核函数有线性核函数、多项式核函数、高斯核函数、径向量核函数、sigmoid核函数。
线性核函数LINEAR:
多用于线性可分情况,输入空间和特征空间维数一致,参数少速度快。
多项式核函数POLY:
线性不可分时,映射到高纬特征空间,参数多,多项式阶数较高时核矩阵元素值将趋近无穷大小计算复杂度高。
高斯核函数RBF:
映射到高维,应用的最广泛,参数比多项式核函数少。
二层神经收集SIGMOID:
实现了一种多层神经网络。
核函数选择,一般特征提取得好包含的信息足够大很多问题都线性可分,如果有足够的时间去寻找RBF核参数会得到更好的效果。
这里使用javacv进行SVM二分类。
正例样本(有车牌图片),负例样本(无车牌图片),样本转二值图进行train和test。首先将train数据及标签转为矩阵保存到xml,然后用svm训练得到模型保存为xml。最后加载test样本进行预测。使用线性核函数的默认配置。
svmLabelData.xml(样本标签)
svmTrainData.xml(训练样本)
svmModulData.xml(训练结果)
- //读取训练数据(0为正例、1为负例、样本名称n.png)
- public static void loadTrainData(String path0,String path1,String trainXml,String labelXml){
- //训练数据
- Mat trainData = new Mat();
- //标签
- Mat labelData = new Mat();
- File file0 = new File(path0);
- File file1 = new File(path1);
- File[] pics0 = file0.listFiles();
- File[] pics1 = file1.listFiles();
- //负例
- for(int i=1;i<=pics0.length;i++){
- File f = pics0[i-1];
- Mat temp = imread(f.getPath(),IMREAD_GRAYSCALE);//灰度图
- opencv_imgproc.threshold(temp, temp, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);//二值图
- Mat convertMat = new Mat();
- temp.reshape(1, 1).row(0).convertTo(convertMat, CV_32F);//转一行
- trainData.push_back(convertMat);//塞入样本
- labelData.push_back(new Mat().put(Mat.zeros(new Size(1,1),CV_32SC1)));//塞入标签0(无车牌)
-
-
- }
- //正例
- for(int i=1;i<=pics1.length;i++){
- File f = pics1[i-1];
- Mat temp = imread(f.getPath(),IMREAD_GRAYSCALE);//灰度图
- opencv_imgproc.threshold(temp, temp, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);//二值图
- Mat convertMat = new Mat();
- temp.reshape(1, 1).row(0).convertTo(convertMat, CV_32F);//转一行
- trainData.push_back(convertMat);//塞入样本
- labelData.push_back(new Mat().put(Mat.ones(new Size(1,1),CV_32SC1)));//塞入标签1(无车牌)
- }
- //保存为xml(注意像素点数据类型svm.train对数据类型有要求)
- opencv_core.FileStorage ft = new opencv_core.FileStorage(trainXml,WRITE);
- ft.write("tag",trainData);
- opencv_core.FileStorage fl = new opencv_core.FileStorage(labelXml,WRITE);
- fl.write("tag",labelData);
- ft.release();
- fl.release();
- }