5 Hauptkomponentenanalyse Ctd.
Im vorherigen Kapitel hatten wir einen zweidimensionalen Datensatz betrachtet und dafür die Richtung bestimmt, in der die Varianz maximal wird. Da wir außerdem ermittelt hatten, dass die Summe der Varianz unabhüngig vom Koordinatensystem ist (es muss nur ein orthogonales sein) bedeutete das gleichzeitig, dass die verbleibende Richtung die Richtung der minimalen Varianz war.
Jetzt wollen wir einen Datensatz mit mehr Merkmalen betrachten und sehen, wie die algorithmische Herangehensweise zum Verständnis beiträgt.
5.1 Der PENGUINS Datensatz
Die Grundlage ist der Pinguin Datensatz, der eine gern genommene Grundlage für die Illustration in der Datenanalyse ist. Die Daten wurden von Kristen Gorman erhoben und beinhalten 4 verschiedene Merkmale (engl. features) von einer Stichprobe von insgesamt 3443Pinguinen die 3 verschiedenen Spezies zugeordnet werden können oder sollen (Fachbegriff hier: targets). Im Beispiel werden die Klassen mit 0, 1, 2
codiert und beschreiben die Unterarten Adele, Gentoo und Chinstrap der Pinguine. Die Merkmale sind gemessene Länge und Höhe des Schnabels (hier bill), die Länge der Flosse (flipper) sowie das Köpergewicht4
(body mass).
Wir stellen uns 2-3 Fragen:
- Würden eventuell 3 (oder sogar nur 2) Dimensionen reichen um den Datensatz zu beschreiben?
- Können wir aus den Merkmalen (features) die Klasse (target) erkennen und wie machen wir gegebenenfalls die Zuordnung?
5.2 Darstellung
In höheren Dimensionen ist schon die graphische Darstellung der Daten ein Problem. Wir können aber alle möglichen 2er Kombinationen der Daten in 2D plots visualisieren.
Ein Blick auf die Diagonale zeigt schon, dass manche Merkmale besser geeignet als andere sind, um die Spezies zu unterscheiden, allerdings keine der Zweierkombinationen eine Eindeutige Diskriminierung erlaubt.
5.3 Korrelationen und die Kovarianzmatrix
Als nächstes suchen wir nach Korrelationen in den Daten in dem wir für alle Merkmalpaare die Korrelationen ausrechnen. Dafür berechnen wir die sogenannte Kovarianzmatrix \[\begin{equation*} \operatorname{Cov}(\mathbf X) = \begin{bmatrix} \rho_{{\mathbf{x} _ i \mathbf{x} _ j}} \end{bmatrix}_{i,j=1,\dots n} \in \mathbb R^{n\times n} \end{equation*}\] wobei \(n\) die Dimension der Daten ist und wobei \[\begin{equation*} s_{{\mathbf{x} _ i \mathbf{x} _ j}} = \frac{1}{N-1} \sum_{k=1}^N (x_{ik}-\overline{{\mathbf{x} _ i}})(x_{jk}-\overline{{\mathbf{x} _ j}} ). \end{equation*}\] die Kovarianzen sind, die wir auch schon in der ersten Vorlesung kennengelernt haben.
Ist \(\mathbf X\in \mathbb R^{N\times n}\) die Matrix mit den Datenvektoren \({\mathbf{x} _ i}\in \mathbb R^{n}\) als Spalten und ist der Datensatz zentriert so erhalten wir die Kovarianzmatrix als \[\begin{equation*} \operatorname{Cov}({\mathbf{X}}) = \frac{1}{N-1}{\mathbf{X}}^T {\mathbf{X}} \end{equation*}\]
Wir bemerken, dass auf der Hauptdiagonalen die Varianzen in Koordinatenrichtung stehen und in den Zeilen oder Spalten ein Mass dafür, wie bspw. \({\mathbf{x} _ i}\) und \({\mathbf{x} _ j}\) korreliert sind. Große Zahlen bedeuten eine große Varianz oder eine starke Korrelation und umgekehrt. Für die Datenanalyse können wir \(\operatorname{Cov}({\mathbf{X}})\) wie folgt heranziehen:
5.4 Hauptachsentransformation
Wie im vorherigen Kapitel hergeleitet, bedeutet ein Koordinatenwechsel die Multiplikation der Datenmatrix \({\mathbf{X}}\in \mathbb R^{N\times n}\) mit einer orthogonalen Matrix \(V\in \mathbb R^{n\times n}\): \[\begin{equation*} \tilde {\mathbf{X}}= {\mathbf{X}}V, \end{equation*}\] wobei \(\tilde {\mathbf{X}}\) die Daten in den neuen Koordinaten sind (die Basisvektoren sind dann die Zeilenvektoren von \(V\)). Wir wollen nun eine Basis finden, in der
- \(\operatorname{Cov}({\mathbf{X}})\) eine Diagonalmatrix ist — damit wären alle Richtungen in den Daten unkorreliert und könnten unabhängig voneinander betrachtet werden5 –
- und in der die neuen Varianzen nach Größe geordnet sind gleichzeitig die verfügbare Varianz maximal in wenigen Richtungen konzentrieren.
Nachden den Überlegungen im vorherigen Kapitel ist die erste Hauptrichtung durch den ersten rechten Singulärvektor \(v_1\in \mathbb R^{n}\) der (ökonomischen) Singulärwertzerlegung \[\begin{equation*} {\mathbf{X}}= U\Sigma V^* = \begin{bmatrix} u_1 & u_2 & \dots & u_n \end{bmatrix} \begin{bmatrix} \sigma_1 \\ &\sigma_2 \\ &&\ddots \\ &&&\sigma_n \end{bmatrix} \begin{bmatrix} v_1^* \\ v_2 ^* \\ \vdots \\ v_n^* \end{bmatrix} \end{equation*}\] von \(\mathbf X\in \mathbb R^{N\times n}\) gegeben. Die zugehörigen Koeffizenten berechnen wir mittels \[\begin{equation*} \tilde {\mathbf{X}}= {\mathbf{X}}v_1. \end{equation*}\]
5.5 Rekonstruktion
Um zu plausibilisieren, dass die weiteren Hauptachsen durch die weiteren (rechten) Singulärvektoren gegeben sind, betrachten wir erst die Rekonstruktion also die Darstellung im Ausgangskoordinatensystem (mit den messbaren oder interpretierbaren Features) die durch \[\begin{equation*} \tilde {\tilde {\mathbf{X}}} = {\mathbf{X}}v_1v_1^T \end{equation*}\] gegeben ist. Die letzte Formel wird vielleicht klarer, wenn Jan sich überlegt, dass für einen Datenpunkt \({\mathbf{X}}_j=\begin{bmatrix} x_{1j} &x_{2j} & \dots& x_{nj}\end{bmatrix}\) (also die \(j\)-te Zeile von \({\mathbf{X}}\)), der Koeffizient für \(v_1\) gegeben ist durch \(\alpha_j=v_1^T{\mathbf{X}}_j^T\) und die Darstellung im Vektorraum durch \[\begin{equation*} \tilde{\tilde{ {\mathbf{X}}}}_j=(\alpha_j v_1)^T = \alpha_j v_1^T = (v_1^T {\mathbf{X}}_j^T) v_1^T = {\mathbf{X}}_j v_1 v_1^T \end{equation*}\] gegeben ist.
Damit können wir mit \[\begin{equation*} {\mathbf{X}}- \tilde{\tilde {{\mathbf{X}}}} = {\mathbf{X}}(I-v_1v_1^T) \end{equation*}\] den Teil der Daten betrachten, der durch die Richtung \(v_1\) nicht abgebildet wird (sozusagen den noch verbleibenden Teil). Jan kann nachrechnen, dass wiederum \(U\) und \(V\) die Singulärvektoren von \({\mathbf{X}}-\tilde{\tilde {{\mathbf{X}}}}\) bilden, mit jetzt \(v_2\) als Richtung mit dem größten (verbleibenden) Singulärwert.
Das heißt, dass der \(k\)-te Singulärvektor die \(k\)-te Hauptrichtung bildet.
5.6 Reduktion der Daten
Ist die Datenmatrix mit linear abhängigen Spalten besetzt, äußert sich das in \(\sigma_k = 0\) für ein \(k<n\) (und alle noch folgenden Singulärwerte). Jan rechnet nach, dass dann \[\begin{equation*} {\mathbf{X}}= {\mathbf{X}}V_{k-1}V_{k-1}^T \end{equation*}\] wobei \(V_{k-1}\) die Matrix der \(k-1\) führenden Singulärvektoren ist und das entsprechende \[\begin{equation*} \tilde {\mathbf{X}}= {\mathbf{X}}V_{k-1} \end{equation*}\] alle Informationen des Datensatzes in kleinerer Dimension parametrisiert.
In der Praxis sind schon allein durch Messfehler exakte lineare Abhängigkeiten sowie durch die näherungsweise Bestimmung auf dem Computer das Auftreten von \(\sigma_k =0\) quasi ausgeschlossen. Stattdessen werden Schwellwerte definiert, unterhalb derer die SVD abgeschnitten wird.
Wie oben, werden dann die Daten \(\tilde {\mathbf{X}}={\mathbf{X}}V_{\hat k}\) in den (reduzierten) Koordinaten der Hauptachsen betrachtet sowie die Rekonstruktion \(\hat {\mathbf{X}}= {\mathbf{X}}V_{\hat k}V_{\hat k}^T\), wobei der \(V_{\hat k}\) die Matrix der \(\hat k\) führenden Singulärvektoren sind (mit Singulärwerten überhalb des Schwellwertes).
5.7 Am Beispiel der Pinguin Daten
Wir stellen die Daten noch einmal zentriert dar:
Für die Kovarianzmatrix der Pinguin Daten erhalten wir:
Covariance matrix: 29.8071 -2.5342 50.3758 2.6056]
[[ -2.5342 3.8998 -16.213 -0.7474]
[ 50.3758 -16.213 197.7318 9.8244]
[ 2.6056 -0.7474 9.8244 0.6431]] [
Für die Singulärwerte:
= np.linalg.svd(data, full_matrices=False)
In: U, S, Vh
print(S)
In: 269.7858 74.1334 28.4183 7.2219] Out: [
Zwar ist hier kein Singulärwert nah an der Null, allerdings beträgt der Unterschied zwischen dem größten und dem kleinsten schon eine gute 10er Potenz, was auf eine starke Dominanz der ersten Hauptachsen hinweist.
In der Tat, plotten wir die Daten in den Koordinaten der Hauptachsen (also \(\tilde {\mathbf{X}}\)), zeigen Bilder der \(v_1\) oder \(v_2\)-Koordinaten klare Tendenzen in den Daten, während die Plots der übrigen Richtungen wie eine zufällige Punktwolke aussieht, vgl. die Abbildung hier.
Als letztes plotten wir noch \(\hat {{\mathbf{X}}}\) für \(\hat k =2\). Das heißt wir reduzieren die Daten auf die \(v_1\) und \(v_2\)-Richtungen und betrachten die Rekonstruktion. Im Plot sehen wir, dass in gewissen Teilen die Daten gut rekonstruiert werden. Allerdings, hat \(\hat{{\mathbf{X}}}\) nur Rang \(\operatorname{Rk} \hat {{\mathbf{X}}}=2\) (warum?), sodass in den Plots notwendigerweise direkte lineare Abhängigkeiten offenbar werden.
5.8 Aufgaben
5.8.1 Kovarianzen (P+T)
Erzeugen Sie für N
aus Nl = [10, 1000, 100000]
zufällige Vektoren x
und y
der Länge N
und berechnen Sie
für den Datensatz X = [x, x, x*y, y]
jeweils die Matrix der Korrelationskoeffizienten
\[\begin{equation*}
\rho _{i\;j} = \frac{s_{i\, j}}{s_i \cdot s_j}
\end{equation*}\]
wobei \(s_{i\,j}\) die Kovarianz der Daten \({\mathbf{x} _ i}\) und \({\mathbf{x} _ j}\) ist und \(s_{i}\) die Varianz von \({\mathbf{x} _ i}\). Interpretieren sie die Ergebnisse.
Hinweis: Weil Zufälligkeit involviert ist, ist die Interpretation manchmal schwierig. Lassen sie das Programm öfter laufen und beobachten sie verschiedene Realisierungen der Stichproben.
import numpy as np
# N = 10
= np.random.randn(10, 1)
x = np.random.randn(10, 1)
y
= np.hstack([x, x, x*y, y])
X
= X - X.mean(axis=0)
Xcntrd # zentrieren der Daten
# Kovarianz Matrix ausrechnen
= 1/(10-1)*Xcntrd.T @ Xcntrd
covX
# Varianzen -- stehen auf der Diagonalen im Quadrat
= np.sqrt(np.diagonal(covX)).reshape(4, 1)
varvec # Matrix mit den Kombinationen aller Varianzen
= varvec @ varvec.T
varmat
= covX * 1/varmat
matcc
print(f'N={10} : Matrix of Correlation Coefficients=')
print(matcc)
5.8.2 Pinguin Datensatz – Targets Plotten (P)
Laden Sie die Pinguin Datensatz (hier als json
file bereitgestellt) und plotten sie bill_length
versus flipper_length
für die drei Spezies Adelie
, Gentoo
, Chinstrap
in drei separaten Grafiken.
import json
import numpy as np
import matplotlib.pyplot as plt
with open('penguin-data.json', 'r') as f:
= json.load(f)
datadict
print(datadict.keys())
= np.array(datadict['data'])
data = np.array(datadict['target'])
target = datadict['feature_names']
feature_names = datadict['target_names']
target_names
print('target names: ', target_names)
print('feature names: ', feature_names)
= plt.subplots(nrows=1, ncols=3, figsize=(10, 3))
fig, axs
# # Ein Vektor der aus dem Target Vektor das target 0 raussucht
= (target == 0)
trgtidx_z # # Wird gleich benutzt um die Daten nach diesem target zu filtern
= data[trgtidx_z, :]
target_z_daten
0].plot(target_z_daten[:, 2], target_z_daten[:, 0],
axs['o', label=target_names[0])
0].legend()
axs[0].set_xlabel(feature_names[3])
axs[0].set_ylabel(feature_names[0])
axs[0].set_title(target_names[0])
axs[
plt.tight_layout() plt.show()
Hier wurden die python
Datentypen
- list – z.B.
datenpunkte = [1, 2, 3]
- array – z.B.
datenmatrix = np.array(datenpunkte)
- dictionary – z.B.
datadict = {'data': datenpunkte}
verwendet, die alle für verschiedene Zwecke gerne benutzt werden. Z.B.
- Liste – als eine Sammlung von (möglicherweise total unterschiedlichen) Objekten, über die iteriert werden kann und die einfach zu erweitern ist
arrays
– Matrix/Vektor von Daten eines Typs, mit denen gerechnet werden kanndictionaries
– ein Lookup table. Objekte können über einen Namen addressiert werden. Ich nehme sie gerne um Daten mit ihrem Namen zum Beispiel alsjson
file zu speichern.
5.8.3 Pinguin Datensatz – 2D plots (P)
Erzeugen sie die Abbildung aller Merkmalpaare zum Beispiel über ein 4x4
Feld von subplots
= plt.subplots(nrows=4, ncols=4, figsize=(10, 8)) fig, axs
erzeugen, in das sie mittels
'o') axs[zeile, spalte].plot(xdaten, ydaten,
die plots fuer die einzelnen targets “eintragen” koennen. Bitte die Achsen beschriften (die legend
ist nicht unbedingt notwendig).
5.8.4 Kovarianz (P)
Zentrieren Sie den Datensatz (zum Beispiel unter Verwendung der numpy.mean
Funktion) und berechnen Sie die Kovarianzmatrix.
5.8.5 Hauptachsentransformation (P)
Berechnen sie Hauptachsen und stellen Sie die Daten in den Hauptachsenkoordinaten dar (wie in dieser Abbildung).
allerdings mit 2 unvollständigen Datenpunkten, die ich entfernt habe für unseere Beispiele↩︎
Im Originaldatensatz ist das Gewicht in Gramm angegeben, um die Daten innerhalb einer 10er Skala zu haben, habe ich das Gewicht auf in kg umgerechnet↩︎
wir dürfen aber nicht vergessen, dass Daten typischerweise nur eine Stichprobe von Beobachtungen eines Phänomens sind. Die Unabhängigkeit in den features gilt also nur für die gesammelten Daten aber in der Regel nicht für das Phänomen. Für normalverteilte Prozesse liefern die daten-basiert ermittelten Hauptrichtungen jedoch auch die Hauptrichtungen des zugrundeliegenden Phänomens↩︎