机器学习 基于逻辑回归的病马死亡率预测 AHU实验

该文详细介绍了如何使用逻辑回归解决实际问题,如预测病马死亡率。通过实验步骤展示了随机梯度上升和梯度上升算法的实现,讨论了这两种方法在小数据集上的优缺点。此外,文中还提到了sklearn库中的LogisticRegression模型,并通过调整参数如solver和max_iter来优化模型性能,从而提高预测的准确性。
摘要由CSDN通过智能技术生成

实验介绍

1.实验内容

本实验介绍如何使用逻辑回归解决一个实际问题:预测病马死亡率。

2. 实验目标

通过本实验进一步掌握逻辑回归的原理,掌握如何使用逻辑回归解决实际问题,掌握实际世界中机器问题的解决流程。

3. 实验要点

  • 逻辑回归
  • 数据预处理
  • 梯度下降
  • sklearn

介绍:逻辑回归,就是在线性回归基础上融入一个激活函数加以改进,激活函数取:

实验步骤

定义函数函数作用传入参数
sigmoid(inX)将inX收束在0~1之间inX:被线性回归处理后的数据
stocGradAscent1(dataMatrix, classLabels, numIter=150)随机梯度上升,每次用一个样本更新回归系数

dataMatrix:数据数组

classLabels:数据标签,即y

numIter=150 迭代次数,默认150次

colicTest()用训练集数据随机梯度上升训练weights,并对预测集及测试,显示错误率
classifyVector(inX, weights)得到对单个标签的训练分类结果

inX:被线性回归处理后的数据

weights:这里的weights是经过训练集随机梯度上升训练后的回归系数矩阵

import numpy as np
import random

"""
函数说明:sigmoid函数

Parameters:
    inX - 数据
Returns:
    sigmoid函数
"""
def sigmoid(inX):
    return 1.0 / (1 + np.exp(-inX))

"""
函数说明:改进的随机梯度上升算法

Parameters:
    dataMatrix - 数据数组
    classLabels - 数据标签
    numIter - 迭代次数
Returns:
    weights - 求得的回归系数数组(最优参数)
"""
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
        
    ### Start Code Here ###
    #实现随机梯度上升算法
    m,n = np.shape(dataMatrix)    #n表示数据条数,m表示数据特征数
    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    

    ### End Code Here ###

"""
函数说明:使用Python写的Logistic分类器做预测

Parameters:
    无
Returns:
    无
"""
def colicTest():
    frTrain = open('lr_horse/horseColicTraining.txt')                                        #打开训练集
    frTest = open('lr_horse/horseColicTest.txt')                                                #打开测试集
    trainingSet = []; trainingLabels = []
    ### Start Code Here ###
    #逐行读取文件
    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)   #使用改进的随即上升梯度训练

    ### End Code Here ###
    #计算错误率
    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:
    分类结果
"""
def classifyVector(inX, weights):
    prob = sigmoid(sum(inX*weights))
    if prob > 0.5: return 1.0
    else: return 0.0

if __name__ == '__main__':
    colicTest()

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

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))
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)                                #梯度上升矢量化公式
        error = labelMat - h
        weights = weights + alpha * dataMatrix.transpose() * error
    return weights.getA()                                                #将矩阵转换为数组,并返回

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

          随机梯度上升算法在每次训练时随机抽取训练数据对回归系数进行调优,梯度上升算法会使用全体数据对相关系数进行优化,每一次更新都要遍历一次训练集。随机梯度上升具有更优的时间复杂度,并且能够提高样本的收敛速度,但梯度上升算法可以获得全局最优解,随机梯度上升容易陷入局部最优解。

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

实验中有详述Sklearn的Logistic回归分类器及其各参数。

编写Sklearn分类器的代码

# -*- coding:UTF-8 -*-
from sklearn.linear_model import LogisticRegression

"""
函数说明:使用Sklearn构建Logistic回归分类器

Parameters:
    无
Returns:
    无
