前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >逻辑回归实战:从疝气病症预测病马的死亡率

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

作者头像
syy
发布2020-04-07 16:12:25
1.7K0
发布2020-04-07 16:12:25
举报
文章被收录于专栏:多选参数
下面使用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函数以及梯度下降算法函数,这边不再赘述:

代码语言:javascript
复制
'''
数据加载
'''
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。

代码语言:javascript
复制
'''
进行分类
'''
def classifyVector(inX, weights):
    prob = sigmoid(np.sum(inX * weights))
    if prob > 0.5:
        return 1.0
    else:
        return 0.0

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

代码语言:javascript
复制
'''
在测试集上计算分类错误率
'''
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次运行之后的平均分类错误率

代码语言:javascript
复制
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%左右。

代码语言:javascript
复制
10次的平均错误率为0.329851

附:数据集及代码

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 多选参数 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 准备数据:处理数据中的缺失值
  • 2. 用Logistic回归进行分类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档