【问题标题】:How can I map functions over arbitrary array dimensions (without using list comprehension)?如何在任意数组维度上映射函数(不使用列表理解)?
【发布时间】:2017-10-11 05:24:48
【问题描述】:

我正在用 numpy 数组做一个小实验,我遇到了以下问题。我正在尝试找到一种方法来映射一个函数,该函数将输入数组作为矩阵的输入,以便该函数应用于两个或多个矩阵的成对元素,其中这些元素是数组。

import numpy as np

x = np.random.random_integers(100, size=(5,4))
y = np.random.random_integers(100, size=(5,4))

print(x); print(y)
[[17 84 60 56]
 [58 71 50 90]
 [80 25 43 55]
 [18 25 77 25]
 [62 49 42 11]]
[[ 9 51 83 58]
 [34 63 26 32]
 [27 54 63 80]
 [29 42 10  6]
 [53 52 45 87]]


# np.dot(x,y) fails

v = np.vectorize(np.dot)
z = v(x,y)

print(z)
[[ 153 4284 4980 3248]
 [1972 4473 1300 2880]
 [2160 1350 2709 4400]
 [ 522 1050  770  150]
 [3286 2548 1890  957]]    # this is wrong

np.sum(z[0]) == np.dot(x[0], y[0])  # prints True
# the vectorized dot function was applied over individual elements at the "bottom-most"
# (second) dimension when instead it should be applied to the array elements
# at the first dimension

# I could instead use list comprehension
z = [np.dot(a, b) for a, b in zip(x,y)]

print(z)
[12665, 10625, 10619, 2492, 8681]    
# this would be a correct mapping of the dot function over the matrices x and y

列表推导式的问题在于我担心它们效率低下,因为它们是 Python 功能而不是 Numpy 功能。

【问题讨论】:

  • vectorize 是 Python 级别的循环;它还将标量提供给您的函数,而不是数组。我知道在不阅读文档的情况下使用它很诱人,但它会为您节省一些错误的开始。

标签: python arrays numpy


【解决方案1】:

您可以将xy 相乘,然后按行求和:

(x * y).sum(1)
# array([12665, 10625, 10619,  2492,  8681])

或者使用numpy.einsum:

np.einsum("ij,ij->i", x, y)
# array([12665, 10625, 10619,  2492,  8681])

【讨论】:

  • 谢谢,我喜欢这个,因为它只使用 numpy 操作,所以我知道它比涉及 python 操作(如列表理解)要快。但是如果我有一些其他的函数想要映射到某个任意维度呢?有没有像矢量化这样的通用方法?
【解决方案2】:

如果函数是任意的,那么你可能必须使用列表推导,或者一些等效的迭代

z = [f(row_x, row_y) for row_x, row_y in zip(x,y)]

其中xy 是(n,m) 数组,z 将是(n,?)

此迭代适用于xy 的第一个维度,将数组视为数组列表。

正如您发现的那样,vectorize 没有做您想做的事,因为它在元素方面起作用,也就是说,它传递标量,而不是行给函数。

正如另一个答案所示,很容易将dot 产品表示为逐行工作的东西。尽可能走这条路。查看计算的组件,并询问哪些组件逐个元素操作,哪些逐行操作,等等。许多基本的数学函数都是这样工作的。但是有些操作只适用于一维数组,例如uniquein1d

在尝试提出适用于任意函数的方法之前,请先了解如何在更简单的情况下使用多维数组。这样你会走得更远。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多