R7:糖尿病预测模型优化探索

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊

一、实验目的:

探索本案例是否还有进一步优化的空间

二、实验环境:

  • 语言环境:python 3.8
  • 编译器:Jupyter notebook
  • 深度学习环境:Pytorch
    • torch==2.4.0+cu124
    • torchvision==0.19.0+cu124

三、数据集标准化处理

对比R6的代码,本案例的改进部分主要是取消了两行代码的注释# 数据集标准化处理

from sklearn.preprocessing import StandardScaler   

# '高密度脂蛋白胆固醇'字段与糖尿病负相关,故而在 X 中去掉该字段   
X = DataFrame.drop(['是否糖尿病','高密度脂蛋白胆固醇'],axis=1)   
y = DataFrame['是否糖尿病']   

# 数据集标准化处理   
sc_X    = StandardScaler()   
X = sc_X.fit_transform(X)   

X = torch.tensor(np.array(X), dtype=torch.float32)   
y = torch.tensor(np.array(y), dtype=torch.int64)   

train_X, test_X, train_y, test_y = train_test_split(X, y,
                                                    test_size=0.2,   
                                                    random_state=1)   
train_X.shape, train_y.shape   

代码输出结果如下:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

对比R6的结果可以看到测试集准确率有了明显的提高,而原因我也有在上一次总结中提及。结果差异大的可能原因分析如下:

数据处理差异

  1. 特征选择不同
    • 在R6中,除了删除'高密度脂蛋白胆固醇''是否糖尿病',还删除了'卡号'。这意味着R6代码使用的特征集比R7少了一个额外的特征。不同的特征集会对模型的学习和预测能力产生影响。'卡号'这个特征本身包含了一些与糖尿病相关的潜在信息(不同卡号对应的人群有不同的糖尿病发病倾向等),那么去掉它会改变模型的行为。
  2. 标准化处理的有无
    • R7代码对数据进行了标准化处理(sc_X.fit_transform(X)),而R6没有。标准化可以使数据的特征具有相似的尺度,这对于一些基于距离或梯度的算法(如神经网络中的梯度下降)非常重要。如果数据没有标准化,可能会导致某些特征在模型训练过程中对损失函数的影响过大或过小,从而影响模型的收敛速度和性能。例如,在神经网络中,如果某个特征的值域很大,而另一个特征的值域很小,那么在计算梯度时,可能会使模型过度关注值域大的特征,而忽略值域小的特征。

模型训练相关因素

  1. 初始条件差异
    • 模型的初始参数(如神经网络的权重初始化)可能会因为数据的不同而导致不同的训练轨迹。不同的数据分布(由于数据处理的不同)可能会使模型在相同的初始化策略下朝着不同的方向优化。
  2. 训练动态变化
    • 由于数据的改变,模型在训练过程中的梯度更新情况也会不同。R6代码中没有标准化的数据可能会导致梯度在某些方向上变化剧烈,影响模型收敛。而在R7中,标准化后的数据可能使梯度更新更加稳定和合理,导致训练和测试准确率的变化趋势不同。而且,不同的数据特征可能在不同的训练阶段对模型的贡献不同,进而影响模型在每个 epoch 的准确率和损失值。

在这里插入图片描述
在这里插入图片描述

四、总结

