机器学习4(Logistic回归)

Logistics回归模型通常被用于处理二分类问题,它是一种用于分析各个影响因素(x1,x2,...xn)与分类结果y之间关系的有监督学习方法。虽然它的名字是"回归",但实际却是一种分类学习方法。这里的"回归"一词源于最佳拟合,表示要找到最佳拟合参数集,因此,logistic训练分类器时的做法就是寻找最佳拟合参数,使用的是最优化方法。

1.Logistic回归概述

我们都知道使用线性模型可以进行回归学习,但若要做的是分类任务改如何处理?只需要找一个单调可微函数将分类任务的真实标记y与线性回归模型的预测值联系起来。

考虑二分类任务,其输出标记y的取值为0和1,而线性回归模型产生的预测值是实值,于是需将实值z转换为0/1值。通过Sigmoid函数引入非线性因素,可以实现实值z转换为0/1值,处理二分类问题。

1.1 Sigmoid函数

首先我们先介绍Sigmoid函数,也称为逻辑函数
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> g ( x ) = 1 1 + e − x g(x) = \frac{1}{1+e^{-x}} </math>g(x)=1+e−x1

其函数图像如下

从上图可以看出sigmoid函数是一个s形的曲线,它的取值是[0,1]之间,在远离0的地方函数的值会很快接近0或者1。它的这个特性对于解决二分类问题十分重要。

逻辑回归的假设函数形式如下:

<math xmlns="http://www.w3.org/1998/Math/MathML"> y = g ( ω T x + b ) g ( z ) = 1 1 + e − z y=g(\omega^Tx+b )\quad g(z) = \frac{1}{1+e^{-z}} </math>y=g(ωTx+b)g(z)=1+e−z1

所以:

<math xmlns="http://www.w3.org/1998/Math/MathML"> y = g ( ω T x + b ) 变为 y = 1 1 + e − ω T x + b y=g(\omega^Tx+b )\quad 变为 y = \frac{1}{1+e^{-{\omega^Tx+b}}} </math>y=g(ωTx+b)变为y=1+e−ωTx+b1

其中x是我们的输入,w和b为我们要求取的参数

若将y视为样本x作为正例的可能性,则1-y是其反例可能性,两者的比值为 <math xmlns="http://www.w3.org/1998/Math/MathML"> y 1 − y \frac{y}{1-y} </math>1−yy称为"几率",反映了x作为正例的相对可能性

样本作为正例的相对可能性的对数
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> l n y 1 − y = l n p ( y = 1 ∣ x ) p ( y = 0 ∣ x ) = ω T x + b ln \frac{y}{1-y}=ln\frac{p(y=1|x)}{p(y=0|x)}=\omega^Tx+b </math>ln1−yy=lnp(y=0∣x)p(y=1∣x)=ωTx+b

因此有:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> p ( y = 1 ∣ x ) = e ω T x + b 1 + e ω T x + b p(y=1|x) = \frac{e^{\omega^Tx+b}}{1+e^{\omega^Tx+b}} </math>p(y=1∣x)=1+eωTx+beωTx+b
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> p ( y = 1 ∣ x ) = 1 1 + e ω T x + b p(y=1|x) = \frac{1}{1+e^{\omega^Tx+b}} </math>p(y=1∣x)=1+eωTx+b1

上面两个式子分别表示y=1和y=0的概率。上述过程我们通过sigmoid函数将z值映射到0到1之间,获得数值之后就可以进行分类。如定义阈值为0.5,y*为分类结果,则 <math xmlns="http://www.w3.org/1998/Math/MathML"> y ∗ = 1 , i f P ( y = 1 ∣ x ) > 0.5 , y ∗ = 0 , i f P ( y = 1 ∣ x ) ⩽ 0.5 y^*=1,ifP(y=1|x)>0.5,y^*=0,ifP(y=1|x)\leqslant0.5 </math>y∗=1,ifP(y=1∣x)>0.5,y∗=0,ifP(y=1∣x)⩽0.5实际应用时特定的情况可以选择不同的阈值。接下来我们要解决的问题就是获得最佳回归系数,即求解w和b得值。

