【问题标题】:Numpy vectorize, using lists as argumentsNumpy矢量化,使用列表作为参数
【发布时间】:2011-05-28 14:36:46
【问题描述】:

numpy vectorize 函数很有用,但是当函数参数是列表而不是标量时,它的表现不佳。举个例子:

import numpy as np

def f(x, A):
    print "type(A)=%s, A=%s"%(type(A),A)
    return sum(A)/x

X = np.linspace(1,2,10)
P = [1,2,3]

f2 = np.vectorize(f)

f(X,P)
f2(X,P)

给予:

type(A)=<type 'list'>, A=[1, 2, 3]
type(A)=<type 'numpy.int64'>, A=1

Traceback (most recent call last):
  File "vectorize.py", line 14, in <module>
    f2(X,P)
  File "/usr/local/lib/python2.6/dist-packages/numpy/lib/function_base.py", line 1824, in __call__
    theout = self.thefunc(*newargs)
  File "vectorize.py", line 5, in f
    return sum(A)/x
TypeError: 'numpy.int64' object is not iterable

我知道函数 f 可以在没有 vectorizeing 的情况下正常工作,但我想知道如何(通常)矢量化其参数采用列表而不是标量。

【问题讨论】:

    标签: python numpy vectorization


    【解决方案1】:

    这是一个递归装饰器的示例,我目前正在使用它来向量化一个以一维数组作为第一个参数的函数:

    def broadcast(fvec):
        def inner(vec, *args, **kwargs):
            if len(vec.shape) > 1:
                return np.array([inner(row, *args, **kwargs) for row in vec])
            else:
                return fvec(vec, *args, **kwargs)
        return inner
    

    我想它与np.vectorize 的作用几乎相同,但结果证明,使用它比尝试适应vectorize/frompyfunc 更容易。

    【讨论】:

      【解决方案2】:

      您的问题并没有明确说明您希望从矢量化函数中看到什么输出,但我假设您希望将相同的列表 (A) 作为参数应用于每次 f() 调用(即 X 数组中的每个元素一次)

      函数的矢量化版本确保所有参数都是数组,然后应用numpy's broadcasting rules 来确定应如何组合这些参数。

      与 np.array 对 np.ndarray 的包装一样,通过自动将列表转换为包含相同元素的数组,而不是使用 dtype=object 创建包含列表作为其唯一元素。大多数情况下,这正是我们想要的,但在你的情况下,这种“聪明”的行为又回来咬你了。

      虽然可能有一种方法可以指示 numpy 仅将某些输入视为向量,但有两种直接的方法可以获取您所追求的行为:

      1. 手动创建 array with dtype=object 以在广播规则内工作
      2. Curry 函数向量化之前的值

      1. dtype=object

      Numpy 数组的效率源于仅存储一种类型的项目,但它们仍然可以通过指定存储的数据类型为 python 对象来包含任意 python 对象:

      list_obj_array = np.ndarray((1,), dtype=object)
      list_obj_array[0] = [1,2,3]
      f2(X,list_obj_array)  # using your definition from above
      

      打印:

      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      

      然后返回:

      array([ 6.        ,  5.4       ,  4.90909091,  4.5       ,  4.15384615,
              3.85714286,  3.6       ,  3.375     ,  3.17647059,  3.        ])
      

      2。咖喱

      由于您将相同的列表传递给数组中每个项目的函数调用,因此您可以在应用矢量化之前通过currying直接将列表与函数一起存储:

      def curry_f(A):
          def f_curried(x):
              return f(x, A)  # using your definition from above
          return f_curried
      
      f2 = np.vectorize(curry_f(P))
      f2(X)
      

      打印:

      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      type(A)=<type 'list'>, A=[1, 2, 3]
      

      然后返回:

      array([ 6.        ,  5.4       ,  4.90909091,  4.5       ,  4.15384615,
              3.85714286,  3.6       ,  3.375     ,  3.17647059,  3.        ])
      

      附:您可能还希望查看 np.frompyfunc - 它类似于 vectorize(),但工作的级别略低。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-23
        • 2018-03-17
        相关资源
        最近更新 更多