54

numpy.vectorize関数 f:a->b を受け取り、それを g:a[]->b[] に変換します。

aとがスカラーの場合、これは問題なく動作しますが、b をor リスト、つまり f:a->b[] と g:a[]->b[] でb動作しない理由が思いつきません。 ndarray[]

例えば:

import numpy as np
def f(x):
    return x * np.array([1,1,1,1,1], dtype=np.float32)
g = np.vectorize(f, otypes=[np.ndarray])
a = np.arange(4)
print(g(a))

これにより、次の結果が得られます。

array([[ 0.  0.  0.  0.  0.],
       [ 1.  1.  1.  1.  1.],
       [ 2.  2.  2.  2.  2.],
       [ 3.  3.  3.  3.  3.]], dtype=object)

わかりました、それで正しい値が得られますが、dtype が間違っています。さらに悪いことに:

g(a).shape

収量:

(4,)

したがって、この配列はほとんど役に立ちません。私はそれを変換できることを知っています:

np.array(map(list, a), dtype=np.float32)

私が欲しいものを私に与えるために:

array([[ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 2.,  2.,  2.,  2.,  2.],
       [ 3.,  3.,  3.,  3.,  3.]], dtype=float32)

しかし、それは効率的でもpythonicでもありません。これを行うためのよりクリーンな方法を見つけられる人はいますか?

前もって感謝します!

4

6 に答える 6

61

np.vectorizeは単なる便利な機能です。実際には、コードの実行が速くなるわけではありません。の使用np.vectorizeが不便な場合は、必要に応じて機能する独自の関数を作成してください。

の目的は、np.vectorizenumpy を認識しない関数 (たとえば、float を入力として受け取り、float を出力として返す) を numpy 配列で操作できる (および返す) 関数に変換することです。

あなたの関数fはすでに numpy に対応しています。定義で numpy 配列を使用し、numpy 配列を返します。したがってnp.vectorize、ユースケースには適していません。

したがって、解決策は、希望どおりに機能する独自の関数をロールするfことです。

于 2010-07-31T19:25:37.890 に答える
6
import numpy as np
def f(x):
    return x * np.array([1,1,1,1,1], dtype=np.float32)
g = np.vectorize(f, otypes=[np.ndarray])
a = np.arange(4)
b = g(a)
b = np.array(b.tolist())
print(b)#b.shape = (4,5)
c = np.ones((2,3,4))
d = g(c)
d = np.array(d.tolist())
print(d)#d.shape = (2,3,4,5)

これで問題が解決し、入力のサイズに関係なく機能します。「マップ」は、1 次元の入力に対してのみ機能します。「.tolist()」を使用して新しい ndarray を作成すると、問題がより完全かつ適切に解決されます (私は信じています)。お役に立てれば。

于 2014-07-24T05:07:47.330 に答える
1

私は関数を書きました。それはあなたのニーズに合っているようです。

def amap(func, *args):
    '''array version of build-in map
    amap(function, sequence[, sequence, ...]) -> array
    Examples
    --------
    >>> amap(lambda x: x**2, 1)
    array(1)
    >>> amap(lambda x: x**2, [1, 2])
    array([1, 4])
    >>> amap(lambda x,y: y**2 + x**2, 1, [1, 2])
    array([2, 5])
    >>> amap(lambda x: (x, x), 1)
    array([1, 1])
    >>> amap(lambda x,y: [x**2, y**2], [1,2], [3,4])
    array([[1, 9], [4, 16]])
    '''
    args = np.broadcast(None, *args)
    res = np.array([func(*arg[1:]) for arg in args])
    shape = args.shape + res.shape[1:]
    return res.reshape(shape)

試してみましょう

def f(x):
        return x * np.array([1,1,1,1,1], dtype=np.float32)
amap(f, np.arange(4))

出力

array([[ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 2.,  2.,  2.,  2.,  2.],
       [ 3.,  3.,  3.,  3.,  3.]], dtype=float32)

便宜上、ラムダまたはパーシャルでラップすることもできます

g = lambda x:amap(f, x)
g(np.arange(4))

vectorize言うのdocstringに注意してください

このvectorize関数は、パフォーマンスのためではなく、主に利便性のために提供されています。実装は基本的に for ループです。

amapしたがって、ここでは と同様のパフォーマンスが期待できvectorizeます。私はそれをチェックしませんでした.どんなパフォーマンステストでも大歓迎です.

パフォーマンスが本当に重要な場合は、他の何かを検討する必要があります。たとえば、 と を使用した直接配列計算を使用しreshapebroadcast、純粋な python でループを回避します (vectorizeとの両方amapが後者のケースです)。

于 2016-08-02T01:34:21.060 に答える
0

これを解決する最善の方法は、元の関数への入力として 2 次元の NumPy 配列 (この場合は列配列) を使用することです。これにより、2 次元の出力が生成され、期待どおりの結果が得られます。

コードでは次のようになります。

import numpy as np
def f(x):
    return x*np.array([1, 1, 1, 1, 1], dtype=np.float32)

a = np.arange(4).reshape((4, 1))
b = f(a)
# b is a 2-D array with shape (4, 5)
print(b)

これは、操作を完了するためのはるかに単純でエラーが発生しにくい方法です。このメソッドは、numpy.vectorize で関数を変換しようとするのではなく、配列をブロードキャストする NumPy の自然な機能に依存しています。秘訣は、配列間で少なくとも 1 つの次元の長さが等しいことを確認することです。

于 2016-08-02T01:23:59.863 に答える