大数据-210 如何在Scikit-Learn中实现逻辑回归及正则化详解(L1与L2)

TL;DR

  • 场景:使用Scikit-Learn实现逻辑回归,并调整正则化(L1与L2)来优化模型。
  • 结论:L1正则化会使特征稀疏化,而L2正则化则不会;两者在不同数据集和C值下表现相似。
  • 产出:掌握如何选择正则化方法及如何根据C值调整模型表现。

版本矩阵

版本 已验证 说明
0.24.x Scikit-Learn 支持L1与L2正则化
0.22.x及之前 适用于大部分旧版逻辑回归功能
最新版本(2026) 包含新优化器及改进的正则化处理方式

逻辑回归的Scikit-Learn实现

参数详解

python 复制代码
class sklearn.linear_model.LogisticRegression(
    penalty='l2',
    dual=False,
    tol=0.0001,
    C=1.0,
    fit_intercept=True,
    intercept_scaling=1,
    class_weight=None,
    random_state=None,
    solver='warn',
    max_iter=100,
    multi_class='warn',
    verbose=0,
    warm_start=False,
    n_jobs=None
)

penalty

正则化参数,LogisticRegression默认带了正则化项,penalty参数可选择的值有1和2,分别对应L1的正则化和L2的正则化,默认是L2的正则化。 在调参时如果我们主要的目的只是为了解决过拟合,一般penalty选择L2正则化就够了,但是如果选择L2正则化后还是过拟合,即预测效果差的时候,就可以考虑L1正则化。另外,如果模型的特征非常多,我们希望一些不重要的特征系数归零,从而让模型稀疏化的话,也可以使用L1正则化。 penalty参数的选择会影响我们损失函数优化算法的选择,即参数solver的选择,如果是L2正则化,那么4种可选的算法(newton-cg、lbfgs、礼包里near、sag)都可以选择。但是如果penalty是L1正则化的话,就只能liblinear了。 这是因为L1正则化的损失函数不是连续可导的,而(newton-cg、lbfgs、sag)这三种优化算法时都需要损失函数的一阶或者二阶段连续倒数。而libnear并没有这个依赖。 而两种正则化下的C的取值,都可以通过学习曲线来进行调整。 建立两个逻辑回归,L1正则化和L2正则化的差别一目了然:

python 复制代码
from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler
import numpy as np

# 加载数据集
data = load_breast_cancer()
X = data.data
y = data.target

# 对数据进行标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 使用L1正则化的逻辑回归
lrl1 = LR(penalty="l1", solver="liblinear", C=0.5, max_iter=1000)

# 使用L2正则化的逻辑回归
lrl2 = LR(penalty="l2", solver="liblinear", C=0.5, max_iter=1000)

# 训练L1正则化的模型
lrl1 = lrl1.fit(X_scaled, y)

# 打印L1模型的系数
print(lrl1.coef_)

# 统计非零系数的数量
print((lrl1.coef_ != 0).sum(axis=1))

# 训练L2正则化的模型
lrl2 = lrl2.fit(X_scaled, y)

# 打印L2模型的系数
print(lrl2.coef_)

执行结果如下图所示: 可以看出,当我们选择L1正则化的时候,许多特征的参数都被设置了0,这些特征在真正建模的时候,就不会出现在我们的模型当中了,而L2正则化是对所有特征都给出了参数。

究竟哪个正则化的效果更好呢?还是都差不多?

python 复制代码
l1 = []
l2 = []
l1test = []
l2test = []
Xtrain, Xtest, Ytrain, Ytest =
train_test_split(X,y,test_size=0.3,random_state=420)
for i in np.linspace(0.05,1,19):
lrl1 = LR(penalty="l1",solver="liblinear",C=i,max_iter=1000)
lrl2 = LR(penalty="l2",solver="liblinear",C=i,max_iter=1000)
lrl1 = lrl1.fit(Xtrain,Ytrain)
l1.append(accuracy_score(lrl1.predict(Xtrain),Ytrain))
l1test.append(accuracy_score(lrl1.predict(Xtest),Ytest))
lrl2 = lrl2.fit(Xtrain,Ytrain)
l2.append(accuracy_score(lrl2.predict(Xtrain),Ytrain))
l2test.append(accuracy_score(lrl2.predict(Xtest),Ytest))
graph = [l1,l2,l1test,l2test]
color = ["green","black","lightgreen","gray"]
label = ["L1","L2","L1test","L2test"]
plt.figure(figsize=(6,6))
for i in range(len(graph)):
plt.plot(np.linspace(0.05,1,19),graph[i],color[i],label=label[i])
plt.legend(loc=4) #图例的位置在哪⾥?4表示,右下⻆
plt.show()

