当前位置:   article > 正文

logistic回归_logistic回归分析

logistic回归分析

logistic回归概述

假设现在有一些数据点,我们用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作回归。利用Logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。这里的“回归”一词源于最佳拟合,表示要找到最佳拟合参数集。训练分类器时的做法就是寻找最佳拟合参数,使用的是最优化算法。

Logistic回归的一般过程

  1. 收集数据:采用任意方法收集数据。
  2. 准备数据:由于需要进行距离计算,因此要求数据类型为数值型。另外,结构化数据格式则最佳。
  3. 分析数据:采用任意方法对数据进行分析。
  4. 训练算法:大部分时间将用于训练,训练的目的是为了找到最佳的分类回归系数。
  5. 测试算法:一旦训练步骤完成,分类将会很快。
  6. 使用算法:首先,我们需要输入一些数据,并将其转换成对应的结构化数值;接着,基于训练好的回归系数就可以对这些数值进行简单的回归计算,判定它们属于哪个类别;在这之后,我们就可以在输出的类别上做一些其他分析工作。

线性模型与回归

线性模型一般形式:
在这里插入图片描述
其中x=(x1, x2, …, xd)是由d维属性描述的样本,其中 xi是 x 在 第 i 个属性上的取值。
向量形式可记为:
在这里插入图片描述
其中w=(w1, w2, …, wd)为待求解系数
在这里插入图片描述

Logistic回归:分类问题

线性模型可以衍生出一般形式:
在这里插入图片描述

g(∙)称为联系函数(link function),该函数一般为单调可微函数。
对数线性回归是 g(∙)=ln(∙) 时广义/多维线性模型的特例。
在这里插入图片描述
预测值与输出标记
在这里插入图片描述
寻找函数将分类标记与线性回归模型输出联系起来。
单位阶跃函数:
在这里插入图片描述
单位阶跃函数缺点:不连续
替代函数——逻辑斯蒂函数(logistic/sigmoid function) – 单调可微、任意阶可导
Sigmoid函数是一种阶跃函数( step function )。在数学中,如果实数域上的某个函数可以用半开区间上的指示函数的有限次线性组合来表示,那么这个函数就是阶跃函数。而数学中指示函数(indicator function)是定义在某集合X上的函数,表示其中有哪些元素属于某一子集A。

在这里插入图片描述
逻辑回归是拟合“y的sigmoid函数”

运用Sigmoid函数
在这里插入图片描述
整合成一个公式,就变成了如下公式:
在这里插入图片描述
对数几率(log odds) – 样本作为正例的相对可能性的对数
在这里插入图片描述
为了实现Logistic回归分类器,我们在每个特征上都乘以一个回归系数,然后把所有的结果值相加,将这个总和代人Sigmoid函数中,进而得到一个范围在0~1之间的数值。任何大于0.5的数据被分入1类,小于0.5即被归入0类。所以,Logistic回归也可以被看成是一种概率估计。

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

梯度上升法

请添加图片描述
梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2.如此循环迭代,知道满足通知条件。迭代的过程中,梯度算子总是保证我们能选取到最佳的移动方向
在这里插入图片描述

在这里插入图片描述

梯度下降

按梯度上升的反方向迭代公式即可在这里插入图片描述
梯度上升算法用来求函数的最大值,而梯度下降算法用来求函数的最小值。

使用梯度上升找到最佳参数

对课本中的例子进行实现,有100个样本点,这些数据有两维特征,因此可以将数据在一个二维平面上展示出来。我们可以将第一列数据(X1)看作x轴上的值,第二列数据(X2)看作y轴上的值。而最后一列数据即为分类标签。根据标签的不同,对这些点进行分类。

# 加载数据
def loadDataSet():
    dataMat = [] 
    labelMat = [] 
    fr = open('testSet.txt')  
    for line in fr.readlines():        
        lineArr = line.strip().split()    
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])  
        labelMat.append(int(lineArr[2]))   
    fr.close()  
    return dataMat, labelMat 
 
# 绘制数据集
def plotDataSet():
    dataMat, labelMat = loadDataSet()#加载数据集
    dataArr = np.array(dataMat) #转换成numpy的array数组
    n = np.shape(dataMat)[0] #数据个数
    xcord1 = []; ycord1 = []#正样本
    xcord2 = []; ycord2 = []#负样本
    for i in range(n): #根据数据集标签进行分类
        if int(labelMat[i]) == 1:
            xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])    #1为正样本
        else:
            xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])    #0为负样本
    fig = plt.figure()
    ax = fig.add_subplot(111)   
    ax.scatter(xcord1, ycord1, s = 20, c = 'red', marker = 's',alpha=.5)
    ax.scatter(xcord2, ycord2, s = 20, c = 'green',alpha=.5)
    plt.title('DataSet') 
    plt.xlabel('x'); plt.ylabel('y') 
    plt.show()  
 
if __name__ == '__main__':
    plotDataSet()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

在这里插入图片描述
sigmoid函数

