Mahalanobisdistanz - Musterlösung

 1import numpy as np
 2import matplotlib.pyplot as plt
 3
 4# Beispielhafte Parameter der Verteilung
 5mu = np.array([2.0, 3.0])  # Erwartungswert
 6Sigma = np.array([[2.0, 1.2], 
 7                  [1.2, 1.0]])  # Kovarianzmatrix (nicht-diagonal, d.h. korrelierte Größen)
 8
 9
10def plot_covariance_ellipse(mu, Sigma, ax, n_std=1.0, **kwargs):
11    """
12    **TODO**:
13    Zeichnen Sie eine Kovarianzellipse (z. B. 1-, 2- oder 3-Sigma) um den Mittelwert einer 2D-Normalverteilung.
14    Verwenden Sie das übergebene `axes <https://matplotlib.org/stable/api/axes_api.html>`_ Objekt zum zeichnen.
15
16    Parameter:
17    ----------
18    mu : np.ndarray
19        2D-Vektor mit dem Mittelwert (Schwerpunkt) der Ellipse.
20
21    Sigma : np.ndarray
22        2x2-Kovarianzmatrix der Verteilung.
23
24    ax : matplotlib.axes.Axes
25        Achse, in die die Ellipse gezeichnet werden soll.
26
27    n_std : float
28        Skalierungsfaktor für die Ellipsenweite (z. B. 1 = 1-Sigma, 2 = 2-Sigma, ...).
29
30    **kwargs :
31        Zusätzliche Parameter für `ax.plot`, z. B. Farbe oder Linienstil.
32    """
33    # TODO: Generieren Sie 100 Punkte auf dem Einheitskreis
34    # Verwenden Sie np.linspace um 100 verschiedene Winkel zwischen 0 und 2pi zu bekommen.
35    # Wenden Sie dann np.cos und np.sin an und verwenden Sie anschließend np.stack
36    # um daraus ein (2, N) Array zu erzeugen. 
37    theta = np.linspace(0, 2 * np.pi, 100)
38    circle = np.stack((np.cos(theta), np.sin(theta)))  # Shape: (2, N)
39
40    # TODO: Bestimmen Sie die Cholesky-Zerlegung der Kovarianzmatrix Sigma
41    # L @ L.T
42    L = np.linalg.cholesky(Sigma)
43
44    # TODO: Transformieren Sie den Einheitskreises in eine entsprechende Ellipse
45    # Multiplizieren Sie mit n_std um die Ellipse zu skalieren. 
46    # Stellen Sie sicher das die Ellipse um den Mittelwert mu zentriert ist.
47    ellipse = mu.reshape(2, 1) + n_std * L @ circle
48
49    # Zeichnen Sie die Ellipse in das übergebene ax Objekt.
50    # Übergeben Sie die zusätzlichen Parameter in kwargs um das Aussehen der Ellipse
51    # beim Aufruf der Methode steuern zu können.
52    ax.plot(ellipse[0], ellipse[1], **kwargs)
53
54# ---------------------------------------------------
55# There is no need to change anything below this line
56# ---------------------------------------------------
57
58if __name__ == "__main__":
59  # Stichprobe generieren
60  samples = np.random.multivariate_normal(mu, Sigma, size=500)
61
62
63  # Plot vorbereiten
64  fig, ax = plt.subplots(figsize=(6, 6))
65  ax.set_aspect('equal')
66  ax.grid(True)
67
68  # Datenpunkte darstellen
69  ax.scatter(samples[:, 0], samples[:, 1], s=10, alpha=0.3, label="Samples")
70
71  # Erwartungswert markieren
72  ax.plot(mu[0], mu[1], 'ro', label="Mittelwert")
73
74  # Kovarianzellipse zeichnen
75  plot_covariance_ellipse(mu, Sigma, ax, n_std=1.0, color='#FF0000', label="1-Sigma-Ellipse")
76  plot_covariance_ellipse(mu, Sigma, ax, n_std=2.0, color='#CF0000', label="2-Sigma-Ellipse")
77  plot_covariance_ellipse(mu, Sigma, ax, n_std=3.0, color='#800000', label="3-Sigma-Ellipse")
78
79  # Achsen und Legende
80  ax.set_xlabel("x")
81  ax.set_ylabel("y")
82  ax.legend()
83  plt.title("2D-Normalverteilung mit Kovarianzellipse")
84  plt.show()