基于脑PET图像的疾病预测挑战赛 学习日记(1)

本文介绍了如何使用Python和深度学习技术处理脑PET图像数据,构建逻辑回归模型进行轻度认知障碍的预测。内容包括数据预处理、特征提取(如统计值和通道选择)、模型训练及预测提交的详细步骤,特别提到了在Windows系统上的路径调整问题。
摘要由CSDN通过智能技术生成

大赛地址

https://aistudio.baidu.com/projectdetail/6554002?sUid=377372&shared=1&ts=1689768420818

任务介绍

基于脑PET图像的疾病预测挑战赛

近年来,深度学习在医学图像处理和疾病预测方面取得了显著的进展。脑PET(Positron Emission Tomography)图像是一种用于研究脑部功能和代谢活动的重要影像技术。在本篇博客中,我们将使用Python编程语言和一些常用的深度学习库,展示如何处理脑PET图像数据,并构建逻辑回归模型来进行脑PET图像的疾病预测。

数据集介绍

为研究基于脑PET图像的疾病预测,本次大赛提供了海量脑PET数据集作为脑PET图像检测数据库的训练样本,参赛者需根据提供的样本构建模型,对轻度认知障碍进行分析和预测。脑PET图像检测数据库,记录了老年人受试志愿者的脑PET影像资料,其中包括确诊为轻度认知障碍(MCI)患者的脑部影像数据和健康人(NC)的脑部影像数据。 被试者按医学诊断分为两类:

NC:健康
MCI:轻度认知障碍
本次大赛所用脑PET图像检测数据库,图像格式为nii。

baseline流程

将baseline部署到自己机器上的,Windows系统

导入相关的包

import glob                # 获取文件路径
import numpy as np
import pandas as pd
import nibabel as nib      # 处理医学图像数据
from nibabel.viewers import OrthoSlicer3D    # 图像可视化
from collections import Counter              # 计数统计

数据预处理

数据预处理的时候,没有先把数据打乱,而是提起出路径,将路径打乱。因为路径方便存储,而直接打乱数据内存消耗大

# 读取训练集文件路径
train_path = glob.glob('./脑PET图像分析和疾病预测挑战赛数据集/Train/*/*')
test_path = glob.glob('./脑PET图像分析和疾病预测挑战赛数据集/Test/*')
print(len(train_path))
print(len(test_path))
# 打乱训练集和测试集的顺序
np.random.shuffle(train_path)
np.random.shuffle(test_path)

特征提取

对于深度学习任务,特征提取是非常重要的一步。在本例中,我们定义了一个函数extract_feature,用于从脑PET图像中提取特征。

extract_feature函数从文件路径加载PET图像数据,并从中随机选择10个通道。然后,它计算了一系列统计特征,如非零像素数量、零像素数量、平均值、标准差等。最后,函数根据文件路径判断样本类别,并将提取到的特征和类别作为返回值。

def extract_feature(path):
    # 加载PET图像数据
    img = nib.load(path)
    # 获取第一个通道的数据
    img = img.dataobj[:, :, :, 0]
    
    # 随机筛选其中的10个通道提取特征
    random_img = img[:, :, np.random.choice(range(img.shape[2]), 10)]
    
    # 对图片计算统计值
    feat = [
        (random_img != 0).sum(),               # 非零像素的数量
        (random_img == 0).sum(),               # 零像素的数量
        random_img.mean(),                     # 平均值
        random_img.std(),                      # 标准差
        len(np.where(random_img.mean(0))[0]),  # 在列方向上平均值不为零的数量
        len(np.where(random_img.mean(1))[0]),  # 在行方向上平均值不为零的数量
        random_img.mean(0).max(),              # 列方向上的最大平均值
        random_img.mean(1).max()               # 行方向上的最大平均值
    ]
    
    # 根据路径判断样本类别('NC'表示正常,'MCI'表示异常)
    if 'NC' in path:
        return feat + ['NC']
    else:
        return feat + ['MCI']

