Scipy.minimize 没有正确最小化
Scipy.minimize not correctly minimizing
我目前正在做一个项目,当你离开银河系中心时绘制恒星的速度(到中心的距离用 r
表示)。
本质上,我的目标是最小化模型函数和观察函数之间的距离。为此,我必须最小化函数:np.sum(((v_model-v_obs)/errors)**2)
其中 errors
是每个不同 r
值的错误数组。 v_obs
是在每个 r
值处观察到的速度(r
只是一个数字数组)。为了最小化函数,我必须操纵 v_model
这可以通过操纵方程中的两个 "fixing parameters" p0
和 r0
来完成(被积函数如下所示):
np.sqrt(4.302*10**(-6)*quad(integrand,0,r.all(),args=(p0,r0))[0]/r.all())
在进入问题之前,我想知道 r.all()
是否合适,因为它不允许我放置 r
因为它是一个数组。我的另一种选择是通过以下方式制作一个 v_model
数组:
#am is the amount of elements in the array r
#r, v_model,v_obs, and errors all have the same size
def integrand(r,p0,r0):
return (p0 * r0**3)/((r+r0)*((r**2)+(r0**2)))*4*3.1415926535*r**2
integrals = []
for i in r:
integrals.append(quad(integrand, 0 ,i,args=(p0,r0)))
v_model = []
for x in range (0,am):
k = integrals[x][0]
i = r[x]
v_model.append(np.sqrt((4.302*10**(-6)*k)/i))
不管,最小化函数np.sum(((v_model-v_obs)/errors)**2)
我试着做这样的事情:
def chisqfunc(parameters):
p0 = parameters[0]
r0 = parameters[1]
v_model = []
for x in range(0,am):
v_model.append(np.sqrt(4.302*10.0**(-6)*quad(integrand, 0, r[x], args=(p0,r0))[0]/r[x]))
chisq = np.sum(((v_model-v_obs)/errors)**2)
return chisq
x0 = np.array([10**6,24])
resolution = minimize(chisqfunc,x0)
但是,我得到的值根本不合适(当我绘制观察到的数据和我的模型时很明显)
总而言之,我有两个主要问题:
1.) 我的函数是否采用模型减去每个不同 r
值的观察值,如果不是,我该如何解决? (我想我搞砸了我的 v_model
等式)
2.) 为什么返回 r0
和 p0
的错误数字?
这是我的完整代码(顺便说一句,了解最小化是否正常工作:r0 应该在 1.5 左右,p0 应该在:3.5*10**8 左右)
from scipy.optimize import*
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
from scipy.integrate import quad
#number of measurements
am = 18
r0 = 1.8
p0 = 3.5*10**8.62
#Observed Data
v_obs = np.array([
234.00,
192.00,
212.00,
223.00,
222.00,
224.00,
224.00,
226.00,
226.00,
227.00,
227.00,
224.00,
220.00,
218.00,
217.00,
216.00,
210.00,
208.00
]
)
r = np.array([0.92,
2.32,
3.24,
4.17,
5.10,
6.03,
6.96,
7.89,
8.80,
9.73,
10.64,
11.58,
12.52,
13.46,
14.40,
15.33,
16.27,
17.11
]
)
errors = np.array([
3.62,
4.31,
3.11,
5.5,
3.9,
3.5,
2.7,
2.5,
2.3,
2.1,
2.3,
2.6,
3.1,
3.2,
3.2,
3.1,
2.9,
2.8
])
#integral
def integrand(r,p0,r0):
return (p0 * r0**3)/((r+r0)*((r**2)+(r0**2)))*4*3.1415926535*r**2
integrals = []
for i in r:
integrals.append(quad(integrand, 0 ,i,args=(p0,r0)))
v_model = []
for x in range (0,am):
k = integrals[x][0]
i = r[x]
v_model.append(np.sqrt((4.302*10**(-6)*k)/i))
def chisqfunc(parameters):
p0 = parameters[0]
r0 = parameters[1]
v_model = np.sqrt(4.302*10**(-6)*quad(integrand,0,r.all(),args=(p0,r0))[0]/r.all())
chisq = np.sum(((v_model-v_obs)/errors)**2)
print(v_model)
return chisq
x0 = np.array([10**6,24])
resolution = minimize(chisqfunc,x0)
print("This is the function",resolution)
如果我遗漏了任何数据,请告诉我,在此先感谢您!
我一直在玩你的代码。我尝试了各种 methods/solvers,它们都收敛到大致相同的答案。我认为这是它可以达到的最佳答案。为了对此进行测试,我计算了您认为正确的答案(r0 = 1.8,p0 = 3.5 * 10 ** 8.62)和计算出的答案的差异和平方根。计算出的答案似乎有更小的错误(527 对 564)。
from scipy.optimize import*
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
from scipy.integrate import quad
#-----------------------------------------------------------------------------
#number of measurements
am = 18
r0 = 1.8
p0 = 3.5*10.0**8.62
#Observed Data
v_obs = np.array([
234.00, 192.00, 212.00, 223.00, 222.00,
224.00, 224.00, 226.00, 226.00, 227.00,
227.00, 224.00, 220.00, 218.00, 217.00,
216.00, 210.00, 208.00,
])
r = np.array([
0.92, 2.32, 3.24, 4.17, 5.10,
6.03, 6.96, 7.89, 8.80, 9.73,
10.64, 11.58, 12.52, 13.46, 14.40,
15.33, 16.27, 17.11
])
errors = np.array([
3.62, 4.31, 3.11, 5.5, 3.9,
3.5, 2.7, 2.5, 2.3, 2.1,
2.3, 2.6, 3.1, 3.2, 3.2,
3.1, 2.9, 2.8
])
#-----------------------------------------------------------------------------
#integral
def integrand(r,p0,r0):
return (p0 * r0**3)/((r+r0)*((r**2)+(r0**2)))*4.0*3.1415926535*r**2
#-----------------------------------------------------------------------------
integrals = []
for i in r:
integrals.append(quad(integrand, 0, i, args=(p0,r0)))
#print "integrals = " + str(integrals)
v_model = []
for x in range(0,am):
k = integrals[x][0]
i = r[x]
v_model.append(np.sqrt((4.302*10.0**(-6)*k)/i))
#print "v_model = " + str(v_model)
#-----------------------------------------------------------------------------
def chisqfunc(parameters):
p0 = parameters[0]
r0 = parameters[1]
v_model = np.sqrt(4.302*10.0**(-6)*quad(integrand, 0, r.all(), args=(p0,r0))[0]/r.all())
chisq = np.sum(((v_model - v_obs)/errors)**2)
#print "chisq = " + str(chisq)
#print "v_model = " + str(v_model)
return chisq
#-----------------------------------------------------------------------------
x0 = np.array([10.0**6,24.0]) # initial guess
# try various methods (they all give about the same answer, they all "converged")
#resolution = minimize(chisqfunc, x0, method='Nelder-Mead', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='Powell', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='CG', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='BFGS', tol=0.001)
# Jac required - resolution = minimize(chisqfunc, x0, method='Newton-CG', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='L-BFGS-B', tol=0.001)
#
resolution = minimize(chisqfunc, x0, method='TNC', tol=0.001,
options={'scale':None})
# options tried
# 'gtol':1e-6, 'xtol':-1, 'rescale':0, 'ftol':0, 'accuracy':0, 'offset':None, 'scale':None
#
#resolution = minimize(chisqfunc, x0, method='COBYLA', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='SLSQP', tol=0.001)
# Jac required - resolution = minimize(chisqfunc, x0, method='dogleg', tol=0.001)
# Jac required - resolution = minimize(chisqfunc, x0, method='trust-ncg', tol=0.001)
# unknown solver - resolution = minimize(chisqfunc, x0, method='trust-exact', tol=0.001)
# unknown solver - resolution = minimize(chisqfunc, x0, method='trust-krylov', tol=0.001)
print("This is the function",resolution)
print "resolution.x"
print resolution.x
print "p0 should be = " + str(3.5*10**8)
print "r0 should be = " + str(1.5)
#-----------------------------------------------------------------------------
# check answers to see which is better
for index in range(len(v_obs)):
# declared answer---------------------------------------------------------
p0 = 3.5*10**8
r0 = 1.5
integrals = []
for i in r:
integrals.append(quad(integrand, 0, i, args=(p0,r0)))
#print "integrals = " + str(integrals)
v_model_declared = []
sum_error1 = 0.0
for x in range(0,am):
k = integrals[x][0]
i = r[x]
v_model_declared.append(np.sqrt((4.302*10.0**(-6)*k)/i))
error1 = (v_obs[x] - v_model_declared[x])**2
sum_error1 += error1
#print "v_model = " + str(v_model)
# computed answer---------------------------------------------------------
p0 = 8.06400536e+06
r0 = 4.27905063e+02
integrals = []
for i in r:
integrals.append(quad(integrand, 0, i, args=(p0,r0)))
#print "integrals = " + str(integrals)
v_model_computed = []
sum_error2 = 0.0
for x in range(0,am):
k = integrals[x][0]
i = r[x]
v_model_computed.append(np.sqrt((4.302*10.0**(-6)*k)/i))
error2 = (v_obs[x] - v_model_computed[x])**2
sum_error2 += error2
print "v_obs, v_model, v_model2 = " + str(v_obs[index]) + ", " + str(v_model_declared[index])+ ", " + str(v_model_computed[index])
#
print "sum_error1 (declared answer) = " + str(sum_error1)
print "sum_error2 (computed answer) = " + str(sum_error2)
print "sqrt(sum_error1) (declared answer) = " + str(np.sqrt(sum_error1))
print "sqrt(sum_error2) (computed answer) = " + str(np.sqrt(sum_error2))
#-----------------------------------------------------------------------------
如果您在函数中更改 p0,它会降低优化程序例程中的数字。这似乎工作得很好,我猜数字太大了,导致求解器出现一些数字错误。只需记住将 p0 答案乘以 3.85e+09,就像在 chisqfunc 例程中所做的那样。
from scipy.optimize import*
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
from scipy.integrate import quad
#-----------------------------------------------------------------------------
am = 18 # number of measurements
#Observed Data
v_obs = np.array([
234.00, 192.00, 212.00, 223.00, 222.00, 224.00, 224.00, 226.00, 226.00, 227.00,
227.00, 224.00, 220.00, 218.00, 217.00, 216.00, 210.00, 208.00,
])
r = np.array([
0.92, 2.32, 3.24, 4.17, 5.10, 6.03, 6.96, 7.89, 8.80, 9.73,
10.64, 11.58, 12.52, 13.46, 14.40, 15.33, 16.27, 17.11
])
errors = np.array([
3.62, 4.31, 3.11, 5.5, 3.9, 3.5, 2.7, 2.5, 2.3, 2.1,
2.3, 2.6, 3.1, 3.2, 3.2, 3.1, 2.9, 2.8
])
grav_const = 4.302e-06
#print "np.pi, grav_const = " + str(np.pi) + ", " + str(grav_const)
#-----------------------------------------------------------------------------
def func_to_integrate(rx, p0, r0):
rho = (p0 * r0**3) / ( (rx + r0) * (rx**2 + r0**2) )
function_result = rho * 4.0 * np.pi * rx**2
#print "rx, p0, r0 = " + str(rx) + ", " + str(p0) + ", " + str(r0)
return function_result
#-----------------------------------------------------------------------------
def simpsonsRule(func, a, b, n, p0, r0):
if n%2 == 1:
return "Not applicable"
else:
h = (b - a) / float(n)
s = func(a, p0, r0) + sum((4 if i%2 == 1 else 2) * func(a+i*h, p0, r0) for i in range(1,n)) + func(b, p0, r0)
return s*h/3.0
#-----------------------------------------------------------------------------
def chisqfunc(iter_vars):
global v_model
p0 = iter_vars[0] * 3.85e+09
r0 = iter_vars[1]
v_model = []
for index in range(0, am):
integral_result = simpsonsRule(func_to_integrate, 0.0, r[index], 200, p0, r0)
v_mod_result = np.sqrt(grav_const * integral_result / r[index])
v_model.append(v_mod_result)
chisq = 0.0
for index in range(0, am):
chisq += ((v_model[index] - v_obs[index])/errors[index])**2
#chisq += ((v_model[index] - v_obs[index]))**2
chisq = np.sqrt(chisq)
#chisq = np.sum(((v_model - v_obs)/errors)**2)
print "chisq = " + str(chisq)
#print "iterated p0, r0 = " + str(p0) + ", " + str(r0)
return chisq
#-----------------------------------------------------------------------------
initial_guess = np.array([1.0, 2.0])
#initial_guess = np.array([3.5*10**8.62, 1.5])
#resolution = minimize(chisqfunc, initial_guess, method='TNC') # , tol=1e-12, options={'accuracy':0})
#resolution = minimize(chisqfunc, initial_guess, method='TNC', options={'rescale':-1})
#resolution = minimize(chisqfunc, initial_guess, method='CG')
resolution = minimize(chisqfunc, initial_guess, method='Nelder-Mead')
# # options tried
# 'gtol':1e-6, 'xtol':-1, 'rescale':0, 'ftol':0, 'accuracy':0, 'offset':None, 'scale':None
print("This is the function",resolution)
#print "resolution.x"
#print resolution.x
print "iterated p0 = " + str(resolution.x[0])
print "iterated p0 * 3.85e+09 = " + str(resolution.x[0] * 3.85e+09)
print "iterated r0 = " + str(resolution.x[1])
print "p0 should be about = " + str(3.5e+08)
print "r0 should be about = " + str(1.5)
print "-----------------------------------------------"
print "iterated model errors"
for index in range(0,am):
print "v_obs, v_model, error = " + str(v_obs[index]) + ", " + str(v_model[index]) + ", " + str(v_obs[index] - v_model[index])
chisq = 0.0
for index in range(0, am):
chisq += ((v_model[index] - v_obs[index])/errors[index])**2
#chisq += ((v_model[index] - v_obs[index]))**2
chisq = np.sqrt(chisq)
print "iterated chisq = " + str(chisq)
print ""
#-----------------------------------------------------------------------------
print "model errors using p0 = 3.5*10**8.62, r0 = 1.8"
p0 = 3.5*10**8.62
r0 = 1.8
# chisq = 118 for p0 = 3.5*10**8.62, r0 = 1.8
# chisq = 564 for p0 = 3.5*10**8 , r0 = 1.5
chisq = 0.0
for index in range(0, am):
integral_result = simpsonsRule(func_to_integrate, 0.0, r[index], 200, p0, r0)
v_mod = np.sqrt(grav_const * integral_result / r[index])
print "v_obs, v_mod, error = " + str(v_obs[index]) + ", " + str(v_mod) + ", " + str(v_obs[index] - v_mod)
#chisq += ((v_mod - v_obs[index]))**2
chisq += ((v_mod - v_obs[index])/errors[index])**2
chisq = np.sqrt(chisq)
print "using p0 = 3.5*10**8.62, r0 = 1.8, the chisq = " + str(chisq)
#-----------------------------------------------------------------------------
我目前正在做一个项目,当你离开银河系中心时绘制恒星的速度(到中心的距离用 r
表示)。
本质上,我的目标是最小化模型函数和观察函数之间的距离。为此,我必须最小化函数:np.sum(((v_model-v_obs)/errors)**2)
其中 errors
是每个不同 r
值的错误数组。 v_obs
是在每个 r
值处观察到的速度(r
只是一个数字数组)。为了最小化函数,我必须操纵 v_model
这可以通过操纵方程中的两个 "fixing parameters" p0
和 r0
来完成(被积函数如下所示):
np.sqrt(4.302*10**(-6)*quad(integrand,0,r.all(),args=(p0,r0))[0]/r.all())
在进入问题之前,我想知道 r.all()
是否合适,因为它不允许我放置 r
因为它是一个数组。我的另一种选择是通过以下方式制作一个 v_model
数组:
#am is the amount of elements in the array r
#r, v_model,v_obs, and errors all have the same size
def integrand(r,p0,r0):
return (p0 * r0**3)/((r+r0)*((r**2)+(r0**2)))*4*3.1415926535*r**2
integrals = []
for i in r:
integrals.append(quad(integrand, 0 ,i,args=(p0,r0)))
v_model = []
for x in range (0,am):
k = integrals[x][0]
i = r[x]
v_model.append(np.sqrt((4.302*10**(-6)*k)/i))
不管,最小化函数np.sum(((v_model-v_obs)/errors)**2)
我试着做这样的事情:
def chisqfunc(parameters):
p0 = parameters[0]
r0 = parameters[1]
v_model = []
for x in range(0,am):
v_model.append(np.sqrt(4.302*10.0**(-6)*quad(integrand, 0, r[x], args=(p0,r0))[0]/r[x]))
chisq = np.sum(((v_model-v_obs)/errors)**2)
return chisq
x0 = np.array([10**6,24])
resolution = minimize(chisqfunc,x0)
但是,我得到的值根本不合适(当我绘制观察到的数据和我的模型时很明显)
总而言之,我有两个主要问题:
1.) 我的函数是否采用模型减去每个不同 r
值的观察值,如果不是,我该如何解决? (我想我搞砸了我的 v_model
等式)
2.) 为什么返回 r0
和 p0
的错误数字?
这是我的完整代码(顺便说一句,了解最小化是否正常工作:r0 应该在 1.5 左右,p0 应该在:3.5*10**8 左右)
from scipy.optimize import*
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
from scipy.integrate import quad
#number of measurements
am = 18
r0 = 1.8
p0 = 3.5*10**8.62
#Observed Data
v_obs = np.array([
234.00,
192.00,
212.00,
223.00,
222.00,
224.00,
224.00,
226.00,
226.00,
227.00,
227.00,
224.00,
220.00,
218.00,
217.00,
216.00,
210.00,
208.00
]
)
r = np.array([0.92,
2.32,
3.24,
4.17,
5.10,
6.03,
6.96,
7.89,
8.80,
9.73,
10.64,
11.58,
12.52,
13.46,
14.40,
15.33,
16.27,
17.11
]
)
errors = np.array([
3.62,
4.31,
3.11,
5.5,
3.9,
3.5,
2.7,
2.5,
2.3,
2.1,
2.3,
2.6,
3.1,
3.2,
3.2,
3.1,
2.9,
2.8
])
#integral
def integrand(r,p0,r0):
return (p0 * r0**3)/((r+r0)*((r**2)+(r0**2)))*4*3.1415926535*r**2
integrals = []
for i in r:
integrals.append(quad(integrand, 0 ,i,args=(p0,r0)))
v_model = []
for x in range (0,am):
k = integrals[x][0]
i = r[x]
v_model.append(np.sqrt((4.302*10**(-6)*k)/i))
def chisqfunc(parameters):
p0 = parameters[0]
r0 = parameters[1]
v_model = np.sqrt(4.302*10**(-6)*quad(integrand,0,r.all(),args=(p0,r0))[0]/r.all())
chisq = np.sum(((v_model-v_obs)/errors)**2)
print(v_model)
return chisq
x0 = np.array([10**6,24])
resolution = minimize(chisqfunc,x0)
print("This is the function",resolution)
如果我遗漏了任何数据,请告诉我,在此先感谢您!
我一直在玩你的代码。我尝试了各种 methods/solvers,它们都收敛到大致相同的答案。我认为这是它可以达到的最佳答案。为了对此进行测试,我计算了您认为正确的答案(r0 = 1.8,p0 = 3.5 * 10 ** 8.62)和计算出的答案的差异和平方根。计算出的答案似乎有更小的错误(527 对 564)。
from scipy.optimize import*
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
from scipy.integrate import quad
#-----------------------------------------------------------------------------
#number of measurements
am = 18
r0 = 1.8
p0 = 3.5*10.0**8.62
#Observed Data
v_obs = np.array([
234.00, 192.00, 212.00, 223.00, 222.00,
224.00, 224.00, 226.00, 226.00, 227.00,
227.00, 224.00, 220.00, 218.00, 217.00,
216.00, 210.00, 208.00,
])
r = np.array([
0.92, 2.32, 3.24, 4.17, 5.10,
6.03, 6.96, 7.89, 8.80, 9.73,
10.64, 11.58, 12.52, 13.46, 14.40,
15.33, 16.27, 17.11
])
errors = np.array([
3.62, 4.31, 3.11, 5.5, 3.9,
3.5, 2.7, 2.5, 2.3, 2.1,
2.3, 2.6, 3.1, 3.2, 3.2,
3.1, 2.9, 2.8
])
#-----------------------------------------------------------------------------
#integral
def integrand(r,p0,r0):
return (p0 * r0**3)/((r+r0)*((r**2)+(r0**2)))*4.0*3.1415926535*r**2
#-----------------------------------------------------------------------------
integrals = []
for i in r:
integrals.append(quad(integrand, 0, i, args=(p0,r0)))
#print "integrals = " + str(integrals)
v_model = []
for x in range(0,am):
k = integrals[x][0]
i = r[x]
v_model.append(np.sqrt((4.302*10.0**(-6)*k)/i))
#print "v_model = " + str(v_model)
#-----------------------------------------------------------------------------
def chisqfunc(parameters):
p0 = parameters[0]
r0 = parameters[1]
v_model = np.sqrt(4.302*10.0**(-6)*quad(integrand, 0, r.all(), args=(p0,r0))[0]/r.all())
chisq = np.sum(((v_model - v_obs)/errors)**2)
#print "chisq = " + str(chisq)
#print "v_model = " + str(v_model)
return chisq
#-----------------------------------------------------------------------------
x0 = np.array([10.0**6,24.0]) # initial guess
# try various methods (they all give about the same answer, they all "converged")
#resolution = minimize(chisqfunc, x0, method='Nelder-Mead', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='Powell', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='CG', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='BFGS', tol=0.001)
# Jac required - resolution = minimize(chisqfunc, x0, method='Newton-CG', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='L-BFGS-B', tol=0.001)
#
resolution = minimize(chisqfunc, x0, method='TNC', tol=0.001,
options={'scale':None})
# options tried
# 'gtol':1e-6, 'xtol':-1, 'rescale':0, 'ftol':0, 'accuracy':0, 'offset':None, 'scale':None
#
#resolution = minimize(chisqfunc, x0, method='COBYLA', tol=0.001)
#resolution = minimize(chisqfunc, x0, method='SLSQP', tol=0.001)
# Jac required - resolution = minimize(chisqfunc, x0, method='dogleg', tol=0.001)
# Jac required - resolution = minimize(chisqfunc, x0, method='trust-ncg', tol=0.001)
# unknown solver - resolution = minimize(chisqfunc, x0, method='trust-exact', tol=0.001)
# unknown solver - resolution = minimize(chisqfunc, x0, method='trust-krylov', tol=0.001)
print("This is the function",resolution)
print "resolution.x"
print resolution.x
print "p0 should be = " + str(3.5*10**8)
print "r0 should be = " + str(1.5)
#-----------------------------------------------------------------------------
# check answers to see which is better
for index in range(len(v_obs)):
# declared answer---------------------------------------------------------
p0 = 3.5*10**8
r0 = 1.5
integrals = []
for i in r:
integrals.append(quad(integrand, 0, i, args=(p0,r0)))
#print "integrals = " + str(integrals)
v_model_declared = []
sum_error1 = 0.0
for x in range(0,am):
k = integrals[x][0]
i = r[x]
v_model_declared.append(np.sqrt((4.302*10.0**(-6)*k)/i))
error1 = (v_obs[x] - v_model_declared[x])**2
sum_error1 += error1
#print "v_model = " + str(v_model)
# computed answer---------------------------------------------------------
p0 = 8.06400536e+06
r0 = 4.27905063e+02
integrals = []
for i in r:
integrals.append(quad(integrand, 0, i, args=(p0,r0)))
#print "integrals = " + str(integrals)
v_model_computed = []
sum_error2 = 0.0
for x in range(0,am):
k = integrals[x][0]
i = r[x]
v_model_computed.append(np.sqrt((4.302*10.0**(-6)*k)/i))
error2 = (v_obs[x] - v_model_computed[x])**2
sum_error2 += error2
print "v_obs, v_model, v_model2 = " + str(v_obs[index]) + ", " + str(v_model_declared[index])+ ", " + str(v_model_computed[index])
#
print "sum_error1 (declared answer) = " + str(sum_error1)
print "sum_error2 (computed answer) = " + str(sum_error2)
print "sqrt(sum_error1) (declared answer) = " + str(np.sqrt(sum_error1))
print "sqrt(sum_error2) (computed answer) = " + str(np.sqrt(sum_error2))
#-----------------------------------------------------------------------------
如果您在函数中更改 p0,它会降低优化程序例程中的数字。这似乎工作得很好,我猜数字太大了,导致求解器出现一些数字错误。只需记住将 p0 答案乘以 3.85e+09,就像在 chisqfunc 例程中所做的那样。
from scipy.optimize import*
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
from scipy.integrate import quad
#-----------------------------------------------------------------------------
am = 18 # number of measurements
#Observed Data
v_obs = np.array([
234.00, 192.00, 212.00, 223.00, 222.00, 224.00, 224.00, 226.00, 226.00, 227.00,
227.00, 224.00, 220.00, 218.00, 217.00, 216.00, 210.00, 208.00,
])
r = np.array([
0.92, 2.32, 3.24, 4.17, 5.10, 6.03, 6.96, 7.89, 8.80, 9.73,
10.64, 11.58, 12.52, 13.46, 14.40, 15.33, 16.27, 17.11
])
errors = np.array([
3.62, 4.31, 3.11, 5.5, 3.9, 3.5, 2.7, 2.5, 2.3, 2.1,
2.3, 2.6, 3.1, 3.2, 3.2, 3.1, 2.9, 2.8
])
grav_const = 4.302e-06
#print "np.pi, grav_const = " + str(np.pi) + ", " + str(grav_const)
#-----------------------------------------------------------------------------
def func_to_integrate(rx, p0, r0):
rho = (p0 * r0**3) / ( (rx + r0) * (rx**2 + r0**2) )
function_result = rho * 4.0 * np.pi * rx**2
#print "rx, p0, r0 = " + str(rx) + ", " + str(p0) + ", " + str(r0)
return function_result
#-----------------------------------------------------------------------------
def simpsonsRule(func, a, b, n, p0, r0):
if n%2 == 1:
return "Not applicable"
else:
h = (b - a) / float(n)
s = func(a, p0, r0) + sum((4 if i%2 == 1 else 2) * func(a+i*h, p0, r0) for i in range(1,n)) + func(b, p0, r0)
return s*h/3.0
#-----------------------------------------------------------------------------
def chisqfunc(iter_vars):
global v_model
p0 = iter_vars[0] * 3.85e+09
r0 = iter_vars[1]
v_model = []
for index in range(0, am):
integral_result = simpsonsRule(func_to_integrate, 0.0, r[index], 200, p0, r0)
v_mod_result = np.sqrt(grav_const * integral_result / r[index])
v_model.append(v_mod_result)
chisq = 0.0
for index in range(0, am):
chisq += ((v_model[index] - v_obs[index])/errors[index])**2
#chisq += ((v_model[index] - v_obs[index]))**2
chisq = np.sqrt(chisq)
#chisq = np.sum(((v_model - v_obs)/errors)**2)
print "chisq = " + str(chisq)
#print "iterated p0, r0 = " + str(p0) + ", " + str(r0)
return chisq
#-----------------------------------------------------------------------------
initial_guess = np.array([1.0, 2.0])
#initial_guess = np.array([3.5*10**8.62, 1.5])
#resolution = minimize(chisqfunc, initial_guess, method='TNC') # , tol=1e-12, options={'accuracy':0})
#resolution = minimize(chisqfunc, initial_guess, method='TNC', options={'rescale':-1})
#resolution = minimize(chisqfunc, initial_guess, method='CG')
resolution = minimize(chisqfunc, initial_guess, method='Nelder-Mead')
# # options tried
# 'gtol':1e-6, 'xtol':-1, 'rescale':0, 'ftol':0, 'accuracy':0, 'offset':None, 'scale':None
print("This is the function",resolution)
#print "resolution.x"
#print resolution.x
print "iterated p0 = " + str(resolution.x[0])
print "iterated p0 * 3.85e+09 = " + str(resolution.x[0] * 3.85e+09)
print "iterated r0 = " + str(resolution.x[1])
print "p0 should be about = " + str(3.5e+08)
print "r0 should be about = " + str(1.5)
print "-----------------------------------------------"
print "iterated model errors"
for index in range(0,am):
print "v_obs, v_model, error = " + str(v_obs[index]) + ", " + str(v_model[index]) + ", " + str(v_obs[index] - v_model[index])
chisq = 0.0
for index in range(0, am):
chisq += ((v_model[index] - v_obs[index])/errors[index])**2
#chisq += ((v_model[index] - v_obs[index]))**2
chisq = np.sqrt(chisq)
print "iterated chisq = " + str(chisq)
print ""
#-----------------------------------------------------------------------------
print "model errors using p0 = 3.5*10**8.62, r0 = 1.8"
p0 = 3.5*10**8.62
r0 = 1.8
# chisq = 118 for p0 = 3.5*10**8.62, r0 = 1.8
# chisq = 564 for p0 = 3.5*10**8 , r0 = 1.5
chisq = 0.0
for index in range(0, am):
integral_result = simpsonsRule(func_to_integrate, 0.0, r[index], 200, p0, r0)
v_mod = np.sqrt(grav_const * integral_result / r[index])
print "v_obs, v_mod, error = " + str(v_obs[index]) + ", " + str(v_mod) + ", " + str(v_obs[index] - v_mod)
#chisq += ((v_mod - v_obs[index]))**2
chisq += ((v_mod - v_obs[index])/errors[index])**2
chisq = np.sqrt(chisq)
print "using p0 = 3.5*10**8.62, r0 = 1.8, the chisq = " + str(chisq)
#-----------------------------------------------------------------------------