DataWhale CV方向 任务一的学习笔记

126 阅读11分钟

DataWhale CV方向 任务一的学习笔记

一、赛事背景 脑PET全称为脑部正电子发射计算机断层显像(brain positron emission tomography PET),是反映脑部病变的基因、分子、代谢及功能状态的显像。它是利用正电子核素标记葡萄糖等人体代谢物作为显像剂,通过病灶对显像剂的摄取来反映其代谢变化,从而为临床提供疾病的生物代谢信息,为脑癫痫病、脑肿瘤、帕金森病、阿尔茨海默综合征等提供了有效的检测手段。可利用脑PET图像检测出轻度认知障碍病灶,并提前介入治疗,从而延缓发病,对后续患者康复治疗有着积极的意义。因此本赛题以轻度认知障碍为例对脑PET图像进行分析与疾病预测。

二、赛事任务 为研究基于脑PET图像的疾病预测,本次大赛提供了海量脑PET数据集作为脑PET图像检测数据库的训练样本,参赛者需根据提供的样本构建模型,对轻度认知障碍进行分析和预测。

脑PET图像检测数据库,记录了老年人受试志愿者的脑PET影像资料,其中包括确诊为轻度认知障碍(MCI)患者的脑部影像数据和健康人(NC)的脑部影像数据。

被试者按医学诊断分为两类:

NC:健康

MCI:轻度认知障碍

赛事链接在:这里

目标:跑出逻辑回归baseline

1. 认识导入的库

下面先来安装nibabel库

!pip install nibabel

1.1 nibabel库介绍

​ "Nibabel"(NeuroImaging in Python - NIfTI and ANALYZE image library)是一个用于处理神经影像数据的Python库。它提供了读取、写入和操作NIfTI(Neuroimaging Informatics Technology Initiative)格式和ANALYZE格式的功能,这些格式通常用于存储和处理神经影像数据,如MRI(磁共振成像)和CT(计算机断层扫描)图像。

具体来说,"Nibabel" 提供了以下主要功能:

  • 读取和写入图像数据: 它可以轻松读取和写入NIfTI和ANALYZE格式的图像文件,使您能够从文件中获取图像数据或将数据写入图像文件。
  • 数据访问和操作: "Nibabel" 允许您访问和操作图像数据的各个方面,包括图像的像素值、尺寸、方向和其他元数据。
  • 坐标空间转换: 处理神经影像数据时,可能需要将图像数据从一个坐标空间转换到另一个。"Nibabel" 提供了用于坐标空间转换的工具。
  • 图像预处理: 您可以使用 "Nibabel" 对神经影像数据进行预处理,例如重新采样、平滑、剪裁等。
  • 与其他Python库集成: "Nibabel" 与其他科学计算和图像处理库(如NumPy、SciPy等)兼容,可以方便地将神经影像数据与其他分析工具集成在一起。

​ 这个包在神经科学研究和医学图像分析中非常有用,它使得处理神经影像数据变得更加容易和灵活。无论您是在进行学术研究还是医学图像分析,"Nibabel" 都是一个强大的工具。

1.2 具体安装问题 以及解决

由于使用的是线上环境,所以在pip前面要加上! ,如果是在本地的命令行输入,请把!去掉

由于一些网络原因或者是线上平台的问题,默认的源不可用,需要更改一成腾讯的源,更改后的代码如下

!pip install nibabel -i http://mirrors.cloud.tencent.com/pypi/simple --trusted-host mirrors.cloud.tencent.com

这样就可以正常安装啦

1.3 其它库的引入与介绍

import glob                # 这个模块用于查找符合特定规则的文件路径名。在这里可能用于获取文件路径列表
import numpy as np         # NumPy是一个用于科学计算的Python库,这里将其命名为np方便使用
import pandas as pd		   # pandas是一个用于数据分析和处理的库,将其命名为pd

import nibabel as nib      # 引入nibabel
from nibabel.viewers import OrthoSlicer3D    # 图像可视化 于进行医学图像的三维切片可视化。
from collections import Counter              # 用于计数统计可迭代对象中各元素的出现次数。

其中,numpy和pandas是nibabel的依赖库,一般安装nibabel会装上这俩库,如果报错的话可以也与nibabel一样安装一下就好

2. 解压数据集

# 解压数据集
!unzip /home/aistudio/data/data229672/脑PET图像分析和疾病预测挑战赛数据集.zip -d ./ 
# 重命名
!mv ─╘PET═╝╧ё╖╓╬Ў║═╝▓▓б╘д▓т╠Ї╒╜╚№╣л┐к╩¤╛▌ 脑PET图像分析和疾病预测挑战赛数据集

