You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义带p值的Logistic Regression报错LinAlgError:奇异矩阵

解决自定义Logistic回归模型中的奇异矩阵错误

嘿,这个问题我之前也碰到过!咱们一步步来拆解原因并解决它:

问题根源

你遇到的LinAlgError: Singular matrix是因为计算Fisher信息矩阵的逆时,矩阵不可逆。而原生sklearn.linear_model.LogisticRegression默认启用了L2正则化(penalty='l2'),正则化会给矩阵添加一个小的对角项,避免矩阵奇异;但你的自定义模型直接计算原始Fisher矩阵,没有处理共线性问题,所以触发了错误。

常见导致矩阵奇异的原因:

  • 哑变量陷阱:对有n个类别的特征生成了n个哑变量(比如性别变量生成「男」「女」两个哑变量),这两个特征完全线性相关,会导致共线性。
  • 零方差特征:某个特征的所有样本值完全相同(比如所有样本的某个特征都是0),这类特征对模型无贡献还会破坏矩阵可逆性。
  • 高度相关特征:两个或多个特征的相关系数接近1,导致共线性。

解决方案

1. 先排查并修复数据层面的共线性问题

  • 处理哑变量陷阱:生成哑变量时使用drop_first=True(比如pd.get_dummies(data, drop_first=True)),去掉一个冗余的哑变量,避免完全共线性。
  • 删除零方差特征:计算每个特征的方差,过滤掉方差为0的特征:
    from sklearn.feature_selection import VarianceThreshold
    selector = VarianceThreshold(threshold=0)
    inputs_train = selector.fit_transform(inputs_train)
    
  • 检测高度相关特征:计算特征的相关系数矩阵,或使用VIF(方差膨胀因子)找出高度相关的特征,移除其中一个:
    from statsmodels.stats.outliers_influence import variance_inflation_factor
    vif_data = pd.DataFrame()
    vif_data["feature"] = your_feature_names
    vif_data["VIF"] = [variance_inflation_factor(inputs_train, i) for i in range(inputs_train.shape[1])]
    # 移除VIF值远大于10的特征
    

2. 给自定义模型添加正则化处理

把原生sklearn的正则化逻辑加入你的自定义模型,确保Fisher矩阵可逆。修改fit方法中的Fisher矩阵计算代码:

def fit(self,X,y):
    self.model.fit(X,y)
    #### Get p-values for the fitted model ####
    denom = (2.0 * (1.0 + np.cosh(self.model.decision_function(X))))
    denom = np.tile(denom,(X.shape[1],1)).T
    # 加入L2正则化项,对应sklearn的C参数(alpha = 1/C)
    alpha = 1.0 / self.model.C
    F_ij = np.dot((X / denom).T,X) + alpha * np.eye(X.shape[1]) ## 加入正则化后的Fisher Information Matrix
    Cramer_Rao = np.linalg.inv(F_ij) ## Inverse Information Matrix
    sigma_estimates = np.sqrt(np.diagonal(Cramer_Rao))
    z_scores = self.model.coef_[0] / sigma_estimates # z-score for each model coefficient
    p_values = [stat.norm.sf(abs(x)) * 2 for x in z_scores] ### two tailed test for p-values
    self.coef_ = self.model.coef_
    # 修正笔误:self.mode 应该是 self.model.intercept_
    self.intercept_ = self.model.intercept_
    # 把p值也存到实例里方便调用
    self.p_values = p_values

3. 修正代码中的笔误

注意到你代码最后一行self.intercept_ = self.mode是笔误,应该改为self.intercept_ = self.model.intercept_,不然之后调用reg.intercept_会报错。

验证

修改完成后,再运行你的调用代码:

reg = LogisticRegression_with_p_values()
reg.fit(inputs_train,loan_data_targets_train)
# 可以查看p值
print(reg.p_values)

内容的提问来源于stack exchange,提问作者Billeh Sarkozy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:12:02