具有 3D 向量的两个 numpy 数组的点积
Dot product of two numpy arrays with 3D Vectors
我的目标是找到距离单个点最近的线段(在线段数组中)。
获取 2D 坐标数组之间的点积有效,但使用 3D 坐标会出现以下错误:
*ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 3)*
A = np.array([[1,1,1],[2,2,2]])
B = np.array([[3,3,3], [4,4,4]])
dp = np.dot(A,B)
dp
应该 return 2 个值,
[1,1,1]@[3,3,3]
和 [2,2,2]@[4,4,4]
的点积
// 谢谢大家
这里是找到离单个点最近的线段的最终解决方案。
欢迎任何优化。
import numpy as np
import time
#find closest segment to single point
then = time.time()
#random line segment
l1 = np.random.rand(1000000, 3)*10
l2 = np.random.rand(1000000, 3)*10
#single point
p = np.array([5,5,5]) #only single point
#set to origin
line = l2-l1
pv = p-l1
#length of line squared
len_sq = np.sum(line**2, axis = 1) #len_sq = numpy.einsum("ij,ij->i", line, line)
#dot product of 3D vectors with einsum
dot = np.einsum('ij,ij->i',line,pv) #np.sum(line*pv,axis=1)
#percentage of line the pv vector travels in
param = np.array([dot/len_sq])
#param<0 projected point=l1, param>1 pp=l2
clamped_param = np.clip(param,0,1)
#add line fraction to l1 to get projected point
pp = l1+(clamped_param.T*line)
##distance vector between single point and projected point
pp_p = pp-p
#sort by smallest distance between projected point and l1
index_of_mininum_dist = np.sum(pp_p**2, axis = 1).argmin()
print(index_of_mininum_dist)
print("FINISHED IN: ", time.time()-then)
numpy 的点积显然不是为与数组一起使用而设计的。围绕它编写一些包装器非常容易。例如:
def array_dot(A, B):
return [A[i]@B[i] for i in range(A.shape[0])]
np.dot 仅适用于向量,不适用于矩阵。传递矩阵时,它希望进行矩阵乘法,但由于传递的维数会失败。
在矢量上它会像你预期的那样工作:
np.dot(A[0,:],B[0,:])
np.dot(A[1,:],B[1,:])
一次性完成:
np.sum(A*B,axis=1)
你是这个意思吗:
np.einsum('ij,ij->i',A,B)
输出:
[ 9 24]
但是,如果您想要 A 中的每一行与 B 中的每一行的点积,您应该这样做:
A@B.T
输出:
[[ 9 12]
[18 24]]
In [265]: A = np.array([[1,1,1],[2,2,2]])
...: B = np.array([[3,3,3], [4,4,4]])
按元素乘法后跟求和效果很好:
In [266]: np.sum(A*B, axis=1)
Out[266]: array([ 9, 24])
einsum
也让表达变得简单:
In [267]: np.einsum('ij,ij->i',A,B)
Out[267]: array([ 9, 24])
dot
与 2d 数组(此处为 (2,3) 形),执行矩阵乘法,经典的跨行、向下列。在 einsum
表示法中,这是 'ij,jk->ik'.
In [268]: np.dot(A,B)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-268-189f80e2c351> in <module>
----> 1 np.dot(A,B)
<__array_function__ internals> in dot(*args, **kwargs)
ValueError: shapes (2,3) and (2,3) not aligned: 3 (dim 1) != 2 (dim 0)
使用转置,维度匹配 (2,3) 与 (3,2),但结果是 (2,2):
In [269]: np.dot(A,B.T)
Out[269]:
array([[ 9, 12],
[18, 24]])
所需的值在对角线上。
问题的一种思路是我们要做一批1d的产品。添加 matmul/@
以执行批量矩阵乘法(dot
无法执行)。但是数组必须扩展到 3d,所以 batch 维度是领先的维度(并且 3 在各自的最后一个和第二个到最后一个维度):
In [270]: A[:,None,:]@B[:,:,None] # (2,1,3) with (2,3,1)
Out[270]:
array([[[ 9]],
[[24]]])
但是结果是(2,1,1)形的。正确的数字在那里,但我们必须挤出额外的维度。
总的来说,前 2 个解决方案是最简单的 - 总和或乘积或 einsum
等价物。
我的目标是找到距离单个点最近的线段(在线段数组中)。 获取 2D 坐标数组之间的点积有效,但使用 3D 坐标会出现以下错误:
*ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 3)*
A = np.array([[1,1,1],[2,2,2]])
B = np.array([[3,3,3], [4,4,4]])
dp = np.dot(A,B)
dp
应该 return 2 个值,
[1,1,1]@[3,3,3]
和 [2,2,2]@[4,4,4]
// 谢谢大家
这里是找到离单个点最近的线段的最终解决方案。
欢迎任何优化。
import numpy as np
import time
#find closest segment to single point
then = time.time()
#random line segment
l1 = np.random.rand(1000000, 3)*10
l2 = np.random.rand(1000000, 3)*10
#single point
p = np.array([5,5,5]) #only single point
#set to origin
line = l2-l1
pv = p-l1
#length of line squared
len_sq = np.sum(line**2, axis = 1) #len_sq = numpy.einsum("ij,ij->i", line, line)
#dot product of 3D vectors with einsum
dot = np.einsum('ij,ij->i',line,pv) #np.sum(line*pv,axis=1)
#percentage of line the pv vector travels in
param = np.array([dot/len_sq])
#param<0 projected point=l1, param>1 pp=l2
clamped_param = np.clip(param,0,1)
#add line fraction to l1 to get projected point
pp = l1+(clamped_param.T*line)
##distance vector between single point and projected point
pp_p = pp-p
#sort by smallest distance between projected point and l1
index_of_mininum_dist = np.sum(pp_p**2, axis = 1).argmin()
print(index_of_mininum_dist)
print("FINISHED IN: ", time.time()-then)
numpy 的点积显然不是为与数组一起使用而设计的。围绕它编写一些包装器非常容易。例如:
def array_dot(A, B):
return [A[i]@B[i] for i in range(A.shape[0])]
np.dot 仅适用于向量,不适用于矩阵。传递矩阵时,它希望进行矩阵乘法,但由于传递的维数会失败。
在矢量上它会像你预期的那样工作:
np.dot(A[0,:],B[0,:])
np.dot(A[1,:],B[1,:])
一次性完成:
np.sum(A*B,axis=1)
你是这个意思吗:
np.einsum('ij,ij->i',A,B)
输出:
[ 9 24]
但是,如果您想要 A 中的每一行与 B 中的每一行的点积,您应该这样做:
A@B.T
输出:
[[ 9 12]
[18 24]]
In [265]: A = np.array([[1,1,1],[2,2,2]])
...: B = np.array([[3,3,3], [4,4,4]])
按元素乘法后跟求和效果很好:
In [266]: np.sum(A*B, axis=1)
Out[266]: array([ 9, 24])
einsum
也让表达变得简单:
In [267]: np.einsum('ij,ij->i',A,B)
Out[267]: array([ 9, 24])
dot
与 2d 数组(此处为 (2,3) 形),执行矩阵乘法,经典的跨行、向下列。在 einsum
表示法中,这是 'ij,jk->ik'.
In [268]: np.dot(A,B)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-268-189f80e2c351> in <module>
----> 1 np.dot(A,B)
<__array_function__ internals> in dot(*args, **kwargs)
ValueError: shapes (2,3) and (2,3) not aligned: 3 (dim 1) != 2 (dim 0)
使用转置,维度匹配 (2,3) 与 (3,2),但结果是 (2,2):
In [269]: np.dot(A,B.T)
Out[269]:
array([[ 9, 12],
[18, 24]])
所需的值在对角线上。
问题的一种思路是我们要做一批1d的产品。添加 matmul/@
以执行批量矩阵乘法(dot
无法执行)。但是数组必须扩展到 3d,所以 batch 维度是领先的维度(并且 3 在各自的最后一个和第二个到最后一个维度):
In [270]: A[:,None,:]@B[:,:,None] # (2,1,3) with (2,3,1)
Out[270]:
array([[[ 9]],
[[24]]])
但是结果是(2,1,1)形的。正确的数字在那里,但我们必须挤出额外的维度。
总的来说,前 2 个解决方案是最简单的 - 总和或乘积或 einsum
等价物。