在Python列表(或numpy数组)上的成对乘积

huangapple go评论63阅读模式
英文:

Pairwise product on a Python List (or numpy array)

问题

我有一个数字列表(浮点数)(列表大小通常大于20,000),需要找到每个数字的两两乘积。例如,如果我有10个数字,我需要一个包含这些45个数字的列表作为输出。在Python中使用嵌套的for循环非常慢。是否有一种方法可以并行化这些计算,考虑到操作是简单的乘积。

import numpy as np

a = np.random.random(100)
c = []
for num in range(0, len(a)):
    for num2 in range(0, len(a)):
        if num2 > num:
            c.append(a[num] * a[num2])

请注意,这是你提供的代码的翻译部分。

英文:

I have a list of numbers (floats) (with the list size typically being greater than 20k) and need to find the pairwise product of each of those. For example if I have 10 numbers, I need an output of 45 numbers in a list with the output being these 45 numbers. A nested for loop in Python is extremely slow. Is there any way for me parallelize these calculations, given that the operation is simple product.

a =np.random.random(100)
c = []
i = 0
for num in range(0,len(a)):
    for num2 in range(0,len(a)):      
        if num2 > num:
            c.append(a[num]*a[num2])

答案1

得分: 1

首先,如果内部循环改为for num2 in range(i+1, len(a)):而不是if检查,执行时间可能会快得多。

个人建议使用以下方法:

import numpy as np

a = np.random.random(100)
c = []

for i in range(1, len(a)):
    c.extend(a[i:] * a[:-i])
    
print(c)

这种方法的乘法方式可以通过以下示例进行说明:

[  1   2   3   4   5  ]   # 初始数组

       1   2   3   4      # 乘以 [2, 3, 4, 5]

           1   2   3      # 乘以 [3, 4, 5]

               1   2      # ...

                   1

初始数组乘以切片array[:-i],对于每个从1开始的i,以匹配维度,我们从位置i开始切片初始数组使用array[i:]

英文:

First of all, your execution time could be much faster if the inner loop was for num2 in range(i+1, len(a)): instead of an if check.

I would personally use this method:

import numpy as np

a = np.random.random(100)
c = []

for i in range(1, len(a)):
    c.extend(a[i:] * a[:-i])
    
print(c)

The way this method multiplies can be show with this example:

[  1   2   3   4   5  ]   # initial array

       1   2   3   4      # multiply by [2, 3, 4, 5]

           1   2   3      # multiply by [3, 4, 5]

               1   2      # ...

                   1

Where the initial array is multiplied by the slice array[:-i] for each i starting at 1. To match the dimensions, we slice the initial array from position i using array[i:].

答案2

得分: 1

访问Numpy数组的值很慢(因为每次访问都会进行C调用,伴随许多内部检查和内部函数子调用)。

加速的方法之一是将Numpy数组转换为列表,但这仍然远非最佳,因为通常使用CPython解释代码。

更快的方法是使用向量化调用,以避免任何循环,仅进行少量Numpy调用。以下是一个完全向量化的方法:

x, y = np.meshgrid(a, a)
product = x * y
mask = np.triu(np.full((a.size, a.size), True), 1)
result = product[mask]

在我的机器上,这比较快(1.33毫秒对比73微秒)。注意,可以在循环中预先计算掩码一次(结果是几乎两倍更快的代码)。

如果这仍然不够快,那么请考虑使用Cython或Numba。请注意,它们还可以帮助减小内存占用,因为无需创建临时矩阵。

英文:

Accessing value of Numpy array is slow (because each access does a C call with many internal checks and internal function sub-calls).

One way to speed this up is to convert the Numpy array to a list, but this is still far from being optimal since the code is generally interpreted using CPython.

A faster approach is to use vectorized calls so to avoid any loops and just do few Numpy calls. Here is a fully vectorized approach:

x, y = np.meshgrid(a, a)
product = x * y
mask = np.triu(np.full((a.size, a.size), True), 1)
result = product[mask]

This is 18 times faster on my machine (1.33 ms VS 73 µs). Note that the mask can be precomputed once in a loop (resulting in a nearly twice faster code).

If this is still not enough, then please consider using Cython or Numba. Note they can also help to reduce the memory footprint since there is no need to create the temporary matrices.

答案3

得分: 1

你可以使用np.outer计算外积(它产生一个方阵),然后使用numpy.triu_indices提取该矩阵的上三角部分的值:

prod = np.outer(a, a)
res = prod[np.triu_indices(a.size, 1)]
英文:

You can compute the outer product with np.outer (which gives a square matrix) and then extract the values by the indices for the upper-triangle of that matrix with numpy.triu_indices:

prod = np.outer(a, a)
res = prod[np.triu_indices(a.size, 1)]

huangapple
  • 本文由 发表于 2023年3月4日 04:24:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75631579.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定