专栏首页多选参数逻辑回归实战:从疝气病症预测病马的死亡率

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

下面使用Logistic回归来预测患有疝病的马的存活问题,数据集中包含了368个样本和28个特征。数据集中包含了医院检测马疝病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。另外需要说明的是,除了部分指标主观和难以测量外,该数据还存在一个问题,数据集中有30%的值是缺失的。首先在使用Logistic回归预测病马的生死之前,需要处理数据集中的数据缺失问题。

1. 准备数据:处理数据中的缺失值

对于有些存在缺失的数据来说,扔掉和重新获取是不可取的,所以有以下这些方法来解决数据缺失的问题:

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

对于该实战中使用的数据集,在预处理阶段需要做两件事:

  • 所有的缺失值必须用一个实数值来替换,这里选择实数0来替换所有缺失值,恰好能适用于Logistic回归,这样做在更新时不会影响回归系数的值。另外由于sigmoid(0)=0.5,即它对结果的预测不具有任何倾向性,因此上述做法也不会对误差造成任何影响。
  • 测试数据集中发现一条数据的类别标签已经缺失,那么应将这条数据丢弃,这是因为类别标签与特征不同,很难确定采用某个合适的值来替换

机器学习中如何处理缺失数据这个问题没有标准答案,取决于实际应用中的需求。

原始的数据集经过预处理之后保存为了两个文件:horseColicTest.txt和horseColicTraining.txt。这两个数据集和原始数据集见文末给出的链接。

2. 用Logistic回归进行分类

使用Logistic回归方法进行分类,所需要做的就是把测试集上的每个特征向量乘以最优化方法得来的回归系数,再将该乘积结果求和,最后输入到Sigmoid函数中,如果对应的函数值大于0.5就预测类别标签为1。下面看看实战中的代码,首先是文件内容的读取、Sigmoid函数以及梯度下降算法函数,这边不再赘述:

'''
数据加载
'''
def loadDataSet(filePath):
    f = open(filePath)
    dataList = []
    labelList = []
    for line in f.readlines():
        currLine = line.strip().split('	')
        lineArr = []
        for i in range(21):
            lineArr.append(float(currLine[i]))
        dataList.append(lineArr)
        labelList.append(float(currLine[21]))
    return dataList, labelList


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


'''
随机梯度下降算法
'''
def stocGradAscent(dataList, labelList, numIter=150):
    dataArr = np.array(dataList)
    m, n = np.shape(dataArr)
    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  # 步长为动态变化
            rand = int(np.random.uniform(0, len(dataIndex)))
            choseIndex = dataIndex[rand]
            h = sigmoid(np.sum(dataArr[choseIndex] * weights))
            error = h - labelList[choseIndex]
            weights = weights - alpha * error * dataArr[choseIndex]
            del (dataIndex[rand])
    return weights

接下去是分类函数,该函数以回归系数和特征向量作为输入来计算对应的Sigmoid值,如果Sigmoid值大于0.5则函数返回1。

'''
进行分类
'''
def classifyVector(inX, weights):
    prob = sigmoid(np.sum(inX * weights))
    if prob > 0.5:
        return 1.0
    else:
        return 0.0

再接下去是在测试集上计算分类错误率,这边返回的错误率多次运行得到的结果可能稍有不同,主要是因为其中有随机的成分在里面。只有当梯度下降算法得到的回归系数已经完全收敛,那么结果才是确定的。

'''
在测试集上计算分类错误率
'''
def colicTest(trainWeights, testDataList, testLabelList):
    errorCount = 0  # 判断错误的数量
    testCount = 0  # 测试集总共的数量
    testCount = len(testDataList)
    for i in range(testCount):
        if int(classifyVector(np.array(testDataList[i]), trainWeights)) != 
                int(testLabelList[i]):
            errorCount += 1
    errorRate = float(errorCount)/testCount
    return errorRate

最后只要调用如下的主函数即可获得10次运行之后的平均分类错误率

def main():
    numTests = 10
    errorSum = 0.0
    trainDataList, trainLabelList = loadDataSet("horseColicTraining.txt")
    testDataList, testLabelList = loadDataSet("horseColicTest.txt")
    for i in range(numTests):
        trainWeights = stocGradAscent(trainDataList, trainLabelList, 500)
        errorSum += colicTest(trainWeights, testDataList, testLabelList)
    print("%d次的平均错误率为%f"%(numTests, errorSum/numTests))

某次运行程序之后,得到的平均分类错误率如下(即输出结果),如果调整stocGradAscent函数中参数numIter的值和梯度下降算法中的步长,那么平均可以降到20%左右。

10次的平均错误率为0.329851

附:数据集及代码

本文所有数据集及代码,均可在https://github.com/DawnGuoDev/MachineLearningStudy/tree/master/LogisticRegression中获取。

本文分享自微信公众号 - 多选参数(zhouxintalk),作者:程序锅

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-03-06

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • vue 学习笔记第二弹

    概念:Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。过滤器应该被添加在...

    syy
  • 二分查找应该都会,那么二分查找的变体呢?

    大家好,我是多选参数的程序锅,一个正在”捣鼓“操作系统、学数据结构和算法以及 Java 的硬核菜鸡。

    syy
  • C++ 万字长文第一篇---拿下字节面试

    有些情况下,基类生成的对象是不合理的,比如动物可以派生出狮子、孔雀等,这些派生类显然存在着较大的差异。那么可以让基类定义一个函数,并不给出具体的操作内容,让派生...

    syy
  • 一份其实很短的 LaTeX 入门文档

    原文地址:https://liam0205.me/2014/09/08/latex-introduction/

    用户1148523
  • 看看是不是你想要的按键处理

    https://qqqqqbucket.oss-cn-beijing.aliyuncs.com/%E5%8D%95%E7%89%87%E6%9C%BA%E6%A...

    杨奉武
  • 如何手动实现一个 UIScrollView

    UIKit 坐标系每一个 View 都定义了他自己的坐标系,如下图所示,x 轴指向右方,y 轴指向下方:

    s_在路上
  • MYSQL导入数据load data infile三种方式

    zhangheng
  • 独家 | 雷军如何秒变军装帅哥?关于腾讯天天P图的8个技术问答(文末有彩蛋)

    作者 | 周翔 近日,小米科技董事长兼 CEO 雷军在微博上放出多张军装照, 还真是有浓浓的红军年代感...。 实际上,这是人民日报为了建军 90 周年策划的一...

    AI科技大本营
  • ThreadLocal详解

      这个玩意有什么用处,或者说为什么要有这么一个东东?先解释一下,在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线程都在操作同一个变量,显然...

    lyb-geek
  • 关于db link权限分配的苦旅(一) (r7笔记第42天)

    昨天接到一个开发的需求,内容看起来非常简单。 申请数据库192.168.1.118:1522:TEST下用户APP_TE_FLOW_128赋予对表testore...

    jeanron100

扫码关注云+社区

领取腾讯云代金券