Python课程设计--基于机器学习的EHG信号分析与早产诊断方法

这是大二下的一个Python期末研究性课程设计,整篇报告比较长,这里就只po一些主要内容,源码的话后续有时间可能会传到github上~

一、引言

        本次实验首先对原始数据集TPEHG和原始EHG信号数据进行了分析和数据预处理。此外,在早产预测中,特征提取是关键步骤,对此我讨论了多种特征提取方 法,除了数据集中已有的峰值频率(Fpeak)、中值频率(Fmed)、采样熵(SamEn)等,还通过原始EHG信号提取了峰度(Kurtosis)和波峰数(NumberofPeaks)作为新的特征值, 并进行讨论和分析,实现病例样本的特征化描述。

        并且我还设计了特征选择方法,首先通过散点图、热力图等对特征相关性进行可视化分析,然后通过SelectKBest方法使用 ANOVAF值进行特征选择,选出与目标值相关性最高的几个特征以实现后续的模型训练。 对于早产样本在TPEHG数据集中的稀少性导致的类间样本不平衡问题,我采用了合成采样技术,使用SMOTE技术对类别不平衡的数据进行过采样,有助于更准确地评估模型的性能。并且我对数据进行了特征缩放,通过StandardScaler来对特征进行标准化处理。

        为了获得较好的性能,我尝试了多种机器学习模型进行训练,包括一开始的逻辑回归和支持向量机模型,以及最终确定的深度神经网络模型、随机森林和XGBoost模型, 并在训练的过程中不断对模型进行调参和优化,以实现较好的分类预测效果。最后打印各个模型的分类报告,可视化混淆矩阵和模型的特征重要性来比较和明确各个模型的性能。结果显示,随机森林和XGBoost在早产诊断中展现出较好的准确性和稳定性,而深度神经网络相对来说稳定性较差,还有很多的优化空间。 通过对EHG信号的深入学习和细致分析,结合先进机器学习技术的创新应用,本次实验在早产诊断取得了较好的效果。

二、材料与方法

1.TPEHG

      为了促进子宫肌电信号的临床应用,美国国立卫生研究院资助建立了开源EHG数 据库TPEHG,旨在分析孕妇的子宫肌电图(EHG)信号,以区分足月和早产分娩的群体。

2.特征提取与分析

      经过分析与尝试,除了数据集中已有的峰值频率(Fpeak)、中值频率(Fmed)、采样熵(SamEn)等,我还通过EHG信号构建了峰度 (Kurtosis) 和波峰数 (Number of Peaks) 作为新的特征值。

     1. 峰度(Kurtosis): 峰度是描述随机变量分布形态的一个统计量,特别是描述分布的尖峭程度或平坦程 度。在信号处理中,峰度可以用来区分不同类型的信号,而对于EHG信号来说,峰度 可能反映了宫缩的强度和特性,这可能与早产风险有较高的相关性。计算公式如下:

     2. 波峰数量(PeakCount): 波峰数量是指信号中局部极大值的个数,这可以反映信号的活跃程度或宫缩的频 率。在EHG信号中,波峰可能对应于宫缩事件,波峰数量可能与宫缩的频率和强度有关,因此这是评估早产风险的一个重要指标。

