您的位置:首页 > 产品设计 > UI/UE

支持向量机SVM----简化版序列最小优化SMO(Sequential Minimal Optimation)

2018-01-07 14:34 381 查看
本算法根据《机器学习实战》中Python版的简化版SMO改编而来,所以详细的过程说明请参照原书,这里只给出了改编后的程序及结果。实验数据数量较大放在云盘上,https://pan.baidu.com/s/1cHJKku。

需要注意的问题:因为存在第二个点是随机选择的特征,所以每次实验的结果可能都不会完全一样。

以下为实验Matlab代码:

clc;
clear;
%加载测试数据文件,前两列为坐标值,后两列为类标号
fileID = fopen('D:\matlabFile\SVM\SVM.txt');
DS=textscan(fileID,'%f %f %f');
fclose(fileID);
%将数据转为矩阵形式
DataMat=cat(2,DS{1},DS{2});
[Row,Column]=size(DataMat);
%提取类别矩阵
LabelMat=DS{3};
%设定常数C
C=0.6;
%设定容错率
Toler=0.001;
%设定循环次数
MaxIter=30;
b=0;
Alpha=zeros(Row,1);
%循环计数器
flag=0;
while flag<MaxIter
alphaPairChanged=0;
for i=1:Row
X_i=(Alpha.*LabelMat)'*(DataMat*DataMat(i,:)')+b;
%计算坐标X的误差
Err_i=X_i-LabelMat(i);
if ((LabelMat(i)*Err_i<-Toler)&&(Alpha(i)<C))||((LabelMat(i)*Err_i>Toler)&&(Alpha(i)>0))
%在Row的范围内,随机选择一个不等于i的数
Rnd=unidrnd(Row,1,Row);
j=Rnd(1);
if i==j
j=Rnd(2);
end
X_j=(Alpha.*LabelMat)'*(DataMat*DataMat(j,:)')+b;
%计算坐标Y的误差
Err_j=X_j-LabelMat(j);
%备份第i,j个Alpha
Alpha_i_old=Alpha(i);
Alpha_j_old=Alpha(j);
%寻找最大最小值,保证Alpha在0到C之间
if LabelMat(i)~=LabelMat(j)
Low=max([0,Alpha(j)-Alpha(i)]);
High=min([C,C+Alpha(j)-Alpha(i)]);
else
Low=max([0,Alpha(j)+Alpha(i)-C]);
High=min([C,Alpha(j)+Alpha(i)]);
end
%如果最大最小相等,循环步进
if Low==High
continue;
end
Eta=2*DataMat(i,:)*DataMat(j,:)'-DataMat(i,:)*DataMat(i,:)'-DataMat(j,:)*DataMat(j,:)';
if Eta>0
continue;
end
Alpha(j)=Alpha(j)-LabelMat(j)*(Err_i-Err_j)/Eta;
if Alpha(j)>High
Alpha(j)=High;
end
if Alpha(j)<Low
Alpha(j)=Low;
end
%判断Alpha的误差是否足够小,如果否则进行更新
if abs(Alpha(j)-Alpha_j_old)<0.00001
continue;
end
Alpha(i)=Alpha(i)+LabelMat(j)*LabelMat(i)*(Alpha_j_old-Alpha(j));
b1=b-Err_i-LabelMat(i)*(Alpha(i)-Alpha_i_old)*DataMat(i,:)*DataMat(i,:)'-LabelMat(j)*(Alpha(j)-Alpha_j_old)*DataMat(i,:)*DataMat(j,:)';
b2=b-Err_j-LabelMat(i)*(Alpha(i)-Alpha_i_old)*DataMat(i,:)*DataMat(j,:)'-LabelMat(j)*(Alpha(j)-Alpha_j_old)*DataMat(j,:)*DataMat(j,:)';
if (0<Alpha(i))&&(Alpha(i)<C)
b=b1;
elseif (0<Alpha(j))&&(Alpha(j)<C)
b=b2;
else
b=(b1+b2)/2;
end
alphaPairChanged=alphaPairChanged+1;
end
end
if alphaPairChanged==0
flag=flag+1;
else
flag=0;
end
end
%显示原始数据
scatter(DataMat(:,1),DataMat(:,2),'filled');
hold on
%显示支持向量
Index=find(Alpha>0);
Sup=DataMat(Index,:);
scatter(Sup(:,1),Sup(:,2),'r');

实验结果仅供参考:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: