CV 第一次学习笔记
零基础入门CV,DataWahle视觉学习夏令营
本次内容为:基于logistic回归的脑PET图像分析和疾病预测
数据解析
- nii格式:基本为医学领域3D图像
- nii格式的3D图像
- 使用nibabel库进行切割取出每一层切片的数据
- 可视化工具:ITK-SNAP
- 数据分布
- 训练集50,NC/MCI各25个
- 测试集共100个(含脏数据)
代码流程图
报错解决(本地)
Traceback (most recent call last):
File "E:\Learn\Code\Python\DataWhale\CV\CV2\cv1.py", line 77, in <module>
'uuid': [int(x.split('/')[-1][:-4]) for x in test_path], # 提取测试集文件名中的ID
File "E:\Learn\Code\Python\DataWhale\CV\CV2\cv1.py", line 77, in <listcomp>
'uuid': [int(x.split('/')[-1][:-4]) for x in test_path], # 提取测试集文件名中的ID
ValueError: invalid literal for int() with base 10: 'Test\\63'
-
由于testpath[0]=‘…/脑PET图像分析和疾病预测挑战赛公开数据/Test\33.nii’
-
将77行代码 ‘uuid’: [int(x.split(‘\’)[-1][:-4]) for x in test_path], 修改为
‘uuid’: [int(x.split(‘\’)[1][:-4]) for x in test_path],
-
完整代码
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
# 对每个样本的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)