1.2 基于最优化方法的最佳回归系数确定

1.2.1 极大似然估计

极大似然估计的方法步骤:

  • 确定待求解的未知参数 <math xmlns="http://www.w3.org/1998/Math/MathML"> θ 1 , θ 2 , . . . θ n \theta_1,\theta_2,...\theta_n </math>θ1,θ2,...θn,如均值、方差或特定分布函数的参数等;
  • 计算每个样本 <math xmlns="http://www.w3.org/1998/Math/MathML"> X 1 , X 2 , . . . , X n X_1,X_2,...,X_n </math>X1,X2,...,Xn的概率密度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> f ( X i ; θ 1 , θ 2 , . . . θ m ) f(X_i;\theta_1,\theta_2,...\theta_m) </math>f(Xi;θ1,θ2,...θm);
  • 根据样本的概率密度累乘构造似然函数 <math xmlns="http://www.w3.org/1998/Math/MathML"> L ( θ 1 , θ 2 , . . . θ m ) = ∏ f ( X i ; θ 1 , θ 2 , . . . θ m ) L(\theta_1,\theta_2,...\theta_m)=\prod{f(X_i;\theta_1,\theta_2,...\theta_m)} </math>L(θ1,θ2,...θm)=∏f(Xi;θ1,θ2,...θm);
  • 通过似然函数最大化(求导为0),求解未知参数θ,为了降低计算难度,可采用对数加法替换概率乘法,通过导数为0/极大值来求解未知参数。

我们可通过"极大似然法"来估计w和b,给定数据集{ <math xmlns="http://www.w3.org/1998/Math/MathML"> ( x i , y i ) (x_i,y_i) </math>(xi,yi)} <math xmlns="http://www.w3.org/1998/Math/MathML"> i = 1 m {}^m_{i=1} </math>i=1m最大化样本属于其真实标记的概率,等同于最大化对数似然函数
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> l ( ω , b ) = ∑ i = 1 m l n p ( y i ∣ x i ; ω , b ) l(\omega,b)=\sum_{i=1}^mlnp(y_i|x_i;\omega,b) </math>l(ω,b)=i=1∑mlnp(yi∣xi;ω,b)

方便于讨论,令 <math xmlns="http://www.w3.org/1998/Math/MathML"> β = ( ω ; b ) , x , = ( x ; 1 ) \beta=(\omega;b),x^,=(x;1) </math>β=(ω;b),x,=(x;1),则 <math xmlns="http://www.w3.org/1998/Math/MathML"> ω T x + b \omega^Tx+b </math>ωTx+b可简化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> β T x , \beta^Tx^, </math>βTx,

令 <math xmlns="http://www.w3.org/1998/Math/MathML"> p 1 ( x , ; β ) = p ( y = 1 ∣ x , ; β ) , p 0 ( x , ; β ) = p ( y = 0 ∣ x , ; β ) = 1 − p 1 ( x , ; β ) p_1(x^,;\beta)=p(y=1|x^,;\beta),p_0(x^,;\beta)=p(y=0|x^,;\beta)=1-p_1(x^,;\beta) </math>p1(x,;β)=p(y=1∣x,;β),p0(x,;β)=p(y=0∣x,;β)=1−p1(x,;β),则上述式中的似然项可重写为
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> p ( y i ∣ x i ; ω , b ) = y i p 1 ( x , ; β ) + ( 1 − y i ) p 0 ( x , ; β ) p(y_i|x_i;\omega,b)=y_ip_1(x^,;\beta)+(1-y_i)p_0(x^,;\beta) </math>p(yi∣xi;ω,b)=yip1(x,;β)+(1−yi)p0(x,;β)

根据sigmoid函数,似然函数可重写为
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> l ( ω , b ) = ∑ i = 1 m ( − y i β T x i + l n ( 1 + e β T x i ) ) l(ω,b)=\sum_{i=1}^m(-y_i\beta^Tx_i+ln(1+e^{\beta^Tx_i})) </math>l(ω,b)=i=1∑m(−yiβTxi+ln(1+eβTxi))