def sigmoid(inX):
    return 1.0 / (1 + np.exp(-inX))
  • 1
  • 2

梯度上升算法

def gradAscent(dataMatIn,classLabels):
    dataMatrix = np.mat(dataMatIn)              #转换成numpy的mat
    labelMat = np.mat(classLabels).transpose()  #转换后进行转置
    m,n = np.shape(dataMatrix)                  #返回dataMatrix的大小,m为函数,n为列数
    alpha = 0.001                               #移动步长
    maxCycles = 500                             #最大迭代次数
    weights = np.ones((n,1))
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)
        error = labelMat - h
        weights = weights + alpha * dataMatrix.transpose() * error
    return weights.getA()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述
梯度上升算哒在每次更新回归系数时都需要遍历整个数据集(批处理),该方法的计算复杂度随着样本和特征的数量的增多而加大。因此我们使用随机梯度上升算法来改进。随机梯度算法是一个在线学习算法
在随机梯度上升算法中一些系数需要的迭代次数更多,并且大的波动停止后会产生一些小的周期性的波动。产生这种现象的原因是存在一些不能正确分类的样本点,在每次迭代时会引法系数的剧烈改变。而改进的随机梯度上升能解决这一问题

def stocGradAscent1(dataMatrix,classLabels,numIter = 150):
    m,n = np.shape(dataMatrix)
    weights = 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的大小
            randIndex = int(random.uniform(0,len(dataIndex)))       #随机抽取样本
            h = sigmoid(sum(dataMatrix[dataIndex[randIndex]]*weights))  #计算h
            error = classLabels[dataIndex[randIndex]] - h       #计算误差
            weights = weights+alpha * error * dataMatrix[dataIndex[randIndex]]#更新回归函数
            del(dataIndex[randIndex])           #删除已使用的样本
    return weights

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述

逻辑回归实例:从疝气病预测病马的死亡率

本节将使用 Logistic回归来预测患有疝病的马的存活问题。这里的数据包含368个样本和28个特征。我并非育马专家,从一些文献中了解到,疝病是描述马胃肠痛的术语。然而,这种病不定源自马的胃肠问题,其他问题也可能引发马疝病。该数据集中包含了医院检测马疝病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。

  1. 收集数据:给定数据文件。
  2. 准备数据:用 Python解析文本文件并填充缺失值。
  3. 分析数据:可视化并观察数据。
  4. 训练算法:使用优化算法,找到最佳的系数。
  5. 测试算法:为了量化回归的效果,需要观察错误率。根据错误率决定是否回退到训练阶段,通过改变迭代的次数和步长等参数来得到更好的回归系数。
  6. 使用算法:实现一个简单的命令行程序来收集马的症状并输出预测结果并非难事,这可以做为留给读者的一道习题。
import random
import matplotlib.pyplot as plt
import numpy as np

def sigmoid(inX):
    return 1.0/(1+np.exp(-inX))
def stocGradAscent1(dataMatrix,classLabels,numIter = 150):
    m,n = np.shape(dataMatrix)
    weights = 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的大小
            randIndex = int(random.uniform(0,len(dataIndex)))       #随机抽取样本
            h = sigmoid(sum(dataMatrix[dataIndex[randIndex]]*weights))  #计算h
            error = classLabels[dataIndex[randIndex]] - h       #计算误差
            weights = weights+alpha * error * dataMatrix[dataIndex[randIndex]]#更新回归函数
            del(dataIndex[randIndex])           #删除已使用的样本
    return weights

def classifyVector(inX,weights):
    prob = sigmoid(sum(inX*weights))
    if prob >0.5:return 1.0
    else:return 0.0
def colicTest():
    frTrain = open('horseColicTraining.txt')
    frTest = open('horseColicTest.txt')
    trainingSet = [];
    trainingLabels = []
    for line in frTrain.readlines():
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(21):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(lineArr)
    trainWeights = stocGradAscent1(np.array(trainingSet),trainingLabels,1000)
    errorCount = 0;numTestVec = 0.0
    for line in frTest.readlines():
        numTestVec +=1.0
        currLine = line.strip().split('\t')
        lineArr = []
        for i in range(21):
            lineArr.append(float(currLine[i]))
        if int(classifyVector(np.array(lineArr),trainWeights))!= int(currLine[21]):
            errorCount +=1
    errorRata = (float(errorCount)/numTestVec)
    print("the error rate of this test is:%f" % errorRata)
    return errorRata
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

在这里插入图片描述

总结

Logistic回归的目的是寻找一个非线性函数Sigmoid的最佳拟合参数,求解过程可以由最优化算法来完成。在最优化算法中,最常用的就是梯度上升算法,而梯度上升算法又可以简化为随机梯度上升算法。
随机梯度上升算法与梯度上升算法的效果相当,但占用更少的计算资源。此外,随机梯度上升是一个在线算法,它可以在新数据到来时就完成参数更新,而不需要重新读取整个数据集来进行批处理运算。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/541119
推荐阅读
相关标签
  

闽ICP备14008679号