1

データセット間で共有される変数とそうでない変数が必要な複数のデータセットを適合させようとしています。ただし、これを行うために必要な手順がわかりません。以下に、私が使用しようとしているアプローチを示しました (「ここから問題を開始する」からは機能せず、説明目的のためだけです)。

この回答では、誰かがパラメーターを共有することができますarcossデータセットは、共有されていないパラメーターをいくつか持つことができるように、これを適応させる方法はありますか?

どうすればこれを達成できるか、誰かが同じ結果を達成するためのより良いアプローチを提案できますか? ありがとう。

import numpy as np
from scipy.stats import gamma
import matplotlib.pyplot as plt
import pandas as pd
from lmfit import minimize, Minimizer, Parameters, Parameter, report_fit, Model


# Create datasets to fit
a = 1.99
start = gamma.ppf(0.001, a)
stop = gamma.ppf(.99, a)
xvals = np.linspace(start, stop, 100)
yvals = gamma.pdf(xvals, a)
data_dict = {}
for dataset in range(4):
    name = 'dataset_' + str(dataset)
    rand_offset = np.random.uniform(-.1, .1)
    noise = np.random.uniform(-.05, .05,len(yvals)) + rand_offset

    data_dict[name] = yvals + noise
df = pd.DataFrame(data_dict)

# Create some non-shared parameters
non_shared_param1 = np.random.uniform(0.009, .21, 4)
non_shared_param2 = np.random.uniform(0.01, .51, 4)

# Create the independent variable
ind_var = np.linspace(.001,100,100)

# Create a model
def model_func(time, Qi, at, vw, R, rhob_cb, al, NSP1, NSP2):
    Dt = at * vw
    Dl = al * vw

    t = time

    first_bot = 8 * np.pi * t * rhob_cb
    sec_bot = np.sqrt((np.pi * (Dl * R) * t))
    exp_top = R * np.power((NSP1 - ((t * vw)/R)), 2)
    exp_bot = 4 * Dl * t
    exp_top2 = R * np.power(NSP2, 2)
    exp_bot2 = 4 * Dt * t
    return (Qi / first_bot * sec_bot) * np.exp(- (exp_top / exp_bot) - (exp_top2 / exp_bot2))

model = Model(model_func)

### Issues begin here ###

all_results = {}
index = 0
for col in df:
    # This block assigns the correct non-shared parameter for the particular fit
    nsp1 = non_shared_param1[index]
    nsp2 = non_shared_param2[index]
    index += 1

    params = Parameters()
    at = 0.1 
    al = 0.15
    vw = 10**-4
    Dt = at * vw
    Dl = al * vw

    # Non-shared parameters
    model.set_param_hint('NSP1', value = nsp1)
    model.set_param_hint('NSP2', value = nsp2)

    # Shared and varying parameters
    model.set_param_hint('vw', value =10**-4, min=10**-10)
    model.set_param_hint('at', value =0.1)
    model.set_param_hint('al', value =0.15)

    # Shared and fixed parameters
    model.set_param_hint('Qi', value = 1000, vary = True)
    model.set_param_hint('R', value = 1.7, vary = True)
    model.set_param_hint('rhob_cb', value =2895, vary = True)

    # One set of parameters should be returned
    result = model.fit(df[col], time = ind_var)

    all_results[index] = result
4

1 に答える 1

2

lmfit を使用した近似では、常に Parameters オブジェクトの 1 つのインスタンスが使用されます。複数の Parameters オブジェクトは使用されません。

複数のデータ セットを類似のモデル (おそらく同じ数学的モデルであるが、モデルごとに異なるパラメーター値を想定している) で同時に適合させるには、異なるコンポーネント モデルからの残差を連結する目的関数が必要です。そして、これらの各モデルには、Parameters() の単一のインスタンスから取得されたパラメーターが必要であり、各パラメーターには一意の名前が付けられています。

したがって、2 つのデータセットを同じ関数 (パラメーター「center」、「amplitude」、および「sigma」で Gaussian を使用してみましょう) で適合させるには、パラメーターを次のように定義できます。

params =  Parameters()
params.add('center_1',    5., vary=True)
params.add('amplitude_1', 10., vary=True)
params.add('sigma_1',    1.0, vary=True
params.add('center_2',    8., vary=True)
params.add('amplitude_2', 3., vary=True)
params.add('sigma_2',    2.0, vary=True)

次に、「center_1」、「amplitude_1」、および「sigma_1」を使用して最初のデータ セットのモデルを計算し、「center_2」などを使用して 2 番目のモデルを計算します。

def residual(params, x, datasets):
    model1 = params['amplitude_1'] * gaussian(x, params['center_1'], params['sigma_1'])
    model2 = params['amplitude_2'] * gaussian(x, params['center_2'], params['sigma_2']

    resid1 = datasets[0] - model1
    resid2 = datasets[1] - model2
    return np.concatenate((resid1, resid2))

fit = lmfit.minimize(residual, params, fcn_args=(x, datasets))

このことからわかるように、パラメータ値はデフォルトで独立しています。異なるデータセットで使用されるパラメーター値を共有するには、明示的に行う必要があります (提供するリンクされた回答に示されているように)。

たとえば、sigma値が同じであることを要求する場合、残差関数は変更せず、上記のパラメーター定義のみを次のように変更します。

params.add('sigma_2', expr='sigma_1')

2 つの振幅に何らかの値を追加する必要がある場合があります。

params.add('amplitude_2', expr='10 - amplitude_1')

または、'center_2' が 'center_1' よりも大きいことを確認したい場合がありますが、その量はフィットで決定されます。

params.add('center_offset', value=0.5, min=0)
params.add('center_2',  expr='center_1 + center_offset')

これらはすべて、パラメーター値を関連付ける方法です。デフォルトでは、それらは独立しています。もちろん、すべてのモデルで使用されるパラメータをいくつか持つこともできます (たとえば、パラメータ 'sigma' を呼び出して、すべてのモデルで使用します)。

于 2016-11-04T02:32:19.553 に答える