2017-02-27 88 views
2

我想minimize经由SciPy的输出chi-square功能,找到亩,西格玛,normc提供了高斯覆盖最合适的。如何将参数传递给其他函数(通常和通过scipy)?

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) 

运行该代码为我提供了这个错误:

TypeError: chisquareopt() got an unexpected keyword argument 'args' 

我有几个问题:

1)我如何写一个函数允许参数通过传递我函数chisquareopt?

2)I如何判断SciPy的将优化参数微米,西格玛,normc]为得到最小卡方?我怎么能从优化中找到这些参数?

3)很难知道我是否在这里取得进展。我在正确的轨道上吗?

编辑:如果它是相关的,我有一个函数输入[mu,sigma,normc]并输出一个子列表,每个子列表包含[mu,sigma,normc]涵盖指定范围内的所有可能的参数组合)。

回答

3

我已经简化你的问题有点给你对你的问题的想法2)。

首先,我已经将您的直方图obslist和数据点数N硬编码为全局变量(简化了函数签名)。第二我已经硬编码的bin边界expvalperbin,假定9个箱具有固定宽度5和第一仓开始于30(所以直方图的范围从30到75)。

第三,我使用的,而不是optimize.minimizeoptimize.fmin(内尔德 - 米德)。使用fmin而不是minimize的原因是,通过args=(x,y)传递附加参数似乎不起作用,因为附加参数在第一次调用时保持在固定值。这不是你想要的:你想同时优化musigma

鉴于这些简化我们有以下的(当然非常unpythonic)脚本:

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]

顺便说一句,在obslist直方图是从N(50.5, 7.0)正态分布1000点随机抽样。请记住,这是我第一个Python代码行,所以请不要评论我的风格。我只是想给你一个关于这个问题的一般结构的想法。

+0

在函数expvalperbin中,'args =(mu,sigma))[0] * N)'是做什么的?我猜测它复制了一个(mu,sigma)的元组N次,但下标[0]让我相信我没有看到完整的图片(类似于'chisquareopt'中的参数)?至于不是pythonic,我愿意接受建议。 – mikey

+1

这和你的'ans.append(quad(gauss,binbound [index],binbound [index + 1])[0])'是一样的。但是我也将'mu'和'lambda'传递给'gauss'函数。最后,为了从必须乘以N的概率中获得预期的**计数**,观测的总数(我已经告诉过你)。 –

+0

啊,我现在看到它!感谢您的帮助。 – mikey

3

通常,这些scipy功能通过args元组值的,以你的代码不变。我应该仔细检查代码,但

minimize(myfunc, x0, args=(y,z)) 

def myfunc(x, y, z): 
    <do something> 

minimize采用可变x的电流值(标量或数组,这取决于x0样子),以及args参数,构建

args = tuple(x) + args 
myfunc(*args) 

换句话说,它将迭代变量加入args元组并将其传递给函数。因此任何中间函数定义都需要使用该模式。

为了说明,定义一个函数,它接受一个通用ARGS元组。

In [665]: from scipy.optimize import minimize 
In [666]: def myfunc(*args): 
    ...:  print(args) 
    ...:  return np.abs(args[0])**2 
    ...: 
In [667]: myfunc(1,2,3) 
(1, 2, 3) 
Out[667]: 1 
In [668]: myfunc(2,2,3) 
(2, 2, 3) 
Out[668]: 4 
In [669]: minimize(myfunc, 10, args=(2,3)) 
(array([ 10.]), 2, 3) 
(array([ 10.00000001]), 2, 3) 
(array([ 10.]), 2, 3) 
(array([ 8.99]), 2, 3) 
.... 
(array([-0.00000003]), 2, 3) 
Out[669]: 
     fun: 1.7161984122524196e-15 
hess_inv: array([[ 0.50000001]]) 
     jac: array([-0.00000007]) 
    message: 'Optimization terminated successfully.' 
    nfev: 15 
     nit: 4 
    njev: 5 
    status: 0 
    success: True 
     x: array([-0.00000004]) 

(删除了关于其被最小化的参数混乱的讨论。见对方的回答还是我的编辑历史)

+0

所以我应该创建元组(mu,sigma,normc)?或者我应该创建一个所有可能的组合(mu,sigma,normc)的元组? – mikey

+0

我已经添加了一个简单的例子。我将不得不更多地考虑组合问题。 – hpaulj

+0

我不明白'mu,sigma,normc'的功能。它们是控制其他变量('binbound')的最小化的参数,还是他们想要优化的变量(选择最佳组合)? – hpaulj