点一下关注吧!!!非常感谢!!持续更新!!!

目前已经更新到了:

  • Hadoop(已更完)
  • HDFS(已更完)
  • MapReduce(已更完)
  • Hive(已更完)
  • Flume(已更完)
  • Sqoop(已更完)
  • Zookeeper(已更完)
  • HBase(已更完)
  • Redis (已更完)
  • Kafka(已更完)
  • Spark(已更完)
  • Flink(已更完)
  • ClickHouse(已更完)
  • Kudu(已更完)
  • Druid(已更完)
  • Kylin(已更完)
  • Elasticsearch(已更完)
  • DataX(已更完)
  • Tez(已更完)
  • 数据挖掘(正在更新…)

章节内容

上节我们完成了如下的内容:

  • 梯度下降
  • 梯度下降算法调优

在这里插入图片描述

逻辑回归的Scikit-Learn实现

参数详解

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正则化的差别一目了然:

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正则化是对所有特征都给出了参数。

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

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正则化了。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部