Existe-t-il une méthode que je peux appeler pour créer une matrice orthonormée aléatoire en python? Peut-être en utilisant numpy? Ou existe-t-il un moyen de créer une matrice orthonormale en utilisant plusieurs méthodes numpy? Merci.
Il s'agit de la méthode rvs
extraite de https://github.com/scipy/scipy/pull/5622/files , avec un minimum de modifications, juste assez pour s'exécuter en tant que fonction numpy autonome.
import numpy as np
def rvs(dim=3):
random_state = np.random
H = np.eye(dim)
D = np.ones((dim,))
for n in range(1, dim):
x = random_state.normal(size=(dim-n+1,))
D[n-1] = np.sign(x[0])
x[0] -= D[n-1]*np.sqrt((x*x).sum())
# Householder transformation
Hx = (np.eye(dim-n+1) - 2.*np.outer(x, x)/(x*x).sum())
mat = np.eye(dim)
mat[n-1:, n-1:] = Hx
H = np.dot(H, mat)
# Fix the last sign such that the determinant is 1
D[-1] = (-1)**(1-(dim % 2))*D.prod()
# Equivalent to np.dot(np.diag(D), H) but faster, apparently
H = (D*H.T).T
return H
Il correspond au test de Warren, https://stackoverflow.com/a/38426572/901925
La version 0.18 de scipy a scipy.stats.ortho_group
et scipy.stats.special_ortho_group
. La demande d'extraction à laquelle il a été ajouté est https://github.com/scipy/scipy/pull/5622
Par exemple,
In [24]: from scipy.stats import ortho_group # Requires version 0.18 of scipy
In [25]: m = ortho_group.rvs(dim=3)
In [26]: m
Out[26]:
array([[-0.23939017, 0.58743526, -0.77305379],
[ 0.81921268, -0.30515101, -0.48556508],
[-0.52113619, -0.74953498, -0.40818426]])
In [27]: np.set_printoptions(suppress=True)
In [28]: m.dot(m.T)
Out[28]:
array([[ 1., 0., -0.],
[ 0., 1., 0.],
[-0., 0., 1.]])
Vous pouvez obtenir une matrice orthogonale n x n
aléatoire Q
(uniformément répartie sur la variété de matrices orthogonales n x n
) en effectuant une factorisation QR
d'une matrice n x n
avec des éléments i.i.d. Variables aléatoires gaussiennes de moyenne 0
et de variance 1
. Voici un exemple:
import numpy as np
from scipy.linalg import qr
n = 3
H = np.random.randn(n, n)
Q, R = qr(H)
print (Q.dot(Q.T))
[[ 1.00000000e+00 -2.77555756e-17 2.49800181e-16] [ -2.77555756e-17 1.00000000e+00 -1.38777878e-17] [ 2.49800181e-16 -1.38777878e-17 1.00000000e+00]]
si vous voulez une matrice carrée non carrée avec des vecteurs de colonne orthonormés, vous pouvez en créer une carrée avec l’une des méthodes mentionnées et supprimer certaines colonnes.
Un moyen simple de créer une matrice orthogonale de formes (n x m
):
import numpy as np
n, m = 3, 5
H = np.random.Rand(n, m)
u, s, vh = np.linalg.svd(H, full_matrices=False)
mat = u @ vh
print(mat @ mat.T) # -> eye(n)
Notez que si n > m
, il obtiendrait mat.T @ mat = eye(m)
.