python - Numpy,通过迭代替换广播

标签 python numpy generator broadcast

我有以下代码片段

def norm(x1, x2):
    return np.sqrt(((x1 - x2)**2).sum(axis=0))

def call_norm(x1, x2):
    x1 = x1[..., :, np.newaxis]
    x2 = x2[..., np.newaxis, :]
    return norm(x1, x2)

据我了解,每个x代表N维空间中的点数组,其中N是数组最终维度的大小(因此对于3维空间中的点,最终维度尺寸为 3)。它插入额外的维度并使用广播生成这些点集的笛卡尔积,从而计算所有点对之间的距离。

x = np.array([[1, 2, 3],[1, 2, 3]])
call_norm(x, x)
array([[ 0.        ,  1.41421356,  2.82842712],
       [ 1.41421356,  0.        ,  1.41421356],
       [ 2.82842712,  1.41421356,  0.        ]])

(因此,[1,1][2,2] 之间的距离为 1.41421356,如预期)

我发现对于中等大小的问题,这种方法可能会使用大量内存。我可以轻松地“去向量化”问题并通过迭代替换它,但我预计这会很慢。我有一个(相当)简单的折衷解决方案,我可以在其中获得矢量化的大部分速度优势,但不会造成内存损失?一些奇特的生成器技巧?

最佳答案

使用 numpy 矢量化时,没有办法在没有内存损失的情况下进行这种计算。对于有效计算成对距离矩阵的特定情况,包往往通过在 C 中(例如 scipy.spatial.distance )或 Cython (例如 sklearn.metrics.pairwise )中实现来解决这个问题。

如果您想“手动”执行此操作,可以说,使用 numpy 样式语法但不会造成内存损失,当前最好的选择可能是 dask.array ,它使用 numpy 风格的语法自动构建和执行灵活的任务图以进行批量执行。

以下是使用 dask 进行此计算的示例:

import dask.array as da

# Create the chunked data. This can be created
# from numpy arrays as well, e.g. x_dask = da.array(x_numpy)
x = da.random.random((100, 3), chunks=5)
y = da.random.random((200, 3), chunks=5)

# Compute the task graph (syntax just like numpy!)
diffs = x[:, None, :] - y[None, :, :]
dist = da.sqrt((diffs ** 2).sum(-1))

# Execute the task graph
result = dist.compute()
print(result.shape)
# (100, 200)

您会发现 dask 比 NumPy 的内存效率更高,通常比 NumPy 的计算效率更高,并且还可以相对直接地并行/核外计算。

关于python - Numpy,通过迭代替换广播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33762175/

相关文章:

python - 如何在 django 中重定向时发送字典或数据?

arrays - Python 数组附加向量,然后按位置(而不是按元素)对数组的元素求和

Python 产量(从 Ruby 迁移): How can I write a function without arguments and only with yield to do prints?

python - 使用像素数组设置 opencv 图像/numpy 数组值

python - 在 python 中抛出 GeneratorExit 和调用 close() 之间的区别

c++ - 非重复随机数发生器

python - raise StopIteration 和生成器中的 return 语句有什么区别?

python - 尝试存储神经网络时获取 'can' t pickle _thread.RLock 对象

Python:循环遍历不同目录中的文件并扫描数据

python - 有没有办法使用矢量化来操作 3D 数组和 1D 数组?