Dimensionality Reduction —降维
预备知识
-
Data:
X=(x1,x2,...,xN)N∗MT=⎝⎜⎜⎛x1Tx2T...xNT⎠⎟⎟⎞=⎝⎜⎜⎛x11x12...x1Mx21x22...x2M...xN1xN2...xNM⎠⎟⎟⎞ -
Sample Mean:
XM×1=N1i=1∑Nxi -
Sample Covariance:
SM×M=N1i=1∑N(xi−x)(xi−x)T
注解:N为特征个数,或样本个数。M表示维度数。 样本均值表示每个维度求均值,因此结果为M×1维。方差转置放在后一项因为假设Xi为列向量(从Data开始)。
S表示各个维度之间的协方差。即因此S矩阵为M×M维
下面将均值和方差矩阵化:
XM×1=N1i=1∑Nxi=N1(x1x2x3...xN)⎝⎜⎜⎜⎜⎜⎜⎜⎜⎛111...1⎠⎟⎟⎟⎟⎟⎟⎟⎟⎞=N1XT1N
SM×M=N1i=1∑N(xi−x)(xi−x)T=N1XTHHTX=N1XTHX
其中:HN=IN−N11N1NT
写程序就用这个,少用几个for
PCA(Principal Component Analysis) 主成分分析
一个中心,两个基本点:
一个中心:对原始特征空间的重构 (把一组线性相关的变量变换为线性无关的变量)
我的理解:基向量的变换。
两个基本点:
(1)最大投影方差
(2)最小重构距离
两个方法都是达到一个中心的目的,本质相同
最大投影方差
向量投影公式 :
令投影方向∣b∣=1,则a在b上的投影可以表示为ab,矩阵表示为aTb
我们在计算之前,一般要中心化 即
对于每一个xi,计算xi−x
假设我们已经知道主轴(主成分)为u1,且|u1| = 1,那么将所有样本投影到主轴上 ,即
(xi−x)Tu1
因为我们已经中心化,因此投影之后的方差(最大投影方差)为:
J=N1i=1∑N((xi−x)Tu1)2=i=1∑NN1u1T(xi−x)(xi−x)Tu1=u1T(i=1∑NN1(xi−x)(xi−x)T)u1=u1TSu1
因此,求最大投影方差就变换为求解最优化问题:
u1^s.t.=argmax(u1TSu1) u1Tu1=1
通过拉格朗日方程求解。
很显然,求值的结果是协方差矩阵S的特征值分解。
这个过程我们可以理解为
1.特征空间变换
2.通过特征值 筛选特征向量
3 .降维
最小重构代价
假设ui为变换之后的特征向量,则无损失重构为:
xi=k=1∑M(xiTuk)uk
如果对变换后的特征向量进行降维处理(降为q维),则重构之后的损失为:
x^i=k=1∑q(xiTuk)uk
J=N1i=1∑N∣∣xi−x^i∣∣2=N1i=1∑Nk=q+1∑M(xiTuk)2
因为实际中我们要对xi进行中心化,因此上式中
xi=xi−xi
替换上式子中的Xi,则有
N1i=1∑Nk=q+1∑M(xiTuk)2=N1i=1∑Nk=q+1∑M((xi−xi)Tuk)2=k=q+1∑Mi=1∑NN1((xi−xi)Tuk)2=k=q+1∑MukTSuk
问题变为:
uk=argmink=q+1∑MukTSuks.t. ukTuk=1
解拉格朗日方程,就可看出与最大投影方差相同。
从SVD(Singular Value Decomposition)奇异值分解的角度分析PCA
我们从样本的角度分析
首先对样本进行中心化处理:
X−X=HX=U∑VTS=XTHX=XTHTHX=(HX)T(HX)=V∑UTU∑VT=V∑∑VT
因此,我们可以不求协方差矩阵,直接求X的奇异值分解即可
T=HXXTH=U∑∑UT
若我们直接用S做,可以直接得到坐标和基向量,若我们用T做,则不能得到基向量,但是可以得到坐标。用T做我们叫它主坐标分析(Principle Coordinate Analysis)PCoA
S一般为M×M,T一般为N×N,选择合适的角度进行分解,可以简化计算量。
从概率的角度分析PCA,P-PCA
https://www.bilibili.com/video/av32709936/?p=6
代码实现
PCA
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import matplotlib
plt.rcParams['savefig.dpi'] = 150 #图片像素
plt.rcParams['figure.dpi'] = 150 #分辨率
#初始化鸢尾花数据
iris = load_iris()
X,y = iris.data , iris.target
class1_X = X[:100,:2] # ['sepal length (cm)', 'sepal width (cm)']
class2_X = X[:100,2:] # ['petal length (cm)', 'petal width (cm)']
X = class1_X[:50,:]
x_overline = np.sum(X,axis = 0)/X.shape[0]
a = X - x_overline
b = a.T.dot(a)
V,sigma,VT = np.linalg.svd(b,1,1)
mark = np.argmax(sigma)
V = V[:,mark]
print(V)
result = X.dot(V.T).reshape([-1,1])*V.reshape([1,-1])
print(X.dot(V.T))
plt.title("test")
plt.xlabel("sepal length")
plt.ylabel("sepal width")
plt.plot(result[:50,0],result[:50,1],'bo',color = 'blue',label = '0')
plt.plot(X[:50,0],X[:50,1],'bo',color = 'orange',label = '1')
#下面是fisher判别,因为想到这个了,就写一些
X1 = class1_X[:50,:]
X2 =class1_X[50:,:]
x1_overline = np.sum(X1,axis = 0)/X1.shape[0]
x2_overline = np.sum(X2,axis = 0)/X2.shape[0]
In = np.identity(X1.shape[0])
Hn = In - 1/X1.shape[0]*np.ones([X1.shape[0],X1.shape[0]])
S1 = 1 / X1.shape[0] * X1.T.dot(Hn).dot(X1)
S2 = 1 / X2.shape[0] * X2.T.dot(Hn).dot(X2)
Sw = S1 + S2
w = np.linalg.inv(Sw).dot(x1_overline-x2_overline)
m = (x1_overline + x2_overline) / 2
m2 = m.dot(w.T).reshape([-1,1])*w
print(m2[:,1])
result1 = X1.dot(w.T).reshape([-1,1])*w
result2 = X2.dot(w.T).reshape([-1,1])*w
plt.title("PCA")
plt.xlabel("sepal length")
plt.ylabel("sepal width")
plt.plot(class1_X[:50,0],class1_X[:50,1],'bo',color = 'blue',label = '0')
plt.plot(class1_X[50:,0],class1_X[50:,1],'bo',color = 'orange',label = '1')
plt.plot(result1[:50,0],result1[:50,1],'bo',color = 'blue',label = '0')
plt.plot(result2[:50,0],result2[:50,1],'bo',color = 'orange',label = '0')
plt.plot(m2[:,0],m2[:,1],'bo',color = 'red',label = '1')
参考视频
https://www.bilibili.com/video/av32709936/?p=6