应用机器学习(五):支持向量机

支持向量机

支持向量机 ( support vector machine/SVM ),是一类有监督的学习算法,主要用于分类和回归问题。它的基本原理是:给定一个训练集,其中的每个实例标记属于两类之一。一个 SVM 算法, 表示训练实例为特征空间里的点,它构建一个非概率的二值分类器,将特征空间用一个尽可能宽的”gap”一分为二,使得相同类的训练实例被分到同一个子空间里。对于一个新实例,根据它映射到”gap”的哪一边,将它分到对应的类中。这条”gap”也称为决策边界( decision boundary ),根据它是否为线性形式,称对应的 SVM 分类器为线性(或非线性)分类器。


这里写图片描述

线性 SVM 分类器

  • Hard-margin

假设训练集由 N 个点 (x⃗ 1,y1),(x⃗ 2,y2),,(x⃗ N,yN) 组成。其中, x⃗ iRp , 所属类标签 yi{1,1} 。现在,我们想找到最大间隔超平面( hyperplane ),分隔来自两类的这 N 个点。该超平面到离它最近的点的距离是最大的。

定义一个超平面:

{x⃗ :w⃗ x⃗ +b⃗ =0}

如果训练集是线性可分的,那么我们能找到两个平行的超平面
分隔这两类实例,使得它们之间的距离尽可能地大。由这两个超平面界定的区域称为间隔( margin ),称位于间隔中间的超平面为最大间隔超平面。


这里写图片描述

间隔超平面可以表示为

w⃗ x⃗ +b=±1(1)

几何上,这两个间隔超平面的距离为 2||w⃗ || , 因此,最大化它们之间的距离,等价于最小化 ||w⃗ || 。同时,还要保证两类的数据点分别位于由这两个间隔超平面分隔出的子空间内,即,