最大化对数似然函数等价于最小化 <math xmlns="http://www.w3.org/1998/Math/MathML"> l ( β ) l(\beta) </math>l(β), <math xmlns="http://www.w3.org/1998/Math/MathML"> l ( β ) l(\beta) </math>l(β)是关于 <math xmlns="http://www.w3.org/1998/Math/MathML"> β \beta </math>β的高阶可导连续凸函数,经典的数值优化算法如梯度下降法可求得其最优解

1.2.2梯度上升法

梯度上升法基本的思想是:要找到某函数的 最大值,最好的方法是沿着该函数的梯度方向探寻。如果梯度记为∇,则函数f(x,y)的梯度由 下式表示:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ∇ f ( x , y ) = [ ∂ f ( x , y ) ∂ x ∂ f ( x , y ) ∂ y ] \nabla f(x,y)=\begin{bmatrix} \frac{\partial f(x,y)}{\partial x}\\ \quad\\ \frac{\partial f(x,y)}{\partial y} \end{bmatrix} </math>∇f(x,y)=⎣ ⎡∂x∂f(x,y)∂y∂f(x,y)⎦ ⎤

这个梯度意味着要沿x的方向移动 <math xmlns="http://www.w3.org/1998/Math/MathML"> ∂ f ( x , y ) ∂ x \frac{\partial f(x,y)}{\partial x} </math>∂x∂f(x,y),沿y的方向移动 <math xmlns="http://www.w3.org/1998/Math/MathML"> ∂ f ( x , y ) ∂ x \frac{\partial f(x,y)}{\partial x} </math>∂x∂f(x,y)其中,函数f(x,y) 必须要在待计算的点上有定义并且可微。如下图:

梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2。如此循环迭代,直到满足停止条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向。我们知道了移动的反向,那移动量的大小是多少。该量值称为步长,记做α。用向量来表示的话,梯度上升算法的迭代公式如下:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ω : = ω + α ∇ ω f ( ω ) \omega:=\omega+\alpha\nabla_\omega f(\omega) </math>ω:=ω+α∇ωf(ω)

该公式将一直被迭代执行,直至达到某个停止条件为止,比如迭代次数达到某个指定值或算法达到某个可以允许的误差范围

1.2.3梯度下降算法

梯度下降算法,它与上述的梯度上升算法是一样的,只是公式中的加法需要变成减法。因此,对应的公式可以写成:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ω : = ω − α ∇ ω f ( ω ) \omega:=\omega-\alpha\nabla_\omega f(\omega) </math>ω:=ω−α∇ωf(ω)

梯度上升算法用来求函数的最大值,而梯度下降算法用来求函数的最小值。

2.Logistic实例分析

利用Logistic回归模型根据身高、体重和肺活量预测性别

2.1 准备数据

2.2使用梯度上升算法进行分类

sigmoid函数:

python 复制代码
# sigmoid函数
def sigmoid(inX):
    return 1.0 / (1 + exp(-inX))

梯度上升算法:

python 复制代码
# 梯度上升算法
def gradAscent(dataMatIn, classLabels):                            # dataMatIn数据集、classLabels数据标签
    dataMatrix = mat(dataMatIn)                                    # 转换为NumPy矩阵
    labelMat = mat(classLabels).transpose()                        # 转换为NumPy矩阵,并且矩阵转置
    m, n = shape(dataMatrix)                                       # 获取数据集矩阵的大小,m为行数,n为列数
    alpha = 0.001                                                  # 目标移动的步长
    maxCycles = 500                                                # 迭代次数
    weights = ones((n, 1))                                         # 权重初始化为1
    for k in range(maxCycles):                                     # 重复矩阵运算
        h = sigmoid(dataMatrix * weights)                          # 矩阵相乘,计算sigmoid函数
        error = (labelMat - h)                                     # 计算误差
        weights = weights + alpha * dataMatrix.transpose() * error # 矩阵相乘,更新权重
    return weights

