当前位置: 首页 > 面试题库 >

scipy未优化,并返回“由于精度损失而不一定实现所需的误差”

鲜于阳
2023-03-14
问题内容

我有以下代码尝试最小化对数似然函数。

#!/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解算器。

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


 类似资料:
  • 问题陈述: 编写一个方法whatTime,它采用int,seconds,表示从某一天午夜开始的秒数,并返回一个格式为“:”的字符串。此处,表示自午夜以来的完整小时数,表示自上一完整小时结束以来的完整分钟数,以及自上一完整分钟结束以来的秒数。和中的每一个都应该是整数,没有额外的前导0。因此,如果秒为0,则应返回“0:0:0”,而如果秒为3661,则应返回“1:1:1” 我的算法: 以下是我的算法对输

  • 问题内容: 我有一个关于精度损失的问题 我的任务是将数字打印为字符串 例如0.2 * 7 = 1.4000000000000001; 0.0000014 / 10 = 1.3999999999999998E-7 如何解决这个问题? UPD :主要问题是 字符串 输出格式。我不担心丢失约0.00000001的值。现在,我将其解析为String.format(“%f”,value),但我认为这不是一个

  • 有人知道为什么。

  • 我是java初学者,遇到过这个错误。 但是错误指向了+号,这是怎么了?上面写着发现:双倍。但我希望我的输出是双倍。但它说作为必需的int。

  • 我有下面的抓耳挠腮,演示在和这里 两个版本中的简单编译类中都会发生相同的情况 尽管17警告不再需要 JLS在第5.1节中说明了这一点。2. 14年,在项目清单之后,它包含以下内容 根据我的阅读,这是实现中的错误?我发现执行此转换的唯一可靠方法是。

  • Oracle(和其他一些DB)有一个数据类型NUMBER,可以选择设置精度和规模。 假设以下查询: 如果上述查询中的两个字段都定义为NUMBER(12,0),则JDBC中的结果确实是agent_code,但在AVG(opening_amt)上,精度和刻度都返回0(通过java.sql.ResultSetMetaData.get精度(col)和java.sql.ResultSetMetaData.g