《机器学习实战》5.2Logistic回归项目案例:预测病马死亡率

本文主要是介绍《机器学习实战》5.2Logistic回归项目案例:预测病马死亡率,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《机器学习实战》5.2Logistic回归项目案例:预测病马死亡率

搜索微信公众号:‘AI-ming3526’或者’计算机视觉这件小事’ 获取更多人工智能、机器学习干货
csdn:https://blog.csdn.net/baidu_31657889/
github:https://github.com/aimi-cn/AILearners

本文出现的所有代码,均可在github上下载,不妨来个Star把谢谢~:Github代码地址

1、项目简介

本次实战内容,将使用Logistic回归来预测患疝气病的马的存活问题。原始数据集下载地址:数据集下载

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

2、开发流程

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

收集数据: 给定数据文件

病马的训练数据已经给出来了,如下形式存储在文本文件中: 原始数据集地址

1.000000	1.000000	39.200000	88.000000	20.000000	0.000000	0.000000	4.000000	1.000000	3.000000	4.000000	2.000000	0.000000	0.000000	0.000000	4.000000	2.000000	50.000000	85.000000	2.000000	2.000000	0.000000
2.000000	1.000000	38.300000	40.000000	24.000000	1.000000	1.000000	3.000000	1.000000	3.000000	3.000000	1.000000	0.000000	0.000000	0.000000	1.000000	1.000000	33.000000	6.700000	0.000000	0.000000	1.000000

准备数据: 用 Python 解析文本文件并填充缺失值

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

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

现在,我们对下一节要用的数据集进行预处理,使其可以顺利地使用分类算法。预处理数据做两件事:

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

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

horseColicTraining.txt

horseColicTest.txt

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

分析数据: 可视化并观察数据

将数据使用 MatPlotlib 打印出来,观察数据是否是我们想要的格式

训练算法: 使用优化算法,找到最佳的系数

我们会使用上一节用到的梯度上升和改进之后的随机梯度上升算法进行训练

测试算法: 为了量化回归的效果,需要观察错误率。根据错误率决定是否回退到训练阶段,通过改变迭代的次数和步长的参数来得到更好的回归系数

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

我们先使用梯度上升算法计算错误率大小
然后使用改进的随机梯度上升算法计算错误率大小

