Python 的约束 MLE
Constrained MLE with Python
我正在使用 Python 进行 MLE 实现。我的对数似然函数有 5 个参数要估计,其中两个参数必须介于 0 和 1 之间。我可以使用 statsmodels 包中的 GenericLikelihoodModel 模块实现 MLE,但我不知道如何使用约束来执行此操作。
具体来说,我的负对数似然函数是
def ekop_ll(bs,alpha,mu,sigma,epsilon_b,epsilon_s):
ll=[]
for bsi in bs:
b=bsi[0]
s=bsi[1]
part1 = (1-alpha)*stats.poisson.pmf(b,epsilon_b)*stats.poisson.pmf(s,epsilon_s)
part2 = alpha*sigma*stats.poisson.pmf(b,epsilon_b)*stats.poisson.pmf(s,mu+epsilon_s)
part3 = alpha*(1-sigma)*stats.poisson.pmf(b,mu+epsilon_b)*stats.poisson.pmf(s,epsilon_s)
li = part1+part2+part3
if part1+part2+part3 == 0:
li = 10**(-100)
lli = np.log(li)
ll.append(lli)
llsum = -sum(ll)
return llsum
并且 MLE 优化 class 是
class ekop(GenericLikelihoodModel):
def __init__(self,endog,exog=None,**kwds):
if exog is None:
exog = np.zeros_like(endog)
super(ekop,self).__init__(endog,exog,**kwds)
def nloglikeobs(self,params):
alpha = params[0]
mu = params[1]
sigma = params[2]
epsilon_b = params[3]
epsilon_s = params[4]
ll = ekop_ll(self.endog,alpha=alpha,mu=mu,sigma=sigma,epsilon_b=epsilon_b,epsilon_s=epsilon_s)
return ll
def fit(self, start_params=None, maxiter=10000, maxfun=5000, **kwds):
if start_params == None:
# Reasonable starting values
alpha_default = 0.5
mu_default = np.mean(self.endog)
sigma_default = 0.5
epsilon_b_default = np.mean(self.endog)
epsilon_s_default = np.mean(self.endog)
start_params =[alpha_default,mu_default,sigma_default,epsilon_b_default,epsilon_s_default]
return super(ekop, self).fit(start_params=start_params,
maxiter=maxiter, maxfun=maxfun,
**kwds)
主要是
if __name__ == '__main__':
bs = #my data#
mod = ekop(bs)
res = mod.fit()
我不知道如何修改我的代码以合并约束。我希望 alpha 和 sigma 介于 0 和 1 之间。
恕我直言,这是一个数学问题,简单的答案是您应该改造您的问题。
要具体解决该问题 - 您应该创建一个从原始模型派生的特例模型,并在其中定义固有的约束。然后为特例模型计算的 MLE 将为您提供您正在寻找的估计。
但是 - 对于具有约束的派生模型,估计会膨胀,而不是对于一般情况模型,因为在原始模型中两个参数不受约束。
实际上,您将用于参数估计的任何方法,如 MCMC、人工神经网络、基于牛顿的迭代方法以及其他方法,它们都将为您提供对派生模型和约束模型的估计。
获得满足约束的内部解的一种常见方法是转换参数,使优化不受约束。
例如:开区间 (0, 1) 内的约束可以使用 Logit 函数进行转换,例如此处使用:
https://github.com/statsmodels/statsmodels/blob/master/statsmodels/miscmodels/count.py#L243
我们可以使用 mulinomial logit 计算概率,参数在 (0, 1) 中并且加起来为 1。
在广义线性模型中,我们使用 link 函数对预测均值施加类似的限制,请参阅 statsmodels/genmod/families/links.py.
如果约束可以绑定,那么这行不通。 Scipy 具有约束优化器,但尚未连接到统计模型 LikelihoodModel 类。
相关:scipy 有一个全局优化器 basinhopping,如果有多个局部最小值,它工作得很好,它连接到 LikelihoodModels,可以使用 fit 中的方法参数进行选择。
确实这是一道数学题而不是编程题。我设法通过使用约束转换参数来解决这个问题,即alpha 和 sigma 到 alpha_hat 和 sigma_hat,
alpha = 1/(1+np.exp(-alpha_hat))
sigma = 1/(1+np.exp(-sigma_hat))
以便我们可以不受限制地估计 alpha_hat 和 sigma_hat。
我正在使用 Python 进行 MLE 实现。我的对数似然函数有 5 个参数要估计,其中两个参数必须介于 0 和 1 之间。我可以使用 statsmodels 包中的 GenericLikelihoodModel 模块实现 MLE,但我不知道如何使用约束来执行此操作。 具体来说,我的负对数似然函数是
def ekop_ll(bs,alpha,mu,sigma,epsilon_b,epsilon_s):
ll=[]
for bsi in bs:
b=bsi[0]
s=bsi[1]
part1 = (1-alpha)*stats.poisson.pmf(b,epsilon_b)*stats.poisson.pmf(s,epsilon_s)
part2 = alpha*sigma*stats.poisson.pmf(b,epsilon_b)*stats.poisson.pmf(s,mu+epsilon_s)
part3 = alpha*(1-sigma)*stats.poisson.pmf(b,mu+epsilon_b)*stats.poisson.pmf(s,epsilon_s)
li = part1+part2+part3
if part1+part2+part3 == 0:
li = 10**(-100)
lli = np.log(li)
ll.append(lli)
llsum = -sum(ll)
return llsum
并且 MLE 优化 class 是
class ekop(GenericLikelihoodModel):
def __init__(self,endog,exog=None,**kwds):
if exog is None:
exog = np.zeros_like(endog)
super(ekop,self).__init__(endog,exog,**kwds)
def nloglikeobs(self,params):
alpha = params[0]
mu = params[1]
sigma = params[2]
epsilon_b = params[3]
epsilon_s = params[4]
ll = ekop_ll(self.endog,alpha=alpha,mu=mu,sigma=sigma,epsilon_b=epsilon_b,epsilon_s=epsilon_s)
return ll
def fit(self, start_params=None, maxiter=10000, maxfun=5000, **kwds):
if start_params == None:
# Reasonable starting values
alpha_default = 0.5
mu_default = np.mean(self.endog)
sigma_default = 0.5
epsilon_b_default = np.mean(self.endog)
epsilon_s_default = np.mean(self.endog)
start_params =[alpha_default,mu_default,sigma_default,epsilon_b_default,epsilon_s_default]
return super(ekop, self).fit(start_params=start_params,
maxiter=maxiter, maxfun=maxfun,
**kwds)
主要是
if __name__ == '__main__':
bs = #my data#
mod = ekop(bs)
res = mod.fit()
我不知道如何修改我的代码以合并约束。我希望 alpha 和 sigma 介于 0 和 1 之间。
恕我直言,这是一个数学问题,简单的答案是您应该改造您的问题。
要具体解决该问题 - 您应该创建一个从原始模型派生的特例模型,并在其中定义固有的约束。然后为特例模型计算的 MLE 将为您提供您正在寻找的估计。
但是 - 对于具有约束的派生模型,估计会膨胀,而不是对于一般情况模型,因为在原始模型中两个参数不受约束。
实际上,您将用于参数估计的任何方法,如 MCMC、人工神经网络、基于牛顿的迭代方法以及其他方法,它们都将为您提供对派生模型和约束模型的估计。
获得满足约束的内部解的一种常见方法是转换参数,使优化不受约束。
例如:开区间 (0, 1) 内的约束可以使用 Logit 函数进行转换,例如此处使用:
https://github.com/statsmodels/statsmodels/blob/master/statsmodels/miscmodels/count.py#L243
我们可以使用 mulinomial logit 计算概率,参数在 (0, 1) 中并且加起来为 1。
在广义线性模型中,我们使用 link 函数对预测均值施加类似的限制,请参阅 statsmodels/genmod/families/links.py.
如果约束可以绑定,那么这行不通。 Scipy 具有约束优化器,但尚未连接到统计模型 LikelihoodModel 类。
相关:scipy 有一个全局优化器 basinhopping,如果有多个局部最小值,它工作得很好,它连接到 LikelihoodModels,可以使用 fit 中的方法参数进行选择。
确实这是一道数学题而不是编程题。我设法通过使用约束转换参数来解决这个问题,即alpha 和 sigma 到 alpha_hat 和 sigma_hat,
alpha = 1/(1+np.exp(-alpha_hat))
sigma = 1/(1+np.exp(-sigma_hat))
以便我们可以不受限制地估计 alpha_hat 和 sigma_hat。