【发布时间】:2021-11-22 06:37:47
【问题描述】:
根据cmets,我修改了例子:
考虑下面的代码
import numpy as np
def subspace_angle(A, B):
M = A.T @ B
s = np.linalg.svd(M, compute_uv=False)
return s[0]
def principal_angles(bases):
k = bases.shape[0]
r = np.zeros((k, k))
for i in range(k):
x = bases[i]
r[i, i] = subspace_angle(x, x)
for j in range(i):
y = bases[j]
r[i, j] = subspace_angle(x, y)
r[j, i] = r[i, j]
r = np.minimum(1, r)
return np.rad2deg(np.arccos(r))
以下是使用示例:
bases = []
# number of subspaces
k = 5
# ambient dimension
n = 8
# subspace dimension
m = 4
for i in range(5):
X = np.random.randn(n, m)
Q,R = np.linalg.qr(X)
bases.append(Q)
# combine the orthonormal bases for all the subspaces
bases = np.array(bases)
# Compute the smallest principal angles between each pair of subspaces.
print(np.round(principal_angles(bases), 2))
有没有办法避免principal_angles函数中的两级for循环,从而加快代码速度?
由于此代码,矩阵 r 是对称的。由于 subspace_angle 的计算量可能很大,具体取决于数组大小,因此请务必避免为 r[i,j] 和 r[j,i] 计算两次。
关于 JIT 的评论,实际上,我正在使用 Google/JAX 编写代码。两级循环确实可以编译 JIT,从而带来性能优势。但是,JIT 编译时间相当长(可能是由于两级 for 循环)。我想知道是否有更好的方法来编写此代码,以便它可以更快地编译。
【问题讨论】:
-
重要的问题是,你将在 func 中执行什么样的计算?可以矢量化吗?
-
这将是一些基于 NumPy 的计算。是的,应该可以对其进行矢量化。我想到的特定函数是 A,B,计算 M = A.T @ B,然后返回 M 的最大奇异值。我想可以向量化。我在上面的代码中保留了一个二维数组。但我的实际用例是一个矩阵数组。
-
在我看来,我正在寻找某种方法来形成 n(n-1)/2 对 A 的行,在每对上运行 func,然后将结果重新格式化为三角矩阵,然后最后以某种方式对称三角矩阵。想知道这样的机制是否存在。
-
请提供一个更好的例子(输入和预期输出)
-
需要澄清的一点:python 定义的函数,包括那些调用 numpy 例程的函数,不能单独由 numpy 向量化。函数 func 将由 CPython 以每个元素的方式运行。 Numpy 无法即时编译。您可以使用 Numba numba.pydata.org 实现显着的加速 - 这是 Python/Numpy 的 JIT - 如果您愿意,也可以使用 Cython。
标签: python performance numpy vectorization