标准化处理对模型训练的具体影响:

  1. 加快收敛速度

    • 原理:在未进行标准化处理时,不同特征的取值范围可能差异巨大。例如,一个特征的取值范围是0 - 1,另一个特征的取值范围是0 - 1000。在基于梯度下降的优化算法中,如随机梯度下降(SGD),损失函数的梯度更新会受到特征尺度的影响。对于取值范围大的特征,其梯度更新步长可能会过大,导致模型难以收敛到最优解;而对于取值范围小的特征,其梯度更新步长可能过小,模型学习这些特征的速度会很慢。标准化将数据变换到均值为0、标准差为1的分布,使得不同特征具有相似的尺度。这样,在梯度更新时,各个特征能够以相对平衡的步长进行学习,从而加快模型收敛速度。
    • 示例:假设我们有一个简单的线性回归模型 y = w 1 x 1 + w 2 x 2 + b y = w_1x_1+w_2x_2 + b y=w1x1+w2x2+b,其中 x 1 x_1 x1的取值范围是[0, 1], x 2 x_2 x2的取值范围是[0, 100]。如果不进行标准化,当更新 w 1 w_1 w1 w 2 w_2 w2的梯度时,由于 x 2 x_2 x2的取值范围大, w 2 w_2 w2的更新步长会比 w 1 w_1 w1大很多。经过标准化后, x 1 x_1 x1 x 2 x_2 x2的尺度变得相似, w 1 w_1 w1 w 2 w_2 w2可以以更合理的步长进行更新,模型能够更快地找到合适的权重组合。
  2. 提高模型精度

    • 原理:标准化可以减少数据中异常值和离群点对模型训练的影响。在一些机器学习算法中,如支持向量机(SVM)和神经网络,异常值可能会导致模型过度拟合这些异常数据点,从而降低模型在其他正常数据点上的泛化能力。标准化通过将数据压缩到一个相对稳定的范围内,降低了异常值的影响,使模型能够更好地学习数据的整体分布规律,进而提高模型的精度。
    • 示例:考虑一个K - 近邻(K - NN)分类器,它基于数据点之间的距离进行分类。如果存在一个特征有很大的取值范围,并且有一些离群点,那么这些离群点会在距离计算中占据主导地位,导致分类错误。通过标准化,所有特征的取值范围变得相对均匀,离群点的影响被减弱,K - NN分类器能够更准确地根据数据的真实分布进行分类。
  3. 增强模型稳定性和鲁棒性

    • 原理:在模型训练过程中,数据的微小变化可能会导致模型性能的大幅波动。标准化后的数据在一定程度上减少了这种波动,因为它使得数据的分布更加稳定。对于神经网络等复杂模型,这种稳定性尤为重要,因为它们通常具有大量的参数,容易受到数据变化的影响。标准化可以帮助模型在不同的数据集(如训练集和测试集)上保持相对一致的性能,提高模型的鲁棒性。
    • 示例:在深度学习中,当使用小批量梯度下降(Mini - Batch Gradient Descent)训练模型时,每个小批量数据的分布可能会有所不同。如果没有标准化,模型可能会因为小批量数据的差异而产生较大的性能波动。而标准化后,小批量数据的分布更加稳定,模型的训练过程更加平稳,对数据变化的敏感度降低,从而增强了模型的鲁棒性。

