Logistic回归实战篇之预测病马死亡率(二)

作 者:崔家华 编 辑:李文臣

三、从疝气病症状预测病马的死亡率

1、实战背景

本次实战内容,将使用Logistic回归来预测患疝气病的马的存活问题。原始数据集下载地址:http://archive.ics.uci.edu/ml/datasets/Horse+Colic

这里的数据包含了368个样本和28个特征。这种病不一定源自马的肠胃问题,其他问题也可能引发马疝病。该数据集中包含了医院检测马疝病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。另外需要说明的是,除了部分指标主观和难以测量外,该数据还存在一个问题,数据集中有30%的值是缺失的。下面将首先介绍如何处理数据集中的数据缺失问题,然后再利用Logistic回归和随机梯度上升算法来预测病马的生死。

2、准备数据

数据中的缺失值是一个非常棘手的问题,很多文献都致力于解决这个问题。那么,数据缺失究竟带来了什么问题?假设有100个样本和20个特征,这些数据都是机器收集回来的。若机器上的某个传感器损坏导致一个特征无效时该怎么办?它们是否还可用?答案是肯定的。因为有时候数据相当昂贵,扔掉和重新获取都是不可取的,所以必须采用一些方法来解决这个问题。下面给出了一些可选的做法:

  • 使用可用特征的均值来填补缺失值;
  • 使用特殊值来填补缺失值,如-1;
  • 忽略有缺失值的样本;
  • 使用相似样本的均值添补缺失值;
  • 使用另外的机器学习算法预测缺失值。

预处理数据做两件事:

  • 如果测试集中一条数据的特征值已经确实,那么我们选择实数0来替换所有缺失值,因为本文使用Logistic回归。因此这样做不会影响回归系数的值。sigmoid(0)=0.5,即它对结果的预测不具有任何倾向性。
  • 如果测试集中一条数据的类别标签已经缺失,那么我们将该类别数据丢弃,因为类别标签与特征不同,很难确定采用某个合适的值来替换。

原始的数据集经过处理,保存为两个文件:horseColicTest.txt和horseColicTraining.txt。已经处理好的“干净”可用的数据集下载地址:

  • https://github.com/Jack-Cherish/Machine-Learning/blob/master/Logistic/horseColicTraining.txt
  • https://github.com/Jack-Cherish/Machine-Learning/blob/master/Logistic/horseColicTest.txt

有了这些数据集,我们只需要一个Logistic分类器,就可以利用该分类器来预测病马的生死问题了。

3、使用Python构建Logistic回归分类器

在使用Sklearn构建Logistic回归分类器之前,我们先用自己写的改进的随机梯度上升算法进行预测,先热热身。使用Logistic回归方法进行分类并不需要做很多工作,所需做的只是把测试集上每个特征向量乘以最优化方法得来的回归系数,再将乘积结果求和,最后输入到Sigmoid函数中即可。如果对应的Sigmoid值大于0.5就预测类别标签为1,否则为0。

# -*- coding:UTF-8 -*-import numpy as npimport random"""函数说明:sigmoid函数Parameters:    inX - 数据Returns:    sigmoid函数Author:    Jack CuiBlog:    http://blog.csdn.net/c406495762Zhihu:    https://www.zhihu.com/people/Jack--Cui/Modify:    2017-09-05"""def sigmoid(inX):    return 1.0 / (1 + np.exp(-inX))"""函数说明:改进的随机梯度上升算法Parameters:    dataMatrix - 数据数组    classLabels - 数据标签    numIter - 迭代次数Returns:    weights - 求得的回归系数数组(最优参数)Author:    Jack CuiBlog:    http://blog.csdn.net/c406495762Zhihu:    https://www.zhihu.com/people/Jack--Cui/Modify:    2017-09-05"""def stocGradAscent1(dataMatrix, classLabels, numIter=150):
     #返回dataMatrix的大小。m为行数,n为列数。    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的大小,每次减小1/(j+i)。
            randIndex = int(random.uniform(0,len(dataIndex)))
     #随机选取样本
            h = sigmoid(sum(dataMatrix[randIndex]*weights)) 
     #选择随机选取的一个样本,计算h
            error = classLabels[randIndex] - h 
      #计算误差
            weights = weights + alpha
                  * error * dataMatrix[randIndex] 
                           #更新回归系数
            del(dataIndex[randIndex]) 
                        #删除已经使用的样本    return weights       #返回"""函数说明:使用Python写的Logistic分类器做预测Parameters:    无Returns:    无Author:    Jack CuiBlog:    http://blog.csdn.net/c406495762Zhihu:    https://www.zhihu.com/people/Jack--Cui/Modify:    2017-09-05"""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(len(currLine)-1):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[-1]))
    trainWeights =
    stocGradAscent1(np.array(trainingSet), trainingLabels, 500)
    #使用改进的随即上升梯度训练
    errorCount = 0; numTestVec = 0.0
    for line in frTest.readlines():
        numTestVec += 1.0
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(len(currLine)-1):
            lineArr.append(float(currLine[i]))
        if int(classifyVector
        (np.array(lineArr), trainWeights))!= int(currLine[-1]):
            errorCount += 1
    errorRate = (float(errorCount)/numTestVec) * 100  
     #错误率计算    print("测试集错误率为: %.2f%%" % errorRate)
