Datawhale•AI夏令营CV笔记1

前言

作为计算机视觉(CV)的初学者(小白)。对于本次的脑PET图像分类任务,我充满了热情和渴望学习。然而,在探索过程中,我也意识到了自己的一些错误理解和局限性。希望能够得到大家的反馈和建议。

赛题简介

任务:脑PET图像分析和疾病预测

数据:脑PET图像检测数据库(三维影像),格式为nii

直接目的:分类问题,将被试者按医学诊断分为两类NC(健康)和MCI(轻度认知障碍)

模型建立

数据处理

数据读取:数据格式较为特殊,需要使用合适的数据读取工具

数据转换:将脑PET三维图像数据转换为利于机器学习模型的数据,如层切片数据、高维绘图

数据增强:图像去噪、图像增强、图像标准化等

将数据划分为训练集、验证集和测试集。

特征提取

从原始数据中提取出对任务有用、有区分性的特征,将数据转化为更有意义的表示,以便更好地进行分类和预测。

使用预训练的卷积神经网络(CNN)模型,如VGG、ResNet等,提取PET图像的高级特征。

  • 输入:脑PET图像数据(经过预处理后的数据)。
  • 处理:通过前面的CNN层堆叠,学习到脑PET图像的高级抽象特征。
  • 输出:得到高级特征。

构建分类模型

将预处理后的脑PET图像输入到CNN中进行模型训练。

  • 输入:从特征提取阶段得到的高级特征表示。
  • 处理:通过全连接层等结构,将高级特征映射到不同类别的输出概率。
  • 输出:每个类别的概率分数,用于进行最终的脑PET图像分类和疾病预测。

在这里可以根据数据集的规模和复杂性考虑其他合适的分类算法,例如Vision Transformer(ViT,一种使用自注意力机制来处理图像数据的新型视觉)、EfficientNet(高效的CNN模型,参数较少时也适用)......

模型评估与优化

使用预留的测试集对训练好的模型进行评估。评估指标可以包括准确率、精确率、召回率和F1值等。如果模型性能不理想,可以尝试调整CNN的架构、增加训练数据、调整超参数等方法进行优化,进一步提高模型性能。

脑PET图像分类和疾病预测

使用训练好的模型对新的脑PET图像进行分类和疾病预测。输入脑PET图像到CNN中,通过模型的预测输出来确定图像所属的类别,健康或轻度认知障碍。

任务

跑通实践基线Baseline

代码如下:

#1. 导入库
import glob                # 获取文件路径
import numpy as np         # 数值计算
import pandas as pd        # 数据处理
import nibabel as nib      # 加载和处理医学图像数据
from nibabel.viewers import OrthoSlicer3D    # 图像可视化
from collections import Counter              # 计数统计

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

# 打乱训练集和测试集的顺序,保证随机性
np.random.shuffle(train_path)
np.random.shuffle(test_path)

# 3.对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']



# 4.对训练集进行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]                       # 类别
)

# 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('submit1.csv', index=None)

我提交结果后的评分为0.5,意味着还有很大的改进空间,由于不会其他的方法、模型等,只能从理论角度进行改进。

Baseline代码精读,以及模型改进

上面的代码中,

1.特征提取方法是随机选择10个通道,提取了一些基本的统计特征。这可能无法捕捉到脑PET图像中更复杂的信息和特征。脑PET图像是高维复杂的数据,仅提取少量简单的特征可能无法很好地区分不同类别。

考虑使用更复杂的特征提取方法,如卷积神经网络(CNN),来自动学习更高级别的图像特征。这样可以更好地捕捉图像中的复杂模式和关联,提高分类性能。

2.特征提取次数

次数增加可以通过数据增强和投票机制来提高模型的性能和稳定性,但也会增加计算复杂度和引入一定的随机性。在选择特征提取次数时,需要综合考虑数据量、模型表现,并进行适当的调优和平衡。

3.使用了简单的逻辑回归分类器,对于复杂的图像分类任务可能不够强大。

对于高维复杂的图像特征,更复杂的分类器,如支持向量机、深度神经网络等,可能更适合。

在此处的分类问题中,还需要考虑数据集是否平衡。可从准确率、精确率、召回率、F1值等,以更全面地评估模型性能。

提交任务一打卡

你可能感兴趣的:(笔记)