2014-02-19 33 views
4

分配到一個計數器我有一個collections.Counter對象使用不同的值的出現這樣的計數:適合在SciPy的

1:193260 
2:51794 
3:19112 
4:9250 
5:6486 

我怎麼能適應的概率分佈這一數據SciPy的? scipy.stats.expon.fit()似乎想要一個數字列表。用193260 [1] s,51794 [2]等創建一個列表似乎很浪費。是否有更優雅或更高效的方式?

+0

或許這可以幫助? http://stackoverflow.com/questions/7805552/fitting-a-histogram-with-python – Sahand

回答

1

看起來像scipy.stats.expon.fit基本上是scipy.optimize.minimize的一個小包裝,它首先創建一個函數來計算neg-log-likelihood,然後使用scipy.optimize.minimize來擬合pdf參數。

所以,我認爲你需要做的是編寫你自己的函數來計算counter對象的neg-log-likelihood,然後調用scipy.optimize.minimize你自己。

更具體地說,SciPy的定義expon '規模' 在這裏參數 http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.expon.html

所以,PDF是:

pdf(x) = 1/scale * exp (- x/scale) 

所以,對兩邊的對數,我們得到:

log_pdf(x) = - log(scale) - x/scale 

因此,您反物體中所有物品的負對數似然爲:

def neg_log_likelihood(scale): 
    total = 0.0 
    for x, count in counter.iteritems(): 
     total += (math.log(scale) + x/scale) * count 
    return total 

這是一個程序來試試。

import scipy.stats 
import scipy.optimize 
import math 
import collections 

def fit1(counter): 
    def neg_log_likelihood(scale): 
     total = 0.0 
     for x, count in counter.iteritems(): 
      total += (math.log(scale) + x/scale) * count 
     return total 

    optimize_result = scipy.optimize.minimize(neg_log_likelihood, [1.0]) 
    if not optimize_result.success: 
     raise Exception(optimize_result.message) 
    return optimize_result.x[0] 

def fit2(counter): 
    data = [] 
    # Create an array where each key is repeated as many times 
    # as the value of the counter. 
    for x, count in counter.iteritems(): 
     data += [x] * count 
    fit_result = scipy.stats.expon.fit(data, floc = 0) 
    return fit_result[-1]  

def test(): 
    c = collections.Counter() 
    c[1] = 193260 
    c[2] = 51794 
    c[3] = 19112 
    c[4] = 9250 
    c[5] = 6486 

    print "fit1 'scale' is %f " % fit1(c) 
    print "fit2 'scale' is %f " % fit2(c) 

test() 

這裏是輸出:

fit1 'scale' is 1.513437 
fit2 'scale' is 1.513438