当前位置: 首页 > news >正文

365打卡第R3周: RNN-心脏病预测

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

🏡 我的环境:

语言环境:Python3.10
编译器:Jupyter Lab
深度学习环境:torch==2.5.1    torchvision==0.20.1
------------------------------分割线---------------------------------

import numpy as np
import pandas as pd
import torch
from torch import nn
import torch.nn.functional as F
import seaborn as sns#设置GPU训练,也可以使用CPU
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
device

df = pd.read_csv("data/heart.csv")df

from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_splitX = df.iloc[:,:-1]
y = df.iloc[:,-1]# 将每一列特征标准化为标准正太分布,注意,标准化是针对每一列而言的
sc = StandardScaler()
X  = sc.fit_transform(X)X = torch.tensor(np.array(X), dtype=torch.float32)
y = torch.tensor(np.array(y), dtype=torch.int64)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.1, random_state = 1)X_train.shape, y_train.shapefrom torch.utils.data import TensorDataset, DataLoadertrain_dl = DataLoader(TensorDataset(X_train, y_train),batch_size=64, shuffle=False)test_dl  = DataLoader(TensorDataset(X_test, y_test),batch_size=64, shuffle=False)

class model_rnn(nn.Module):def __init__(self):super(model_rnn, self).__init__()self.rnn0 = nn.RNN(input_size=13 ,hidden_size=200, num_layers=1, batch_first=True)self.fc0   = nn.Linear(200, 50)self.fc1   = nn.Linear(50, 2)def forward(self, x):out, hidden1 = self.rnn0(x) out    = self.fc0(out) out    = self.fc1(out) return out   model = model_rnn().to(device)
model

# 训练循环
def train(dataloader, model, loss_fn, optimizer):size = len(dataloader.dataset)  # 训练集的大小num_batches = len(dataloader)   # 批次数目, (size/batch_size,向上取整)train_loss, train_acc = 0, 0  # 初始化训练损失和正确率for X, y in dataloader:  # 获取图片及其标签X, y = X.to(device), y.to(device)# 计算预测误差pred = model(X)          # 网络输出loss = loss_fn(pred, y)  # 计算网络输出和真实值之间的差距,targets为真实值,计算二者差值即为损失# 反向传播optimizer.zero_grad()  # grad属性归零loss.backward()        # 反向传播optimizer.step()       # 每一步自动更新# 记录acc与losstrain_acc  += (pred.argmax(1) == y).type(torch.float).sum().item()train_loss += loss.item()train_acc  /= sizetrain_loss /= num_batchesreturn train_acc, train_lossdef test (dataloader, model, loss_fn):size        = len(dataloader.dataset)  # 测试集的大小num_batches = len(dataloader)          # 批次数目, (size/batch_size,向上取整)test_loss, test_acc = 0, 0# 当不进行训练时,停止梯度更新,节省计算内存消耗with torch.no_grad():for imgs, target in dataloader:imgs, target = imgs.to(device), target.to(device)# 计算losstarget_pred = model(imgs)loss        = loss_fn(target_pred, target)test_loss += loss.item()test_acc  += (target_pred.argmax(1) == target).type(torch.float).sum().item()test_acc  /= sizetest_loss /= num_batchesreturn test_acc, test_lossloss_fn    = nn.CrossEntropyLoss() # 创建损失函数
learn_rate = 1e-4   # 学习率
opt        = torch.optim.Adam(model.parameters(),lr=learn_rate)
epochs     = 50train_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']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)

import matplotlib.pyplot as plt
from datetime import datetime
#隐藏警告
import warnings
warnings.filterwarnings("ignore")        #忽略警告信息current_time = datetime.now() # 获取当前时间plt.rcParams['font.sans-serif']    = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False      # 用来正常显示负号
plt.rcParams['figure.dpi']         = 200        #分辨率epochs_range = range(epochs)plt.figure(figsize=(12, 3))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, train_acc, label='Training Accuracy')
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.xlabel(current_time) # 打卡请带上时间戳,否则代码截图无效plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label='Training Loss')
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

