MNLogit回归结果全为nan问题的排查与解决咨询
问题描述
我希望研究部分变量对电力消耗的影响,自变量包含分类变量(性别、年龄、婚姻状况)和有序变量(居住人数),因变量为分为4个档位的电力消耗类别。运行MNLogit模型代码后,结果中出现大量nan值,干扰分析,现寻求该问题的解决方法。
运行代码
# Import librairies import pandas as pd import statsmodels.formula.api as smf # Loading dataset data = pd.read_excel("donnees_socio.xlsx") data['conso_elect_codes'] = data['conso_elect'].astype('category').cat.codes # model classification formula formula = "conso_elect_codes ~ sexe + age + statut + nbre_occ" # fit the multinomial model model = smf.mnlogit(formula, data = data) result = model.fit() # Display results print(result.summary())
输出结果
Optimization terminated successfully. Current function value: nan Iterations 27 MNLogit Regression Results ============================================================================== Dep. Variable: conso_elect_codes No. Observations: 749 Model: MNLogit Df Residuals: 719 Method: MLE Df Model: 27 Date: Tue, 24 Oct 2023 Pseudo R-squ.: nan Time: 11:56:11 Log-Likelihood: nan converged: True LL-Null: -562.99 Covariance Type: nonrobust LLR p-value: nan ========================================================================================== conso_elect_codes=1 coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------------------ Intercept nan nan nan nan nan nan sexe[T.Homme] nan nan nan nan nan nan age[T.35 - 49 ans ] nan nan nan nan nan nan age[T.50 - 64 ans ] nan nan nan nan nan nan age[T.65 et plus] nan nan nan nan nan nan age[T.Moins de 25 ans] nan nan nan nan nan nan statut[T.Divorcé(e)] nan nan nan nan nan nan statut[T.Marié(e)] nan nan nan nan nan nan statut[T.Veuf(ve)] nan nan nan nan nan nan nbre_occ nan nan nan nan nan nan ------------------------------------------------------------------------------------------ conso_elect_codes=2 coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------------------ Intercept nan nan nan nan nan nan sexe[T.Homme] nan nan nan nan nan nan age[T.35 - 49 ans ] nan nan nan nan nan nan age[T.50 - 64 ans ] nan nan nan nan nan nan age[T.65 et plus] nan nan nan nan nan nan age[T.Moins de 25 ans] nan nan nan nan nan nan statut[T.Divorcé(e)] nan nan nan nan nan nan statut[T.Marié(e)] nan nan nan nan nan nan statut[T.Veuf(ve)] nan nan nan nan nan nan nbre_occ nan nan nan nan nan nan ------------------------------------------------------------------------------------------ conso_elect_codes=3 coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------------------ Intercept nan nan nan nan nan nan sexe[T.Homme] nan nan nan nan nan nan age[T.35 - 49 ans ] nan nan nan nan nan nan age[T.50 - 64 ans ] nan nan nan nan nan nan age[T.65 et plus] nan nan nan nan nan nan age[T.Moins de 25 ans] nan nan nan nan nan nan statut[T.Divorcé(e)] nan nan nan nan nan nan statut[T.Marié(e)] nan nan nan nan nan nan statut[T.Veuf(ve)] nan nan nan nan nan nan nbre_occ nan nan nan nan nan nan ==========================================================================================
解决方法
检查数据集缺失值
运行data.isnull().sum()查看所有变量的缺失数量,尤其是因变量conso_elect和各自变量的缺失情况。如果存在缺失值,可选择:- 删除缺失样本:
data = data.dropna() - 填充缺失值:分类变量用众数填充(如
data['sexe'] = data['sexe'].fillna(data['sexe'].mode()[0])),连续变量用均值/中位数填充。
- 删除缺失样本:
核查因变量类别分布
执行data['conso_elect_codes'].value_counts()查看每个电力消耗档位的样本量。若某档位样本量为0或极少(≤2),模型无法估计该类别的参数,会出现nan。解决方式:- 合并样本量极低的档位
- 补充该档位的样本数据
排查自变量完全分离问题
当某个自变量的取值完全对应因变量的某一类别时(比如所有男性样本都属于电力消耗第1档),会导致模型参数无法识别。可通过交叉表验证:pd.crosstab(data['sexe'], data['conso_elect_codes']) pd.crosstab(data['age'], data['conso_elect_codes']) pd.crosstab(data['statut'], data['conso_elect_codes'])若存在完全分离,可合并该自变量的对应类别,或移除该自变量。
优化模型拟合稳定性
MNLogit的MLE拟合可能因数值问题出现nan,可尝试调整拟合参数:- 增加迭代次数:
result = model.fit(maxiter=100) - 更换优化方法:
result = model.fit(method='bfgs') - 标准化连续变量:对居住人数
nbre_occ做标准化处理,减少数值波动:data['nbre_occ'] = (data['nbre_occ'] - data['nbre_occ'].mean()) / data['nbre_occ'].std()
- 增加迭代次数:
确认分类变量编码
确保所有分类变量已正确转为类别类型,避免字符串编码问题:data['sexe'] = data['sexe'].astype('category') data['age'] = data['age'].astype('category') data['statut'] = data['statut'].astype('category')
内容的提问来源于stack exchange,提问作者Leonce
相关产品推荐
相关产品推荐

