Oto krótki przewodnik. Najpierw tworzymy macierz twoich ukrytych zmiennych (lub "czynników"). Ma 100 obserwacji i istnieją dwa niezależne czynniki.
>> factors = randn(100, 2);
Teraz utwórz macierz obciążeń. To zmapuje ukryte zmienne na obserwowane zmienne. Powiedz, że obserwowane zmienne mają cztery funkcje. Wówczas macierz obciążenia musi być 4 x 2
>> loadings = [
1 0
0 1
1 1
1 -1 ];
, który mówi, że po raz pierwszy zaobserwowane zmienne obciążenia na pierwszy czynnik, drugi ładuje na drugiego czynnika, trzeci zmiennych obciążeń na sumę czynników i zmiennych czwartego obciąża różnicę czynników.
teraz tworzyć swoje obserwacje:
>> observations = factors * loadings' + 0.1 * randn(100,4);
dodałem niewielką ilość szumu losowego do symulacji błędu doświadczalnego. Teraz wykonujemy PCA używając funkcji pca
z przybornika statystyki:
>> [coeff, score, latent, tsquared, explained, mu] = pca(observations);
Zmienna score
jest tablica z zasadniczych punktów składowych. Będą prostopadłe przez budowę, co można sprawdzić -
>> corr(score)
ans =
1.0000 0.0000 0.0000 0.0000
0.0000 1.0000 0.0000 0.0000
0.0000 0.0000 1.0000 0.0000
0.0000 0.0000 0.0000 1.0000
Połączenie score * coeff'
będzie odtworzyć wyśrodkowany wersję swoimi obserwacjami. Średnia mu
jest odejmowana przed wykonaniem PCA. Aby odtworzyć oryginalne obserwacje trzeba dodać ją z powrotem,
>> reconstructed = score * coeff' + repmat(mu, 100, 1);
>> sum((observations - reconstructed).^2)
ans =
1.0e-27 *
0.0311 0.0104 0.0440 0.3378
uzyskać przybliżenie do oryginalnych danych, można rozpocząć upuszczanie kolumny z obliczonymi głównych komponentów.Aby zorientować się, które kolumny spadać, badamy explained
zmienne
>> explained
explained =
58.0639
41.6302
0.1693
0.1366
Wpisy powiedzieć, jaki procent wariancji jest wyjaśnione przez każdego z głównych składników. Możemy wyraźnie zobaczyć, że pierwsze dwa elementy są bardziej znaczące niż dwa pierwsze (wyjaśniają ponad 99% wariancji między nimi). Korzystanie z dwóch pierwszych części zrekonstruować uwagi daje ranga-2 przybliżenie,
>> approximationRank2 = score(:,1:2) * coeff(:,1:2)' + repmat(mu, 100, 1);
Możemy teraz próbować kreślenia:
>> for k = 1:4
subplot(2, 2, k);
hold on;
grid on
plot(approximationRank2(:, k), observations(:, k), 'x');
plot([-4 4], [-4 4]);
xlim([-4 4]);
ylim([-4 4]);
title(sprintf('Variable %d', k));
end
otrzymujemy niemal idealne odwzorowanie oryginału obserwacje. Gdybyśmy chcieli grubsze przybliżenie, możemy po prostu użyć pierwszy składnik główny:
>> approximationRank1 = score(:,1) * coeff(:,1)' + repmat(mu, 100, 1);
i wykreślić go,
>> for k = 1:4
subplot(2, 2, k);
hold on;
grid on
plot(approximationRank1(:, k), observations(:, k), 'x');
plot([-4 4], [-4 4]);
xlim([-4 4]);
ylim([-4 4]);
title(sprintf('Variable %d', k));
end
Tym razem odbudowa nie jest tak dobry. Dzieje się tak, ponieważ celowo skonstruowaliśmy nasze dane, aby mieć dwa czynniki, a my tylko rekonstruujemy je z jednego z nich.
Należy zauważyć, że pomimo podobieństwa sugestywny sposób, w jaki zbudowane oryginalnych danych i ich reprodukcji,
>> observations = factors * loadings' + 0.1 * randn(100,4);
>> reconstructed = score * coeff' + repmat(mu, 100, 1);
tam niekoniecznie jest wszelka korespondencja pomiędzy factors
i score
lub pomiędzy loadings
i coeff
. Algorytm PCA nie wie nic o sposobie konstruowania danych - próbuje jedynie wyjaśnić jak najwięcej wariancji z każdym kolejnym komponentem.
Użytkownik @Mari zapytał w komentarzach, w jaki sposób może wykreślić błąd rekonstrukcji w zależności od liczby głównych składników. Używanie powyższej zmiennej jest całkiem proste. Będę wygenerować pewne dane z bardziej interesujących strukturze czynnika w celu zilustrowania wpływu -
>> factors = randn(100, 20);
>> loadings = chol(corr(factors * triu(ones(20))))';
>> observations = factors * loadings' + 0.1 * randn(100, 20);
Teraz wszystkie obserwacje załadować na znaczną wspólnego czynnika, z innych czynników maleje znaczenie. Możemy dostać rozkład PCA jak przed
>> [coeff, score, latent, tsquared, explained, mu] = pca(observations);
i wykreślić procent wyjaśnione wariancji następująco,
>> cumexplained = cumsum(explained);
cumunexplained = 100 - cumexplained;
plot(1:20, cumunexplained, 'x-');
grid on;
xlabel('Number of factors');
ylabel('Unexplained variance')
naprawdę świetna odpowiedź, chciałem ci podziękować. –
Niesamowita odpowiedź. Dzięki Chris! – rayryeng
Świetne do nauki. Dzięki za wiele. Chociaż mam małe wątpliwości, dlaczego najpierw musimy tworzyć ukryte zmienne? Czy mogę rozpocząć od '[w pc ev] = princomp (X);' do analizy moich oryginalnych danych? Dzięki jeszcze raz. – Mari