Nach dem hervorragenden Beitrag von JD Long in diesem Thread suchte ich nach einem einfachen Beispiel und dem R-Code, der zur Erstellung der PCA erforderlich ist, und kehrte dann zu den Originaldaten zurück. Es gab mir eine geometrische Intuition aus erster Hand, und ich möchte teilen, was ich bekam. Der Datensatz und der Code können direkt kopiert und in R-Form Github eingefügt werden .
Ich habe einen Datensatz verwendet, den ich hier online auf Halbleitern gefunden habe , und ihn auf nur zwei Dimensionen - "Ordnungszahl" und "Schmelzpunkt" - getrimmt, um das Plotten zu erleichtern.
Als Einschränkung dient die Idee lediglich der Veranschaulichung des Berechnungsprozesses: PCA wird verwendet, um mehr als zwei Variablen auf einige abgeleitete Hauptkomponenten zu reduzieren oder die Kollinearität auch bei mehreren Merkmalen zu identifizieren. Daher würde es bei zwei Variablen keine große Anwendung finden, und es würde auch keine Notwendigkeit bestehen, Eigenvektoren von Korrelationsmatrizen zu berechnen, wie von @amoeba ausgeführt.
Außerdem habe ich die Beobachtungen von 44 auf 15 gekürzt, um die Verfolgung einzelner Punkte zu vereinfachen. Das Endergebnis war ein Skelett-Datenrahmen ( dat1
):
compounds atomic.no melting.point
AIN 10 498.0
AIP 14 625.0
AIAs 23 1011.5
... ... ...
Die Spalte "Verbindungen" gibt die chemische Konstitution des Halbleiters an und spielt die Rolle des Zeilennamens.
Dies kann wie folgt reproduziert werden (fertig zum Kopieren und Einfügen auf der R-Konsole):
dat <- read.csv(url("http://rinterested.github.io/datasets/semiconductors"))
colnames(dat)[2] <- "atomic.no"
dat1 <- subset(dat[1:15,1:3])
row.names(dat1) <- dat1$compounds
dat1 <- dat1[,-1]
Die Daten wurden dann skaliert:
X <- apply(dat1, 2, function(x) (x - mean(x)) / sd(x))
# This centers data points around the mean and standardizes by dividing by SD.
# It is the equivalent to `X <- scale(dat1, center = T, scale = T)`
Die linearen Algebra-Schritte folgten:
C <- cov(X) # Covariance matrix (centered data)
⎡⎣⎢at_nomelt_pat_no10.296melt_p0.2961⎤⎦⎥
Die Korrelationsfunktion cor(dat1)
gibt die gleiche Ausgabe für die nicht skalierten Daten aus wie die Funktion cov(X)
für die skalierten Daten.
lambda <- eigen(C)$values # Eigenvalues
lambda_matrix <- diag(2)*eigen(C)$values # Eigenvalues matrix
⎡⎣⎢λPC11.2964220λPC200.7035783⎤⎦⎥
e_vectors <- eigen(C)$vectors # Eigenvectors
12√⎡⎣⎢PC111PC21−1⎤⎦⎥
Da der erste Eigenvektor anfänglich als zurückgibt , ändern wir ihn in , um ihn mit den eingebauten Formeln in Einklang zu bringen:∼[−0.7,−0.7][0.7,0.7]
e_vectors[,1] = - e_vectors[,1]; colnames(e_vectors) <- c("PC1","PC2")
Die resultierenden Eigenwerte waren und . Unter weniger minimalistischen Bedingungen hätte dieses Ergebnis dazu beigetragen, zu entscheiden, welche Eigenvektoren einbezogen werden sollen (größte Eigenwerte). Zum Beispiel ist der relative Beitrag des ersten Eigenwerts : Dies bedeutet , dass es für Konten der Variabilität in den Daten. Die Variabilität in Richtung des zweiten Eigenvektors beträgt . Dies wird typischerweise in einem Geröllplot gezeigt, das den Wert der Eigenwerte darstellt:1.29642170.703578364.8%eigen(C)$values[1]/sum(eigen(C)$values) * 100
∼65%35.2%
In Anbetracht der geringen Größe dieses Beispiels für einen Spielzeugdatensatz schließen wir beide Eigenvektoren ein, wobei wir verstehen, dass das Ausschließen eines der Eigenvektoren zu einer Verringerung der Dimensionalität führen würde - die Idee hinter PCA.
Die Punktematrix wurde als Matrixmultiplikation der skalierten Daten ( X
) mit der Matrix der Eigenvektoren (oder "Rotationen") bestimmt :
score_matrix <- X %*% e_vectors
# Identical to the often found operation: t(t(e_vectors) %*% t(X))
Das Konzept beinhaltet eine lineare Kombination jedes Eintrags (in diesem Fall Zeile / Subjekt / Beobachtung / Supraleiter) der zentrierten (und in diesem Fall skalierten) Daten, gewichtet mit den Zeilen jedes Eigenvektors , so dass in jeder der letzten Spalten des Punktematrix, wir werden einen Beitrag von jeder Variablen (Spalte) der Daten (der gesamten X
) finden, ABER nur der entsprechende Eigenvektor wird an der Berechnung teilgenommen haben (dh der erste Eigenvektor wird trage zu (Hauptkomponente 1) und zu , wie in: PC[0.7,0.7]T[ 0,7 , - 0,7 ] T PCPC1[0.7,−0.7]TPC2
Daher wird jeder Eigenvektor jede Variable unterschiedlich beeinflussen, und dies wird sich in den "Ladungen" der PCA widerspiegeln. In unserem Fall ändert das negative Vorzeichen in der zweiten Komponente des zweiten Eigenvektors das Vorzeichen der Schmelzpunktwerte in den linearen Kombinationen, die PC2 erzeugen, während der Effekt des ersten Eigenvektors durchgehend positiv ist: [0.7,−0.7]
Die Eigenvektoren sind auf skaliert :1
> apply(e_vectors, 2, function(x) sum(x^2))
PC1 PC2
1 1
wohingegen die ( Ladungen ) die mit den Eigenwerten skalierten Eigenvektoren sind (trotz der verwirrenden Terminologie in den unten gezeigten eingebauten R-Funktionen). Folglich können die Belastungen berechnet werden als:
> e_vectors %*% lambda_matrix
[,1] [,2]
[1,] 0.9167086 0.497505
[2,] 0.9167086 -0.497505
> prcomp(X)$rotation %*% diag(princomp(covmat = C)$sd^2)
[,1] [,2]
atomic.no 0.9167086 0.497505
melting.point 0.9167086 -0.497505
Es ist interessant festzustellen, dass die gedrehte Datenwolke (das Score-Diagramm) entlang jeder Komponente (PC) eine Varianz aufweist, die den Eigenwerten entspricht:
> apply(score_matrix, 2, function(x) var(x))
PC1 PC2
53829.7896 110.8414
> lambda
[1] 53829.7896 110.8414
Mithilfe der integrierten Funktionen können die Ergebnisse repliziert werden:
# For the SCORE MATRIX:
prcomp(X)$x
# or...
princomp(X)$scores # The signs of the PC 1 column will be reversed.
# and for EIGENVECTOR MATRIX:
prcomp(X)$rotation
# or...
princomp(X)$loadings
# and for EIGENVALUES:
prcomp(X)$sdev^2
# or...
princomp(covmat = C)$sd^2
Alternativ kann die Singularwertzerlegungsmethode ( ) angewendet werden, um die PCA manuell zu berechnen. in der Tat ist dies die Methode, die in verwendet wird . Die Schritte können wie folgt geschrieben werden:UΣVTprcomp()
svd_scaled_dat <-svd(scale(dat1))
eigen_vectors <- svd_scaled_dat$v
eigen_values <- (svd_scaled_dat$d/sqrt(nrow(dat1) - 1))^2
scores<-scale(dat1) %*% eigen_vectors
Das Ergebnis ist unten gezeigt, wobei zunächst die Abstände von den einzelnen Punkten zum ersten Eigenvektor und in einer zweiten Auftragung die orthogonalen Abstände zum zweiten Eigenvektor angegeben sind:
Wenn wir stattdessen die Werte der Punktematrix (PC1 und PC2) aufzeichnen würden - nicht mehr "Schmelzpunkt" und "atomic.no", sondern tatsächlich eine Änderung der Basis der Punktkoordinaten mit den Eigenvektoren als Basis, wären diese Abstände erhalten, würde aber natürlich senkrecht zur xy-Achse werden:
Der Trick bestand nun darin , die ursprünglichen Daten wiederherzustellen . Die Punkte wurden durch eine einfache Matrixmultiplikation der Eigenvektoren transformiert. Nun wurden die Daten durch Multiplikation mit der Inversen der Matrix der Eigenvektoren zurückgedreht, was zu einer deutlichen Änderung der Position der Datenpunkte führte. Beachten Sie zum Beispiel die Änderung des rosa Punkts "GaN" im linken oberen Quadranten (schwarzer Kreis im linken Diagramm unten) und kehren Sie in die Ausgangsposition im linken unteren Quadranten (schwarzer Kreis im rechten Diagramm unten) zurück.
Jetzt hatten wir endlich die ursprünglichen Daten in dieser "de-gedreht" Matrix wiederhergestellt:
Über die Änderung der Rotationskoordinaten der Daten in PCA hinaus müssen die Ergebnisse interpretiert werden, und dieser Prozess beinhaltet tendenziell eine biplot
, auf der die Datenpunkte in Bezug auf die neuen Eigenvektorkoordinaten aufgetragen werden und die ursprünglichen Variablen nun als überlagert werden Vektoren. Es ist interessant, die Äquivalenz in der Position der Punkte zwischen den Diagrammen in der zweiten Reihe der obigen Rotationsgraphen ("Scores with xy Axis = Eigenvectors") (links in den folgenden Diagrammen) und dem biplot
(nach dem ) zu beachten richtig):
Die Überlagerung der ursprünglichen Variablen als rote Pfeile bietet einen Weg zur Interpretation PC1
als Vektor in der Richtung (oder mit einer positiven Korrelation) mit beiden atomic no
und melting point
; und von PC2
als Komponente entlang ansteigender Werte von, atomic no
aber negativ korreliert mit melting point
, konsistent mit den Werten der Eigenvektoren:
PCA$rotation
PC1 PC2
atomic.no 0.7071068 0.7071068
melting.point 0.7071068 -0.7071068
Dieses interaktive Tutorial von Victor Powell gibt sofort ein Feedback zu den Änderungen in den Eigenvektoren, wenn die Datenwolke geändert wird.