问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Logistic模型回归

创作时间:
作者:
@小白创作中心

Logistic模型回归

引用
CSDN
1.
https://blog.csdn.net/weixin_74105361/article/details/139270287

逻辑回归(Logistic Regression)是机器学习中一种重要的分类算法,广泛应用于疾病预测、经济预测等领域。本文将从逻辑回归的基本概念出发,深入探讨其数学原理,并通过Python代码示例展示如何使用逻辑回归进行分类。

一、逻辑回归简介

逻辑回归又称逻辑回归分析,是一种广义的线性回归分析模型,常用于数据挖掘、疾病自动诊断、经济预测等领域。例如,探讨引发疾病的危险因素,并根据危险因素预测疾病发生的概率等。以胃癌病情分析为例,选择两组人群,一组是胃癌组,一组是非胃癌组,两组人群必定具有不同的体征与生活方式等。因此因变量就为是否胃癌,值为“是”或“否”,自变量就可以包括很多了,如年龄、性别、饮食习惯、幽门螺杆菌感染等。然后通过逻辑回归分析,可以得到自变量的权重,同时根据该权值可以根据危险因素预测一个人患癌症的可能性。

逻辑回归的因变量可以是二分类的,如上述中是否患胃癌;也可以是多分类的,如MNIST手写识别,但是二分类的更为常用,也更加容易解释。所以实际中最常用的就是二分类的逻辑回归。

假设现在有一些数据点,我们利用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作为回归,如下图所示:

逻辑回归是一种二分类算法,它利用的是Sigmoid函数阈值在[0,1]这个特性。逻辑回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。其实,逻辑回归本质上是一个基于条件概率的判别模型(Discriminative Model)。

二、逻辑回归

1. 线性回归

逻辑回归在本质上其实是由线性回归衍变而来的,因此想要更好地理解逻辑回归,先让我们复习一下线性回归。线性回归的原理其实就是用一个线性回归方程来描述一个线性回归的问题。而线性回归的方程可以写作一个几乎大家都熟悉的方程:

在这个方程中,w0被称作截距,w1 ~ wn 被称作系数,这个线性回归方程也可以用矩阵来表示:

通过求出函数z,线性回归便完成了使用输入的特征矩阵X得到了一组连续型的标签值y_pred的操作,从而就可以完成对各种连续型变量的预测任务了。

但是线性回归模型更多地被用于对连续型数据进行预测,很少甚至是不被用于对离散型数据进行分类。因此为了实现回归模型可以对离散型数据进行分类操作,就有了逻辑回归这个回归模型。在逻辑回归算法中,为了实现分类的效果,我们通常使用的就是sigmoid函数

2. sigmoid函数

为了实现Logistic回归分类,我们可以在每个特征上都乘以一个回归系数,然后把所有的结果值相加,将这个总和代入Sigmoid函数中,进而得到一个范围在0~1之间的数值。任何大于0.5的数据被分入1类,小于0.5即被归入0类。所以,Logistic回归也可以被看成是一种概率估计。

输入数据

,经过函数映射为

,该函数为sigmoid函数,形式为

输入和输出形式:

输入:

输出:

,其中

这里

如图所示,分别为输入数据和待求参数,

为偏置项,为了后续推导方便,设定:

,即

输出值

就是概率值,对

中参数

的求导过程如下所示,后面会用到,先求出来放在这里哈:

求导过程为除法求导运算法则,需要注意一个推导公式:

3. 极大似然估计

逻辑回归与极大似然估计的关系:

最大似然估计就是通过已知结果去反推最大概率导致该结果的参数。极大似然估计是概率论在统计学中的应用,它提供了一种给定观察数据来评估模型参数的方法,即 “模型已定,参数未知”,通过若干次试验,观察其结果,利用实验结果得到某个参数值能够使样本出现的概率为最大,则称为极大似然估计。逻辑回归是一种监督式学习,是有训练标签的,就是有已知结果的,从这个已知结果入手,去推导能获得最大概率的结果参数θ,只要我们得出了这个参数,那我们的模型就自然可以很准确的预测未知的数据了。

之前提到了

可以视为类1的后验概率,所以有:

将上面两式写为一般形式

接下来使用极大似然估计来根据给定的训练集估计出参数w:

为了简化运算,我们对上述等式两边取一个对数:

现在要求使得

最大的

,在

前面加一个负号就变为最小化负对数似然函数:

如此就得到了代价函数。让我们更好地理解这个代价函数:

等价于:

可以看出,如果样本的类别为1,估计值ϕ(z)越接近1付出的代价越小,反之越大。

