【问题标题】:scipy minimize returns initial valuescipy 最小化返回初始值
【发布时间】:2017-11-02 04:30:50
【问题描述】:

我正在尝试使用 scipy.minimize 执行简单的最小化(模拟最大似然的基本示例)。由于某种原因,它只返回初始值。我做错了什么?

这是我的代码:

import numpy as np
from scipy.optimize import minimize

# Simulated likelihood function
# Arguments:
# theta: vector representing probabilities
# sims: vector representing uniform simulated data, e.g. [0.43, 0.11, 0.02, 0.97, 0.77]
# dataCounts: vector representing counts of actual data, e.g. [4, 10, 7]
def simLogLikelihood(theta, sims, dataCounts):

        # Categorise sims using theta
        simCounts = np.bincount(theta.cumsum().searchsorted(sims))

        # Calculate probabilities using simulated data
        simProbs = simCounts/simCounts.sum()
        # Calculate likelihood using simulated probabilities and actual data
        logLikelihood = (dataCounts*np.log(simProbs)).sum()

        return -logLikelihood


# Set seed
np.random.seed(121)

# Generate 'true' data
trueTheta = np.array([0.1, 0.4, 0.5])
dataCounts = np.bincount(np.random.choice([0, 1, 2], 1000, p=trueTheta))

# Generate simulated data (random draws from [0, 1))
sims = np.random.random(1000)

# Choose theta to maximise likelihood
thetaStart = np.array([0.33, 0.33, 0.34])
bnds = ((0, 1), (0, 1), (0, 1))
cons = ({'type': 'eq', 'fun': lambda x:  x.sum() - 1.0})

result = minimize(simLogLikelihood, x0=thetaStart, args=(sims, dataCounts), method='SLSQP', bounds=bnds, constraints=cons)

bnds 中的界限反映了概率需要介于 0 和 1 之间的事实。cons 中的约束是概率的总和必须为 1。)

如果我运行这段代码,result 包含:

     fun: 1094.7593617864004
     jac: array([ 0.,  0.,  0.])
 message: 'Optimization terminated successfully.'
    nfev: 5
     nit: 1
    njev: 1
  status: 0
 success: True
       x: array([ 0.33,  0.33,  0.34])

所以它只进行一次迭代并返回我开始使用的概率向量。但是很容易找到另一个目标较低的概率向量,例如[0.1, 0.4, 0.5]。出了什么问题?

【问题讨论】:

  • 感谢 sascha 注意到我对 numpy 而不是 scipy 的错误引用。这些已得到纠正。

标签: python numpy scipy minimization


【解决方案1】:

您的优化问题看起来很不顺利(可能是因为np.bincount(),但我不会深入探讨),这对于那里的大多数优化器来说确实是一件坏事。由于您也有约束,因此您只剩下 2 个优化器(SLSQP、COBYLA),它们都假设平滑。

添加类似的打印:

print(theta, -logLikelihood)

simLogLikelihood 最后向您展示,在数值微分期间(因为您没有提供梯度),scipy 正在尝试一些小的扰动,但目标根本没有改变(不平滑)!

[ 0.33  0.33  0.34] 1094.75936179
[ 0.33  0.33  0.34] 1094.75936179
[ 0.33000001  0.33        0.34      ] 1094.75936179
[ 0.33        0.33000001  0.34      ] 1094.75936179
[ 0.33        0.33        0.34000001] 1094.75936179
     fun: 1094.7593617864004
     jac: array([ 0.,  0.,  0.])
 message: 'Optimization terminated successfully.'
    nfev: 5
     nit: 1
    njev: 1
  status: 0
 success: True
       x: array([ 0.33,  0.33,  0.34])

虽然可以调整 num-diff 以采取更大的步骤,但我认为您的问题不适合这里!

快速演示(不推荐):

result = minimize(simLogLikelihood, x0=thetaStart, args=(sims, dataCounts),
              method='SLSQP', bounds=bnds, constraints=cons, options={'eps': 1e-2})
                                                             # much bigger num-diff steps

输出:

[ 0.  0.  1.] inf
[ 0.21587719  0.2695045   0.51461833] 1013.80776084
[ 0.23010601  0.28726799  0.48262602] 1012.05516321
[ 0.23627513  0.29496961  0.46875527] 1010.48916647
[ 0.2386537   0.29793905  0.46340726] 1010.13774627
[ 0.23957593  0.29909039  0.46133369] 1009.0850268
[ 0.2397671   0.29932904  0.46090387] 1008.96044271
[ 0.23981532  0.29938924  0.46079545] 1008.96044271
[ 0.23983943  0.29941934  0.46074124] 1008.96044271
[ 0.23985149  0.29943439  0.46071414] 1008.96044271
[ 0.23985751  0.29944192  0.46070058] 1008.96044271
     fun: 1008.960442706361
     jac: array([ 947.81880269,  -52.71300484,    0.        ])
 message: 'Optimization terminated successfully.'
    nfev: 44
     nit: 6
    njev: 5
  status: 0
 success: True
       x: array([ 0.23985751,  0.29944192,  0.46070058])

您会看到,在某些情况下,您的函数会返回非有限值。也有很糟糕的事情!

所以我强烈建议尝试制定一些平滑的东西,而不是调整优化器!

【讨论】:

    猜你喜欢
    • 2019-07-02
    • 2019-12-16
    • 2021-01-29
    • 2020-11-26
    • 2015-06-09
    • 2013-07-30
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多