当梯度非常远离最优解时,如何在 python 中数值估计 MLE 估计器?

数据挖掘 Python 统计数据
2021-10-05 14:26:26

我正在探索如何使用正态分布对数据集进行建模,均值和方差均定义为自变量的线性函数。

像 N ~ (f(x), g(x)) 这样的东西。

我生成一个这样的随机样本:

def draw(x):
    return norm(5 * x + 2, 3 *x + 4).rvs(1)[0]

所以我想检索 5、2 和 4 作为我的分布的参数。

我生成我的样本:

smp = np.zeros((100,2))

for i in range(0, len(smp)):
    smp[i][0] = i
    smp[i][1] = draw(i)

似然函数是:

def lh(p):
    p_loc_b0 = p[0]
    p_loc_b1 = p[1]
    p_scl_b0 = p[2]
    p_scl_b1 = p[3]

    l = 1
    for i in range(0, len(smp)):
        x = smp[i][0]
        y = smp[i][1]
        l = l * norm(p_loc_b0 + p_loc_b1 * x, p_scl_b0 + p_scl_b1 * x).pdf(y)

    return -l

因此,模型中使用的线性函数的参数在 p 4 变量向量中给出。

使用 scipy.optimize,我可以使用极低的 xtol 求解 MLE 参数,并且已经将解决​​方案作为起点:

fmin(lh, x0=[2,5,3,4], xtol=1e-35)

哪个效果不好:

Warning: Maximum number of function evaluations has been exceeded.
array([ 3.27491346,  4.69237042,  5.70317719,  3.30395462])

将 xtol 提高到更高的值没有好处。

所以我尝试使用远离真正解决方案的起始解决方案:

>>> fmin(lh, x0=[1,1,1,1], xtol=1e-8)
Optimization terminated successfully.
         Current function value: -0.000000
         Iterations: 24
         Function evaluations: 143
array([ 1.,  1.,  1.,  1.])

这让我想到:

PDF 主要集中在均值周围,并且梯度非常低,距离均值只有几个标准差,这对于数值方法来说肯定不是太好。

那么如何在梯度非常接近于零的函数中进行这种数值估计呢?

1个回答

您得到错误结果的原因有多种。首先,您应该考虑使用对数似然而不是似然。乘以许多小数存在数值问题(想象一下,如果您有数百万个样本,则必须为 lhd 乘以数百万个小数)。当您处理对数似然时,还为需要梯度的优化方法采用梯度通常更容易。一般来说,在处理优化问题时,最好有一个目标是变量的总和而不是变量的乘积。

其次,根据scipy 文档,fmin 使用的是没有收敛保证的 Nelder-Mead 单纯形算法。这意味着收敛是完全随机的,您不应该期望找到接近原始参数的参数。为了解决这个问题,我建议您使用基于梯度的方法,如随机梯度下降或 BFGS。由于您知道生成模型(rvs 是高斯分布的),您可以将似然性和对数似然写为: 方程

其中 a、b、c 和 d 分别是您的模型参数 5、2、3 和 4。然后取相对于 [a,b,c,d] 的梯度并将其输入 fmin_bfgs 的主要输入。请注意,由于方差不同,仅通过线性回归即可解决的问题现在是一个更棘手的问题。

最后,您可能还想在此处此处查看广义最小二乘法,它们讨论了您的问题并提供了几种可用的解决方案。

祝你好运!