"""
def colicSklearn():
    frTrain = open('lr_horse/horseColicTraining.txt')                                        #打开训练集
    frTest = open('lr_horse/horseColicTest.txt')                                                #打开测试集
    trainingSet = []; trainingLabels = []
    testSet = []; testLabels = []
    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]))
    for line in frTest.readlines():
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(len(currLine)-1):
            lineArr.append(float(currLine[i]))
        testSet.append(lineArr)
        testLabels.append(float(currLine[-1]))
        
    ### Start Code Here ###
    #创建LogisticRegression对象
    classifier = LogisticRegression(solver='liblinear',max_iter=10).fit(trainingSet, trainingLabels)
    test_accurcy = classifier.score(testSet, testLabels) * 100

    #调用fit函数进行模型训练,设置迭代次数为1000
    
    #调用score函数计算模型在测试集上的正确率
    
    ### End Code Here ###
    print('正确率:%f%%' % test_accurcy)

if __name__ == '__main__':
    colicSklearn()

可以看到,正确率又高一些了。更改solver参数,比如设置为sag,使用随机平均梯度下降算法,看一看效果。你会发现,有警告了。

def colicSklearn():
    frTrain = open('lr_horse/horseColicTraining.txt')                                        #打开训练集
    frTest = open('lr_horse/horseColicTest.txt')                                                #打开测试集
    trainingSet = []; trainingLabels = []
    testSet = []; testLabels = []
    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]))
    for line in frTest.readlines():
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(len(currLine)-1):
            lineArr.append(float(currLine[i]))
        testSet.append(lineArr)
        testLabels.append(float(currLine[-1]))
        
    ### Start Code Here ###
    #创建LogisticRegression对象
    classifier = LogisticRegression(solver='sag',max_iter=10).fit(trainingSet, trainingLabels)
    test_accurcy = classifier.score(testSet, testLabels) * 100
    #调用fit函数进行模型训练
    
    #调用score函数计算模型在测试集上的正确率
    
    ### End Code Here ###
    print('正确率:%f%%' % test_accurcy)

if __name__ == '__main__':
    colicSklearn()

更改max_iter=5000,再运行代码:

# -*- coding:UTF-8 -*-
from sklearn.linear_model import LogisticRegression

"""
函数说明:使用Sklearn构建Logistic回归分类器

Parameters:
    无
Returns:
    无
"""
def colicSklearn():
    frTrain = open('lr_horse/horseColicTraining.txt')                                        #打开训练集
    frTest = open('lr_horse/horseColicTest.txt')                                                #打开测试集
    trainingSet = []; trainingLabels = []
    testSet = []; testLabels = []
    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]))
    for line in frTest.readlines():
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(len(currLine)-1):
            lineArr.append(float(currLine[i]))
        testSet.append(lineArr)
        testLabels.append(float(currLine[-1]))
        
    ### Start Code Here ###
    #创建LogisticRegression对象
    classifier = LogisticRegression(solver='sag',max_iter=5000).fit(trainingSet, trainingLabels)
    test_accurcy = classifier.score(testSet, testLabels) * 100
    #调用fit函数进行模型训练,设置迭代次数为5000
    
    #调用score函数计算模型在测试集上的正确率
    
    ### End Code Here ###
    print('正确率:%f%%' % test_accurcy)

if __name__ == '__main__':
    colicSklearn()

实验总结

1. Logistic回归的一般过程

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

2. Logistic回归的优点:

  • 实现简单,易于理解和实现;
  • 计算代价不高,速度很快;
  • 存储资源低。
  • logistic回归模型直接对分类的可能性进行分类,无需事先假设数据满足某种分类模型
  • logistic回归可以处理稀疏高维特征(非0值很少的情况)
  • 不仅可以预测出样本类别,还可以得到预测得到预测为某类的近似概率

3. Logistic回归的点:

  • 容易欠拟合;
  • 分类精度可能不高;

4. 其他:

        Logistic回归的目的是寻找一个非线性函数Sigmoid的最佳拟合参数,求解过程可以由最优化算法完成。改进的一些最优化算法,比如sag。它可以在新数据到来时就完成参数更新,而不需要重新读取整个数据集来进行批量处理。机器学习的一个重要问题就是如何处理缺失数据。这个问题没有标准答案,取决于实际应用中的需求。现有一些解决方案,每种方案都各有优缺点。我们需要根据数据的情况,这是Sklearn的参数,以期达到更好的分类效果。

        给出对数似然函数:

        logistic回归的对数似然函数是一个取对数后的交叉熵损失函数的相反数,我们最大化这个似然函数函数就是最小化损失函数。

在医学领域,尤其是动物健康监测中,预测病马死亡率通常涉及机器学习模型的应用,例如基于统计学或深度学习的模型。然而,由于这是一个复杂的任务,并且直接提供完整的代码并不现实,我会给出一个简单的Python示例框架,使用scikit-learn库中的线性回归模型作为简化版本。真实场景下可能会用到神经网络或更复杂的算法。 ```python import pandas as pd from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, confusion_matrix # 假设你已经有了一个名为horse_data.csv的数据集,其中包含有关马的特征(如年龄、症状等)以及是否患有疝气和死亡状态的信息 data = pd.read_csv('horse_data.csv') # 数据预处理:将'疝气'和'死亡'列转换为数字编码 data['疝气'] = data['疝气'].map({'有': 1, '无': 0}) # 疝气列 data['死亡'] = data['死亡'].map({'死亡': 1, '存活': 0}) # 死亡列 # 分割特征(X)和目标变量(y) X = data.drop(['死亡'], axis=1) y = data['死亡'] # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 使用Logistic Regression模型 model = LogisticRegression() model.fit(X_train, y_train) # 预测 y_pred = model.predict(X_test) # 计算死亡率预测的性能指标 accuracy = accuracy_score(y_test, y_pred) conf_mat = confusion_matrix(y_test, y_pred) print(f"死亡率预测的准确率为:{accuracy*100:.2f}%") print("混淆矩阵:\n", conf_mat) # 这只是一个基本的框架,实际应用可能还需要调整模型参数、特征选择、数据清洗等步骤,并可能需要使用交叉验证来评估模型性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值