如何在python numpy中创建随机正交矩阵

如何在python numpy中创建随机正交矩阵,python,numpy,linear-algebra,orthogonal,Python,Numpy,Linear Algebra,Orthogonal,有没有一种方法可以在python中调用以创建随机正交矩阵?可能使用numpy?或者有没有一种方法可以使用多个numpy方法创建正交矩阵?谢谢。scipy的0.18版有和。添加它的拉取请求是 比如说, 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.2

有没有一种方法可以在python中调用以创建随机正交矩阵?可能使用numpy?或者有没有一种方法可以使用多个numpy方法创建正交矩阵?谢谢。

scipy的0.18版有和。添加它的拉取请求是

比如说,

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

这是从中提取的
rvs
方法,只需进行最小的更改即可作为独立的numpy函数运行

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

它与Warren的检验相匹配,

你可以得到一个随机的
nxn
正交矩阵
Q
,(均匀分布在
nxn
正交矩阵的流形上)通过对具有均值
0
和方差
1
的i.i.d.高斯随机变量的
n x n
矩阵执行
QR
因子分解。以下是一个例子:

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))
编辑:(在@g的评论之后再次访问此答案。)上述关于高斯矩阵的QR分解的主张,提供了一个均匀分布(在所谓的斯蒂夫流形上)正交矩阵,由的定理2.3.18-19提出。请注意,结果说明表明存在“类似QR”的分解,但三角形矩阵
R
具有正元素

显然,scipy(numpy)函数的
qr
函数不能保证
R
的正对角元素,而相应的
Q
实际上并不是均匀分布的。这一点已在专论第。4.6(讨论涉及MATLAB,但我猜MATLAB和scipy使用相同的LAPACK例程)。建议将
qr
提供的矩阵
Q
与随机酉对角矩阵相乘,从而对其进行修改

下面我复制了上述参考文献中的实验,绘制了由
qr
提供的“直接”
Q
矩阵以及“修改”版本的特征值相位的经验分布(柱状图),其中可以看出修改后的版本确实具有统一的特征值相位,正如均匀分布的正交矩阵所期望的那样

from scipy.linalg import qr, eigvals
from seaborn import distplot

n = 50
repeats = 10000

angles = []
angles_modified = []
for rp in range(repeats):
    H = np.random.randn(n, n)
    Q, R = qr(H)
    angles.append(np.angle(eigvals(Q)))
    Q_modified = Q @ np.diag(np.exp(1j * np.pi * 2 * np.random.rand(n)))
    angles_modified.append(np.angle(eigvals(Q_modified))) 

fig, ax = plt.subplots(1,2, figsize = (10,3))
distplot(np.asarray(angles).flatten(),kde = False, hist_kws=dict(edgecolor="k", linewidth=2), ax= ax[0])
ax[0].set(xlabel='phase', title='direct')
distplot(np.asarray(angles_modified).flatten(),kde = False, hist_kws=dict(edgecolor="k", linewidth=2), ax= ax[1])
ax[1].set(xlabel='phase', title='modified');

如果您想要一个具有正交列向量的非正方形矩阵,您可以使用上述任何方法创建一个正方形矩阵并删除一些列。

创建任何形状(
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)
注意,如果
n>m
,它将获得
mat.T@mat=eye(m)


Numpy也有qr分解


谢谢你的回复。我注意到给出的答案都是关于方阵的。我还可以用这种方法得到一个dxk矩阵,其中kqr的“直接”应用并不提供均匀分布的正交矩阵。请查看编辑后的答案以了解解决方法。非常好的答案!参考文献是相关的,非常感谢!不需要随机角度,只要使用R的对角线上的符号:
Q_modified=Q@np.diag(np.sign(np.diag(R))
我认为你应该将
rand
更改为
randn
,以获得矩阵的均匀分布。否则,我认为这是最好的答案。
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)
from scipy.stats import special_ortho_group
num_dim=3
x = special_ortho_group.rvs(num_dim)
import numpy as np

a = np.random.rand(3, 3)
q, r = np.linalg.qr(a)

q @ q.T
# array([[ 1.00000000e+00,  8.83206468e-17,  2.69154044e-16],
#        [ 8.83206468e-17,  1.00000000e+00, -1.30466244e-16],
#        [ 2.69154044e-16, -1.30466244e-16,  1.00000000e+00]])