Pythonによる累乗近似
出川智啓
非線形関数の近似
2019/03/23オープンCAE第68回勉強会@岐阜2
 PythonでExcelの累乗近似(Power Approximation)
を再現したい
 Excelの累乗近似はPower Approx.ではないらしい
 オープンCAE第63回勉強会@岐阜
 非線形データの近似曲線作成
 井口豊,Excelグラフ累乗,指数,多項式近似の論文記載の
注意(accessed at 13th Mar. 2019)
 が,私はExcelの累乗近似を再現したい
Pythonによる非線形関数の近似
2019/03/23オープンCAE第68回勉強会@岐阜3
 scipy.optimizeのcurve_fit
 与えられたデータの組と関数形から,最もよく近似するパラ
メータを返す
 f:モデル関数.y=f(x, parameter1,parameter2,...)
 x:独立変数
 y:f(x)で記述できる(と期待される)従属変数
 opt:fのパラメータparameter1,...の最適値
 cov:共分散
from scipy.optimize import curve_fit
opt, cov = curve__fit(f, x, y)
Pythonによる非線形関数の近似
2019/03/23オープンCAE第68回勉強会@岐阜4
def nonlinear_fit(x, a, b, c):
return b*x**a + c
%matplotlib inline
import numpy as np
from scipy.optimize import curve_fit
from matplotlib import pyplot as plt
#井口氏の値
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.array([6, 12, 27, 50, 75, 108, 149, 198, 249, 303])
p_opt,cov = curve_fit(nonlinear_fit,x,y)
p_opt
array([ 2.01749389, 2.92169046, 1.17462894])
Pythonによる非線形関数の近似
2019/03/23オープンCAE第68回勉強会@岐阜5
fig,ax = plt.subplots()
ax.plot(x,y,lw=0,marker='o',clip_on=False)
ax.plot(x,y_fit(x,p_opt[0],p_opt[1],p_opt[2]),lw=1)
plt.show()
y_fit = np.vectorize(nonlinear_fit)
Excelの累乗近似
2019/03/23オープンCAE第68回勉強会@岐阜6
 どうやら変数変換してから線形近似しているらしい
 非線形関数𝑦 = 𝑏𝑥 𝑎の両辺の対数をとる
 log 𝑦 = 𝑎 log 𝑥 + log 𝑏 ⇒ 𝑌 = 𝑎𝑎 + 𝐵
 対数を取った式を基に最小2乗法で近似
Pythonによる累乗近似の再現
2019/03/23オープンCAE第68回勉強会@岐阜7
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.array([6, 12, 27, 50, 75, 108, 149, 198, 249, 303])
p_opt2,cov = curve_fit(loglog_fit,x,y)
p_opt2
array([ 1.79238713, 4.45246989])
def loglog_fit(x, a, b,):
return a*x + np.log(b)
Pythonによる非線形関数の近似
2019/03/23オープンCAE第68回勉強会@岐阜8
fig,ax = plt.subplots()
ax.plot(x,y,lw=0,marker='o',clip_on=False)
ax.plot(x,p_opt2[1]*x**p_opt2[0],lw=1)
plt.show()
Excelの累乗近似
2019/03/23オープンCAE第68回勉強会@岐阜9
 データを選択して右クリック→近似曲線の追加→累乗近似
y = 4.4525x1.7924
0
50
100
150
200
250
300
350
0 2 4 6 8 10
なぜ累乗近似を再現したいのか?
2019/03/23オープンCAE第68回勉強会@岐阜10
 非線形関数でフィッティングした方がよい結果が出る
 独立変数(𝑥)の範囲が狭い場合は真
 変数変換した方がよい場合もある
 数値計算における誤差の収束性
 cos 𝑥 =
𝑑
𝑑𝑑
sin 𝑥 ≈
sin 𝑥+Δ𝑥 −sin 𝑥−Δ𝑥
2Δ𝑥
 Δ𝑥 = 10 𝑛, −7 ≤ 𝑛 ≤ 1
 𝜀 = cos 𝑥 −
sin 𝑥+Δ𝑥 −sin 𝑥−Δ𝑥
2Δ𝑥
誤差の収束性
2019/03/23オープンCAE第68回勉強会@岐阜11
Δx = np.logspace(-7,1,9,base=10)
x = np.zeros(Δx.size)
df = (np.sin(x+Δx)-np.sin(x-Δx))/(2.*Δx)
ɛ = np.abs(df-np.cos(x))
fig,ax = plt.subplots()
ax.plot(Δx,ɛ,lw=0,marker='o',clip_on=False)
ax.set_xscale('log')
ax.set_yscale('log')
plt.show()
誤差の収束性
2019/03/23オープンCAE第68回勉強会@岐阜12
1
2
 解析的には,Δ𝑥が1桁小さくなると𝜀は2桁落ちる
 2次精度
近似精度が悪く,
2次精度がでない
誤差の収束次数の調査
2019/03/23オープンCAE第68回勉強会@岐阜13
p_opt,cov = curve_fit(nonlinear_fit,Δx,ɛ)
ɛ_fit = np.vectorize(nonlinear_fit)
p_opt
def nonlinear_fit(x,a,b): #非線形回帰
return b*x**a
lower_bounds = (-np.inf,0.) #logに負の値が入らないように
upper_bounds = (np.inf,np.inf) #下限と上限を設定
p_opt2,cov = curve_fit(loglog_fit,np.log(Δx),np.log(ɛ),¥
bounds=(lower_bounds,upper_bounds))
ɛ_loglogfit = p_opt2[1]*Δx**p_opt2[0]
p_opt2
def loglog_fit(x,a,b): #対数を取って線形回帰
return a*x + np.log(b)
array([ 0.84009246, 0.15243934])
array([ 1.91900884, 0.06969248])
誤差の収束次数の調査
2019/03/23オープンCAE第68回勉強会@岐阜14
 非線形回帰は大きな値に影響される
誤差の収束次数の調査
2019/03/23オープンCAE第68回勉強会@岐阜15
 近似するデータの範囲を選べば同じ結果が出てくる
 明らかに傾きがおかしい結果を使わない
p_opt,cov = curve_fit(nonlinear_fit,Δx[:-2],ɛ[:-2])
ɛ_fit = np.vectorize(nonlinear_fit)
p_opt2,cov = curve_fit(loglog_fit,np.log(Δx[:-2]),¥
np.log(ɛ[:-2]),¥
bounds=((-np.inf,0.),(np.inf,np.inf)))
ɛ_loglogfit = p_opt2[1]*Δx**p_opt2[0]
誤差の収束次数の調査
2019/03/23オープンCAE第68回勉強会@岐阜16
 どちらもほぼ同じ
まとめ
2019/03/23オープンCAE第68回勉強会@岐阜17
 Excelの累乗近似をPythonで再現した
 変数変換してから線形回帰
 独立変数(𝑥)の範囲が狭い場合は非線形回帰の方がよ
い結果がでる
 独立変数(𝑥)の範囲が広い場合は,Excel方式の方が
よさそう
 非線形回帰は,大きな値の従属変数を重要視
 Excel式は全ての点を均等に評価
 誤差の収束性はまずExcel方式で確認するのがよい

Pythonによる累乗近似