web-dev-qa-db-fra.com

Comment créer une matrice orthonormée aléatoire en python numpy

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.

13
Dacion

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

10
hpaulj

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.]])
22
Warren Weckesser

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]]
10
Stelios

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.

3
kyuunin

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).

0
Zing Lee