我在尝试对著名的iris数据集使用statsmodels的MNLogit函数时,得到的结果是:“当前函数值:nan”。这是我使用的代码:
import statsmodels.api as stiris = st.datasets.get_rdataset('iris','datasets')y = iris.data.Speciesx = iris.data.ix[:, 0:4]x = st.add_constant(x, prepend = False)mdl = st.MNLogit(y, x)mdl_fit = mdl.fit()print (mdl_fit.summary())
回答:
在iris的例子中,我们可以完美预测Setosa。这在Logit和MNLogit中会导致(部分)完美分离的问题。
完美分离对于预测是有利的,但logit的参数会趋向于无穷。在这种情况下,我使用statsmodels的最新版本(在Windows上)时,得到的是奇异矩阵错误,而不是Nans。
离散模型的默认优化器是牛顿法,当Hessian矩阵变为奇异时会失败。其他不使用Hessian信息的优化器能够完成优化。例如,使用’bfgs’,我得到
>>> mdl_fit = mdl.fit(method='bfgs')Warning: 已超过最大迭代次数。 当前函数值:0.057112 迭代次数:35 函数评估次数:37 梯度评估次数:37e:\josef\eclipsegworkspace\statsmodels-git\statsmodels-all-new2_py27\statsmodels\statsmodels\base\model.py:471: ConvergenceWarning: 最大似然优化未能收敛。检查mle_retvals "检查mle_retvals", ConvergenceWarning)
对于Setosa的预测概率基本上是(1, 0, 0),也就是说它们被完美预测
>>> fitted = mdl_fit.predict()>>> fitted[y=='setosa'].min(0)array([ 9.99497636e-01, 2.07389867e-11, 1.71740822e-38])>>> fitted[y=='setosa'].max(0)array([ 1.00000000e+00, 5.02363854e-04, 1.05778255e-20])
然而,由于完美分离,参数无法被识别,值主要由优化器的停止标准决定,标准误差非常大。
>>> print(mdl_fit.summary()) MNLogit回归结果 ==============================================================================因变量: 物种 观测数: 150模型: MNLogit 残差自由度: 140方法: 最大似然估计 模型自由度: 8日期: 2015年7月20日星期一 伪R平方: 0.9480时间: 04:08:04 对数似然: -8.5668收敛: 否 空模型对数似然: -164.79 LLR p值: 9.200e-63=====================================================================================物种=versicolor 系数 标准误差 z P>|z| [95.0% 置信区间]--------------------------------------------------------------------------------------萼片长度 -1.4959 444.817 -0.003 0.997 -873.321 870.330萼片宽度 -8.0560 282.766 -0.028 0.977 -562.267 546.155花瓣长度 11.9301 374.116 0.032 0.975 -721.323 745.184花瓣宽度 1.7039 759.366 0.002 0.998 -1486.627 1490.035常数 1.6444 1550.515 0.001 0.999 -3037.309 3040.597--------------------------------------------------------------------------------------物种=virginica 系数 标准误差 z P>|z| [95.0% 置信区间]-------------------------------------------------------------------------------------萼片长度 -8.0348 444.835 -0.018 0.986 -879.896 863.827萼片宽度 -15.8195 282.793 -0.056 0.955 -570.083 538.444花瓣长度 22.1797 374.155 0.059 0.953 -711.152 755.511花瓣宽度 14.0603 759.384 0.019 0.985 -1474.304 1502.425常数 -6.5053 1550.533 -0.004 0.997 -3045.494 3032.483=====================================================================================
关于statsmodels中的实现
Logit会专门检查完美分离,并引发一个可以选择性地减弱为警告的异常。对于其他模型如MNLogit,目前还没有明确的完美分离检查,主要是因为缺乏好的测试案例和容易识别的通用条件。(有几个问题如https://github.com/statsmodels/statsmodels/issues/516仍未解决)
我的总体策略:
当出现收敛失败时,尝试不同的优化器和不同的起始值(start_params
)。如果某些优化器成功了,那么这可能是一个困难的优化问题,要么是目标函数的曲率,要么是解释变量的比例不当或类似情况。一个有用的检查是使用像nm
或powell
这样的鲁棒优化器的参数估计作为更严格的优化器(如newton
或bfgs
)的起始值。
如果在某些优化器收敛后结果仍然不好,那么这可能是数据本身的问题,如Logit、Probit和其他几个模型中的完美分离,或是设计矩阵的奇异或近似奇异。在这种情况下,必须更改模型。关于完美分离的建议可以通过互联网搜索找到。