print("==============输入数据Shape为==============")
print("X_test.shape:",X_test.shape)
print("y_test.shape:",y_test.shape)pred = model(X_test.to(device)).argmax(1).cpu().numpy()print("\n==============输出数据Shape为==============")
print("pred.shape:",pred.shape)import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay# 计算混淆矩阵
cm = confusion_matrix(y_test, pred)plt.figure(figsize=(6,5))
plt.suptitle('')
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues")# 修改字体大小
plt.xticks(fontsize=10)
plt.yticks(fontsize=10)
plt.title("Confusion Matrix", fontsize=12)
plt.xlabel("Predicted Label", fontsize=10)
plt.ylabel("True Label", fontsize=10)# 显示图
plt.tight_layout()  # 调整布局防止重叠
plt.show()test_X = X_test[0].reshape(1, -1) # X_test[0]即我们的输入数据pred = model(test_X.to(device)).argmax(1).item()
print("模型预测结果为:",pred)
print("=="*20)
print("0:不会患心脏病")
print("1:可能患心脏病")

测试集预测准确率为87.1%,为了进一步提高模型性能,做了如下改进:

1、调整数据加载方式(启用Shuffle),打乱训练数据顺序,使每个batch的数据分布更均匀,提升模型泛化能力。

# 修改前(shuffle=False)
train_dl = DataLoader(..., shuffle=False)# 修改后
train_dl = DataLoader(..., shuffle=True)

2、调整优化器和学习率

# 修改前
learn_rate = 1e-4
opt = torch.optim.Adam(model.parameters(), lr=learn_rate)# 修改后
opt = torch.optim.Adam(model.parameters(), lr=1e-4, weight_decay=1e-5)  # 增加L2正则
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(opt, 'max', patience=5)  # 动态调整学习率

修改之后预测率最高超过了90%,预测准确率也有所提高

------------------小结---------------------------

循环神经网络(RNN)是一种专门处理序列数据的神经网络模型,其核心特点可归纳如下:

一、​​序列建模能力​

RNN通过​​循环连接结构​​处理序列输入(如文本、语音、时间序列),每个时间步的隐藏状态(hidden state)不仅依赖当前输入,还继承前一时间步的状态。这种设计使其能够捕捉​​时间依赖性​​,例如句子中单词的上下文关系或股价的历史趋势。

二、​​参数共享机制​

所有时间步共享同一组权重参数(如输入-隐藏层和隐藏-隐藏层矩阵),显著减少模型复杂度并提升泛化能力。这一特性使其能灵活处理​​变长序列​​,无需为不同长度输入单独设计网络。

三、​​记忆性与动态状态​

RNN通过隐藏状态的递归更新实现​​记忆功能​​,理论上可保留无限长的历史信息。例如,在机器翻译中,模型能利用前文信息生成连贯的译文。但实际中受限于梯度问题,长程依赖能力较弱。

相关文章:

  • YOLOv5修改检测框颜色,粗细,标签大小,标签名称
  • AI编程案例拆解|基于机器学习XX评分系统-后端篇
  • 深入理解算力:从普通电脑到宏观计算世界
  • 【Docker项目实战】使用Docker部署Caddy+vaultwarden密码管理工具(详细教程)
  • 如何在项目中使用双token机制?
  • 代码随想录算法训练营Day36
  • MyBatis XML 配置完整示例(含所有核心配置项)
  • 单片机-89C51部分:4、固件烧录
  • MAVLink协议:原理、应用与实践
  • Pytorch(无CPU搭建)+Jupyter
  • 代码随想录算法训练营第二十八天
  • Pygame入门:零基础打造你的第一个游戏窗口
  • 二、UI自动化测试02--元素定位方法
  • Leetcode刷题 由浅入深之哈希法——202. 快乐数
  • Adruino:传感器及步进电机
  • 我们分析前端生活。
  • 驱动开发硬核特训 · Day 21(上篇加强版):深入理解子系统机制与实战初探
  • 微服务架构下 MySQL 大表分库分表方案
  • 【Linux网络】构建与优化HTTP请求处理 - HttpRequest从理解到实现
  • std::mutex底层实现原理
  • 张家界乒乓球公开赛设干部职级门槛引关注,回应:仅限嘉宾组
  • VR数字沉浸体验又添新节目,泰坦尼克号驶进文旅元宇宙
  • 俄罗斯准备在没有先决条件的情况下与乌克兰进行谈判
  • 怎样更加贴近中国消费者,运动品牌给出“本地化”选择
  • 著名统计学家、北京工业大学应用数理学院首任院长王松桂逝世
  • 政治局会议深度|提出“设立新型政策性金融工具”有何深意?