计算numpy中两个矩阵的行之间的夹角
Calculate the angle between the rows of two matrices in numpy
我有两个由 3d 向量(numpy 一维数组)组成的矩阵,我需要逐行计算向量之间的角度,return 一维数组中的结果。我知道如何计算两个一维向量之间的角度。这样做的正确方法是什么?
*** 生成的角度是度数而不是弧度。
现在我有这个:
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。
我想要一个数组:
C = [ angle(A[0],B[0]) , angle(A[1],B[1])...... and so on]
如果有人能提供帮助,我将不胜感激。
我们可以使用 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
如果您正在使用 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 中冗长或不透明的简单想法。
我有两个由 3d 向量(numpy 一维数组)组成的矩阵,我需要逐行计算向量之间的角度,return 一维数组中的结果。我知道如何计算两个一维向量之间的角度。这样做的正确方法是什么?
*** 生成的角度是度数而不是弧度。
现在我有这个:
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。
我想要一个数组:
C = [ angle(A[0],B[0]) , angle(A[1],B[1])...... and so on]
如果有人能提供帮助,我将不胜感激。
我们可以使用 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
如果您正在使用 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 中冗长或不透明的简单想法。