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

逻辑回归模型L1正则化(Lasso)实现与结果解读技术咨询

L1正则化逻辑回归的实现优化与问题解答

一、初始代码的合理性分析

你的初始实现存在几个关键问题,导致结果不可靠:

  • 每次循环重新划分训练测试集:不同alpha对应的模型在完全不同的训练/测试数据上评估,无法公平比较不同正则化强度的效果,结果随机性极强。
  • 数据泄露:在划分数据集前就用全量数据拟合StandardScaler,会把测试集的统计信息(均值、方差)带入训练过程,导致模型泛化能力的估计偏乐观。
  • 单轮评估不稳定:仅用一次训练测试拆分的对数似然选择alpha,容易受随机拆分的影响,无法得到稳定的最优正则化参数。

二、数据缩放的正确时机

绝对不能在划分训练测试集前对全数据集做缩放!正确流程是:

  1. 先划分X_train, X_test, Y_train, Y_test
  2. 用X_train的特征部分拟合StandardScaler
  3. 用拟合好的scaler分别缩放X_train和X_test的特征
    这样能避免测试集信息泄露,保证模型评估的客观性。

三、Alpha值选择方式的可行性

你最初用循环遍历alpha+单轮拆分评估的方式不可行,建议改用交叉验证(比如sklearn的LogisticRegressionCV):

  • 交叉验证会在训练集内部多次拆分,对每个alpha计算平均性能指标,结果更稳定
  • LogisticRegressionCV会自动选择交叉验证中最优的C值(注意sklearn中C = 1/alpha,C越大正则化强度越弱)

四、更新后代码的问题修正与解答

1. 代码中的错误修正

你的更新代码里有一个严重错误:不能用测试集去拟合lasso_model_best!测试集的作用是评估模型泛化能力,不是用来训练的。正确流程是:

X_train, X_test, Y_train, Y_test = train_test_split(DM, Y, train_size=0.8)
AlphasToTest = np.arange(0.01, 10, 0.01)
# 转换为sklearn的C参数(C = 1/alpha)
Cs = 1 / AlphasToTest

scaler = StandardScaler()
# 仅用训练集拟合scaler
scaler.fit(X_train[:, 1:])
ScaledDM_train = scaler.transform(X_train[:, 1:])

# 用交叉验证选择最优C
lasso_model_cv = LogisticRegressionCV(
    penalty='l1',
    solver='saga',
    Cs=Cs,
    cv=5,
    scoring='neg_log_loss',
    max_iter=1000
)
lasso_model_cv.fit(ScaledDM_train, Y_train.ravel())
best_C = lasso_model_cv.C_[0]

# 用最优C在完整训练集上拟合最终模型
lasso_model_best = LogisticRegression(
    penalty='l1',
    solver='saga',
    C=best_C,
    max_iter=1000
)
lasso_model_best.fit(ScaledDM_train, Y_train.ravel())

# 用测试集评估模型
ScaledDM_test = scaler.transform(X_test[:, 1:])
y_pred_proba = lasso_model_best.predict_proba(ScaledDM_test)
test_neg_log_loss = log_loss(Y_test, y_pred_proba)

2. 获取Lasso逻辑回归的p值

sklearn的LogisticRegression(带L1正则化)默认不提供p值,原因是正则化改变了系数的统计分布,传统基于无正则化模型的p值假设不再成立。如果需要近似获取显著性指标,可采用以下方法:

  • 方法1:筛选特征后用无正则化模型计算p值
    先用Lasso选出非零系数的特征,再用statsmodels的无正则化逻辑回归拟合这些特征,得到p值:

    import statsmodels.api as sm
    
    # 获取Lasso选中的特征索引
    selected_features_idx = np.where(lasso_model_best.coef_[0] != 0)[0]
    # 提取训练集中的选中特征,加上常数项
    X_train_selected = sm.add_constant(ScaledDM_train[:, selected_features_idx])
    # 拟合无正则化逻辑回归
    model = sm.Logit(Y_train, X_train_selected)
    result = model.fit()
    print(result.summary())  # 查看p值
    

    注意:这种方法仅能作为参考,因为Lasso筛选后的特征可能仍存在共线性,且正则化的影响未完全消除。

  • 方法2:Bootstrapping近似显著性
    通过多次重采样训练数据,拟合Lasso模型,统计每个特征系数不为零的频率,频率越高说明特征越稳定:

    n_bootstrap = 1000
    coef_counts = np.zeros(ScaledDM_train.shape[1])
    
    for _ in range(n_bootstrap):
        # 重采样训练数据
        idx = np.random.choice(len(Y_train), len(Y_train), replace=True)
        X_boot = ScaledDM_train[idx]
        Y_boot = Y_train[idx]
        # 拟合Lasso模型
        boot_model = LogisticRegression(penalty='l1', solver='saga', C=best_C, max_iter=1000)
        boot_model.fit(X_boot, Y_boot.ravel())
        # 统计非零系数
        coef_counts += (boot_model.coef_[0] != 0).astype(int)
    
    # 计算每个特征的选中频率
    feature_selection_freq = coef_counts / n_bootstrap
    print("特征选中频率:", feature_selection_freq)
    

3. 模型输出的最优解读

  • 系数解读:
    • 非零系数对应的特征是Lasso筛选出的、对二分类结果有预测价值的特征。
    • 系数的正负表示特征对正类概率的影响方向:正系数意味着特征值越高,样本属于正类的概率越大;负系数则相反。
    • 系数的大小反映特征的相对重要性(因数据已标准化,系数大小可直接比较)。
  • 最优C值解读:
    • LogisticRegressionCV选出的best_C是在交叉验证中使neg_log_loss最优的参数,代表该正则化强度下模型的泛化能力最好。
  • 模型性能解读:
    • 用测试集的neg_log_loss(对数损失)、ROC-AUC、准确率等指标评估模型的泛化能力,而不是仅看训练集表现。
    • 若多个特征系数被压缩为0,说明这些特征对预测结果的贡献被正则化抵消,可从后续分析中剔除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:05:55