对于线性不可分的数据,从低维度映射到高维度空间,有可能变为线性可分,如:
上图红点和蓝点是线性不可分的,我们将四个点执行(x,y)->(x*x,y*y,1.414*x*y)映射,该数据变为线性可分,如下图:
代码如下(python3.x):
import matplotlib.pyplot as plt
#import numpy as np
from mpl_toolkits.mplot3d import Axes3D
p1 = [1,1]
p2 = [7,1]
p3 = [4,-2]
p4 = [4,4]
plt.figure(1)
plt.plot([p1[0],p2[0]],[p1[1],p2[1]],'ro')
plt.plot([p3[0],p4[0]],[p3[1],p4[1]],'bo')
plt.xlim(-3, 8)
plt.ylim(-3, 8)
plt.xlabel('x')
plt.ylabel('y')
fig=plt.figure(2)
ax = Axes3D(fig)
t_p1 = [p1[0]**2,p1[1]**2,1.414*p1[0]*p1[1]]
t_p2 = [p2[0]**2,p2[1]**2,1.414*p2[0]*p2[1]]
t_p3 = [p3[0]**2,p3[1]**2,1.414*p3[0]*p3[1]]
t_p4 = [p4[0]**2,p4[1]**2,1.414*p4[0]*p4[1]]
ax.scatter([t_p1[0],t_p2[0]],[t_p1[1],t_p2[1]],[t_p1[2],t_p2[2]],s=40,c='r')
ax.scatter([t_p3[0],t_p4[0]],[t_p3[1],t_p4[1]],[t_p3[2],t_p4[2]],s=40,c='b',)
ax.set_zlabel('Z')
ax.set_ylabel('Y')
ax.set_xlabel('X')
plt.show()
==================================================================
因此我们可以通过将低维度数据映射到高维度空间的方法,提升数据的线性的可分离度。然而该方法需要消耗大量的计算资源。
有没有不额外消耗计算资源,又能够将低维度数据映射到高维度空间的方法呢?有的。
令
<x,z>
<script type="math/tex" id="MathJax-Element-8652">
</script>表示x和z的内积,即
<x,z>=x1∗z1+x2∗z2+x3∗z3 ...
<script type="math/tex" id="MathJax-Element-8653">
= x_1*z_1+x_2*z_2+x_3*z_3 \ \ \ ...</script>
假如计算过程中数据仅以
<x,z>
<script type="math/tex" id="MathJax-Element-8654">
</script>的形式出现,而不是单独出现,则可以通过将计算过程中的
<x,z>
<script type="math/tex" id="MathJax-Element-8655">
</script>替换成
k(x,z)
来实现映射,如
k(x,z)=<x,z>2
,其中
k(x,z)
是核函数。
现在有两个问题,一个是为什么替换之后可以实现将低维度数据映射到高维度空间?二是为什么不会额外增加计算资源?
例如数据是3维度的,即
<x,z>=x1∗z1+x2∗z2+x3∗z3
<script type="math/tex" id="MathJax-Element-8659">
= x_1*z_1+x_2*z_2+x_3*z_3 </script>
那么
<x,z>2=(x1∗z1+x2∗z2+x3∗z3)2=((x1z1)2+(x2z2)2+(x3z3)2+2x1z1x2z2+2x1z1x3z3+2x2z2x3z3)=<X,Z>
<script type="math/tex" id="MathJax-Element-8660">
^2=(x_1*z_1+x_2*z_2+x_3*z_3 )^2=((x_1z_1)^2+(x_2z_2)^2+(x_3z_3)^2+2x_1z_1x_2z_2+2x_1z_1x_3z_3+2x_2z_2x_3z_3)=
</script>
其中
<X,Z>
<script type="math/tex" id="MathJax-Element-8661">
</script>中的
X
和
也就是说,对于
x:(x1,x2,x3)
,
z:(x1,z2,z3)
,当我们将计算过程中的
<x,z>
<script type="math/tex" id="MathJax-Element-8667">
</script>替换成
<x,z>2
<script type="math/tex" id="MathJax-Element-8668">
^2</script>,就相当于完成了数据的从3维度到6维度映射:从
(x1,x2,x3)
到
(x21,x22,x23,2√x1x2,2√x1x3,2√x2x3)
。
到这里,第一个问题就解决了。
那为什么不额外增加计算量呢?因为我们本来就是要计算
<x,z>
<script type="math/tex" id="MathJax-Element-8671">
</script>的。将计算结果平方,增加的步骤仅仅是平方这一步,省略了复杂的内积计算.对于计算机而言,计算一个浮点数的平方是很快的。
==================================================================
核方法是一个很巧妙的方法,巧就巧在不显著的增加计算量的情况下,能实现将低维度数据映射到高维度空间,提升数据的线性的可分离性。
常用的核函数有:
高斯核:
k(x,z)=exp(−||x−z||22σ2)
多项式核:
k(x,z)=(axtz+c)d
指数核:
k(x,z)=exp(−||x−z||2σ2)
拉普拉斯核:
k(x,z)=exp(−||x−z||σ)
Sigmoid核:
k(x,z)=tanh(axtz+c)
ANOVA 核:
k(x,z)=exp(−σ(xk−zk)2)d
等等