同理,如果样本的值为0的话,估计值ϕ(z)越接近于0付出的代价越小,反之越大。

4. 利用梯度下降法求解参数w

首先解释一些问什么梯度的负方向就是代价函数下降最快的方向,借助于泰勒展开:

均为向量,那么两者的内积就等于:

当θ=π时,也就是在f′(x)的负方向时,取得最小值,也就是下降的最快方向了。

梯度下降:

η为学习率,用来控制步长

所以,在使用梯度下降法更新权重时,只要根据下式即可:

(xj代表第j列特征,wj代表第j个特征对应的参数)

当样本量极大的时候,每次更新权重都需要遍历整个数据集,会非常耗时,这时可以采用随机梯度下降法:

每次仅用一个样本点来更新回归系数,这种方法被称作随机梯度上升法。(由于可以在新样本到来时对分类器进行增量式更新,因此随机梯度算法是一个在线学习算法。)它与梯度上升算法效果相当,但占用更少的资源。

三、逻辑回归的优缺点

1. 优点

(1)适合分类场景

(2)计算代价不高,容易理解实现。

(3)不用事先假设数据分布,这样避免了假设分布不准确所带来的问题。

(4)不仅预测出类别,还可以得到近似概率预测。

(5)目标函数任意阶可导。

2. 缺点

(1)容易欠拟合,分类精度不高。

(2)数据特征有缺失或者特征空间很大时表现效果并不好。

四、分析数据:画出决策边界

def plotBestFit(dataArr, labelMat, weights):
    """
    画出决策边界
    :param dataArr: 特征值数组
    :param labelMat: 类型数组
    :param weights: 最佳回归系数
    :return:
    """
    # 通过shape函数获得dataArr的行列数,其中[0]即行数
    n = shape(dataArr)[0]
    # xCord1和yCord1是类型为1的点的x和y坐标值
    xCord1 = []
    yCord1 = []
    # xCord2和yCord1是类型为0的点的x和y坐标值
    xCord2 = []
    yCord2 = []
    # 特征数组的每一行和类型数组的没每一列一一对应
    for i in range(n):
        # 当类型为1时,
        # 将特征数组中的指定行的1和2两个下标下的值分别作为x轴和y轴的值
        if int(labelMat[i]) == 1:
            xCord1.append(dataArr[i, 1])
            yCord1.append(dataArr[i, 2])
        # 当类型为0时,
        # 将特征数组中的指定行的1和2两个下标下的值分别作为x轴和y轴的值
        else:
            xCord2.append(dataArr[i, 1])
            yCord2.append(dataArr[i, 2])
    # figure()操作时创建或者调用画板
    # 使用时遵循就近原则,所有画图操作是在最近一次调用的画图板上实现。
    fig = plt.figure()
    # 将fig分成1×1的网格,在第一个格子中加载ax图
    # 参数111表示“1×1网格中的第1个表格”
    # 如果参数是211则表示“2行1列的表格的中的第一个表格”
    # 第几个表格的计算顺序为从左到右,从上到下
    ax = fig.add_subplot(111)
    # 设置散点图参数
    # 前两个参数xCord1,yCord1表示散点对应的x和y坐标值
    # s=30表示散点大小为30
    # c='red'表示散点颜色为红色
    # marker='s'表示散点的形状,这里是正方形
    ax.scatter(xCord1, yCord1, s=30, c='red', marker='s')
    # 同上说明
    ax.scatter(xCord2, yCord2, s=30, c='green')
    # 生成一个[-3.0, 3.0]范围中间隔每0.1取一个值
    x = arange(-3.0, 3.0, 0.1)
    # y相对于x的函数
    """
    这里的y是怎么得到的呢?
        从dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        可得:w0*x0+w1*x1+w2*x2 = z
        x0最开始就设置为1,x2就是我们画图的y值,x1就是我们画图的x值。
        所以:w0 + w1*x + w2*y = 0
        →   y = (-w0 - w1 * x) / w2
    """
    y = (-weights[0] - weights[1] * x) / weights[2]
    # 画线
    ax.plot(x, y)
    # 设置x轴和y轴的名称
    plt.xlabel('x1')
    plt.ylabel('x2')
    # 展示图像
    plt.show()

输出:

if __name__ == '__main__':
    dataMats, classMats = loadDataSet()
    dataArr = array(dataMats)
    weights = array(gradAscent(dataMats, classMats))
    plotBestFit(dataArr, classMats, weights)  # 调用该函数话决策边界

输出图:

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号