代码如下:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   Logistic_demo01.py
@Time    :   2019/05/27 16:31:12
@Author  :   xiao ming 
@Version :   1.0
@Contact :   xiaoming3526@gmail.com
@Desc    :   Logistic回归案例之预测病马死亡率
@github  :   https://github.com/aimi-cn/AILearners
'''# here put the import lib
import numpy as np
import random'''
@description: sigmoid函数
@param  inX - 数据
@return: sigmoid函数
'''
def sigmoid(inX):return 1.0 / (1 + np.exp(-inX))'''
@description: 梯度上升法
@param {type} 两个参数:
第一个参数==> dataMatIn 是一个2维NumPy数组,每列分别代表每个不同的特征,每行则代表每个训练样本。
第二个参数==> classLabels 是类别标签,它是一个 1*100 的行向量。为了便于矩阵计算,需要将该行向量转换为列向量,做法是将原向量转置,再将它赋值给labelMat。
@return: 求得的权重数组(最优参数)
'''
def gradAscent(dataMatIn, classLabels):#用dataMatIn创建特征矩阵dataMatrix = np.mat(dataMatIn)#调换矩阵的坐标顺序,对于二维矩阵来说,transpose()就是转置 labelMat = np.mat(classLabels).transpose()#m是样本数,n是特征数m, n = np.shape(dataMatrix)#梯度上升步长alpha = 0.001   #最大迭代次数                                                     maxCycles = 500       #权重向量b,初始化为全1 这里面n为3                                                weights = np.ones((n,1))for k in range(maxCycles):#讲给定的值通过sigmoid函数输出为0-1之间的数值 #对w1*x1+w2*x2求对数几率回归h = sigmoid(dataMatrix * weights)      #计算真实值和预测值之间的误差                         error = labelMat - h#根据误差进行梯度更新weights = weights + alpha * dataMatrix.transpose() * error#.getA()将自身矩阵变量转化为ndarray类型的变量return weights'''
@description: 改进的随机梯度上升算法
@param  dataMatrix - 数据数组classLabels - 数据标签numIter - 迭代次数
@return: weights - 求得的回归系数数组(最优参数)
'''
def stocGradAscent1(dataMatrix, classLabels, numIter=150):#返回dataMatrix的大小。m为行数,n为列数。m,n = np.shape(dataMatrix)#参数初始化weights = np.ones(n)# 随机梯度, 循环150,观察是否收敛for j in range(numIter):# [0, 1, 2 .. m-1]dataIndex = list(range(m))for i in range(m):# i和j的不断增大,导致alpha的值不断减少,但是不为0alpha = 4/(1.0+j+i)+0.0001# 随机产生一个 0~len()之间的一个值# random.uniform(x, y) 方法将随机生成下一个实数,它在[x,y]范围内,x是这个范围内的最小值,y是这个范围内的最大值。randIndex = int(np.random.uniform(0,len(dataIndex)))# sum(dataMatrix[i]*weights)为了求 f(x)的值, f(x)=a1*x1+b2*x2+..+nn*xnh = sigmoid(sum(dataMatrix[randIndex]*weights))error = classLabels[randIndex] - h#更新回归系数weights = weights + alpha * error * dataMatrix[randIndex]#删除已经使用的样本del(dataIndex[randIndex])return weightsdef colicTest():frTrain = open('C:/Users/Administrator/Desktop/blog/github/AILearners/data/ml/jqxxsz/5.Logistic/horseColicTraining.txt')                                        #打开训练集frTest = open('C:/Users/Administrator/Desktop/blog/github/AILearners/data/ml/jqxxsz/5.Logistic/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.0for line in frTest.readlines():numTestVec += 1.0currLine = 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 += 1errorRate = (float(errorCount)/numTestVec) * 100                                 #错误率计算print("梯度上升算法测试集错误率为: %.2f%%" % errorRate).decode('utf-8').encode('gb2312')def colicTest1():frTrain = open('C:/Users/Administrator/Desktop/blog/github/AILearners/data/ml/jqxxsz/5.Logistic/horseColicTraining.txt')                                        #打开训练集frTest = open('C:/Users/Administrator/Desktop/blog/github/AILearners/data/ml/jqxxsz/5.Logistic/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)       errorCount = 0; numTestVec = 0.0for line in frTest.readlines():numTestVec += 1.0currLine = 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 += 1errorRate = (float(errorCount)/numTestVec) * 100                                 #错误率计算print("随机梯度上升测试集错误率为: %.2f%%" % errorRate).decode('utf-8').encode('gb2312')def classifyVector(inX, weights):prob = sigmoid(sum(inX*weights))if prob > 0.5: return 1.0else: return 0.0if __name__ == '__main__':#使用梯度上升训练colicTest()#使用随机梯度上升训练colicTest1()

运行结果如下:
在这里插入图片描述

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

我们看到梯度上升算法错误率稳定且较低。很显然,使用随机梯度上升算法,反而得不偿失了。

所以可以得到如下结论:

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

使用算法: 实现一个简单的命令行程序来收集马的症状并输出预测结果并非难事,这可以作为留给大家的一道习题

补充:对于这么复杂的分类算法 以及之后要学习的支持向量机SVM 都是非常复杂的 是不是很害怕自己写不出来代码 不用担心 这些东西其他开发者都为我们想好了 我们直接调用api就可以了 我们最好是了解一下他的原理 具体实现细节不会也无妨 我这里准备了使用sklearn实现Logistic回归的代码 核心代码只有两行就可以实现这样的算法 有兴趣的小伙伴去sklearn官网查看

sklearn.linear_model模块提供了很多模型供我们使用,比如Logistic回归、Lasso回归、贝叶斯脊回归等,可见需要学习的东西还有很多很多。

我使用了liblinear和sag方法进行实现

完整代码地址:https://github.com/aimi-cn/AILearners/tree/master/src/py2.x/ml/jqxxsz/5.Logistic/Logistic_demo02.py

liblinear(使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数)

sag方法(即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候。)

核心代码(两行):

    # 使用solver优化算法选择参数,只有五个可选参数 我们使用liblinear和sag进行优化# max_iter:算法收敛最大迭代次数,int类型,默认为10classifier = LogisticRegression(solver='liblinear',max_iter=10).fit(trainingSet, trainingLabels)# 此时max_iter=3000是因为10的话算法还没有收敛 所以就选择较大的数进行收敛classifier2 = LogisticRegression(solver='sag',max_iter=3000).fit(trainingSet, trainingLabels)# score方法返回测试之后的正确率test_accurcy = classifier.score(testSet, testLabels) * 100print("正确率为: %.2f%%" % test_accurcy).decode('utf-8').encode('gb2312')

运行结果如下:

在这里插入图片描述

优化的正确率达到7成以上
还是那句话,我们需要根据数据集情况,选择最优化算法。

对于每个函数的具体使用,可以看下官方文档:点我查看

AIMI-CN AI学习交流群【1015286623】 获取更多AI资料
扫码加群:

在这里插入图片描述

分享技术,乐享生活:我们的公众号计算机视觉这件小事每周推送“AI”系列资讯类文章,欢迎您的关注!

在这里插入图片描述

这篇关于《机器学习实战》5.2Logistic回归项目案例:预测病马死亡率的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/601246

相关文章

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1

Nginx进行平滑升级的实战指南(不中断服务版本更新)

《Nginx进行平滑升级的实战指南(不中断服务版本更新)》Nginx的平滑升级(也称为热升级)是一种在不停止服务的情况下更新Nginx版本或添加模块的方法,这种升级方式确保了服务的高可用性,避免了因升... 目录一.下载并编译新版Nginx1.下载解压2.编译二.替换可执行文件,并平滑升级1.替换可执行文件

精选20个好玩又实用的的Python实战项目(有图文代码)

《精选20个好玩又实用的的Python实战项目(有图文代码)》文章介绍了20个实用Python项目,涵盖游戏开发、工具应用、图像处理、机器学习等,使用Tkinter、PIL、OpenCV、Kivy等库... 目录① 猜字游戏② 闹钟③ 骰子模拟器④ 二维码⑤ 语言检测⑥ 加密和解密⑦ URL缩短⑧ 音乐播放

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd

RabbitMQ消费端单线程与多线程案例讲解

《RabbitMQ消费端单线程与多线程案例讲解》文章解析RabbitMQ消费端单线程与多线程处理机制,说明concurrency控制消费者数量,max-concurrency控制最大线程数,prefe... 目录 一、基础概念详细解释:举个例子:✅ 单消费者 + 单线程消费❌ 单消费者 + 多线程消费❌ 多

PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例

《PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例》词嵌入解决NLP维度灾难,捕捉语义关系,PyTorch的nn.Embedding模块提供灵活实现,支持参数配置、预训练及变长... 目录一、词嵌入(Word Embedding)简介为什么需要词嵌入?二、PyTorch中的nn.Em

在IntelliJ IDEA中高效运行与调试Spring Boot项目的实战步骤

《在IntelliJIDEA中高效运行与调试SpringBoot项目的实战步骤》本章详解SpringBoot项目导入IntelliJIDEA的流程,教授运行与调试技巧,包括断点设置与变量查看,奠定... 目录引言:为良驹配上好鞍一、为何选择IntelliJ IDEA?二、实战:导入并运行你的第一个项目步骤1

Spring Boot3.0新特性全面解析与应用实战

《SpringBoot3.0新特性全面解析与应用实战》SpringBoot3.0作为Spring生态系统的一个重要里程碑,带来了众多令人兴奋的新特性和改进,本文将深入解析SpringBoot3.0的... 目录核心变化概览Java版本要求提升迁移至Jakarta EE重要新特性详解1. Native Ima