除了标准化处理,还有下述数据预处理方法:

  1. 数据清洗
    • 缺失值处理
      • 删除法:当数据集中的缺失值占比较小,且缺失是完全随机的情况下,可以直接删除含有缺失值的行或列。例如,在一个包含1000条记录的客户信息数据集中,如果只有少数几条记录的“联系电话”字段缺失,且这些缺失看起来是随机发生的,那么可以考虑删除这些记录。
      • 插补法
        • 均值/中位数/众数插补:对于数值型特征的缺失值,可以使用该特征的均值、中位数来填充。比如,在一个学生成绩数据集中,如果某个学生的数学成绩缺失,可以用全班数学成绩的均值来填充。对于分类型特征,则可以使用众数填充,例如,在一个调查问卷数据集中,“性别”字段有缺失值,就可以用出现频率最高的性别(众数)来填充。
        • 回归插补:通过建立一个回归模型,利用数据集中其他相关特征来预测缺失值。假设在一个房屋价格数据集中,“房屋面积”字段有缺失值,可以建立一个以房屋价格、房间数量等其他特征为自变量,房屋面积为因变量的回归模型,然后利用该模型预测缺失的房屋面积。
    • 异常值处理
      • 盖帽法:将超出一定范围(如大于某个分位数加上几倍的四分位距,或小于某个分位数减去几倍的四分位距)的异常值替换为该范围的边界值。例如,在一个员工工资数据集中,若发现工资数据有异常高的值,可以将这些异常高的值替换为上四分位数加上1.5倍四分位距的值。
      • 删除法:当异常值对模型训练有严重干扰,且其出现是由于数据录入错误等原因时,可以直接删除异常值。例如,在一个体温测量数据集中,如果出现了明显不符合人体正常体温范围(如50℃)的异常值,且确定是测量错误导致的,就可以删除。
  2. 数据编码
    • 独热编码(One - Hot Encoding):主要用于处理分类型数据。对于一个具有 n n n个类别(如颜色有红、绿、蓝三种)的分类变量,会创建 n n n个新的二进制变量(0或1)来表示。例如,对于“颜色”这个分类变量,会创建“红色”、“绿色”、“蓝色”三个新变量,当原始数据为红色时,“红色”变量为1,其他两个为0。这种编码方式可以避免模型将分类变量的类别顺序错误地理解为数值大小关系。
    • 标签编码(Label Encoding):将分类变量的类别转换为整数。例如,对于一个包含“低”、“中”、“高”三个类别的变量“风险等级”,可以将“低”编码为0,“中”编码为1,“高”编码为2。不过这种编码方式可能会让模型误解类别之间的顺序关系,所以在一些对类别顺序不敏感的模型(如决策树)中可以使用,而在对顺序敏感的模型(如线性回归)中可能需要谨慎使用。
  3. 数据变换
    • 对数变换:对于一些具有正偏态分布(数据大部分集中在左侧,右侧有较长的尾巴)的数据,如收入数据、人口数据等,可以使用对数变换将其转换为近似正态分布。例如,对一组公司营业收入数据进行对数变换后,数据的分布会更加对称,这样更符合一些模型(如基于正态分布假设的线性回归)的假设,有助于提高模型性能。
    • 平方根变换:和对数变换类似,主要用于改善数据的分布形态。当数据的偏态程度不是特别严重时,平方根变换可能是一种有效的方法。例如,对于一些生物实验中的细胞计数数据,其分布可能存在一定的偏态,通过平方根变换可以使其分布更加合理,方便后续模型的训练。

五、模型优化探索

1. 调整模型结构

  • 增加更多的层:可以考虑增加LSTM层的数量。更多的层可能能够捕捉到更复杂的数据模式。例如,可以增加到3层或4层的LSTM,但要注意防止过拟合,可以结合正则化方法。

  • 添加Dropout层:在LSTM层之间或者在全连接层之前添加Dropout层。Dropout在训练过程中随机忽略一些神经元,有助于减少过拟合。比如,可以在每个LSTM层之后添加Dropout层,设置Dropout概率为0.2 - 0.5之间。

class model_lstm(nn.Module):
    def __init__(self):
        super(model_lstm, self).__init__()
        self.lstm0 = nn.LSTM(input_size=13, hidden_size=200, num_layers=1, batch_first=True)
        self.dropout1 = nn.Dropout(0.2)  # 添加Dropout层,概率为0.2
        self.lstm1 = nn.LSTM(input_size=200, hidden_size=200, num_layers=1, batch_first=True)
        self.dropout2 = nn.Dropout(0.2)  # 添加另一个Dropout层
        self.fc0 = nn.Linear(200, 2)

    def forward(self, x):
        out, hidden1 = self.lstm0(x)
        out = self.dropout1(out)  # 使用Dropout
        out, _ = self.lstm1(out, hidden1)
        out = self.dropout2(out)  # 使用Dropout
        out = self.fc0(out)
        return out

