Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 计算两组向量的叉积numpy的有效方法_Python_Numpy - Fatal编程技术网

Python 计算两组向量的叉积numpy的有效方法

Python 计算两组向量的叉积numpy的有效方法,python,numpy,Python,Numpy,我有两组2000个3D向量,每个向量,我需要计算每对向量之间的叉积。我现在是这样做的 for tx in tangents_x: for ty in tangents_y: cross = np.cross(tx, ty) (... do something with the cross variable...) 这是可行的,但速度很慢。有没有办法让它更快 如果我对元素方面的产品感兴趣,我可以做以下几点 # Define initial vector

我有两组2000个3D向量,每个向量,我需要计算每对向量之间的叉积。我现在是这样做的

for tx in tangents_x:
    for ty in tangents_y:
         cross = np.cross(tx, ty)
         (... do something with the cross variable...)
这是可行的,但速度很慢。有没有办法让它更快

如果我对元素方面的产品感兴趣,我可以做以下几点

# Define initial vectors
tx = np.array([np.random.randn(3) for i in range(2000)])
ty = np.array([np.random.randn(3) for i in range(2000)])
# Store them into matrices
X = np.array([tx for i in range(2000)])
Y = np.array([ty for i in range(2000)]).T
# Compute the element-wise product
ew = X * Y
# Use the element_wise product as usual
for i,tx in enumerate(tangents_x):
    for j,ty in enumerate(tangents_y):
        (... use the element wise product of tx and ty as ew[i,j])
如何将其应用于叉积而不是元素积?或者,你有没有看到其他的选择


非常感谢:)

np.dot
几乎总是会更快。所以你可以把一个向量转换成一个向量

在我的机器上,这运行得更快:

tx = np.array([np.random.randn(3) for i in range(100)])
ty = np.array([np.random.randn(3) for i in range(100)])

tt=time.clock()
for x in tx:
    for y in ty:
         cross = np.cross(x, y)
print(time.clock()-tt)
0.207秒 0.015秒
此结果可能因计算机而异。

使用笛卡尔乘积获得所有可能的对

import itertools as it
all_pairs = it.product(tx, ty)
然后使用map在所有对上循环并计算叉积:

map(lambda x: np.cross(x[0], x[1]), all_pairs)

您可以使用
np.meshgrid()
构建组合矩阵,然后分解叉积。其余的人在摆弄轴等:

# build two lists of 5 3D vecotrs as example values:
a_list = np.random.randint(0, 10, (5, 3))
b_list = np.random.randint(0, 10, (5, 3))

# here the original approach using slow list comprehensions:
slow = np.array([[ np.cross(a, b) for a in a_list ] for b in b_list ])

# now the faster proposed version:
g = np.array([ np.meshgrid(a_list[:,i], b_list[:,i]) for i in range(3) ])
fast = np.array([ g[1,0] * g[2,1] - g[2,0] * g[1,1],
                  g[2,0] * g[0,1] - g[0,0] * g[2,1],
                  g[0,0] * g[1,1] - g[1,0] * g[0,1] ]).transpose(1, 2, 0)
我用10000×10000个元素(而不是上面例子中的5×5)测试了这个,用快速版本测试了6.4秒。慢版本已经花费了27秒的时间来处理500个元素

对于您的2000×2000元素,快速版本在我的计算机上需要0.23秒。速度够快吗?

只要把它写出来并编译就行了 性能

#create data
tx = np.random.rand(3000,3)
ty = np.random.rand(3000,3)
#don't measure compilation overhead
comb=calc_cros(tx,ty)

t1=time.time()
comb=calc_cros(tx,ty)
print(time.time()-t1)

This gives 0.08s for the two (3000,3) matrices.

与许多numpy函数一样,
cross
支持广播,因此您可以简单地执行以下操作:

np.cross(tangents_x[:, None, :], tangents_y)
或者-更详细,但可能更容易阅读

np.cross(tangents_x[:, None, :], tangents_y[None, :, :])

这会将
切线x
切线y
重塑为
2000,1,3
1,2000,3
形状。根据广播规则,这将被解释为两个形状数组
2000、2000、3
,其中
切线x
沿轴
1
重复,而
切线y
沿轴
0
重复。嗯,叉积也只是一组乘积,加和减。您可以分解它背后的算法,然后重新构建自己的算法。你考虑过了吗?可能有任何不起作用的代码?这是
交叉积
np.cross
中实现的吗?或者是
np.outer
np.dot
的某个版本?@hpaulj它是np.cross,正如所提供的示例中所示,你不能只做
np.cross(切线x[:,无,:],切线y)
?@PaulPanzer我相信你是对的,原来
np.cross
完全支持广播…这里的慢部分是纯Python的迭代。您需要摆脱这个问题,并将其推到更快的numpy实现中。使用
itertools
仍然需要为每个组合调用
np.cross()
。对于3000×3000个元素,在我的计算机上已经花费了5.4秒。将其与我提供的
meshgrid
解决方案进行比较。它的速度相当快。这真是太棒了!非常感谢:D将在明天接受它,如果没有更快的结果出现,这将返回我要求的矩阵的转置-fast[I,j]给出第I个ty向量和第j个tx向量的叉积,而不是相反。只要有人注意到,没什么大不了的。如果
numba
是一个选择,这真是太棒了:)谢谢你给我介绍广播。我经常想要这个功能,但从来没有发现用隐式的东西来实现它的简单方法。比下面的编译版本更快,而且非常简洁易读!我的选择:)
#create data
tx = np.random.rand(3000,3)
ty = np.random.rand(3000,3)
#don't measure compilation overhead
comb=calc_cros(tx,ty)

t1=time.time()
comb=calc_cros(tx,ty)
print(time.time()-t1)

This gives 0.08s for the two (3000,3) matrices.
np.cross(tangents_x[:, None, :], tangents_y)
np.cross(tangents_x[:, None, :], tangents_y[None, :, :])