为什么要提取这些特征:
在这个特征提取函数中,提取了以下几个统计特征:
1.非零像素的数量
2.零像素的数量
3.平均值
4.标准差
5.列方向上非零均值的数量
6.行方向上非零均值的数量
7.列方向上的最大平均值
8.行方向上的最大平均值
9.这些特征被提取的考量有:

		capturing overall intensity distribution - 通过均值、标准差等可以反映整体强度分布
		highlighting sparse structures - 非零像素数量可以反映稀疏结构
		summarizing shape/structure - 非零均值数量、最大均值可以反映形状结构信息
		easy and fast to compute - 这些统计特征计算简单快速
		working with random slices - 通过随机选取slice,可以计算稳定的统计特征
		effective for anomaly detection - 平均值、极值等参数在异常检测中很有效
		generalizable to new data - 这些特征对新的PET数据也具有普适性
		结合病例的PET图像差异,这些特征可以用来区分正常和异常样本。

值得注意的是:

if 'NC' in path:
        return feat + ['NC']
    else:
        return feat + ['MCI']

这个代码段在test路径中没有NC,返回值都加入了MCI并没有影响,因为最后预测数据的时候没用用最后一列。

模型训练

在这一步骤中,我们将利用extract_feature函数提取训练集和测试集的特征,并使用逻辑回归模型对训练集进行训练。

在这里,我们通过循环将特征提取过程重复进行30次,这是为了增加训练样本的多样性。然后,我们使用逻辑回归模型LogisticRegression来训练数据。在训练完成后,模型已经学习到了从特征到类别的映射关系。

# 对训练集进行30次特征提取,每次提取后的特征以及类别('NC'表示正常,'MCI'表示异常)被添加到train_feat列表中。
train_feat = []
for _ in range(30):
    for path in train_path:
        train_feat.append(extract_feature(path))
     
# 对测试集进行30次特征提取   
test_feat = []
for _ in range(30):
    for path in test_path:
        test_feat.append(extract_feature(path))
        
# 使用训练集的特征作为输入,训练集的类别作为输出,对逻辑回归模型进行训练。
from sklearn.linear_model import LogisticRegression
m = LogisticRegression(max_iter=1000)
m.fit(
    np.array(train_feat)[:, :-1].astype(np.float32),  # 特征
    np.array(train_feat)[:, -1]                       # 类别
)

对测试机和训练集都进行了30次的训练,并将训练集分为data、label丢入了LogisticRegression进行训练
这一类机器学习模型的分类效果还是较差

预测与结果提交

步骤五:预测与结果提交
在这一步骤中,我们使用训练好的逻辑回归模型对测试集进行预测,并将预测结果进行投票,选出最多的类别作为该样本的最终预测类别。最后,我们将预测结果存储在CSV文件中并提交结果。

具体来说,我们使用了Counter来统计每个样本的30次预测结果中最多的类别,并将结果存储在test_pred_label列表中。然后,我们将样本ID和对应的预测类别存储在一个DataFrame中,并将其按照ID排序后保存为CSV文件,这样我们就得到了最终的结果提交文件。

# 对测试集进行预测并进行转置操作,使得每个样本有30次预测结果。
test_pred = m.predict(np.array(test_feat)[:, :-1].astype(np.float32))
test_pred = test_pred.reshape(30, -1).T

# 对每个样本的30次预测结果进行投票,选出最多的类别作为该样本的最终预测类别,存储在test_pred_label列表中。
test_pred_label = [Counter(x).most_common(1)[0][0] for x in test_pred]

# 生成提交结果的DataFrame,其中包括样本ID和预测类别。
submit = pd.DataFrame(
    {
        'uuid': [int(x.split('/')[-1][:-4]) for x in test_path],  # 提取测试集文件名中的ID
        'label': test_pred_label                                  # 预测的类别
    }
)

# 按照ID对结果排序并保存为CSV文件
submit = submit.sort_values(by='uuid')
submit.to_csv('submit.csv', index=None)

最后使用 m.predict()函数进行预测,因为之前进行了30次的特征提取,所以对每个样本的30次预测结果进行投票,选出最多的类别作为该样本的最终预测类别,存储在test_pred_label列表中。

同时,部署在Windows上有个小坑,就是路径问题:
原代码:

'uuid': [int(x.split('/')[-1][:-4]) for x in test_path],  # 提取测试集文件名中的ID

报错:
在这里插入图片描述
因为在windows上路径表达不同,代码应该改为:

'uuid': [int(x.split('\\')[-1][:-4]) for x in test_path],  # 提取测试集文件名中的ID
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值