我们的目的是将高维的数据投影到一维直线上并在投影的值中取一个阈值进行分类,如下图所示:(绘画水平有限,将就着看)
在上图,很明显左边的投影更适合分类,因为两种类别(o和x)在投影直线上能轻松地找到一个阈值将其区分开来,而右边的投影方向则不适合当前分类。
所以我们需要求解一个适合的投影方向 w w w
在理解fisher的时候,我遇到了很多不理解问题,在经过多本书籍的对比之后终于搞懂了,其大致的思路如下:
值得注意的是,我们求得的w是最终投影的平面(在这里为一维直线)方向,而不是感知机或逻辑斯蒂回归中的决策边界,这个问题一度让我以为自己的w求错了!!!
另外,在推导公式中,一定一定记得随时查看当前数据维度,不然极易混淆
对于样本点 X = ( x 1 , x 2 , . . . , x N ) T X = (x_1,x_2,...,x_N)^T X=(x1,x2,...,xN)T,其维度为 N × p N×p N×p,即每一个样本有 p p p个特征 ,其类别 Y = ( y 1 , y 2 , . . . , y N ) T Y = (y_1,y_2,...,y_N)^T Y=(y1,y2,...,yN)T,其中 y i ∈ { + 1 , − 1 } y_i\in\{+1,-1\} yi∈{+1,−1}
我们将样本按其标签分为两类,数量分别为 N 1 N_1 N1和 N 2 N_2 N2,即 ∣ x c 1 ∣ = N 1 , ∣ x c 2 ∣ = N 2 , N 1 + N 2 = N |x_{c1}|=N_1\ ,\ |x_{c2}| = N_2\ ,\ N_1+N_2 = N ∣xc1∣=N1 , ∣xc2∣=N2 , N1+N2=N
在本文中,我们用坐标点投影在直线上来直观地表述,即 p = 2 p=2 p=2
假设,我是说假设啊,我们现在找到了一个适合的投影方向,则样本 x x x在直线 z z z上的投影为: z i = w T x i z_i = w^Tx_i zi=wTxi这个公式的来源:我们假设 w w w的模为1(因为方向重要长度不重要,可以缩放)。在两个向量中,你可以很明显地看出 x i x_i xi在 w w w上的投影为 Δ = x i c o s θ \Delta = x_icos\theta Δ=xicosθ,而 x i x_i xi和 w w w的点积为 x i ⋅ w = ∣ x i ∣ ∣ w ∣ c o s θ = ∣ x i ∣ c o s θ = Δ x_i·w = |x_i||w|cos\theta = |x_i|cos\theta = \Delta xi⋅w=∣xi∣∣w∣cosθ=∣xi∣cosθ=Δ,就是说我们可以用 x i x_i xi和 w w w的点积表示其 x i x_i xi在 w w w上的投影,写作 w T x i w^Tx_i wTxi的形式。
值得注意的是,在这里投影指的是 :以原点为起点, x i x_i xi为终点的向量在直线 z z z(方向为 w w w)上的投影
然后,所有样本在 z z z上的投影的均值为: z ˉ = 1 N ∑ i = 1 N z i = 1 N ∑ i = 1 N w T x i \bar z = \frac{1}{N}\displaystyle\sum_{i=1}^Nz_i=\frac{1}{N}\displaystyle\sum_{i=1}^Nw^Tx_i zˉ=N1i=1∑Nzi=N1i=1∑NwTxi
协方差(在这里可以理解为方差)为 S z = 1 N ∑ i = 1 N ( z i − z ˉ ) ( z i − z ˉ ) T = 1 N ∑ i = 1 N ( w T x i − z ˉ ) ( w T x i − z ˉ ) T S_z=\frac{1}{N}\displaystyle\sum_{i=1}^N(z_i-\bar z)(z_i-\bar z)^T=\frac{1}{N}\displaystyle\sum_{i=1}^N(w^Tx_i-\bar z)(w^Tx_i-\bar z)^T Sz=N1i=1∑N(zi−zˉ)(zi−zˉ)T=N1i=1∑N(wTxi−zˉ)(wTxi−zˉ)T
两个类分开写:
类别1: z 1 ˉ = 1 N 1 ∑ i = 1 N 1 w T x i \bar {z_1} = \frac{1}{N_1}\displaystyle\sum_{i=1}^{N_1}w^Tx_i z1ˉ=N11i=1∑N1wTxi , S 1 = 1 N 1 ∑ i = 1 N 1 ( w T x i − z 1 ˉ ) ( w T x i − z 1 ˉ ) T S_1=\frac{1}{N_1}\displaystyle\sum_{i=1}^{N_1}(w^Tx_i-\bar {z_1})(w^Tx_i-\bar {z_1})^T S1=N11i=1∑N1(wTxi−z1ˉ)(wTxi−z1ˉ)T
类别2: z 2 ˉ = 1 N 2 ∑ i = 1 N 2 w T x i \bar {z_2} = \frac{1}{N_2}\displaystyle\sum_{i=1}^{N_2}w^Tx_i z2ˉ=N21i=1∑N2wTxi , S 1 = 1 N 2 ∑ i = 1 N 2 ( w T x i − z 2 ˉ ) ( w T x i − z 2 ˉ ) T S_1=\frac{1}{N_2}\displaystyle\sum_{i=1}^{N_2}(w^Tx_i-\bar {z_2})(w^Tx_i-\bar {z_2})^T S1=N21i=1∑N2(wTxi−z2ˉ)(wTxi−z2ˉ)T
注意,这里由于我们是平面坐标点在一维直线上的投影,所以 z ˉ 、 S z 、 z 1 ˉ 、 z 2 ˉ 、 S 1 、 S 2 \bar z、S_z、\bar {z_1}、\bar{z_2}、S_1、S_2 zˉ、Sz、z1ˉ、z2ˉ、S1、S2均可以理解为一个数。
还记得我们的目标吗:类内小,类间大
在这里,我们将类间表示为 ( z 1 ˉ − z 2 ˉ ) 2 (\bar{z_1}-\bar{z_2})^2 (z1ˉ−z2ˉ)2,即两个类别的样本分别取均值,其均值之差的平方
将类内表示为 S 1 + S 2 S_1+S_2 S1+S2,即两个类别的样本方差之和
由此我们可以很自然地得到一个最大化的目标函数:
J ( w ) = ( z 1 ˉ − z 2 ˉ ) 2 S 1 + S 2 J(w) = \frac{(\bar {z_1}-\bar{z_2})^2}{S_1+S_2} J(w)=S1+S2(z1ˉ−z2ˉ)2
极大化这个式子就相当于最小化 S 1 + S 2 S_1+S_2 S1+S2和最大化 ( z 1 ˉ − z 2 ˉ ) 2 (\bar {z_1}-\bar{z_2})^2 (z1ˉ−z2ˉ)2,完美符合我们的目标
对于 J ( w ) J(w) J(w),我们可以进一步的调整:
对于其分子:
( z 1 ˉ − z 2 ˉ ) 2 = [ 1 N 1 ∑ i = 1 N 1 w T x i − 1 N 2 ∑ i = 1 N 2 w T x i ] 2 = [ w T ( 1 N 1 ∑ i = 1 N 1 x i − 1 N 2 ∑ i = 1 N 2 x i ) ] 2 = [ w T ( x c 1 ˉ − x c 2 ˉ ) ] 2 = w T ( x c 1 ˉ − x c 2 ˉ ) ( x c 1 ˉ − x c 2 ˉ ) T w \begin{aligned} (\bar {z_1}-\bar{z_2})^2 &= \left[\frac{1}{N_1}\displaystyle\sum_{i=1}^{N_1}w^Tx_i - \frac{1}{N_2}\displaystyle\sum_{i=1}^{N_2}w^Tx_i \right]^2\\&=\left[w^T(\frac{1}{N_1}\displaystyle\sum_{i=1}^{N_1}x_i-\frac{1}{N_2}\displaystyle\sum_{i=1}^{N_2}x_i)\right]^2\\&=\left[w^T(\bar{x_{c1}}-\bar{x_{c2}})\right]^2\\&=w^T(\bar{x_{c1}}-\bar{x_{c2}})(\bar{x_{c1}}-\bar{x_{c2}})^Tw \end{aligned} (z1ˉ−z2ˉ)2=[N11i=1∑N1wTxi−N21i=1∑N2wTxi]2=[wT(N11i=1∑N1xi−N21i=1∑N2xi)]2=[wT(xc1ˉ−xc2ˉ)]2=wT(xc1ˉ−xc2ˉ)(xc1ˉ−xc2ˉ)Tw
对于其分母,我们先取 S 1 S1 S1进行分析:
S 1 = 1 N 1 ∑ i = 1 N 1 ( w T x i − z 1 ˉ ) ( w T x i − z 1 ˉ ) T = 1 N 1 ∑ i = 1 N 1 w T ( x i − x c 1 ˉ ) ( x i − x c 1 ˉ ) T w = w T 1 N 1 ∑ i = 1 N 1 ( x i − x c 1 ˉ ) ( x i − x c 1 ˉ ) T w = w T S c 1 w \begin{aligned} S_1 &=\frac{1}{N_1}\displaystyle\sum_{i=1}^{N_1}(w^Tx_i-\bar {z_1})(w^Tx_i-\bar {z_1})^T \\&= \frac{1}{N_1}\displaystyle\sum_{i=1}^{N_1}w^T(x_i-\bar{x_{c1}})(x_i-\bar{x_{c1}})^Tw \\&= w^T\frac{1}{N_1}\displaystyle\sum_{i=1}^{N_1}(x_i-\bar{x_{c1}})(x_i-\bar{x_{c1}})^Tw\\&=w^TS_{c1}w \end{aligned} S1=N11i=1∑N1(wTxi−z1ˉ)(wTxi−z1ˉ)T=N11i=1∑N1wT(xi−xc1ˉ)(xi−xc1ˉ)Tw=wTN11i=1∑N1(xi−xc1ˉ)(xi−xc1ˉ)Tw=wTSc1w
上式中我们用 S c 1 S_{c1} Sc1表示 1 N 1 ∑ i = 1 N 1 ( x i − x c 1 ˉ ) ( x i − x c 1 ˉ ) T \frac{1}{N_1}\displaystyle\sum_{i=1}^{N_1}(x_i-\bar{x_{c1}})(x_i-\bar{x_{c1}})^T N11i=1∑N1(xi−xc1ˉ)(xi−xc1ˉ)T,很显然,这个式子的意思为类别1中样本的方差
值得注意的是,这里的 S c 1 S_{c1} Sc1与之前的 S 1 S_1 S1有很大的不同!!!!!! S 1 S_1 S1表示的是投影的方差,维度1×1,在投影中可以理解为一个数!一个数!一个数!!!!而 S c 1 S_{c1} Sc1表示类别1样本的协方差矩阵,没有投影之前的协方差矩阵,维度为p×p,是一个矩阵!一个矩阵!一个矩阵!
这个地方一定要搞清楚,不然你就不知道为什么前面是方差是一个数但是后面方差求出来是一个矩阵了,我当时推了几遍才反应过来!
此外, p × p p×p p×p的协方差矩阵为 x i x_i xi的每一个特征的标准差与其他特征标准差的乘积
好了,书接上回:
S 2 S_2 S2同理,所以其分母等价于:
S 1 + S 2 = w T S c 1 w + w T S c 2 w = w T ( S c 1 + S c 2 ) w S_1+S_2 =w^TS_{c1}w + w^TS_{c2}w = w^T(S_{c1}+S_{c2})w S1+S2=wTSc1w+wTSc2w=wT(Sc1+Sc2)w
则 J ( w ) J(w) J(w)可以转化为:
J ( w ) = w T ( x c 1 ˉ − x c 2 ˉ ) ( x c 1 ˉ − x c 2 ˉ ) T w w T ( S c 1 + S c 2 ) w = w T S b w w T S w w J(w) = \frac{w^T(\bar{x_{c1}}-\bar{x_{c2}})(\bar{x_{c1}}-\bar{x_{c2}})^Tw}{ w^T(S_{c1}+S_{c2})w} = \frac{w^TS_bw}{w^TS_ww} J(w)=wT(Sc1+Sc2)wwT(xc1ˉ−xc2ˉ)(xc1ˉ−xc2ˉ)Tw=wTSwwwTSbw
我们用 S b S_b Sb表示 ( x c 1 ˉ − x c 2 ˉ ) ( x c 1 ˉ − x c 2 ˉ ) T (\bar{x_{c1}}-\bar{x_{c2}})(\bar{x_{c1}}-\bar{x_{c2}})^T (xc1ˉ−xc2ˉ)(xc1ˉ−xc2ˉ)T,其被称为类间方差
用 S w S_w Sw表示 S c 1 + S c 2 S_{c1}+S_{c2} Sc1+Sc2,其被称为类内方差
这里将 J ( w ) J(w) J(w)转化的意义在于,将原来假设的投影 w w w的方差和均值转化为了各类别样本本身的方差和均值,这样求解出来的w就可以直接用样本本来的值求解了,你甚至可以理解成把虚的变成实的!
由上面的式子,可以得到:
J ( w ) = w T S b w w T S w w = w T S b w ⋅ ( w T S w w ) − 1 J(w) = \frac{w^TS_bw}{w^TS_ww} = w^TS_bw·(w^TS_ww)^{-1} J(w)=wTSwwwTSbw=wTSbw⋅(wTSww)−1
对 w w w进行求导并令结果为0:
∂ J ( w ) ∂ w = 2 S b w ⋅ ( w T S w w ) − 1 + w T S b w ⋅ ( − 1 ) ( w T S w w ) − 2 ⋅ 2 S w w = 0 \frac{\partial J(w)}{\partial w} = 2S_bw·(w^TS_ww)^{-1}+w^TS_bw·(-1)(w^TS_ww)^{-2}·2S_ww = 0 ∂w∂J(w)=2Sbw⋅(wTSww)−1+wTSbw⋅(−1)(wTSww)−2⋅2Sww=0
两边同时乘上 ( w T S w w ) 2 (w^TS_ww)^2 (wTSww)2,注意这里 ( w T S w w ) (w^TS_ww) (wTSww)是一个数,维度计算: 1 × p ⋅ p × p ⋅ p × 1 = 1 × 1 1×p\ · \ p×p\ ·\ p×1 = 1×1 1×p ⋅ p×p ⋅ p×1=1×1
可得:
S b w ( w T S w w ) − w T S b w ⋅ S w w = 0 w T S b w ⋅ S w w = S b w ( w T S w w ) S_bw(w^TS_ww)-w^TSbw·S_ww = 0\\ w^TSbw·S_ww = S_bw(w^TS_ww) Sbw(wTSww)−wTSbw⋅Sww=0wTSbw⋅Sww=Sbw(wTSww)
同 ( w T S w w ) (w^TS_ww) (wTSww)一样, ( w T S b w ) (w^TS_bw) (wTSbw)依然是一个数,所以可得:
S w w = w T S w w w T S b w ⋅ S b ⋅ w S_ww = \frac{w^TS_ww}{w^TS_bw}·S_b·w Sww=wTSbwwTSww⋅Sb⋅w
两边左乘 S w − 1 S_w^{-1} Sw−1,可得:
w = w T S w w w T S b w ⋅ S w − 1 ⋅ S b ⋅ w w =\frac{w^TS_ww}{w^TS_bw}·S_w^{-1}·S_b·w w=wTSbwwTSww⋅Sw−1⋅Sb⋅w
由于 w T S w w w T S b w \large \frac{w^TS_ww}{w^TS_bw} wTSbwwTSww是一个数,并不会影响我们求 w w w的方向,所以我们不妨设它为1(这里可以理解为我们投影的直线 z z z可以放缩),即可得:
w = S w − 1 ⋅ S b ⋅ w w = S_w^{-1}·S_b·w w=Sw−1⋅Sb⋅w
我们继续研究,可以发现 S b ⋅ w = ( x c 1 ˉ − x c 2 ˉ ) ( x c 1 ˉ − x c 2 ˉ ) T ⋅ w S_b·w = (\bar{x_{c1}}-\bar{x_{c2}})(\bar{x_{c1}}-\bar{x_{c2}})^T·w Sb⋅w=(xc1ˉ−xc2ˉ)(xc1ˉ−xc2ˉ)T⋅w,而 ( x c 1 ˉ − x c 2 ˉ ) T ⋅ w (\bar{x_{c1}}-\bar{x_{c2}})^T·w (xc1ˉ−xc2ˉ)T⋅w的维度计算为 1 × p ⋅ p × 1 = 1 × 1 1×p · p×1 = 1×1 1×p⋅p×1=1×1,即实数,与 w w w方向无关。
所以最终我们求得的 w w w为:
w = S w − 1 ( x c 1 ˉ − x c 2 ˉ ) w = S_w^{-1}(\bar{x_{c1}}-\bar{x_{c2}}) w=Sw−1(xc1ˉ−xc2ˉ)
即两个类协方差矩阵之和的逆矩阵乘上两个类的均值之差
有了上述结果,我们可以很清楚的得到算法流程:
以下为python实现代码:
import numpy as np
import matplotlib.pyplot as plt
def fisher(x_1 , y_1 , x_2 ,y_2):
#类内方差 Sw = S1 + S2
u_1 = np.mean(x_1 , axis = 0 )
S1 = (x_1 - u_1).T.dot((x_1-u_1))
u_2 = np.mean(x_2 , axis = 0 )
S2 = (x_2 - u_2).T.dot(x_2-u_2)
Sw = S1 + S2
# print(Sw)
w = np.linalg.pinv(Sw).dot(u_1 - u_2) #inv逆矩阵,pinv伪逆矩阵
return w
def predict(test_data , w , c1 , c2): #根据计算的W进行预测
u_1 = np.mean(c1, axis=0)
u_2 = np.mean(c2, axis=0)
diff_1 = w.dot(u_1.T)
diff_2 = w.dot(u_2.T)
diff_cur = w.dot(test_data.T) #根据投影距离远近决定是哪一类
return [1 if abs(diff_cur[i]-diff_1) < abs(diff_cur[i]-diff_2) else -1 for i in range(len(test_data))]
if __name__ == '__main__':
X_True = [[1,1],[2,2],[0,4],[3,4]] #正例
X_False = [[3,3],[4,5],[3,4],[5,4]] #负例
Y_True = [1] * len(X_True)
Y_False = [-1] * len(X_False)
w = fisher(X_True,Y_True,X_False,Y_False) #求投影直线的方向w
test_point = np.array([[2,5],[4,0]]) #测试数据
predict_result = predict(test_point,w,X_True,X_False)
print('测试点预测类别:'+str(predict_result))
#绘图
plot_x = np.arange(0,6)
plot_y = -(w[0]*plot_x)/w[1]
plt.scatter([x[0] for x in X_True] ,[x[1] for x in X_True] ,c = 'r',label = 'class 1')
plt.scatter([x[0] for x in X_False] ,[x[1] for x in X_False] ,c = 'b',label = 'class -1')
plt.scatter([x[0] for x in test_point] ,[x[1] for x in test_point] ,c = 'green',label = 'test_point')
plt.plot(plot_x,plot_y,c = 'pink')
plt.legend()
plt.show()
图中的粉色直线即为所求结果,注意这个是投影的直线,而不是决策边界。
如有问题欢迎评论区指出,有问题也可以联系我:
[email protected]