"""函数说明:分类函数Parameters:    inX - 特征向量    weights - 回归系数Returns:    分类结果Author:    Jack CuiBlog:    http://blog.csdn.net/c406495762Zhihu:    https://www.zhihu.com/people/Jack--Cui/Modify:    2017-09-05"""def classifyVector(inX, weights):    prob = sigmoid(sum(inX*weights))
    if prob > 0.5: return 1.0
    else: return 0.0if __name__ == '__main__':
    colicTest()

运行结果如下:

错误率还是蛮高的,而且耗时1.9s,并且每次运行的错误率也是不同的,错误率高的时候可能达到40%多。为啥这样?首先,因为数据集本身有30%的数据缺失,这个是不能避免的。另一个主要原因是,我们使用的是改进的随机梯度上升算法,因为数据集本身就很小,就几百的数据量。用改进的随机梯度上升算法显然不合适。让我们再试试梯度上升算法,看看它的效果如何?

# -*- coding:UTF-8 -*-import numpy as npimport random"""函数说明:sigmoid函数Parameters:    inX - 数据Returns:    sigmoid函数Author:    Jack CuiBlog:    http://blog.csdn.net/c406495762Zhihu:    https://www.zhihu.com/people/Jack--Cui/Modify:    2017-09-05"""def sigmoid(inX):    return 1.0 / (1 + np.exp(-inX))
"""函数说明:梯度上升算法Parameters:    dataMatIn - 数据集    classLabels - 数据标签Returns:    weights.getA() - 求得的权重数组(最优参数)Author:    Jack CuiBlog:    http://blog.csdn.net/c406495762Zhihu:    https://www.zhihu.com/people/Jack--Cui/Modify:    2017-08-28"""def gradAscent(dataMatIn, classLabels):    dataMatrix = np.mat(dataMatIn) 
    #转换成numpy的mat
    labelMat = np.mat(classLabels).transpose()
#转换成numpy的mat,并进行转置
    m, n = np.shape(dataMatrix) 
    #返回dataMatrix的大小。m为行数,n为列数。
    alpha = 0.01 
    #移动步长,也就是学习速率,控制更新的幅度。
    maxCycles = 500 
    #最大迭代次数
    weights = np.ones((n,1))
       #梯度上升矢量化公式
        error = labelMat - h
        weights = weights + alpha * 
                         dataMatrix.transpose() * error    return weights.getA()  
    #将矩阵转换为数组,并返回
"""函数说明:使用Python写的Logistic分类器做预测Parameters:    无Returns:    无Author:    Jack CuiBlog:    http://blog.csdn.net/c406495762Zhihu:    https://www.zhihu.com/people/Jack--Cui/Modify:    2017-09-05"""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(len(currLine)-1):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[-1]))
    trainWeights = gradAscent(np.array(trainingSet), trainingLabels)
      #使用改进的随即上升梯度训练
    errorCount = 0; numTestVec = 0.0
    for line in frTest.readlines():
        numTestVec += 1.0
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(len(currLine)-1):
            lineArr.append(float(currLine[i]))
        if int(classifyVector
        (np.array(lineArr), trainWeights[:,0]))!= int(currLine[-1]):
            errorCount += 1
    errorRate = (float(errorCount)/numTestVec) * 100

