Python 是否可以使用字典作为参数参考,使用PyMinuit最小化

Python 是否可以使用字典作为参数参考,使用PyMinuit最小化,python,Python,是否可以通过向最小化器传递参数字典来执行函数最小化 例如,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() p = dict() p['x

是否可以通过向最小化器传递参数字典来执行函数最小化

例如,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()
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()
从中,我了解到PyMinuit使用内省来确定参数x和y(但我不完全确定这意味着什么)。理想情况下,我希望能够做到以下几点:

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()
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()    
但由于某些原因,所有参数都被归类为“固定”参数,我似乎无法“取消固定”它们


我认为这样做应该是可能的,但我对python的了解还不足以说明这是否是最好的方法,甚至不知道是否应该尝试这样做。如果有人能对此有所了解,我将不胜感激。:)

好的,我不喜欢回答我自己的问题,但我想我已经找到了使用
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

这有点混乱,我不确定这是否是处理此类问题的最佳方式,但它确实有效

好的,我不喜欢回答我自己的问题,但我想我已经找到了使用
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

这有点混乱,我不确定这是否是处理此类问题的最佳方式,但它确实有效

以下内容基本上未经测试,我通常会尽量避免这样做,但我破例向您更好地解释我在评论中提到的可能适用于此的简化方式。它基于所示的第一个示例


正如您所看到的,所使用的模板非常简单,创建它不需要手动将要最小化的函数体中的任何代码转换为格式化字符串。

以下内容基本上未经测试,我通常会尝试避免这样做,但我破例向你们更好地解释我在评论中提到的可能适用于此的简化方式。它基于所示的第一个示例


正如您所看到的,所使用的模板非常简单,创建它不需要手动将要最小化的函数体中的任何代码翻译成格式化字符串。

可能会迟些回答。试试这个。我之所以写这篇文章,是因为在其他方面缺乏这一特定的功能

请参见此处编写通用成本函数的示例:

然而,尽管编写chi^2/似然函数很容易,但它已经在probfit中为您编写了


回答可能会迟到。试试这个。我之所以写这篇文章,是因为在其他方面缺乏这一特定的功能

请参见此处编写通用成本函数的示例:

然而,尽管编写chi^2/似然函数很容易,但它已经在probfit中为您编写了


内省是自我检查的行为。在编程语言中,它是一种检查某种东西以确定它是什么、它知道什么以及它能够做什么的能力。在本例中,它可能指的是能够确定函数参数的名称以及它们在其代码中的使用位置。在我看来,这就像您的第一个示例,
minuit.minuit(chi2,**p)
,其中
p
是一个字典,因为它非常类似于
minuit.minuit(f,x=10,y=10)
第一个链接中显示的示例。你试过了吗?如果没有,那么可以通过从字典中生成一些非常简单的“假代码”使其工作,这样它就与第一个例子完全一样,使用了问题后半部分中的技术。我的建议是,你试着去做这些,如果两者都不起作用(你也不知道为什么),在这里问另一个更具体的问题。这个特定的例子(第一个)不起作用,并给出一个“无参数”错误。我做了更多的阅读,我认为这是因为PyMinuit使用内省来分配参数,它将根据输入函数(在本例中为
chi2
)所需的参数进行更新。在第一个示例中,
chi2
不接受任何参数,因此不分配任何参数。在第二个例子中,所有参数最终都是“固定”的,我还没有弄清楚是如何或为什么。由于
minuit.minuit(卡方,**p)
不起作用,我建议您只为它创建一个模板,并在运行时使用
exec
将参数名称和值添加到该模板中,与您在回答中所做的整个
chi_squared()
函数定义相反。我不确定您的意思-是不是我应该在运行时使用
exec
来生成
minuit.minuit(chi_squared)
?我可以看到它如何在最小化例程中添加额外的参数,比如
limits\u a1=(下限,上限)
,但我正在努力处理参数。你能给我举个例子让我看看吗?内省是自我反省的行为。在编程语言中,它是一种检查某种东西以确定它是什么、它知道什么以及它能够做什么的能力。在本例中,它可能指的是能够确定函数参数的名称以及它们在其代码中的使用位置。在我看来,这就像您的第一个示例,
minuit.minuit(chi2,**p)
,其中
p
是一个字典,因为它非常类似于
minuit.minuit(f,x=10,y=10)
第一个链接中显示的示例。你试过了吗?如果没有,那么可能通过从源代码生成一些非常简单的“伪代码”来实现