医工互联

 找回密码
 注册[Register]

手机动态码快速登录

手机号快速登录

微信登录

微信扫一扫,快速登录

QQ登录

只需一步,快速开始

查看: 161|回复: 0
收起左侧

PaddlePaddle笔记5-心电图智能诊断

[复制链接]

  离线 

发表于 2023-1-19 21:39:25 来自手机 | 显示全部楼层 |阅读模式 <
睿洛医疗
参考资料:
AIWIN - 比赛
AIWIN 心电图智能诊断竞赛:TextCNN 精度0.67 - 飞桨AI Studio - 人工智能学习与实训社区
        心电图是临床最基础的一个检查项目,因为安全、便捷成为心脏病诊断的利器。每天都有大量的心电图诊断需求,但是全国范围内诊断心电图的专业医生数量不足,导致很多医院都面临专业心电图医生短缺的情况。人工智能技术的出现,为改善医生人力资源不足的问题带来了全新的可能。由于心电图数据与诊断的标准化程度较高,相对较易于运用人工智能技术进行智能诊断算法的开发。由于心电图可诊断的疾病类别特别丰富,目前,市面上出现较多的是针对某些特定类别的算法,尚没有看到能够按照临床诊断标准、在一定准确率标准下,提供类似医生的多标签多分类算法。
        需要识别的心电图包括12个类别:正常心电图、窦性心动过缓、窦性心动过速、窦性心律不齐、心房颤动、室性早搏、房性早搏、一度房室阻滞、完全性右束支阻滞、T波改变、ST改变、其它。
1.png

         心电数据的单位为mV,采样率为 500HZ,记录时长为 10 秒,存储格式为 MAT;文件中存储了 12 导联的电压信号(包含了I,II,III,aVR,aVL,aVF,V1,V2,V3,V4,V5 和 V6)。数据下载地址:心电图测试数据集https://download.csdn.net/download/zj850324/67399060
2.png
https://download.csdn.net/download/zj850324/67399060
数据格式:
12导联的数据,保存matlab格式文件中。数据格式是(12, 5000);
采样500HZ,10S长度有效数据;
0..12是I, II, III, aVR, aVL, aVF, V1, V2, V3, V4, V5和V6数据,单位是mV。
1,准备模块(依赖库按需安装即可,不再赘述)
  1. import scipy.io as sio
  2. import matplotlib.pyplot as plt
  3. import codecs, glob, os
  4. import numpy as np
  5. import pandas as pd
  6. import paddle
  7. import paddle.nn as nn
  8. from paddle.io import DataLoader, Dataset
  9. import paddle.optimizer as optim
  10. from paddlenlp.data import Pad
  11. import scipy.io as sio
  12. from sklearn.model_selection import StratifiedKFold
复制代码
2,构造数据集
  1. class MyDataset(Dataset):
  2.     def __init__(self, mat, label, mat_dim=3000):
  3.         super(MyDataset, self).__init__()
  4.         self.mat = mat
  5.         self.label = label
  6.         self.mat_dim = mat_dim
  7.     def __len__(self):
  8.         return len(self.mat)
  9.     def __getitem__(self, index):
  10.         idx = np.random.randint(0, 5000-self.mat_dim)
  11.         # idy = np.random.choice(range(12), 9)
  12.         inputs=paddle.to_tensor(self.mat[index][:, :, idx:idx+self.mat_dim])
  13.         label=paddle.to_tensor(self.label[index])
  14.         return inputs,label
复制代码
3,构造模型
  1. class TextCNN_Plus(nn.Layer):
  2.     def __init__(self, kernel_num=30, kernel_size=[3, 4, 5], dropout=0.5,mat_dim=3000):
  3.         super(TextCNN_Plus, self).__init__()
  4.         self.kernel_num = kernel_num
  5.         self.kernel_size = kernel_size
  6.         self.dropout = dropout
  7.         self.convs = nn.LayerList([nn.Conv2D(1, self.kernel_num, (kernel_size_, mat_dim))
  8.                 for kernel_size_ in self.kernel_size])
  9.         self.dropout = nn.Dropout(self.dropout)
  10.         self.linear = nn.Linear(3 * self.kernel_num, 1)
  11.     def forward(self, x):
  12.         convs = [nn.ReLU()(conv(x)).squeeze(3) for conv in self.convs]
  13.         pool_out = [nn.MaxPool1D(block.shape[2])(block).squeeze(2) for block in convs]
  14.         pool_out = paddle.concat(pool_out, 1)
  15.         logits = self.linear(pool_out)
  16.         return logits
