如何将参数传递给其他函数(通常并通过scipy)? [英] How do I pass through arguments to other functions (generally and via scipy)?

查看:131
本文介绍了如何将参数传递给其他函数(通常并通过scipy)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试最小化一个输出 chi-通过scipy平方,找到最适合高斯覆盖的mu,sigma,normc.

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'

我有几个问题:

1)我如何编写一个函数以允许将参数传递给我的函数chisquareopt?

1) How can I write a function to allow arguments to be passed through to my function chisquareopt?

2)如何确定scipy是否可以优化给出最小卡方的参数[mu,sigma,normc]?如何从优化中找到这些参数?

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)很难知道我是否在这里取得了进步.我在正确的轨道上吗?

3) It is difficult to know if I'm making progress here or not. Am I on the right track?

如果相关,我有一个输入[mu,sigma,normc]并输出子列表列表的函数,每个子列表包含[mu,sigma,normc]的可能组合(其中外部列表​​覆盖在指定范围内的所有可能参数组合.)

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).

推荐答案

我已经简化了您的问题,以使您对问题2有所了解.

I've simplified your problem somewhat to give you an idea on your question 2).

首先,我已经将您的直方图obslist和数据点N的数量硬编码为全局变量(这稍微简化了函数签名).其次,我在expvalperbin中硬编码了bin边界,假设9个bin的宽度固定为5,第一个bin从30开始(因此直方图的范围是30到75).

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).

第三,我使用的是optimize.fmin(Nelder-Mead)而不是optimize.minimize.使用fmin而不是minimize的原因是,通过args=(x,y)传递附加参数在从第一次调用起就将附加参数保持为固定值的意义上似乎不起作用.那不是您想要的:您希望同时优化musigma.

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.

鉴于这些简化,我们有以下脚本(肯定是非Python的):

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.

当前功能值:2.010966

Current function value: 2.010966

迭代次数:49

功能评估:95

[50.57590239 7.01857529]

[ 50.57590239 7.01857529]

顺便说一句,obslist直方图是来自N(50.5, 7.0)正态分布的1000点随机样本.请记住,这些是我的第一个Python代码行,所以请不要以风格来评判我.我只是想向您介绍问题的一般结构.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