我有一个collections.Counter对象,其中包含不同值的出现次数,如下所示:
1:193260 2:51794 3:19112 4:9250 5:6486
如何在scipy中为这些数据拟合概率分布? scipy.stats.expon.fit()似乎想要一个数字列表.使用193260 [1] s,51794 [2]等创建列表似乎很浪费.是否有更优雅或更有效的方法?
解决方法
看起来像scipy.stats.expon.fit基本上是scipy.optimize.minimize上的一个小包装器,它首先创建一个计算neg-log-likelihood的函数,然后使用scipy.optimize.minimize来拟合pdf参数.
所以,我认为你需要做的是编写自己的函数来计算counter对象的neg-log-likelihood,然后自己调用scipy.optimize.minimize.
更具体地说,scipy在这里定义了expon’scale’参数
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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。