in graspologic/align/seedless_procrustes.py [0:0]
def fit(self, X: np.ndarray, Y: np.ndarray) -> "SeedlessProcrustes":
"""
Uses the two datasets to learn the matrix `self.Q_` that aligns the
first dataset with the second.
Parameters
----------
X : np.ndarray, shape (n, d)
Dataset to be mapped to ``Y``, must have same number of dimensions
(axis 1) as ``Y``.
Y : np.ndarray, shape (m, d)
Target dataset, must have same number of dimensions (axis 1) as ``X``.
Returns
-------
self : returns an instance of self
"""
X, Y = self._check_datasets(X, Y)
n, d = X.shape
m, _ = Y.shape
if self.init == "2d":
P_matrices = np.zeros((2 ** d, n, m))
Q_matrices = np.zeros((2 ** d, d, d))
objectives = np.zeros(2 ** d)
# try 2^d different initializations
for i in range(2 ** d):
initial_Q = _sign_flip_matrix_from_int(i, d)
P_matrices[i], Q_matrices[i] = P, Q = self._iterative_ot(
X, Y, initial_Q
)
objectives[i] = self._compute_objective(X, Y, Q, P)
# pick the best one, using the objective function value
best = np.argmin(objectives).item()
self.selected_initial_Q_ = _sign_flip_matrix_from_int(best, d)
self.P_, self.Q_ = P_matrices[best], Q_matrices[best]
elif self.init == "sign_flips":
aligner = SignFlips()
self.selected_initial_Q_ = aligner.fit(X, Y).Q_
self.P_, self.Q_ = self._iterative_ot(X, Y, self.selected_initial_Q_)
else:
# determine initial Q if "custom"
if self.initial_Q is not None:
self.selected_initial_Q_ = self.initial_Q
elif self.initial_P is not None:
# use initial P, if provided
self.selected_initial_Q_ = self._procrustes(X, Y, self.initial_P)
else:
# set to initial Q to identity if neither Q nor P provided
self.selected_initial_Q_ = np.eye(d)
self.P_, self.Q_ = self._iterative_ot(X, Y, self.selected_initial_Q_)
self.score_ = self._compute_objective(X, Y)
return self