主成分分析(PCA)的数学原理与应用

PCA(主成分分析)主要用于数据降维。

问题:样本 x i R m   以列向量表示,现将 n  个样本构成的样本集 XR m×n   降维到 X ^ R k×n   km  ),以达到数据压缩的目的。

不难发现,上述问题的核心是:将 X  中的每个样本点由原来的 m  维坐标系投影到新的 k  维坐标系中。

考虑最简单的二维数据:

import numpy as np
import matplotlib.pyplot as plt

# 绘制数据点
k = 0.3   # 斜率
b = 0.1   # 截距
x1 = np.random.random(30)
x2 = k * x1 + b + np.random.randint(-5, 5, 30) / 100

ax = plt.gca()
ax.set_aspect(1)
plt.scatter(x1, x2, marker='x')

# 中心点
cx = np.mean(x1)
cy = np.mean(x2)

# 绘制第一个维度u1
u1_x = 0.9
u1_y = k * u1_x + b
plt.annotate('', xytext=(cx, cy), xy=(u1_x, u1_y), arrowprops=dict(arrowstyle="->"))
plt.text(u1_x - 0.1, u1_y + 0.01, '$u_1$', fontsize=16)

# 绘制第二个维度u2
u2_x = cx - 0.02
u2_y = (-1 / k) * u2_x + (cy + cx / k)
plt.annotate('', xytext=(cx, cy), xy=(u2_x, u2_y), arrowprops=dict(arrowstyle="->"))
plt.text(u2_x - 0.1, u2_y - 0.01, '$u_2$', fontsize=16)

plt.show()

这里写图片描述

人能够很直观地看出上述二维数据的2个维度的大致方向,其中最主要的那个方向是 u 1   ,因为数据在该方向上的分布最为分散(投影绝对值或方差之和最大)。也可以换个角度看,如果要用1维数据来最大限度地“拟合”二维数据,显然这些二维数据投影在 u 1   这个方向上要比投影在 u 2   上好。因此, u 1   是该数据集的【第1主要成分】,而 u 2   则是【第2主要成分】,这个思想同样适用于更高维的数据。

通过上面的分析可知,当所有的数据点在 u 1   方向上的投影绝对值(或方差)之和最大时,此时的 u 1   就是第1主成分。找 u 1   的问题则可以表示为:

argmax u 1  ( i=1 n proj(x i ,u 1 ))x i ,u 1 R m  

其中, proj(x i ,u 1 )  x i   u 1   上的投影长度。容易求得:

proj(x i ,u 1 )=x i u 1 u 1  2  =x T i u 1 u 1  2   

因为我们只考虑 u 1   的方向,故设 u 1   具有单位长度,即 u 1   L 2   范数为1,则:

== argmax u 1  ( i=1 n proj(x i ,u 1 ))=argmax u 1  ( i=1 n x T i u 1 )s.t.u 1  2 =1argmax u 1  ( i=1 n (x T i u 1 ) 2 )=argmax u 1  ( i=1 n (x T i u 1 ) T x T i u 1 )argmax u 1  ( i=1 n u T 1 x i x T i u 1 )=argmax u 1  (u T 1 ( i=1 n x i x T i )u 1 )  

因为, X=[x 1 x 2 x n  ],X T =      x T 1 x T 2 x T n          ,所以:

argmax u 1  (u T 1 ( i=1 m x i x T i )u 1 )=argmax u 1  (u T 1 XX T u 1 ) 

上式即为我们要最大化的目标函数。若能证明矩阵 XX T R m×m   是(半)正定的,则说明 u T 1 XX T u 1   是(半)正定二次型,也就存在最大值。设 λ  是对称矩阵 XX T   的任一特征值,其对应的特征向量是 vR m   ,则有:

 XX T v=λv(XX T v) T v=(λv) T vv T XX T v=v T λv(X T v) T X T v=λv T vX T v 2 2 =λv 2 2 λ0  

证毕。

下面使用拉格朗日乘子法求 u T 1 XX T u 1   在约束 u T 1 u 1 =1  下的极值,令:

f(u 1 )=u T 1 XX T u 1 α(1u T 1 u 1 ) 

u 1   求导,并令其为 0 

 fu 1  =2XX T u 1 2αu 1 =0XX T u 1 =αu 1   

可见,当 u 1   取矩阵 XX T   的某个特征值 α  对应的特征向量时,前述目标函数取得最大值。注意,若选取的特征值 α  不同,其对应的特征向量 u 1   也不同,则前述目标函数的最大值也不同。将上式代入目标函数,可得:

argmax u 1  (u T 1 XX T u 1 )=αu T 1 u 1 =α 

可见,当 u 1   取最大特征值对应的特征向量时,前述目标函数将取得所有最大值中的最大值,此时的 u 1   即为【第1主成分】。若取前 k  大特征值对应的特征向量 u 1 ,u 2 ,,u k  ,则样本 x i   在这 k  个主成分(维度)上的投影则为:

x i  ^ =[x T i u 1 x T i u 2 x T i u k  ]kn 

主成分矩阵:

U=[u 1 u 2 u k  ]R m×k kn 

降维后的数据集:

X ^ =U T XR k×n  

将降维后的 k  维数据集还原到原始的 m  维坐标系:

X restore =UX ^ =UU T XR m×n  

下面通过一个图像压缩的例子来验证PCA。

import math
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

# 读取图片
X = np.array(Image.open(".\_data\son.jpg").convert('L'), 'f') # M*N
M = X.shape[0]
N = X.shape[1]

XXT = X.dot(X.T) # shape: M*M

e, V = np.linalg.eig(XXT) #特征值、特征向量 
U = V[np.argsort(-e)] # M*M,按特征值从大到小,对特征向量排序

plt.subplots(figsize=(20,10))
r, c, i = (5, 6, 1)

for k in range(M, 0, -math.ceil(M/(r*c))):
    Uk = U[:, 0:k] # M*k
    X_ = Uk.dot(Uk.T).dot(X) # X_restore: M*N
    ratio = 1.0*k*(M+N)/(M*N)
    plt.subplot(r, c, i, title='↓k=%d, ratio=%.1f' % (k, ratio)).axis('off')
    plt.imshow(Image.fromarray(X_))
    i+=1

plt.axis('off')
plt.show()

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值