支持向量机(Support Vector Machines)
在监督学习中,许多学习算法的性能都非常类似,因此,重要的不是你该选择使用学习算法 A
还是学习算法 B
,而更重要的是,应用这些算法在你需要解决的业务场景中时,表现情况通常依赖于你的水平。比如:你为学习算法所设计的特征选择,以及如何选择正则化参数等等。还有一个更加强大的算法广泛的应用于工业界和学术界,它被称为支持向量机( Support Vector Machine
)。与逻辑回归和神经网络相比,支持向量机,或者简称 SVM
,在学习复杂的非线性方程时提供了一种更为清晰,更加强大的方式。因此,在接下来的内容中,对于支持向量机,鉴于该算法的强大和受欢迎度,在本节,我们会花许多时间来深入了解它。
1.1 优化目标函数(损失函数)
和我们之前学习的算法一样,我们先从算法的优化目标开始。那么,为了描述支持向量机,事实上,我将会从逻辑回归开始展示我们如何一点一点修改来得到本质上的支持向量机。
那么,在逻辑回归中我们已经熟悉了这里的假设函数形式,以及右边的
S
S
S 型激励函数。然而,为了解释一些数学知识.我将用
z
z
z 表示
θ
T
x
\theta^Tx
θTx 。
现在考虑下我们想要逻辑回归做什么:如果有一个
y
=
1
y=1
y=1 的样本,因为我们想要正确地将此样本分类,这就意味着当
h
θ
(
x
)
h_{\theta}(x)
hθ(x) 趋近于
1
1
1 时,
θ
T
x
\theta^Tx
θTx 应当远大于
0
0
0 ,这里的
≫
\gg
≫ 意思是远远大于
0
0
0 。这是因为由于
z
z
z 表示
θ
T
x
\theta^Tx
θTx ,当
z
z
z 远大于
0
0
0 时,即到了该图的右边,你不难发现此时逻辑回归的输出将趋近于
1
1
1 。相反地,如果我们有另一个样本,即
y
=
0
y=0
y=0 ,我们希望假设函数的输出值将趋近于
0
0
0 ,这对应于
θ
T
x
\theta^Tx
θTx ,或者就是
z
z
z 会远小于
0
0
0 。
如果你进一步观察逻辑回归的代价函数,你会发现每个样本
(
x
,
y
)
(x, y)
(x,y) 都会为总代价函数增加一次计算单个样本损失的值(因为是求和),并且这里还有一个
1
m
\frac{1}{m}
m1 项,表示的是求
m
m
m 个样本总损失的平均损失。但是,在逻辑回归中,这里的这一项就是表示一个训练样本所对应的损失表达式。现在,如果我将完整定义的假设函数代入这里,那么我们就会得到每一个训练样本都影响这一项的式子。
我们先忽略 1 m \frac{1}{m} m1 这一项,但是这一项是影响整个总代价函数的式子。
现在,我们来考虑两种情况:
一种是 y y y 等于 1 1 1 的情况;另一种是 y y y 等于 0 0 0 的情况。
在第一种情况中,假设 y = 1 y=1 y=1 ,此时在目标函数中只需有第一项起作用,因为 y = 1 y=1 y=1 时, ( 1 − y ) (1-y) (1−y) 项将等于 0 0 0 。因此,当在 y = 1 y=1 y=1 的样本中时,即在 ( x , y ) (x, y) (x,y) 中 ,我们得到 y = 1 − l o g ( 1 − 1 1 + e x p − z ) y = 1 - log(1 - \frac{1}{1 + exp^{-z}}) y=1−log(1−1+exp−z1) 这样一项。
我们用 z z z 表示 θ T x \theta^Tx θTx ,即: z = θ T x z = \theta^Tx z=θTx 。当然,在代价函数中, y y y 前面有负号。我们只是这样表示,如果 y = 1 y=1 y=1 时代价函数中,这一项等于 1 1 1 。这样做是为了简化此处的表达式。如果画出关于 z z z 的函数,你会看到左下角的这条曲线,我们同样可以看到,当 z z z 增大时,也就是相当于 θ T x \theta^Tx θTx 增大时, − l o g ( 1 1 + e x p − z ) -log(\frac{1}{1 + exp^{-z}}) −log(1+exp−z1) 对应的值会变的非常小。对整个代价函数而言,影响也非常小。这也就解释了,为什么逻辑回归在观察到正样本 y = 1 y=1 y=1 时,试图将 θ T x \theta^Tx θTx 设置得非常大。因为在代价函数中的这一项会变的非常小。
现在开始建立支持向量机,我们先画出将要用的代价函数:
新的代价函数将会水平的从这里到右边(图外),然后我再画一条同逻辑回归非常相似的直线,但是,在这里是一条直线,也就是我用紫红色画出的曲线,就是这条紫红色的曲线。那么,到了这里已经非常接近逻辑回归中使用的代价函数了。只是这里是由两条直线段组成,即位于右边的水平部分和位于左边的直线部分,先别过多的考虑左边直线部分的斜率,这并不是很重要。但是,这里我们将使用的新的代价函数,是在
y
=
1
y=1
y=1 的前提下的。事实上,在之后的优化问题中我们能做和逻辑回归中类似的事情,并且为支持向量机带来计算上的优势。例如,更容易用来计算股票交易中的问题等等。
目前,我们只是讨论了
y
=
1
y=1
y=1 的情况,另外一种情况是当
y
=
0
y=0
y=0 时,此时如果你仔细观察代价函数只留下了第二项
−
(
1
−
y
)
l
o
g
(
1
−
1
1
+
e
x
p
−
z
)
-(1-y)log(1-\frac{1}{1 + exp^{-z}})
−(1−y)log(1−1+exp−z1) ,因为第一项被消除了。如果当
y
=
0
y=0
y=0 时,那么这一项也就是
0
0
0 了。所以上述表达式只留下了第二项。因此,这个样本的代价或是代价函数的贡献将会由这一项表示。并且,如果你将这一项作为
z
z
z 的函数,那么,这里就会得到横轴
z
z
z 。同样地,我们要替代这一条蓝色的线,用相似的方法。
如果我们用一个新的代价函数来代替,即这条从
0
0
0 点开始的水平直线,然后是一条斜线,如上图。那么,现在让我给这两个方程命名,左边的函数,我称之为
c
o
s
t
1
(
z
)
cost_{1}(z)
cost1(z) ,同时,右边函数我称它为
c
o
s
t
0
(
z
)
cost_{0}(z)
cost0(z) 。这里的下标是指在代价函数中,对应的
y
=
1
y=1
y=1 和
y
=
0
y=0
y=0 的情况,拥有了这些定义后,现在我们就开始构建支持向量机。
这是我们在逻辑回归中使用代价函数
J
(
θ
)
J(\theta)
J(θ) 。也许这个方程看起来不是非常熟悉。这是因为之前有个负号在方程外面,但是,这里我所做的是,将负号移到了表达式的里面,这样做使得方程看起来有些不同。对于支持向量机而言,实质上我们要将
c
o
s
t
1
(
z
)
cost_{1}(z)
cost1(z) 替换为
c
o
s
t
1
(
θ
T
x
)
cost_{1}(\theta^Tx)
cost1(θTx) ,同样地,我也将
c
o
s
t
0
(
z
)
cost_{0}(z)
cost0(z) 替换为
c
o
s
t
0
(
θ
T
x
)
cost_{0}(\theta^Tx)
cost0(θTx) 。因此,对于支持向量机,我们得到了这里的最小化问题,即:
1
m
[
∑
i
=
1
m
y
(
i
)
(
−
l
o
g
h
θ
(
x
(
i
)
)
)
+
(
1
−
y
(
i
)
)
(
−
l
o
g
(
1
−
h
θ
(
x
(
i
)
)
)
)
]
\frac{1}{m}\bigg[\sum_{i=1}^m y^{(i)}\bigg(-logh_{\theta}(x^{(i)})\bigg) + (1-y^{(i)})\bigg(-log(1-h_{\theta}(x^{(i)}))\bigg) \bigg]
m1[i=1∑my(i)(−loghθ(x(i)))+(1−y(i))(−log(1−hθ(x(i))))]
然后,再加上正则化参数。现在按照支持向量机的惯例,我们的书写会稍微有些不同,代价函数的参数表示也会稍微有些不同。
首先,我们要除去 1 m \frac{1}{m} m1 这一项,当然这仅仅是由于人们使用支持向量机时,对比于逻辑回归而言,不同的习惯所致。因为 1 m \frac{1}{m} m1 仅是个常量,因此,无论式子前面是否有这一项,最终我们所得到的最优值都是一样的。举个例子,假定有一最小化问题:即要求当 f ( u ) = ( u − 5 ) 2 + 1 f(u) = (u - 5)^2 +1 f(u)=(u−5)2+1 取得最小值时 u u u 的值,很明显:当 u = 5 u=5 u=5 时 f ( u ) f(u) f(u) 取得最小值。
现在,如果我们想要将这个目标函数乘上常数 10 10 10 ,这里我们的最小化问题就变成了:求使得 f ( u ) = 10 × ( u − 5 ) 2 + 10 f(u) = 10 \times (u - 5)^2 +10 f(u)=10×(u−5)2+10 最小的值 u u u ,显然,也是当 u = 5 u=5 u=5 时 f ( u ) f(u) f(u) 取得最小值。因此将一些常数乘以你的最小化项,这并不会改变最小化该方程时 u u u 的值。因此,这里我所做的是约去常量。同理,我们将目标函数乘上一个常量,并不会改变取得最小值时的 θ \theta θ 值。
第二点是概念上的变化,在使用支持向量机时一般会遵循一些如下的标准惯例。因此,对于逻辑回归,在目标函数中,我们有两项:第一个是训练样本的代价,第二个是我们的正则化项,我们必须用这一项来平衡。这就相当于我们想要最小化
A
A
A 加上正则化参数
λ
\lambda
λ ,然后乘以其他项
B
B
B 对吧?这里的
A
A
A 表示这里的第一项,同时我用
B
B
B 表示第二项,但不包括
λ
\lambda
λ ,我们不是优化这里的
A
+
λ
B
A + \lambda B
A+λB 。我们所做的是通过设置不同正则参数
λ
\lambda
λ 达到优化目的。这样我们就能够权衡,是使得训练样本拟合的更好,即最小化
A
A
A 。还是保证正则化参数足够小,即最小化
B
B
B 项。但对于支持向量机,我们将使用一个不同的参数替换这里使用的
λ
\lambda
λ 来权衡这两项。我们使用一个不同的参数称为
C
C
C ,同时优化目标函数为
C
A
+
B
CA + B
CA+B 。因此,在逻辑回归中,如果给定
λ
\lambda
λ 一个非常大的值,意味着给予
B
B
B 更大的权重。而这里,就对应于将
C
C
C 设定为非常小的值,这也表示给予
B
B
B 更大的权重。因此这里其实是采用不同的方式来控制这种权衡,或者用参数来决定是更关心第一项的优化,还是更关心第二项的优化。当然你也可以把这里的参数
C
C
C 考虑成
1
λ
\frac{1}{\lambda}
λ1 ,同
1
λ
\frac{1}{\lambda}
λ1 所扮演的角色相同,这两个目标函数得到的最优解
θ
\theta
θ 是相同的。那么,我们现在删掉这里的
λ
\lambda
λ ,并且用常数
C
C
C 来代替。这里我们就得到了在支持向量机中优化后的目标函数。然后最小化这个目标函数,得到 SVM
学习到的参数
C
C
C 。
最后有别于逻辑回归输出的概率。在这里,当我们最小化代价函数获得参数
θ
\theta
θ 时,支持向量机是直接预测
y
y
y 的值等于
1
1
1 ,还是等于
0
0
0 。当
θ
T
x
\theta^Tx
θTx 大于或者等于 0 时,这个假设函数会预测
y
y
y 的值为
1
1
1 。所以学习参数
θ
\theta
θ 就是支持向量机假设函数的形式,这就是支持向量机在数学上的定义。
1.2 大边界的直观理解
人们有时将支持向量机看作是大间距分类器。在这一小节,我们将介绍其中的含义,这有助于我们直观理解 SVM
模型的假设是什么样的。
这是我的支持向量机模型的代价函数,在左边这里我画出了关于
z
z
z 的代价函数
c
o
s
t
1
(
z
)
cost_{1}(z)
cost1(z) ,此函数用于正样本,而在右边这里我画出了关于
z
z
z 的代价函数
c
o
s
t
0
(
z
)
cost_{0}(z)
cost0(z) ,横轴表示
z
z
z ,现在让我们考虑一下,最小化这些代价函数的必要条件是什么。如果你有一个正样本
y
=
1
y = 1
y=1 ,则只有在
z
≥
1
z \geq 1
z≥1 时,代价函数
c
o
s
t
1
(
z
)
cost_{1}(z)
cost1(z) 才等于
0
0
0 。
换句话说,如果你有一个正样本,我们会希望 θ T x ≥ 1 \theta^Tx \geq 1 θTx≥1 ,反之,如果 y = 0 y=0 y=0 ,我们观察一下函数 c o s t 0 ( z ) cost_{0}(z) cost0(z) ,它只有在 z ≤ − 1 z \leq -1 z≤−1 的区间里函数值为 0 0 0 。这是支持向量机的一个有趣性质。事实上,如果你有一个正样本,则其实我们仅仅要求 θ T x \theta^Tx θTx 大于等于 0 0 0 ,就能将该样本恰当分出,这是因为如果 θ T x > 0 \theta^Tx > 0 θTx>0 大的话,我们的模型代价函数值为 0 0 0 。类似地,如果你有一个负样本,则仅需要 θ T x ≤ 0 \theta^Tx \leq 0 θTx≤0 就会将负例正确分离,但是支持向量机的要求比较高,不仅仅要能正确分开输入的样本,即不仅仅要求 θ T x > 0 \theta^Tx > 0 θTx>0 ,我们需要的是比 0 0 0 值大很多,比如大于等于 1 1 1 ,同理对于负样本的情况,我们希望 θ T x \theta^Tx θTx 小于等于 − 1 -1 −1 ,这就相当于在支持向量机中嵌入了一个额外的安全因子,或者说安全的间距因子。
当然,逻辑回归做了类似的事情。但是让我们来看一下,在支持向量机中,这个安全因子会导致什么结果。具体而言,我们接下来会考虑一个特例。我们将这个常数
C
C
C 设置成一个非常大的值。比如我们假设
C
C
C 的值为 100000
或者其它非常大的数,然后观察支持向量机会给出什么结果呢?
如果
C
C
C 非常大,则最小化代价函数的时候,我们将会很希望找到一个使第一项为
0
0
0 的最优解。因此,让我们尝试在代价项的第一项为
0
0
0 的情形下理解该优化问题。比如我们可以把
C
C
C 设置成了非常大的常数,这将给我们一些关于支持向量机模型的直观感受。
min
θ
C
∑
i
=
1
m
[
y
(
i
)
c
o
s
t
1
(
θ
T
x
(
i
)
)
+
(
1
−
y
(
i
)
)
c
o
s
t
0
(
θ
T
x
(
i
)
)
]
+
1
2
∑
j
=
1
n
θ
j
2
\min_{\theta} C\sum_{i=1}^m \bigg[y^{(i)}cost_{1}(\theta^Tx^{(i)}) + (1-y^{(i)})cost_{0}(\theta^Tx^{(i)}) \bigg] + \frac{1}{2} \sum_{j=1}^n \theta_{j}^2
θminCi=1∑m[y(i)cost1(θTx(i))+(1−y(i))cost0(θTx(i))]+21j=1∑nθj2
我们已经看到输入一个训练样本标签为
y
=
1
y=1
y=1 ,你想令第一项为
0
0
0 ,你需要做的是找到一个
θ
\theta
θ ,使得
θ
T
x
≥
1
\theta^Tx \geq 1
θTx≥1 。类似地,对于一个训练样本,标签为
y
=
0
y=0
y=0 ,为了使
c
o
s
t
0
(
z
)
cost_{0}(z)
cost0(z) 函数的值为
0
0
0 ,我们需要
θ
T
x
≤
−
1
\theta^Tx \leq -1
θTx≤−1。现在来考虑我们的优化问题。选择参数,使得第一项等于 0,就会导致下面的优化问题,因为我们将选择参数使第一项为
0
0
0 ,要让这个函数的第一项为
0
0
0 ,则必须是
C
C
C 乘以
0
0
0 加上二分之一乘以第二项。这里第一项是
C
C
C 乘以
0
0
0 ,因此我们可以将其删去。
支持向量机这时将遵从以下的约束: 如果
y
(
i
)
y^{(i)}
y(i)是等于
1
1
1 的,
θ
T
x
(
i
)
≥
1
\theta^Tx^{(i)} \geq 1
θTx(i)≥1 ;反之, 如果样本
i
i
i 是一个负样本,则
θ
T
x
(
i
)
≤
−
1
\theta^Tx^{(i)} \leq -1
θTx(i)≤−1 。当你最小化这个关于变量的函数的时候,你会得到一个非常有趣的决策边界。
具体而言,如果你考察这样一个数据集,其中有正样本,也有负样本,可以看到这个数据集是线性可分的。即存在一条直线把正负样本完全分开。当然这里存在多条不同的直线,可以把正样本和负样本完全分开。
比如,这就是一个决策边界可以把正样本和负样本分开。但是多多少少这个看起来并不是非常自然是么?
或者我们可以画一条更差的决策边界,这是另一条决策边界,可以将正样本和负样本分开,但仅仅是勉强分开,这些决策边界看起来都不是特别好的选择,支持向量机将会选择这个黑色的决策边界,相较于之前我用粉色或者绿色画的决策界。这条黑色的看起来好得多,黑线看起来是更稳健的决策界。在分离正样本和负样本上它显得的更好。数学上来讲,这是什么意思呢?这条黑线有更大的距离,这个距离叫做间距(margin)。
当画出这两条额外的蓝线,我们看到黑色的决策界和训练样本之间有更大的最短距离。然而粉线和蓝线离训练样本就非常近,在分离样本的时候就会比黑线表现差。因此,这个距离叫做支持向量机的间距,这是支持向量机具有鲁棒性的原因,因为它努力用一个最大间距来分离样本。因此支持向量机有时被称为大间距分类器。
我将会从直观上略述为什么这个优化问题会产生大间距分类器。
在本小节中关于大间距分类器,我们将这个大间距分类器中的正则化因子常数
C
C
C 设置的非常大,我们将其设置为了 100000
,因此对这样的一个数据集,也许我们将选择这样的决策边界,从而最大间距地分离开正样本和负样本。那么在让代价函数最小化的过程中,我们希望找出在
y
=
1
y=1
y=1 和
y
=
0
y=0
y=0 两种情况下都使得代价函数中左边的第一项尽量为零的参数
C
C
C 。如果我们找到了这样的参数,则我们的最小化问题便转变成:
min
∑
j
=
1
n
θ
j
2
subject to
{
θ
T
x
(
i
)
≥
1
,
if
y
(
i
)
=
1
θ
T
x
(
i
)
≤
−
1
,
if
y
(
i
)
=
0
\min \sum_{j=1}^n \theta_{j}^2 \quad \text{subject to $\begin{cases}\theta^Tx^{(i)} \geq 1, \quad \text{if $y^{(i)} = 1$} \\ \theta^Tx^{(i)} \leq -1, \quad \text{if $y^{(i)} = 0$}\end{cases}$}
minj=1∑nθj2subject to {θTx(i)≥1,if y(i)=1θTx(i)≤−1,if y(i)=0
事实上,支持向量机现在要比这个大间距分类器所体现得更成熟,尤其是当你使用大间距分类器的时候,你的学习算法会受异常点( outlier
) 的影响。例如我们加入一个额外的正样本。
在这里,如果你加了这个样本,为了将样本用最大间距分开,也许我们最终会得到一条类似这样的决策边界,对么?就是这条粉色的线,仅仅基于一个异常值,仅仅基于一个样本,就将我的决策界从这条黑线变到这条粉线,这是不明智的。而如果正则化参数
C
C
C 设置的非常大,它将决策边界从黑线变到了粉线,但是如果
C
C
C 设置的小一点,则你最终会得到这条黑线,当然数据如果不是线性可分的,则支持向量机也会将它们恰当分开。因此,大间距分类器的描述,仅仅是从直观上给出了正则化参数
C
C
C 非常大的情形,同时,要提醒你
C
C
C 的作用类似于
1
λ
\frac{1}{\lambda}
λ1 ,
λ
\lambda
λ 是我们之前使用过的正则化参数。这只是
C
C
C 非常大的情形,或者等价地
λ
\lambda
λ 非常小的情形。你最终会得到类似粉线这样的决策边界,但是实际上应用支持向量机的时候,当
C
C
C 不是非常非常大的时候,它可以忽略掉一些异常点的影响,得到更好的决策边界。甚至当你的数据不是线性可分的时候,支持向量机也可以给出好的结果。
回顾 C = 1 λ C = \frac{1}{\lambda} C=λ1 ,因此:
C C C 较大时,相当于 λ \lambda λ 较小,可能会导致过拟合,高方差。
C C C 较小时,相当于 λ \lambda λ 较大,可能会导致欠拟合,高偏差。
我们在下一小节会介绍支持向量机的偏差和方差,希望在那时候关于如何处理参数的这种平衡会变得更加清晰。我希望,这小节给出了一些关于为什么支持向量机被看做大间距分类器的直观理解。它用最大间距将样本区分开,尽管从技术上讲,这只有当参数 C C C 是非常大的时候是真的,但是它对于理解支持向量机是有益的。
1.3 大边界分类背后的数学
在本小节,将会为大家介绍一些大间隔分类背后的数学原理。这些知识能让你对支持向量机中的优化问题,以及如何得到大间距分类器,产生更好的直观理解。
首先,让我们来复习一下关于向量内积的知识。假设有两个向量,
u
u
u 和
v
v
v 。两个都是二维向量,我们看一下
u
T
v
u^Tv
uTv 的结果。
u
T
v
u^Tv
uTv 也叫做向量
u
u
u 和
v
v
v 之间的内积。由于是二维向量,我可以将它们画在这个图上。我们可以将向量
u
u
u 进行分解,分解成与
x
x
x 轴重合的分量
u
1
u_1
u1 和与
y
y
y 轴重合的分量
u
2
u_2
u2。现在我们很容易计算的一个量就是向量
u
u
u 的范数。
∣
∣
u
∣
∣
||u||
∣∣u∣∣ 表示
u
u
u 的范数,即向量
u
u
u 的欧几里得长度。根据毕达哥拉斯定理,
∣
∣
u
∣
∣
=
u
1
2
+
u
2
2
||u|| = \sqrt{u_1^2 + u_2^2}
∣∣u∣∣=u12+u22 ,这是向量
u
u
u 的长度,它是一个实数。
现在让我们回头来看向量
v
v
v ,因为我们想计算内积。
v
v
v 是另一个向量,它的两个分量
v
1
v_1
v1 和
v
2
v_2
v2 是已知的。现在让我们来看看如何计算
u
u
u 和
v
v
v 之间的内积,具体做法是,我们将向量
v
v
v 投影到向量
u
u
u 上,我们做一个直角投影,或者说一个
90
90
90 度投影将其投影到
u
u
u 上,接下来我们度量这条红线的长度。我称这条红线的长度为
p
p
p ,因此
p
p
p 就是向量
v
v
v 投影到向量
u
u
u 上的量,那么
u
u
u 和
v
v
v 的内积可表示为
u
T
v
=
p
×
∣
∣
u
∣
∣
u^Tv = p \times ||u||
uTv=p×∣∣u∣∣ ,这是计算内积的一种方法。如果你从几何上画出
p
p
p 的值,同时画出
u
u
u 的范数
∣
∣
u
∣
∣
||u||
∣∣u∣∣ ,你也会同样地计算出内积,答案是一样的。另一个计算公式是:
u
T
v
u^Tv
uTv 就是
[
u
1
,
u
2
]
[u_1, u_2]
[u1,u2] 这个一行两列的矩阵乘以
v
v
v 。因此可以得到
u
1
×
v
+
u
2
×
v
u_1 \times v + u_2 \times v
u1×v+u2×v 。根据线性代数的知识,这两个公式会给出同样的结果。顺便说一句,
u
T
v
=
v
T
u
u^Tv = v^Tu
uTv=vTu 。因此如果你将
u
u
u 和
v
v
v 交换位置,将
u
u
u 投影到
v
v
v 上,然后做同样地计算内积,得到的是同样的结果。申明一点,在这个等式中
u
u
u 的范数是一个实数,
p
p
p 也是一个实数,因此
u
T
v
u^Tv
uTv 就是两个实数正常相乘。
最后一点,需要注意的就是
p
p
p 值,事实上
p
p
p 是有符号的,即它可能是正值,也可能是负值。如果
u
u
u 是一个类似这样的向量,
v
v
v 是一个类似这样的向量,
u
u
u 和
v
v
v 之间的夹角大于
90
90
90 度,则如果将
v
v
v 投影到
u
u
u 上,会得到长度为
p
p
p 的一个投影,在这个情形下我们仍然有
u
T
v
u^Tv
uTv 是等于
p
p
p 乘以
u
u
u 的范数。唯一一点不同的是
p
p
p 在这里是负的。在内积计算中,如果
u
u
u 和
v
v
v 之间的夹角小于
90
90
90 度,那么那条红线的长度
p
p
p 是正值。然而如果这个夹角大于
90
90
90 度,则
p
p
p 将会是负的。如果它们之间的夹角大于
90
90
90 度,两个向量之间的内积也是负的。我们接下来将会使用这些关于向量内积的性质来理解支持向量机中的目标函数。
为了方便演示,我们对目标函数做一点简化,仅仅是为了让目标函数更容易被分析。
我们接下来忽略掉截距,令
θ
0
=
0
\theta_0 = 0
θ0=0 ,这样更容易画示意图。我将特征数
n
n
n 置为
2
2
2 ,因此我们仅有两个特征
x
1
,
x
2
x_1, x_2
x1,x2 ,现在我们来看一下支持向量机的优化目标函数。当我们仅有两个特征,即
n
=
2
n=2
n=2 时,这个式子可以写作:
1
2
(
θ
1
2
+
θ
2
2
)
=
1
2
(
θ
1
2
+
θ
2
2
)
2
\frac{1}{2}(\theta_1^2 + \theta_2^2) = \frac{1}{2} \bigg(\sqrt{\theta_1^2 + \theta_2^2}\bigg)^2
21(θ12+θ22)=21(θ12+θ22)2 ,我们只有两个参数
θ
1
,
θ
2
\theta_1, \theta_2
θ1,θ2 。你可能注意到括号里面的这一项是向量
t
h
e
t
a
theta
theta 的范数,或者说是向量
t
h
e
t
a
theta
theta 的长度。我的意思是如果我们将向量
t
h
e
t
a
theta
theta 写出来,那么我刚刚画红线的这一项就是向量
t
h
e
t
a
theta
theta 的长度或范数。
当然你可以将其写作 θ 0 , θ 1 , θ 2 \theta_0, \theta_1, \theta_2 θ0,θ1,θ2 ,如果 θ 0 = 0 \theta_0 = 0 θ0=0 ,那就是 θ 1 , θ 2 \theta_1, \theta_2 θ1,θ2 的长度。在这里我将 θ 0 \theta_0 θ0 忽略,这样来写 θ \theta θ 的范数,它仅仅和 θ 1 , θ 2 \theta_1, \theta_2 θ1,θ2 有关。但是在数学上不管你是否包含 θ 0 \theta_0 θ0 ,其实并没有差别,因此在我们接下来的推导中去掉 θ 0 \theta_0 θ0 不会有任何影响,这意味着我们的目标函数是等于 1 2 ∣ ∣ θ ∣ ∣ 2 \frac{1}{2}||\theta||^2 21∣∣θ∣∣2 。因此支持向量机做的全部事情,就是极小化参数向量 θ \theta θ 范数的平方,或者说长度的平方。
现在我将要看看
θ
T
x
\theta^Tx
θTx 项并更深入地理解它们的含义。给定参数向量
θ
\theta
θ 和一个样本
x
x
x ,这等于什么呢?在上一张图片上,我们画出了在不同情形下,
u
T
v
u^Tv
uTv 的示意图,我们将会使用这些概念,
θ
\theta
θ 和
x
(
i
)
x^{(i)}
x(i) 就类似于
u
u
u 和
v
v
v 。
让我们看一下示意图:我们考察一个单一的训练样本,用一个叉来表示正样本
x
(
i
)
x^{(i)}
x(i) ,意思是在
x
x
x 轴上取值为
x
1
(
i
)
x_1^{(i)}
x1(i) ,在
y
y
y 轴上取值为
x
2
(
i
)
x_2^{(i)}
x2(i) 。它们实际上就是一个始于原点,终点与这个训练样本点平行的向量。现在,我们有一个参数向量
θ
\theta
θ 我将
θ
1
\theta_1
θ1 画在横轴这里,将
θ
2
\theta_2
θ2 画在纵轴这里,那么内积
θ
T
x
(
i
)
\theta^Tx^{(i)}
θTx(i) 将会是什么呢?
使用我们之前的方法,我们计算的方式就是我将训练样本 x ( i ) x^{(i)} x(i) 投影到参数向量 θ \theta θ 上,我将它称为 p ( i ) p^{(i)} p(i) 用来表示这是第 i i i 个训练样本在参数向量 θ \theta θ 上的投影,并将它画成红色。根据我们之前的内容,我们知道的是 θ T x ( i ) \theta^Tx^{(i)} θTx(i) 将会等于 p p p 乘以向量 θ \theta θ 的长度或范数。这就等于 θ 1 x 1 ( i ) + θ 2 x 2 ( i ) \theta_1 x_1^{(i)} + \theta_2 x_2^{(i)} θ1x1(i)+θ2x2(i) 。这两种方式是等价的,都可以用来计算向量 θ \theta θ 和样本 x ( i ) x^{(i)} x(i) 之间的内积。
这告诉了我们什么呢?约束
θ
T
x
(
i
)
≥
1
\theta^Tx^{(i)} \geq 1
θTx(i)≥1 或者
θ
T
x
(
i
)
≤
−
1
\theta^Tx^{(i)} \leq -1
θTx(i)≤−1 是可以被
p
(
i
)
x
≥
1
p^{(i)}x \geq 1
p(i)x≥1 这个约束所代替的。因为
θ
T
x
(
i
)
=
p
(
i
)
∣
∣
θ
∣
∣
\theta^Tx^{(i)} = p^{(i)} ||\theta||
θTx(i)=p(i)∣∣θ∣∣ ,将其写入我们的优化目标,我们将会得到简化约束后的目标函数。
需要提醒一点,我们之前曾讲过这个优化目标函数可以被写成等于
1
2
∣
∣
θ
∣
∣
2
\frac{1}{2}||\theta||^2
21∣∣θ∣∣2 。
现在让我们考虑下面这里的训练样本。我们继续使用之前的简化,即 θ 0 = 0 \theta_0 = 0 θ0=0 ,我们来看一下支持向量机会选择什么样的决策边界。
对于这样选择的参数
θ
\theta
θ ,可以看到参数向量
θ
\theta
θ 事实上是和决策边界呈
90
90
90 度正交的,因此这个绿色的决策边界对应着一个参数向量
θ
\theta
θ 的一个方向,顺便提一句
θ
0
=
0
\theta_0 = 0
θ0=0 的简化仅仅意味着决策边界必须通过原点
(
0
,
0
)
(0, 0)
(0,0) 。现在让我们看一下这对于优化目标函数意味着什么。
比如这个样本,我们假设它是我的第一个样本
x
(
1
)
x^{(1)}
x(1) ,如果我考察这个样本到参数
θ
\theta
θ 的投影,投影是这个短的红线段,就等于
p
(
1
)
p^{(1)}
p(1) ,它非常短。类似地,我的第二个训练样本如果它恰好是
x
(
2
)
x^{(2)}
x(2) ,则它到
θ
\theta
θ 的投影我们用粉色表示,这个短的粉色线段是
p
(
2
)
p^{(2)}
p(2) ,即第二个样本到我的参数向量
θ
\theta
θ 的投影。
p
(
2
)
p^{(2)}
p(2) 是在相反的方向,即事实上它是一个负值,这个向量和参数向量
θ
\theta
θ 的夹角大于
90
90
90 度,即
p
(
2
)
p^{(2)}
p(2) 的值小于
0
0
0。
我们会发现这些
p
(
i
)
p^{(i)}
p(i) 将会是非常小的数,因此当我们考察优化目标函数的时候,对于正样本而言,我们需要
p
(
i
)
∣
∣
θ
∣
∣
≥
1
p^{(i)}||\theta|| \geq 1
p(i)∣∣θ∣∣≥1 ,但是如果
p
(
i
)
p^{(i)}
p(i) 在这里非常小,那就意味着我们需要的
θ
\theta
θ 范数非常大。因为如果
p
(
1
)
p^{(1)}
p(1) 很小,而我们希望
p
(
1
)
∣
∣
θ
∣
∣
≥
1
p^{(1)}||\theta|| \geq 1
p(1)∣∣θ∣∣≥1 ,令其实现的唯一的办法就是这两个数都比较大。如果
p
(
1
)
p^{(1)}
p(1) 小,我们就希望
θ
\theta
θ 的范数大。类似地,对于负样本而言我们需要
p
(
2
)
∣
∣
θ
∣
∣
≤
−
1
p^{(2)}||\theta|| \leq -1
p(2)∣∣θ∣∣≤−1 。我们已经在这个样本中看到
p
(
2
)
p^{(2)}
p(2) 会是一个非常小的数,因此唯一的办法就是
θ
\theta
θ 的范数变大。但是我们的目标函数是希望找到一个参数
θ
\theta
θ ,使它的范数是较小的。因此,这看起来不像是一个好的参数向量
θ
\theta
θ 的选择。
相反的,来看一个不同的决策边界。比如说,支持向量机选择了这个绿色的决策边界,现在状况会有很大不同。使用线性代数的知识可以说明,这个绿色的决策边界有一个垂直于它的向量
θ
\theta
θ 。现在如果考察你的数据在
x
x
x 轴上的投影,比如我们之前提到的样本
x
(
1
)
x^{(1)}
x(1) ,当我将它投影到
x
x
x 轴上,或说投影到
θ
\theta
θ 上,就会得到这样的
p
(
1
)
p^{(1)}
p(1) ,它的长度是
p
(
1
)
p^{(1)}
p(1) ;另一个样本
x
(
2
)
x^{(2)}
x(2) ,做同样的投影会发现,
p
(
2
)
p^{(2)}
p(2) 的长度是负值。如果我们仍然要满足这些约束,
p
(
i
)
∣
∣
θ
∣
∣
≥
1
p^{(i)}||\theta|| \geq 1
p(i)∣∣θ∣∣≥1 ,则因为
p
(
1
)
p^{(1)}
p(1) 变大了, 相应的
θ
\theta
θ 的范数就可以变小了。这意味着我们会选择右图中绿色的决策边界,而不是左图的那个,支持向量机可以使参数
θ
\theta
θ 的范数变的小很多。因此,如果我们想令
θ
\theta
θ 的范数变小,从而令
θ
\theta
θ 范数的平方变小,就能让支持向量机选择右图的决策边界。这就是支持向量机如何能有效地产生大间距分类器的原因。
看这个绿色的决策边界,我们希望正样本和负样本投影到 θ \theta θ 的值大。要做到这一点的唯一方式就是选择这条绿线做决策边界。通过让间距变大,这个间距的值就是 p ( 1 ) , p ( 2 ) , p ( 3 ) p^{(1)}, p^{(2)}, p^{(3)} p(1),p(2),p(3) 等等的值,支持向量机最终可以找到一个较小的 θ \theta θ 范数。
以上就是为什么支持向量机最终会找到大间距分类器的原因。因为它试图极大化这些
p
(
i
)
p^{(i)}
p(i) 的范数,它们是训练样本到决策边界的距离。最后一点,我们的推导自始至终使用了这个简化假设,就是参数
θ
0
=
0
\theta_0 = 0
θ0=0 ,即便
θ
0
\theta_0
θ0 不等于
0
0
0,支持向量机仍然会找到正样本和负样本之间的大间距分隔。
1.4 核函数(一)
回顾我们之前讨论过可以使用高级数的多项式模型来解决而无法用直线进行分隔的分类问题:
为了获得上图所示的判定边界,我们的模型可能是
θ
0
+
θ
1
x
1
+
θ
2
x
2
+
θ
3
x
1
x
2
+
θ
4
x
1
2
+
θ
5
x
2
2
+
⋯
\theta_0 + \theta_1 x_1 + \theta_2 x_2 + \theta_3 x_1 x_2 + \theta_4 x_1^2 + \theta_5 x_2^2 + \cdots
θ0+θ1x1+θ2x2+θ3x1x2+θ4x12+θ5x22+⋯ 的形式。
我们可以用一系列新的特征
f
f
f 来替换模型中的每一项。例如令:
f
1
=
x
1
,
f
2
=
x
2
f
3
=
x
1
x
2
f
4
=
x
1
2
,
f
5
=
x
2
2
,
⋯
f_1 = x_1, \; f_2 = x_2 \; f_3 = x_1 x_2 \; f_4 = x_1^2, \; f_5 = x_2^2, \; \cdots
f1=x1,f2=x2f3=x1x2f4=x12,f5=x22,⋯
即得到:
h
θ
(
x
)
=
θ
1
f
1
+
θ
2
f
2
+
θ
3
f
3
+
θ
4
f
4
+
θ
5
f
5
+
⋯
h_{\theta}(x) = \theta_1 f_1 + \theta_2 f_2 + \theta_3 f_3 + \theta_4 f_4 + \theta_5 f_5 + \cdots
hθ(x)=θ1f1+θ2f2+θ3f3+θ4f4+θ5f5+⋯
然而,除了对原有的特征进行组合以外,有没有更好的方法来构造
f
1
,
f
2
,
f
3
,
⋯
f_1, f_2, f_3, \cdots
f1,f2,f3,⋯ 呢 ?我们可以利用核函数来计算出新的特征。
给定一个训练样本
x
x
x ,我们利用
x
x
x 的各个特征与我们预先选定的地标( landmarks
)
l
(
1
)
,
l
(
2
)
,
l
(
3
)
,
⋯
l^{(1)}, l^{(2)}, l^{(3)}, \cdots
l(1),l(2),l(3),⋯ 的近似程度来选取新的特征
f
1
,
f
2
,
f
3
,
⋯
f_1, f_2, f_3, \cdots
f1,f2,f3,⋯ 。
例如:
f
1
=
s
i
m
i
l
a
r
i
t
y
(
x
,
l
(
1
)
)
=
e
x
p
(
−
∣
∣
x
−
l
(
1
)
∣
∣
2
2
σ
2
)
f_1 = similarity(x, l^{(1)}) = exp^{(-\frac{||x - l^{(1)}||^2}{2\sigma^2})}
f1=similarity(x,l(1))=exp(−2σ2∣∣x−l(1)∣∣2)
其中:
∣
∣
x
−
l
(
1
)
∣
∣
2
=
∑
j
=
1
n
(
x
j
−
l
j
(
1
)
)
2
||x - l^{(1)}||^2 = \sum_{j=1}^n (x_j - l_j^{(1)})^2
∣∣x−l(1)∣∣2=j=1∑n(xj−lj(1))2
它是实例
x
x
x 中所有特征与地标
l
(
1
)
l^{(1)}
l(1) 之间的距离的和。
上例中的
s
i
m
i
l
a
r
i
t
y
(
x
,
l
(
1
)
)
similarity(x, l^{(1)})
similarity(x,l(1)) 就是核函数,具体而言,这里是一个高斯核函数( Gaussian Kernel
)。注:这个函数与正态分布没什么实际上的关系,只是看上去像而已。
这些地标的作用是什么?如果一个训练样本 x x x 与地标 l l l 之间的距离近似于 0 0 0 ,则新特征 f f f 近似于 e x p − 0 = 1 exp^{-0} = 1 exp−0=1 ,如果训练样本 x x x 与地标 l l l 之间距离较远,则近似于 e x p − ∞ ≈ 0 exp^{-\infty} \approx 0 exp−∞≈0 一个较小的数。
假设我们的训练样本含有两个特征
[
x
1
,
x
2
]
[x_1, x_2]
[x1,x2] ,给定地标
l
(
1
)
l^{(1)}
l(1) 与
σ
\sigma
σ 不同的值,见下图:
图中水平面的坐标为
(
x
1
,
x
2
)
(x_1, x_2)
(x1,x2) ,而垂直坐标轴代表
f
f
f 。可以看出,只有当
x
x
x 与
l
l
l 重合时
f
f
f 才具有最大值。随着
x
x
x 的改变
f
f
f 值改变的速率受到
σ
\sigma
σ 的控制。
在下图中,当样本处于洋红色的点位置处,因为其离
l
(
1
)
l^{(1)}
l(1) 更近,但是离
l
(
2
)
l^{(2)}
l(2) 和
l
(
3
)
l^{(3)}
l(3) 较远,因此
f
1
f_1
f1 接近
1
1
1 ,而
f
2
,
f
3
f_2, f_3
f2,f3 接近
0
0
0 。因此
h
θ
(
x
)
=
θ
1
f
1
+
θ
2
f
2
+
θ
3
f
3
>
0
h_{\theta}(x) = \theta_1 f_1 + \theta_2 f_2 + \theta_3 f_3 \gt 0
hθ(x)=θ1f1+θ2f2+θ3f3>0 ,因此预测
y
=
1
y=1
y=1 。同理可以求出,对于离
l
(
2
)
l^{(2)}
l(2) 较近的绿色点,也预测
y
=
1
y=1
y=1 ,但是对于蓝绿色的点,因为其离三个地标都较远,预测
y
=
0
y=0
y=0 。
这样,图中红色的封闭曲线所表示的范围,便是我们依据一个单一的训练样本和我们选取的地标所得出的判定边界,在预测时,我们采用的特征不是训练样本本身的特征,而是通过核函数计算出的新特征
f
1
,
f
2
,
f
3
f_1, f_2, f_3
f1,f2,f3 。
1.5 核函数(二)
考虑一下这个问题:如何选择地标?
我们通常是根据训练集的数量选择地标的数量,即如果训练集中有
m
m
m 个样本,则我们选取
m
m
m 个地标,并且令:
l
(
1
)
=
x
(
1
)
,
l
(
2
)
=
x
(
2
)
,
⋯
,
l
(
m
)
=
x
(
m
)
l^{(1)} = x^{(1)}, l^{(2)} = x^{(2)}, \cdots, l^{(m)} = x^{(m)}
l(1)=x(1),l(2)=x(2),⋯,l(m)=x(m) 。这样做的好处在于:现在我们得到的新特征是建立在原有特征与训练集中所有其他特征之间距离的基础之上的,即:
f
(
i
)
=
[
f
0
(
i
)
=
1
f
1
(
i
)
=
s
i
m
(
x
(
i
)
,
l
(
1
)
)
f
2
(
i
)
=
s
i
m
(
x
(
i
)
,
l
(
2
)
)
f
1
(
i
)
=
s
i
m
(
x
(
i
)
,
l
(
i
)
)
=
e
0
=
1
⋮
f
i
(
i
)
=
s
i
m
(
x
(
i
)
,
l
(
m
)
)
]
f^{(i)} = \begin{bmatrix} f_0^{(i)} = 1 \\ f_1^{(i)} = sim(x^{(i)}, l^{(1)}) \\ f_2^{(i)} = sim(x^{(i)}, l^{(2)}) \\ f_1^{(i)} = sim(x^{(i)}, l^{(i)}) = e^0 = 1 \\ \vdots \\ f_i^{(i)} = sim(x^{(i)}, l^{(m)}) \\ \end{bmatrix}
f(i)=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡f0(i)=1f1(i)=sim(x(i),l(1))f2(i)=sim(x(i),l(2))f1(i)=sim(x(i),l(i))=e0=1⋮fi(i)=sim(x(i),l(m))⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤
下面我们将核函数运用到支持向量机中,修改我们的支持向量机假设为:
给定 x x x ,计算新特征 f f f ,当 θ T f ≥ 0 \theta^Tf \geq 0 θTf≥0 时,预测 y = 1 y=1 y=1 ,否则反之。
相应地修改代价函数为:
∑
j
=
1
n
=
m
θ
j
2
=
θ
T
θ
\sum_{j=1}^{n=m} \theta_j^2 = \theta^T\theta
j=1∑n=mθj2=θTθ
min
θ
[
C
∑
i
=
1
m
(
y
(
i
)
c
o
s
t
1
(
θ
T
f
(
i
)
)
+
(
1
−
y
(
i
)
)
c
o
s
t
0
(
θ
T
f
(
i
)
)
]
)
+
1
2
∑
j
=
1
n
=
m
θ
j
2
]
\min_{\theta} \bigg[C\sum_{i=1}^m \bigg(y^{(i)} cost_1(\theta^Tf^{(i)}) + (1 - y^{(i)}) cost_0(\theta^Tf^{(i)})]\bigg)+ \frac{1}{2} \sum_{j=1}^{n=m} \theta_j^2\bigg]
θmin[Ci=1∑m(y(i)cost1(θTf(i))+(1−y(i))cost0(θTf(i))])+21j=1∑n=mθj2]
在具体实施过程中,我们还需要对最后的正则化项进行些微调整,在计算
∑
j
=
1
n
=
m
θ
j
2
=
θ
T
θ
\sum_{j=1}^{n=m} \theta_j^2 = \theta^T\theta
∑j=1n=mθj2=θTθ 时,我们用
θ
T
M
θ
\theta^TM\theta
θTMθ 代替
θ
T
θ
\theta^T\theta
θTθ ,其中
M
M
M 是根据我们选择的不同的核函数而确定的一个不同的矩阵。这样做的原因是为了简化计算。
理论上讲,我们也可以在逻辑回归中使用核函数,但是上面使用 M M M 来简化计算的方法不适用于逻辑回归,因为计算将非常耗费时间。
在此,我们不介绍最小化支持向量机的代价函数的方法,你可以使用现有的软件包(如liblinear
,libsvm
等)。在使用这些软件包最小化我们的代价函数之前,我们通常需要编写核函数,并且如果我们使用高斯核函数,那么在使用之前进行特征缩放是非常必要的。
另外,支持向量机也可以不使用核函数,不使用核函数又称为线性核函数(linear kernel
),当我们不采用非常复杂的函数,或者我们的训练集特征非常多而样本非常少的时候,可以采用这种不带核函数的支持向量机。
下面是支持向量机的两个参数
C
C
C 和
σ
\sigma
σ 对支持向量机模型的影响:
C
=
1
λ
C = \frac{1}{\lambda}
C=λ1
C
C
C 较大时,相当于
λ
\lambda
λ 较小,可能会导致模型过拟合,高方差;
C C C 较小时,相当于 λ \lambda λ 较大,可能会导致模型欠拟合,高偏差;
σ \sigma σ 较大时,可能会导致模型低方差,高偏差;
σ \sigma σ 较小时,可能会导致模型低偏差,高方差。
希望这些关于偏差和方差的讨论,能给你一些对于算法结果预期的直观印象。
1.6 支持向量机的使用指导
到目前为止,我们已经讨论了 SVM
比较抽象的层面,在这个视频中我将要讨论到为了运行或者运用 SVM
。你实际上所需要的是:支持向量机算法的优化问题。我们不建议你自己写软件来求解参数,因为基本上很少有人考虑过自己写代码来转换矩阵,或者求一个数的平方根等等,我们只需知道如何去调用库函数来实现这些功能。同样的,用以解决 SVM
最优化问题的软件很复杂,且已经有研究者做了很多年数值优化了。有许多好的软件库,用得最多的两个是 liblinear
和 libsvm
,还有其它很多类似的功能库,特别是在Python中,强大的第三方库使我们省去了很多重复造轮子的工作。
在高斯核函数之外我们还有其他一些选择,如:
多项式核函数(Polynomial Kernel)
字符串核函数(String kernel)
卡方核函数( chi-square kernel)
直方图交集核函数(histogram intersection kernel)
等等…
这些核函数的目标也都是根据训练集和地标之间的距离来构建新特征,这些核函数需要满足 Mercer's
定理,才能被支持向量机的优化软件正确处理。
多类分类问题:
假设我们利用之前介绍的一对多方法来解决一个多类分类问题。如果一共有 k k k 个类,则我们需要 k k k 个模型,以及包含 k k k 个参数的向量 θ \theta θ 。我们同样也可以训练 k k k 个支持向量机来解决多类分类问题。但是大多数支持向量机软件包都有内置的多类分类功能,我们只需直接使用即可。
尽管你不去写你自己的 SVM
的优化软件,但是你也需要做几件事:
1、选择参数 C C C 。我们在之前讨论过误差、方差在这方面的性质。
2、选择内核参数或你想要使用的相似函数,其中一个选择是:我们选择不需要任何内核参数的SVM
,也叫线性核函数。因此,如果有人说他使用了线性核的 SVM
,这就意味者他使用了不带有核函数的支持向量机。
从逻辑回归模型,我们得到了支持向量机模型,在两者之间,我们应该如何选择呢?
下面是一些普遍使用的准则:
n n n 为特征数, m m m 为训练样本数。
(1)如果相较于 m m m 而言, n n n 要大许多,即训练集数据量不够支持我们训练一个复杂的非线性模型,我们选用逻辑回归模型或者不带核函数的支持向量机。
(2)如果
n
n
n 较小,而且
m
m
m 大小中等,例如
n
n
n 在 1-1000
之间,而
m
m
m 在 10-10000
之间,使用高斯核函数的支持向量机。
(3)如果
n
n
n 较小,而
m
m
m 较大,例如
n
n
n 在 1-1000
之间,而
m
m
m 大于 50000
,则使用支持向量机会非常慢,解决方案是创造、增加更多的特征,然后使用逻辑回归或不带核函数的支持向量机。
值得一提的是,神经网络在以上三种情况下都可能会有较好的表现,但是训练神经网络可能非常慢,选择支持向量机的原因主要在于它的代价函数是凸函数,不存在局部最小值。
算法确实很重要,但是通常更加重要的是:你有多少数据,你是否擅长做误差分析,对学习算法有多熟练,能否指出如何设定新的特征变量和找出其他能决定你学习算法的变量等方法,通常这些会比你使用逻辑回归还是 SVM
更加重要。但是,前面已经说过了, SVM
仍然被广泛认为是一种最强大的学习算法,这是一个体系,包含了什么时候用一个有效的方法去学习复杂的非线性函数。因此,实际上与 逻辑回归
、神经网络
、SVM
一起使用这些方法来提高学习算法,你会快速找到最合适的解决方案。
1.7 SVM推导(统计学习方法)
① 支持向量机最简单的情况是线性可分支持向量机,或硬间隔支持向量机。构建它的条件是训练数据线性可分。其学习策略是最大间隔法。可以表示为凸二次规划问题,其原始最优化问题为:
min
w
,
b
1
2
∣
∣
w
∣
∣
2
subject to
y
i
(
w
x
i
+
b
)
−
1
≥
0
,
i
=
1
,
2
,
⋯
,
N
\min_{w, b} \frac{1}{2} ||w||^2 \quad \text{subject to \quad $y_i (wx_i + b) - 1 \geq 0, \; i = 1, 2, \cdots, N$}
w,bmin21∣∣w∣∣2subject to yi(wxi+b)−1≥0,i=1,2,⋯,N
求得最优化问题的解为
w
∗
w^{*}
w∗ ,
b
∗
b^{*}
b∗ ,得到线性可分支持向量机,分离超平面是:
w
∗
⋅
x
+
b
∗
=
0
w^{*} \cdot x + b^{*} = 0
w∗⋅x+b∗=0
分类决策函数是:
f
(
x
)
=
s
i
g
n
(
w
∗
⋅
x
+
b
∗
)
f(x) = sign(w^{*} \cdot x + b^{*})
f(x)=sign(w∗⋅x+b∗)
最大间隔法中,函数间隔与几何间隔是重要的概念。
线性可分支持向量机的最优解存在且唯一。位于间隔边界上的实例点为支持向量。最优分离超平面由支持向量完全决定。 二次规划问题的对偶问题是:
min
α
[
1
2
∑
i
=
1
N
∑
j
=
1
N
α
i
α
j
y
i
y
j
(
x
i
⋅
x
j
)
−
∑
i
=
1
N
α
i
]
\min_{\alpha} \bigg[\frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N \alpha_i \alpha_j y_i y_j (x_i \cdot x_j) - \sum_{i=1}^N \alpha_i \bigg]
αmin[21i=1∑Nj=1∑Nαiαjyiyj(xi⋅xj)−i=1∑Nαi]
subject to
∑
i
=
1
N
α
i
y
i
=
0
,
α
i
≥
0
,
i
=
1
,
2
,
⋯
,
N
\text{subject to \quad $\sum_{i=1}^N \alpha_i y_i = 0, \quad \alpha_i \geq 0, \quad i = 1, 2, \cdots, N$}
subject to ∑i=1Nαiyi=0,αi≥0,i=1,2,⋯,N
通常,通过求解对偶问题学习线性可分支持向量机,即首先求解对偶问题的最优值
α
∗
\alpha^{*}
α∗ ,然后求最优值
w
∗
w^{*}
w∗ 和
b
∗
b^{*}
b∗ ,得出分离超平面和分类决策函数。
② 现实中训练数据是线性可分的情形较少,训练数据往往是近似线性可分的,这时使用线性支持向量机,或软间隔支持向量机。线性支持向量机是最基本的支持向量机。
对于噪声或例外,通过引入松弛变量
ξ
i
\xi_i
ξi ,使其“可分”,得到线性支持向量机学习的凸二次规划问题,其原始最优化问题是:
min
w
,
b
,
ξ
(
1
2
∣
∣
w
∣
∣
2
+
C
∑
i
=
1
N
ξ
i
)
\min_{w, b, \xi} \bigg(\frac{1}{2} ||w||^2 + C \sum_{i=1}^N \xi_i\bigg)
w,b,ξmin(21∣∣w∣∣2+Ci=1∑Nξi)
subject to
y
i
(
w
x
i
+
b
)
≥
1
−
ξ
i
,
i
=
1
,
2
,
⋯
,
N
\text{subject to \quad $y_i (wx_i + b) \geq 1 - \xi_i, \; i = 1, 2, \cdots, N$}
subject to yi(wxi+b)≥1−ξi,i=1,2,⋯,N
ξ
i
≥
0
,
i
=
1
,
2
,
⋯
,
N
\xi_i \geq 0, \quad i = 1, 2, \cdots, N
ξi≥0,i=1,2,⋯,N
求解原始最优化问题的解
w
∗
w^{*}
w∗ 和
b
∗
b^{*}
b∗ ,得到线性支持向量机,其分离超平面为:
w
∗
⋅
x
+
b
∗
=
0
w^{*} \cdot x + b^{*} = 0
w∗⋅x+b∗=0
分类决策函数为:
f
(
x
)
=
s
i
g
n
(
w
∗
⋅
x
+
b
∗
)
f(x) = sign(w^{*} \cdot x + b^{*})
f(x)=sign(w∗⋅x+b∗)
此时线性可分支持向量机的解
w
∗
w^{*}
w∗ 唯一但
b
∗
b^{*}
b∗ 不唯一。对偶问题是:
min
α
[
1
2
∑
i
=
1
N
∑
j
=
1
N
α
i
α
j
y
i
y
j
(
x
i
⋅
x
j
)
−
∑
i
=
1
N
α
i
]
\min_{\alpha} \bigg[\frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N \alpha_i \alpha_j y_i y_j (x_i \cdot x_j) - \sum_{i=1}^N \alpha_i \bigg]
αmin[21i=1∑Nj=1∑Nαiαjyiyj(xi⋅xj)−i=1∑Nαi]
subject to
∑
i
=
1
N
α
i
y
i
=
0
,
0
≤
α
i
≤
C
,
i
=
1
,
2
,
⋯
,
N
\text{subject to \quad $\sum_{i=1}^N \alpha_i y_i = 0, \quad 0 \leq \alpha_i \leq C, \quad i = 1, 2, \cdots, N$}
subject to ∑i=1Nαiyi=0,0≤αi≤C,i=1,2,⋯,N
线性支持向量机的对偶学习算法,首先求解对偶问题得到最优解
α
∗
\alpha^{*}
α∗ ,然后求原始问题最优解
w
∗
w^{*}
w∗ 和
b
∗
b^{*}
b∗ ,得出分离超平面和分类决策函数。
对偶问题的解 α ∗ \alpha^{*} α∗ 中满足 α i ∗ > 0 \alpha_i^{*} \gt 0 αi∗>0 的实例点 x i x_i xi 称为支持向量。支持向量可在间隔边界上,也可在间隔边界与分离超平面之间,或者在分离超平面误分一侧。最优分离超平面由支持向量完全决定。
线性支持向量机学习等价于最小化二阶范数正则化的合页函数:
∑
i
=
1
N
[
1
−
y
i
(
w
x
i
+
b
)
]
+
+
λ
∣
∣
w
∣
∣
2
\sum_{i=1}^N [1 - y_i(wx_i + b)]_{+} + \lambda||w||^2
i=1∑N[1−yi(wxi+b)]++λ∣∣w∣∣2
③ 非线性支持向量机
对于输入空间中的非线性分类问题,可以通过非线性变换将它转化为某个高维特征空间中的线性分类问题,在高维特征空间中学习线性支持向量机。由于在线性支持向量机学习的对偶问题里,目标函数和分类决策函数都只涉及实例与实例之间的内积,所以不需要显式地指定非线性变换,而是用核函数来替换当中的内积。核函数表示,通过一个非线性转换后的两个实例间的内积。具体地,
K
(
x
,
z
)
K(x, z)
K(x,z) 是一个核函数,或正定核,意味着存在一个从输入空间
x
x
x 到特征空间的映射
χ
→
H
\chi \rightarrow \mathcal{H}
χ→H ,对任意
χ
\chi
χ ,有对称函数:
K
(
x
,
z
)
=
ϕ
(
x
)
⋅
ϕ
(
z
)
K(x, z) = \phi (x) \cdot \phi (z)
K(x,z)=ϕ(x)⋅ϕ(z)
x
i
∈
χ
,
i
=
1
,
2
,
⋯
,
m
x_i \in \chi, \quad i = 1, 2, \cdots, m
xi∈χ,i=1,2,⋯,m
任意正整数
m
m
m ,对称函数
K
(
x
,
z
)
K(x, z)
K(x,z) 对应的 Gram
矩阵是半正定的。
所以,在线性支持向量机学习的对偶问题中,用核函数
K
(
x
,
z
)
K(x, z)
K(x,z) 替代内积,求解得到的就是非线性支持向量机:
f
(
x
)
=
s
i
g
n
(
∑
i
=
1
N
α
i
∗
y
i
(
x
,
x
i
)
+
b
∗
)
f(x) = sign \bigg( \sum_{i=1}^N \alpha_i^{*}y_i (x, x_i) + b^{*}\bigg)
f(x)=sign(i=1∑Nαi∗yi(x,xi)+b∗)
④ SMO 算法
SMO
算法是支持向量机学习的一种快速算法,其特点是不断地将原二次规划问题分解为只有两个变量的二次规划子问题,并对子问题进行解析求解,直到所有变量满足 KKT
条件为止。这样通过启发式的方法得到原二次规划问题的最优解。因为子问题有解析解,所以每次计算子问题都很快,虽然计算子问题次数很多,但在总体上还是高效的。
分离超平面: w T x + b = 0 w^Tx + b = 0 wTx+b=0
点到直线距离: r = ∣ w T x + b ∣ ∣ ∣ w ∣ ∣ 2 r = \frac{|w^Tx + b|}{||w||_2} r=∣∣w∣∣2∣wTx+b∣
∣
∣
w
∣
∣
2
||w||_2
∣∣w∣∣2 为 2-范数
:
∣
∣
w
∣
∣
2
=
(
∑
i
=
1
m
w
i
2
)
1
/
2
||w||_2 = (\sum_{i=1}^m w_i^2)^{1/2}
∣∣w∣∣2=(∑i=1mwi2)1/2
直线为超平面,样本可表示为:
w
T
x
+
b
≥
+
1
w
T
x
+
b
≤
+
1
w^Tx + b \geq +1 \\ w^Tx + b \leq +1
wTx+b≥+1wTx+b≤+1
margin:
函数间隔: l a b e l ( w T x + b ) o r y i ( w T x + b ) label(w^Tx + b) \quad or \quad y_i(w^Tx + b) label(wTx+b)oryi(wTx+b)
几何间隔: r = l a b e l ∣ w T x + b ∣ ∣ ∣ w ∣ ∣ 2 r = \frac{label|w^Tx + b|}{||w||_2} r=∣∣w∣∣2label∣wTx+b∣
当数据被正确分类时,几何间隔就是点到超平面的距离。
为了求几何间隔最大,SVM
基本问题可以转化为求解(
r
∗
∣
∣
w
∣
∣
\frac{r^{*}}{||w||}
∣∣w∣∣r∗ 为几何间隔,
r
∗
r^{*}
r∗ 为函数间隔):
max
r
∗
∣
∣
w
∣
∣
subject to
y
i
(
w
T
x
i
+
b
)
≥
r
∗
,
i
=
1
,
2
,
⋯
,
m
\max \frac{r^{*}}{||w||} \\ \text{subject to \quad $y_i(w^Tx_i + b) \geq r^{*}, \quad i = 1, 2, \cdots, m$}
max∣∣w∣∣r∗subject to yi(wTxi+b)≥r∗,i=1,2,⋯,m
分类点几何间隔最大,同时被正确分类。但这个方程并非凸函数求解,所以要 1) 先将方程转化为凸函数,2) 用拉格朗日乘子法和 KKT
条件求解对偶问题。
-
转化为凸函数:
先令 r ∗ = 1 r^{*} = 1 r∗=1 ,方便计算(参照衡量,不影响评价结果):
max 1 ∣ ∣ w ∣ ∣ subject to y i ( w T x i + b ) ≥ 1 , i = 1 , 2 , ⋯ , m \max \frac{1}{||w||} \\ \text{subject to \quad $y_i(w^Tx_i + b) \geq 1, \quad i = 1, 2, \cdots, m$} max∣∣w∣∣1subject to yi(wTxi+b)≥1,i=1,2,⋯,m
再将 max 1 ∣ ∣ w ∣ ∣ \max \frac{1}{||w||} max∣∣w∣∣1 转化成 min 1 2 ∣ ∣ w ∣ ∣ 2 \min \frac{1}{2}||w||^2 min21∣∣w∣∣2 求解凸函数,1/2
是为了求导之后方便计算:
min 1 2 ∣ ∣ w ∣ ∣ 2 subject to y i ( w T x i + b ) ≥ 1 , i = 1 , 2 , ⋯ , m \min \frac{1}{2}||w||^2 \\ \text{subject to \quad $y_i(w^Tx_i + b) \geq 1, \quad i = 1, 2, \cdots, m$} min21∣∣w∣∣2subject to yi(wTxi+b)≥1,i=1,2,⋯,m -
用拉格朗日乘子法和
KKT
条件求解最优值:
min 1 2 ∣ ∣ w ∣ ∣ 2 subject to − y i ( w T x i + b ) + 1 ≤ 0 , i = 1 , 2 , ⋯ , m \min \frac{1}{2}||w||^2 \\ \text{subject to \quad $-y_i(w^Tx_i + b) + 1 \leq 0, \quad i = 1, 2, \cdots, m$} min21∣∣w∣∣2subject to −yi(wTxi+b)+1≤0,i=1,2,⋯,m
整合成:
L ( w , b , α ) = 1 2 ∣ ∣ w ∣ ∣ 2 + ∑ i = 1 m α i ( − y i ( w T x i + b ) + 1 ) L(w, b, \alpha) = \frac{1}{2}||w||^2 + \sum_{i=1}^m \alpha_i \bigg(-y_i(w^Tx_i + b) + 1\bigg) L(w,b,α)=21∣∣w∣∣2+i=1∑mαi(−yi(wTxi+b)+1)
推导: min f ( x ) = min max L ( w , b , α ) ≥ max min L ( w , b , α ) \min f(x) = \min \max L(w, b, \alpha) \geq \max \min L(w, b, \alpha) minf(x)=minmaxL(w,b,α)≥maxminL(w,b,α)
根据 KKT
条件有:
∂
∂
w
L
(
w
,
b
,
α
)
=
w
−
∑
i
=
1
m
α
i
y
i
x
i
=
0
⇔
w
=
∑
i
=
1
m
α
i
y
i
x
i
∂
∂
b
L
(
w
,
b
,
α
)
=
∑
i
=
1
m
α
i
y
i
=
0
\frac{\partial}{\partial w} L(w, b, \alpha) = w - \sum_{i=1}^m \alpha_i y_i x_i = 0 \\ \Leftrightarrow w = \sum_{i=1}^m \alpha_i y_i x_i \\ \frac{\partial}{\partial b} L(w, b, \alpha) = \sum_{i=1}^m \alpha_i y_i = 0
∂w∂L(w,b,α)=w−i=1∑mαiyixi=0⇔w=i=1∑mαiyixi∂b∂L(w,b,α)=i=1∑mαiyi=0
代入
L
(
w
,
b
,
α
)
L(w, b, \alpha)
L(w,b,α) 中:
min
L
(
w
,
b
,
α
)
=
1
2
∣
∣
w
∣
∣
2
+
∑
i
=
1
m
α
i
(
−
y
i
(
w
T
x
i
+
b
)
+
1
)
=
1
2
w
T
w
−
∑
i
=
1
m
α
i
y
i
w
T
x
i
−
b
∑
i
=
1
m
α
i
y
i
+
∑
i
=
1
m
α
i
=
1
2
w
T
∑
i
=
1
m
α
i
y
i
x
i
−
∑
i
=
1
m
α
i
y
i
w
T
x
i
+
∑
i
=
1
m
α
i
=
∑
i
=
1
m
α
i
−
1
2
∑
i
=
1
m
α
i
y
i
w
T
x
i
=
∑
i
=
1
m
α
i
−
1
2
∑
i
,
j
=
1
m
α
i
α
j
y
i
y
j
(
x
i
⋅
x
j
)
\min L(w, b, \alpha) = \frac{1}{2}||w||^2 + \sum_{i=1}^m \alpha_i \bigg(-y_i(w^Tx_i + b) + 1\bigg) \\ = \frac{1}{2}w^Tw - \sum_{i=1}^m \alpha_i y_i w^T x_i - b\sum_{i=1}^m \alpha_i y_i + \sum_{i=1}^m \alpha_i \\ = \frac{1}{2}w^T \sum_{i=1}^m \alpha_i y_i x_i - \sum_{i=1}^m \alpha_i y_i w^T x_i + \sum_{i=1}^m \alpha_i \\ = \sum_{i=1}^m \alpha_i - \frac{1}{2} \sum_{i=1}^m \alpha_i y_i w^T x_i \\ = \sum_{i=1}^m \alpha_i - \frac{1}{2} \sum_{i, j=1}^m \alpha_i \alpha_j y_i y_j (x_i \cdot x_j)
minL(w,b,α)=21∣∣w∣∣2+i=1∑mαi(−yi(wTxi+b)+1)=21wTw−i=1∑mαiyiwTxi−bi=1∑mαiyi+i=1∑mαi=21wTi=1∑mαiyixi−i=1∑mαiyiwTxi+i=1∑mαi=i=1∑mαi−21i=1∑mαiyiwTxi=i=1∑mαi−21i,j=1∑mαiαjyiyj(xi⋅xj)
再把 max
问题转成 min
问题:
max
[
∑
i
=
1
m
α
i
−
1
2
∑
i
,
j
=
1
m
α
i
α
j
y
i
y
j
(
x
i
⋅
x
j
)
]
=
min
[
1
2
∑
i
,
j
=
1
m
α
i
α
j
y
i
y
j
(
x
i
⋅
x
j
)
−
∑
i
=
1
m
α
i
]
\max \bigg[\sum_{i=1}^m \alpha_i - \frac{1}{2} \sum_{i, j=1}^m \alpha_i \alpha_j y_i y_j (x_i \cdot x_j)\bigg] \\ = \min \bigg[\frac{1}{2} \sum_{i, j=1}^m \alpha_i \alpha_j y_i y_j (x_i \cdot x_j) - \sum_{i=1}^m \alpha_i \bigg]
max[i=1∑mαi−21i,j=1∑mαiαjyiyj(xi⋅xj)]=min[21i,j=1∑mαiαjyiyj(xi⋅xj)−i=1∑mαi]
subject to
∑
i
=
1
m
α
i
y
i
=
0
,
α
i
≥
0
,
i
=
1
,
2
,
⋯
,
m
\text{subject to \quad $\sum_{i=1}^m \alpha_i y_i = 0, \quad \alpha_i \geq 0, \quad i = 1, 2, \cdots, m$}
subject to ∑i=1mαiyi=0,αi≥0,i=1,2,⋯,m
以上为 SVM
对偶问题的对偶形式。
kernel:
在低维空间计算获得高维空间的计算结果,也就是说计算结果满足高维(满足高维,才能说明高维下线性可分)。
soft margin & slack variable:
引入松弛变量
ξ
≥
0
\xi \geq 0
ξ≥0 ,对应数据点允许偏离的 functional margin
的量。
目标函数:
min
w
,
b
,
ξ
(
1
2
∣
∣
w
∣
∣
2
+
C
∑
i
=
1
N
ξ
i
)
\min_{w, b, \xi} \bigg(\frac{1}{2} ||w||^2 + C \sum_{i=1}^N \xi_i\bigg)
w,b,ξmin(21∣∣w∣∣2+Ci=1∑Nξi)
subject to
y
i
(
w
x
i
+
b
)
≥
1
−
ξ
i
,
i
=
1
,
2
,
⋯
,
N
\text{subject to \quad $y_i (wx_i + b) \geq 1 - \xi_i, \; i = 1, 2, \cdots, N$}
subject to yi(wxi+b)≥1−ξi,i=1,2,⋯,N
对偶问题:
max
[
∑
i
=
1
m
α
i
−
1
2
∑
i
,
j
=
1
m
α
i
α
j
y
i
y
j
(
x
i
⋅
x
j
)
]
=
min
[
1
2
∑
i
,
j
=
1
m
α
i
α
j
y
i
y
j
(
x
i
⋅
x
j
)
−
∑
i
=
1
m
α
i
]
\max \bigg[\sum_{i=1}^m \alpha_i - \frac{1}{2} \sum_{i, j=1}^m \alpha_i \alpha_j y_i y_j (x_i \cdot x_j)\bigg] \\ = \min \bigg[\frac{1}{2} \sum_{i, j=1}^m \alpha_i \alpha_j y_i y_j (x_i \cdot x_j) - \sum_{i=1}^m \alpha_i \bigg]
max[i=1∑mαi−21i,j=1∑mαiαjyiyj(xi⋅xj)]=min[21i,j=1∑mαiαjyiyj(xi⋅xj)−i=1∑mαi]
subject to
∑
i
=
1
m
α
i
y
i
=
0
,
0
≤
α
i
≤
C
,
i
=
1
,
2
,
⋯
,
m
\text{subject to \quad $\sum_{i=1}^m \alpha_i y_i = 0, \quad 0 \leq \alpha_i \leq C, \quad i = 1, 2, \cdots, m$}
subject to ∑i=1mαiyi=0,0≤αi≤C,i=1,2,⋯,m
Sequantial Minimal Optimization(SMO):
首先定义特征到结果的输出函数: u = w T x + b u = w^Tx + b u=wTx+b ,因为 w = ∑ i = 1 m α i y i x i w = \sum_{i=1}^m \alpha_i y_i x_i w=∑i=1mαiyixi ,有 u = ∑ i = 1 m y i α i K ( x i , x ) + b u = \sum_{i=1}^m y_i \alpha_i K(x_i, x) +b u=∑i=1myiαiK(xi,x)+b 。
即:
max
[
∑
i
=
1
m
α
i
−
1
2
∑
i
=
1
m
∑
j
=
1
m
α
i
α
j
y
i
y
j
<
ϕ
(
x
i
)
T
,
ϕ
(
x
j
)
>
]
\max \bigg[\sum_{i=1}^m \alpha_i - \frac{1}{2} \sum_{i=1}^m \sum_{j=1}^m \alpha_i \alpha_j y_i y_j \lt \phi(x_i)^T, \phi(x_j) \gt \bigg]
max[i=1∑mαi−21i=1∑mj=1∑mαiαjyiyj<ϕ(xi)T,ϕ(xj)>]
subject to
∑
i
=
1
m
α
i
y
i
=
0
,
α
i
≥
0
,
i
=
1
,
2
,
⋯
,
m
\text{subject to \quad $\sum_{i=1}^m \alpha_i y_i = 0, \quad \alpha_i \geq 0, \quad i = 1, 2, \cdots, m$}
subject to ∑i=1mαiyi=0,αi≥0,i=1,2,⋯,m
Python代码实现:
# 导包
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
%matplotlib inline
# 获取特征值和目标值
def create_data():
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
data = np.array(df.iloc[:100, [0, 1, -1]])
for i in range(len(data)):
if data[i,-1] == 0:
data[i,-1] = -1
# print(data)
return data[:,:2], data[:,-1]
# 拆分数据集为训练集和测试集
X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# 绘制出样本分布的散点图
plt.figure(figsize=(12, 8), dpi=80)
plt.scatter(X[:50,0],X[:50,1], label='0')
plt.scatter(X[50:,0],X[50:,1], label='1')
plt.xlabel('sepal length', fontsize=16)
plt.ylabel('sepal width', fontsize=16)
plt.legend()
plt.show()
# svm算法实现
class SVM:
def __init__(self, max_iter=100, kernel='linear'):
self.max_iter = max_iter
self._kernel = kernel
def init_args(self, features, labels):
self.m, self.n = features.shape
self.X = features
self.Y = labels
self.b = 0.0
# 将Ei保存在一个列表里
self.alpha = np.ones(self.m)
self.E = [self._E(i) for i in range(self.m)]
# 松弛变量
self.C = 1.0
def _KKT(self, i):
y_g = self._g(i) * self.Y[i]
if self.alpha[i] == 0:
return y_g >= 1
elif 0 < self.alpha[i] < self.C:
return y_g == 1
else:
return y_g <= 1
# g(x)预测值,输入xi(X[i])
def _g(self, i):
r = self.b
for j in range(self.m):
r += self.alpha[j] * self.Y[j] * self.kernel(self.X[i], self.X[j])
return r
# 核函数
def kernel(self, x1, x2):
if self._kernel == 'linear':
return sum([x1[k] * x2[k] for k in range(self.n)])
elif self._kernel == 'poly':
return (sum([x1[k] * x2[k] for k in range(self.n)]) + 1)**2
return 0
# E(x)为g(x)对输入x的预测值和y的差
def _E(self, i):
return self._g(i) - self.Y[i]
def _init_alpha(self):
# 外层循环首先遍历所有满足0<a<C的样本点,检验是否满足KKT
index_list = [i for i in range(self.m) if 0 < self.alpha[i] < self.C]
# 否则遍历整个训练集
non_satisfy_list = [i for i in range(self.m) if i not in index_list]
index_list.extend(non_satisfy_list)
for i in index_list:
if self._KKT(i):
continue
E1 = self.E[i]
# 如果E2是+,选择最小的;如果E2是负的,选择最大的
if E1 >= 0:
j = min(range(self.m), key=lambda x: self.E[x])
else:
j = max(range(self.m), key=lambda x: self.E[x])
return i, j
def _compare(self, _alpha, L, H):
if _alpha > H:
return H
elif _alpha < L:
return L
else:
return _alpha
def fit(self, features, labels):
self.init_args(features, labels)
for t in range(self.max_iter):
# train
i1, i2 = self._init_alpha()
# 边界
if self.Y[i1] == self.Y[i2]:
L = max(0, self.alpha[i1] + self.alpha[i2] - self.C)
H = min(self.C, self.alpha[i1] + self.alpha[i2])
else:
L = max(0, self.alpha[i2] - self.alpha[i1])
H = min(self.C, self.C + self.alpha[i2] - self.alpha[i1])
E1 = self.E[i1]
E2 = self.E[i2]
# eta=K11+K22-2K12
eta = self.kernel(self.X[i1], self.X[i1]) + self.kernel(
self.X[i2],
self.X[i2]) - 2 * self.kernel(self.X[i1], self.X[i2])
if eta <= 0:
# print('eta <= 0')
continue
alpha2_new_unc = self.alpha[i2] + self.Y[i2] * (
E1 - E2) / eta #此处有修改,根据书上应该是E1 - E2,书上130-131页
alpha2_new = self._compare(alpha2_new_unc, L, H)
alpha1_new = self.alpha[i1] + self.Y[i1] * self.Y[i2] * (
self.alpha[i2] - alpha2_new)
b1_new = -E1 - self.Y[i1] * self.kernel(self.X[i1], self.X[i1]) * (
alpha1_new - self.alpha[i1]) - self.Y[i2] * self.kernel(
self.X[i2],
self.X[i1]) * (alpha2_new - self.alpha[i2]) + self.b
b2_new = -E2 - self.Y[i1] * self.kernel(self.X[i1], self.X[i2]) * (
alpha1_new - self.alpha[i1]) - self.Y[i2] * self.kernel(
self.X[i2],
self.X[i2]) * (alpha2_new - self.alpha[i2]) + self.b
if 0 < alpha1_new < self.C:
b_new = b1_new
elif 0 < alpha2_new < self.C:
b_new = b2_new
else:
# 选择中点
b_new = (b1_new + b2_new) / 2
# 更新参数
self.alpha[i1] = alpha1_new
self.alpha[i2] = alpha2_new
self.b = b_new
self.E[i1] = self._E(i1)
self.E[i2] = self._E(i2)
return 'train done!'
def predict(self, data):
r = self.b
for i in range(self.m):
r += self.alpha[i] * self.Y[i] * self.kernel(data, self.X[i])
return 1 if r > 0 else -1
def score(self, X_test, y_test):
right_count = 0
for i in range(len(X_test)):
result = self.predict(X_test[i])
if result == y_test[i]:
right_count += 1
return right_count / len(X_test)
def _weight(self):
# linear model
yx = self.Y.reshape(-1, 1) * self.X
self.w = np.dot(yx.T, self.alpha)
return self.w
# 训练SVM模型
svm = SVM(max_iter=100)
svm.fit(X_train, y_train)
# result
# 'train done!'
# 查看训练后模型的准确率
svm.score(X_test, y_test)
# result
# 0.52