Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python scipy未进行优化并返回“;由于精度损失,不一定达到预期误差”;_Python_Math_Optimization_Scipy - Fatal编程技术网

Python scipy未进行优化并返回“;由于精度损失,不一定达到预期误差”;

Python scipy未进行优化并返回“;由于精度损失,不一定达到预期误差”;,python,math,optimization,scipy,Python,Math,Optimization,Scipy,下面的代码试图最小化对数似然函数 #!/usr/bin/python import math import random import numpy as np from scipy.optimize import minimize def loglikelihood(params, data): (mu, alpha, beta) = params tlist = np.array(data) r = np.zeros(len(tlist)) for i in

下面的代码试图最小化对数似然函数

#!/usr/bin/python
import math
import random
import numpy as np
from scipy.optimize import minimize

def loglikelihood(params, data):
    (mu, alpha, beta) = params
    tlist = np.array(data)
    r = np.zeros(len(tlist))
    for i in xrange(1,len(tlist)):
        r[i] = math.exp(-beta*(tlist[i]-tlist[i-1]))*(1+r[i-1])
    loglik  = -tlist[-1]*mu
    loglik = loglik+alpha/beta*sum(np.exp(-beta*(tlist[-1]-tlist))-1)
    loglik = loglik+np.sum(np.log(mu+alpha*r))
    return -loglik

atimes = [ 148.98894201,  149.70253172,  151.13717804,  160.35968355,
        160.98322609,  161.21331798,  163.60755544,  163.68994973,
        164.26131871,  228.79436067]
a= 0.01
alpha = 0.5
beta = 0.6
print loglikelihood((a, alpha, beta), atimes)

res = minimize(loglikelihood, (0.01, 0.1,0.1), method = 'BFGS',args = (atimes,))
print res
它给了我

28.3136498357
./test.py:17: RuntimeWarning: invalid value encountered in log
  loglik = loglik+np.sum(np.log(mu+alpha*r))
   status: 2
  success: False
     njev: 14
     nfev: 72
 hess_inv: array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]])
      fun: 32.131359359964378
        x: array([ 0.01,  0.1 ,  0.1 ])
  message: 'Desired error not necessarily achieved due to precision loss.'
      jac: array([ -2.8051672 ,  13.06962156, -48.97879982])

请注意,它根本无法优化参数,最小值32大于28,这是使用a=0.01、alpha=0.5、beta=0.6得到的结果。通过选择更好的初始猜测可能可以避免这个问题,但如果是这样,我如何能够自动做到这一点?

我复制了您的示例并尝试了一点。看起来如果您坚持使用BFGS解算器,经过几次迭代,
mu+alpha*r
将有一些负数,这就是您获得RuntimeWarning的原因

我能想到的最简单的解决方法是切换到Nelder Mead solver

res = minimize(loglikelihood, (0.01, 0.1,0.1), method = 'Nelder-Mead',args = (atimes,))
它会给你这个结果:

28.3136498357
  status: 0
    nfev: 159
 success: True
     fun: 27.982451280648817
       x: array([ 0.01410906,  0.68346023,  0.90837568])
 message: 'Optimization terminated successfully.'
     nit: 92

注意log()函数的负值,解决它们并通过添加惩罚告诉优化器它们是错误的:

#!/usr/bin/python
import math
import random
import numpy as np
from scipy.optimize import minimize

def loglikelihood(params, data):
    (mu, alpha, beta) = params
    tlist = np.array(data)
    r = np.zeros(len(tlist))
    for i in xrange(1,len(tlist)):
        r[i] = math.exp(-beta*(tlist[i]-tlist[i-1]))*(1+r[i-1])
    loglik = -tlist[-1]*mu
    loglik += alpha/beta*sum(np.exp(-beta*(tlist[-1]-tlist))-1)
    argument = mu + alpha * r
    limit = 1e-6
    if np.min(argument) < limit:
        # add a penalty for too small argument of log
        loglik += np.sum(np.minimum(0.0, argument - limit)) / limit
        # keep argument of log above the limit
        argument = np.maximum(argument, limit)
    loglik += np.sum(np.log(argument))
    return -loglik

