web-dev-qa-db-ja.com

pythonに多数のパラメーターがある関数のパラメーターを1つだけ当てはめる

pythonには、多くのパラメーターを持つ関数があります。この関数をデータセットに適合させたいのですが、パラメーターを1つだけ使用して、残りのパラメーターは自分で提供します例は次のとおりです。

def func(x,a,b):
   return a*x*x + b

for b in xrange(10):
   popt,pcov = curve_fit(func,x1,x2)

これで私はフィッティングがaに対してのみ行われ、パラメータbがループ変数の値を取ることを望みます。これはどのように行うことができますか?

32
lovespeed

次のように、funcをラムダでラップできます。

def func(x,a,b):
   return a*x*x + b

for b in xrange(10):
   popt,pcov = curve_fit(lambda x, a: func(x, a, b), x1, x2)

ラムダは無名関数であり、Pythonで使用できるのは単純な1行の関数のみです。基本的に、名前を割り当てる必要がない場合に、コードの量を減らすために通常使用されますより詳細な説明は公式ドキュメントに記載されています: http://docs.python.org/tutorial/controlflow.html#lambda-forms

この場合、ラムダを使用してfuncの引数の1つを修正します。新しく作成された関数はxaの2つの引数のみを受け入れますが、bはローカルのb変数から取得した値に固定されます。次に、この新しい関数が引数としてcurve_fitに渡されます。

41

ダイジェストを直感的に理解できない可能性があるラムダ関数を使用する代わりに、カスタム境界内でパラメーターを強制的に検索するscikit curve_fit parameter boundsを指定することをお勧めします。

あなたがしなければならないのは、変数aを-infと+ infの間で移動させ、変数bbetween( b-イプシロン)および(b+イプシロン)

あなたの例では:

epsilon = 0.00001

def func(x,a,b):
    return a*x*x + b

for b in xrange(10):
    popt,pcov = curve_fit(func,x1,x2, bounds=((-np.inf,b-epsilon), (np.inf,b+epsilon))
1
bobo32

Scipyのcurve_fitは、func、xdata、ydataの3つの位置引数を取ります。したがって、(関数ラッパーを使用する)代替のアプローチは、元のxdata(x1)と固定パラメーターbの2番目の列の両方を含む行列を作成することにより、「b」をxdata(つまり、独立変数)として扱うことです。

X1とx2が配列であると仮定します。

def func(xdata,a):
   x, b = xdata[:,0], xdata[:,1]  # Extract your x and b
   return a*x*x + b

for b in xrange(10): 
   xdata = np.zeros((len(x1),2))  # initialize a matrix
   xdata[:,0] = x1  # your original x-data
   xdata[:,1] = b  # your fixed parameter
   popt,pcov = curve_fit(func,xdata,x2)  # x2 is your y-data
0
Arjan Groen

元の関数を編集する意思がある、または編集できる場合は、より簡単なオプションがあります。

関数を次のように再定義します。

def func(x,a):
    return a*x*x + b

次に、パラメーターbのループに単純に配置できます。

for b in xrange(10):
   popt,pcov = curve_fit(func, x1, x2)

注意:関数は、これが機能するために呼び出されるのと同じスクリプトで定義する必要があります。

0
Rick Berg