Added hessian_nlogps for more robust estimation of the covariance.

master
Per.Andreas.Brodtkorb 14 years ago
parent 0177714a8d
commit 39d93a8f78

@ -2031,6 +2031,64 @@ class rv_continuous(rv_generic):
else:
N = len(x)
return self._nnlf(x, *args) + N*log(scale)
def hessian_nlogps(self, theta, data, eps=None):
''' approximate hessian of nlogps where theta are the parameters (including loc and scale)
'''
#Nd = len(x)
np = len(theta)
# pab 07.01.2001: Always choose the stepsize h so that
# it is an exactly representable number.
# This is important when calculating numerical derivatives and is
# accomplished by the following.
if eps == None:
eps = (floatinfo.machar.eps) ** 0.4
#xmin = floatinfo.machar.xmin
#myfun = lambda y: max(y,100.0*log(xmin)) #% trick to avoid log of zero
delta = (eps + 2.0) - 2.0
delta2 = delta ** 2.0
# % Approximate 1/(nE( (d L(x|theta)/dtheta)^2)) with
# % 1/(d^2 L(theta|x)/dtheta^2)
# % using central differences
LL = self.nlogps(theta, data)
H = zeros((np, np)) #%% Hessian matrix
theta = tuple(theta)
for ix in xrange(np):
sparam = list(theta)
sparam[ix] = theta[ix] + delta
fp = self.nlogps(sparam, data)
#fp = sum(myfun(x))
sparam[ix] = theta[ix] - delta
fm = self.nlogps(sparam, data)
#fm = sum(myfun(x))
H[ix, ix] = (fp - 2 * LL + fm) / delta2
for iy in range(ix + 1, np):
sparam[ix] = theta[ix] + delta
sparam[iy] = theta[iy] + delta
fpp = self.nlogps(sparam, data)
#fpp = sum(myfun(x))
sparam[iy] = theta[iy] - delta
fpm = self.nlogps(sparam, data)
#fpm = sum(myfun(x))
sparam[ix] = theta[ix] - delta
fmm = self.nlogps(sparam, data)
#fmm = sum(myfun(x));
sparam[iy] = theta[iy] + delta
fmp = self.nlogps(sparam, data)
#fmp = sum(myfun(x))
H[ix, iy] = ((fpp + fmm) - (fmp + fpm)) / (4. * delta2)
H[iy, ix] = H[ix, iy]
sparam[iy] = theta[iy];
# invert the Hessian matrix (i.e. invert the observed information number)
#pcov = -pinv(H);
return -H
def hessian_nnlf(self, theta, data, eps=None):
''' approximate hessian of nnlf where theta are the parameters (including loc and scale)
'''

@ -192,7 +192,6 @@ class Profile(object):
Examples
--------
# MLE
>>> import numpy as np
>>> import wafo.stats as ws
>>> R = ws.weibull_min.rvs(1,size=100);
>>> phat = FitDistribution(ws.weibull_min, R, 1, scale=1, floc=0.0)
@ -364,6 +363,10 @@ class Profile(object):
pcov = self.fit_dist.par_cov[i_notfixed, :][:, i_notfixed]
pvar = sum(numpy.dot(drl, pcov) * drl)
if pvar<0:
pvar = -pvar*2
elif numpy.isnan(pvar):
pvar = p_opt*0.5
p_crit = -norm_ppf(self.alpha / 2.0) * sqrt(numpy.ravel(pvar)) * 1.5
if self.pmin == None:
self.pmin = p_opt - 5.0 * p_crit
@ -515,7 +518,6 @@ class FitDistribution(rv_frozen):
--------
Estimate distribution parameters for weibull_min distribution.
>>> import wafo.stats as ws
>>> import numpy as np
>>> R = ws.weibull_min.rvs(1,size=100);
>>> phat = FitDistribution(ws.weibull_min, R, 1, scale=1, floc=0.0)
@ -719,7 +721,8 @@ class FitDistribution(rv_frozen):
'''Compute covariance
'''
somefixed = (self.par_fix != None) and any(isfinite(self.par_fix))
H = numpy.asmatrix(self.dist.hessian_nnlf(self.par, self.data))
H1 = numpy.asmatrix(self.dist.hessian_nnlf(self.par, self.data))
H = numpy.asmatrix(self.dist.hessian_nlogps(self.par, self.data))
self.H = H
try:
if somefixed:
@ -798,7 +801,6 @@ class FitDistribution(rv_frozen):
Examples
--------
# MLE
>>> import numpy as np
>>> import wafo.stats as ws
>>> R = ws.weibull_min.rvs(1,size=100);
>>> phat = FitDistribution(ws.weibull_min, R, 1, scale=1, floc=0.0)
@ -1006,13 +1008,15 @@ class FitDistribution(rv_frozen):
def main():
# import wafo.stats as ws
# R = ws.weibull_min.rvs(1,size=100);
# phat = FitDistribution(ws.weibull_min, R, 1, scale=1, floc=0.0)
#
import doctest
doctest.testmod()
def test1():
import wafo.stats as ws
R = ws.weibull_min.rvs(1,size=100);
phat = FitDistribution(ws.weibull_min, R, method='mps')
# # Better CI for phat.par[i=0]
# Lp1 = Profile(phat, i=0)
Lp1 = Profile(phat, i=1)
# Lp2 = Profile(phat, i=2)
# SF = 1./990
# x = phat.isf(SF)
@ -1029,8 +1033,7 @@ def main():
# pass
import doctest
doctest.testmod()
# _WAFODIST = ppimport('wafo.stats.distributions')
@ -1080,4 +1083,5 @@ def main():
# lp = pht.profile()
if __name__ == '__main__':
test1()
main()

Loading…
Cancel
Save