复制代码
4,加载数据集
  1. def load_data(BATCH_SIZE):
  2.     train_mat = glob.glob('./data/ecg/train/*.mat')
  3.     train_mat.sort()
  4.     train_mat = [sio.loadmat(x)['ecgdata'].reshape(1, 12, 5000) for x in train_mat]
  5.     test_mat = glob.glob('./data/ecg/val/*.mat')
  6.     test_mat.sort()
  7.     test_mat = [sio.loadmat(x)['ecgdata'].reshape(1, 12, 5000) for x in test_mat]
  8.     train_df = pd.read_csv('./data/ecg/trainreference.csv')
  9.     train_df['tag'] = train_df['tag'].astype(np.float32)
  10.     # 查看数据
  11.     plt.plot(range(5000), train_mat[0][0][0])
  12.     plt.plot(range(5000), train_mat[0][0][1])
  13.     plt.plot(range(5000), train_mat[0][0][3])
  14.     # plt.show()
  15.     train_df.head()
  16.     print(test_mat[0].shape)
  17.     train_ds = MyDataset(train_mat, train_df['tag'])
  18.     train_loader = DataLoader(train_ds, batch_size=BATCH_SIZE, shuffle=True)
  19.     for batch in train_loader:
  20.         print(batch)
  21.         break
  22.     return train_mat,train_df,test_mat
复制代码
3.png

4.png


5,定义模型网络
  1. def model_create(mat_dim):
  2.     # model = TextCNN()
  3.     model = TextCNN_Plus(mat_dim=mat_dim)
  4.     paddle.summary(model, (64, 1, 9, mat_dim))
  5.     return model
复制代码
5.png


6,模型训练
  1. def model_train(EPOCHS,BATCH_SIZE,LEARNING_RATE,num_splits,mat_dim,output_dir):
  2.     train_mat, train_df, test_mat = load_data(BATCH_SIZE)
  3.     skf = StratifiedKFold(n_splits=num_splits)
  4.     if (not os.path.exists(output_dir)):
  5.         os.mkdir(output_dir)
  6.     fold_idx = 0
  7.     for tr_idx, val_idx in skf.split(train_mat, train_df['tag'].values):
  8.         train_ds = MyDataset(np.array(train_mat)[tr_idx], train_df['tag'].values[tr_idx], mat_dim=mat_dim)
  9.         dev_ds = MyDataset(np.array(train_mat)[val_idx], train_df['tag'].values[val_idx], mat_dim=mat_dim)
  10.         Train_Loader = DataLoader(train_ds, batch_size=BATCH_SIZE, shuffle=True)
  11.         Val_Loader = DataLoader(dev_ds, batch_size=BATCH_SIZE, shuffle=True)
  12.         # model = TextCNN()
  13.         model = TextCNN_Plus(mat_dim=mat_dim)
  14.         optimizer = optim.Adam(parameters=model.parameters(), learning_rate=LEARNING_RATE)
  15.         criterion = nn.BCEWithLogitsLoss()
  16.         Test_best_Acc = 0
  17.         for epoch in range(0, EPOCHS):
  18.             Train_Loss, Test_Loss = [], []
  19.             Train_Acc, Test_Acc = [], []
  20.             model.train()
  21.             for i, (x, y) in enumerate(Train_Loader):
  22.                 pred = model(x)
  23.                 loss = criterion(pred, y)
  24.                 Train_Loss.append(loss.item())
  25.                 pred = (paddle.nn.functional.sigmoid(pred) > 0.5).astype(int)
  26.                 Train_Acc.append((pred.numpy() == y.numpy()).mean())
  27.                 loss.backward()
  28.                 optimizer.step()
  29.                 optimizer.clear_grad()
  30.             model.eval()
  31.             for i, (x, y) in enumerate(Val_Loader):
  32.                 pred = model(x)
  33.                 Test_Loss.append(criterion(pred, y).item())
  34.                 pred = (paddle.nn.functional.sigmoid(pred) > 0.5).astype(int)
  35.                 Test_Acc.append((pred.numpy() == y.numpy()).mean())
  36.             if epoch % 10 == 0:
  37.                 print(
  38.                     "Epoch: [{}/{}] TrainLoss/TestLoss: {:.4f}/{:.4f} TrainAcc/TestAcc: {:.4f}/{:.4f}".format( \
  39.                         epoch + 1, EPOCHS, \
  40.                         np.mean(Train_Loss), np.mean(Test_Loss), \
  41.                         np.mean(Train_Acc), np.mean(Test_Acc) \
  42.                         )
  43.                 )
  44.             if Test_best_Acc < np.mean(Test_Acc):
  45.                 print(f'Fold {fold_idx} Acc imporve from {Test_best_Acc} to {np.mean(Test_Acc)} Save Model...')
  46.                 paddle.save(model.state_dict(), os.path.join(output_dir, "model_{}.pdparams".format(fold_idx)))
  47.                 Test_best_Acc = np.mean(Test_Acc)
  48.         fold_idx += 1
