前提・実現したいこと
研究用途として、数値計算のプログラムを作成しています。
解析的には解くことができない偏微分方程式の数値計算の結果として、下の表のように時間ステップt=0, 1, 2,..., iごとの計算結果yのリストが格納されたresult.csv
ファイルが出力されています。
t\x | 0 | 1 | ... | 20 |
---|---|---|---|---|
0 | y[0,0] | y[0,1] | ... | y[0,20] |
1 | y[1,0] | y[1,1] | ... | y[1,20] |
2 | y[2,0] | y[2,1] | ... | y[2,20] |
... | ||||
i | y[i,0] | y[i,1] | ... | y[i,20] |
一方、実データdata.csv
は下記のような形式になっています。
x | 0.00 | 0.74 | 1.08 | ... | 19.39 |
---|---|---|---|---|---|
y | 37 | 24 | 59 | ... | 43 |
この結果から、実データを最も適切に説明する時間tを探索する方法を実装しようとしています。
発生している問題
例えば以下のようにして、時間ステップごとの測定値-数値計算の結果の残差二乗和を計算し、その最小値をmin()
で探せば良いと考えました。
python
1import numpy as np 2import pandas as pd 3 4df_result = pd.read_csv("result.csv", index_col=0).values 5df_data = pd.read_csv("data.csv", index_col=0).iloc[0].values 6list_rsds = [] 7for i in range(df_result.shape[0]): 8 rsd_sum = 0 9 for j in range(len(df_data)): 10 rsd_sq = (df_data[j] - df_result[i, j])**2 11 rsd_sum += rsd_sq 12 list_rsds.append(rsd_sum) 13print(list_rsds.index(min(list_rsds)))
しかし、実データのx座標の値が等間隔ではないため、数値計算の結果と実データのx座標が異なり(定数倍ですらない)、直接残差を計算することができません。
試したこと
「パラメータフィッティング python」等で検索しましたが、フィッティングする関数が予め与えられている場合がヒットしました。
補間やカーブフィッティングなどの最適化
しかし、数値計算の結果のような離散値をどのように扱うべきか分かりませんでした。
解決案として、
- 測定値を線形補間して2点間の直線の式を求め、数値計算のx座標の値を代入->残差を計算する
- 数値計算の値を何らかの多変数関数として表現し、その関数を用いてパラメータフィッティングを行う
~~
といったことを考えているのですが、このような方針がそもそも適切なのか、どのように実装するのが良いのか方針が立っておりません。~~
1で示した方法についてコードを書いてみましたが、もう少しうまいやり方があるような気がするのでアドバイスを頂けると幸いです。
python
1# 直線の式y = a * x + bのa, bを計算してparamsとして出力 2def calc_param(result): 3 dx = 1 / len(result) 4 result_distance = np.linspace(0,1,len(result),endpoint=True) # x座標を0-1に規格化している 5 params = np.zeros([len(result)-1, 2]) 6 for j in range(len(result)-1): 7 a = (result[j+1] - result[j]) / dx 8 b = result[j] - j * dx 9 params[j] = [a,b] 10 return params, result_x 11 12def main(): 13 df_result = pd.read_csv("result.csv", index_col=0).values 14 15 data_value = [37, 24, 59,..., 43] 16 data_x = [0, 0.74, 1.08,..., 19.39] 17 18 # x座標の規格化 19 data_x = data_x / max(data_x) 20 21 # 計算 22 list_reses = [] 23 for i in range(len(df_result)): 24 result = df_result[i] 25 params, result_x = calc_param(result) 26 reses = 0 27 #print(len(result_x)) 28 # 数値計算のx座標を順番に入力 29 for m in range(len(result_x)-1): 30 # 分析値のx座標を順番に入力 31 for n in range(len(data_x)): 32 # もし範囲内にあれば内挿して残差二乗を計算 33 # 末尾は規格化して1なのでresult_x[m+1]==data_x[n] 34 if ( result_x[m] <= data_x[n] < result_x[m+1] ) \ 35 or (result_x[m+1] == data_x[n]): 36 f = params[m,0] * data_x[n] + params[m,1] 37 res = (f - data_value[n]) ** 2 38 reses += res 39 else: 40 pass 41 list_reses.append(reses) 42 print(list_reses.index(min(list_reses))) 43if __name__ == '__main__': 44 main()
補足情報(FW/ツールのバージョンなど)
- OS: Windows 10 Home
- Python 3.8.5
回答3件
あなたの回答
tips
プレビュー