一、逻辑回归概述

1.定义

Logistic回归是一种广义线性回归(generalized linear model),因此与多重线性回归分析有很多相同之处。它们的模型形式基本上相同,都具有 w’x+b,其中w和b是待求参数,其区别在于他们的因变量不同,多重线性回归直接将w’x+b作为因变量,即y =w’x+b,而logistic回归则通过函数L将w’x+b对应一个隐状态p,p =L(w’x+b),然后根据p 与1-p的大小决定因变量的值。逻辑回归假设数据服从伯努利分布,通过极大似然估计的方法,运用梯度下降来求解参数,来达到数据二分类的目的。

2.原理

逻辑回归的原理是基于线性回归,但是通过引入一个sigmoid函数将线性回归的连续值映射到0和1之间,从而实现对二分类问题的处理。在逻辑回归中,我们假设输出变量y服从伯努利分布,即y只取0和1两个值,并且给定x的条件下,y取1的概率是p,取0的概率是1-p。

二、Sigmoid函数

Sigmoid函数是⼀个⾃然的选择,因为它是⼀个平滑的、可微的阈值单元近似。sigmoid函数在神经网络中常被用于二元分类任务,因为它可以将输入转换成概率值。Sigmoid函数是一个在生物学中常见的S型函数,也称为逻辑函数,它可以将一个实数映射到(0,1)的区间内。在深度学习和机器学习的上下文中,它经常被用作神经元的激活函数,因为它可以将任意输入压缩到0和1之间,从而方便地进行概率解释。需要注意的是,当输入x非常大或非常小时,Sigmoid函数的梯度会变得非常小,可能导致在训练神经网络时出现梯度消失的问题。

在这里插入图片描述

三、梯度上升算法

逻辑回归的梯度上升算法与梯度下降算法在本质上是相似的,但方向相反。梯度下降算法用于最小化损失函数,而梯度上升算法则用于最大化某个函数,如最大似然函数。在逻辑回归的上下文中,我们虽然经常使用梯度下降来最小化损失函数(如交叉熵损失),但为了理解梯度上升的概念,我们可以假设我们要最大化一个与逻辑回归相关的函数,如对数似然函数。

以下是逻辑回归梯度上升算法的基本步骤和解释:

1.定义损失函数(或目标函数):在逻辑回归中,我们通常使用对数似然函数作为目标函数,因为它度量了模型参数与训练数据的匹配程度。对数似然函数越大,模型参数越合理。

2计算梯度:梯度是函数在某一点上变化最快的方向。在逻辑回归中,我们需要计算对数似然函数关于模型参数(即权重向量和偏置项)的梯度。这可以通过求导来实现。

3.选择初始参数:在开始梯度上升之前,我们需要为模型参数选择一个初始值。这些初始值可以是随机的,也可以是预先设定的。

4.执行梯度上升:在梯度上升算法中,我们沿着梯度的方向更新模型参数,以使得对数似然函数值增加。具体地,我们将当前参数值加上梯度的某个比例(即学习率)来得到新的参数值。这个过程不断重复,直到满足某个停止条件(如达到最大迭代次数或梯度值变得非常小)。

5.返回优化后的参数:当梯度上升算法停止时,我们返回优化后的模型参数。这些参数使得对数似然函数值尽可能大,从而得到了一个较好的逻辑回归模型。

四、实验

1.代码

#Logistic 回归
from numpy import *
import matplotlib.pyplot as plt
#加载数据集
def loadDataSet():
    dataMat=[]; labelMat=[]
    fr=open("testSet.txt")
    for line in fr.readlines():#逐行读取
        lineArr=line.strip().split()#对testSet文件进行分割
        dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])#默认X0=1.0,文件中每行的前两个值X1和X2
        labelMat.append(int(lineArr[2]))  #每行的第三个值(数据的类别标签)
    return dataMat,labelMat 
 
#Sigmoid函数 
def sigmoid(inX):
    return 1.0/(1+exp(-inX))#对应Sigmoid函数
 
