欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

sklearn逻辑回归中损失函数与正则化

程序员文章站 2022-03-22 17:39:28
...

在随机森林和决策树中,存在两种模型表现:训练集上和测试集上的表现。在建模过程中,追求模型在测试集上表现最优,因此模型的评价指标往往是用来衡量模型在测试集上的表现。然而逻辑回归有着基于训练数据求解参数的需求,并且希望训练出来的模型能够尽可能的拟合训练数据,即模型在训练集上的预测准确率越靠近100%越好。
因此使用“损失函数”这个评估指标,来衡量参数的优劣,即这一参数能否是模型在训练集上表现优异。
如果用一组参数建模后,模型在训练集上表现良好,那我们就说模型表现的规律与训练集数据的规律一致,拟合过程中的损失很小,损失函数的值很小,这一组参数就优秀;相反,如果模型在训练集上表现糟糕,损失函数就会很 大,模型就训练不足,效果较差,这一组参数也就比较差。即是说,我们在求解参数时,追求损失函数小,让 模型在训练数据上的拟合效果优,即预测准确率尽量靠近100%。

损失函数

衡量参数的优劣的评估指标,用来求解最优参数的工具。
损失函数小,模型在训练集上表现优异,拟合充足,参数优秀。
损失函数大,模型在训练集上表现差劲,拟合不足,参数糟糕。
我们追求,能够让损失函数最小化的参数组合。
没有“求解参数”需求的模型没有损失函数,比如KNN、决策树。

如果我们追求损失函数的最小值,让模型在训练集上表现最优,可能会引发一个问题:如果模型在训练集上表现优秀,却在测试集上表现糟糕,这就是我们常说的过拟合。虽然逻辑回归和线性回归是天生欠拟合的模型,但我们还是需要控制过拟合的技术来调整模型。
对逻辑回归中的过拟合控制,通过正则化来实现。

正则化

正则化是用来防止模型过拟合的过程,常用的有L1正则化和L2正则化两种选项。分别通过在损失函数后加上参数向量的L1范式和L2范式的倍数来实现。这个增加的范式,被称为“正则项”,也被称为"惩罚项"。损失函数改变,基于损失函数的优化来求解的参数取值必然改变,我们以此来调节模型拟合的程度。其中L1范数表现为参数向量中的每个参数的绝对值之和,L2范数表现为参数向量中的每个参数的平方和的开方值。

参数 说明
penalty 可以输入“l1”,“l2” 两种,默认l2。在l1中,参数solver仅能使用“liblinear”。
C C正则化强度的倒数,必须是一个大于0的浮点数,不填写默认1.0,即默认一倍正则项。 C越小,对损失函数的惩罚越重,正则化的效力越强,参数 会逐渐被压缩得越来越小。在很多书 籍和博客的原理讲解中, 被写作 ,为了大家便于理解sklearn中的参数,我将公式改写成 , 更加直观。

L1正则化和L2正则化虽然都可以控制过拟合,但它们的效果并不相同。当正则化强度逐渐增大(即C逐渐变小), 参数 的取值会逐渐变小,但L1正则化会将参数压缩为0,L2正则化只会让参数尽量小,不会取到0。
如果特征量很大,数据维度很高,倾向于使用L1正则化。
如果目的只是为了防止过拟合,选择L2就足够了。
还是要在具体情况下进行使用。

建立两个逻辑回归,观察L1和L2的差别

from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

data = load_breast_cancer()
X = data.data
y = data.target

lrl1 = LR(penalty="l1", solver="liblinear", C=0.5, max_iter=1000)

lrl2 = LR(penalty="l2", solver="liblinear", C=0.5, max_iter=1000)

# 逻辑回归的重要属性coef_,查看每个特征所对应的参数 lrl1 = lrl1.fit(X,y) lrl1.coef_

lrl1 = lrl1.fit(X, y)

print(lrl1.coef_)
print((lrl1.coef_ != 0).sum(axis=1))  # 实现降维,系数为0的被压缩,成为一维数组

lrl2 = lrl2.fit(X, y)

print(lrl2.coef_)
print((lrl2.coef_ != 0).sum(axis=1))

在选择L1时许多参数变成了0,不会出现在建模中。# 10
L2是所有特征都给出了参数。 #30

继续观察哪个正则化效果最佳,或者相同:
代码实现:

from sklearn.linear_model import LogisticRegression as LR
from sklearn.datasets import load_breast_cancer
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

data = load_breast_cancer()
X = data.data
y = data.target

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) 
plt.show()

运行结果:
sklearn逻辑回归中损失函数与正则化
随着C的逐渐变大,正则化的强度越来越小,模型在训练集和测试集上的表现都呈上升趋势,直到C=0.8左右,训练集上的表现依然在走高,但模型在未知数据集上的表现开始下跌,这时候就是出现了过拟合。我们可以认为,C设定为0.9会比较好。在实际使用时,基本就默认使用l2正则化,如果感觉到模型的效果不好,那就换L1试试。

相关标签: Sklearn