Graduate Quantitative Economics and Datascience
An SVD for any \(X \in {\mathbb{R}}^{N\times M}\) is:
\[ X = U \Sigma V^{\top} \]
A key result is that we can decompose the data into a sum of outer products of the eigenvectors and singular values. Assume ordered so that \(\sigma_1 \geq \sigma_2 \geq \ldots \geq \sigma_M\) and \(M \leq N\): \[ X = U \Sigma V^{\top} = \sum_{m=1}^M \sigma_m u_m v_m^{\top} \]
Note that
\[ [X X^{\top}]_{ij} = x_i^{\top} x_j \]
\[ X \approx \sum_{m=1}^L \sigma_m u_m v_m^{\top} \]
Create a dataset with two latent factors, the first dominating
N = 50 # number of observations
L, M = 2, 3 # number of latent and observed factors
Z = np.random.randn(N, L) # latent factors
F = np.array([[1.0, 0.05], # X_1 = Z_1 + 0.05 Z_2
[2.0, 0.0], # X_2 = 2 Z_1
[3.0, 0.1]]) # X_3 = 3 Z_1 + 0.1 Z_2
X = Z @ F.T + 0.1 * np.random.randn(N, M) # added noise
print(f"Z is {Z.shape}, X is {X.shape}")Z is (50, 2), X is (50, 3)
Singular Values (sqrt eigenvalues):
[23.4967 0.7801 0.6799]
Explained Variance (ordered):
[0.9981 0.0011 0.0008]
pca = PCA(n_components=2) # one less, and correctly specified
Z_hat = pca.fit_transform(X) # transformed by dropping last factor
# Scale and sign may not match due to indeterminacy
print(f"Correlation of Z_1 to Z_hat_1 = {np.corrcoef(Z.T, Z_hat.T)[0,2]}")
print(f"Correlation of Z_2 to Z_hat_2 = {np.corrcoef(Z.T, Z_hat.T)[1,3]}")Correlation of Z_1 to Z_hat_1 = 0.9991782640019669
Correlation of Z_2 to Z_hat_2 = -0.4829688858606044
\[ g(f(x; \theta_e); \theta_d) \approx x \]
If we had a distribution for \(x\) then can solve
\[ \min_{\theta_e, \theta_d} {\mathbb{E}}||g(f(x; \theta_e); \theta_d) - x||_2^2 \]
But typically in practice we replace expectation with empirical distribution \(\{x_1,\ldots x_N\}\)
\[ \min_{\theta_e, \theta_d} \frac{1}{N} \sum_{n=1}^N ||g(f(x_n; \theta_e); \theta_d) - x_n||_2^2 \]
\[ \min_{W} \frac{1}{N} \sum_{n=1}^N ||W \overbrace{W^{\top} x_n}^{z_n = f(x_n;W)} - x_n||_2^2,\quad \text{with } W^{\top} W = I \]
Formally,
\[ \min_{\mathbf{S}} \sum_{k=1}^K \frac{1}{2|S_k|}\sum_{x_n, x_{n'} \in S_k} ||x_n - x_{n'}||_2^2 \]
Using standard Euclidean norm between two elements in \(S_k\) \[ ||x_n - x_{n'}||_2^2 = \sum_{m=1}^M (x_{nm} - x_{n'm})^2 \]
Can prove that the previous objective is equivalent to minimizing the sum of the squared distances from the group \(k\)’s mean
\[ \min_{\mathbf{S}} \sum_{k=1}^K \sum_{n \in S_k} ||x_n - \bar{x}_k||_2^2 \]
Where the mean of group \(k\) is standard, and across all \(m\) features
\[ \bar{x}_k \equiv \frac{1}{|S_k|}\sum_{x_n \in S_k} x_n \]
Avoid different scales so \(\bar{x}_k\) isn’t dominated by one feature
mu_1 = np.array([0.0, 0.0]) # mean of k=1
mu_2 = np.array([1.0, 1.0]) # mean of k=2
sigma = np.array([[0.2, 0], [0, 0.2]]) # use same variance
N = 100 # observations
X_1 = np.random.multivariate_normal(mu_1, sigma, N)
X_2 = np.random.multivariate_normal(mu_2, sigma, N)
df_1 = pd.DataFrame({"f1": X_1[:, 0], "f2": X_1[:, 1], "k": 1})
df_2 = pd.DataFrame({"f1": X_2[:, 0], "f2": X_2[:, 1], "k": 2})
df = pd.concat([df_1, df_2], ignore_index=True)Label ordering is arbitrary, so the confusion matrix might require reordering to compare
Correlation now 0.8904007705404129
Use Economics, and don’t rely on technical tools alone
In the previous lecture we introduced code for simulation
A = np.array([[0.6619469, 0.49646018],[0.5840708, 0.4380531]])
G = np.array([[10.0, 4.0]])
d_0 = np.array([1.0, 1.0])
T, beta = 10, 0.9
p_0 = G @ solve(np.eye(2) - beta * A, d_0)
d = simulate(A, d_0, T)
y = G @ d # total dividends from portfolio
print(f"Portfolio value at t=0 is {p_0[0]:.5g}, total dividends at time {T} is {y[0,T]:.5g}")Portfolio value at t=0 is 1424.5, total dividends at time 10 is 36.955

If we stack columns \(Q \equiv \begin{bmatrix} q_1 & q_2 \end{bmatrix}\) and let \(\tilde{q}_1\) be the first row of \(Q^{-1}\) then, \[ A = Q \Lambda Q^{-1} = Q \begin{bmatrix} \lambda_1 & 0 \\ 0 & 0 \end{bmatrix} Q^{-1} = \lambda_1 q_1 \tilde{q}_1 \]
norm = 2.349441087662224e-10
Let’s see if these line up perfectly
