我正在研究的模型是一个多项logit选择模型。这是一个非常具体的数据集,因此其他现有的MNLogit库不适合我的数据。
所以基本上,它是一个非常复杂的函数,它接受11个参数并返回对数似然值。然后我需要找到可以使用scipy.optimize.minimize最小化对数似然的最佳参数值。
以下是我遇到的不同方法的问题:
<'Nelder-Mead':它运作良好,并且总是给我正确的答案。但是,它非常慢。对于具有更复杂设置的另一功能,需要15个小时才能达到最佳点。同时,使用fminunc(默认情况下使用BFGS)在Matlab上使用相同的函数仅需1小时'BFGS':这是Matlab使用的方法。它适用于任何简单的功能。但是,对于我所拥有的功能,它始终无法收敛并返回“由于精度损失而无法实现所需的错误”。我花了很多时间玩这些选项但仍未能奏效。
'鲍威尔':它迅速收敛成功,但回答错误答案。代码打印在下面(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
更新:03/07/14更简单的代码版本 现在鲍威尔的耐受性非常小,但在这种情况下,鲍威尔的速度比Nelder-Mead慢。 BFGS仍然无法正常工作。