Numpy矢量化2d数组操作错误

时间:2017-07-12 20:48:44

标签: python arrays numpy vectorization

我正试图在n-row行中的2-d数组上应用矢量化函数,我遇到了ValueError: setting an array element with a sequence.

import numpy as np

X = np.array([[0, 1], [2, 2], [3, 0]], dtype=float)
coeffs = np.array([1, 1], dtype=float)

np.apply_along_axis(
    np.vectorize(lambda row: 1.0 / (1.0 + np.exp(-coeffs.dot(row)))),
    0, X
)

我不完全知道如何解释这个错误。我如何设置一个带序列的数组元素?

当我在一行上测试lambda函数时,它可以工作并返回一个浮点数。不知怎的,它在这个向量化函数的范围内失败了,这让我相信向量化函数是错误的,或者我没有正确使用apply_along_axis

在这种情况下是否可以使用矢量化函数?如果是这样,怎么样?矢量化函数可以采用数组还是我误解了文档?

2 个答案:

答案 0 :(得分:2)

您将X的第二个轴与coeffs的唯一轴相减。因此,您只需将np.dot(X,coeffs)用于sum-reductions

因此,矢量化解决方案将是 -

1.0 / (1.0 + np.exp(-X.dot(coeffs)))

示例运行 -

In [227]: X = np.array([[0, 1], [2, 2], [3, 0]], dtype=float)
     ...: coeffs = np.array([1, 1], dtype=float)
     ...: 

# Using list comprehension    
In [228]: [1.0 / (1.0 + np.exp(-coeffs.dot(x))) for x in X]
Out[228]: [0.7310585786300049, 0.98201379003790845, 0.95257412682243336]

# Using proposed method
In [229]: 1.0 / (1.0 + np.exp(-X.dot(coeffs)))
Out[229]: array([ 0.73105858,  0.98201379,  0.95257413])

使用np.apply_along_axis的正确方法是删除np.vectorize并沿X的第二轴应用它,即X的每一行 -

np.apply_along_axis(lambda row: 1.0 / (1.0 + np.exp(-coeffs.dot(row))), 1,X)

答案 1 :(得分:0)

在v 1.12 vectorize文档中说:

  

默认情况下,pyfunc是       假设将标量作为输入和输出。

在你的尝试中:

np.apply_along_axis(
    np.vectorize(lambda row: 1.0 / (1.0 + np.exp(-coeffs.dot(row)))),
    0, X
)

apply_along_axis遍历除0之外的所有轴,并将生成的1d数组提供给其函数。因此对于2d,它将在1轴上迭代,并且为另一个轴提供。 Divakar显示它在0轴上迭代,并提供行。所以它与使用数组包装器的列表理解基本相同。

apply_along_axis使用3d或更高的输入更有意义,在2轴上迭代并将第三轴输入到您的函数中更为繁琐。

将lambda编写为函数:

def foo(row):
    return 1.0/(1.0+np.exp(-coeffs.dot(row)))

给定一个数组(行),它返回一个标量:

In [768]: foo(X[0,:])
Out[768]: 0.7310585786300049

但是给定一个标量,它返回一个数组:

In [769]: foo(X[0,0])
Out[769]: array([ 0.5,  0.5])

这解释了sequence错误消息。 vectorize期望你的函数返回一个标量,但它有一个数组。

签名

在v 1.12 vectorize中添加了signature参数,这样我们就可以向函数提供大于标量的内容。我在以下方面进行了探讨:

https://stackoverflow.com/a/44752552/901925

使用signature我可以使用vectorize

In [784]: f = np.vectorize(foo, signature='(n)->()')
In [785]: f(X)
Out[785]: array([ 0.73105858,  0.98201379,  0.95257413])

与此相同:

In [787]: np.apply_along_axis(foo,1,X)
Out[787]: array([ 0.73105858,  0.98201379,  0.95257413])

定时

In [788]: timeit np.apply_along_axis(foo,1,X)
10000 loops, best of 3: 80.8 µs per loop
In [789]: timeit f(X)
1000 loops, best of 3: 181 µs per loop
In [790]: np.array([foo(x) for x in X])
Out[790]: array([ 0.73105858,  0.98201379,  0.95257413])
In [791]: timeit np.array([foo(x) for x in X])
10000 loops, best of 3: 22.1 µs per loop

列表理解最快,vectorize最慢。