Python:计算两个向量列表中每个向量的点积

8

假设我有两个包含向量的列表:

A = [(1,1,1), (0,1,1)]
B = [(1,0,1), (1,0,0)]

我希望能够对每个向量逐元素执行点积,以便输出结果。
C = [2, 0]

我该如何在Python中实现这个功能?

6个回答

19

最快的方法是使用einsum

out = numpy.einsum('ij, ij->i', A, B)

它比乘加版本快2倍;列表推导式版本慢几百倍。

enter image description here


生成绘图的代码:

import numpy
import perfplot

perfplot.show(
    setup=lambda n: (numpy.random.rand(n, 3), numpy.random.rand(n, 3)),
    kernels=[
        lambda data: numpy.einsum("ij, ij->i", data[0], data[1]),
        lambda data: numpy.multiply(data[0], data[1]).sum(1),
        lambda data: [
            sum(ai * bi for ai, bi in zip(a, b)) for a, b in zip(data[0], data[1])
        ],
    ],
    labels=["einsum", "multiply+sum", "sum+zip"],
    n_range=[2 ** k for k in range(18)],
    xlabel="len(a)",
)

这真的很好也很快。我也喜欢它的优雅。谢谢! - Miladiouss

6
在纯Python中,尝试使用嵌套的列表/生成器推导式:
>>> [sum(ai * bi for ai, bi in zip(a, b))
...  for a, b in zip(A, B)]
[2, 0]

或者使用numpy,您可以对二维数组进行逐元素乘积,然后沿每一行求和:

>>> import numpy as np
>>> np.multiply(A, B).sum(1)
array([2, 0])

请注意,若所有向量的长度不同,则 numpy 解决方案将不能正常工作。每个向量列表会被隐式转换为二维矩阵。

1
我们可以使用压缩、求和和列表推导式来实现一个花哨的一行代码:
A = [(1,1,1), (0,1,1)]
B = [(1,0,1), (1,0,0)]
C = [sum(i*j for i, j in zip(a, b)) for a, b in zip(A, B)]
print(C)  # [2, 0]

0

使用numpy.dot

dots_prods = [numpy.dot(a, b) for a,b in zip(list1, list2)]

然而,与@nico-schlömer的einsum方法相比仍然较慢:

enter image description here


0

试试这个:

[sum([y*z for y, z in zip(*x)]) for x in zip(A, B)]

这将产生:

[2, 0]

0
def dot_product(vector_a, vector_b):
    vector_c = (vector_a[0]*vector_b[0],vector_a[1]*vector_b[1],vector_a[2]*vector_b[2]) #vector multiplication
    return sum(vector_c) #sum of each chord in the new vector
c = [dot_product(a[0],a[1]), dot_product(b[0],b[1])]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接