PCA主成分分析
语言:Matlab
不知道为啥Matlab的代码块竟然没高亮
文章目录
- PCA主成分分析
- 原理
- 求解步骤
- PCA函数
- 示例
- 二维输入
- 三维输入
原理
寻找一组正交基组成的矩阵,有
,使得优化数据
的平方对称矩阵
是对角阵,则此时矩阵的行向量就是数据
的主元向量。这是因为:
- 对角线上的元素对应观测变量的方差,方差越大,表明信号越强
- 非对角线上的元素对应观测变量的协方差,协方差越小,观测变量对之间的冗余程度越小
取,则矩阵
是一个
的对称阵,可以写出
,其中
是对角阵,
是
的特征向量排成的矩阵。再取
,有
,代入上式得
此时得出的恰好为对角阵,因而此时取的
即为所求的变换基。因此,我们只需要对
进行特征分解,再求转置,即可得到
。
求解步骤
设数据维度,每一维度采样点数
,则:
- 得到
的矩阵作为输入矩阵,其中每行为同一个维度的
个采样值
- 对输入数据的每一行减去该行的平均值
,使每一维度的数据均值为0,得到矩阵
- 对矩阵
进行特征分解,求出特征向量及相应的特征根
- 特征向量按行组成变换基
,即
的每一行均为
的主元,可验证其正交性。
将上述计算步骤封装称为PCA函数,将输入数据作为参数传入,返回矩阵和相应特征值。
PCA函数
文件名:PCA.m
function [P, lambda] = PCA(X)
% X - m*n的输入矩阵,其中m为数据维度,n为采样点个数
% P - 特征向量组成的矩阵
% lambda - 特征根组成的列向量
[m, n] = size(X);
for i = 1:m
ave = sum(X(i,:)) / n; % 按维度求平均值ave
X(i,:) = X(i,:) - ave;
end
[P, B] = eig(X*X');
% 对XX'进行特征分解,此时:
% P的每一列是特征向量
% B是对角阵,对角线上的元素是特征根
P = P'; % 使P的行向量为XX'的特征向量
lambda = diag(B); % 提取对角线元素,转化为列向量
end
示例
二维输入
clear
close all
clc
x = randn(1, 200); % 随机产生x,作为第一维输入
y = x + randn(1, 200) * 0.4; % 在y=2x附近随机产生y,作为第二维输入
Input = [x; y]; % 组合成为2*200输入矩阵
[P, lambda] = PCA(Input) % 执行PCA函数
plot([0, P(1,1)*2], [0, P(1,2)*2], '-b'); % 2倍拉长基底,以直观展示
hold on;
plot([0, P(2,1)*2], [0, P(2,2)*2], '-r'); % 2倍拉长基底,以直观展示
hold on;
scatter(x, y);
xlabel('x'); ylabel('y');
axis([-3, 3, -3, 3]); % 限制坐标范围,以直观展示垂直关系
在附近产生
是为了使实验结果更为直观,实际输入的数据可以是完全随机的。
P =
-0.7202 0.6938
0.6938 0.7202
lambda =
15.9034
378.2395
>>
容易看出两组基底具有正交性。
调整输入为
x = randn(1, 200);
y = -x + randn(1, 200) * 0.4;
再次进行测试,有输出为
P =
-0.7295 -0.6840
-0.6840 0.7295
lambda =
14.5966
373.8049
>>
容易得出两组基底仍具有正交性。
三维输入
clear
close all
clc
x = randn(1, 200); % 随机产生x,作为第一维输入
y = randn(1, 200); % 随机产生y,作为第二维输入
z = x + y + randn(1, 200) * 0.2; % 在z=x+y附近随机产生z,作为第三维输入
Input = [x; y; z]; % 组合成3*200输入矩阵
[P, lambda] = PCA(Input) % 执行PCA函数
for i = 1:3
plot3([0,P(i,1)*4], [0, P(i,2)*4], [0,P(i,3)*4]); % 4倍拉长基底,以直观展示
hold on;
end
scatter3(x, y, z);
xlabel('x'); ylabel('y'); zlabel('z');
axis([-4, 4, -4, 4, -4, 4]); % 限制坐标范围,以直观展示垂直关系
同理,在附近产生
也是考虑到结果的直观性。可以得到输出
P =
0.5876 0.5786 -0.5656
0.6178 -0.7723 -0.1482
0.5225 0.2623 0.8113
lambda =
2.4494
177.0606
617.6643
>>
容易看出三组基底的正交性。