这里是把比赛直接给的数据集解压出来,但是由于编码的问题直接解压出来文件名是乱码,所以要进行重命名

通过群友的帮助,这里可以使用CP936编码解压,就不用重命名,代码如下

!unzip -O CP936 /home/aistudio/data/data229672/脑PET图像分析和疾病预测挑战赛数据集.zip -d ./

注意,这是线上环境的代码,本地运行的话要改一下文件路径,并且把开头的!去掉,再在shell里运行,或者自己直接手动解压其实应该就行(自己写搞什么花里胡哨的)

3.数据预处理

3.1 导入数据集

由于上面导入库已经介绍过了,下面就把测试集和训练集都导入进来,然后打乱顺序

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

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

函数对训练集和测试集的文件路径进行随机打乱,以改变它们的顺序。这种随机打乱可以有助于更好地训练和评估模型,避免模型学习到数据的特定顺序。

3.2 读取特征值

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']

这里是定义了个函数,用于读取指定路径的图像并计算出该特征值。我们先读取出其第一个通道的所有数据,然后随机(随机的原因是为了在数据处理中引入一些随机性,有助于模型更好地泛化和学习数据的多样性)取了其中的10个切片(这里10个也不是定死的,也可以自己调整来达到更好的效果),然后计算它们的各个特征值,目前是选择了这8个属性,后续可以再添加。最后就是给这张照片加上它是NC还是MCI这条属性,由于文件夹分好类了,所以根据路径就可以判断了。

4.模型训练

4.1逻辑回归模型介绍

本次采用的是逻辑回归模型,因为是第一次进行练习,逻辑回归对于我们小白来说有很多好处,先进行一下简单的介绍

逻辑回归是一种用于解决分类问题的统计学习方法。虽然名字中包含"回归"一词,但实际上它是一种分类算法,用于预测二分类问题中的类别标签。逻辑回归通过一个称为逻辑函数(或Sigmoid函数)的曲线来建模,并将线性回归模型的输出映射到0到1之间的概率值。

逻辑回归的基本思想是将输入特征与权重相乘并加上偏置项,得到一个线性组合,然后通过逻辑函数将线性组合转换为概率值。如果概率值大于一个阈值(通常是0.5),则预测为正类,否则预测为负类。

逻辑回归模型可以使用最大似然估计等方法进行训练,调整权重和偏置项,使得模型的预测尽可能接近实际标签。逻辑回归可用于二分类问题,也可通过技术扩展到多分类问题,如一对多法(One-vs-Rest)。

尽管逻辑回归在处理复杂数据时可能不如其他算法(如神经网络)效果好,但在许多实际应用中,它仍然是一种常用且有效的分类算法,尤其在解释性和计算效率方面具有优势。

  • 简单而高效: 逻辑回归是一种简单且易于理解的模型,不需要太多的调参和复杂的设置。它在许多情况下能够提供良好的性能,尤其是在数据线性可分或近似线性可分的情况下。
  • 可解释性强: 逻辑回归模型的结果很容易解释和理解。它输出的是概率值,可以直观地表示某个样本属于某个类别的可能性。
  • 低计算成本: 逻辑回归的计算成本相对较低,适用于大规模数据集。它的训练速度通常较快。

特别是方便我们理解,跑通后可以提高自己的信心,也可以鼓励我们进行后续的改进

4.2 代码实现

# 对训练集进行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次特征值,然后利用逻辑回归模型,使用训练集的特征作为输入,类别作为输出,进行了30次训练。这样,逻辑回归模型就将学习如何根据特征来区分正常和异常样本啦。

训练后的模型可以用于对测试数据进行分类,帮助预测样本是否为正常或异常。

5.预测与结果提交

# 对测试集进行预测并进行转置操作,使得每个样本有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)

在训练完模型后,运行这段代码就可以使用模型对测试集数据进行预测了,每个样本预测30次,并将预测结果转置以得到每个样本的多次预测。对每个样本的多次预测的结果进行投票,选出现最多次数的类别作为最终预测结果就基本完成啦,最后把样本ID和预测类别组成一个DataFrame,按照ID排序后保存为CSV文件就好啦。

最后只要提交到网站下来就会有自己的第一份成绩啦

虽然可能不是很理想,但是后续继续改进的信息已经有了,希望之后可以有更高分!

总结

这次通过老师们的讲解,和群友的帮助下,总算跑通了baseline,虽然模型可能有些简陋,但是真的学到了很多,我相信只要继续努力,一定会在后续的改进下,拿到一个好成绩! 希望之后会有更好的结果!!