NUMPY 矢量化增维功能



我想创建一个具有input:x.shape==(2,2)和输出y.shape==(2,2,3)的函数。

例如:

@np.vectorize
def foo(x):
#This function doesn't work like I want
return x,x,x
a = np.array([[1,2],[3,4]])
print(foo(a))
#desired output
[[[1 1 1]
[2 2 2]]
[[3 3 3]
[4 4 4]]]
#actual output
(array([[1, 2],
[3, 4]]), array([[1, 2],
[3, 4]]), array([[1, 2],
[3, 4]]))

或者也许:

@np.vectorize
def bar(x):
#This function doesn't work like I want
return np.array([x,2*x,5])
a = np.array([[1,2],[3,4]])
print(bar(a))
#desired output
[[[1 2 5]
[2 4 5]]
[[3 6 5]
[4 8 5]]]

请注意,foo只是一个示例。 我想要一种方法来mapnumpy 数组(这是矢量化应该做的),但map拿一个 0d 对象并将一个 1d 对象推到它的位置。 在我看来,这里的维度是任意的,因为人们可能希望采用一个函数,该函数采用一个 1d 对象并返回一个 3d 对象,对其进行矢量化,在 5d 对象上调用它,然后返回一个 7d 对象......但是,我的具体用例只需要将 0d 矢量化到 1d 函数,并将其适当地映射到 2d 数组。

在您的问题中,显示实际结果和您想要的结果会有所帮助。 正如所写,这不是很清楚。

In [79]: foo(np.array([[1,2],[3,4]]))
Out[79]: 
(array([[1, 2],
[3, 4]]), array([[1, 2],
[3, 4]]), array([[1, 2],
[3, 4]]))

vectorize文档中所述,这返回了一个数组元组,对应于函数返回的值元组。

您的bar返回一个数组,其中vectorize预期返回标量(或单个值):

In [82]: bar(np.array([[1,2],[3,4]]))
ValueError: setting an array element with a sequence.

vectorize采用有时有帮助的otypes参数。 例如,如果我说bar(没有包装器)返回一个对象,我会得到:

In [84]: f=np.vectorize(bar, otypes=[object])
In [85]: f(np.array([[1,2],[3,4]]))
Out[85]: 
array([[array([1, 2, 5]), array([2, 4, 5])],
[array([3, 6, 5]), array([4, 8, 5])]], dtype=object)

(3,) 个数组的 (2,2) 个数组。(2,2)形状与输入的形状匹配。

vectorize有一个相对较新的参数,signature

In [90]: f=np.vectorize(bar, signature='()->(n)')
In [91]: f(np.array([[1,2],[3,4]]))
Out[91]: 
array([[[1, 2, 5],
[2, 4, 5]],
[[3, 6, 5],
[4, 8, 5]]])
In [92]: _.shape
Out[92]: (2, 2, 3)

我没有用过这么多,所以我仍然对它的工作原理有所了解。 当我测试它时,它比vectorize的原始标量版本慢。 两者都不提供显式循环的任何速度优势。 但是,vectorize在"广播"时确实有帮助,允许您使用各种输入形状。 当您的函数接受多个输入(而不是像本例中那样只有一个输入)时,这更有用。

In [94]: f(np.array([1,2]))
Out[94]: 
array([[1, 2, 5],
[2, 4, 5]])
In [95]: f(np.array(3))
Out[95]: array([3, 6, 5])

为了获得最佳速度,您希望尽可能使用现有的 numpy 全数组函数。 例如,您的foo案例可以通过以下方式完成:

In [97]: np.repeat(a[:,:,None],3, axis=2)
Out[97]: 
array([[[1, 1, 1],
[2, 2, 2]],
[[3, 3, 3],
[4, 4, 4]]])

np.stack([a]*3, axis=2)也有效。

以及您bar期望的结果:

In [100]: np.stack([a, 2*a, np.full(a.shape, 5)], axis=2)
Out[100]: 
array([[[1, 2, 5],
[2, 4, 5]],
[[3, 6, 5],
[4, 8, 5]]])

2*a利用了全数组乘法。 这才是真正的"麻木"思维。

只需将值重复到另一个维度就非常简单:

import numpy as np
x = a = np.array([[1,2],[3,4]])
y = np.repeat(x[:,:,np.newaxis], 3, axis=2)
print y.shape
print y

(2L, 2L, 3L)
[[[1 1 1]
[2 2 2]]
[[3 3 3]
[4 4 4]]]

这似乎适用于"f R0 -> R1 映射到一个 nd 数组上,给出一个 (n+1)d">

def foo(x):
return np.concatenate((x,x))
np.apply_along_axis(foo,2,x.reshape(list(x.shape)+[1]))

不过,并不能很好地概括所有内容

最新更新