复制代码

 7,载入模型预测(得先训练)
  1. def model_predict(modelpath,mat_dim,answer_path):
  2.     train_mat, train_df, test_mat = load_data(BATCH_SIZE)
  3.     test_perd = np.zeros(len(test_mat))
  4.     tta_count = 20
  5.     model = model_create(mat_dim)
  6.     layer_state_dict = paddle.load(modelpath + '/model_4.pdparams')
  7.     model.set_state_dict(layer_state_dict)
  8.     for fold_idx in range(num_splits):
  9.         test_ds = MyDataset(test_mat, [0] * len(test_mat), mat_dim=mat_dim)
  10.         Test_Loader = DataLoader(test_ds, batch_size=BATCH_SIZE, shuffle=False)
  11.         layer_state_dict = paddle.load(os.path.join(output_dir, "model_{}.pdparams".format(fold_idx)))
  12.         model.set_state_dict(layer_state_dict)
  13.         for tta in range(tta_count):
  14.             test_pred_list = []
  15.             for i, (x, y) in enumerate(Test_Loader):
  16.                 pred = model(x)
  17.                 test_pred_list.append(
  18.                     paddle.nn.functional.sigmoid(pred).numpy()
  19.                 )
  20.             test_perd += np.vstack(test_pred_list)[:, 0]
  21.     test_perd /= tta_count * num_splits
  22.     # 生成结果
  23.     test_path = glob.glob('./data/ecg/val/*.mat')
  24.     test_path = [os.path.basename(x)[:-4] for x in test_path]
  25.     test_path.sort()
  26.     test_answer = pd.DataFrame({
  27.         'name': test_path,
  28.         'tag': (test_perd > 0.5).astype(int)
  29.     }).to_csv(answer_path, index=None)
复制代码
8,预测结果
6.png


备注
调试步骤及临时配参
  1. #### 测试
  2. EPOCHS = 200
  3. BATCH_SIZE = 30
  4. LEARNING_RATE = 0.0005
  5. num_splits = 5
  6. mat_dim = 4000
  7. output_dir = 'checkpoint'
  8. answer_path = './data/ecg/answer.csv'
  9. # model_train(EPOCHS,BATCH_SIZE,LEARNING_RATE,num_splits,mat_dim,output_dir)
  10. model_predict(output_dir,mat_dim,answer_path)
复制代码



来源:https://blog.csdn.net/zj850324/article/details/122037474
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

提醒:禁止复制他人回复等『恶意灌水』行为,违者重罚!
您需要登录后才可以回帖 登录 | 注册[Register] 手机动态码快速登录 微信登录

本版积分规则

发布主题 快速回复 收藏帖子 返回列表 客服中心 搜索
简体中文 繁體中文 English 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french

QQ|RSS订阅|小黑屋|处罚记录|手机版|联系我们|Archiver|医工互联 |粤ICP备2021178090号 |网站地图

GMT+8, 2024-12-22 14:50 , Processed in 0.277010 second(s), 63 queries .

Powered by Discuz!

Copyright © 2001-2023, Discuz! Team.

快速回复 返回顶部 返回列表