使用的数据是来自MASS包的cats数据集。在本例中你将尝试使用体重和心脏重量来预测一只猫的性别。我们拿数据集中20%的数据点,用于测试模型的准确性(在其余的80%的数据上建立模型)。
SVM旨在在多维空间中找到一个能将全部样本单元分成两类的最优平面,这一平面应使两类中距离最近的点的间距尽可能大,在间距边界上的点被称为支持向量,分割的超平面位于间距的中间。
对于一个N维空间(即N个变量),最优超平面(即线性决策面)为N-1维,例如,当变量数为2,曲面是一条直线,当变量数为3,曲面是一个平面,等等。间距为两条虚线间的距离,虚线上的点即支持向量,最优超平面即间距中的黑色实线。
超平面指的是分割输入变量空间的直线。 在 SVM 中,选择超平面以最好地将输入变量空间中的点与它们的类(0级或1级)分开。在二维中,我们可以将其视为一条线,并假设我们的所有输入点都可以 被这条线完全分开。 SVM 学习算法找到导致超平面最好地分离类的系数。
超平面和最近数据点之间的距离称为边距。 可以分离两个类的最佳或最佳超平面是具有最大边距的线。 只有这些点与定义超平面和分类器的构造有关。 这些点称为支持向量。 它们支持或定义超平面。 实际上,优化算法用于找到使裕度最大化的系数的值。
支持向量机SVM优化目的为寻找一个超平面,使得正负样本能够以最大间隔分离开,从而得到更好的泛化性能,其通过引入核函数来将低维线性不可分的样本映射到高维空间从而线性可分,通过引入惩罚参数C(类似于正则化参数)来对错分样本进行惩罚,从而减少模型复杂度,提高泛化能力,通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,即支持向量机的学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。
由简至繁的模型包括:
1)当训练样本线性可分时,通过硬间隔最大化,学习一个线性可分支持向量机;
2)当训练样本近似线性可分时,通过软间隔最大化,学习一个线性支持向量机;
3)当训练样本线性不可分时,通过核技巧和软间隔最大化,学习一个非线性支持向量机;
支持向量机SVM是从线性可分情况下的最优分类面提出的。所谓最优分类,就是要求分类线不但能够将两类无错误的分开,而且两类之间的分类间隔最大,使分类间隔最大实际上就是使得推广性中的置信范围最小。推广到高维空间,最优分类线就成为最优分类面。
基本思想可以概括为:首先通过非线性变换将输入空间变换到一个高维空间,然后在这个新空间中求取最优线性分类面,而这种非线性变换是通过定义适当的内积函数来实现的。支持向量机求得的分类函数形式上类似于一个神经网络,其输出是若干中间层节点的线性组合,而每一个中间层节点对应于输入样本与一个支持向量的内积,因此也被叫做支持向量网络。
library(e1071)
set.seed(1234)
data(cats, package="MASS")
inputData <- data.frame(cats[, c (2,3)], response = as.factor(cats$Sex)) # response as factor
传递给函数svm()的关键参数是kernel、cost和gamma。
Kernel指的是支持向量机的类型,它可能是线性SVM、多项式SVM、径向SVM或Sigmoid SVM。
Cost是违反约束时的成本函数,代表犯错的成本,一个较大的成本意味着模型对误差的惩罚更大,从而将生成一个更复杂的分类边界,对应的训练集中的误差也会更小,但也意味着可能存在过拟合问题,即对新样本单元的预测误差可能更大,较小的成本意味着分类边界更平滑,但可能导致欠拟合,成本参数恒为正。
gamma是除线性SVM外其余所有SVM都使用的一个参数,控制分割超平面的形状,gamma越大,通常导致支持向量越多,我们也可以将gamma看作控制训练样本“到达范围”的参数,即gamma参数越大意味着训练样本到达范围越广,而越小意味着到达范围越窄,gamma参数恒为正,一般为预测变量个数的倒数。
还有一个类型参数,用于指定该模型是用于回归、分类还是异常检测。但是这个参数不需要显式地设置,因为支持向量机会基于响应变量的类别自动检测这个参数,响应变量的类别可能是一个因子或一个连续变量。所以对于分类问题,一定要把你的响应变量作为一个因子。
svmfit <- svm(response ~ ., data = inputData, kernel = "linear", cost = 10, scale = FALSE) # linear svm, scaling turned OFF
print(svmfit)
plot(svmfit, inputData)
compareTable <- table (inputData$response, predict(svmfit)) # tabulate
mean(inputData$response != predict(svmfit)) # 19.44% misclassification error
径向基函数作为一个受欢迎的内核函数,可以通过设置内核参数作为“radial”来使用。当使用一个带有“radial”的内核时,结果中的超平面就不需要是一个线性的了。通常定义一个弯曲的区域来界定类别之间的分隔,这也往往导致相同的训练数据,更高的准确度。
svmfit <- svm(response ~ ., data = inputData, kernel = "radial", cost = 10, scale = FALSE) # radial svm, scaling turned OFF
print(svmfit)
plot(svmfit, inputData)
compareTable <- table (inputData$response, predict(svmfit)) # tabulate
mean(inputData$response != predict(svmfit)) # 18.75% misclassification error
可以使用tune.svm()函数,来寻找svm()函数的最优参数,对每一个参数组合生成一个SVM模型,并输出在每一个参数组合上的表现。
### Tuning
# Prepare training and test data
set.seed(100) # for reproducing results
rowIndices <- 1 : nrow(inputData) # prepare row indices
sampleSize <- 0.8 * length(rowIndices) # training sample size
trainingRows <- sample (rowIndices, sampleSize) # random sampling
trainingData <- inputData[trainingRows, ] # training data
testData <- inputData[-trainingRows, ] # test data
tuned <- tune.svm(response ~., data = trainingData, gamma = 10^(-6:-1), cost = 10^(1:2)) # tune
summary (tuned) # to select best gamma and cost
当cost为100,gamma为0.01时产生最小的错误率。利用这些参数训练径向支持向量机。
svmfit <- svm (response ~ ., data = trainingData, kernel = "radial", cost = 100, gamma=0.01, scale = FALSE) # radial svm, scaling turned OFF
print(svmfit)
plot(svmfit, trainingData)
compareTable <- table (testData$response, predict(svmfit, testData)) # comparison table
mean(testData$response != predict(svmfit, testData)) # 13.79% misclassification error
网友评论