問題は、最初の推測が実際の解決策とはかけ離れていることです。chisqfunc()
like内に print ステートメントを追加しprint (a,b)
てコードを再実行すると、次のような結果が得られます。
(0, 0)
(1.4901161193847656e-08, 0.0)
(0.0, 1.4901161193847656e-08)
これは、minimize
がこれらの点でのみ関数を評価することを意味します。
これらの 3 つの値のペアで評価しようとするとchisqfunc()
、たとえば、それらが完全に一致することがわかります。
print chisqfunc((0,0))==chisqfunc((1.4901161193847656e-08,0))
True
これは、浮動小数点演算の丸めが原因で発生します。つまり、 を評価するときstress - model
、varstress
は より桁違いに大きいためmodel
、結果は切り捨てられます。
data=data.astype(np.float128)
でデータをロードした直後に書き込むことで、浮動小数点の精度を上げて総当たり攻撃を試みることができloadtxt
ます。minimize
で失敗しresult.success=False
ますが、役立つメッセージが表示されます
精度の低下により、必ずしも目的のエラーが達成されるとは限りません。
1 つの可能性は、より良い初期推定値を提供することです。これにより、減算stress - model
でmodel
部分が同じ大きさになるようになり、もう 1 つはデータを再スケーリングして、解が初期推定値に近くなります(0,0)
。
データを再スケーリングして、たとえば特定の応力値 (この材料の黄ばみ/ひび割れなど) に関して無次元にする場合は、はるかに優れています。
これは、測定された最大応力を応力スケールとして使用したフィッティングの例です。コードからの変更はほとんどありません。
import numpy
import scipy.optimize as opt
filename = 'data.csv'
data = numpy.loadtxt(open(filename,"r"),delimiter=",")
stress = data[:,0]
strain = data[:,1]
err_stress = data[:,2]
smax = stress.max()
stress = stress/smax
#I am assuming the errors err_stress are in the same units of stress.
err_stress = err_stress/smax
def chisqfunc((a, b)):
model = a + b*strain
chisq = numpy.sum(((stress - model)/err_stress)**2)
return chisq
x0 = numpy.array([0,0])
result = opt.minimize(chisqfunc, x0)
print result
assert result.success==True
a,b=result.x*smax
plot(strain,stress*smax)
plot(strain,a+b*strain)
線形モデルは非常に優れています。つまり、材料はこの範囲の変形に対して非常に線形の動作をします (とにかく、どの材料ですか?):
