web-dev-qa-db-ja.com

NumPy配列の各行(行ごと)に関数を適用する

だから、私は機能を持っています-

def function(x):
    x , y = vector
    return exp(((-x**2/200))-0.5*(y+0.05*(x**2) - 100*0.05)**2)

そして、次の点で評価したいとしましょう(最初の列はx値で、2番目の列はy値です)-

array([[-1.56113514,  4.51759732],
       [-2.80261623,  5.068371  ],
       [ 0.7792729 ,  6.0169462 ],
       [-1.35672858,  3.52517478],
       [-1.92074891,  5.79966161],
       [-2.79340321,  4.73430001],
       [-2.79655868,  5.05361163],
       [-2.13637747,  5.39255837],
       [ 0.17341809,  3.60918261],
       [-1.22712921,  4.95327158]])

つまり、関数の最初の行に値を渡して評価し、次に2番目の行に渡して評価するなどし、最終結果はこれらのポイントで評価された値の配列になります(つまり、10個の値で構成される配列) 。

そのため、たとえば、関数が2変量正規分布の場合、

def function2(x):

function2 = (mvnorm.pdf(x,[0,0],[[1,0],[0,1]]))

return function2

そして、私はこの関数に上記の値を渡しました、私は得るでしょう-

array([  1.17738907e-05,   1.08383957e-04,   1.69855078e-04,
         5.64757613e-06,   1.37432346e-05,   1.44032800e-04,
         1.33426313e-05,   1.97822328e-06,   6.56121709e-08,
         4.67076770e-05])

だから基本的に、私はそれができるように関数を書き換える方法を探しています。さらに、1つの変数のみの関数(つまり、xの関数のみ)として関数を保持したいと思います。

ご協力ありがとうございました!

11
tattybojangler

np.apply_along_axis

np.apply_along_axis(function, 1, array)

最初の引数は関数、2番目の引数は関数が適用される軸です。あなたの場合、それは最初の軸です。もちろん、最後の引数は配列です。

ただし、apply_along_axisは便利な機能であり、特効薬ではありません。ループを隠すだけなので、速度制限が厳しくなります。可能な場合は、常に計​​算をベクトル化するようにしてください。これを行う方法は次のとおりです。

v = array[:, 0] ** 2   # computing just once  
return np.exp((-v / 200) - 0.5 * (array[:, 1] + 0.05 * v - 5) ** 2)
17
cs95

これを実現する方法はいくつかありますが、変更する必要があるのはxyの割り当てだけです。 x,y = vectorは、vectorの最初の次元の長さが2の場合にのみ機能します。(vector.shape = 2,...)。したがって、次のコマンドのいずれかを使用してベクターを簡単に変更できます。

x,y = vector.T #transpose the array
x,y = vector.swapaxes(0,1) #swap the axis 0 and 1
x,y = np.rollaxis(vector,1) #roll the axis 1 to the front
x,y = vector[:,0], vector[:,1] #slice asignement

あなたが一番好きなものを選ぶだけで、他の方法があるかもしれません(私はほとんど確信していますが、これで十分だと思います)。最後のものは断然最速であり、他のものは同等です。ただし、最後の欠点は、高次元で使用するのがそれほど簡単ではないことです。

2