使用Logistic 回归方法进行分类并不需要做很多工作,所需做的只是把测试集上每个特征向量乘以最优化方法得来的回归系数,再将该乘积结果求和,最后输入到Sigmoid函数中即可。如果对应的Sigmoid值大于0.5就预测类别标签为1,否则为0。

python 复制代码
# 分类函数
def classifyVector(inX, weights):
    prob = sigmoid(sum(inX * weights))   # 计算sigmoid值
    if prob > 0.5:                       # 概率大于0.5,返回分类结果1.0
        return 1.0
    else:                                # 概率小于等于0.5,返回分类结果0.0
        return 0.0
python 复制代码
def colicTest1():
    # 读取测试集和训练集,并对数据进行格式化处理
    frTrain = open("D:\syy\MachineLearning\data\dataTrain.txt")     # 读取训练集文件
    frTest = open('D:\syy\MachineLearning\data\dataTest.txt')           # 读取测试集文件
    trainingSet = []                              # 创建数据列表
    trainingLabels = []                           # 创建标签列表
    for line in frTrain.readlines():              # 按行读取
        currLine = line.strip().split('\t')       # 分隔
        lineArr = []
        for i in range(3):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[3]))
 
    # 使用改进的随即上升梯度训练
    trainWeights =  gradAscent(array(trainingSet), trainingLabels)
    errorCount = 0                                # 错误数
    numTestVec = 0.0
    for line in frTest.readlines():               # 遍历每行数据
        numTestVec += 1.0                         # 测试集数量加1
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(3):
            lineArr.append(float(currLine[i]))
        if int(classifyVector(array(lineArr), trainWeights)) != int(currLine[3]):
            errorCount += 1                        # 预测结果与真值不一致,错误数加1
    errorRate = (float(errorCount) / numTestVec)   # 计算错误率
    print("测试的错误率为: %f" % errorRate)
    return errorRate
python 复制代码
# 求结果的平均值
def multiTest():
    numTests = 10
    errorSum = 0.0
    for k in range(numTests):
        errorSum += colicTest1()
    print("在 %d 迭代之后, 平均错误率为: %f" % (numTests, errorSum / float(numTests)))

运行结果如图:

从上述实验结果来看,使用逻辑回归进行性别分类的错误率较高

3.实验总结

  • 逻辑回归的优点:直接对分类的可能性建模,无需事先假设数据分布,避免了假设分布不准确带来的问题,不仅预测出类别,还可得到近似概率预测
  • 缺点:容易欠拟合,分类精度不高,数据特征有缺失或特征空间很大时效果不好
相关推荐
slomay1 小时前
关于对比学习(简单整理
经验分享·深度学习·学习·机器学习
whaosoft-1431 小时前
大模型~合集3
人工智能
Dream-Y.ocean1 小时前
文心智能体平台AgenBuilder | 搭建智能体:情感顾问叶晴
人工智能·智能体
丶21361 小时前
【CUDA】【PyTorch】安装 PyTorch 与 CUDA 11.7 的详细步骤
人工智能·pytorch·python
春末的南方城市1 小时前
FLUX的ID保持项目也来了! 字节开源PuLID-FLUX-v0.9.0,开启一致性风格写真新纪元!
人工智能·计算机视觉·stable diffusion·aigc·图像生成
zmjia1111 小时前
AI大语言模型进阶应用及模型优化、本地化部署、从0-1搭建、智能体构建技术
人工智能·语言模型·自然语言处理
jndingxin2 小时前
OpenCV视频I/O(14)创建和写入视频文件的类:VideoWriter介绍
人工智能·opencv·音视频
AI完全体2 小时前
【AI知识点】偏差-方差权衡(Bias-Variance Tradeoff)
人工智能·深度学习·神经网络·机器学习·过拟合·模型复杂度·偏差-方差
GZ_TOGOGO2 小时前
【2024最新】华为HCIE认证考试流程
大数据·人工智能·网络协议·网络安全·华为
sp_fyf_20242 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