9

numpyvectorize関数は便利ですが、関数の引数がスカラーではなくリストの場合はうまく動作しません。例として:

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 はing しなくても問題なく動作することは理解していvectorizeますが、引数がスカラーではなくリストを取る関数を (一般的に) ベクトル化する方法を知りたいです。

4

2 に答える 2

11

あなたの質問は、ベクトル化された関数からどの出力を見たいかを正確に明確にしませんが、f()のすべての呼び出しに引数として同じリスト(A)を適用したいと思います(つまり、一度X配列の各要素に対して)

関数のベクトル化されたバージョンは、すべての引数が配列であることを確認し、次にnumpyのブロードキャストルールを適用して、これらの引数をどのように組み合わせるかを決定します。

np.arrayによるnp.ndarrayのラッピングと同様に、配列への引数の強制は、リストを含むdtype = objectの配列を作成するのではなく、リストを同じ要素を含む配列に自動的に変換することによって、役立つように試みます。その唯一の要素。ほとんどの場合、これは私たちが望んでいることですが、あなたの場合、この「スマートな」動作が戻ってきてあなたを噛みます。

特定の入力のみをベクトルとして扱うようにnumpyに指示する方法があるかもしれませんが、目的の動作を取得するための2つの簡単な方法があります。

  1. ブロードキャストルール内で機能するように、dtype=objectを使用して配列を手動で作成します
  2. 関数をベクトル化する前に値をカレーします

1. dtype = object

Numpy配列は、1つのタイプのアイテムのみを格納することで効率を引き出しますが、格納されるデータ型を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.カリー化

配列内の各項目の関数呼び出しに同じリストを渡すため、ベクトル化を適用する前にカリー化することで、関数とともにリストを直接保存できます。

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.        ])

PSまた、np.frompyfuncも確認することをお勧めします。これはvectorize()に似ていますが、わずかに低いレベルで機能します。

于 2010-12-21T05:09:27.920 に答える
1

これは、最初の引数として1D配列をとる関数をベクトル化するために現在使用している再帰デコレータの例です。

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に適応させるよりも、これを使用する方が簡単であることがわかりました。vectorizefrompyfunc

于 2012-11-26T10:39:01.313 に答える