2. 优化超参数

  • 调整隐藏层大小:当前LSTM的隐藏层大小是200,可以尝试不同的值,如128、256、300等。通过交叉验证等方法来确定最佳的隐藏层大小,以提高模型的性能。
  • 调整学习率:使用不同的学习率策略,如学习率衰减。可以从一个相对较大的学习率开始,随着训练的进行逐渐降低学习率。例如,使用Adam优化器,并设置初始学习率为0.001,然后每几个epoch按照一定比例(如0.9)降低学习率。
from torch.optim.lr_scheduler import StepLR

loss_fn = nn.CrossEntropyLoss()  # 创建损失函数
learn_rate = 1e-3   # 初始学习率增大为1e - 3
opt = torch.optim.Adam(model.parameters(), lr=learn_rate)
scheduler = StepLR(opt, step_size=10, gamma=0.1)  # 添加学习率调度器
epochs = 30

train_loss = []
train_acc = []
test_loss = []
test_acc = []

for epoch in range(epochs):
    model.train()
    epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, opt)

    model.eval()
    epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)

    train_acc.append(epoch_train_acc)
    train_loss.append(epoch_train_loss)
    test_acc.append(epoch_test_acc)
    test_loss.append(epoch_test_loss)

    # 获取当前的学习率
    lr = opt.state_dict()['param_groups'][0]['lr']
    scheduler.step()  # 更新学习率

    template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%, Test_loss:{:.3f}, Lr:{:.2E}')
    print(template.format(epoch + 1, epoch_train_acc * 100, epoch_train_loss, 
                          epoch_test_acc * 100, epoch_test_loss, lr))

print("=" * 20, 'Done', "=" * 20)

3. 改进输入数据处理

  • 特征工程:进一步分析输入的13个特征,看是否可以通过特征组合、特征变换等方式提高数据的质量。例如,如果某些特征之间存在非线性关系,可以尝试添加一些新的特征来表示这种关系。
  • 数据增强(如果适用):如果数据具有一定的可变性,可以考虑数据增强方法。例如,如果数据是时间序列数据,可以通过对数据进行小幅度的时间平移、缩放等操作来增加数据量和多样性。

4. 模型集成

  • 使用多个模型进行集成:训练多个不同初始化或者不同超参数的LSTM模型,然后将它们的预测结果进行集成,如简单平均或者加权平均。这样可以利用不同模型的优势,提高整体的预测准确性。

经过上述调整模型结构、优化超参数后(特征工程效果不明显),效果有所提升,结果输出如下:
在这里插入图片描述
在这里插入图片描述

5. 改进空间

  • 进一步调整模型结构

    • 增加更多层或调整层大小:虽然已经添加了一些改进,但可以继续尝试增加LSTM的层数或者调整隐藏层大小。例如,可以尝试将LSTM的层数增加到3层,同时适当调整每层的隐藏单元数量,如将隐藏单元数量从200增加到256或300等,然后观察模型性能的变化。
    • 尝试不同类型的层:可以考虑在模型中添加其他类型的神经网络层,如卷积层(如果数据结构适合)。对于时间序列数据或具有局部相关性的数据,卷积层可以提取数据中的局部特征,与LSTM层结合可能会提高模型性能。
  • 优化超参数

    • 更精细的学习率调整:目前使用了简单的学习率衰减策略,可以尝试更复杂的学习率调整方法,如余弦退火学习率(Cosine Annealing Learning Rate)。这种方法可以使学习率在训练过程中按照余弦函数的规律变化,在前期可以有较大的学习率快速收敛,后期学习率逐渐减小以更精细地调整模型参数。
    • 调整Dropout概率:当前设置的Dropout概率为0.2,可以尝试不同的值,如0.3、0.4等,观察对模型过拟合情况的影响。不同的Dropout概率可能会改变模型的复杂度和泛化能力。
  • 改进特征工程

    • 深入分析数据相关性:对新添加的特征进行更深入的分析,检查它们与目标变量的相关性。如果某些新特征与目标变量相关性较低,可以考虑删除或进一步修改这些特征的构建方式。同时,可以探索更多的特征组合和变换方法,以挖掘数据中更有价值的信息。
    • 添加领域相关特征(如果可能):根据数据的领域知识,添加更多有意义的特征。例如,如果是医疗数据,可以考虑添加一些与疾病相关的衍生特征,如不同指标之间的比率等。
  • 模型集成

    • 使用多种模型集成:除了单一的LSTM模型,可以尝试将其与其他类型的模型(如决策树、支持向量机等)进行集成。例如,可以使用堆叠(Stacking)或混合(Blending)等集成方法,将不同模型的预测结果进行组合,以提高模型的泛化能力和稳定性。
    • 训练多个不同初始化的LSTM模型并集成:训练多个不同初始化参数的LSTM模型,然后通过平均或加权平均等方式将它们的预测结果集成在一起。这种方法可以利用不同初始化模型的多样性,降低模型的方差,提高预测性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/910780.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

