线性支持向量分类机及其实现
2011-10-28 21:18
176 查看
本文讨论对于一般的分类问题,线性支持向量分类机(C-SVC)的实现原理及MATLAB代码实现。
由于需要处理线性不可分问题,我们没法找到一个超平面可以完全正确的分化训练集,因此需要“软化”一些条件。由标准的支持向量机(SVM)的最大间隔法所导出的约束条件可以进行如下的“软化”:
yi((w·xi)+b) ≥ 1-ξi , i = 1, 2, ... , n
当ξi足够大时,训练点(yi, xi)总是可以满足条件的,所以我们不能让ξi太大,因此得给ξi一个惩罚系数,所以C-SVC的原问题可以归纳如下:
minω,b,ξ 1/2||ω||2 + CΣξi
s.t. yi((w·xi)+b) ≥ 1-ξi , i = 1, 2, ... , n
ξi ≥ 0, i = 1, 2, ... , n
根据原问题,我们可以得到如下的对偶问题:
minα 1/2αTHα-eTα
s.t. αTy = 0
0 ≤ α ≤ C
其中,H = ΣΣyiyj(xi·xj), i = 1, 2, ... , n, j = 1, 2, ... , n,α = (α1, α2, ... , αn),y = (y1, y2, ... , yn)。
对于得到的对偶问题,我们可以用函数quadprog()对这个凸二次规划问题进行相应的求解,所得到的结果即为α的解。代码如下:
接下来我们需要计算b的值。由于在求对偶问题的过程中,我们知道ω = Σαiyixi , i = 1, 2, ... , n。所以b = yj-ωTxj。在这里需要注意的是αj取(0, C)之间的数的时候,所得到的b是唯一的(具体证明在以后的随笔中会介绍)。因此我们可以得到划分的超平面 ωTx+b = 0。所以决策函数为 f(x) = sgn( ωTx+b)。求b以及决策函数的代码如下:
上面代码中的测试正确率是这样进行计算的,将得到的决策函数在原始的训练集中跑一遍,因为是线性不可分的,所以不可能完全划分正确,我们将正确的数目除以总的样本数就得到一个简单正确率的计算,需要说明的是,要测试决策函数的好坏,判断C的选取,应该使用LOOCV等方法。
问题与思考:
1. 我曾采用的二维测试数据集为:
y = [1;1;1;1;1;-1;-1;-1;-1;-1];
X1 = [1.5 15;0.2 11;0.3 17;4 1;2 20;-10 -21;-2 -1;-15 -11;-1.4 -1;-2 -6.20];
X2 = [1.5 15;0.2 11;0.3 17;4 1;2 20;-10 -21;-2 -1;0.7 13;-1.4 -1;-2 -6.20];
其中X1是线性可分的情况、X2是线性不可分的情况。
对于数据集(y,X1)得到的结果如下图所示,有两个支持向量(第四个和第八个)。此时b不为零的取值为-0.4188和-0.4252。
对于数据集(y,X2)得到的结果如下图所示,有五个支持向量(第二、三、四、八和第九个)。此时b不为零的取值均为-0.4435。
所以我特别好奇为什么在前一个数据集上的测试中,得到的b不唯一。带着这个问题,我将不同的b的值都画出了相应的直线,得到了几乎重合的直线,因此我的解释是机器误差产生的,但是不知道这样解释靠不靠谱。这个问题还会继续去看看有没有办法解决。
2. 对于线性不可分问题的最大间隔法有理论基础吗?因为此时已经没有间隔了...
由于需要处理线性不可分问题,我们没法找到一个超平面可以完全正确的分化训练集,因此需要“软化”一些条件。由标准的支持向量机(SVM)的最大间隔法所导出的约束条件可以进行如下的“软化”:
yi((w·xi)+b) ≥ 1-ξi , i = 1, 2, ... , n
当ξi足够大时,训练点(yi, xi)总是可以满足条件的,所以我们不能让ξi太大,因此得给ξi一个惩罚系数,所以C-SVC的原问题可以归纳如下:
minω,b,ξ 1/2||ω||2 + CΣξi
s.t. yi((w·xi)+b) ≥ 1-ξi , i = 1, 2, ... , n
ξi ≥ 0, i = 1, 2, ... , n
根据原问题,我们可以得到如下的对偶问题:
minα 1/2αTHα-eTα
s.t. αTy = 0
0 ≤ α ≤ C
其中,H = ΣΣyiyj(xi·xj), i = 1, 2, ... , n, j = 1, 2, ... , n,α = (α1, α2, ... , αn),y = (y1, y2, ... , yn)。
对于得到的对偶问题,我们可以用函数quadprog()对这个凸二次规划问题进行相应的求解,所得到的结果即为α的解。代码如下:
% 选定适当的惩罚系数 C = 1.95; % 实验数据heartData的存储格式为第一列是正负类的标记,其他列为属性 % 根据具体情况对y和X进行赋值 y = heartData(:,1); X = heartData(:,2:end); % 记录数据的规模:样本数*属性维数 numbers = size(X); % 求维数为“样本数*样本数”的矩阵 H = zeros(numbers(1),numbers(1)); for i = 1:numbers(1) for j = 1:numbers(1) H(i,j) = y(i)*y(j)*X(i,:)*X(j,:)'; end end % 以下是几个约束: % Aeq 线性等式约束的矩阵 % beq 线性等式约束的向量 % f 向量 % lb 存储下界的向量 % ub 存储上界的向量 Aeq = y'; beq = 0; f = -ones(numbers(1), 1); lb = zeros(numbers(1), 1); ub = C * ones(numbers(1), 1); % 计算拉格朗日乘子,返回向量x,即拉格朗日乘子 [x,fval,exitflag,output,lambda] = quadprog(H,f,[],[],Aeq,beq,lb, ub, [], optimset('LargeScale','off','MaxIter', 500)); % 将x中小于一定阀值的数置为零(机器误差) for j = 1:numbers(1) if(x(j) < 0.001) x(j) = 0; end end
接下来我们需要计算b的值。由于在求对偶问题的过程中,我们知道ω = Σαiyixi , i = 1, 2, ... , n。所以b = yj-ωTxj。在这里需要注意的是αj取(0, C)之间的数的时候,所得到的b是唯一的(具体证明在以后的随笔中会介绍)。因此我们可以得到划分的超平面 ωTx+b = 0。所以决策函数为 f(x) = sgn( ωTx+b)。求b以及决策函数的代码如下:
% 计算向量w的值 w = zeros(1,numbers(2)); for i = 1:numbers(1) w = w + y(i)*x(i)*X(i,:); end % 计算b的值(这里计算每一个y对应的b的值) b = zeros(numbers(1), 1); for i = 1:numbers(1) if(x(i) > 0 && x(i) < C) b(i) = y(i) - w*X(i,:)'; end end % 将b中小于一定阀值的数置为零(机器误差) for j = 1:numbers(1) if(abs(b(j)) < 0.001) b(j) = 0; end end % 由于计算的原因,b不一定总是相等,所以这里取b的值为最大和最小值的均值 bNonZero = find( b ~= 0 ); bval = 1/2*(max(b(bNonZero)) + min(b(bNonZero))); %% 测试:通过已经求出来的判别函数对数据进行分类的错误率分析 % 记录分类正确的数目 correctNumbers = 0; % 记录通过判别函数计算的结果 result = zeros(numbers(1),1); for i = 1:numbers(1) result(i) = w*X(i,:)' + bval; if(((result(i) > 0) && (y(i) == 1))||((result(i) < 0)&&(y(i) == -1))) correctNumbers = correctNumbers + 1; end end % 输出正确率 disp (correctNumbers/numbers(1))
上面代码中的测试正确率是这样进行计算的,将得到的决策函数在原始的训练集中跑一遍,因为是线性不可分的,所以不可能完全划分正确,我们将正确的数目除以总的样本数就得到一个简单正确率的计算,需要说明的是,要测试决策函数的好坏,判断C的选取,应该使用LOOCV等方法。
问题与思考:
1. 我曾采用的二维测试数据集为:
y = [1;1;1;1;1;-1;-1;-1;-1;-1];
X1 = [1.5 15;0.2 11;0.3 17;4 1;2 20;-10 -21;-2 -1;-15 -11;-1.4 -1;-2 -6.20];
X2 = [1.5 15;0.2 11;0.3 17;4 1;2 20;-10 -21;-2 -1;0.7 13;-1.4 -1;-2 -6.20];
其中X1是线性可分的情况、X2是线性不可分的情况。
对于数据集(y,X1)得到的结果如下图所示,有两个支持向量(第四个和第八个)。此时b不为零的取值为-0.4188和-0.4252。
对于数据集(y,X2)得到的结果如下图所示,有五个支持向量(第二、三、四、八和第九个)。此时b不为零的取值均为-0.4435。
所以我特别好奇为什么在前一个数据集上的测试中,得到的b不唯一。带着这个问题,我将不同的b的值都画出了相应的直线,得到了几乎重合的直线,因此我的解释是机器误差产生的,但是不知道这样解释靠不靠谱。这个问题还会继续去看看有没有办法解决。
2. 对于线性不可分问题的最大间隔法有理论基础吗?因为此时已经没有间隔了...
相关文章推荐
- 线性支持向量分类机及其实现
- LIBSVM代码实现 线性支持向量机之权重向量和决策函数戏说解读
- python实现支持向量回归,包括线性,多项式,径向基
- 实验一线性表的基本操作实现及其应用
- 线性表链式存储(双向循环链表)及其14种操作的实现
- 实验一线性表的基本操作实现及其应用
- Eboot 编译编译器决定中断向量及其实现单一性的原因
- eclipse + libsvm-3.12 用SVM实现简单线性分类
- 使用深度卷积网络和支撑向量机实现的商标检测与分类的例子
- 用tensorflow实现svm的线性和非线性分类
- java学习笔记4>顺序线性表的实现及其内存分配
- AdapterView及其子类之三:基于ListView及ArrayAdapter实现列表 分类: H1_ANDROID 2013-11-19 22:35 987人阅读 评论(0) 收藏
- 线性代数(一)--什么是线性代数(兼论向量空间及其性质)
- 线性表的基本操作实现及其应用
- 实验一线性表的基本操作实现及其应用
- django中实现按内容分类,并支持分页的实现方法
- 实验一线性表的基本操作实现及其应用
- 实验一:线性表的基本操作实现及其应用
- 实验一 线性表的基本操作实现及其应用
- 线性神经网络及其代码实现