atimes = [ 148.98894201,  149.70253172,  151.13717804,  160.35968355,
        160.98322609,  161.21331798,  163.60755544,  163.68994973,
        164.26131871,  228.79436067]
a= 0.01
alpha = 0.5
beta = 0.6
print loglikelihood((a, alpha, beta), atimes)

res = minimize(loglikelihood, (0.01, 0.1,0.1), method = 'BFGS',args = (atimes,))
print res
#/usr/bin/python
输入数学
随机输入
将numpy作为np导入
从scipy.optimize导入最小化
def日志可能性(参数、数据):
(μ,α,β)=参数
tlist=np.array(数据)
r=np.零(len(tlist))
对于x范围内的i(1,len(tlist)):
r[i]=math.exp(-beta*(tlist[i]-tlist[i-1])*(1+r[i-1])
loglik=-tlist[-1]*mu
loglik+=alpha/beta*和(np.exp(-beta*(tlist[-1]-tlist))-1)
参数=mu+alpha*r
极限=1e-6
如果np.min(参数)<限制:
#为log参数太小添加惩罚
loglik+=np.sum(np.minimum(0.0,参数限制))/limit
#保持log的参数高于限制
参数=np.最大值(参数,极限)
loglik+=np.sum(np.log(参数))
返回-loglik
时间=[148.988942011949.70253172151.13717804160.35968355,
160.98322609,  161.21331798,  163.60755544,  163.68994973,
164.26131871,  228.79436067]
a=0.01
α=0.5
β=0.6
打印日志可能性((a、alpha、beta)、时间)
res=最小化(对数似然,(0.01,0.1,0.1),方法='BFGS',参数=(时间,)
打印资源

面对同样的警告,我通过重写log likelion函数来解决它,将
log(params)
log(data)
作为参数,而不是参数和数据

因此,如果可能的话,我避免在似然函数或雅可比矩阵中使用
np.log()

另一个解决方案(对我有效)是将函数(和渐变)缩放到接近0的值。例如,当我必须评估60k点的对数可能性时,我的问题出现了。这意味着我的对数可能性是一个非常大的数字。从概念上讲,对数似然是一个非常尖峰的函数

梯度开始时很大(为了爬上这座尖峰山),然后变得中等小,但决不能小于BGFS例程中的默认
gtol
参数(这是所有梯度在终止时必须低于的阈值)。而且,在这个时候,我基本上得到了正确的值(我使用生成的数据,所以我知道了真实的值)

发生的事情是,我的梯度大约为60k*
平均个体梯度值
,即使
平均个体梯度值
很小,比如说小于1e-8,60k*1e-8>
gtol
。因此,即使我已经找到了解决方案,我也从未达到阈值


从概念上讲,由于这座尖峰山的存在,该算法进行了小步运算,但跨过了真正的最小值,从未达到
平均个体梯度。我认为您希望最大化LL,而不是最小化它。如果你在最小化平方和,你就是在最大化LL。@MikeDunlavey是的。请注意,该函数返回处理此问题的
-loglik
。@felix只是一句话-我曾经遇到过一个与您的问题症状相同的问题,但原因完全不同。原来我的梯度函数中有一个bug,所以当我通过
jac
参数在例程中传递它时,例程无法工作。错误是隐晦的,只有在重新检查我的代码后,我才发现了错误。也就是说,下面使用
Nelder Mead
的答案确实很有帮助,因为它可以在没有梯度的情况下进行优化,并为我提供了正确的答案,帮助我意识到问题在于梯度函数中的缺陷。有人能解释一下警告所指的精度损失是什么吗?我发现它非常模糊,似乎这里有一个答案,实际上,对于参数值具有完全不同的尺度的情况来说,这听起来是一个非常好的主意,就像我的情况一样。谢谢谢谢分享你解决这个问题的方法。然而,我仍然在想,为什么不重新缩放它就不能收敛?如果我理解正确,您的解决方案就相当于扩展gtol。为什么即使有真正的对数可能性,它也不能达到要求的精度?谢谢!为什么/何时内尔德·米德会是比BGFS更好的选择?