[lmfit] 23. basinhopping法によるフィッティング

lmfit

はじめに

データをガウス関数モデルでカーブフィッティングする際に、basinhopping法を用いた。色々なパラメータを変化させてフィッティングした時のデータをiter_cbを使って取得し、matplotlib FuncAnimationでアニメーションを作成した。これによって、各種パラメータがフィッティングに及ぼす影響を調べた。

コード&解説

モジュールのインポート

バージョン

データの生成

lmfit.lineshapes の gaussianでガウス分布のラインプロファイルを作成する。np.random.random(len(x))/100でノイズも追加する。

モデルとパラメータの設定

GaussianModel()でガウス分布のモデルを作成し、model.make_params()でパラメータを作成する。各パラメータの値をparams[“center”].set(value=3)のようにして設定していく。

xとyとモデルに初期値を適用して得られるデータの関係を図で示すと以下のようになる。

コールバック関数の設定

fittingの試行処理毎に行う処理をこの関数に記述する。ここでは、p_listにパラメータをvaluesdictで辞書形式にして追加していく処理とした。

フィッティングの実行

からのリストを作成し(p_list=[])、model.fit(y, x=x,params=params,iter_cb=per_iteration,method=”basinhopping”,fit_kws=dict(niter=3))でコールバック関数を実行しながらフィッティングを行う。時間短縮のためniter=3としている。print(result.fit_report())でフィッティングの結果を表示できる。

カーブフィット結果の表示

result.best_fitはフィッティング後のデータとなる。図から、うまくフィッティングできていることが分かる。

アニメーション

各パラメータでモデル曲線を再現し、リストに追加していく処理

リストのパラメータを順次取り出していく。取り出したパラメータをモデルのパラメータに適用して、モデル曲線を出力し、リストに追加していく処理を行う。最後に、np.arrayとしておく。

アニメーションの表示

fit_dataをプロットするためにpを設定して、p.set_ydataでモデル曲線を更新していく。アニメーションは以下のようになる。収束した後に再度初期値を設定し直して、フィッティングするベイスンホッピング的な挙動が垣間見れる。

step sizeを変化させた場合

stepsizeは初期値をランダムに変える時の最大ステップサイズとなる。大きいほど初期値の移動量が大きくなる。デフォルト値は0.5で下の動画は3とした時の結果となっている。デフォルトでも最適値を見つけるためにステップサイズを調整するようになっているが、時間がかかる可能性がある。つまり、最適ステップサイズがわかっていれば、フィッティングの高速化ができると思われる。

intervalを変化させた場合

intervalはダメな初期値の時に諦めずに何回反復するかを設定できるパラメータのような気がする。デフォルト値は50で下の動画は10とした時のフィッティングの様子となる。デフォルトの場合よりもポンポンと初期値が移動しているように見える。

niterを変化させた場合

niterは何回のbasinhoppingの反復を行うかを設定できる。デフォルト値は100なので結構時間がかかる。10とした場合は下のようになり、何回もフィッティングを繰り返している様子を把握できる。
fit_reportのfunction evals は 512となっており、最初にniter=3とした時のfunction evals = 216よりも多くの計算を行なっていることが分かる。

コードをダウンロード(.pyファイル)

コードをダウンロード(.ipynbファイル)

参考

doc_model_with_iter_callback.py — Non-Linear Least-Squares Minimization and Curve-Fitting for Python
scipy.optimize.basinhopping — SciPy v1.9.1 Manual
Performing Fits and Analyzing Outputs — Non-Linear Least-Squares Minimization and Curve-Fitting for Python

コメント