logistic回归原理以及实现

本文介绍了线性模型、回归的基本概念,重点讲解了最小二乘法参数求解和对数线性回归的应用,以及Logistic回归的原理,包括Sigmoid函数和梯度上升算法的运用。实验比较了梯度上升和随机梯度上升在不同场景下的性能。
摘要由CSDN通过智能技术生成

目录

线性模型与回归

最小二乘与参数求解

对数线性回归

Logistic回归


线性模型与回归

        机器学习最常见的场景是监督学习: 给定一些数据,使用计算机学习到一种模式,然后用它来预测新的数据。一个简单的监督学习任务可以表示为,给定N个两两数据对(xi,yi),使用某种机器学习模型对其进行建模,得到一个模型 (model),其中某个给定的数据对为样本(sample),x 为特征 (feature) ,y 为真实值 (label)。

        中学时,我们经常使用上面的方程来解一些数学问题,方程描述了变量 y 随着变量 而变化。方程从图形上来看,是一条直线。如果建立好这样的数学模型,已知  我们就可以得到预测的》了。统计学家给变量带上了一个小帽子,表示这是预测值,以区别于真实观测到的数据。方程只有一个自变量 a,且不含平方立方等非一次项,因此被称为一元线性方程。

        如下图所示,但是直线并不唯一,即改变w和b的值获得不同的直线,在此过程中寻找最佳参数。

        但是我们要如何选取最佳的w和b呢?这就要采用最小二乘法

最小二乘与参数求解

图片来源) 

        最小二乘法是由勒让德在19世纪发现的,形式如下式:

        观测值就是我们的多组样本,理论值就是我们的假设拟合函数。目标函数也就是在机器学习中常说的损失函数,我们的目标是得到使目标函数最小化时候的拟合函数的模型。 

对数线性回归

        对数线性回归引入主要是为了实现线性模型预测非线性复杂的函数

        线性回归模型: y=f(x)=wx+b

         可推广至: y=g(f(x))=g(wx+b)          其中g为单调可微函数

        例如设g(x)=ex,取y的对数,即lny,就可以得到对数线性回归模型:

Logistic回归

        Logistic回归(Logistic Regression)是一种广义线性模型,通常用于二分类问题,也可以扩展到多分类问题。Logistic回归中采用单位阶跃函数(也可称为阈值函数)是为了得到一个二分类器,来对样本进行分类预测。而由于阶跃函数不连续、不可导,因此采用sigmoid函数的平滑版本是更为合适的选择。它采用的是sigmoid函数作为激活函数,将输入映射到0到1之间的概率值,表示属于某个类别的概率。

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

        线性模型可以衍生出一般形式:

        g(∙)称为联系函数(link function),该函数一般为单调可微函数。


 

具体实现

 数据 testSet.tet,可自行创建txt文档保存

-0.017612   14.053064   0
-1.395634   4.662541    1
-0.752157   6.538620    0
-1.322371   7.152853    0
0.423363    11.054677   0
0.406704    7.067335    1
0.667394    12.741452   0
-2.460150   6.866805    1
0.569411    9.548755    0
-0.026632   10.427743   0
0.850433    6.920334    1
1.347183    13.175500   0
1.176813    3.167020    1
-1.781871   9.097953    0
-0.566606   5.749003    1
0.931635    1.589505    1
-0.024205   6.151823    1
-0.036453   2.690988    1
-0.196949   0.444165    1
1.014459    5.754399    1
1.985298    3.230619    1
-1.693453   -0.557540   1
-0.576525   11.778922   0
-0.346811   -1.678730   1
-2.124484   2.672471    1
1.217916    9.597015    0
-0.733928   9.098687    0
-3.642001   -1.618087   1
0.315985    3.523953    1
1.416614    9.619232    0
-0.386323   3.989286    1
0.556921    8.294984    1
1.224863    11.587360   0
-1.347803   -2.406051   1
1.196604    4.951851    1
0.275221    9.543647    0
0.470575    9.332488    0
-1.889567   9.542662    0
-1.527893   12.150579   0
-1.185247   11.309318   0
-0.445678   3.297303    1
1.042222    6.105155    1
-0.618787   10.320986   0
1.152083    0.548467    1
0.828534    2.676045    1
-1.237728   10.549033   0
-0.683565   -2.166125   1
0.229456    5.921938    1
-0.959885   11.555336   0
0.492911    10.993324   0
0.184992    8.721488    0
-0.355715   10.325976   0
-0.397822   8.058397    0
0.824839    13.730343   0
1.507278    5.027866    1
0.099671    6.835839    1
-0.344008   10.717485   0
1.785928    7.718645    1
-0.918801   11.560217   0
-0.364009   4.747300    1
-0.841722   4.119083    1
0.490426    1.960539    1
-0.007194   9.075792    0
0.356107    12.447863   0
0.342578    12.281162   0
-0.810823   -1.466018   1
2.530777    6.476801    1
1.296683    11.607559   0
0.475487    12.040035   0
-0.783277   11.009725   0
0.074798    11.023650   0
-1.337472   0.468339    1
-0.102781   13.763651   0
-0.147324   2.874846    1
0.518389    9.887035    0
1.015399    7.571882    0
-1.658086   -0.027255   1
1.319944    2.171228    1
2.056216    5.019981    1
-0.851633   4.375691    1
-1.510047   6.061992    0
-1.076637   -3.181888   1
1.821096    10.283990   0
3.010150    8.401766    1
-1.099458   1.688274    1
-0.834872   -1.733869   1
-0.846637   3.849075    1
1.400102    12.628781   0
1.752842    5.468166    1
0.078557    0.059736    1
0.089392    -0.715300   1
1.825662    12.693808   0
0.197445    9.744638    0
0.126117    0.922311    1
-0.679797   1.220530    1
0.677983    2.556666    1
0.761349    10.693862   0
-2.168791   0.143632    1
1.388610    9.341997    0
0.317029    14.739025   0
import numpy as np
import array
import random


