我正在研究的模型是多项 logit 选择模型。这是一个非常具体的数据集,因此其他现有的 MNLogit 库不适合我的数据。
所以基本上,这是一个非常复杂的函数,它接受 11 个参数并返回一个对数似然值。然后我需要找到可以使用 scipy.optimize.minimize 最小化对数似然的最佳参数值。
以下是我使用不同方法遇到的问题:
'Nelder-Mead':效果很好,而且总是给我正确的答案。但是,它非常缓慢。对于另一个设置更复杂的功能,需要 15 个小时才能达到最佳点。同时,使用 fminunc(默认使用 BFGS)在 Matlab 上相同的功能仅需 1 小时
'BFGS':这是 Matlab 使用的方法。它适用于任何简单的功能。但是,对于我拥有的函数,它总是无法收敛并返回“由于精度损失而不一定实现的期望错误。”。我花了很多时间玩这些选项,但仍然无法工作。
'Powell':快速收敛,但返回错误的答案。代码打印在下面(x0 是正确答案,Nelder-Mead 适用于任何初始值),您可以在此处获取数据:https ://www.dropbox.com/s/aap2dhor5jyxy94/data.csv
谢谢!
import pandas as pd
import numpy as np
from scipy.optimize import minimize
# https://www.dropbox.com/s/aap2dhor5jyxy94/data.csv
df = pd.read_csv('data.csv', index_col=0)
dfhh = df.hh
B = df.ix[:,'b0':'b4'].values # NT*5
P = df.ix[:,'p1':'p4'].values # NT*4
F = df.ix[:,'f1':'f4'].values # NT*4
SDV = df.ix[:,'lagb1':'lagb4'].values
def Li(x):
b1 = x[0] # coeff on prices
b2 = x[1] # coeff on features
a = x[2:7] # take first 4 values as alpha
E = np.exp(a + b1*P + b2*F) # (1*4) + (NT*4) + (NT*4) build matrix (NT*J) for each exp()
E = np.insert(E, 0, 1, axis=1) # (NT*5)
denom = E.sum(1)
return -np.log((B * E).sum(1) / denom).sum()
x0 = np.array([-32.31028223, 0.23965953, 0.84739154, 0.25418215,-3.38757007,-0.38036966])
np.random.seed(0)
x0 = x0 + np.random.rand(6)
minL = minimize(Li, x0, method='Nelder-Mead',options={'xtol': 1e-8, 'disp': True})
# minL = minimize(Li, x0, method='BFGS')
# minL = minimize(Li, x0, method='Powell', options={'xtol': 1e-12, 'ftol': 1e-12})
print minL
更新:2014 年 3 月 7 日更简单的代码版本现在 Powell 在非常小的容差下运行良好,但是在这种情况下 Powell 的速度比 Nelder-Mead 慢。BFGS 仍然无法正常工作。