numpy 如何从两个单独的列表中为所有可能的向量对生成余弦矩阵?

qyyhg6bp  于 2023-06-23  发布在  其他
关注(0)|答案(2)|浏览(121)

我想在Python中高效地计算一个矩阵,该矩阵包含来自两个单独数组的所有向量对的余弦。它将是形状为(M,N)的矩阵A,而所考虑的向量是2-D [x, y] ndarrays,因此包含它们的阵列的形状为(M,2)(N,2)

u = [u0, ..., uM]
v = [v0, ..., vN]

A = [[cos(u0,v0), cos(u0,v1), ....     ],
    ...
    [...                  .., cos(uM,vN)]]

这是一个非常简单的代码,有一个for循环,但在我的例子中,它被调用了很多次,我希望通过使用向量化的方式来提高我的算法的性能,理想情况下使用numpy数组,但我愿意接受建议。
我尝试通过使用np.meshgrid()创建一个矩阵来实现这个结果,但它给出了二维向量的奇怪结果(形状列表(6,4)而不是(3,2)):

AC_vectors = np.array([[69., 40.],[187.3, 35.], [12., 80]])
AB_vectors = np.array([[22., 150.],[42.5, 20.7]])

np.meshgrid(AB_vectors, AC_vectors)
[array([[ 22. , 150. ,  42.5,  20.7],
       [ 22. , 150. ,  42.5,  20.7],
       [ 22. , 150. ,  42.5,  20.7],
       [ 22. , 150. ,  42.5,  20.7],
       [ 22. , 150. ,  42.5,  20.7],
       [ 22. , 150. ,  42.5,  20.7]]), array([[ 69. ,  69. ,  69. ,  69. ],
       [ 40. ,  40. ,  40. ,  40. ],
       [187.3, 187.3, 187.3, 187.3],
       [ 35. ,  35. ,  35. ,  35. ],
       [ 12. ,  12. ,  12. ,  12. ],
       [ 80. ,  80. ,  80. ,  80. ]])]

而对于对象(因此输入数组是一维数组),它的行为符合预期:

AB_vectors = [Vector(x,y) for x,y in[[22., 150.], [42.5, 20.7]]]
AC_vectors = [Vector(x,y) for x,y in[[69., 40.], [187.3, 35.], [12., 80]]]

np.meshgrid(AB_vectors, AC_vectors)
[array([[Vector(x=22.0, y=150.0), Vector(x=42.5, y=20.7)],
       [Vector(x=22.0, y=150.0), Vector(x=42.5, y=20.7)],
       [Vector(x=22.0, y=150.0), Vector(x=42.5, y=20.7)]], dtype=object), array([[Vector(x=69.0, y=40.0), Vector(x=69.0, y=40.0)],
       [Vector(x=187.3, y=35.0), Vector(x=187.3, y=35.0)],
       [Vector(x=12.0, y=80), Vector(x=12.0, y=80)]], dtype=object)]

我当时希望使用余弦向量化版本的点积和范数来计算矩阵,但我找不到一种有效的方法来绕过meshgrid()来生成[ui,vj]对矩阵。
理想情况下,将存在直接生成矩阵的方法,而无需首先创建所有可能对的矩阵。

3b6akqbq

3b6akqbq1#

如果你想得到向量之间的成对余弦,你可以直接使用公式,而不需要(显式地)生成每一对。计算的成对分量表示为矩阵乘法。

import numpy as np

A = np.array([
    [69., 40.],
    [187.3, 35.], 
    [12., 80]
])
B = np.array([
    [22., 150.],
    [42.5, 20.7]
])

A = A / np.linalg.norm(A, axis=-1)[:, None]
B = B / np.linalg.norm(B, axis=-1)[:, None]

A @ B.T

> array([[0.62176578, 0.99740007],
>       [0.32438716, 0.96416838],
>       [0.99999468, 0.56640008]])

矩阵的(i,j)单元包含第i个向量和第j个向量的余弦相似性。

liwlm1x9

liwlm1x92#

您可以创建索引的网格,然后使用它创建所有组合。从那里,你可以计算点积,并除以范数得到向量之间的Angular 的余弦。

import numpy as np

u = np.array([[69.,40.], [187.3, 35.], [12., 80]])
v = np.array([[22., 150.], [42.5, 20.7]])
norm_u = np.linalg.norm(u, axis=1)
norm_v = np.linalg.norm(v, axis=1)

def mesh_cosine(u, v):
    norm_u = np.linalg.norm(u, axis=1)
    norm_v = np.linalg.norm(v, axis=1)
    
    n = u.shape[0]
    m = v.shape[0]
    U, V = np.meshgrid(np.arange(0, n), np.arange(0, m))
    
    res = np.sum(u[U.ravel()]*v[V.ravel()], axis=1)
    res /= norm_u[U.ravel()]*norm_v[V.ravel()]
    
    return res.reshape(n,m)

print(mesh_cosine(u, v))

相关问题