计算numpy中两个矩阵的行之间的角度

时间:2018-06-09 08:02:20

标签: python numpy matrix vector angle

我有两个由3d矢量(numpy 1D数组)组成的矩阵,我需要逐行计算矢量之间的角度,并在1d数组中返回结果。我知道如何计算两个1d向量之间的角度。这样做的正确方法是什么?

***生成的角度以度为单位而不是弧度。

到现在为止我有这个:

import numpy as np

A = np.array([[1,0,0],
              [0,1,0],
              [0,0,1]])

B = np.array([[1,0,1],
              [1,1,0],
              [0,1,0]])

def angle(V1,V2):
    """
    angle between vectors V1 and V2 in degrees using
    angle = arccos ( V1 dot V2 / norm(V1) * norm(V2) ) *180/np.pi
    """

    cos_of_angle = V1.dot(V2) / (np.linalg.norm(V1) * np.linalg.norm(V2)) 
    return np.arccos(np.clip(cos_of_angle,-1,1))  * 180/np.pi

请注意缩放项180 / np.pi,用于从rad到deg的转换。

我想要一个数组:

C = [ angle(A[0],B[0]) , angle(A[1],B[1])...... and so on]

非常感谢有人可以提供帮助。

2 个答案:

答案 0 :(得分:2)

我们可以使用einsum替换点积计算和axis参数替换norm以获得矢量化解决方案,就像这样 -

def angle_rowwise(A, B):
    p1 = np.einsum('ij,ij->i',A,B)
    p2 = np.linalg.norm(A,axis=1)
    p3 = np.linalg.norm(B,axis=1)
    p4 = p1 / (p2*p3)
    return np.arccos(np.clip(p4,-1.0,1.0))

我们可以进一步优化并引入更多einsum,特别是用它来计算norms。因此,我们可以这样使用它 -

def angle_rowwise_v2(A, B):
    p1 = np.einsum('ij,ij->i',A,B)
    p2 = np.einsum('ij,ij->i',A,A)
    p3 = np.einsum('ij,ij->i',B,B)
    p4 = p1 / np.sqrt(p2*p3)
    return np.arccos(np.clip(p4,-1.0,1.0))

因此,要解决我们的案例以获得以度为单位的输出 -

out = angle_rowwise(A, B)*180/np.pi

答案 1 :(得分:1)

如果您正在使用3D矢量工作,你可以做到这一点简洁使用工具区vg。它是numpy之上的一个轻层,并且与单个向量和向量堆栈同样有效。

import numpy as np
import vg

A = np.array([[1,0,0],
              [0,1,0],
              [0,0,1]])

B = np.array([[1,0,1],
              [1,1,0],
              [0,1,0]])

vg.angle(A, B)

我在上次启动时创建了该库,它的使用动机如下:在NumPy中冗长或不透明的简单想法。