我正在尝试使用最小函数形式scipy从正态分布中找到mu和sigma的最大似然估计。但是,极小值返回的是均值的期望值,但sigma的估计值与实际sigma相差甚远。
我定义函数llnorm,该函数返回正态分布的负对数似然性,然后从正态分布中创建均值150和标准偏差为10的随机样本,然后使用优化来尝试找到MLE。
import numpy as np
import math
import scipy.optimize as optimize
def llnorm(par, data):
n = len(data)
mu, sigma = par
ll = -np.sum(-n/2 * math.log(2*math.pi*(sigma**2)) - ((data-mu)**2)/(2 * (sigma**2)))
return ll
data = 10 * np.random.randn(100) + 150
result = optimize.minimize(llnorm, [150,10], args = (data))
即使数据均值接近150,std接近10,优化也会返回估计的sigma(接近0)的值。
答案 0 :(得分:1)
您的数学略有下降:
ll = n*math.log(2*math.pi*(sigma**2))/2 + np.sum(((data-mu)**2)/(2 * (sigma**2)))
或
ll = np.sum(math.log(2*math.pi*(sigma**2))/2 + ((data-mu)**2)/(2 * (sigma**2)))
首先我取消了-
(不是问题),但最重要的是要么将常数项保留在总和中,不要将其乘以n
,要么将其取出并将其乘以n
,...,但不能同时使用。
答案 1 :(得分:-1)
np.random.randn
创建具有方差 1(docs here)的随机高斯分布。由于您的目标是使std为10,因此您需要乘以10 * 10
而不是
import numpy as np
import math
import scipy.optimize as optimize
def llnorm(par, data):
n = len(data)
mu, sigma = par
ll = -np.sum(-n/2 * math.log(2*math.pi*(sigma**2)) - ((data-mu)**2)/(2 * (sigma**2)))
return ll
data = 10 * 10 * np.random.randn(100) + 150
result = optimize.minimize(llnorm, [150,10], args = (data))
print(result)
这给了我:
fun: 36328.17002555693
hess_inv: array([[ 0.96235834, -0.32116447],
[-0.32116447, 0.10879383]])
jac: array([0., 0.])
message: 'Optimization terminated successfully.'
nfev: 44
nit: 8
njev: 11
status: 0
success: True
x: array([166.27014352, 9.15113937])
编辑:看来〜9的输出纯粹是巧合。还有其他事情需要调查