如何将参数传递给其他函数(通常和通过 scipy)? [英] How do I pass through arguments to other functions (generally and via scipy)?
问题描述
我正在尝试 最小化一个输出chi-的函数通过 scipy 平方,找到最适合高斯叠加的 mu、sigma、normc.
from math import exp从数学导入 pi从 scipy.integrate 导入四边形从 scipy.optimize 导入最小化从 scipy.stats 导入卡方将 numpy 导入为 np# 猜测最小化卡方的初始值mu, sigma = np.mean(mydata), np.std(mydata) # mydata 是我的数据点normc = 1/(sigma * (2*pi)**(1/2))gauss = lambda x: normc * exp( (-1) * (x - mu)**2/( 2 * (sigma **2) ) ) # 高斯分布# 假设我有预定义的 bin-boundaries 作为一个名为 binbound 的列表def expvalperbin(binbound,mu,sigma,normc):# 计算每个 bin 的期望值答案 = []对于范围内的索引(len(binbound)):如果索引 != len(binbound)-1:ans.append(quad( 高斯,binbound[index],binbound[index+1])[0])返回答案expvalguess = expvalperbin(binbound,mu,sig,normc)obsval = countperbin(binbound,mydata)arglist = [mu,sig,norm]def chisquareopt(obslist,explist):返回卡方(obslist,explist)[0]chisquareguess = chisquareopt((obsval,expvalguess), expvalguess, args=arglist)结果 = 最小化( chisquareopt(obsval,expvalguess), chisquareguess)打印(结果)
运行此代码为我提供了此错误:
TypeError: chisquareopt() 得到了一个意外的关键字参数args"
我有几个问题:
1) 如何编写一个函数来允许将参数传递给我的函数 chisquareopt?
2) 如何判断 scipy 是否会优化给出最小卡方的参数 [mu, sigma, normc]?我如何从优化中找到这些参数?
3) 很难知道我是否在这里取得了进展.我在正确的轨道上吗?
如果相关,我有一个函数输入 [mu, sigma, normc] 并输出子列表列表,每个子列表包含 [mu, sigma, normc] 的可能组合(其中外部列表涵盖指定范围内所有可能的参数组合).
我已经稍微简化了您的问题,让您对问题 2 有所了解.
首先,我将您的直方图 obslist
和数据点的数量 N
硬编码为全局变量(这稍微简化了函数签名).其次,我在 expvalperbin
中硬编码了 bin 边界,假设 9 个 bin 具有固定宽度 5
并且第一个 bin 从 30
开始(所以直方图范围从 30 到 75).
第三,我使用 optimize.fmin
(Nelder-Mead) 而不是 optimize.minimize
.使用 fmin
而不是 minimize
的原因是通过 args=(x,y)
传递附加参数似乎不起作用从这个意义上说,附加参数从第一次调用开始就保持固定值.这不是您想要的:您想同时优化 mu
和 sigma
.
鉴于这些简化,我们有以下(肯定非常非pythonic)脚本:
from math import exp从数学导入 pi从 scipy.integrate 导入四边形从 scipy.optimize 导入 fmin从 scipy.stats 导入卡方obslist = [12, 51, 144, 268, 264, 166, 75, 18, 2] # 直方图,1000 个观察值N = 1000 # 没有.数据点def gauss(x, mu, sigma):返回 1/(sigma * (2*pi)**(1/2)) * exp( (-1) * (x - mu)**2/( 2 * (sigma **2) ) )def expvalperbin(mu, sigma):e = []# 硬编码的 bin 边界对于范围内的 i (30, 75, 5):e.append(quad(gauss, i, i + 5, args=(mu, sigma))[0] * N)返回 edef chisquareopt(args):# args[0] = mu# args[1] = 西格玛返回卡方(obslist,expvalperbin(args[0],args[1]))[0]# 初步猜测initial_mu = 35.5初始西格玛 = 14结果 = fmin(chisquareopt, [initial_mu, initial_sigma])打印(结果)
<块引用>
优化成功终止.
当前函数值:2.010966
迭代次数:49
功能评估:95
[50.57590239 7.01857529]
顺便说一句,obslist
直方图是来自 N(50.5, 7.0)
正态分布的 1000 点随机样本.请记住,这些是我的第一行 Python 代码行,所以请不要以风格来评判我.我只是想让你了解一下问题的一般结构.
I am trying to minimize a function that outputs chi-square via scipy and find the mu,sigma,normc that provide the best fit for a Gaussian overlay.
from math import exp
from math import pi
from scipy.integrate import quad
from scipy.optimize import minimize
from scipy.stats import chisquare
import numpy as np
# guess intitial values for minimized chi-square
mu, sigma = np.mean(mydata), np.std(mydata) # mydata is my data points
normc = 1/(sigma * (2*pi)**(1/2))
gauss = lambda x: normc * exp( (-1) * (x - mu)**2 / ( 2 * (sigma **2) ) ) # Gaussian Distribution
# assume I have pre-defined bin-boundaries as a list called binbound
def expvalperbin(binbound,mu,sigma,normc):
# calculates expectation value per bin
ans = []
for index in range(len(binbound)):
if index != len(binbound)-1:
ans.append( quad( gauss, binbound[index], binbound[index+1])[0] )
return ans
expvalguess = expvalperbin(binbound,mu,sig,normc)
obsval = countperbin(binbound,mydata)
arglist = [mu,sig,norm]
def chisquareopt(obslist,explist):
return chisquare(obslist,explist)[0]
chisquareguess = chisquareopt((obsval,expvalguess), expvalguess, args=arglist)
result = minimize( chisquareopt(obsval,expvalguess), chisquareguess )
print(result)
Running this code provides me with this error:
TypeError: chisquareopt() got an unexpected keyword argument 'args'
I have a few questions:
1) How can I write a function to allow arguments to be passed through to my function chisquareopt?
2) How can I tell if scipy will optimize parameters [mu, sigma, normc] that give the minimum chi-square? How could I find these parameters from the optimization?
3) It is difficult to know if I'm making progress here or not. Am I on the right track?
EDIT: If it is relevant, I have a function that inputs [mu, sigma, normc] and outputs a list of sublists, each sublist containing a possible combination of [mu, sigma, normc] (where the outer list covers all possible combinations of parameters within specified ranges).
I've simplified your problem somewhat to give you an idea on your question 2).
First, I've hard-coded your histogram obslist
and the number of data points N
as global variables (that simplifies the function signatures a little). Second I've hard-coded the bin boundaries in expvalperbin
, assuming 9 bins with fixed width 5
and the first bin starts at 30
(so the histogram ranges from 30 to 75).
Third, I'm using optimize.fmin
(Nelder-Mead) instead of optimize.minimize
. The reason for using fmin
instead of minimize
is that the passing of additional parameters via args=(x,y)
doesn't seem to work in the sense that the additional parameters are kept at the fixed values from the very first invocation. That's not what you want: you want to optimize over mu
and sigma
simultaneously.
Given these simplifications we have the following (surely very unpythonic) script:
from math import exp
from math import pi
from scipy.integrate import quad
from scipy.optimize import fmin
from scipy.stats import chisquare
obslist = [12, 51, 144, 268, 264, 166, 75, 18, 2] # histogram, 1000 observations
N = 1000 # no. of data points
def gauss(x, mu, sigma):
return 1/(sigma * (2*pi)**(1/2)) * exp( (-1) * (x - mu)**2 / ( 2 * (sigma **2) ) )
def expvalperbin(mu, sigma):
e = []
# hard-coded bin boundaries
for i in range(30, 75, 5):
e.append(quad(gauss, i, i + 5, args=(mu, sigma))[0] * N)
return e
def chisquareopt(args):
# args[0] = mu
# args[1] = sigma
return chisquare(obslist, expvalperbin(args[0], args[1]))[0]
# initial guesses
initial_mu = 35.5
initial_sigma = 14
result = fmin(chisquareopt, [initial_mu, initial_sigma])
print(result)
Optimization terminated successfully.
Current function value: 2.010966
Iterations: 49
Function evaluations: 95
[ 50.57590239 7.01857529]
Btw., the obslist
histogram is a 1000 point random sample from a N(50.5, 7.0)
normal distribution. Remember that these are my very first Python code lines, so please don't judge me on the style. I just wanted to give you an idea about the general structure of the problem.
这篇关于如何将参数传递给其他函数(通常和通过 scipy)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!