def test_principal_angles(seed, m, n): # Set random seed, draw random linear alignment. rs = check_random_state(seed) W = rs.randn(n, n) # Create pair of matrices related by a linear transformation. X = rand_orth(m, n) Y = rand_orth(m, n) # Compute metric based on principal angles. cos_thetas = np.linalg.svd(X.T @ Y, compute_uv=False) dist_1 = np.arccos(np.mean(cos_thetas)) # Fit model, assert two approaches match. metric = LinearMetric(alpha=1.0, center_columns=False).fit(X, Y) assert abs(dist_1 - metric.score(X, Y)) < TOL
def test_rand_orth(seed, m, n): Q = rand_orth(m, n, random_state=seed) if m == n: assert_array_almost_equal(Q.T @ Q, np.eye(n)) assert_array_almost_equal(Q @ Q.T, np.eye(n)) elif m > n: assert_array_almost_equal(Q.T @ Q, np.eye(n)) else: assert_array_almost_equal(Q @ Q.T, np.eye(m))
def test_uncentered_procrustes(seed, m, n): # Set random seed, draw random rotation rs = check_random_state(seed) Q = rand_orth(n, n, random_state=rs) # Create a pair of randomly rotated matrices. X = rs.randn(m, n) Y = X @ Q # Fit model, assert distance == 0. metric = LinearMetric(alpha=1.0, center_columns=False) metric.fit(X, Y) assert abs(metric.score(X, Y)) < TOL
def test_gaussian(seed, n_rep, m, n): rs = check_random_state(seed) X = rs.randn(n_rep, m, n) Y = np.copy(X) @ rand_orth(n) metric = StochasticMetric(max_iter=1000) metric.fit(X, Y) d0 = metric.biased_score(X, Y) assert_allclose( 2 * d0, metric.Xself_ + metric.Yself_, atol=1e-3, rtol=1e-2, )
def test_centered_procrustes(seed, m, n): # Set random seed, draw random rotation, offset, and isotropic scaling. rs = check_random_state(seed) Q = rand_orth(n, n, random_state=rs) v = rs.randn(1, n) c = rs.exponential() # Create a pair of randomly rotated matrices. X = rs.randn(m, n) Y = c * X @ Q + v # Fit model, assert distance == 0. metric = LinearMetric(alpha=1.0, center_columns=True) metric.fit(X, Y) assert abs(metric.score(X, Y)) < TOL
def fit(self, X, y=None): X = self._validate_data(X, accept_sparse='csr') rs = check_random_state(self.random_state) n_features = X.shape[1] nc = self.n_components // 2 self.random_weights_ = np.full((n_features, nc), np.nan) i = 0 while i < nc: Q = rand_orth(n_features, random_state=rs) j = min(nc, i + n_features) self.random_weights_[:, i:j] = Q[:, :(j - i)] i = j self.random_weights_ *= np.sqrt(2 * self.gamma) self.random_weights_ *= np.sqrt(rs.chisquare(n_features, size=(1, nc))) return self