假设我有一个数组:adata=array([0.5, 1.,2.,3.,6.,10.])
并且我想计算这个数组的 Weibull 分布的对数似然,给定参数[5.,1.5]
和[5.1,1.6]
。我从来没有想过我需要为这个任务编写自己的 Weibull 概率密度函数,因为它已经在scipy.stat.distributions
. 所以,这应该这样做:
from scipy import stats
from numpy import *
adata=array([0.5, 1.,2.,3.,6.,10.])
def wb2LL(p, x): #log-likelihood of 2 parameter Weibull distribution
return sum(log(stats.weibull_min.pdf(x, p[1], 0., p[0])), axis=1)
和:
>>> wb2LL(array([[5.,1.5],[5.1,1.6]]).T[...,newaxis], adata)
array([-14.43743911, -14.68835298])
或者我重新发明轮子,写一个新的 Weibull pdf 函数,比如:
wbp=lambda p, x: p[1]/p[0]*((x/p[0])**(p[1]-1))*exp(-((x/p[0])**p[1]))
def wb2LL1(p, x): #log-likelihood of 2 paramter Weibull
return sum(log(wbp(p,x)), axis=1)
和:
>>> wb2LL1(array([[5.,1.5],[5.1,1.6]]).T[...,newaxis], adata)
array([-14.43743911, -14.68835298])
诚然,我总是理所当然地认为,如果某些东西已经存在scipy
,那么它应该得到很好的优化,并且重新发明轮子很少会使它变得更快。但惊喜出现了:如果 I timeit
, 100000 次调用wb2LL1(array([[5.,1.5],[5.1,1.6]])[...,newaxis], adata)
需要 2.156s 而 100000 次调用wb2LL(array([[5.,1.5],[5.1,1.6]])[...,newaxis], adata)
需要 5.219s,则内置stats.weibull_min.pdf()
速度会慢两倍以上。
检查源代码python_path/sitepackage/scipy/stat/distributions.py
并没有提供一个简单的答案,至少对我来说是这样。如果有的话,我希望它stats.weibull_min.pdf()
几乎和wbp()
.
相关源码:2999-3033行:
class frechet_r_gen(rv_continuous):
"""A Frechet right (or Weibull minimum) continuous random variable.
%(before_notes)s
See Also
--------
weibull_min : The same distribution as `frechet_r`.
frechet_l, weibull_max
Notes
-----
The probability density function for `frechet_r` is::
frechet_r.pdf(x, c) = c * x**(c-1) * exp(-x**c)
for ``x > 0``, ``c > 0``.
%(example)s
"""
def _pdf(self, x, c):
return c*pow(x,c-1)*exp(-pow(x,c))
def _logpdf(self, x, c):
return log(c) + (c-1)*log(x) - pow(x,c)
def _cdf(self, x, c):
return -expm1(-pow(x,c))
def _ppf(self, q, c):
return pow(-log1p(-q),1.0/c)
def _munp(self, n, c):
return special.gamma(1.0+n*1.0/c)
def _entropy(self, c):
return -_EULER / c - log(c) + _EULER + 1
frechet_r = frechet_r_gen(a=0.0, name='frechet_r', shapes='c')
weibull_min = frechet_r_gen(a=0.0, name='weibull_min', shapes='c')
所以,问题是:stats.weibull_min.pdf()
真的慢吗?如果有,怎么来的?