scipy 修正方案优化结构最小化

d6kp6zgx  于 2022-11-09  发布在  其他
关注(0)|答案(2)|浏览(161)

我无法理解scipy.optimize的工作原理。
具体来说,我正在尝试使用optimize.minimize()来找到一个函数的最小值,该函数根据二项分布计算数据集的负似然。我在网上和书上读了很多东西,但我仍然无法找出我做错了什么,我卡住了!这是我的代码

from scipy.stats import binom
from scipy.optimize import minimize
import numpy as np
import plotly.express as px
import pandas as pd

n=20
p=0.45

## data

d1 = binom.rvs(n, p, size=200)

def likelihood(data, n, p):
    return -sum(binom.logpmf(data, n, p))

def opt_like(parameters, constants):
    p = parameters
    n, data = constants[0], constants[1]
    return likelihood(data, n, p)

minimize(opt_like, 0.5, args=[n, d1])

我希望它是清楚的。你知道是什么原因导致优化失败吗?
注记
参数和超参数是分开的,函数的结果和输入向量的形状是一样的(都是标量),函数的结果和输入向量的形状是一样的。

xtfmy6hx

xtfmy6hx1#

问题是你的logpmf函数相当敏感,它在很大的范围内都是平坦的(它的导数也是如此),而且很快就变成了巨大的值,甚至是NaN。
另外,很明显,你的参数应该在0和1之间。大多数方法,在一次迭代中,会很快地把你的p发送到-1000或+1000,这对概率来说是毫无意义的,并很快地把这个过程陷入一个结果都是相同的循环(nan)。
所以,你需要选择一个接受边界的方法,并且利用你的函数导数的单调性。
比如说

minimize(opt_like, 0.5, args=[n, d1], bounds=[(0,1)], method='SLSQP')
sz81bmfz

sz81bmfz2#

binom.logpmf将给予概率密度函数的对数,而不是数据的对数似然。请改用binom.nnlf

from scipy.stats import binom
from scipy.optimize import minimize
import numpy as np

n=20
p=0.45

## data

d1 = binom.rvs(n, p, size=200)

def likelihood(p, n, data):
    return binom.nnlf((n, p, 0), data)

minimize(likelihood, 0.5, args=(n, d1))

结果是:

fun: 436.57474309015436
 hess_inv: array([[6.15202944e-05]])
      jac: array([0.])
  message: 'Optimization terminated successfully.'
     nfev: 17
      nit: 4
     njev: 7
   status: 0
  success: True
        x: array([0.43749999])

(最佳p = 0.43749999)
或者使用scipy.stats.fit

>>> stats.fit(binom, d1, bounds={"n": (1, 100), "p": (0, 1)})

  params: FitParams(n=18.0, p=0.48611110564996524, loc=0.0)
 success: True
 message: 'Optimization terminated successfully.'

相关问题