引子
首先看一下如何对一维向量的进行分解,我们知道,一个
n
n
n 维向量
a
a
a 可以由
n
n
n 个正交向量线性
v
i
,
i
=
1
,
2
,
.
.
.
,
n
v_i,i=1,2,...,n
vi,i=1,2,...,n 组合而来,即
a
=
∑
k
=
1
n
k
i
v
i
(1)
a=\sum_{k=1}^{n}k_iv_i \tag {1}
a=k=1∑nkivi(1)
在图像与信号处理领域常用的傅里叶变换(Fourier Transform)、小波变换(Wavelet Transform)等,都是基于此理论。
我们知道,随着傅里叶级数的阶数的增加,其结果将越来越接近原始信号,因此实际上我们只需要记录能量较高的几个分量及其幅值,就可以基本复原原始信号。那么对于图像这样的二维数据,要怎样分解呢?
实际上,答案是对每一行向量分别进行分解,它们使用同一组正交基。
如何获取正交基
我们知道,对于矩阵 A A A ,如果有一组标准正交基 v i v_i vi ,那么矩阵 A A A 的每一行都可以由向量 v i v_i vi 线性组合得到。
然而正交基有很多,如何选取正交基,可以从中挑选尽可能少的向量,而能表示尽可能多信息?(如何提高压缩效率)
假设我们已经有了一组正交向量
u
i
u_i
ui ,那么对于向量
u
u
u ,如何衡量它所表示的信息的多少呢?我们知道,向量
a
a
a 与向量
u
u
u 做内积,即
a
⋅
u
=
∑
j
=
1
n
a
i
u
i
(2)
a\cdot u=\sum_{j=1}^{n}a_iu_i \tag {2}
a⋅u=j=1∑naiui(2)
表征了向量
a
a
a 中向量
u
u
u 占据的分量大小,对于数据
A
m
×
n
=
[
a
1
T
,
a
2
T
,
.
.
.
,
a
m
T
]
T
A_{m\times n}=[a_1^T,a_2^T,...,a_m^T]^T
Am×n=[a1T,a2T,...,amT]T ,其每一行
a
i
a_i
ai 中向量
u
u
u 的分量大小
e
i
e_i
ei 为
A
u
=
[
a
1
a
2
⋮
a
m
]
u
=
[
e
1
e
2
⋮
e
m
]
(3)
Au= \left[ \begin{array}{c} a_1 \\ a_2 \\ \vdots \\ a_m \end{array} \right] u = \left[ \begin{array}{c} e_1 \\ e_2 \\ \vdots \\ e_m \end{array} \right] \tag {3}
Au=⎣⎢⎢⎢⎡a1a2⋮am⎦⎥⎥⎥⎤u=⎣⎢⎢⎢⎡e1e2⋮em⎦⎥⎥⎥⎤(3)
为了使向量
u
u
u 能够表示尽可能多信息,即
e
i
e_i
ei尽可能大,我们计算其平方和,并希望其尽可能大
E
=
∑
j
=
1
m
e
j
2
=
(
A
u
)
T
(
A
u
)
=
u
T
A
T
A
u
(4)
\begin{array}{l} E&=\ \sum_{j=1}^{m}e_j^2\\ &=\ (Au)^T(Au)\\ &=\ u^TA^TAu \end{array} \tag {4}
E= ∑j=1mej2= (Au)T(Au)= uTATAu(4)
这里我们发现,有一个熟悉的结构出现了!回忆矩阵的特征向量,对于矩阵
R
R
R ,其特征向量组成的矩阵
Q
=
[
v
1
,
v
2
,
⋯
,
v
n
]
Q=[v_1,v_2,\cdots,v_n]
Q=[v1,v2,⋯,vn] ,其特征值组成的对角矩阵
Σ
=
d
i
a
g
{
λ
1
,
λ
2
,
⋯
,
λ
n
}
\Sigma=diag\{\lambda_1,\lambda_2,\cdots,\lambda_n \}
Σ=diag{λ1,λ2,⋯,λn} ,有
R
=
Q
Σ
Q
−
1
(5)
R=Q \Sigma Q^{-1} \tag {5}
R=QΣQ−1(5)
变换一下形式
Σ
=
Q
−
1
R
Q
(6)
\Sigma=Q^{-1}RQ \tag {6}
Σ=Q−1RQ(6)
如果我们把
A
T
A
A^TA
ATA 视作
R
1
R_1
R1 ,把
[
u
1
,
u
2
,
⋯
,
u
n
]
[u_1,u_2,\cdots,u_n]
[u1,u2,⋯,un] 视作
Q
1
Q_1
Q1 ,我们有
Σ
1
=
Q
1
T
R
1
Q
1
(7)
\Sigma _1=Q_1^T R_1 Q_1 \tag {7}
Σ1=Q1TR1Q1(7)
然而我们发现式(7)与式(6)还存在微小差别,那么让我们继续回忆线性代数的知识,什么情况下矩阵
Q
Q
Q 的逆等于其自身的转置呢?答案是如果方阵
Q
Q
Q 的每一列(行)向量都是单位向量,且两两之间相互正交,则
Q
T
Q
=
I
Q^TQ=I
QTQ=I ,
Q
Q
T
=
I
QQ^T=I
QQT=I ,即
Q
−
1
=
Q
T
Q^{-1}=Q^T
Q−1=QT 。
也就是说,如果我们将能够使 R 1 R_1 R1 的特征向量单位正交,那么问题将转化为:选择一特征向量,使其对应的特征值尽可能大。
什么样的矩阵的特征向量单位正交?
- 满足什么特征的矩阵的特征向量相互正交?
我们知道,实对称矩阵的特征向量是自然正交的。
由于矩阵 ( A T A ) T = A T A (A^TA)^T=A^TA (ATA)T=ATA ,因此矩阵 A T A A^TA ATA 是实对称阵,即其特征向量是一组正交向量。
- 特征向量单位化
至于单位化,由于
A
x
=
λ
x
Ax=\lambda x
Ax=λx,所以
A
x
∣
∣
x
∣
∣
=
λ
x
∣
∣
x
∣
∣
(8)
A\frac{x}{||x||}=\lambda \frac{x}{||x||} \tag {8}
A∣∣x∣∣x=λ∣∣x∣∣x(8)
所以
x
/
∣
∣
x
∣
∣
x/||x||
x/∣∣x∣∣ 也是
A
A
A 的特征向量。
至此,我们得到了 R 1 R_1 R1 的一组单位正交的特征向量组。
求矩阵 R 1 R_1 R1 的特征值与特征向量,然后对特征值进行排序,从最大特征值对应的特征向量开始挑选,直到达到所要求的信息保留率为止,则挑选出的向量组 [ v k 1 , v k 2 , . . . , v k p ] [v_{k_1},v_{k_2},...,v_{k_p}] [vk1,vk2,...,vkp] 即所谓的“主成分”,记为 V V V。
如何计算主成分得分
对于矩阵
A
=
[
b
1
T
,
b
2
T
,
.
.
.
,
b
m
T
]
T
A=[b_1^T,b_2^T,...,b_m^T]^T
A=[b1T,b2T,...,bmT]T 的每一行向量
b
i
b_i
bi,与向量
v
j
v_j
vj 做内积,即向量
b
i
T
b_i^T
biT 中向量
v
j
v_j
vj 的分量大小,因此主成分得分为
F
m
×
p
=
A
V
=
[
b
1
T
⋅
v
1
b
1
T
⋅
v
2
⋯
b
1
T
⋅
v
p
b
2
T
⋅
v
1
b
2
T
⋅
v
2
⋯
b
2
T
⋅
v
p
⋮
⋮
⋱
⋮
b
m
T
⋅
v
1
b
m
T
⋅
v
1
⋯
b
m
T
⋅
v
p
]
(9)
F_{m\times p}=A V= \left[ \begin{array}{c} b_1^T\cdot v_1& \quad b_1^T\cdot v_2& \quad \cdots& \quad b_1^T\cdot v_p \\ b_2^T\cdot v_1& \quad b_2^T\cdot v_2& \quad \cdots& \quad b_2^T\cdot v_p \\ \vdots& \quad \vdots& \quad \ddots& \quad \vdots& \\ b_m^T\cdot v_1& \quad b_m^T\cdot v_1& \quad \cdots& \quad b_m^T\cdot v_p \\ \end{array} \right] \tag {9}
Fm×p=AV=⎣⎢⎢⎢⎡b1T⋅v1b2T⋅v1⋮bmT⋅v1b1T⋅v2b2T⋅v2⋮bmT⋅v1⋯⋯⋱⋯b1T⋅vpb2T⋅vp⋮bmT⋅vp⎦⎥⎥⎥⎤(9)
其中
F
i
j
F_{ij}
Fij 表示
A
A
A 的第
i
i
i 行数据中,
v
j
v_j
vj 分量的大小。
如何恢复数据
我们根据
A
2
=
F
V
T
(10)
A_2=FV^T \tag {10}
A2=FVT(10)
进行数据恢复( 因为
v
i
v_i
vi 单位正交,
V
V
T
=
I
VV^T=I
VVT=I ,由(9)式可推知(10)式 ) ,
A
2
A_2
A2 即
A
A
A 的近似。
标准PCA流程
好了,现在我们已经了解了如何用特征向量来进行数据压缩,让我们来看一下标准的PCA是如何做的:
- 将数据 A m × n A_{m\times n} Am×n 的每一列进行标准化
A 2 = [ a 1 − m e a n ( a 1 ) s t d ( a 1 ) , a 2 − m e a n ( a 2 ) s t d ( a 2 ) , . . . , a n − m e a n ( a n ) s t d ( a n ) ] (11) A_2= \left[ \frac{a_1-mean(a_1)}{std(a_1)},\frac{a_2-mean(a_2)}{std(a_2)},...,\frac{a_n-mean(a_n)}{std(a_n)} \right] \tag {11} A2=[std(a1)a1−mean(a1),std(a2)a2−mean(a2),...,std(an)an−mean(an)](11)
其中
X
‾
=
m
e
a
n
(
X
)
=
1
m
∑
j
=
1
m
x
j
(12)
\overline X=mean(X)=\frac{1}{m}\sum_{j=1}^{m}x_j \tag {12}
X=mean(X)=m1j=1∑mxj(12)
s t d ( X ) = 1 m − 1 ∑ j = 1 m ( x j − X ‾ ) 2 (13) std(X)=\frac{1}{m-1}\sqrt{\sum_{j=1}^{m}(x_j-\overline X)^2} \tag {13} std(X)=m−11j=1∑m(xj−X)2(13)
- 计算 A 2 A_2 A2 的协方差矩阵,矩阵 A 2 = [ X 1 , X 2 , ⋯ , X n ] A_2=[X_1,X_2,\cdots,X_n] A2=[X1,X2,⋯,Xn] 的协方差矩阵为
R = σ ( X 1 , X 2 , . . . , X n ) = 1 n − 1 [ σ ( X 1 , X 1 ) σ ( X 1 , X 2 ) ⋯ σ ( X 1 , X n ) σ ( X 2 , X 1 ) σ ( X 2 , X 2 ) ⋯ σ ( X 2 , X n ) ⋮ ⋮ ⋱ ⋮ σ ( X n , X 1 ) σ ( X n , X 2 ) ⋯ σ ( X n , X n ) ] (14) R= \sigma(X_1,X_2,...,X_n)= \frac{1}{n-1} \left[ \begin{array}{c} \sigma(X_1,X_1)& \quad \sigma(X_1,X_2)& \quad \cdots& \quad \sigma(X_1,X_n) \\ \sigma(X_2,X_1)& \quad \sigma(X_2,X_2)& \quad \cdots& \quad \sigma(X_2,X_n) \\ \vdots& \quad \vdots& \quad \ddots& \quad \vdots& \\ \sigma(X_n,X_1)& \quad \sigma(X_n,X_2)& \quad \cdots& \quad \sigma(X_n,X_n) \\ \end{array} \right] \tag {14} R=σ(X1,X2,...,Xn)=n−11⎣⎢⎢⎢⎡σ(X1,X1)σ(X2,X1)⋮σ(Xn,X1)σ(X1,X2)σ(X2,X2)⋮σ(Xn,X2)⋯⋯⋱⋯σ(X1,Xn)σ(X2,Xn)⋮σ(Xn,Xn)⎦⎥⎥⎥⎤(14)
其中方差计算公式为
σ
(
X
,
Y
)
=
1
m
−
1
∑
j
=
1
m
(
x
j
−
X
‾
)
(
y
j
−
Y
‾
)
(15)
\sigma (X,Y)=\frac{1}{m-1}\sum_{j=1}^{m}(x_j-\overline X)(y_j-\overline Y) \tag {15}
σ(X,Y)=m−11j=1∑m(xj−X)(yj−Y)(15)
由于经过变换后,
A
2
A_2
A2 的每一列向量均值为0,因此
R
=
1
n
−
1
A
2
T
A
2
(16)
R=\frac{1}{n-1}A_2^T A_2 \tag {16}
R=n−11A2TA2(16)
根据之前的讨论,这里的协方差矩阵
R
R
R 的特征向量,将是一组单位正交向量。
- 计算 R R R 的特征值与对应的特征向量,并按照特征值大小降序排列。
- 依据主成分信息保留率 T T T ,计算出保留的特征向量个数 k k k ,使
∑ i = 1 k λ k > T (17) \sum_{i=1}^{k}\lambda_k>T \tag {17} i=1∑kλk>T(17)
- 获得主成分 V V V
V = [ v 1 , v 2 , . . . , v k ] (18) V=[v_1,v_2,...,v_k] \tag {18} V=[v1,v2,...,vk](18)
- 计算主成分得分 F F F
F = A 2 V (19) F=A_2V \tag {19} F=A2V(19)
- 算法结束,输出主成分 V n × k V_{n\times k} Vn×k 、主成分得分 F m × k F_{m\times k} Fm×k 、 A A A 的列向量的 均值 M 1 × n M_{1\times n} M1×n 与 标准差 D 1 × n D_{1\times n} D1×n
PCA数据恢复
- 计算 B = [ b 1 , b 2 , . . . , b n ] = F V T B=[b_1,b_2,...,b_n]=FV^T B=[b1,b2,...,bn]=FVT ;
- 对每一列进行还原,得到复原数据 C = [ c 1 , c 2 , . . . , c n ] C=[c_1,c_2,...,c_n] C=[c1,c2,...,cn] ,其中
c j = s t d j b j + m e a n j (20) c_j=std_jb_j+mean_j \tag {20} cj=stdjbj+meanj(20)
matlab实验
第一种,使用标准的PCA方法:
%----------主成分分析(PCA)---------
% author: 今朝无言
function [V,F,M,D]=PCA(m,T)
% m为二维数据,T为信息保留率
M=mean(m,1);
D=std(m,1);
s=size(m);
m2=(m-ones(s(1),1)*M)./(ones(s(1),1)*D); %标准化
R=cov(m2); %协方差矩阵
[x,y]=eig(R); %求特征向量x、特征值y
y=diag(y);
[y,index]=sort(y);
y=y(end:-1:1); index=index(end:-1:1); %降序排列
x=x(:,index); %将x按y的次序排列
DS(:,1)=y; %特征值
DS(:,2)=DS(:,1)/sum(DS(:,1)); %贡献率
DS(:,3)=cumsum(DS(:,2)); %累积贡献率
k=find(DS(:,3)>=T); k=k(1); %选取的特征向量个数
V=x(:,1:k); %k个特征向量
F=m2*V; %主成分得分
end
第二种,不归一化:
%----------主成分分析(PCA)---------
% author: 今朝无言
function [V,F]=PCA2(m,T)
% m为二维数据,T为信息保留率
R=m'*m;
[x,y]=eig(R); %求特征向量x、特征值y
y=diag(y);
[y,index]=sort(y);
y=y(end:-1:1); index=index(end:-1:1); %降序排列
x=x(:,index); %将x按y的次序排列
DS(:,1)=y; %特征值
DS(:,2)=DS(:,1)/sum(DS(:,1)); %贡献率
DS(:,3)=cumsum(DS(:,2)); %累积贡献率
k=find(DS(:,3)>=T); k=k(1); %选取的特征向量个数
V=x(:,1:k); %k个特征向量
F=m*V; %主成分得分 Fij表示m第i行数据对特征向量j的得分(数据i对向量j的投影长度)
end
实验验证:
% test PCA
clc,clear,close all
%%
m=imread('1.jpg');
m=double(rgb2gray(m));
s=size(m);
%% 标准PCA
T=0.95;
[V,F,M,D]=PCA(m,T);
m2=F*V';
m2=m2.*(ones(s(1),1)*D)+ones(s(1),1)*M;
figure
set(gcf,'unit','normalized','position',[0.2,0.2,0.64,0.32]);
subplot(1,2,1); imshow(uint8(m))
subplot(1,2,2); imshow(uint8(m2))
title('PCA')
%% 不归一化的PCA
T2=0.999;
%由于第一个向量比重太大,因此T要设置的大一些,然而在更小的压缩率下,恢复效果比上述PCA强很多!
[V2,F2]=PCA2(m,T2);
m3=F2*V2';
figure
set(gcf,'unit','normalized','position',[0.2,0.2,0.64,0.32]);
subplot(1,2,1); imshow(uint8(m))
subplot(1,2,2); imshow(uint8(m3))
title('PCA2')
%%
fprintf('PCA 压缩率=%f\t\t',...
(size(V(:),1)+size(F(:),1)+size(M(:),1)+size(D(:),1))/size(m(:),1))
fprintf('PCA MSE=%f\n',sum(sqrt(m2(:)-m(:)))/(s(1)*s(2)))
fprintf('PCA2 压缩率=%f\t\t',...
(size(V2(:),1)+size(F2(:),1))/size(m(:),1))
fprintf('PCA2 MSE=%f\n',sum(sqrt(m3(:)-m(:)))/(s(1)*s(2)))
结果:
可以看到,第二种方法在获得更小的压缩率的同时,同时数据恢复效果也更好。单从视觉上看,尽管均方误差差不多,但前者的噪声肉眼明显可见,而后者几乎完全看不到噪声。