質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1015閲覧

2つのガウス関数でフィッティングするとき、幅のみを共有パラメータにしたい

noob4

総合スコア21

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/06/17 12:25

やりたいこと
2つのガウス関数の幅のみを共有パラメータとし、データに対してフィッティングしたい。

下記コードは2つのピークを持つ回折データに対して
2つのガウス関数でフィッティングするコードの一部抜粋です。
ピークサーチを用いて2つのピーク位置と高さをそれぞれctrおよびampとしています。
paramsの数で繰り返し回数を決め、ガウス関数の数を指定しています(params=6なら6/3=2回)。
このコードでもある程度良いフィッティング結果が得られていますが、
幅のパラメータ(wid)が独立でフィッティングされるので、
幅のみを2つのガウス関数で共有してフィッティングしたいです。

質問
基本コードは変えずに幅のみを共有パラメータとする方法はありますでしょうか。
もし難しいようであれば、どのようなコードにすれば共有パラメータとしてフィッティングできますでしょうか。

お力添え頂けると幸いです。

python

1 width = 0.04 2 #ピークサーチ 3 peaks, _ = find_peaks(y, height=peak_height, distance=peak_dis) 4 5 ctr1 = x[peaks[0]] 6 amp1 = y[peaks[0]] 7 ctr2 = x[peaks[1]] 8 amp2 = y[peaks[1]] 9 10 def func(x, *params): 11 #paramsの長さでフィッティングする関数の数を判別。 12 num_func = int(len(params)/3) 13 #ガウス関数にそれぞれのパラメータを挿入してy_listに追加。 14 y_list = [] 15 for i in range(num_func): 16 y = np.zeros_like(x) 17 param_range = list(range(3*i,3*(i+1),1)) 18 amp = params[int(param_range[0])] 19 ctr = params[int(param_range[1])] 20 wid = params[int(param_range[2])] 21 y = y + amp * np.exp( -((x - ctr)/wid)**2) 22 y_list.append(y) 23 #y_listに入っているすべてのガウス関数を重ね合わせる。 24 y_sum = np.zeros_like(x) 25 for i in y_list: 26 y_sum = y_sum + i 27 return y_sum 28 29 def fit_plot(x, *params): 30 num_func = int(len(params)/3) 31 y_list = [] 32 for i in range(num_func): 33 y = np.zeros_like(x) 34 param_range = list(range(3*i,3*(i+1),1)) 35 amp = params[int(param_range[0])] 36 ctr = params[int(param_range[1])] 37 wid = params[int(param_range[2])] 38 y = y + amp * np.exp( -((x - ctr)/wid)**2) 39 y_list.append(y) 40 return y_list 41 #初期値のリストを作成 42 guess = [] 43 guess.append([amp1, ctr1, width]) 44 guess.append([amp2, ctr2, width]) 45 46 #初期値リストの結合 47 guess_total = [] 48 for i in guess: 49 guess_total.extend(i) 50 51 popt, pcov = curve_fit(func, x, y, p0=guess_total)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jbpb0

2022/06/18 01:10 編集

> このコードでもある程度良いフィッティング結果が得られています > 幅のみを2つのガウス関数で共有してフィッティングしたい ・「guess_total」を[amp1, ctr1, amp2, ctr2, width]とする ・「def func」内の「for i in range...」のループ内で、「wid」には常に「params」の末尾を代入 とすればいいのではないですかね 「wid」が特別扱いになるので、ペアになるのは「amp」と「ctr」だけになり、「num_func」や「param_range」の計算式も変わりますけど 「def fit_plot」も同様
noob4

2022/06/18 15:46

guess_totalをパラメータ5個にする方向性で解決しました。 パラメータの数で関数の数(ループ回数)を決定する方法では、 それぞれのループの計算が独立になるので、そもそも幅のパラメータを共有することが出来ませんでした。 定義式の段階で2つのガウス関数の足し算にしました(コードとしては少し不格好ですが)。 助言いただいた方法とは異なると思いますが、お陰で解決しました。
guest

回答1

0

自己解決

定義式をガウス関数の足し算にし、パラメータをパラメータの数を減らすことで解決しました。

投稿2022/06/18 15:47

noob4

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問