def read_signal_file_and_compute_rms(file_path):  #读取EHG信号并构建新特征
    with open(file_path, 'rb') as file:
        binary_data = file.read()
   
    samples = struct.unpack('<' + 'h' * (len(binary_data) // 2), binary_data)
    signal = np.array(samples, dtype=np.float32) / (2**15) * 2.5  # 转换为电压值
    num_channels = 3
    samples_per_channel = len(signal) // num_channels
    kurt_values = []  #峰度
    peaks_values = []  #波峰
    for i in range(num_channels):
        channel_signal = signal[i * samples_per_channel: (i + 1) * samples_per_channel]
        kurt = kurtosis(channel_signal)
        kurt_values.append(kurt)
        peaks, _ = find_peaks(channel_signal)  # 获取峰值索引
        peaks_values.append(len(peaks)) #计算峰值数量
    return kurt_values,peaks_values

        总之,选择峰度和波峰数量作为特征是为了更好的捕捉EHG信号的特定属性,这些属性可能与早产风险有很大的相关性。峰度提供了信号分布形态的信息,而波峰数量 提供了信号活动频率的信息。这两种特征的结合可以帮助我们更好地理解和预测早产的 可能性。

三、机器学习模型

       在本次实验中,我构建了多种模型进行早产诊断预测,使得诊断系统能够更全面地分析数据,促进了对不同模型性能的深入理解和比较,为后续的研究 和优化提供更多可能的方向。

(1) 深度神经网络

       本次实验我选择了全连接神经网络模型来进行训练。全连接神经网络,也称为密集网络,是深度学习中的基础架构,结构如图,由多层神经元组成,每层的所有神经元 均与前一层的所有神经元相连接。这种网络通过权重和偏置参数将输入数据在各层间传递,并通过非线性激活函数引入复杂性,使其能够学习和模拟复杂的函数映射。全连接 网络广泛应用于分类、回归和时间序列预测等多种任务。作为深度学习的核心构件,全 连接网络不仅是独立应用的重要模型,也是构成更复杂网络如卷积神经网络中不可或缺 的部分

        具体构建与优化:首先,对初始设定的神经网络结构进行扩展,将其从单隐层网 络升级为双层隐层网络,以增强模型的学习能力和表征复杂性。其次,选用了CrossEn tropyLoss() 作为损失函数,以更有效地衡量和最小化预测概率分布与真实标签之间的差 异。此外,我还采用了Adam优化器,它通过自适应估计的梯度方差和均值来调整学习 率,从而加快收敛速度并提高模型的稳定性。最后,通过细致调整训练周期数,确保模 型在训练过程中充分学习数据特征,避免了过拟合或欠拟合的问题,实现了模型性能的 优化和提升。 

#构建深度神经网络
# 将SMOTE处理后的数据转换为PyTorch张量
X_res_tensor = torch.tensor(X_res, dtype=torch.float32)
y_res_tensor = torch.tensor(y_res, dtype=torch.long)
# 划分训练集和验证集
from torch.utils.data import TensorDataset, DataLoader, random_split

dataset = TensorDataset(X_res_tensor, y_res_tensor)
train_size = int(0.8 * len(dataset))
test_size = len(dataset) - train_size
train_dataset, test_dataset = random_split(dataset, [train_size, test_size])

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

#构建神经网络模型
class DeepNetwork(nn.Module):
    def __init__(self, input_size, hidden_size1, hidden_size2, num_classes):
        super(DeepNetwork, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size1)
        self.relu1 = nn.ReLU()
        self.fc2 = nn.Linear(hidden_size1, hidden_size2)
        self.relu2 = nn.ReLU()
        self.fc3 = nn.Linear(hidden_size2, num_classes)
        
    def forward(self, x):
        x = self.fc1(x)
        x = self.relu1(x)
        x = self.fc2(x)
        x = self.relu2(x)
        x = self.fc3(x)
        return x

model_nn=DeepNetwork(4,128,64,2)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model_nn.parameters(), lr=0.001)
# 训练模型
num_epochs = 100
for epoch in range(num_epochs):
    for inputs, labels in train_loader:
        optimizer.zero_grad()
        outputs = model_nn(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

# 评估模型
model_nn.eval()
all_predictions = []
all_labels = []
with torch.no_grad():
    for inputs, labels in test_loader:
        outputs = model_nn(inputs)
        _, predicted = torch.max(outputs, 1)
        # 将预测结果和实际标签添加到列表中
        all_predictions.extend(predicted.numpy())
        all_labels.extend(labels.numpy())

# 打印分类报告
print("深度神经网络:")
print(classification_report(all_labels, all_predictions))
print(f"准确率: {accuracy_score(all_labels, all_predictions)}\n")

(2) 随机森林

       随机森林(RandomForest,RF)是一种强大的集成学习技术,它通过构建多个决策 树来提高模型的预测准确性和鲁棒性,结构如图3。每棵树在训练时使用随机选取的样 本子集,并且在选择分裂节点时引入随机性,这不仅增加了模型的多样性,还有助于减 少过拟合的风险。随机森林能够自动评估特征的重要性,为理解模型决策提供了有力工 具。此外,它的训练过程可以并行化,使得处理大规模数据集变得高效。随机森林对噪 声和异常值具有很好的抵抗力,适用于分类和回归任务,广泛应用于金融、生物信息学、 医疗诊断等多个领域。 具体构建与优化:定义了超参数网格,创建GridSearchCV实例,通过K折交叉验 证系统地遍历超参数网格中的所有组合,来训练模型、评估不同超参数组合的性能,最后选择出最优的组合作为最终的预测模型,以提高随机森林模型的准确率和泛化能力。

(3)XGBoost

        XGBoost 是一种先进的梯度提升算法,以其卓越的性能和效率在机器学习领域广受 青睐。它通过逐步添加决策树来最小化带有正则化项的可微分损失函数,有效控制模型 复杂度并减少过拟合。XGBoost支持处理缺失值,允许自动学习最优分裂点,并且通过 并行化处理大幅提升计算速度。此外,它提供灵活的自定义损失函数和评估标准,以及 特征重要性评估,帮助理解模型决策过程。XGBoost的另一显著优势是其早停法策略, 可以在交叉验证中及时终止训练,避免不必要的计算。由于这些特性,XGBoost适用于 大规模数据集和多种机器学习任务,包括分类、回归和排序问题,使其成为数据科学家 和工程师解决复杂问题的强大工具。具体构建与优化与随机森林同理,采用网格搜索通 过K折交叉验证来获得最优参数

#随机森林和XGBoost模型
#数据划分
X_train, X_test, y_train, y_test = train_test_split(X_res, y_res, test_size=0.2, stratify=y_res, random_state=42)

rf_model = RandomForestClassifier(random_state=42)
# 随机森林的超参数网格
param_grid_rf = {
    'n_estimators': [100, 200],  
    'max_depth': [10, 20],  
    'min_samples_split': [2, 5],  
    'min_samples_leaf': [1, 2],  
    'bootstrap': [True, False]  
}
# 创建GridSearchCV实例
grid_search_rf = GridSearchCV(estimator=rf_model, param_grid=param_grid_rf, cv=3, scoring='accuracy')
# 训练随机森林模型并找到最佳参数
grid_search_rf.fit(X_train, y_train)

# 定义 XGBoost 模型
xgb_model = XGBClassifier(use_label_encoder=False, eval_metric='logloss', random_state=42)
# 定义超参数网格
param_grid = {
    'max_depth': [5, 7,9],
    'learning_rate': [0.01, 0.1],
    'n_estimators': [200,300],
    'subsample': [0.8, 0.9],
    'colsample_bytree': [ 0.8, 0.9]
}
# 创建 GridSearchCV 实例
grid_search = GridSearchCV(estimator=xgb_model, param_grid=param_grid, cv=3, scoring='accuracy')
# 训练模型并找到最佳参数
grid_search.fit(X_train, y_train)

def train_and_evaluate(model, X_train, y_train, X_test, y_test, model_name):
    model.fit(X_train, y_train)
    y_pred_test = model.predict(X_test)
    print(f"{model_name}评估:")
    print(classification_report(y_test, y_pred_test))
    print(f"准确率: {accuracy_score(y_test, y_pred_test)}\n")
    return y_pred_test

# 运行模型训练和评估
rf_predictions=train_and_evaluate(grid_search_rf, X_train, y_train, X_test, y_test, "随机森林")
xgb_predictions=train_and_evaluate(grid_search, X_train, y_train, X_test, y_test,  "XGBoost")

四、结果

1.特征有效性与特征选择

       通过对原始EHG信号数据的提取与计算,得到每个样本的峰度(Kurtosis)和波峰数 (Number of Peaks) 数据后,加上原始的信号特征一共有六个特征。 首先先对这六个特征进行可视化分析: (1) 散点图

       散点图可用于探索性数据分析,以帮助研究人员理解哪些特征与目标的进展有统计学上的相关性或模式。(具体图略)

(2) 相关性热力图

       特征相关性热力图是一种数据可视化工具,用于展示数据集中各个特征之间的相关性强度。在热力图中,通常使用颜色的深浅来表示相关性的强度,颜色越深表示相关性 越强。 由图中可得,不同的特征之间的相关性差异较大,对目标变量的相关强弱也不同。 如特征Fmed和Fpeak的相关系数为0.8,这表明它们之间有较强的正相关性。而目标变 量Gestation 和 SamEn 的相关系数为-0.61,这表明它们之间有较强的负相关性。此时就 需要进行特征选择,剔除那些与其他特征高度相关的特征,去掉无关或对目标影响很小 的特征,选择与目标相关度高的特征,以减少特征空间的维度,有助于提高模型的泛化能力。(具体图略)

(3) 特征选择

     使用SelectKBest 方法从原始数据集中筛选出最具预测力的四个特征。首先,通过 设置ANOVAF-value 作为评分函数并指定选择的特征数量,创建了一个特征选择器。随后,该选择器被拟合到特征矩阵x和目标变量y上,以评估各特征的重要性。利 用得到的布尔索引,代码提取了选中特征的索引和相应的评分,并从全局特征列表中检 索了这些特征的名称。最终,通过转换原始数据集,生成了一个新的仅包含这四个被选 中的特征的数据集。这一过程不仅有助于简化模型结构,降低复杂性,还能提高模型的 泛化能力和解释性,为后续的模型训练和分析打下坚实的基础。

        最后将不同特征的ANOVAF-value 进行可视化,直观地展示了每个特征对预测目标变量的贡献 大小。 由图中可知,筛选出的分数最高的四个特征为中值频率(Fmed)、采样熵(SamEn)、 峰度(Kurtosis) 和波峰数(NumberofPeaks),可见前面根据原始EHG信号构建的新特征 与目标变量具有较高的相关性,体现了本次的特征提取是比较合理性且有效的。

2.不同模型的性能比较

(1) 合成采样

       由于数据集中某些类别的样本数量远多于其他类别,出现了样本不平衡的问题。在 这种情况下,多数类可能会主导模型的训练过程,导致模型对少数类的预测性能不佳。 因此,我选择了smote来进行过采样。 SMOTE(Synthetic Minority Over-sampling Technique)技术,通过在少数类的现有样 本之间生成合成样本来增加其数量,从而实现类别分布的平衡。这种方法不仅提高了模 型对少数类的识别能力,还有助于减少过拟合的风险,并保持了原有数据的统计特性。

(2) 性能比较

       在完成了特征提取、选择以及通过SMOTE技术进行合成采样处理之后,我对多种不同的机器学习模型进行了综合训练与评估,其中包括逻辑回归和支持向量机模型的尝 试,但由于其复杂度较低,模型的分类效果较差,未能满足性能预期。因此, 最后我选定了深度神经网络、随机森林和XGBoost模型来进行综合训练和评估。

       首先对三个模型的预测结果打印了分类报告,充分直观地展现各个模型的评估数 据,如图11所示。 从图中可以看到:深度神经网络的Recall和F1-Score值在类别0上都要比类别1要 高,表明模型对负样本的分类能力稍好一点。整体来说样本的分类准确率较好,不过相对随机森林和XGBoost要稍差一点,宏平均和加权平均的值很接近,表明模型在两个 类别上的性能整体还是比较均衡的。随机森林模型性能的宏平均和加权平均的精确度、 召回率和F1分数均为0.82,表明随机森林在两个类别的预测上都表现出较高的精确度, 9 图10支持向量机分类报告 图11分类报告 实现了较好的分类性能。XGBoost模型整体准确率为0.81,介于随机森林和深度神经网 络之间,宏平均和加权平均的精确度、召回率和F1分数均为0.81,在两个类别上的性 能整体上看较为均衡。 10 接着对每个模型的混淆矩阵结果进行热力图可视化分析,如图12。由热力图可以 图12混淆矩阵热力图 非常直观的看到每个模型在各个类别样本上的分类结果,可以帮助识别模型在哪些类 别上容易出错,有助于我们识别模型的弱点,以此来优化和改进数据与模型。比如从图 中可以看出,随机森林在正类上的性能略低于XGBoost,但在负类样本上表现的很好; XGBoost 显示出较高的真正例数量,表明其在正类上的识别能力较强;而神经网络则对 于负类样本的预测过于敏感,容易产生误判。 综合分析可得,随机森林的整体分类性能最佳,XGBoost也实现了较好的分类效 果,它们在两个类别上都表现出了最高的准确率,提供了较好的结果,这表明随机森林 和XGBoost 模型在早产诊断中都具有较好的分类能力和泛化性能。深度神经网络整体性能稍差,可能需要更多的数据或调整网络结构来进一步提高性能。

(其余图略)

3.特征重要性分析

        为了进一步理解模型的分类依据和增强模型的可解释性,我对随机森林和XGBoost 模型进行了特征重要性可视化,如图所示。 将两个模型的特征重要性图进行比较,可以看到中值频率(Fmed)、采样熵(SamEn)、 峰度(Kurtosis) 和波峰数(Number of Peaks) 这四个特征在两个模型中均具有较高的重要 性,尤其是SamEn和Peaks,这表明前面所选的特征都是比较有效且合理的,都是对预 测目标变量有显著影响的关键特征。 综上所述,特征重要性分析是一个关键的工具,它揭示了模型分类决策背后的逻 辑。通过识别和评估不同特征对预测结果的贡献度,我们可以更深入地理解模型的行 为,从而对模型的可信度和透明度进行验证。这种分析不仅证实了所提取特征的合理性 和有效性,而且为模型的进一步优化提供了方向。

整体写的比较粗略,可能不是很连贯,有问题可以一起交流讨论~

  • 22
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值