既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
=
0
\nabla f\left(x{*}\right)+\sum_{i=1}{p} \lambda_{i} \nabla h_{i}\left(x{*}\right)+\sum_{j=1}{q} \mu_{k} \nabla g_{k}\left(x^{*}\right)=0
∇f(x∗)+∑i=1pλi∇hi(x∗)+∑j=1qμk∇gk(x∗)=0
3. λ
i
≠
0
,
μ
k
≥
0
,
μ
k
g
k
(
x
∗
)
=
0
\lambda_{i} \neq 0, \mu_{k} \geq 0, \mu_{k} g_{k}\left(x^{*}\right)=0
λi̸=0,μk≥0,μkgk(x∗)=0
我们这里的问题是满足 KKT 条件的(首先已经满足Slater条件,再者f和gi也都是可微的,即L对w和b都可导),因此现在我们便转化为求解第二个问题。
也就是说,原始问题通过满足KKT条件,已经转化成了对偶问题。而求解这个对偶学习问题,分为3个步骤:首先要让L(w,b,a) 关于 w 和 b 最小化,然后求对
α
\alpha
α的极大,最后利用SMO算法求解对偶问题中的拉格朗日乘子。
对偶问题求解的3个步骤
- 首先固定
α
\alpha
α,要让 L 关于 w 和 b 最小化,我们分别对w,b求偏导数,即令 ∂L/∂w 和 ∂L/∂b 等于零
∂
L
∂
w
=
0
⇒
w
=
∑
i
=
1
n
α
i
y
i
x
i
∂
L
∂
b
=
0
⇒
∑
i
=
1
n
α
i
y
i
=
0
\begin{aligned} \frac{\partial \mathcal{L}}{\partial w} &=0 \Rightarrow w=\sum_{i=1}^{n} \alpha_{i} y_{i} x_{i} \ \frac{\partial \mathcal{L}}{\partial b} &=0 \Rightarrow \sum_{i=1}^{n} \alpha_{i} y_{i}=0 \end{aligned}
∂w∂L∂b∂L=0⇒w=i=1∑nαiyixi=0⇒i=1∑nαiyi=0
将以上结果代入之前的L:
L
(
w
,
b
,
α
)
=
1
2
∥
w
∥
2
−
∑
i
=
1
n
α
i
(
y
i
(
w
T
x
i
b
)
−
1
)
\mathcal{L}(w, b, \alpha)=\frac{1}{2}|w|{2}-\sum_{i=1}{n} \alpha_{i}\left(y_{i}\left(w^{T} x_{i}+b\right)-1\right)
L(w,b,α)=21∥w∥2−∑i=1nαi(yi(wTxi+b)−1)
得到:
L
(
w
,
b
,
α
)
=
1
2
∑
i
,
j
=
1
n
α
i
α
j
y
i
y
j
x
i
T
x
j
−
∑
i
,
j
=
1
n
α
i
α
j
y
i
y
j
x
i
T
x
j
−
b
∑
i
=
1
n
α
i
y
i
∑
i
=
1
n
α
i
=
∑
i
=
1
n
α
i
−
1
2
∑
i
,
j
=
1
n
α
i
α
j
y
i
y
j
x
i
T
x
j
\begin{aligned} \mathcal{L}(w, b, \alpha) &=\frac{1}{2} \sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j}-\sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j}-b \sum_{i=1}^{n} \alpha_{i} y_{i}+\sum_{i=1}^{n} \alpha_{i} \ &=\sum_{i=1}^{n} \alpha_{i}-\frac{1}{2} \sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j} \end{aligned}
L(w,b,α)=21i,j=1∑nαiαjyiyjxiTxj−i,j=1∑nαiαjyiyjxiTxj−bi=1∑nαiyi+i=1∑nαi=i=1∑nαi−21i,j=1∑nαiαjyiyjxiTxj
具体推导过程是比较复杂的,如下所示:
最后,得到:
L
(
w
,
b
,
α
)
=
1
2
∑
i
,
j
=
1
n
α
i
α
j
y
i
y
j
x
i
T
x
j
−
∑
i
,
j
=
1
n
α
i
α
j
y
i
y
j
x
i
T
x
j
−
b
∑
i
=
1
n
α
i
y
i
∑
i
=
1
n
α
i
=
∑
i
=
1
n
α
i
−
1
2
∑
i
,
j
=
1
n
α
i
α
j
y
i
y
j
x
i
T
x
j
\begin{aligned} \mathcal{L}(w, b, \alpha) &=\frac{1}{2} \sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j}-\sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j}-b \sum_{i=1}^{n} \alpha_{i} y_{i}+\sum_{i=1}^{n} \alpha_{i} \ &=\sum_{i=1}^{n} \alpha_{i}-\frac{1}{2} \sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j} \end{aligned}
L(w,b,α)=21i,j=1∑nαiαjyiyjxiTxj−i,j=1∑nαiαjyiyjxiTxj−bi=1∑nαiyi+i=1∑nαi=i=1∑nαi−21i,j=1∑nαiαjyiyjxiTxj
“倒数第4步”推导到“倒数第3步”使用了线性代数的转置运算,由于ai和yi都是实数,因此转置后与自身一样。“倒数第3步”推导到“倒数第2步”使用了(a+b+c+…)(a+b+c+…)=aa+ab+ac+ba+bb+bc+…的乘法运算法则。最后一步是上一步的顺序调整。
从上面的最后一个式子,我们可以看出,此时的拉格朗日函数只包含了一个变量,那就是
α
i
\alpha_{i}
αi(求出了
α
i
\alpha_{i}
αi便能求出w,和b,由此可见,则核心问题:分类函数
f
(
x
)
=
w
T
x
b
f(x)=w^{T} x+b
f(x)=wTx+b也就可以轻而易举的求出来了)。
- 求对
α
\alpha
α的极大,即是关于对偶问题的最优化问题。经过上面第一个步骤的求w和b,得到的拉格朗日函数式子已经没有了变量w,b,只有
α
\alpha
α。从上面的式子得到:
max
α
≥
0
∑
i
=
1
m
α
i
−
1
2
∑
i
,
j
=
1
m
α
i
α
j
y
i
y
j
x
i
T
x
j
s.t.
∑
i
=
1
m
α
i
y
i
.
=
0
α
i
≥
0
,
i
=
1
,
2
,
…
,
m
\begin{array}{l}{\max _{\alpha \geq 0} \sum_{i=1}^{m} \alpha_{i}-\frac{1}{2} \sum_{i, j=1}^{m} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j}} \ {\text {s.t.} \sum_{i=1}^{m} \alpha_{i} y_{i} .=0} \ {\alpha_{i} \geq 0, i=1,2, \ldots, m}\end{array}
maxα≥0∑i=1mαi−21∑i,j=1mαiαjyiyjxiTxjs.t.∑i=1mαiyi.=0αi≥0,i=1,2,…,m
这样,求出了
α
i
\alpha_{i}
αi,根据
w
=
∑
i
=
1
m
α
i
y
(
i
)
x
(
i
)
w=\sum_{i=1}^{m} \alpha_{i} y^{(i)} x^{(i)}
w=∑i=1mαiy(i)x(i),即可求出w,然后通过
b
∗
=
−
max
i
:
y
(
i
)
=
−
1
w
∗
T
x
(
i
)
min
i
:
y
(
i
)
=
1
w
∗
T
x
(
i
)
2
b^{*}=-\frac{\max _{i : y^{(i)}=-1} w^{* T} x^{(i)}+\min _{i : y^{(i)}=1} w^{* T} x^{(i)}}{2}
b∗=−2maxi:y(i)=−1w∗Tx(i)+mini:y(i)=1w∗Tx(i),即可求出b,最终得出分离超平面和分类决策函数。
3. 在求得L(w, b, a) 关于 w 和 b 最小化,以及对
α
\alpha
α的极大之后,最后一步则可以利用SMO算法求解对偶问题中的拉格朗日乘子
α
\alpha
α
max
α
≥
0
∑
i
=
1
m
α
i
−
1
2
∑
i
,
j
=
1
m
α
i
α
j
y
i
y
j
x
i
T
x
j
s.t.
∑
i
=
1
m
α
i
y
i
.
=
0
α
i
≥
0
,
i
=
1
,
2
,
…
,
m
\begin{array}{l}{\max _{\alpha \geq 0} \sum_{i=1}^{m} \alpha_{i}-\frac{1}{2} \sum_{i, j=1}^{m} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j}} \ {\text {s.t.} \sum_{i=1}^{m} \alpha_{i} y_{i} .=0} \ {\alpha_{i} \geq 0, i=1,2, \ldots, m}\end{array}
maxα≥0∑i=1mαi−21∑i,j=1mαiαjyiyjxiTxjs.t.∑i=1mαiyi.=0αi≥0,i=1,2,…,m
上述式子要解决的是在参数上
{
α
1
,
α
2
,
…
,
α
n
}
\left{\alpha_{1}, \alpha_{2}, \ldots, \alpha_{n}\right}
{α1,α2,…,αn}求最大值W的问题,至于
x
(
i
)
x^{(i)}
x(i)和
y
(
i
)
y^{(i)}
y(i)都是已知数。要了解这个SMO算法是如何推导的,请跳到下文第3.5节、SMO算法。
总结
让我们再来看看上述推导过程中得到的一些有趣的形式。首先就是关于我们的 hyper plane ,对于一个数据点 x 进行分类,实际上是通过把 x 带入到
f
(
x
)
=
w
T
x
b
f(x)=w^{T} x+b
f(x)=wTx+b算出结果然后根据其正负号来进行类别划分的。而前面的推导中我们得到:
w
=
∑
i
=
1
n
α
i
y
i
x
i
w=\sum_{i=1}^{n} \alpha_{i} y_{i} x_{i}
w=∑i=1nαiyixi
因此分类函数为:
f
(
x
)
=
(
∑
i
=
1
n
α
i
y
i
x
i
)
T
x
b
=
∑
i
=
1
n
α
i
y
i
⟨
x
i
,
x
⟩
b
\begin{aligned} f(x) &=\left(\sum_{i=1}^{n} \alpha_{i} y_{i} x_{i}\right)^{T} x+b \ &=\sum_{i=1}^{n} \alpha_{i} y_{i}\left\langle x_{i}, x\right\rangle+ b \end{aligned}
f(x)=(i=1∑nαiyixi)Tx+b=i=1∑nαiyi⟨xi,x⟩+b
这里的形式的有趣之处在于,对于新点 x的预测,只需要计算它与训练数据点的内积即可(表示向量内积),这一点至关重要,是之后使用 Kernel 进行非线性推广的基本前提。此外,所谓 Supporting Vector 也在这里显示出来——事实上,所有非Supporting Vector 所对应的系数
α
\alpha
α都是等于零的,因此对于新点的内积计算实际上只要针对少量的“支持向量”而不是所有的训练数据即可。
为什么非支持向量对应的
α
\alpha
α等于零呢?直观上来理解的话,就是这些“后方”的点——正如我们之前分析过的一样,对超平面是没有影响的,由于分类完全有超平面决定,所以这些无关的点并不会参与分类问题的计算,因而也就不会产生任何影响了。
回忆一下我们通过 Lagrange multiplier得到的目标函数:
注意到如果 xi 是支持向量的话,上式中红颜色的部分是等于 0 的(因为支持向量的 functional margin 等于 1 ),而对于非支持向量来说,functional margin 会大于 1 ,因此红颜色部分是大于零的,而
α
i
\alpha_{i}
αi又是非负的,为了满足最大化,
α
i
\alpha_{i}
αi必须等于 0 。这也就是这些非Supporting Vector 的点的局限性。
至此,我们便得到了一个maximum margin hyper plane classifier,这就是所谓的支持向量机(Support Vector Machine)。当然,到目前为止,我们的 SVM 还比较弱,只能处理线性的情况,不过,在得到了对偶dual 形式之后,通过 Kernel 推广到非线性的情况就变成了一件非常容易的事情了(通过求解对偶问题得到最优解,这就是线性可分条件下支持向量机的对偶算法,这样做的优点在于:一者对偶问题往往更容易求解;二者可以自然的引入核函数,进而推广到非线性分类问题”)。
核函数Kernel
1. 特征空间的隐式映射:核函数
事实上,大部分时候数据并不是线性可分的,这个时候满足这样条件的超平面就根本不存在。在上文中,我们已经了解到了SVM处理线性可分的情况,那对于非线性的数据SVM咋处理呢?对于非线性的情况,SVM 的处理方法是选择一个核函数 κ(⋅,⋅) ,通过将数据映射到高维空间,来解决在原始空间中线性不可分的问题。
具体来说,在线性不可分的情况下,支持向量机首先在低维空间中完成计算,然后通过核函数将输入空间映射到高维特征空间,最终在高维特征空间中构造出最优分离超平面,从而把平面上本身不好分的非线性数据分开。如图所示,一堆数据在二维空间无法划分,从而映射到三维空间里划分:
而在我们遇到核函数之前,如果用原始的方法,那么在用线性学习器学习一个非线性关系,需要选择一个非线性特征集,并且将数据写成新的表达形式,这等价于应用一个固定的非线性映射,将数据映射到特征空间,在特征空间中使用线性学习器,因此,考虑的假设集是这种类型的函数:
f
(
x
)
=
∑
i
=
1
N
w
i
ϕ
i
(
x
)
b
f(\mathbf{x})=\sum_{i=1}^{N} w_{i} \phi_{i}(\mathbf{x})+b
f(x)=i=1∑Nwiϕi(x)+b
这里ϕ:X->F是从输入空间到某个特征空间的映射,这意味着建立非线性学习器分为两步:
首先使用一个非线性映射将数据变换到一个特征空间F,
然后在特征空间使用线性学习器分类。
而由于对偶形式就是线性学习器的一个重要性质,这意味着假设可以表达为训练点的线性组合,因此决策规则可以用测试点和训练点的内积来表示:
f
(
x
)
=
∑
i
=
1
′
α
i
y
i
⟨
ϕ
(
x
i
)
⋅
ϕ
(
x
)
⟩
b
f(\mathbf{x})=\sum_{i=1}^{\prime} \alpha_{i} y_{i}\left\langle\phi\left(\mathbf{x}_{i}\right) \cdot \phi(\mathbf{x})\right\rangle+ b
f(x)=i=1∑′αiyi⟨ϕ(xi)⋅ϕ(x)⟩+b
如果有一种方式可以在特征空间中直接计算内积〈φ(xi · φ(x)〉,就像在原始输入点的函数中一样,就有可能将两个步骤融合到一起建立一个非线性的学习器,这样直接计算法的方法称为核函数方法:
核是一个函数K,对所有x,z,满足
K
(
x
,
z
)
=
⟨
ϕ
(
x
)
⋅
ϕ
(
z
)
⟩
K(\mathbf{x}, \mathbf{z})=\langle\phi(\mathbf{x}) \cdot \phi(\mathbf{z})\rangle
K(x,z)=⟨ϕ(x)⋅ϕ(z)⟩,这里φ是从X到内积特征空间F的映射。
2. 核函数:如何处理非线性数据
来看个核函数的例子。如下图所示的两类数据,分别分布为两个圆圈的形状,这样的数据本身就是线性不可分的,此时咱们该如何把这两类数据分开呢(下文将会有一个相应的三维空间图)?
事实上,上图所述的这个数据集,是用两个半径不同的圆圈加上了少量的噪音生成得到的,所以,一个理想的分界应该是一个“圆圈”而不是一条线(超平面)。如果用
X
1
\mathrm{X}_{1}
X1和
X
2
\mathrm{X}_{2}
X2来表示这个二维平面的两个坐标的话,我们知道一条二次曲线(圆圈是二次曲线的一种特殊情况)的方程可以写作这样的形式:
a
1
X
1
a
2
X
1
2
a
3
X
2
a
4
X
2
2
a
5
X
1
X
2
a
6
=
0
a_{1} X_{1}+a_{2} X_{1}^{2}+a_{3} X_{2}+a_{4} X_{2}^{2}+a_{5} X_{1} X_{2}+a_{6}=0
a1X1+a2X12+a3X2+a4X22+a5X1X2+a6=0
注意上面的形式,如果我们构造另外一个五维的空间,其中五个坐标的值分别为
Z
1
=
X
1
,
Z
2
=
X
1
2
,
Z
3
=
X
2
,
Z
4
=
X
2
2
,
Z
5
=
X
1
X
2
Z_{1}=X_{1}, Z_{2}=X_{1}^{2}, Z_{3}=X_{2}, Z_{4}=X_{2}^{2},Z_{5}=X_{1} X_{2}
Z1=X1,Z2=X12,Z3=X2,Z4=X22,Z5=X1X2,那么显然,上面的方程在新的坐标系下可以写作:
∑
i
=
1
5
a
i
Z
i
a
6
=
0
\sum_{i=1}^{5} a_{i} Z_{i}+a_{6}=0
i=1∑5aiZi+a6=0
关于新的坐标
Z
\mathrm{Z}
Z,这正是一个 hyper plane 的方程!也就是说,如果我们做一个映射
ϕ
:
R
2
→
R
5
\phi : R_{2} \rightarrow R_{5}
ϕ:R2→R5,将
X
\mathrm{X}
X 按照上面的规则映射为
Z
\mathrm{Z}
Z,那么在新的空间中原来的数据将变成线性可分的,从而使用之前我们推导的线性分类算法就可以进行处理了。这正是 Kernel 方法处理非线性问题的基本思想。
再进一步描述 Kernel 的细节之前,不妨再来看看上述例子在映射过后的直观形态。当然,你我可能无法把 5 维空间画出来,不过由于我这里生成数据的时候用了特殊的情形,所以这里的超平面实际的方程是这个样子的(圆心在
X
2
\mathrm{X}_{2}
X2轴上的一个正圆)
∑
i
=
1
5
a
i
Z
i
a
6
=
0
\sum_{i=1}^{5} a_{i} Z_{i}+a_{6}=0
i=1∑5aiZi+a6=0
因此我只需要把它映射到
Z
1
=
X
1
2
,
Z
2
=
X
2
2
,
Z
3
=
X
2
Z_{1}=X_{1}^{2}, Z_{2}=X_{2}^{2}, \quad Z_{3}=X_{2}
Z1=X12,Z2=X22,Z3=X2,这样一个三维空间中即可,下图即是映射之后的结果,将坐标轴经过适当的旋转,就可以很明显地看出,数据是可以通过一个平面来分开的
核函数相当于把原来的分类函数:
f
(
x
)
=
∑
i
=
1
n
α
i
y
i
⟨
x
i
,
x
⟩
b
f(x)=\sum_{i=1}^{n} \alpha_{i} y_{i}\left\langle x_{i}, x\right\rangle+ b
f(x)=∑i=1nαiyi⟨xi,x⟩+b
映射成:
f
(
x
)
=
∑
i
=
1
n
α
i
y
i
⟨
ϕ
(
x
i
)
,
ϕ
(
x
)
⟩
b
f(x)=\sum_{i=1}^{n} \alpha_{i} y_{i}\left\langle\phi\left(x_{i}\right), \phi(x)\right\rangle+ b
f(x)=∑i=1nαiyi⟨ϕ(xi),ϕ(x)⟩+b
而其中的
α
\alpha
α可以通过求解如下 dual 问题而得到的:
max
α
∑
i
=
1
n
α
i
−
1
2
∑
i
,
j
=
1
n
α
i
α
j
y
i
y
j
⟨
ϕ
(
x
i
)
,
ϕ
(
x
j
)
⟩
s.t.
,
α
i
≥
0
,
i
=
1
,
…
,
n
∑
i
=
1
n
α
i
y
i
=
0
\begin{array}{l}{\max _{\alpha} \sum_{i=1}^{n} \alpha_{i}-\frac{1}{2} \sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j}\left\langle\phi\left(x_{i}\right), \phi\left(x_{j}\right)\right\rangle} \ {\text {s.t.}, \alpha_{i} \geq 0, i=1, \ldots, n} \ {\sum_{i=1}^{n} \alpha_{i} y_{i}=0}\end{array}
maxα∑i=1nαi−21∑i,j=1nαiαjyiyj⟨ϕ(xi),ϕ(xj)⟩s.t.,αi≥0,i=1,…,n∑i=1nαiyi=0
这样一来问题就解决了吗?似乎是的:拿到非线性数据,就找一个映射
ϕ
(
⋅
)
\phi(\cdot)
ϕ(⋅),然后一股脑把原来的数据映射到新空间中,再做线性 SVM 即可。不过事实上好像并没有这么简单。
细想一下,刚才的方法是不是有问题?
在最初的例子里,我们对一个二维空间做映射,选择的新空间是原始空间的所有一阶和二阶的组合,得到了五个维度;
如果原始空间是三维(一阶、二阶和三阶的组合),那么我们会得到:3(一次)+3(二次交叉)+3(平方)+3(立方)+1(x1x2x3)+23(交叉,一个一次一个二次,类似x1x2^2) = 19维的新空间,这个数目是呈指数级爆炸性增长的,从而势必这给
ϕ
(
⋅
)
\phi(\cdot)
ϕ(⋅)的计算带来非常大的困难,而且如果遇到无穷维的情况,就根本无从计算了。
这个时候,可能就需要 Kernel 出马了。
不妨还是从最开始的简单例子出发,设两个向量
x
1
=
(
η
1
,
η
2
)
T
x_{1}=\left(\eta_{1}, \eta_{2}\right)^{T}
x1=(η1,η2)T和
x
2
=
(
ξ
1
,
ξ
2
)
T
x_{2}=\left(\xi_{1}, \xi_{2}\right)^{T}
x2=(ξ1,ξ2)T,而
ϕ
(
⋅
)
\phi(\cdot)
ϕ(⋅)即是到前面说的五维空间的映射,因此映射过后的内积为:
⟨
ϕ
(
x
1
)
,
ϕ
(
x
2
)
⟩
=
η
1
ξ
1
η
1
2
ξ
1
2
η
2
ξ
2
η
2
2
ξ
2
2
η
1
η
2
ξ
1
ξ
2
\left\langle\phi\left(x_{1}\right), \phi\left(x_{2}\right)\right\rangle=\eta_{1} \xi_{1}+\eta_{1}^{2} \xi_{1}^{2}+\eta_{2} \xi_{2}+\eta_{2}^{2} \xi_{2}^{2}+\eta_{1} \eta_{2} \xi_{1} \xi_{2}
⟨ϕ(x1),ϕ(x2)⟩=η1ξ1+η12ξ12+η2ξ2+η22ξ22+η1η2ξ1ξ2
(公式说明:上面的这两个推导过程中,所说的前面的五维空间的映射,回顾下之前的映射规则,再看那第一个推导,其实就是计算x1,x2各自的内积,然后相乘相加即可,第二个推导则是直接平方,去掉括号,也很容易推出来)
另外,我们又注意到:
(
⟨
x
1
,
x
2
⟩
1
)
2
=
2
η
1
ξ
1
η
1
2
ξ
1
2
2
η
2
ξ
2
η
2
2
ξ
2
2
2
η
1
η
2
ξ
1
ξ
2
1
\left(\left\langle x_{1}, x_{2}\right\rangle+ 1\right)^{2}=2 \eta_{1} \xi_{1}+\eta_{1}^{2} \xi_{1}^{2}+2 \eta_{2} \xi_{2}+\eta_{2}^{2} \xi_{2}^{2}+2 \eta_{1} \eta_{2} \xi_{1} \xi_{2}+1
(⟨x1,x2⟩+1)2=2η1ξ1+η12ξ12+2η2ξ2+η22ξ22+2η1η2ξ1ξ2+1
二者有很多相似的地方,实际上,我们只要把某几个维度线性缩放一下,然后再加上一个常数维度,具体来说,上面这个式子的计算结果实际上和映射
φ
(
X
1
,
X
2
)
=
(
2
X
1
,
X
1
2
,
2
X
2
,
X
2
2
,
2
X
1
X
2
,
1
)
T
\varphi\left(X_{1}, X_{2}\right)=\left(\sqrt{2} X_{1}, X_{1}^{2}, \sqrt{2} X_{2}, X_{2}^{2}, \sqrt{2} X_{1} X_{2}, 1\right)^{T}
φ(X1,X2)=(2
X1,X12,2
X2,X22,2
X1X2,1)T
之后的内积
⟨
φ
(
x
1
)
,
φ
(
x
2
)
⟩
\left\langle\varphi\left(x_{1}\right), \varphi\left(x_{2}\right)\right\rangle
⟨φ(x1),φ(x2)⟩的结果是相等的,那么区别在于什么地方呢?
- 一个是映射到高维空间中,然后再根据内积的公式进行计算;
- 而另一个则直接在原来的低维空间中进行计算,而不需要显式地写出映射后的结果。
我们把这里的计算两个向量在隐式映射过后的空间中的内积的函数叫做核函数 (Kernel Function) ,例如,在刚才的例子中,我们的核函数为:
κ
(
x
1
,
x
2
)
=
(
⟨
x
1
,
x
2
⟩
1
)
2
\kappa\left(x_{1}, x_{2}\right)=\left(\left\langle x_{1}, x_{2}\right\rangle+ 1\right)^{2}
κ(x1,x2)=(⟨x1,x2⟩+1)2
核函数能简化映射空间中的内积运算——刚好“碰巧”的是,在我们的 SVM 里需要计算的地方数据向量总是以内积的形式出现的。对比刚才我们上面写出来的式子,现在我们的分类函数为:
∑
i
=
1
n
α
i
y
i
κ
(
x
i
,
x
)
b
\sum_{i=1}^{n} \alpha_{i} y_{i} \kappa\left(x_{i}, x\right)+b
i=1∑nαiyiκ(xi,x)+b
其中
α
\alpha
α由如下 dual 问题计算而得:
max
α
∑
i
=
1
n
α
i
−
1
2
∑
i
,
j
=
1
n
α
i
α
j
y
i
y
j
κ
(
x
i
,
x
j
)
s.t.
,
α
i
≥
0
,
i
=
1
,
…
,
n
∑
i
=
1
n
α
i
y
i
=
0
\begin{array}{l}{\max _{\alpha} \sum_{i=1}^{n} \alpha_{i}-\frac{1}{2} \sum_{i, j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j} \kappa\left(x_{i}, x_{j}\right)} \ {\text {s.t.}, \alpha_{i} \geq 0, i=1, \ldots, n} \ {\sum_{i=1}^{n} \alpha_{i} y_{i}=0}\end{array}
maxα∑i=1nαi−21∑i,j=1nαiαjyiyjκ(xi,xj)s.t.,αi≥0,i=1,…,n∑i=1nαiyi=0
这样一来计算的问题就算解决了,避开了直接在高维空间中进行计算,而结果却是等价的!当然,因为我们这里的例子非常简单,所以我可以手工构造出对应于的
ϕ
(
⋅
)
\phi(\cdot)
ϕ(⋅)核函数出来,如果对于任意一个映射,想要构造出对应的核函数就很困难了。
常见核函数
通常人们会从一些常用的核函数中选择(根据问题和数据的不同,选择不同的参数,实际上就是得到了不同的核函数),例如:
- 线性核,这实际上就是原始空间中的内积。这个核存在的主要目的是使得“映射后空间中的问题”和“映射前空间中的问题”两者在形式上统一起来了(意思是说,咱们有的时候,写代码,或写公式的时候,只要写个模板或通用表达式,然后再代入不同的核,便可以了,于此,便在形式上统一了起来,不用再分别写一个线性的,和一个非线性的)。
K
(
x
,
z
)
=
x
∙
z
K(x, z)=x \bullet z
K(x,z)=x∙z
- 多项式核,显然刚才我们举的例子是这里多项式核的一个特例(R = 1,d = 2)。虽然比较麻烦,而且没有必要,不过这个核所对应的映射实际上是可以写出来的。
K
(
x
,
z
)
=
(
γ
x
∙
z
r
)
d
K(x, z)=(\gamma x \bullet z+r)^{d}
K(x,z)=(γx∙z+r)d
- 高斯核函数(Gaussian Kernel),在SVM中也称为径向基核函数(Radial Basis Function,RBF),它是非线性分类SVM最主流的核函数。这个核就是最开始提到过的会将原始空间映射为无穷维空间的那个家伙。不过,如果
σ
\sigma
σ选得很大的话,高次特征上的权重实际上衰减得非常快,所以实际上(数值上近似一下)相当于一个低维的子空间;反过来,如果
σ
\sigma
σ选得很小,则可以将任意的数据映射为线性可分——当然,这并不一定是好事,因为随之而来的可能是非常严重的过拟合问题。不过,总的来说,通过调控参数,高斯核实际上具有相当高的灵活性,也是使用最广泛的核函数之一。下图所示的例子便是把低维线性不可分的数据通过高斯核函数映射到了高维空间:
K
(
x
,
z
)
=
exp
(
−
γ
∥
x
−
z
∥
2
)
K(x, z)=\exp \left(-\gamma|x-z|^{2}\right)
K(x,z)=exp(−γ∥x−z∥2)
k
(
x
,
y
)
=
exp
(
−
∥
x
−
y
∥
2
2
σ
2
)
k(x, y)=\exp \left(-\frac{|x-y|^{2}}{2 \sigma^{2}}\right)
k(x,y)=exp(−2σ2∥x−y∥2)
- Sigmoid核函数
Sigmoid核函数(Sigmoid Kernel)也是线性不可分SVM常用的核函数之一。
K
(
x
,
z
)
=
tanh
(
γ
x
∙
z
r
)
K(x, z)=\tanh (\gamma x \bullet z+r)
K(x,z)=tanh(γx∙z+r)
核函数的本质
上面说了这么一大堆,读者可能还是没明白核函数到底是个什么东西?我再简要概括下,即以下三点:
- 实际中,我们会经常遇到线性不可分的样例,此时,我们的常用做法是把样例特征映射到高维空间中去(映射到高维空间后,相关特征便被分开了,也就达到了分类的目的);
- 但进一步,如果凡是遇到线性不可分的样例,一律映射到高维空间,那么这个维度大小是会高到可怕的(如上文中19维乃至无穷维的例子)。那咋办呢?
- 此时,核函数就隆重登场了,核函数的价值在于它虽然也是将特征进行从低维到高维的转换,但核函数绝就绝在它事先在低维上进行计算,而将实质上的分类效果表现在了高维上,也就如上文所说的避免了直接在高维空间中的复杂计算。
SMO算法的步骤
SMO的主要步骤,如下:
第一步选取一对
α
i
\alpha_{i}
αi和
α
j
\alpha_{j}
αj,选取方法使用启发式方法;
第二步,固定除
α
i
\alpha_{i}
αi和
α
j
\alpha_{j}
αj之外的其他参数,确定W极值条件下的
α
i
\alpha_{i}
αi,
α
j
\alpha_{j}
αj由
α
i
\alpha_{i}
αi表示。
假定在某一次迭代中,需要更新
x
1
x_{1}
x1,
x
2
x_{2}
x2对应的拉格朗日乘子
α
1
\alpha_{1}
α1,
α
2
\alpha_{2}
α2,那么这个小规模的二次规划问题写为:
那么在每次迭代中,如何更新乘子呢?
知道了如何更新乘子,那么选取哪些乘子进行更新呢?具体选择方法有以下两个步骤:
步骤1:先“扫描”所有乘子,把第一个违反KKT条件的作为更新对象,令为a1;
步骤2:在所有不违反KKT条件的乘子中,选择使|E1 −E2|最大的a2进行更新,使得能最大限度增大目标函数的值(类似于梯度下降. 此外
E
i
=
u
i
−
y
i
E_{i}=u_{i}-y_{i}
Ei=ui−yi,而
u
=
w
⃗
⋅
x
⃗
−
b
u=\vec{w} \cdot \vec{x}-b
u=w
⋅x
−b,求出来的E代表函数ui对输入xi的预测值与真实输出类标记yi之差)。
最后,每次更新完两个乘子的优化后,都需要再重新计算b,及对应的Ei值。
综上,SMO算法的基本思想是将Vapnik在1982年提出的Chunking方法推到极致,SMO算法每次迭代只选出两个分量ai和aj进行调整,其它分量则保持固定不变,在得到解ai和aj之后,再用ai和aj改进其它分量。与通常的分解算法比较,尽管它可能需要更多的迭代次数,但每次迭代的计算量比较小,所以该算法表现出较好的快速收敛性,且不需要存储核矩阵,也没有矩阵运算。
对于LR与SVM的异同总结如下:
相同点:
- LR和SVM都是分类算法
- LR和SVM都是监督学习算法。
- LR和SVM都是判别模型。
- 如果不考虑核函数,LR和SVM都是线性分类算法,也就是说他们的分类决策面都是线性的。说明:LR也是可以用核函数的.但LR通常不采用核函数的方法.(计算量太大)
LR和SVM不同点:
1、LR采用log损失,SVM采用合页(hinge)损失。
逻辑回归的损失函数:
J
(
θ
)
=
−
1
m
[
∑
i
=
1
m
y
(
i
)
log
h
θ
(
x
(
i
)
)
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
]
J(\theta)=-\frac{1}{m}\left[\sum_{i=1}^{m} y^{(i)} \log h_{\theta}\left(x{(i)}\right)+\left(1-y{(i)}\right) \log \left(1-h_{\theta}\left(x^{(i)}\right)\right)\right]
J(θ)=−m1[i=1∑my(i)loghθ(x(i))+(1−y(i))log(1−hθ(x(i)))]
支持向量机的损失函数:
L
(
w
,
b
,
α
)
=
1
2
∥
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
=x∙z
- 多项式核,显然刚才我们举的例子是这里多项式核的一个特例(R = 1,d = 2)。虽然比较麻烦,而且没有必要,不过这个核所对应的映射实际上是可以写出来的。
K
(
x
,
z
)
=
(
γ
x
∙
z
r
)
d
K(x, z)=(\gamma x \bullet z+r)^{d}
K(x,z)=(γx∙z+r)d
- 高斯核函数(Gaussian Kernel),在SVM中也称为径向基核函数(Radial Basis Function,RBF),它是非线性分类SVM最主流的核函数。这个核就是最开始提到过的会将原始空间映射为无穷维空间的那个家伙。不过,如果
σ
\sigma
σ选得很大的话,高次特征上的权重实际上衰减得非常快,所以实际上(数值上近似一下)相当于一个低维的子空间;反过来,如果
σ
\sigma
σ选得很小,则可以将任意的数据映射为线性可分——当然,这并不一定是好事,因为随之而来的可能是非常严重的过拟合问题。不过,总的来说,通过调控参数,高斯核实际上具有相当高的灵活性,也是使用最广泛的核函数之一。下图所示的例子便是把低维线性不可分的数据通过高斯核函数映射到了高维空间:
K
(
x
,
z
)
=
exp
(
−
γ
∥
x
−
z
∥
2
)
K(x, z)=\exp \left(-\gamma|x-z|^{2}\right)
K(x,z)=exp(−γ∥x−z∥2)
k
(
x
,
y
)
=
exp
(
−
∥
x
−
y
∥
2
2
σ
2
)
k(x, y)=\exp \left(-\frac{|x-y|^{2}}{2 \sigma^{2}}\right)
k(x,y)=exp(−2σ2∥x−y∥2)
- Sigmoid核函数
Sigmoid核函数(Sigmoid Kernel)也是线性不可分SVM常用的核函数之一。
K
(
x
,
z
)
=
tanh
(
γ
x
∙
z
r
)
K(x, z)=\tanh (\gamma x \bullet z+r)
K(x,z)=tanh(γx∙z+r)
核函数的本质
上面说了这么一大堆,读者可能还是没明白核函数到底是个什么东西?我再简要概括下,即以下三点:
- 实际中,我们会经常遇到线性不可分的样例,此时,我们的常用做法是把样例特征映射到高维空间中去(映射到高维空间后,相关特征便被分开了,也就达到了分类的目的);
- 但进一步,如果凡是遇到线性不可分的样例,一律映射到高维空间,那么这个维度大小是会高到可怕的(如上文中19维乃至无穷维的例子)。那咋办呢?
- 此时,核函数就隆重登场了,核函数的价值在于它虽然也是将特征进行从低维到高维的转换,但核函数绝就绝在它事先在低维上进行计算,而将实质上的分类效果表现在了高维上,也就如上文所说的避免了直接在高维空间中的复杂计算。
SMO算法的步骤
SMO的主要步骤,如下:
第一步选取一对
α
i
\alpha_{i}
αi和
α
j
\alpha_{j}
αj,选取方法使用启发式方法;
第二步,固定除
α
i
\alpha_{i}
αi和
α
j
\alpha_{j}
αj之外的其他参数,确定W极值条件下的
α
i
\alpha_{i}
αi,
α
j
\alpha_{j}
αj由
α
i
\alpha_{i}
αi表示。
假定在某一次迭代中,需要更新
x
1
x_{1}
x1,
x
2
x_{2}
x2对应的拉格朗日乘子
α
1
\alpha_{1}
α1,
α
2
\alpha_{2}
α2,那么这个小规模的二次规划问题写为:
那么在每次迭代中,如何更新乘子呢?
知道了如何更新乘子,那么选取哪些乘子进行更新呢?具体选择方法有以下两个步骤:
步骤1:先“扫描”所有乘子,把第一个违反KKT条件的作为更新对象,令为a1;
步骤2:在所有不违反KKT条件的乘子中,选择使|E1 −E2|最大的a2进行更新,使得能最大限度增大目标函数的值(类似于梯度下降. 此外
E
i
=
u
i
−
y
i
E_{i}=u_{i}-y_{i}
Ei=ui−yi,而
u
=
w
⃗
⋅
x
⃗
−
b
u=\vec{w} \cdot \vec{x}-b
u=w
⋅x
−b,求出来的E代表函数ui对输入xi的预测值与真实输出类标记yi之差)。
最后,每次更新完两个乘子的优化后,都需要再重新计算b,及对应的Ei值。
综上,SMO算法的基本思想是将Vapnik在1982年提出的Chunking方法推到极致,SMO算法每次迭代只选出两个分量ai和aj进行调整,其它分量则保持固定不变,在得到解ai和aj之后,再用ai和aj改进其它分量。与通常的分解算法比较,尽管它可能需要更多的迭代次数,但每次迭代的计算量比较小,所以该算法表现出较好的快速收敛性,且不需要存储核矩阵,也没有矩阵运算。
对于LR与SVM的异同总结如下:
相同点:
- LR和SVM都是分类算法
- LR和SVM都是监督学习算法。
- LR和SVM都是判别模型。
- 如果不考虑核函数,LR和SVM都是线性分类算法,也就是说他们的分类决策面都是线性的。说明:LR也是可以用核函数的.但LR通常不采用核函数的方法.(计算量太大)
LR和SVM不同点:
1、LR采用log损失,SVM采用合页(hinge)损失。
逻辑回归的损失函数:
J
(
θ
)
=
−
1
m
[
∑
i
=
1
m
y
(
i
)
log
h
θ
(
x
(
i
)
)
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
]
J(\theta)=-\frac{1}{m}\left[\sum_{i=1}^{m} y^{(i)} \log h_{\theta}\left(x{(i)}\right)+\left(1-y{(i)}\right) \log \left(1-h_{\theta}\left(x^{(i)}\right)\right)\right]
J(θ)=−m1[i=1∑my(i)loghθ(x(i))+(1−y(i))log(1−hθ(x(i)))]
支持向量机的损失函数:
L
(
w
,
b
,
α
)
=
1
2
∥
[外链图片转存中…(img-b7zlAEWZ-1715878831955)]
[外链图片转存中…(img-g4M6tOYp-1715878831956)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新