| from __future__ import annotations |
|
|
| import numpy as np |
|
|
| from .spectrum import sample_covariance, symmetric_matrix_sqrt |
|
|
|
|
| def sample_covariance_sqrt_shrinkage( |
| eigenvalues: np.ndarray, n_samples: int, trials: int, seed: int |
| ) -> np.ndarray: |
| """Estimate E[u_i^T sample_cov^{1/2} u_i] in the population eigenbasis.""" |
| eig = np.asarray(eigenvalues, dtype=np.float64) |
| rng = np.random.default_rng(seed) |
| accum = np.zeros_like(eig) |
| for _ in range(trials): |
| cov = sample_covariance(eig, n_samples, rng) |
| sqrt_cov = symmetric_matrix_sqrt(cov) |
| accum += np.diag(sqrt_cov) |
| return accum / float(trials) |
|
|
|
|
| def _cross_split_mse(eigenvalues: np.ndarray, n_samples: int, trials: int, rng: np.random.Generator) -> float: |
| eig = np.asarray(eigenvalues, dtype=np.float64) |
| mses = [] |
| for _ in range(trials): |
| seed_vector = rng.standard_normal(eig.size) |
| left = symmetric_matrix_sqrt(sample_covariance(eig, n_samples, rng)) @ seed_vector |
| right = symmetric_matrix_sqrt(sample_covariance(eig, n_samples, rng)) @ seed_vector |
| mses.append(float(np.mean((left - right) ** 2))) |
| return float(np.mean(mses)) |
|
|
|
|
| def sampling_map_cross_split_variance( |
| eigenvalues: np.ndarray, n_samples: int, trials: int, seed: int |
| ) -> dict[str, float]: |
| rng = np.random.default_rng(seed) |
| base = _cross_split_mse(eigenvalues, n_samples, trials, rng) |
| larger = _cross_split_mse(eigenvalues, n_samples * 4, trials, rng) |
| return { |
| "cross_split_mse": base, |
| "larger_n_cross_split_mse": larger, |
| "n_samples": float(n_samples), |
| "larger_n_samples": float(n_samples * 4), |
| } |
|
|