执行结果如下图所示: 对应的图如下所示: 可见,在我们的乳腺癌数据集下,两种正则化的结果区别不大。但随着C的逐渐变大,正则化的强度越来越小,模型在训练集和测试集上表现呈现了上升趋势,直到C=0.8左右,训练集上的表现依然走高,但模型在未知数据集上的表现就开始下跌,这时候就是出现了过拟合。我们可以认为,C设置0.8会比较好。 在实际使用中,基本就默认使用L2正则化,如果感觉到效果不好,就试试L1。

solver

solver参数决定了我们对逻辑回归损失函数的优化方法,有4种算法可以选择,分别是:

  • liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降来迭代优化损失函数
  • lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数
  • newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数
  • sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅用一部分的样本来计算梯度,适合于样本数据多的时候。

从上面的描述可以看出,newton-cg,lbfgs和sag这三种优化算法时都需要损失函数一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear通吃L1正则化和L2正则化。同时,sag每次仅使用部分样本进行梯度迭代,所以当样本量少的时候不要选择它,而如果样本非常大,比如大于10万,sag是第一选择。 但是sag不能用于L1正则化,所以当你有大量的样本,又需要L1的时候就需要自己做取舍了,要么通过对样本采样来降低样本量,要么回到L2正则化。

此时大家可能觉着,既然newton-cg、lbfgs和sag这么多限制,如果不是大样本,我们选择liblinear不就行了吗?因为liblinear也有自己的弱点,我们知道逻辑回归二元逻辑回归和多元逻辑回归。对于多元逻辑回归常见有one-vs-rest(OvR)和many-vs-many(MvM)两种,而MvM一般比OvR分类相对准确一些。liblinear只支持OvR,不支持MvM,这样如果我们需要相对精准的多元逻辑回归时就不能选择liblinear。这也意味着我们需要相对精确的多元回归逻辑就不能用L1正则化了。

错误速查

症状 根因 定位 修复
正则化方法无法选择L1 优化使用的solver不支持L1正则化 检查solver是否选择为liblinear 将solver参数设置为liblinear,仅此支持L1
模型出现过拟合 C值过大,正则化强度不足 调整C值,逐步减小C值,使用学习曲线检查 减小C值,观察训练集与测试集的表现变化
使用SAG时训练速度较慢且不支持L1正则化 SAG不支持L1正则化 使用的优化器不支持L1,查看solver设置 改用liblinear或选择L2正则化

其他系列

🚀 AI篇持续更新中(长期更新)

AI炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究 ,持续打造实用AI工具指南! AI研究-132 Java 生态前沿 2025:Spring、Quarkus、GraalVM、CRaC 与云原生落地

💻 Java篇持续更新中(长期更新)

Java-218 RocketMQ Java API 实战:同步/异步 Producer 与 Pull/Push Consumer MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务已完结,Dubbo已完结,MySQL已完结,MongoDB已完结,Neo4j已完结,FastDFS 已完结,OSS已完结,GuavaCache已完结,EVCache已完结,RabbitMQ已完结,RocketMQ正在更新... 深入浅出助你打牢基础!

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈! 大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

相关推荐
xiaobaishuoAI4 小时前
全链路性能优化实战指南:从瓶颈定位到极致优化
大数据·人工智能·科技·百度·geo
jarreyer4 小时前
数据项目分析标准化流程
开发语言·python·机器学习
乾元4 小时前
如何把 CCIE / HCIE 的实验案例改造成 AI 驱动的工程项目——从“实验室能力”到“可交付系统”的完整迁移路径
大数据·运维·网络·人工智能·深度学习·安全·机器学习
Coder_Boy_4 小时前
Spring Boot 事务回滚异常 UnexpectedRollbackException 详解(常见问题集合)
java·spring boot·后端
风象南4 小时前
SpringBoot 实现网络限速
后端
QBoson4 小时前
量子机器学习用于药物发现:系统综述
人工智能·机器学习·量子计算
xiaobaishuoAI4 小时前
后端工程化实战指南:从规范到自动化,打造高效协作体系
java·大数据·运维·人工智能·maven·devops·geo
源代码•宸4 小时前
Golang语法进阶(定时器)
开发语言·经验分享·后端·算法·golang·timer·ticker
计算机学姐4 小时前
基于SpringBoot的汽车租赁系统【个性化推荐算法+数据可视化统计】
java·vue.js·spring boot·后端·spring·汽车·推荐算法