#错误率计算    print("测试集错误率为: %.2f%%" % errorRate)
"""函数说明:分类函数Parameters:    inX - 特征向量    weights - 回归系数Returns:     分类结果Author:    Jack CuiBlog:    http://blog.csdn.net/c406495762Zhihu:    https://www.zhihu.com/people/Jack--Cui/Modify:    2017-09-05"""def classifyVector(inX, weights):    prob = sigmoid(sum(inX*weights))
    if prob > 0.5: return 1.0
    else: return 0.0if __name__ == '__main__':
    colicTest()

运行结果如下:

可以看到算法耗时减少了,错误率稳定且较低。很显然,使用随机梯度上升算法,反而得不偿失了。所以可以得到如下结论:

  • 当数据集较小时,我们使用梯度上升算法
  • 当数据集较大时,我们使用改进的随机梯度上升算法

对应的,在Sklearn中,我们就可以根据数据情况选择优化算法,比如数据较小的时候,我们使用liblinear,数据较大时,我们使用sag和saga。

本系列篇章:

Logistic回归实战篇之预测病马死亡率(一)

Logistic回归实战篇之预测病马死亡率(二)

Logistic回归实战篇之预测病马死亡率(三)

原文发布于微信公众号 - 机器学习算法全栈工程师(Jeemy110)

原文发表时间:2017-10-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏null的专栏

简单易学的机器学习算法——因子分解机(Factorization Machine)

一、因子分解机FM的模型        因子分解机(Factorization Machine, FM)是由Steffen Rendle提出的一种基于矩阵分解的...

1.3K9
来自专栏用户2442861的专栏

caffe python 图片训练识别 实例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/details...

1362
来自专栏大数据智能实战

LargeVis可视化技术学习

大图可视化一直是大数据可视化领域的一个关键技术,当前有各种办法,但是今年出来了一个LargeVis的技术,因此对这个技术进行复现和学习一下。 前面有很多基础理论...

2977
来自专栏程序生活

pyltp的使用教程

pyltp 是 LTP 的 Python 封装,提供了分词,词性标注,命名实体识别,依存句法分析,语义角色标注的功能。

631
来自专栏ATYUN订阅号

使用多种工具组合进行分布式超参数优化

在这篇文章中,我介绍如何使用工具组合来加速超参数优化任务。这里提供了Ubuntu的说明,但可以合理地应用于任何*nix系统。

764
来自专栏MixLab科技+设计实验室

自己动手做一个识别手写数字的web应用01

最近在深入地学习keras,发现网上各种教程都是教你怎么训练模型的,很少有问题提到如何把训练好的模型部署为后端服务,为web及app提供服务。 于是,我决定把学...

3738
来自专栏机器之心

资源 | Mask R-CNN神应用:像英剧《黑镜》一样屏蔽人像

选自GitHub 机器之心编译 参与:思源、黄小天 黑镜特别篇《白色圣诞节》中有种名为「屏蔽」的黑科技,每个人安装上智能眼,可以凭意愿屏蔽动态视界中的任何人(及...

29210
来自专栏人工智能LeadAI

逻辑回归 | TensorFlow深度学习笔记

课程目标:学习简单的数据展示,训练一个Logistics Classifier,熟悉以后要使用的数据 Install Ipython NoteBook 可以参考...

2877
来自专栏编程

基于Python库Face_Recognition动手DIY人脸识别

0X00 前言 最近使用iPhone x,把人脸识别代入了我们的生活中。前段时间了解了一个Python的一个开元函数库,并对其进行了分析、学习和实践,那么今天我...

2495
来自专栏姜媚的专栏

CoreML尝鲜:将自己训练的 caffe 模型移植到 IOS 上

俗话说的好,知己知彼,百战不殆。为了找出对手的优缺点,研究对手的技术核心,在 WWDC 召开近20多天后,终于有时间静下心来研究一下苹果这个机器学习 SDK—...

8451

扫码关注云+社区