机器学习算法——支持向量机
是一类按方式对数据进行二元分类的广义线性分类器(Generalized Linear Classifier),其决策边界是对学习样本求解的。支持向量机在各种实际问题上都表现优秀,在手写体识别和人脸识别应用广泛,在文本和超文本分类上,因为可以大量减少标准归纳和转换设置中对标记训练实例的需求,也是举足轻重的存在。另外,支持向量机也被用在图像分类,图像分割系统,在生物学和其他科学上支持向量机也备受青睐。
一、支持向量机的概念
支持向量机(Support Vector Machine, SVM) 是一类按监督学习方式对数据进行二元分类的广义线性分类器(Generalized Linear Classifier),其决策边界是对学习样本求解的最大边距超平面(Maximum-margin Hyperplane)。
支持向量机在各种实际问题上都表现优秀,在手写体识别和人脸识别应用广泛,在文本和超文本分类上,因为可以大量减少标准归纳和转换设置中对标记训练实例的需求,也是举足轻重的存在。另外,支持向量机也被用在图像分类,图像分割系统,在生物学和其他科学上支持向量机也备受青睐。
二、支持向量机的原理
1. 支持向量机的基本原理
1.1 超平面
支持向量机(后文简称SVM)的基本原理可以概括为:在特征空间中找到一个最优的超平面(Hyperplane),将不同类别的样本尽可能地分开。
所谓超平面,并非指几何意义上的平面对象,而是分类问题的决策边界。如下图的二分类数据集,存在一条直线将该数据集划分成两部分,此时这条直线可被称为超平面。
现在假设有一三维数据集,若要对其进行分隔,则需要一个平面,即三维数据集的超平面就是一个平面;而四维数据集的超平面明显是一个三位对象。以此类推,对于一个N维的数据集,一个能将其分隔成两部分的N-1维对象,即称为超平面。它反映了对该数据集进行分隔的决策边界。
而SVM要寻找的就是一个可以将数据集分为两部分的超平面,在超平面一侧的数据均属于一类,超平面另一侧的数据均属于另一类,如上图所示,并依此构造分类器,以解决分类问题。
1.2 间隔和支持向量
对于一个数据集可能存在多个分隔超平面满足要求,如下图所示,A为原始二分类数据集,B、C、D中直线均为符合要求的超平面。
显然,此时应找到一个最优超平面作为最终分类结果。因此需要一个衡量分类结果的标准。显然可知,想要使超平面的分类效果越好,需要找到各类离超平面最近的点,使它们离超平面的距离尽可能远。如上图中D明显就是三者中最优。
将点与超平面的距离称为间隔(Margin),离超平面最近的点称为支持向量(Support Vector),则寻找最优超平面的过程就是支持向量间隔最大化的过程。
1.3 寻找最大间隔
超平面可用以下形式表示:
wTx+b=0w^Tx+b=0wTx+b=0
其中x=(x1,x2,...,xn)Tx=(x_1,x_2,...,x_n)^Tx=(x1,x2,...,xn)T,代表nnn维空间的样本点坐标集;w=(w1,w2,...,wn)w=(w_1,w_2,...,w_n)w=(w1,w2,...,wn),为nnn维参数向量;bbb为常数。
对于超平面外的某一点aaa,其坐标为AAA,则其到分隔面的法线或垂线的长度为:
d=∣wTA+b∣∣∣w∣∣d=\frac{|w^TA+b|}{||w||}d=∣∣w∣∣∣wTA+b∣
点到分隔面法线的长度代表着该点到分隔面的实际欧氏距离,也就是物理几何距离。它仅衡量点到超平面的距离,而不包含对于分类结果正确性的判断。
为加入对分类结果的判断,我们使用一个类似单位阶跃函数的函数对wTx+bw^Tx+bwTx+b进行处理,该函数定义如下:
f(x)={−1,x<01,x≥0f(x)=\begin{cases}-1,\quad &x<0 \\ 1,\quad &x\ge0\end{cases}f(x)={−1,1,x<0x≥0
这个函数以超平面法向量www的方向为正方向,位于超平面正方向的类别为正类,标签为+1+1+1,反之则为−1-1−1。
与Logistic回归有所不同,这里不使用000或111,而是−1-1−1或+1+1+1来作为类别标签。这是为了方便后续数学上的处理,使用±1\pm1±1作为标签允许我们使用一个统一的公式来表示间隔,而不用担心数据的类别对表示结果的影响。
得到标签之后,我们就可以计算点到超平面的函数间隔(Functional Margin) 来判断超平面分类的准确性:
γ^=y⋅(wTx+b)\hat\gamma=y\cdot(w^Tx+b)γ^=y⋅(wTx+b)
其中xxx为样本点的坐标,yyy为样本点的标签。
函数间隔用于衡量超平面分类的正确性,当:
- γ^>0\hat\gamma>0γ^>0,样本分类正确;且其绝对值∣wTx+b∣|w^Tx+b|∣wTx+b∣越大,说明超平面离样本点越远,即分类边界离样本点越远,分类结果的置信度也就越高。
- γ^<0\hat\gamma<0γ^<0,样本分类错误。
- γ^=0\hat\gamma=0γ^=0,样本点位于超平面上,此为特殊情况。
明显地,函数间隔的值会随着超平面参数www和bbb的缩放而同比例变化,但超平面的位置并未改变。为了避免这种缩放带来的不确定性,通常通过约束最小函数间隔为111来归一化问题。即对于任意样本点,有约束条件:
y⋅(wTx+b)≥1y\cdot(w^Tx+b)\ge1y⋅(wTx+b)≥1
在此情况下,对于分类正确的分隔超平面,有:
wTx+b≥+1⇒y=+1wTx+b≤−1⇒y=−1w^Tx+b\ge+1\quad \Rightarrow\quad y=+1 \\ w^Tx+b\le-1\quad \Rightarrow\quad y=-1wTx+b≥+1⇒y=+1wTx+b≤−1⇒y=−1
即参数空间存在两个间隔边界:wTx+b=+1w^Tx+b=+1wTx+b=+1和wTx+b=−1w^Tx+b=-1wTx+b=−1,间隔边界可以看作与分隔超平面平行的两个超平面。同时,因函数间隔的最小化约束,落在间隔边界上的点即可看作支持向量。
由函数间隔,我们还能得到点到超平面的几何间隔(Geometrical Margin):
γ=γ^∣∣w∣∣=y⋅(wTx+b)∣∣w∣∣\gamma=\frac{\hat\gamma}{||w||}=\frac{y\cdot(w^Tx+b)}{||w||}γ=∣∣w∣∣γ^=∣∣w∣∣y⋅(wTx+b)
与函数间隔相同,几何间隔的符号也可用于判断分类结果的正确性,方式与函数间隔相同,此处不再赘述。因其引入了归一化范数∣∣w∣∣||w||∣∣w∣∣,使其避免了函数间隔因权重缩放而失效的问题。此外,函数间隔的绝对值等同于点到分隔超平面法线的长度,即其绝对值的几何意义即为点到超平面的几何距离。
因之前对函数间隔的归一化约束,可得几何间隔有约束条件:
γ≥1∣∣w∣∣\gamma\ge\frac{1}{||w||}γ≥∣∣w∣∣1
可知:两个间隔边界和分隔超平面的距离为1∣∣w∣∣\frac{1}{||w||}∣∣w∣∣1,即两个间隔边界的距离为2∣∣w∣∣\frac{2}{||w||}∣∣w∣∣2,如下图所示:
此处2∣∣w∣∣\frac{2}{||w||}∣∣w∣∣2被称为分类器的间隔,或数据集的间隔。
因支持向量即为分隔边界上的向量,故我们只需最大化分类器间隔,即是最大化支持向量间隔。又因分类器间隔为2∣∣w∣∣\frac{2}{||w||}∣∣w∣∣2,因此我们只需最大化∣∣w∣∣−1||w||^{-1}∣∣w∣∣−1,即最小化∣∣w∣∣||w||∣∣w∣∣ 即可。由此,问题可以进一步转化为最小化12∣∣w∣∣2\frac{1}{2}||w||^221∣∣w∣∣2。
引入12∣∣w∣∣2\frac{1}{2}||w||^221∣∣w∣∣2是为了在保证问题目标一致的同时,将问题转化为凸优化问题,简化函数形式,并以此高效求解。
至此,SVM将问题转化为:
minw,b12∣∣w∣∣2s.t.yi⋅(wTxi+b)≥1∀i\underset{w,b}\min\frac{1}{2}||w||^2 \quad s.t. \quad y_i\cdot(w^Tx_i+b)\ge1 \quad\forall iw,bmin21∣∣w∣∣2s.t.yi⋅(wTxi+b)≥1∀i
引入拉格朗日乘子后,优化目标函数为:
maxα[∑i=1mα−12∑i,j=1my(i)⋅y(j)⋅αi⋅αj⋅⟨x(i),x(j)⟩]s.t.α≥0and∑i=1mαi⋅y(i)=0\underset{\alpha}\max\left[\sum^m_{i=1}\alpha-\frac{1}{2}\sum^m_{i,j=1}y^{(i)}\cdot y^{(j)}\cdot\alpha_i\cdot\alpha_j\cdot\langle x^{(i)},x^{(j)}\rangle\right] \\ s.t.\quad\alpha\ge0\quad and\quad\sum^m_{i=1}\alpha_i\cdot y^{(i)}=0αmax[i=1∑mα−21i,j=1∑my(i)⋅y(j)⋅αi⋅αj⋅⟨x(i),x(j)⟩]s.t.α≥0andi=1∑mαi⋅y(i)=0
但是,实际中会发现,数据并不都是那么“纯净”,即数据并非100%线性可分。此时,我们可以采用软间隔处理:引入一个松弛变量(Slack Variable),允许小部分误分类样本的存在。
此时问题为:
minw,b12∣∣w∣∣2+C∑i=1mξis.t.yi⋅(wTxi+b)≥1∀i\underset{w,b}\min\frac{1}{2}||w||^2+C\sum^m_{i=1}\xi_i\quad s.t.\quad y_i\cdot(w^Tx_i+b)\ge1 \quad\forall iw,bmin21∣∣w∣∣2+Ci=1∑mξis.t.yi⋅(wTxi+b)≥1∀i
其中ξ\xiξ为松弛变量,CCC为惩罚系数。
拉格朗日乘子引入后优化函数不变,约束条件变为:
C≥α≥0and∑i=1mαi⋅y(i)=0C\ge\alpha\ge0\quad and\quad \sum^m_{i=1}\alpha_i\cdot y^{(i)}=0C≥α≥0andi=1∑mαi⋅y(i)=0
三、样例实现
现展示SVM的一个用途:垃圾邮件分类。我们要做的是将邮件信息向量化,然后在参数区间内找到决策边界,将邮件分为垃圾邮件和非垃圾邮件两类。
以下是正常邮件示例:
> Anyone knows how much it costs to host a web portal ?
>
Well, it depends on how many visitors you're expecting.
This can be anywhere from less than 10 bucks a month to a couple of $100.
You should checkout http://www.rackspace.com/ or perhaps Amazon EC2
if youre running something big..
To unsubscribe yourself from this mailing list, send an email to:
groupname-unsubscribe@egroups.com
以下是垃圾邮件示例:
Do You Want To Make $1000 Or More Per Week?
If you are a motivated and qualified individual - I
will personally demonstrate to you a system that will
make you $1,000 per week or more! This is NOT mlm.
Call our 24 hour pre-recorded number to get the
details.
000-456-789
I need people who want to make serious money. Make
the call and get the facts.
Invest 2 minutes in yourself now!
现有一个词汇集文件vocab.txt,其中部分内容如下:
1 aa
2 ab
3 abil
4 abl
5 about
6 abov
7 absolut
8 abus
9 ac
10 accept
11 access
12 accord
13 account
14 achiev
15 acquir
16 across
17 act
18 action
19 activ
20 actual
21 ad
22 adam
23 add
24 addit
25 address
26 administr
27 adult
28 advanc
29 advantag
30 advertis
(词汇集共1899个单词,其余单词不在此处展示)
该词汇集文件将部分单词赋予了标签,以便我们将邮件内容转化为向量,形式如:x=(x1,x2,...,xn)x=(x_1,x_2,...,x_n)x=(x1,x2,...,xn),其中xi∈{0,1}∀i∈[1,n]x_i\in\{0,1\}\quad\forall i\in[1,n]xi∈{0,1}∀i∈[1,n]。同时,对于∀i∈[1,n]\forall i\in[1,n]∀i∈[1,n],xi=0x_i=0xi=0代表词汇集中编号为iii的词未出现在该邮件中,xi=1x_i=1xi=1则相反。
除此之外还有一训练集文件spamTrain.mat和测试集文件spamTest.mat。使用MATLAB分别读取这些文件,查看其中的内容:
读取spamTrain.mat文件之后,得到了两个变量:X和y。其中X存储了4000个向量化的邮件信息,向量化方式如之前所述。X的部分内容如下图所示:
与之对应,y则是4000个邮件内容的标签,其中标签的值为0则代表该邮件不是垃圾邮件,为1则相反。y的部分内容如下图所示:
spamTest.mat则是存储了Xtest和ytest两个变量,分别存储了1000封电子邮件的向量化内容和标签,此处不再展示。
以上为已给出的数据信息,现在要使用Python读取数据文件并构造SVM,完成垃圾邮件分类器。
SVM定义如下:
import numpy as np
from scipy.optimize import minimize
class SVM:
def __init__(self, C=1.0):
self.C = C
self.w = None
self.b = None
self.alpha = None
def linear_kernel(self, X1, X2):
return X1.dot(X2.T)
def objective(alpha):
return 0.5 * np.sum(alpha * y * K * alpha * y) - np.sum(alpha)
def gradient(alpha):
return (alpha * y * K * y).sum(axis=1) - 1
def fit(self, X, y):
n_samples, n_features = X.shape
y = y.reshape(-1, 1) * 2 - 1 # 将{0,1}标签转换为{-1,1}
K = self.linear_kernel(X, X)
constraints = [
{'type': 'eq', 'fun': lambda alpha: np.sum(alpha * y.flatten())},
{'type': 'ineq', 'fun': lambda alpha: alpha},
{'type': 'ineq', 'fun': lambda alpha: self.C - alpha}
]
alpha0 = np.ones(n_samples) * 0.1
res = minimize(
fun=objective,
x0=alpha0,
method='SLSQP',
jac=gradient,
constraints=constraints,
options={'maxiter': 100, 'ftol': 1e-3}
)
alpha = res.x
sv = (alpha > 1e-5) & (alpha < self.C)
self.w = np.sum((alpha[sv] * y[sv].flatten())[:, np.newaxis] * X[sv], axis=0)
self.b = np.mean(y[sv] - np.dot(X[sv], self.w))
def predict(self, X):
scores = np.dot(X, self.w) + self.b
return (scores > 0).astype(int)
读取数据函数定义如下:
import scipy.io as sio
def load_data():
train_data = sio.loadmat('spamTrain.mat')
test_data = sio.loadmat('spamTest.mat')
X_train = train_data['X']
y_train = train_data['y'].ravel()
X_test = test_data['Xtest']
y_test = test_data['ytest'].ravel()
return X_train, y_train, X_test, y_test
文件向量化相关函数定义如下:
import numpy as np
def load_vocab(vocab_path):
vocab_dict = {}
with open(vocab_path, 'r') as f:
for line in f:
idx, word = line.strip().split('\t')
vocab_dict[word] = int(idx) - 1
return vocab_dict
def preprocess_email(email_content):
email = email_content.lower()
tokens = email.split()
return tokens
def email_to_feature_vector(email_content, vocab_dict, vocab_size):
tokens = preprocess_email(email_content)
feature_vec = np.zeros(vocab_size)
for token in tokens:
if token in vocab_dict:
feature_vec[vocab_dict[token]] = 1
return feature_vec
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)