#数据加载
def loadDataSet():
    dataMat = []
    labelMat = []
    fr = open('D:/yy-study/python/machine-learning/6.逻辑回归/testSet.txt')
    for line in fr.readlines():
        #对于每行数据,使用strip去掉前后的空格,使用split按照空格拆分成一个列表lineArr。
        #将lineArr中的第一个元素转换成float类型并作为样本的第一个特征,将lineArr中的第二个元素转换成float类型并作为样本的第二个特征。
        #将lineArr中的第三个元素转换成int类型并作为样本的标签。
        lineArr = line.strip().split()
        dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat
    #将样本特征和标签分别添加到dataMat和labelMat中,并返回它们。

#Sigmoid函数
def sigmoid(inX):
    return 1.0/(1+np.exp(-inX))

以下这段代码是实现Logistic回归模型的核心部分,采用梯度上升算法来更新模型参数。具体实现如下:

        首先,将输入的样本数据和标签转化为numpy的矩阵形式,方便后续的矩阵运算。

        然后,获取样本矩阵的行数和列数,同时设置学习率alpha和最大迭代次数maxCycles

        初始化权重向量weight,其中所有元素均为1.0。

        在进行梯度上升迭代时,我们需要计算当前权重向量对应的模型预测值h,并计算误差值error。其中,模型预测值的计算采用了前面提到的sigmoid函数。

        接着,根据梯度上升的迭代公式,更新权重向量weight。在这里,我们使用矩阵运算来计算梯度,可以极大地简化代码编写和运算速度。

        在每次迭代中,我们都更新了一次权重向量weight。当达到最大迭代次数或者误差足够小的时候,算法停止迭代,并返回最终权重向量。

def gradAscent(dataMathIn,classLabel):
    dataMatrix = np.mat(dataMathIn) #将列表转化为numpy的矩阵
    labelMat = np.mat(classLabel).transpose()   #将列表转化为矩阵,并求转置(transpose)
    m,n = np.shape(dataMatrix)
    alpha = 0.001
    maxCycles = 500     #迭代次数
    weight = np.ones((n,1))
    for k in range(maxCycles):
        h = sigmoid(dataMatrix*weight)
        error = labelMat - h    #(y-h)误差值
        weight = weight + alpha*dataMatrix.transpose()*error #w=w+alpha*(y-h)*x梯度上升的迭代公式
    return weight
#画出决策边界
def plotBestFit(weight):
    import matplotlib.pyplot as plt
    dataMat,labelMat = loadDataSet()
    dataArr = np.array(dataMat)
    n = np.shape(dataArr)[0] #[0]求dataArr的行数,1,是求列数
    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []
    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()
    ax = fig.add_subplot(111)   #添加subplot
    ax.scatter(xcord1,ycord1,s = 30,c='red',marker = 's')   #绘制正样本
    ax.scatter(xcord2,ycord2,s = 30, c = 'green')   #绘制负样本
    w = np.array(weight)
    x = np.arange(-3.0,3.0,0.1) #X轴的取值范围
    y = (-w[0] - w[1] * x) / w[2] #设sigmoid =0,因为sigmoid = 0是两种类别的分界线  sigmoid = w0x0+w1x1+w2x2 = 0
    ax.plot(x,y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()

#随机梯度上升
def stoGradAscent0(dataMatrix,classLabels):
    dataMatrix=np.array(dataMatrix)
    m,n = np.shape(dataMatrix)
    alpha = 0.01
    weight = np.ones(n)  #获取样本数组的行数和列数,设置学习率alpha和初始化权重向量weight,其中所有元素均为1.0。
    #在每次迭代中,随机选择一个样本,计算该样本对应的模型预测值h,并计算误差值error。其中,模型预测值的计算采用了前面提到的sigmoid函数。
    #接着,根据随机梯度上升的迭代公式,更新权重向量weight。在这里,我们使用数组运算来计算梯度,可以极大地简化代码编写和运算速度。
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i]*weight))
        error = classLabels[i] - h
        weight = weight +alpha*error*dataMatrix[i]
    return weight



#随机梯度算法的改进
def stoGradAscent1(dataMatrix,classLabels,numIter = 150):
    dataMatrix=np.array(dataMatrix)
    m,n = np.shape(dataMatrix)
    weight = np.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的大小,每次减小1/(j+i)。
            randIndex = int(random.uniform(0,len(dataIndex))) #随机选取样本,可以实现随机选取更新
            h = sigmoid(sum(dataMatrix[randIndex]*weight))
            error = classLabels[randIndex] - h
            weight = weight + alpha*error*dataMatrix[randIndex]
            del(dataIndex[randIndex])
    return weight
dataMat,labelMat = loadDataSet()
# weight=gradAscent(dataMat,labelMat)
weight = stoGradAscent1(dataMat,labelMat)
plotBestFit(weight)

 实验小结

在本次Logistic回归实验中,我使用了梯度上升算法和随机梯度上升算法来训练模型。通过实验,我得出了以下结论和总结:

  1. 数据预处理:在实验开始之前,我对数据进行了适当的预处理,包括数据清洗、特征选择和特征缩放。这些步骤有助于提高模型对数据的拟合效果。

  2. 算法选择:我比较了梯度上升算法和随机梯度上升算法的性能表现。在实验中发现,随机梯度上升算法在处理大规模数据集时具有一定的优势,而梯度上升算法在小规模数据集上可能更有效。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值