1import numpy as np
2from matplotlib import pyplot as plt
3import seaborn as sns
4from misc import draw_samples, draw_cov_ellipses
5
6
7def map_samples(samples, alpha):
8 """
9 **TODO**
10 Assume you have a normal distributed random variable :math:`\\boldsymbol{X}`
11 with mean
12
13 .. math::
14 \mu = (1.5 ,0.5)
15
16 and covariance
17
18 .. math::
19 \Sigma = \\begin{pmatrix}0.7&-0.4\\\\-0.4&1.4\\end{pmatrix}
20
21 Assume further that :math:`\\boldsymbol{Y}` is another random variable with
22
23 .. math::
24 \\boldsymbol{Y} = A\cdot \\boldsymbol{X}
25
26 and
27
28 .. math::
29 A = \\begin{pmatrix}\cos(\\alpha)&-\sin(\\alpha)\\\\\sin(\\alpha)&\cos(\\alpha)\\end{pmatrix}
30
31 The samples parameter holds 512 samples of this random variable.
32
33 Apply the linear mapping to the samples and calculate the **exact** new mean and covariance of
34 :math:`\\boldsymbol{Y}`, namely
35
36 .. math::
37 E[\\boldsymbol{Y}] = E[A\cdot\\boldsymbol{X}] = A\cdot\\boldsymbol{\mu}
38
39 .. math::
40 Cov[\\boldsymbol{Y}] = Cov[A\cdot\\boldsymbol{X}] = A\cdot Cov[\\boldsymbol{X}] \cdot A^T
41
42 Return the mapped samples as well as the
43 *exact* mean and covariance of the mapped random variable.
44 **Do not** estimate the mean and covariance from the mapped samples.
45
46 :param samples: (np.array 2x512) 512 Samples from :math:`\\boldsymbol{X}`
47 :param alpha: Parameter :math:`\\alpha` of the Matrix :math:`A` (see above)
48 :return: 3-tuple (mapped_samples, mapped_mu, mapped_cov)
49 """
50 # TODO: Calculate Matrix A
51 s, c = np.sin(alpha), np.cos(alpha)
52
53 A = np.array([[c, s], [-s, c]])
54
55 # TODO: Map the samples and calculate the exact mean and covariance of the Y
56 mu = np.array([1.5, 0.5])
57 cov = np.array([[0.7, -0.4], [-0.4, 1.4]])
58
59 mapped_samples = A @ samples
60 mapped_mu = A @ mu.reshape(-1, 1)
61 mapped_cov = A @ cov @ A.T
62
63 # TODO: Return your mapped samples, the mapped mean and the mapped covariance
64 return mapped_samples, mapped_mu, mapped_cov
65
66
67# ---------------------------------------------------
68# There is no need to change anything below this line
69# ---------------------------------------------------
70
71# Generate 512 samples of a multivariate normal random variable (Shape 2 x 512)
72# Do not change
73samples = np.random.multivariate_normal(
74 mean=np.array([1.5, 0.5]), cov=np.array([[0.7, -0.4], [-0.4, 1.4]]), size=512
75).T
76
77# Main Program
78if __name__ == "__main__":
79 # Set Seaborn display style
80 sns.set_style("whitegrid")
81
82 # Create figure for plots
83 fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(8, 8))
84
85 # Iterate different radians for plotting (0 to 2pi)
86 for radians in np.linspace(0.0, 2.0 * np.pi, 360):
87 # Clear all axes
88 for a in ax:
89 a.clear()
90
91 # Generate mapped samples
92 mapped_samples, mapped_mu, mapped_cov = map_samples(samples, radians)
93
94 # Estimate mu and covariance from original samples as well as mapped samples
95 mu = np.mean(samples, axis=1)
96 cov = np.cov(samples)
97
98 estimated_mu = np.mean(mapped_samples, axis=1)
99 estimated_cov = np.cov(mapped_samples)
100
101 # Draw original sample point cloud as well as mapped samples point cloud
102 draw_samples(samples, ax[0])
103 draw_samples(mapped_samples, ax[1])
104
105 # Draw covariance ellipses
106 draw_cov_ellipses(
107 mu, cov, ax[0], edgecolor="lightblue", facecolor="none", linewidth=2
108 )
109 draw_cov_ellipses(
110 estimated_mu,
111 estimated_cov,
112 ax[1],
113 edgecolor="lightblue",
114 facecolor="none",
115 linewidth=2,
116 )
117 draw_cov_ellipses(
118 mapped_mu,
119 mapped_cov,
120 ax[1],
121 edgecolor="#1f77b4",
122 facecolor="none",
123 linewidth=2,
124 )
125
126 # Apply styling to plot
127 for cnt in [0, 1]:
128 if cnt == 0:
129 ax[cnt].set_title("Linear Mapping - Original Data")
130 else:
131 ax[cnt].set_title("Linear Mapping - Wrapped Grid")
132
133 ax[cnt].set_xlabel("x0")
134 ax[cnt].set_ylabel("x1")
135 ax[cnt].set_xlim(-6.0, 6.0)
136 ax[cnt].set_ylim(-6.0, 6.0)
137 ax[cnt].set_aspect("equal")
138
139 # Wait shortly for animation to roll
140 plt.pause(0.01)