#梯度上升算法
def gradAscent(dataMatIn,classLabels):
    dataMatrix=mat(dataMatIn)#dataMatIn作为二维数组,每列代表不同的特征,每行代表每个训练样本
    labelMat=mat(classLabels).transpose()#类别标签,1*100的行向量进行转置变成列向量再赋值给labelMat
    m,n=shape(dataMatrix)
    alpha=0.001#目标移动的步长
    maxCycles=500#迭代次数为500
    weights=ones((n,1))
    for k in range(maxCycles):
        h=sigmoid(dataMatrix*weights)#变量h是列向量而不是数值
        error=(labelMat-h)
        weights=weights+alpha*dataMatrix.transpose()*error#梯度上升算法迭代公式,这里的error是向量
    return weights#返回训练好的回归系数
 
#绘制图像显示数据集的分布和最佳拟合直线
def plotBestFit(weights):
    import matplotlib.pyplot as plt
    dataMat,labelMat=loadDataSet()#获取数据集dataMat和标签集labelMat
    dataArr=array(dataMat)#数据集转换为数组操作
    n=shape(dataArr)[0]#n为数据集的行数
    xcord1=[];ycord1=[]#xcord1和ycord1存储类别为1的数据点
    xcord2=[];ycord2=[]#xcord2和ycord2存储类别为2的数据点
    for i in range(n):
        if int(labelMat[i])==1:
            xcord1.append(dataArr[i,1]);ycord1.append(dataArr[i,2])
        else:
            xcord2.append(dataArr[i,1]);ycord2.append(dataArr[i,2])
    fig=plt.figure()#创建图形对象fig
    ax=fig.add_subplot(111)
    ax.scatter(xcord1,ycord1,s=30,c='red',marker='s')
    ax.scatter(xcord2,ycord2,s=30,c='green')
    x=arange(-3.0,3.0,0.1)
    y=(-weights[0]-weights[1]*x)/weights[2]#根据weights计算纵坐标y
    ax.plot(x,y)
    plt.xlabel('X1');plt.ylabel('X2')
    plt.show()
 
#随机梯度上升算法
def stocGradAscent0(dataMatrix,classLabels):
    m,n=shape(dataMatrix)
    alpha=0.01
    weights=ones(n)
    for i in range(m):
        h=sigmoid(sum(dataMatrix[i]*weights))#数值
        error=classLabels[i]-h#数值
        weights=weights+alpha*error*dataMatrix[i]
    return weights
 
#改进后的随机梯度上升算法
def stocGradAscent1(dataMatrix,classLabels,numIter=150):
    m,n=shape(dataMatrix)
    weights=ones(n)
    for j in range(numIter): 
        dataIndex=list(range(m))
        for i in range(m):
            alpha=4/(1.0+j+i)+0.01#alpha在每次迭代时都会调整
            randIndex=int(random.uniform(0,len(dataIndex)))#随机选取样本
            h=sigmoid(sum(dataMatrix[randIndex]*weights))
            error=classLabels[randIndex]-h
            weights=weights+alpha*error*dataMatrix[randIndex]
            del(dataIndex[randIndex])
    return weights
 
#main函数调用各个相关函数
if __name__=='__main__':  
    dataArr,labelMat=loadDataSet()
    print(dataArr)
    print(labelMat)
    weights1=gradAscent(dataArr,labelMat)
    print(weights1)
    plotBestFit(weights1.getA())
    weights2=stocGradAscent0(array(dataArr),labelMat)
    plotBestFit(weights2)
    weights3=stocGradAscent1(array(dataArr),labelMat)
    plotBestFit(weights3)

2.运行结果

绘制的数据集及最佳拟合直线展示在坐标图中。分类结果较好,仅错分几个数据。
在这里插入图片描述
数据data以数组[X0,X1,X2]形式展现,分类标签是一个1*100的行向量,同时输出梯度上升算法所需的参数,即一组回归系数。在这里插入图片描述

3.实验小结

本次实验我们学习了对逻辑回归算法的具体实现,逻辑回归应用于分类问题,常用于二分类问题。逻辑回归的目的就是找到Sigmoid函数的最佳拟合参数,求解最佳拟合参数的过程可以通过最优化算法实现,最优化算法有很多种,比如梯度上升、梯度下降等等。本次实验,我们使用梯度上升优化方法,但是梯度上升算法在处理样本较多的数据时,会有复杂度过高的情况。因此我们又提出了一种处理方法——随机梯度上升算法,仅迭代一次的随机梯度算法的分类器性能较差,所以我们对随机梯度上升算法进行改进,改进后的随机梯度上升算法的结果与梯度上升算法的结果类似,但是迭代的次数明显更少。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