본문 바로가기

Enginius/Machine Learning

Principal component analysis (PCA) on data

0. PCA란? 

 PCA는 principal component analysis의 약자로 주어진 데이터의 principal component를 찾는 알고리즘이다. 그리고 principal component는 주어진 데이터를 가장 잘 표현하는 축인 basis를 의미한다. 

 

 즉 PCA를 이해하기 위해서는 주어진 데이터를 잘 표현하는 것이 무엇인지를 알아야한다. PCA에서는 분산을 최대로하는 basis를 찾는 것을 의미한다. 밑의 구현에서 보면 알겠지만 데이터를 col 방향으로 쌓은 matrix D가 있을 때 분산은 D'*D이고, D'*D의 eigenvector들이 principal component들이다. 데이터의 손실률은 eigenvalue의 합에 반비례한다. 


1. PCA 결과 


[그림을 클릭하면 크게 보임]


2. 매트랩 코드 

%% PCA는 기본적으로 unsupervised learning이다. 

clc;

clear all;

close all;


%% 데이터를 만든다. 

c_var = 2;

c1count = 100;

c1mean  = [10 4 1];

c1var   = diag([c_var c_var c_var]);


c2count = 100;

c2mean  = [2 10 5];

c2var   = diag([c_var c_var c_var]);


c3count = 100;

c3mean  = [3 1 10];

c3var   = diag([c_var c_var c_var]);


% 데이터를 하나로 묶는다. 

data = [ ones(c1count, 1)*c1mean+randn(c1count, 3)*sqrt(c1var) ...

    ; ones(c2count, 1)*c2mean+randn(c2count, 3)*sqrt(c2var) ...

    ; ones(c3count, 1)*c3mean+randn(c3count, 3)*sqrt(c3var) ...

    ];


%% PCA를 수행한다. 

[coeff, score] = princomp(data);


% 차원을 줄이지 않았을 때 (3차원)

data_3d = data*coeff;


% 차원을 하나 줄였을 때 (2차원)

data_2d = data*coeff(:, 1:2);


% 차원을 두 개 줄였을 때 (1차원)

data_1d = data*coeff(:, 1:2);


%% 결과를 그림으로 확인한다. 

fig1 = figure('Position', [100 100 1300 800], 'Name' ...

    , 'Note that PCA is basically an Unsupervised learning algorithm. Lable information is not used. ');

% reference 

subplot(221); hold on;

h1 = plot3( data(1:c1count, 1) ...

    , data(1:c1count, 2) ...

    , data(1:c1count, 3), 'ro');

h2 = plot3( data(c1count+1:c1count+c2count, 1) ...

    , data(c1count+1:c1count+c2count, 2) ...

    , data(c1count+1:c1count+c2count, 3), 'go');

h3 = plot3( data(c1count+c2count+1:c1count+c2count+c3count, 1) ...

    , data(c1count+c2count+1:c1count+c2count+c3count, 2) ...

    , data(c1count+c2count+1:c1count+c2count+c3count, 3), 'bo');

hold off; grid on;title('Reference data'); legend([h1 h2 h3], 'type1', 'type2', 'type3');

view(-33, 24); axis tight;


% 3D

subplot(222); hold on;

h1 = plot3( data_3d(1:c1count, 1) ...

    , data_3d(1:c1count, 2) ...

    , data_3d(1:c1count, 3), 'ro');

h2 = plot3( data_3d(c1count+1:c1count+c2count, 1) ...

    , data_3d(c1count+1:c1count+c2count, 2) ...

    , data_3d(c1count+1:c1count+c2count, 3), 'go');

h3 = plot3( data_3d(c1count+c2count+1:c1count+c2count+c3count, 1) ...

    , data_3d(c1count+c2count+1:c1count+c2count+c3count, 2) ...

    , data_3d(c1count+c2count+1:c1count+c2count+c3count, 3), 'bo');

hold off; grid on;title('PCA dim no reduced data'); legend([h1 h2 h3], 'type1', 'type2', 'type3');

view(-80, 56); axis tight;


% 2D

subplot(223); hold on;

h1 = plot( data_2d(1:c1count, 1) ...

    , data_2d(1:c1count, 2), 'ro');

h2 = plot( data_2d(c1count+1:c1count+c2count, 1) ...

    , data_2d(c1count+1:c1count+c2count, 2), 'go');

h3 = plot( data_2d(c1count+c2count+1:c1count+c2count+c3count, 1) ...

    , data_2d(c1count+c2count+1:c1count+c2count+c3count, 2), 'bo');

hold off; grid on;title('PCA 3D->2D data'); legend([h1 h2 h3], 'type1', 'type2', 'type3');

axis tight;


% 1D

subplot(224); hold on;

h1 = plot( data_1d(1:c1count, 1), 'ro-');

h2 = plot( data_1d(c1count+1:c1count+c2count, 1), 'go-');

h3 = plot( data_1d(c1count+c2count+1:c1count+c2count+c3count, 1), 'bo-');

hold off; grid on;title('PCA 3D->1D data'); legend([h1 h2 h3], 'type1', 'type2', 'type3');

axis tight;



set(fig1,'PaperPositionMode','auto')

print (fig1 , '-dpng', ['fig_pca', num2str(0), '.png']) ;

%%



3. 추가 - 매트랩의 princomp를 svd로 구현하기 

%% PCA를 수행한다. 

[coeff, score, latent] = princomp(data);


%% svd를 이용해서 PCA를 하기 

x = data;

[n, p] = size(x);

avg = ones(n, 1)*mean(x, 1);

x0 = x - avg;

[U D V] = svd(x0', 0);

evs = diag(D);

evs = evs ./ sqrt(n-1);

evs = evs.^2;

% U가 coeff와 같고, evs가 latent와 같다. 




'Enginius > Machine Learning' 카테고리의 다른 글