numpy 将方程`A[x,y] = A[x,y] / sqrt(A[x,x] * A[y,y])`矢量化以减少计算时间

yyhrrdl8  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(117)

有一个形状为N x N的对称矩阵A,我想执行A[x, y] = A[x, y] / sqrt(A[x, x] * A[x, y])变换来生成一个新矩阵。目前,下面的代码片段是我的实现。

def gen_new_mat(mat: np.ndarray):
    new_mat = np.copy(mat)
    for i in range(new_mat.shape[0]):
        for j in range(i + 1, new_mat.shape[0]):
            alpha = np.sqrt(new_mat[i, i] * new_mat[j, j])
            new_mat[i, j] /= alpha
            new_mat[j, i] = new_mat[i, j]

    return new_mat

这是正确的。然而,它计算非常慢(当N ≈ 3800时,大约12秒)。
如何通过使用一些为矩阵相关任务设计的库(例如,numpy)来加速此过程?我只能想到这一点,但任何其他方法都非常赞赏。非常感谢你们!!

nhjlsmyf

nhjlsmyf1#

本质上,你需要向量化分母的运算,可以使用:np.multiply.outer(mat.diagonal(), mat.diagonal()
所以函数是:

def gen_new_alpha_np(mat: np.ndarray):
    return mat/ np.sqrt(np.multiply.outer(mat.diagonal(), mat.diagonal()))

注意这里假设你也想对对角线项进行除法运算,如果你不想的话,你需要在最后加上像new_mat.diagonal() = mat.diagonal()这样的东西

时间对比:

我比较了200x200矩阵的两个函数:
1.新增功能:

def test():
    mat = np.random.randint(1, 10, size=(200,200))
    mat = mat.astype(np.float32)
    return mat/ np.sqrt(np.multiply.outer(mat.diagonal(), mat.diagonal()))

 
# timeit statement
print(timeit.timeit("test()", number=1000, globals=globals()))

输出量:

0.5923793000001751

1.旧功能:

def test():
    mat = np.random.randint(1, 10, size=(200,200))
    mat = mat.astype(np.float32)
    new_mat = np.copy(mat)
    for i in range(new_mat.shape[0]):
        for j in range(i + 1, new_mat.shape[0]):
            alpha = np.sqrt(new_mat[i, i] * new_mat[j, j])
            new_mat[i, j] /= alpha
            new_mat[j, i] = new_mat[i, j]

    return new_mat 

 
# timeit statement
print(timeit.timeit("test()", number=1000, globals=globals()))

输出量:

34.02517700000021

正如你所看到的,numpy操作要快得多。

相关问题