是否可以通过将参数字典传递给最小化器来执行PyMinuit函数最小化?
例如,PyMinuit的通常用法是这样调用的:
def f(x, a, b): return a + b*x
def chi2(a,b):
c2 = 0.
for x, y, yerr in data:
c2 += (f(x, a, b) - y)**2 / yerr**2
return c2
m = minuit.Minuit(chi2)
m.migrad()在this question中,我了解到PyMinuit使用自省来确定参数x和y(但我不完全确定这是什么意思)。理想情况下,我希望能够这样做:
p = dict()
p['x'] = 0.
p['y'] = 0.
def f(x,a,b): return a + b*x
def chi2():
c2 = 0.
for x, y, yerr in data:
c2 += (f(x, a, b) - y)**2 / yerr**2
return c2
m = minuit.Minuit(chi2,**p)
m.migrad()或者甚至是:
p = <dictionary of parameters + initial values>
model = <list containing strings representing functions e.g. 'a*b+a**2*x'>
data = x, y, yerr, model
def chi2():
c2 = 0.
for x, y, yerr, model in data:
c2 += (eval(model,{"__builtins__":None},p) - y)**2 / yerr**2
return c2
m = minuit.Minuit(chi2)
m.migrad() 我在google groups issues page上看到了一个类似问题的变通方法,他们从整数输入生成‘伪代码’和‘伪函数’(点击链接查看)。我在我的字典中尝试了类似的东西:
class fake_code:
def __init__(self,p):
self.co_argcount = len(p)
self.co_varnames = tuple(p.keys())
print tuple(p.keys())
class fake_function:
def __init__(self,p):
self.func_code = fake_code(p)
def __call__(self,*args):
c2 = 0.
print args
for x, y, yerr in data:
c2 += (f(x, a, b) - y)**2 / yerr**2
return c2但由于某些原因,所有的参数都被归类为“固定”,我似乎无法“解除”它们。
我认为这样做应该是可能的,但我对python的了解还不够多,不知道这是不是最好的方法,或者是否应该尝试这样做。如果有人能对此有所了解,我将不胜感激。:)
发布于 2013-02-18 18:30:21
好吧,我不喜欢回答我自己的问题,但我想我已经找到了一个使用exec的解决方案。如果在模板中定义chi2函数,并在运行时使用函数make_chi_squared构建它,那么这是可能的。我想出的解决方案如下所示。
import minuit
import numpy
chi_squared_template = """
def chi_squared(%(params)s):
li = [%(params)s]
for i,para in enumerate(li):
p[l[i]] = para
return (((f(data_x, p) - data_y) / errors) ** 2).sum()
"""
l = ['a1','a2','a3','a4']
p = dict()
p['a1'] = 1.
p['a2'] = 1.
p['a3'] = 1.
p['a4'] = 1.
def make_chi_squared(f, data_x, data_y, errors):
params = ", ".join(l)
exec chi_squared_template % {"params": params}
return chi_squared
def f(x,p):
return eval('a1 + a2*x + a3*x**2 + a4*x**3',
{"__builtins__":locals()},
p)
data_x = numpy.arange(50)
errors = numpy.random.randn(50) * 0.3
data_y = data_x**3 + errors
chi_squared = make_chi_squared(f, data_x, data_y, errors)
m = minuit.Minuit(chi_squared)
m.printMode = 1
m.migrad()
print m.values
p = m.values
print p这有点混乱,我不确定这是否是处理这类问题的最好方法,但它是有效的!
发布于 2013-02-19 03:55:54
下面的内容在很大程度上是未经测试的,我通常会尽量避免这样做,但我做了一个例外,以便更好地向您解释我在评论中提到的可能对此有效的简化方法。它基于here显示的第一个示例。
import minuit
def minuit_call(func, **kwargs):
CALL_TEMPLATE = "minuit.Minuit({0.__name__}, {1})"
arg_str = ', '.join('{}={}'.format(k, v) for k,v in kwargs.iteritems())
return eval(CALL_TEMPLATE.format(func, arg_str))
def f(x, y):
return ((x-2) / 3)**2 + y**2 + y**4
m = minuit_call(f, x=0, y=0)
m.migrad()正如您所看到的,使用的模板相当简单,创建它不需要手动将函数体中的任何代码转换为格式化字符串。
发布于 2013-03-28 18:08:46
可能来不及回答了。试试这个iminuit。我之所以写它,是因为除了其他功能之外,还缺少这个特定功能。
http://iminuit.github.com/iminuit/
请参阅此处的示例,您将如何编写通用成本函数:
http://nbviewer.ipython.org/urls/raw.github.com/iminuit/iminuit/master/tutorial/hard-core-tutorial.ipynb
然而,尽管编写一个X^2/似然函数很容易,但它已经在概率中为您编写好了
http://iminuit.github.com/probfit/
https://stackoverflow.com/questions/14925618
复制相似问题