Hochdimensionale Daten mit MDS visualisieren

Beginner

This tutorial is from open-source community. Access the source code

Einführung

Multi-dimensionale Skalierung (MDS) ist eine Technik, die verwendet wird, um hochdimensionale Daten in einem niedrigerdimensionalen Raum (gewöhnlich 2D oder 3D) zu visualisieren, während die paarweisen Distanzen zwischen den Datenpunkten möglichst gut beibehalten werden. Sie wird häufig in der explorativen Datenanalyse und Visualisierung eingesetzt.

In diesem Tutorial werden wir die Schritte durchgehen, um MDS auf einem generierten rauschenden Datensatz mit der scikit-learn-Bibliothek in Python durchzuführen.

Tipps für die VM

Nachdem der VM-Start abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu nutzen.

Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund der Einschränkungen in Jupyter Notebook nicht automatisiert werden.

Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.

Bibliotheken importieren

Zunächst müssen wir die erforderlichen Bibliotheken importieren. Wir werden numpy, matplotlib, scikit-learn und PCA aus scikit-learn verwenden.

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
from sklearn import manifold
from sklearn.metrics import euclidean_distances
from sklearn.decomposition import PCA

Daten generieren

Als nächstes werden wir mit numpy einen rauschenden Datensatz generieren. Wir werden 20 Stichproben mit jeweils 2 Merkmalen generieren.

EPSILON = np.finfo(np.float32).eps
n_samples = 20
seed = np.random.RandomState(seed=3)
X_true = seed.randint(0, 20, 2 * n_samples).astype(float)
X_true = X_true.reshape((n_samples, 2))
## Center the data
X_true -= X_true.mean()

Rauschen zu den Daten hinzufügen

Anschließend werden wir mit numpy Rauschen zu den paarweisen Distanzen zwischen den Datenpunkten hinzufügen.

similarities = euclidean_distances(X_true)

## Add noise to the similarities
noise = np.random.rand(n_samples, n_samples)
noise = noise + noise.T
noise[np.arange(noise.shape[0]), np.arange(noise.shape[0])] = 0
similarities += noise

Multi-dimensionale Skalierung (MDS) durchführen

Anschließend werden wir MDS auf dem rauschenden Datensatz mit der MDS-Klasse von scikit-learn durchführen. Wir werden die Option für die vorgeberechnete Ungleichartigkeit verwenden, da wir bereits die paarweisen Distanzen zwischen den Datenpunkten berechnet haben. Wir werden auch die Anzahl der Komponenten auf 2 für die 2D-Visualisierung setzen.

mds = manifold.MDS(
    n_components=2,
    max_iter=3000,
    eps=1e-9,
    random_state=seed,
    dissimilarity="precomputed",
    n_jobs=1,
    normalized_stress="auto",
)
pos = mds.fit(similarities).embedding_

Nicht-metrische Multi-dimensionale Skalierung (Non-Metric MDS) durchführen

Wir werden auch nicht-metrische MDS auf dem gleichen Datensatz durchführen, um einen Vergleich durchzuführen. Wir werden die gleichen Optionen wie bei MDS verwenden, nur dass wir die Option „metric“ auf False setzen.

nmds = manifold.MDS(
    n_components=2,
    metric=False,
    max_iter=3000,
    eps=1e-12,
    dissimilarity="precomputed",
    random_state=seed,
    n_jobs=1,
    n_init=1,
    normalized_stress="auto",
)
npos = nmds.fit_transform(similarities, init=pos)

Daten skalieren und rotieren

Anschließend werden wir die Daten für die Visualisierung skalieren und rotieren, indem wir PCA von scikit-learn verwenden.

## Rescale the data
pos *= np.sqrt((X_true**2).sum()) / np.sqrt((pos**2).sum())
npos *= np.sqrt((X_true**2).sum()) / np.sqrt((npos**2).sum())

## Rotate the data
clf = PCA(n_components=2)
X_true = clf.fit_transform(X_true)
pos = clf.fit_transform(pos)
npos = clf.fit_transform(npos)

Ergebnisse visualisieren

Schließlich werden wir die Ergebnisse mit matplotlib visualisieren. Wir werden die wahre Position der Datenpunkte, die Position der Datenpunkte mit MDS und die Position der Datenpunkte mit nicht-metrischer MDS plotten. Wir werden auch die paarweisen Distanzen zwischen den Datenpunkten mit LineCollection aus matplotlib plotten.

fig = plt.figure(1)
ax = plt.axes([0.0, 0.0, 1.0, 1.0])

s = 100
plt.scatter(X_true[:, 0], X_true[:, 1], color="navy", s=s, lw=0, label="True Position")
plt.scatter(pos[:, 0], pos[:, 1], color="turquoise", s=s, lw=0, label="MDS")
plt.scatter(npos[:, 0], npos[:, 1], color="darkorange", s=s, lw=0, label="NMDS")
plt.legend(scatterpoints=1, loc="best", shadow=False)

similarities = similarities.max() / (similarities + EPSILON) * 100
np.fill_diagonal(similarities, 0)
## Plot the edges
start_idx, end_idx = np.where(pos)
## a sequence of (*line0*, *line1*, *line2*), where::
##            linen = (x0, y0), (x1, y1),... (xm, ym)
segments = [
    [X_true[i, :], X_true[j, :]] for i in range(len(pos)) for j in range(len(pos))
]
values = np.abs(similarities)
lc = LineCollection(
    segments, zorder=0, cmap=plt.cm.Blues, norm=plt.Normalize(0, values.max())
)
lc.set_array(similarities.flatten())
lc.set_linewidths(np.full(len(segments), 0.5))
ax.add_collection(lc)

plt.show()

Zusammenfassung

In diesem Tutorial haben wir gelernt, wie man MDS auf einem rauschenden Datensatz mit scikit-learn in Python durchführt. Wir haben auch gelernt, wie man die Ergebnisse mit matplotlib visualisiert. MDS ist eine nützliche Technik, um hochdimensionale Daten in einem niedriger dimensionalen Raum zu visualisieren, während die paarweisen Distanzen zwischen den Datenpunkten möglichst gut beibehalten werden.