逻辑回归:一个打着回归旗号,却在做分类任务的分类器。
逻辑回归在本质上其实是由线性回归衍变而来的,因此想要更好地理解逻辑回归,先让我们复习一下线性回归。线性回归的原理其实就是用一个线性回归方程来描述一个线性回归的问题。而线性回归的方程可以写作一个几乎大家都熟悉的方程:
在这个方程中,w0被称作截距,w1 ~ wn 被称作系数,这个线性回归方程也可以用矩阵来表示:
通过求出函数z,线性回归便完成了使用输入的特征矩阵X得到了一组连续型的标签值y_pred的操作,从而就可以完成对各种连续型变量的预测任务了。(比如预测一个人的收入、一只股票的价格等等) 深度了解线性回归可参考博主之前有关线性回归的博文:链接在此
但是线性回归模型更多地被用于对连续型数据进行预测,很少甚至是不被用于对离散型数据进行分类。因此为了实现回归模型可以对离散型数据进行分类操作,就有了逻辑回归这个回归模型。在逻辑回归算法中,为了实现分类的效果,我们通常使用的就是sigmoid函数。
在线性回归中我们可以得出有关z的线性回归方程,再将其带入到sigmoid函数中,就可以把线性回归方程得到的结果压缩到0~1之间了。从而有了以下的组合方程。这个结果也就是我们逻辑回归所返回的标签值。将这个标签中重命名为y(x)。
那么又如何将这个标签值退化为之前的线性回归方程呢?这里就要用到形似几率了,并在形似几率的基础上取对数,就可以将逻辑回归得到的标签结果重新退化为之前的线性回归方程了。过程如下:
不难发现,其实逻辑回归的结果的形似几率再取对数的本质其实就是线性回归方程,那么反过来其实就是我们对线性回归模型预测的结果取对数几率来让其结果无限地逼近0或者1,因此我们也常常将逻辑回归叫做对数几率回归。
总结来说: 逻辑回归的形似几率取对数就是线性回归,线性回归解的对数几率就是逻辑回归。从而我们就知道了,其实逻辑回归就是由线性回归衍变而来的。
由于逻辑回归其实就是线性回归的一个衍生,而线性回归的核心任务就是通过求解线性回归方程中的系数w(也叫权重)从而构建线性回归函数z,并希望通过线性回归函数z解得的值能够尽量地拟合真实数据。因此,逻辑回归的核心任务也是类似的,即通过求解逻辑回归函数中的w来构建一个能够尽量拟合的数据的预测函数y(x),并通过向预测函数中输入特征矩阵X来获取相应的标签值y。
通过sigmoid函数求得的y(x)的取值范围为(0,1),因此可以有这么一个公式: (1 - y(x)) + y(x) = 1。而这个公式恰巧类似于概率中的正反事件的求和公式。因此可以抽象地理解为:y(x)为事件A会发生的概率,1 - y(x) 就为事件A不会发生的概率,从而也可以衍生为:事件A和事件B联合起来构成了一个总的事件S,即P(A) + P(B) = P(S) = 1,从而求得y(x)就是会发生事件A的概率,而1 - y(x)就为事件B发生的概率,通过比较y(x)和1 - y(x)的大小就可以知道到底是会发生事件A还是事件B,从而就完成了类似于分类的功能。
因为逻辑回归是线性回归的衍生物,因此,当特征数据与标签数据存在着极强的线性关系的时候,逻辑回归后所得到的拟合效果非常的好!那么如何判断数据集是一个线性关系数据集呢?这里以二分类为例,给你做一个简单的解释。简单的来说当所对应的分类的决策边界可以由一条直线来表示时,就可以称这个数据集是一个线性关系的数据集。如下图中的图一,圆圈和三角的决策边界正好可以由一条直线来表示,那么这组数据集就符合线性关系,反之如图二,这组数据就不符合线性关系。
逻辑回归对于线性数据的拟合和计算都非常快,在计算效率上甚至优于SVM和随机森林。
逻辑回归的结果并不是单纯的0和1,而返回的是一个概率,因此我们就可以将这些返回的概率值当作连续型数据来使用。举个例子来说,当一个用户想要办理信用卡的时候,你可以通过逻辑回归求得一个他会不会定时还款的概率结果,从而决定要不要给他办理信用卡。同时,这个概率结果也可以被用作是这个用户的信用额度,概率越高,信用额度就可以适当的升高。
不论是预测还是分类,我们都会想要通过量化的方式来表示出来结果的准确性,或者说我们需要找到这个结果所伴随的误差是多少。在做逻辑回归分类的时候,不管原本样本数据的类别使用怎样的值或文字表示,逻辑回归统一将其视为0类别或1类别。因为逻辑回归的本质其实也是通过寻找每个特征的权重w来寻找特征数据与目标数据之间的关系,在这过程中难免会出现真实值与预测值的误差,这个误差就可以通过损失函数计算出来。但是逻辑回归是用来做分类操作的,因此该损失函数和线性回归的损失函数是不一样的(注:没有求解参数需求的模型是没有损失函数的,比如KNN算法,决策树算法)逻辑回归采用的损失函数是:对数似然损失函数。逻辑回归的损失函数方程如下:
逻辑回归的数学目的是求解能够让模型最优化,拟合程度最好的参数w的值,也就是求解能够让损失函数最小的值。因此如何减小损失函数的值就成为了最重要的问题。在线性回归中我们经常使用最小二乘法降低减少我们的损失,在逻辑回归中我们最常用的方法就是梯度下降法。
"""L1范式和L2范式的比较"""
from sklearn.linear_model import LogisticRegression as LR # 逻辑回归
from sklearn.datasets import load_breast_cancer # 导入数据集
# import numpy as np
# from sklearn.model_selection import train_test_split # 数据集拆分
# 加载数据集
data = load_breast_cancer()
X = data.data # 特征数据
Y = data.target # 标签数据
# 建立两种用于正则化的模型
LR1 = LR(penalty="l1", C=0.5, solver="liblinear")
LR2 = LR(penalty="l2", C=0.5, solver="liblinear")
# 逻辑回归的重要属性coef_, 查看每个特征所对应的参数
LR1.fit(X, Y)
print("L1范式:", LR1.coef_)
LR2.fit(X, Y)
print("L2范式:", LR2.coef_)
# 结果
# L1范式: [[ 3.21172271 0.02596161 -0.06371837 -0.01242846 0. 0.
# 0. 0. 0. 0. 0. 0.49961334
# 0. -0.07298843 0. 0. 0. 0.
# 0. 0. 0.37556908 -0.23964358 -0.14220463 -0.01748585
# 0. 0. -2.351896 0. 0. 0. ]]
# L2范式: [[ 1.61358623e+00 1.00284781e-01 4.61036191e-02 -4.21333984e-03
# -9.27388895e-02 -3.00561176e-01 -4.53477303e-01 -2.19973055e-01
# -1.33257382e-01 -1.92654788e-02 1.87887747e-02 8.75532438e-01
# 1.31708341e-01 -9.53440922e-02 -9.64408195e-03 -2.52457845e-02
# -5.83085040e-02 -2.67948347e-02 -2.74103894e-02 -6.09326731e-05
# 1.28405755e+00 -3.00219699e-01 -1.74217870e-01 -2.23449384e-02
# -1.70489339e-01 -8.77400140e-01 -1.15869741e+00 -4.22909464e-01
# -4.12968162e-01 -8.66604813e-02]]
# 可以看出来L1明显明显压缩的更狠,很多系数w都被压缩成了0,而且随着对超参数C的缩小,对系数的压缩就会更厉害,也就是会出现更多的0
from sklearn.linear_model import LogisticRegression
超参数介绍:
import sklearn.datasets as datasets
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression as LR
import numpy as np
l2 = []
l2_test = []
cancer_data = datasets.load_breast_cancer()
data = cancer_data.data
target = cancer_data.target
x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.3, random_state=420)
for i in np.arange(1, 201, 10):
lrl2 = LR(penalty="l2", solver="liblinear", C=0.9, max_iter=i)
lrl2.fit(x_train, y_train)
l2.append(accuracy_score(lrl2.predict(x_train), y_train))
l2_test.append(accuracy_score(lrl2.predict(x_test), y_test))
graph = [l2, l2_test]
color = ["black", "red"]
label = ["L2train", "L2test"]
plt.figure(figsize=(20, 5))
for i in range(len(graph)):
plt.plot(np.arange(1, 201, 10), graph[i], color[i], label=label[i])
plt.legend(loc=4)
plt.xticks(np.arange(1, 201, 10))
plt.show()
结果展示
其中黑色的线是模型在训练集的表现,红色的线是模型在测试集的表现。
如有问题,敬请指正。欢迎转载,但请注明出处。