w⃗ x⃗ i+b{1,1,if yi=1 if yi=1 (2)

(2)式可以重写为

yi(w⃗ x⃗ i+b)1,i=1,2,,N(3)

这样,超平面的解等价于优化问题

Minimizew⃗ ,b12||w⃗ ||2s.t.yi(w⃗ x⃗ i+b)1,i=1,2,,N(4)


这里写图片描述

优化函数是凸的,因此存在唯一的全局最小值。解 w⃗ ,b 确定了分类器

x⃗ sgn(w⃗ x⃗ +b)(5)

值得注意的是,最大间隔超平面完全由离它最近的那些点决定,称这样的点为支持向量( support vectors )。


这里写图片描述

  • Soft-margin

假设数据不是线性可分的,如图5所示。这时仍然最大化两个间隔超平面的距离,允许一些点“跑到”错误的一边去,但要“惩罚”它们。为此,引入松弛变量( slack variables ) ξ1,ξ2,,ξN , ξi0 .


这里写图片描述

ξi>1 时,发生错分,因此,限制 i=1NξiK , 此即训练的错分总数控制在 K 以内。这样,约束条件变为

yi(w⃗ x⃗ i+b)1ξi,ξi0,i=1NξiKi=1,2,,N(6)

最终,解带惩罚项的优化问题

Minimizew⃗ ,b12||w⃗ ||2+Ci=1Nξis.t.yi(w⃗ x⃗ i+b)1ξi,i=1,2,,Nξi0,i=1,2,,N.(7)

注意:

(1). 算法并不是最小化错分类数,而是最小化间隔超平面的距离;

(2). 可以用 ξ2i 代替 ξi

(3). 当 C0 时,得到 Hard-margin 的解。

  • Hard-margin vs Soft-margin SVM 比较


这里写图片描述


这里写图片描述

计算 SVM 分类器

为了计算 Soft-margin SVM 分类器,即求解(7),(7)是一个带有线性不等式约束的凸优化问题,称 primal 问题,我们采用拉格朗日乘子法( Lagrange multipliers )。

Lagrange ( primal )函数

LP=12||w⃗ ||2+Ci=1Nξii=1Nαi[yi(w⃗ x⃗ i+b)(1ξi)]i=1Nμiξi(8)

最小化 w⃗ ,b,ξi 的函数 LP ,由于最小值在导数为0的点,故分别求导

w⃗ =i=1Nαiyix⃗ i0=i=1Nαiyiαi=Cμi,fori(9)(10)(11)

αi,μi,ξi0,i . 将(9)——(11)代入(8),得到
Lagrangian dual 目标函数
LD=i=1Nαi12i=1Nj=1Nαiαjyiyjx⃗ ix⃗ j(12)

LD 给出了目标函数(7)的下界,因此

MaximizeLDs.t.0αiC,i=1Nαiyi=0(13)

同时,Karush–Kuhn–Tucker 条件包括约束

αi[yi(w⃗ x⃗ i+b)(1ξi)]=0μiξi=0yi(w⃗ x⃗ i+b)(1ξi)0(14)(15)(16)

i=1,2,,N . 联合方程(9)——(16),得 primal 问题的解

w⃗ =i=1Nα^iyix⃗ i(17)

α^i=0 ,当 x⃗ i 位于正确的一边时;
0<α^iC ,当 x⃗ i 位于边界时,即为支持向量。
因此, w⃗  是支持向量的线性组合。
通过边界上的点 x⃗ i b

yi(w⃗ x⃗ i+b)=1b=yiw⃗ x⃗ i(18)

注意, y1i=yi ,由于 yi=±1 .

最后,得到分类器

x⃗ sgn(w⃗ x⃗ +b)(19)

SVM与核

假设训练数据在输入特征空间是非线性可分的,我们想找到一个函数 Φ(x) ,将数据映射到更高维的空间,在这个空间里,映射的数据是线性可分的。那么,我们利用之前的方法构建线性SVM。通常,线性SVM实现更好的分类效果和更低的时间复杂度。


这里写图片描述

  • SVM对偶公式

称线性SVM在映射后的空间里的形式为对偶( dual ),那么,(7)的对偶形式为

Minimizew⃗ ,b12||w⃗ ||2+Ci=1Nξis.t.yi(w⃗ Φ(xi)+b)1ξi,i=1,2,,Nξi0,i=1,2,,N.(20)

(13)的对偶形式为

Maximizei=1Nαi12i=1Nj=1NαiαjyiyjΦ(xi)Φ(xj)s.t.0αiC,i=1Nαiyi=0(21)

式(21)的解为

w⃗ =i=1Nα^iyiΦ(xi)(22)

这样,

yi(w⃗ Φ(xi)+b)=1b=yiw⃗ Φ(xi)(23)

SVM 分类器

x⃗ sgn(w⃗ Φ(x)+b)(24)

下面举个例子


这里写图片描述

  • The Kernel Trick

式(21)中, Φ(xi)Φ(xj) 表示先将原特征空间的向量 xi,xj 通过函数 Φ() 映射到高维空间,然后对映射后的新向量 Φ(xi),Φ(xj) 作内积。实际上,我们并不需要映射 Φ() ,而只需要找到一个函数 K(,) ,使得 K(xi,xj)=Φ(xi)Φ(xj) . 称这样的函数 K(,) 为核函数( kernel function )。

假设特征空间是 d 维的,那么,核函数 K Rd×Rd R 的实值对称函数,满足 K(x,z)=Φ(x)TΦ(z) . 在 SVM,流行的核函数有:

Linear kernel: K(x,z)=xz

d th-Degree polynomial: K(x,z)=(1+xz)d

Radial basis: K(x,z)=eγ||xz||2

Neural network: K(x,z)=tanh(κ1xz+κ2)

利用核函数,可以避免在高维空间求解优化问题。给定核函数 K(,) , 对于固定的 i , 式(23)等价于

b=yij=1Nα^jyjΦ(xj)Φ(xi)=yij=1Nα^jyjK(xj,xi)(25)

最终的 SVM 分类器

x⃗ sgn(w⃗ Φ(x)+b)=sgn(i=1Nα^iyiK(xi,x)+b)(26)

实例:分类银行客户的欠贷者

现在有一个银行客户的数据集 Bank_dataset.csv 包括5000个客户,12个特征,以 Personal loan (0-1 二值)作为目标变量。这14个特征(或变量)分别是:

  1. ID —— 客户 ID
  2. Age —— 客户年龄
  3. Experience —— 工龄
  4. Income —— 客户年收入
  5. Zip Code —— 家庭地址的邮政编码
  6. Family —— 客户家庭人数
  7. CCAvg —— 每月信用卡的平均消费额
  8. Education —— 教育水平 1: 大学以下 2: 大学 3: 大学以上
  9. Mortgage —— 抵押价值
  10. Securities Account —— 客户是否在银行开户
  11. CD Account —— 客户是否在银行存款
  12. Online —— 客户是否使用网上银行
  13. CreditCard —— 客户是否使用信用卡
  14. Personal Loan —— 客户是否拖欠贷款

其中,1为客户 ID,2-13为输入特征,14为分类的目标变量。

可到百度网盘:http://pan.baidu.com/s/1geHMxAN 下载该数据集。

下面,将数据集 Bank_dataset.csv 按7:3分成训练集和检验集两部分。在训练集上训练线性 SVM 分类器,在检验集上预测 Personal Loan 的状态,计算分类的准确率。主要应用 e1071 包的 svm 函数,R 代码如下:

rm(list=ls(all=T))
dir <- "E:/机器学习/论文/代码/svm"
# set dir as the working directory
setwd(dir) 

data=read.csv("Bank_dataset.csv")
str(data)
# dropping three fields from original dataset
drop_atr <- c("ID","ZIP.Code","Experience")
names <- setdiff(colnames(data),drop_atr)
final_data <- data[names]
str(final_data)

library(e1071)

# segmenting final_data into trainset and testset
set.seed(123)
ind <- sample(2, nrow(final_data), replace = TRUE, prob=c(0.7, 0.3))
trainset <- final_data[ind == 1,]
testset <- final_data[ind == 2,]
ind_Atr <- setdiff(colnames(trainset),"Personal.Loan")
table(trainset$Personal.Loan)
table(testset$Personal.Loan)
trainset$Personal.Loan <- as.factor(trainset$Personal.Loan)

model <- svm(trainset[ind_Atr], trainset$Personal.Loan, 
          type="C-classification", kernel="linear")

summary(model)

# testing with testset
pred_test <- predict(model,testset[ind_Atr])
pred_test2 <- table(testset$Personal.Loan,pred_test)
# counting prediction accuracy
acc_test <- sum(diag(pred_test2))/sum(pred_test2)

阅读更多精彩内容,请关注微信公众号”统计学习与大数据”!

猜你喜欢

转载自blog.csdn.net/wong2016/article/details/72550805