支持向量机
支持向量机 ( support vector machine/SVM ),是一类有监督的学习算法,主要用于分类和回归问题。它的基本原理是:给定一个训练集,其中的每个实例标记属于两类之一。一个 SVM 算法, 表示训练实例为特征空间里的点,它构建一个非概率的二值分类器,将特征空间用一个尽可能宽的”gap”一分为二,使得相同类的训练实例被分到同一个子空间里。对于一个新实例,根据它映射到”gap”的哪一边,将它分到对应的类中。这条”gap”也称为决策边界( decision boundary ),根据它是否为线性形式,称对应的 SVM 分类器为线性(或非线性)分类器。
线性 SVM 分类器
- Hard-margin
假设训练集由
定义一个超平面:
如果训练集是线性可分的,那么我们能找到两个平行的超平面
分隔这两类实例,使得它们之间的距离尽可能地大。由这两个超平面界定的区域称为间隔( margin ),称位于间隔中间的超平面为最大间隔超平面。
间隔超平面可以表示为
几何上,这两个间隔超平面的距离为
(2)式可以重写为
这样,超平面的解等价于优化问题
优化函数是凸的,因此存在唯一的全局最小值。解
值得注意的是,最大间隔超平面完全由离它最近的那些点决定,称这样的点为支持向量( support vectors )。
- Soft-margin
假设数据不是线性可分的,如图5所示。这时仍然最大化两个间隔超平面的距离,允许一些点“跑到”错误的一边去,但要“惩罚”它们。为此,引入松弛变量( slack variables )
当
最终,解带惩罚项的优化问题
注意:
(1). 算法并不是最小化错分类数,而是最小化间隔超平面的距离;
(2). 可以用
(3). 当
- Hard-margin vs Soft-margin SVM 比较
计算 SVM 分类器
为了计算 Soft-margin SVM 分类器,即求解(7),(7)是一个带有线性不等式约束的凸优化问题,称 primal 问题,我们采用拉格朗日乘子法( Lagrange multipliers )。
令 Lagrange ( primal )函数
最小化
Lagrangian dual 目标函数
同时,Karush–Kuhn–Tucker 条件包括约束
因此,
通过边界上的点
注意,
最后,得到分类器
SVM与核
假设训练数据在输入特征空间是非线性可分的,我们想找到一个函数
- SVM对偶公式
称线性SVM在映射后的空间里的形式为对偶( dual ),那么,(7)的对偶形式为
(13)的对偶形式为
式(21)的解为
这样,
SVM 分类器
下面举个例子
- The Kernel Trick
式(21)中,
假设特征空间是
Linear kernel:
Radial basis:
Neural network:
利用核函数,可以避免在高维空间求解优化问题。给定核函数
最终的 SVM 分类器
实例:分类银行客户的欠贷者
现在有一个银行客户的数据集 Bank_dataset.csv 包括5000个客户,12个特征,以 Personal loan (0-1 二值)作为目标变量。这14个特征(或变量)分别是:
- ID —— 客户 ID
- Age —— 客户年龄
- Experience —— 工龄
- Income —— 客户年收入
- Zip Code —— 家庭地址的邮政编码
- Family —— 客户家庭人数
- CCAvg —— 每月信用卡的平均消费额
- Education —— 教育水平 1: 大学以下 2: 大学 3: 大学以上
- Mortgage —— 抵押价值
- Securities Account —— 客户是否在银行开户
- CD Account —— 客户是否在银行存款
- Online —— 客户是否使用网上银行
- CreditCard —— 客户是否使用信用卡
- 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)
阅读更多精彩内容,请关注微信公众号”统计学习与大数据”!