ある25個のデータでz軸に観測結果、x, yで観測値の位置三次元で表現されるものを三次元のガウス関数の積分によってfittingをおこないました。
このプログラムの最小二乗法を行っているoptimeze.leastsqの部分での所要時間が10秒ほどかかっています。ここで、同様の処理を1800回ほど連続して行うため、総処理時間が5時間ほどになってしまいます。
leastsqの引数を変更してみたりしたのですが、あまり変化が見らなかったです(中身を正確に理解しているとは言えないので、方法が悪い可能性はあり)。
よって処理速度の向上を目標としているのですが、良い方法が見つからないため、詳しい方がおりましたらご指摘していただければ幸いです。
修正後のプログラム
python
1import time 2import numpy as np 3from scipy import optimize 4from sympy import * 5 6a = Symbol('a') 7f = 1/sqrt(2)*exp(-(a**2/2)) 8F = integrate(f, a) 9func_gauss = lambdify(a, F) 10 11#二次元ガウスの積分 12def integ_gaussian(param, x_range, y_range): 13 height = param[0] 14 sigma = param[1] 15 cen_x = param[2] 16 cen_y = param[3] 17 constant = param[4] 18 #x_list, y_listに範囲内の不定積分を格納する 19 #積分する回数を減らすことができる 20 x_list = [func_gauss((x-cen_x)/sigma) for x in x_range] 21 y_list = [func_gauss((y-cen_y)/sigma) for y in y_range] 22 #np.diffは前後の差を求める 23 #二次元ガウスの積分値が求まる 24 diff_x = np.diff(x_list) 25 diff_y = np.diff(y_list) 26 #np.meshgridで格子座標を生成し、x, yの二次元ガウスの積分値の掛け算を網羅する 27 mesh_x, mesh_y = np.meshgrid(diff_x, diff_y) 28 np_integ = (height * mesh_x * mesh_y + constant).ravel() 29 return np_integ 30 31#実測値 ― 計算値から最小二乗法を行う 32def residuals_2D(param, z, x_range, y_range): 33 return (z - integ_gaussian(param, x_range, y_range)) 34 35#第1引数はガウス関数のheightで体積を表す。観測データ中心の最も値が高いものの1/3としている 36#第2引数はガウス関数のσでグラフの拡がりを表す。 37#第3引数はガウス関数の中心のx座標 38#第4引数はガウス関数の中心のy座標 39#第5引数はガウス関数のコンスタントで、5×5の観測データの最外のデータ値の平均をとったもの 40param_2D = [3221.33/3, 0.3, 0, 0, 307.30625 41 42#観測データ 43actual_data = [276.67, 336.11, 248.22, 294.89, 290.44, 44 285.33, 438.78, 472.89, 289.33, 416.78, 45 343.0, 2456.44, 3618.44, 308.78, 281.56, 46 279.78, 456.56, 492.89, 273.22, 282.56, 47 272.22, 444.0, 281.89, 269.67, 313.78] 48 49#積分範囲を指定するのに使用 50np_range = np.arange(-2.5, 2.6) 51 52#optimised_param_2Dにfitting結果のパラメータが格納される 53#optimised_param_2Dの所要時間を記録する。 54time_1 = time.time() 55optimised_param_2D = optimize.leastsq(residuals_2D, param_2D, args = (actual_data, np_range, np_range, ftol=1.49012e-1, xtol=1.49012e-1, gtol=1.49012e-1, maxfev=40)) 56time_2 =time.time() 57print(time_2-time_1)
処理時間
time_2 - time_1 = 0.007936954498291016
fitting結果
height:1943.76
sigma:0.31
center_x:-0.41
center_y:0.01
constant:304.71
回答1件
あなたの回答
tips
プレビュー