支持向量机分类及在R中实现
SVM分类原理
已知一个数据集包含M个对象N个变量,这些对象可划分为两类别。如果将对象以点绘制在变量空间中,则可获得N维空间。
SVM旨在多维空间中找到一个超平面(hyperplane),该平面能够将全部对象分成最优的两类:两类中距离最近的点的间距(margin)尽可能大。这些在间距边界上的点被称为支持向量(support vector),它们决定间距,分割的超平面位于间距的中间。
因此在一个N维空间(对应N个变量)中,可获得一个N–1维的最优超平面。如下展示了当变量数为2时的情形,超平面此时是一条直线。当变量数为3时,超平面是一个平面;当变量数N>3时,超平面是N-1维的超平面。
该图中,蓝色和红色的点分别代表两类别的对象,数据集通过超平面实现分类。SVM的计算过程可简单概括如下:
(1)将M个对象描述在N维变量空间中,SNM中也将对象称为向量(vector),首先使用两个最接近的类间向量计算间距,并获得最大间距(maximum margin);
(2)将最大间距分成两部分,获得超平面(hyperplane),超平面是N-1维的;超平面与两个最接近的类间向量等距,这些向量称为支持向量(support vector)。
(3)进而通过超平面实现对象分类。
由于此算法完全依赖于支持向量,因此将其命名为支持向量机。
不难看出,通过上述过程获得的超平面,实质上代表了一种线性决策面(linear decision surface)。在N维变量空间中的M个对象具有良好的线性可分离特征时,能够实现较好的分类。但实际中,并非所有数据都能适用,有可能数据本身就是非线性的。
如下图(左)所示,该数据集中只有两个变量,因此对于描述在二维变量空间中的对象来说,很难直接通过线性决策面实现划分。
在这种情况下,解决方案是将数据投影到更高维的空间。新的维度是虚拟的,称为内核(kernel),计算程序中一般都有默认的内核参数项,也可以在计算过程时手动指定。
例如通过下式投影到高维空间:
也可以在计算过程中手动指定内核。
通过引入一个新的维度,使对象在更高维空间中获得线性可分的特征,并应用SVM算法实现类别划分(右)。
SVM广泛流行于高维(多元)数据集的分析中,一方面可输出较准确的预测结果,另一方面模型基于较优雅的数学理论。
但是与方法相比,SVM在处理大量样本时的性能较弱。
尽管SVM可以应用于变量数远多于样本数时的情形,但过拟合问题也是经常伴随的。过拟合问题是机器学习方法中普遍存在的缺点,不再多说。
R语言执行SVM
数据集
威斯康星州乳腺癌数据集,包含699个细胞组织样本,由空心细针在皮下肿瘤组织中抽得。其中458个(65.5%)为良性样本,241个(34.5%)为恶性样本。
#威斯康星州乳腺癌数据集
breast <- read.csv('http://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data',na.strings = '?', header = FALSE)
names(breast) <- c('ID', 'clumpThickness', 'sizeUniformity', 'shapeUniformity', 'maginalAdhesion',
'singleEpithelialCellSize', 'bareNuclei', 'blandChromatin', 'normalNucleoli', 'mitosis', 'class')
breast$class <- as.factor(breast$class)
str(breast)
数据集中共有11个变量,包括:
ID:样本ID;
clumpThickness:肿瘤厚度;
sizeUniformity:细胞大小的均匀性;
shapeUniformity:细胞形状的均匀性;
maginalAdhesion:边际附着力;
singleEpithelialCellSize:单个上皮细胞大小;
bareNuclei:裸核,其中有16个样本中有缺失数据并用“?”表示;
blandChromatin:乏味染色质
normalNucleoli:正常核;
mitosis:有丝分裂;
class:样本类别,2代表良性样本(共458个),4代表为恶性样本(共241个)。
除样本ID和样本类别外,其余9个变量均可视为与判别恶性肿瘤相关的细胞特征,特征以得分为1(最接近良性)至10(最接近病变)之间的整数来表示。
任一变量都不能单独作为判别良性或恶性肿瘤的标准,因此接下来综合考虑这9种细胞特征并进行建模,目的是确立一个判断被检者是否患有乳腺癌的分类器模型,实现对恶性肿瘤的准确预测。
#将总数据集分为训练集和测试集
set.seed(123)
select_train <- sample(699, 699*0.7)
breast_train <- breast[select_train, ]
breast_test <- breast[-select_train, ]
首先将总数据集分为两部分,70%的样本(行)用作训练集构建预测模型,30%的样本(行)作为测试集评估模型性能。
e1071包的SVM
在R中,可用于执行SVM的包有很多,如kernlab、e1071等。
本篇以e1071包的方法作为展示。
library(e1071)
#拟合模型,详情 ?svm
#~. 是使用所有变量的简写,等同于 clumpThickness+sizeUniformity+...+normalNucleoli+mitosis
#推荐使用 scale=TRUE 将变量标准化为均值为 0、标准差为 1,有助于消除方差较大的变量对超平面识别的影响
set.seed(123)
fit.svm <- svm(class~., data = breast_train, scale = TRUE)
fit.svm
#细节部分可 names(fit.svm) 后,通过 fit.svm$XXX 等提取查看
svm()默认通过径向基函数(Radial Basis Function,RBF)将对象映射到高维空间,它是一种非线性投影,可以应对类别标签与预测变量间的非线性关系。在用带RBF核的SVM拟合对象时,gamma和cost是重要的参数。
gamma控制分割超平面的形状,gamma越大通常导致支持向量越多,即意味着训练对象到达范围越广,反之范围越窄。
cost越大意味着模型对误差的惩罚更大,从而将生成一个更复杂的分类边界,对应的训练集中的误差也会更小,但也可能存在过拟合问题,即对新对象的预测误差可能更大;反之分类边界更平滑,但可能会导致欠拟合。
默认情况下,gamma为预测变量个数的倒数,cost为1。与直接使用默认值相比,gamma和cost值的不同组合也可能生成更有效的模型,特别是对于非线性数据集而言。因此实际情况中,通常选择不同的参数多加调试并选择相对更优的组合。
e1071包中也提供了一个方法,可以通过设置参数的候选范围,对每一个参数组合生成一个SVM模型,并输出最佳的组合值。
#tune.svm() 可用于自动确定最佳的 gamma 和 cost 值,详情 ?tune.svm
set.seed(123)
tuned <- tune.svm(class~., data = breast_train, gamma = 10^(-6:1), cost = 10^(-10:10))
tuned
训练集的10折交叉验证误差最小的模型给出评估,推荐使用gamma=1e-4、cost=10。
接下来将上述确定的cost和gamma值输入至拟合模型中,即手动指定内核。
#本示例给出 gamma=1e-4,cost=10
set.seed(123)
fit.svm <- svm(class~., data = breast_train, scale = TRUE, gamma = 1e-4, cost = 100)
fit.svm
#细节部分可 names(fit.svm) 后,通过 fit.svm$XXX 等提取查看
将构建好的分类器分类训练集样本,查看判别的样本分类情况。
#训练集自身的预测
#注,支持向量机预测时不允许有缺失值出现,因此使用 na.omit() 去除数据集中的缺失值
pred_train <- predict(fit.svm, na.omit(breast_train))
svm_accuracy <- table(na.omit(breast_train)$class, pred_train, dnn = c('Actual', 'Predicted'))
svm_accuracy
分类准确度在(291+173)/(291+173+5+7)≈97.5%,非常可观的。
接下来使用测试集数据,进一步评估分类器性能。
#使用测试集样本进行评估
#同上,支持向量机预测时不允许有缺失值出现,因此使用 na.omit() 去除数据集中的缺失值
pred_test <- predict(fit.svm, na.omit(breast_test))
svm_accuracy <- table(na.omit(breast_test)$class, pred_test, dnn = c('Actual', 'Predicted'))
svm_accuracy
对于训练集外的测试样本,分类准确度为(142+57)/(142+57+6+2)≈96.1%,同样是很高的。
参考资料