生成随机正交矩阵的一种简单方法是首先对随机矩阵进行采样,然后应用奇异值分解
def random_orthonormal_matrix(n):
random_matrix = np.random.normal(0., 1., (n, n))
u, _, _ = np.linalg.svd(random_matrix)
return u
但是,随着
n
的增加,使用此过程似乎会限制正交矩阵采样的空间。特别是,矩阵似乎越来越不可能从极端的任一端采样,即接近单位矩阵的单位矩阵或负矩阵:
def cosine_similarity(A, B):
norm_A = np.linalg.norm(A)
norm_B = np.linalg.norm(B)
return np.dot(A.flatten(), B.flatten()) / (norm_A * norm_B)
for n in range(4, 33, 4):
similarities = []
I = np.identity(items_n)
for _ in range(100000):
U = random_orthonormal_matrix(n)
similarities.append(cosine_similarity(U, I))
print(np.min(similarities), np.max(similarities))
生成输出
-0.9512750256370359 0.9196429830937393
-0.5402804372155989 0.5641902334710601
-0.33279493103542684 0.3570616519070167
-0.26855564226727774 0.26038092858834694
-0.24803547122804348 0.21364982076125164
-0.18041307918712912 0.18015163443704285
-0.1502303153596804 0.15272379170859116
-0.13915507336472144 0.13962760476513508
如何修改此过程,使得到单位矩阵的预期距离对于任何
n
都是均匀的?更进一步,是否可以直接生成给定距离的随机正交矩阵d
?
Mezzadri 算法已在 SciPy 中实现,详情请参阅 https://docs.scipy.org/doc/scipy/reference/ generated/scipy.stats.ortho_group.html
因此,如果您将 def random_orthonormal_matrix(n) 替换为
from scipy.stats import ortho_group
def random_orthonormal_matrix(n):
return ortho_group.rvs(dim=n)
那么你应该得到你想要的。对于 U(n) 的复数矩阵有 scipy.stats.unitary_group 具有相同/相似的实现