赛事实践任务:脑PET图像分析和疾病预测挑战赛------Baseline逐行精读

2023 iFLYTEK A.I.开发者大赛-讯飞开放平台2022 iFLYTEK A.I.开发者大赛-讯飞开放平台https://challenge.xfyun.cn/topic/info?type=pet-2023&ch=vWxQGFU本文用于记录讯飞开办的AI夏令营-CV实践笔记

 此文将逐行解释代码逻辑,和基础赛事数据的导入。作为一些新手小白遇到的基础问题

一、数据的下载和导入

 在注册赛事后得到以下界面,选择赛事数据,得到两个文件。第一个为数据文件,第二个为代码运行后得到的示例.csv文件。如图所示:

得到的是判别类型。

二、 代码的逐行解析

1、python代码

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/*')

# 打乱训练集和测试集的顺序
np.random.shuffle(train_path)
np.random.shuffle(test_path)


# 对PET文件提取特征
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']


# 对训练集进行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次预测结果。
test_pred = m.predict(np.array(test_feat)[:, :-1].astype(np.float32))
test_pred = test_pred.reshape(30, -1).T
test_path = [x.replace("\\", "/") for x in test_path]
# 对每个样本的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('submit1.csv', index=None)

2、数据集存放位置

下载好的数据集需要存放文件位置,其具体位置应该为

当前项目的一级目录下。

# 读取训练集文件路径
train_path = glob.glob('./脑PET图像分析和疾病预测挑战赛公开数据/Train/*/*')
test_path = glob.glob('./脑PET图像分析和疾病预测挑战赛公开数据/Test/*')

 如上述代码所示,在当前工作目录下寻找名为“脑PET图像分析和疾病预测挑战赛公开数据”的文件夹,并读取其中的训练集和测试集数据的文件路径。具体地,训练集数据应该位于“脑PET图像分析和疾病预测挑战赛公开数据/Train/”目录下的子文件夹中,测试集数据应该位于“脑PET图像分析和疾病预测挑战赛公开数据/Test/”目录下

主函数main和 脑PET图像分析和疾病预测挑战赛公开数据”的文件夹在一个目录123下面。

3、代码逻辑

主要作用是实现对医学图像数据进行特征提取和分类预测,包括以下主要步骤:

1、使用glob模块获取训练集和测试集中PET图像数据的文件路径,并随机打乱其顺序。

train_path = glob.glob('./脑PET图像分析和疾病预测挑战赛公开数据/Train/*/*')
test_path = glob.glob('./脑PET图像分析和疾病预测挑战赛公开数据/Test/*')
np.random.shuffle(train_path)
np.random.shuffle(test_path)

2、定义一个extract_feature函数,对PET图像数据进行特征提取,并返回提取的特征值以及对应的类别('NC'表示正常,'MCI'表示异常)。

def extract_feature(path):
    # 加载PET图像数据 使用nibabel库中的load函数加载医学图像数据,其中path是图像文件的路径。
    img = nib.load(path)
    # 获取第一个通道的数据 因为医学图像数据通常是4D数据。从加载的图像数据中获取第一个通道的数据,即取出图像数据的第四维
    img = img.dataobj[:, :, :, 0]
 
    # 随机筛选其中的10个通道提取特征  从第二维和第三维中随机选择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']

综上,这段代码的主要作用是提取医学图像数据中的特征,并将特征值和类别一起返回,其中特征包括非零像素数量、零像素数量、平均值、标准差、在列方向上平均值不为零的数量、在行方向上平均值不为零的数量、列方向上的最大平均值和行方向上的最大平均值。
3、对训练集和测试集进行30次特征提取,每次提取后的特征以及类别被添加到train_feat和test_feat列表中。

train_feat = []
for _ in range(30):
    for path in train_path:
        train_feat.append(extract_feature(path))

test_feat = []
for _ in range(30):
    for path in test_path:
        test_feat.append(extract_feature(path))

 4、使用逻辑回归模型对训练集的特征进行训练,并对测试集进行预测。其中,训练集的特征作为输入,训练集的类别作为输出。

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]  # 类别
)

test_pred = m.predict(np.array(test_feat)[:, :-1].astype(np.float32))

 5、对每个测试样本的30次预测结果进行投票,并将得票最多的类别作为该样本的最终预测类别。

test_pred = test_pred.reshape(30, -1).T
test_pred_label = [Counter(x).most_common(1)[0][0] for x in test_pred]

 6、生成提交结果的DataFrame,其中包括样本ID和预测类别,并按照ID对结果排序并保存为CSV文件。

        此处容易出现报错,test_path找不到id,其原因就是前面对test_path中的路径提取,得到的x的形式为./脑PET图像分析和疾病预测挑战赛公开数据/Test\\71.nii,对其按照’/‘划分后取最后一个元素,其实取不到想要的71.nii后缀。所以需要前面循环之前对test_path中的符号修改。

test_path = [x.replace("\\", "/") for x in test_path]

submit = pd.DataFrame(
    {
        'uuid': [int(x.split('/')[-1][:-4]) for x in test_path],  # 提取测试集文件名中的ID
        'label': test_pred_label  # 预测的类别
    }
)
submit = submit.sort_values(by='uuid')
submit.to_csv('submit1.csv', index=None)

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值