首页 > 解决方案 > 使用从对应于数组轴的一组向量生成的产品递增多维 numpy 数组(python)

问题描述

A 是 ak 维 numpy 浮点数组(k 可能非常大,例如最多 10 个)

我需要通过增加每个值来实现对 A 的更新(如下所述)。我想知道是否有一种 numpy 风格的方式会很快。

L_i长度为axis i

该数组的更新通过以下两个步骤生成:

  1. 对于 A 的每个轴,生成一个对应的向量 G。例如,对应于轴 ia 生成长度为 L_i 的向量 G_i(从数据)。

  2. 通过计算 A 中每个位置的 G 向量的增量来更新所有位置的 A

要在任何特定位置执行此操作,设 p 是 k 个索引的数组,对应于 A 中的一个位置。然后 p 处的 A 增加一个计算为乘积的值:

Product(G_i[p[i]], for i from 0 to k-1)

对 A 的完全更新涉及对 A 中的所有位置(即 p 的所有可能值)执行此操作

这个操作通过循环一个一个地做位置会很慢。

有没有一种快速的 numpy 风格的方法来做到这一点?

编辑

##  this for three dimensions, final matrix at pos i,j,k has the 
## product of c[i]*b[j]*a[k]
## but for arbitrary # of dimensions it will have a loop in a loop 
## and will be slow
import numpy as np

a = np.array([1,2])
b = np.array([3,4,5])
c = np.array([6,7,8,9])

ab = []
for bval in b:
    ab.append(bval*a)
ab = np.stack(ab)

abc = []
for cval in c:
    abc.append(cval*ab)
abc = np.stack(abc)

作为一个函数

def loopfunc(arraylist):
    ndim = len(arraylist)
    m = arraylist[0]
    for i in range(1,ndim):
        ml = []
        for val in arraylist[i]:
            ml.append(val*m)
        m = np.stack(ml)
    return m

标签: pythonnumpy

解决方案


这是一个古怪的问题,但我喜欢它。

如果我从您的示例中了解您需要什么,您可以通过一些重塑技巧和 NumPy 的常用广播规则来完成此操作。这个想法是重塑每个数组,使其具有正确的维数,然后直接相乘。

这是一个实现这一点的函数。

from functools import reduce
import operator
import numpy as np
import scipy.linalg

def wacky_outer_product(*arrays):
    assert len(arrays) >= 2
    assert all(arr.ndim == 1 for arr in arrays)
    ndim = len(arrays)
    shapes = scipy.linalg.toeplitz((-1,) + (1,) * (ndim - 1))
    reshaped = (arr.reshape(new_shape) for arr, new_shape in zip(arrays, shapes))
    return reduce(operator.mul, reshaped).T

在您的示例数组上进行测试,我们有:

>>> foo = wacky_outer_product(a, b, c)
>>> np.all(foo, abc)
True

编辑

好的,上面的功能很有趣,但下面的功能可能要好得多。没有转置,更清晰,小:

from functools import reduce
import operator
import numpy as np

def wacky_outer_product(*arrays):
    return reduce(operator.mul, np.ix_(*reversed(arrays)))

推荐阅读