2017-02-27 49 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

相關問題