张氏宗谱序言白话文翻译

序言: 回想千家有赤松子的传承,张家有 “百忍” 的风范。感慨因迁徙和战乱、水灾之苦,远居他乡而失去了家族秩序。想起自从从泗州来到淮安,安家在安东县东北乡众湖荡之地。(这里可能在回忆家族的迁徙历史)…

从0开始学习Linux——Yum工具

往期目录: 从0开始学习Linux——简介&安装 从0开始学习Linux——搭建属于自己的Linux虚拟机 从0开始学习Linux——文本编辑器 上一个章节我们简单了解了Linux中常用的一些文本编辑器,本次教程我们将学习yum工具。 一、Yum简介 Yum(全名…

推荐一款基于Flash的交互式园林设计工具:Garden Planner

Garden Planner是一款由Artifact Interactive开发的基于Flash的交互式园林设计工具。它允许用户以拖放的方式安排植物、树木、建筑物和各种对象,使园林规划变得简单直观。此外,Garden Planner提供工具来快速创建铺路、路径和围栏,帮助用户设计…

WinForms 中使用 MVVM 模式构建应用:实现登录页面、页面导航及 SQLite 数据库连接完整框架搭建过程

前言 在传统的 WinForms 应用程序开发中,很多开发者使用事件驱动的设计模式,直接将业务逻辑编写在界面代码中。然而,随着应用程序的复杂性增加,单一的界面文件变得臃肿,难以测试和维护。借鉴 WPF 中 MVVM(…

诗林工作室(编号:mb0003)分享:Finbiz自适应响应式网页设计模版,适用于前端设计、博客、官网等多类型开发模版

本设计模版来自外网,为HTML类型的模版,色彩多样,适合Web开发人员做前端站点设计参考使用。全站模版倾向于官网设计、自主博客等多行业的平台模版开发,适合各大CMS的主题模版开发参考,如常见的Wordpress主题开发、Z-Blo…

在python中解析命令行参数,并做一个命令行程序

命令行参数 加密程序 考虑这样一个加密程序,其中一个功能,是对一段字符串进行base64加密,另一个功能,是对一段base64字符串解密: import base64def encrypt_to_base64(input_string):byte_data input_string.encod…

ESP8266 自定义固件烧录-Tcpsocket固件

一、固件介绍 固件为自定义开发的一个适配物联网项目的开源固件,支持网页配网、支持网页tcpsocket服务器配置、支持串口波特率设置。 方便、快捷、稳定! 二、烧录说明 固件及工具打包下载地址: https://download.csdn.net/download/flyai…

I.MX6U 裸机开发3. GPIO操作控制LED灯

I.MX6U 裸机开发3. GPIO操作控制LED灯 一、创建项目目录及源文件1. 新建目录2. 远程开发环境3. 创建源文件 二、代码编写1. 打开时钟2. 配置端口复用功能为GPIO3. 配置端口电气属性4. 设置GPIO方向(GDIR寄存器)5. 输出6. 死循环等待 三、编译程序1. 整体…

「Mac畅玩鸿蒙与硬件19」鸿蒙UI组件篇9 - 自定义动画实现

自定义动画让开发者可以设计更加个性化和复杂的动画效果,适合表现独特的界面元素。鸿蒙提供了丰富的工具,支持通过自定义路径和时间控制来创建复杂的动画运动。本篇将带你学习如何通过自定义动画实现更多样化的效果。 关键词 自定义动画动画路径贝塞尔曲…

FLUX 推出 Ultra 和 Raw 模式,仅10秒生成2K高清图!

大家好,我是渔夫。 就在 2024年11月6日,BlackForestLabs 团队升级了他们最新的文生图模型 FLUX1.1 [pro]。 推出 Ultra 和 Raw 模式,仅10秒就能生成2K高清图片,速度非常惊人。 Ultra 模式:可生成超高分辨率图像&#x…

24/11/6 算法笔记 SVD

SVD,即奇异值分解(Singular Value Decomposition),是线性代数中一种重要的矩阵分解方法。 定义 对于任何给定的 mnmn 的实数矩阵 AA(其中 mm 是行数,nn 是列数),SVD分解可以表示为…

开发笔记 | 快速上手基于Dify等第三方大模型平台接口实现AI智能聊天

前置: 1.部署Dify,见官方教程及介绍https://docs.dify.ai/zh-hans,本文主要讲基于部署完之后的java实现的调用它的接口实现AI智能聊天,其他AI功能后续有用到再补充,没有就看缘分 2.什么是Dify?可以简单理解…

数据分析:转录组差异fgsea富集分析

文章目录 介绍加载R包数据链接导入数据数据预处理DE testing: 2BP vs no-BP比较limma-voomLoad steroid dataIn No-BP patientsIn 2BP patientsCompare gene expression vs bacterial mass其他系统信息介绍 转录组差异fgsea富集分析是一种基于基因集的富集分析方法,它关注的是…

查看网路信息-ifconfig命令

1.ifconfig缺点: 可以查看接口的网络类型;部分IP和掩码以及状态是否插线,看不到接口下的网关,DNS, 要想看到接口下多个IP,使用 ip addr show 命令 要想看网关,使用 ip route show 命令、route -n 命令 显示路由表内…

基于Spring Boot的中小型制造企业质量管理系统设计与实现,LW+源码+讲解

摘 要 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自…

Java:多态的调用

1.什么是多态 允许不同类的对象对同一消息做不同的响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)。多态使用了一种动态绑定(dynamic binding)技术,指在执行期间判断所引用…

并查集算法详解

文章目录 并查集概念并查集的常见操作构建并查集合并并查集和查找 关于find函数 并查集概念 并查集(Union-Find)是一种树型的数据结构,用于处理一些不交集的合并及查询问题。其主要应用是判断两个元素是否在同一个集合中,以及合并…

Redis持久化机制——针对实习面试

目录 Redis持久化机制Redis为什么要有持久化机制?Redis持久化方式有哪些?AOF持久化工作原理是什么?有什么优缺点?AOF持久化工作原理AOF的优点AOF的缺点 RDB持久化工作原理是什么?有什么优缺点?RDB持久化工作…

【系统架构设计师(第2版)】七、系统架构设计基础知识

有效的软件体系结构及其明确的描述和设计,已成为软件工程领域中重要的主题。 *注:由于历史原因,研究者和工程人员对**Software Architecture(简称SA)*的翻译不尽相同,本文中软件“体系结构”和“架构”具有…

【NLP】使用 SpaCy、ollama 创建用于命名实体识别的合成数据集

命名实体识别 (NER) 是自然语言处理 (NLP) 中的一项重要任务,用于自动识别和分类文本中的实体,例如人物、位置、组织等。尽管它很重要,但手动注释大型数据集以进行 NER 既耗时又费钱。受本文 ( https://huggingface.co/blog/synthetic-data-s…