PCA - Temel Bileşenler Analizi

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
% Temel/Ana Bilesenler Cozumlemesi/Analizi (Principle Component Analysis)
% 
% Girdiler: sampleMat -> Her satiri bir ornek vektorden olusan matris, 
%           n -> (opsiyonel) istenilen ozvektor ve ozdeger sayisi 
% Ciktilar: V -> "sampleMat" ile verilen vektorlerin ana yonleri (ozvektorleri). 
%   "V" matrisinin her sutunu bir ozvektordur. Soldan saga dogru baskinlik azalir.
%           D -> "V" ozvektorlerine ait ozdegerler. "D" vektorunun her elemani, "V" 
%   matrisinin ilgili sutunundaki ozvektor yonundeki degisintiyi (varyasyonu) gosterir.   
%
% Ornek: 3 boyutta olan 5 nokta olsun. Bunlari her satira bir tanesi gelecek sekilde yazalim. 
% x = [1 2 1; 0 2 1; 0 3 2; 2 4 1; 1 3 0], n = 2 olursa V iki sutundan olusur ve ilk sutun 
% en cok degisintinin oldugu yonu, ikinci sutun da sonraki 
% baskin yonu gosterir.

% Not: Eger ornek sayisi, boyut sayisindan azsa hizli olmasi icin 
% Eckart-Young teoremini kullanir.

function [V,D] = pca(sampleMat,n)

nSamples = size(sampleMat,1);
nDim = size(sampleMat,2);

% Ortalama vektoru bul
meanSample = mean(sampleMat,1);

% sampleMat'taki tum elemanlardan ortalamayi cikararak normalizasyon yap
sampleMat = sampleMat - repmat(meanSample, nSamples, 1);

% Eger boyut sayisi ornek sayisindan coksa, hizli olmasi icin 
% sampleMat'in transpozesini al
if nDim > nSamples
    sampleMat = sampleMat.';
end

% Dagilimin kovaryansini bul
C = sampleMat.' * sampleMat ./ nSamples;

% Ozdegerler (D) ve ozvektorleri (V) bul
% Hatirla ki: A*V = V*D ve V'nin her sutunu bir ozvektor
[V,D] = eig(C);
D = diag(D);

% Ozdegerleri buyukten kucuge siralamak gerekli. Matlab tersinden 
% buldugu icin degerleri ters dondur.
D = flipud(D); % Sutun vektorunu altust et
V = fliplr(V); % Matrisin sagdan sola aynasini al

% Eger hizlandirma kullanildiysa Buldugumuz sutunlardan ozvektor bulup 
% ozvektorleri normalize etmeliyiz. Ozdegerler aynidir. Bak: Eckart-Young Teoremi
if nDim > nSamples
    V = sampleMat * V;
    for i = 1:nSamples
        normV = norm(V(:,i));
        V(:,i) = V(:,i) ./ normV;
    end
end

if exist('n','var') % n verildiyse, ilk n degeri dondur
    if n > nDim
        error('Isdeginiz ozvektor sayisi bulduklarimdan fazla!')
    end
    D = D(1:n);
    V = V(:,1:n);
end