机器学习的日益普及导致了一些工具的开发,旨在使这种方法的应用易于机器学习新手。这些努力已经产生了PRoNTo和NeuroMiner这样的工具,这并不需要任何编程技能。然而,尽管这些工具可能非常有用,但它们的简单性是以透明度和灵活性为代价的。学习如何编程一个机器学习管道(即使是一个简单的)是一个很好的方式来洞察这种分析方法的优势,以及沿着机器学习管道可能发生的扭曲。此外,它还允许更大的灵活性,如使用任何机器学习算法或感兴趣的数据模式。尽管学习如何为机器学习管道编程有明显的好处,但许多研究人员发现这样做很有挑战性,而且不知道如何着手。
在本文中,我们提供了一个循序渐进的教程,介绍如何使用scikit-learn实现一个标准的有监督机器学习管道,scikit-learn是Python编程语言中一种广泛流行且易于使用的机器学习库。在流程的每个步骤中,我们都提供了简短的基本原理和对代码的解释,当相关的时候,我们会向读者提供有用的外部资源,这些资源提供了进一步的示例或更深入的讨论。示例代码遵循第2章中描述的工作流程。鼓励读者参考本章,以获得机器学习管道主要元素的更深入的理论解释。
本教程的目标是机器学习初学者。由于这个原因,它需要最少的编程知识。但是,鼓励读者熟悉基本的Python。Python是一种广泛使用的编程语言,有很多可用的资源。中级用户也会发现本教程很有用。示例代码的结构方式很容易用其他技术删除、添加或替换某些技术。这样,读者可以尝试不同的方法,并在代码的基础上开发更复杂的管道。该实现遵循严格的方法,以避免双重倾斜等常见错误,并获得可靠的结果。本文发表在本文发表在Machine Learning Methods and Applications to Brain Disorders。
曾做过多期机器学习/深度学习在脑影像中的应用文章,请结合阅读,加深理解,(:
重度抑郁症患者的脑龄
AJP:有和没有内化性精神障碍的受虐女孩情绪回路延迟成熟的差异性
SVM在脑影像数据中的应用
基于深度学习和自闭症脑成像数据库(ABIDE)识别自闭症谱系障碍
Radiology:皮层厚度预测轻度认知障碍转化为帕金森痴呆症
阿尔茨海默病及其先兆分期的神经影像分类研究及相关特征提取
Nature子刊:基于深度学习预测家族性阿尔兹海默症患者临床前功能性脑老化
神经影像研究驱动的脑龄估计作为脑疾病和健康状况识别的生物学标记
机器学习在重度抑郁症患者中的应用:从分类到治疗结果预测
基于原始影像数据的深度学习模型预测脑龄可获得可靠的遗传生物标志物
基于功能磁共振成像数据的机器学习对精神分裂症进行分类
使用多元表征方法提升对大脑-行为之间关系的机器学习研究的泛化
用于临床心理学和精神病学的机器学习方法
PLOS Biology:重度抑郁症多成像中心的泛化脑网络标志物
Nature Medicine:持续的实验性和临床性疼痛的神经影像生物
深度学习在婴儿大脑的磁共振图像分析中的作用(上)
参数选择对脑卒中后失语症预测模型的影响
大脑数据分类时意外过拟合的危险
机器学习在静息态功能磁共振成像中的应用
有监督机器学习在系统神经科学中的作用
AJP:精神分裂症患者大脑加速老化的纵向识别研究
Nature Protocols:为解释神经成像中的机器学习模型
Biological Psychiatry: 基于多模态脑影像的个体指标预测-方法
BRAIN:基于全球14468名被试MRI数据特征预测脑龄和疾病
Biological Psychiatry:自闭症的神经亚型研究进展
PNAS:灰质年龄预测作为痴呆风险的生物标志物
BRAIN:用于阿尔茨海默病分类的可解释深度学习框架的开发
异质性问题:识别精神疾病亚型的方法
NPP:结构MRI数据的生理性别分类显示跨性别者女性的错误分
利用功能连接对脑疾病进行分类和预测
基于脑影像的精神疾病预测
基于影像学和定量感觉测试预测慢性疼痛的治疗结果
BRAIN:利用机器学习揭示了两种精神分裂症的神经解剖学亚型
识别最优的数据驱动特征选择方法以提高分类任务的可重复性
Neuron脑影像机器学习:表征、模式信息与大脑特征
Molecular Psychiatry:静息态fMRI预测青少年认知能力
JAMA Psychiatry:脑影像机器学习预测精神疾病患者社会功能
AJP:基于脑网络的可卡因戒断预测
基于机器学习的情绪障碍诊断:功能网络预测药物反应
脑影像特征预测散发性阿尔茨海默病症状发作时间
影像组学:
影像组学初学者指南
放射学中基于影像组学和人工智能预测癌症预后
脑肿瘤的影像组学:图像评估、定量特征描述和机器学习方法
基于MRI医学图像的脑肿瘤分级
Radiology:图像生物标志物标准化:基于高通量图像表型的标准化定量影像组学
IEEE Signal Processing Magazine:从手工放射组学特征到深
使用多模态脑部扫描数据的自动脑肿瘤分割
Radiology:脑部MRI影像组学:转移瘤类型预测的应用
神经放射学诊断中的MRI数据分析
AJNR:深度学习在神经放射学的应用
Neuro-Oncology:对脑胶质瘤IDH突变状态进行分类的一种新型的
Neuro-Oncology:深度学习算法全自动评估脑胶质瘤负荷
Lancet Oncology:利用人工神经网络对神经肿瘤学MRI成像进行
Radiology:人工智能系统脑MRI鉴别诊断精度接近神经放射科
深度学习在医学图像分析中的应用
我们首先简要介绍如何安装Python和所有必要的库,以及如何访问该代码的数据集和在线版本。
19.2 安装python和主要库
在本教程中,源代码是使用Python 3编写的。和大多数编程语言一样,Python是在库中组织的。每个库都包含一组用于特定目的的专用函数。在本教程中,我们使用以下库:
Pandas和numpy是被广泛使用的用于加载、操作和汇总数据的库。虽然pandas用于处理表格数据(例如,数据排列在表格中,有行和列),numpy是一个更通用的库。我们还使用科学计算的基础库scipy运行一些单变量统计数据,以探索数据并为统计分析做准备。Matplotlib和seaborn是用于数据可视化的库。这在研究数据或总结结果时非常有用。最后,scikit-learn,或者更通俗的说法是sklearn,可以说是最流行和最容易访问的机器学习Python库。它是一个高级库,这意味着许多复杂的应用程序被封装在更简单、更短和易于使用的函数中。
要运行本教程中的示例代码,读者需要安装Python 3以及上述所有库。最简单的方法是下载并安装Anaconda。这是用于科学计算的Python编程语言的免费和开源发行版,旨在简化包的管理和部署。
19.3 如何读本章
在本章中,读者会发现不同的文本风格区分不同种类的信息。代码块(称为代码片段)将出现在下面的框中。代码片段有编号,以便更容易地引用分析的不同阶段。每个代码段的输出都显示在代码下面。
在某些情况下,一行代码可能太长,必须分成两行。这将用表示(注意这不是在代码的在线版本中)。示例代码的在线版本是用笔记本格式编写的。>>>符号表示命令的输出将在笔记本中显示。对于某些代码段,输出可能太长,在这种情况下,只显示输出的一部分。这将被标记为“... .”。文本中对主要库或特定库中特定工具的引用以courier新字体显示。
19.4 使用大脑形态测量学对精神分裂症患者和健康对照组进行分类
本教程中使用的例子涉及到使用神经解剖学数据对精神分裂症患者(SZ)和健康对照组(HC)进行分类。模拟FreeSurfer输出的数据集包含了大脑101个区域的灰质体积和厚度,以及每个参与者的ID、年龄、性别和诊断结果。图19.1展示了本教程最后一个流程的概要。为了本练习的目的,我们假设特征提取,即从原始结构磁共振成像(MRI)图像中提取体积和厚度值的过程已经完成。因此,我们从为机器学习分析准备数据开始我们的教程。在这个步骤中,我们将探索缺失数据、混杂变量和类别不平衡的数据,并讨论如何解决这些问题。接下来,我们定义了具有10次迭代(外部CV)的交叉验证(CV)方案。在每次迭代中,训练集和测试集分别进行数据转换,以避免知识泄漏。然后将支持向量机(SVM)模型用于训练集。SVM依赖于超参数C。为了决定使用C的哪个值,我们创建了一个包含10折的内部CV。这意味着,对于我们想要测试的每一个C值,一个SVM模型都要训练和测试10次;对于给定的C值,最后的性能是通过平均10个性能来估计的。然后使用最优的C参数在整个训练集上训练SVM模型。该训练模型的性能在测试集中进行测量。整个过程重复10次(即外部CV的10次迭代)。一旦完成,我们的SVM模型的最终性能是通过平均10个外部折的性能指标来计算的。最后,我们调查哪些特征在驱动模型的预测中更重要,并测试我们的模型的最终性能的统计显著性。
图19.1 本教程中实现的机器学习流程概述。
19.5 示例代码
在我们的例子中使用的机器学习管道包括以下组件:问题制定、数据准备、特征工程、模型训练、模型评估和事后分析。在开始之前,我们首先需要导入所有必要的库,将随机种子设置为一个固定值,并组织我们的工作区。
19.5.1导入库
默认情况是不加载用于计算机器学习分析的库。因此,在开始编写代码文件时,最好先导入我们需要的所有库。除了pandas、numpy、scipy、seaborn、matplotlib和sklearn之外,我们还使用pathlib模块来组织文件夹,并使用warnings模块在分析过程中抑制任何无用的警告(两者都是Python自带的,因此我们不需要安装它们)。如果读者决定修改代码,我们建议通过抑制代码片段1中的最后一行来重新激活警告。理解这些警告可以帮助读者避免错误并调试代码。为了使代码更易于阅读,在导入多次使用的库时,通常会指定一个别名。例如,pandas库通常作为pd导入。这样,每当我们想要调用这个库时,只需输入pd即可。
19.5.2 设置随机种子
我们分析中的一些步骤将受到随机性的影响。例如,我们可能希望在数据清理期间随机删除一些参与者。同样,在定义CV方案时,每次迭代的训练/测试分区也是随机进行的。在Python中,这种随机性可以通过将种子值设置为固定值来控制。没有定义一个特定的种子值意味着依赖于这个随机性元素的变量在每次我们运行代码时都会有不同的表现。例如,每次迭代的训练测试分区将是不同的,这可能会导致不同的模型性能。因此,我们将种子值设置为一个固定的数字,以保证每次运行代码时都得到相同的结果。有些函数需要将随机种子作为参数再次传递。
19.5.3 组织工作空间
在开始分析之前,我们应该首先创建文件夹结构,用于存储所有结果。在本教程中,读者可能希望沿着机器学习的管道测试不同的策略,例如,不同的预处理策略或机器学习算法。在大量测试之后,我们很容易就会忘记哪些结果与哪些策略有关。为每个实验指定一个名称,在结果目录中创建一个具有相同名称的文件夹,并将实验输出存储在该目录中,这是一种很好的做法。
19.5.4 问题公式化
在进行任何类型的项目时,有一个良好框架的问题是至关重要的,特别是在机器学习中,可能有许多可能的方法来分析相同的数据集。在本教程中,我们的机器学习问题如下:
使用结构MRI数据对SZ和HC患者进行分类。
从这个公式中,我们可以推导出机器学习问题的主要元素:
19.5.5 数据准备
这一步的目的是执行一系列的统计分析,为机器学习模型准备数据。在这里,根据机器学习问题的性质和数据类型,可能需要不同的统计分析。
19.5.5.1 导入数据
在本教程中,我们使用表格数据。数据以逗号分隔值(CSV)文件的形式存储。我们使用从pandas中的read_csv()函数来加载csv文件。这个函数将数据加载到一个名为dataframe的对象类型中,我们将其命名为dataset_df。
在我们的数据集中,诊断和性别是由单词定义的。有时,人们用不同的名字存储信息;例如,在列诊断中不使用sz,我们可以用“schizophrenia”这个词来定义这个问题属于一个病人。为了使这些代码更容易适应不同的格式,我们在代码的开头定义了我们的符号.
让我们从数据的前六行开始。使用pandas选择dataframe的子部分是很简单的。有不同的方法可以做到这一点。这里,我们只是简单地指出dataframe中需要的索引(注意,第一行索引为0,最后一行不包括在内)。
从输出中,我们可以看到顶部的列名和前六个参与者的数据。列包括诊断,性别,年龄,以及几个脑区的灰质体积和厚度。ID在代码片段4中设置为列索引。我们可以看到至少缺少一个值(第c006行)。我们稍后会处理这个问题。
知道数据集中可用的所有特征的名称也可能很有用。为此,只需知道数据列的名称。
接下来检查数据集的大小。
为了处理构建机器学习管道时一些最常见的问题,我们的数据准备阶段将检查以下数据集:
19.5.5.2 缺失数据
大多数机器学习模型不支持缺失值的数据。因此,检查dataset_df中是否有任何缺失值是很重要的。下面我们使用来自pandas的函数isnull()来确定每个特性总共有多少缺失数据,以及缺失数据的参与者的id。
我们可以看到有43个缺失的年龄值。没有这方面的资料,就无法对不平衡的人口数据进行彻底的评估,这在解释结果时可能会有问题。这里有许多不同复杂程度的选项(关于这些选项的更多信息请参见第14章)。因为删除这些参与者只会损失总数据的6%,所以我们将简单地删除他们。我们可以通过使用来自pandas的dropna()函数来做到这一点。
正如预期的那样,新的dataframe比以前少了43个参与者。
19.5.5.3 类别不平衡
接下来,让我们检查每个类别的总人数:
在我们的数据集中,共有367名对照组和330名患者。类别之间似乎没有很大的不平衡。然而,这两个类别并不完全匹配。正如我们在第2章中提到的,这可能会在估计模型性能时产生问题。一种选择是将HC降采样以匹配SZ组。然而,这意味着除了我们已经丢弃的6%之外,还会丢失更多的数据,这是不希望看到的。由于不平衡不是太大,我们将保留相同的数据,并使用平衡的准确性作为我们选择的性能指标,以及分层CV方案,以确保CV迭代中SZ/HC的比例相同。
19.5.5.4 混淆变量
人们可能想要检查许多潜在的混淆变量。在这里,我们将调查两个明显的问题:性别和年龄。
将性别作为可能的混淆因素进行调查的一种简单方法是验证患者和对照组中男性和女性的比例。让我们先用seaborn来可视化一下每一组的性别比例。使用这个库绘制数据非常简单(https://seaborn.pydata.org)。请注意,seaborn操作基于另一个名为matplotlib的库,这是Python中使用最广泛的绘图库。为了编辑图形中的一些元素(例如,将图形框中的M和F改为Male和Female),我们也将使用matplotlib。
我们可以看到这两组的男性数量相当相似。然而,对照组比患者组有更多的女性。除了使数据可视化之外,最好总是执行适当的统计检验,即使在目视检查中没有明显的偏差。由于性别是一个分类变量,我们将采用齐性的chisquare检验来检查这种差异是否具有统计学意义。在本例中,我们想检验零假设,即HC组中的女性比例与患者组中的女性比例没有差异(相当于检验HC组的男性比例与患者组的男性比例没有差异)。
以上结果表明,这两个类别在性别方面确实存在统计学上的显著差异(p<.05)。
这可能是一个问题,因为性别对大脑形态的影响是公认的。因此,机器学习算法可能使用与性别差异相关的大脑特征来区分HC和SZ,而不是与所研究的障碍相关的差异。
为了减轻这种潜在的偏差来源,我们将在HC类中迭代随机删除一名女性,直到两个类之间的男性女性比例不再有统计学上的显著差异。
从输出中,我们可以看到,在去除两个女性对照后,卡方检验不再具有统计学意义。
接下来,让我们检查一下与年龄有关的不平衡。该想法是为了检验零假设,即HC组的平均年龄(或中位数)与SZ组的平均年龄(或中位数)没有区别。一种方法是对两个样本使用参数t检验。重要的是,这个测试假设年龄在两组中都是正态分布(高斯分布)。为了检查这个假设,我们可以使用来自scipy库的stats模块的shapiro Wilk检验与seaborn来绘制每个组的分布。
从上面我们可以看出,年龄在两组中都是正态分布的。此外,两组间的分布、均值和标准差也相当相似。这意味着我们可以用t检验来检查各组之间年龄的统计学差异。
可以看出,两组的年龄差异无统计学意义。因此,在我们的分析中,我们不会将年龄视为一个重要的混杂因素。
19.5.5.5特征集合和目标
我们的下一步是从dataset中检索目标和特征。对于目标变量,我们将dataset_df中的列诊断分配给变量targets_df。对于这些特征,我们选择从第四列开始的所有行(回想一下,dataframes的索引是0),并将它们保存在features_df中。
清理后的数据集包含695个被试和169个特征。这一数量的被试远高于为获得稳定结果而推荐的130名被试的样本量。然而,在许多关于大脑障碍的研究中,我们的样本量可能会较小。在这些情况下,一定要小心,小于最佳样本量可能导致不可靠的结果。
接下来,让我们将清理后的数据保存到创建的目录中的CSV文件中。
19.5.6 特征工程
在这一步中,我们想要对我们的数据进行一系列的转换,这将帮助我们建立一个良好的机器学习模型。如第2章所述,这一系列的转换可以根据数据的性质涉及不同的过程。下面我们将按照与第2章相同的顺序讨论每一个步骤。
19.5.6.1 特征提取
在我们的示例中,我们希望使用神经解剖数据对SZ和HC进行分类。这需要从原始MRI图像中提取大脑形态特征信息。正如前面提到的,在本教程中,我们假设这个特征提取已经为我们完成了。组成features_df变量的区域灰质体积和厚度已经被FreeSurfer提取出来。
19.5.6.2 交叉验证(CV)
在我们继续将任何转换应用到我们的特征之前,我们首先需要将数据分割成训练集和测试集。回想一下,这是确保机器学习分析的训练和测试步骤之间独立性的关键步骤。在本教程中,我们使用分层的10折CV。第2章概述了一些最常用的CV类型。
首先将targets_df变换为一维numpy数组,其中0表示HC, 1表示SZ;我们称之为新的变量,targets。通过将targets_df转换为2D numpy数组,我们对特征进行了同样的处理。将数据从dataframes转换为数组以后会更容易,因为有些函数要求数据采用这种格式。
接下来,我们定义了分层10折CV的参数。我们通过从sklearn库的StratifiedKFold类中创建一个对象来实现这一点。我们将这个对象称为skf。
注意skf中的参数random_state。这个参数允许我们控制内在的随机性元素,将全部数据分解为训练集和测试集。我们的数据集总共包含695个参与者。在上面的代码中,我们已经指示模型将数据集分成10组(同时在整个CV迭代中保持SZ/HC比率相似)。在这些情况下,Python会随机执行这个分组。不将随机状态设置为固定值意味着每次我们运行代码时,分配到每个组的参与者将不同。因此,我们的结果很可能也会不同。这是我们希望避免的事情,至少在我们构建模型以改进它的时候是这样,因为我们希望能够在不同模型之间进行比较时重现相同的结果。
接下来,我们准备了一组空对象,这些对象将被预测、性能指标和每一次CV迭代中的机器学习模型系数填充。在下面的代码中,我们创建:
(1)一个空的dataframe叫做predictions_df,它将存储模型的预测;
(2)每个性能指标的三个空数组:平衡精度(bac),敏感性(sens),特异性(spec);
(3)SVM的系数的空数组,其中每个特征的权重(系数或重要性)将被存储。最后,我们还创建了一个额外的文件夹model dir,稍后将保存上面的所有对象。
既然定义了CV,我们就可以遍历10个CV迭代中的每一个。在每次迭代中,我们对训练集执行任何转换(例如,特征选择,归一化),并使机器学习算法适合相同的数据;然后,在执行了在训练集中应用的相同的数据转换后,我们使用测试集来测试算法。这可以使用for循环来迭代10个i_folds来实现。在每一次i_folds中,我们将有四个新变量:
(1)features_train 和 targets_train :训练集和对应的标签;
(2)features_test 和 targets_test:测试集和对应的标签;
现在,让我们检查在CV的每次迭代中,训练集和测试集中有多少参与者。我们可以通过简单地设置targets_train和targets_test的长度来做到这一点。
注意for循环内部的代码是如何放置在更右的位置的。这称为缩进,意味着在CV的每次迭代中,将执行缩进代码块中的指令。接下来的代码段(22到31)将保持相同的缩进,表示它们仍然是这个for循环的一部分。一旦CV完成,缩进将被删除,也就是说,文本将再次从文本框的左端放置。请注意,如果运行这段代码,所有的循环片段将需要一起运行。还要注意,折的编号从0开始,而不是1;这是因为在Python中,for循环的索引是0。
19.5.6.3 特征选择
正如在第2章中所讨论的,特征选择可以帮助我们去除特征集中的冗余。然而,考虑到SZ的神经解剖异常往往是微妙和广泛的,我们有理由假设,我们的特征集中包含的169个特征中的大多数将对区分患者和对照组作出一些贡献。此外,我们注意到,在我们的示例中,特征的数量与总样本容量相比并不是太大。由于这些原因,我们将不删除特征。如果我们使用特征选择,会有大量的策略可以通过sklearn使用。
19.5.6.4 特征归一化
在将数据输入分类器之前,我们希望确保不同大脑区域的测量具有不同的测量范围这一情况不会影响我们模型的可靠性。如果一个特征的方差比其他特征的方差大几个数量级,那么这个特征可能会主导数据集中的其他特征。
有几种可能的解决方案可以避免这个问题。在这个例子中,我们将对数据进行转换,使每个特征的分布类似于标准正态分布(例如,均值0和方差1)。每个新归一化的值Zxi是通过取每个数据点xi,减去对应特征的均值X,然后除以相同特征的标准差(SD):
我们可以使用sklearn中的StandardScaler对象自动地将这个公式独立地应用到每个特征上。
首先,我们创建一个标量对象。然后,我们使用训练集拟合标量参数(均值和标准差)。换句话说,我们在对象标量中计算并存储训练集中每个特征的均值X和SD。然后,我们使用上面的公式将训练集和测试集与存储的参数进行转换。Sklearn还提供其他的扩展策略;例如,如果分布不是正态分布或有几个离群值,则函数RobustScaler()将更适合。
19.5.7 模型训练
19.5.7.1机器学习算法与超参数优化
在本教程中,我们使用由sklearn实现的SVM。如第6章所述,支持向量机允许使用不同的核。在这里,我们将使用线性核,因为这将使稍后更容易提取SVM模型的系数(特征重要性)。
重要的是,SVM依赖于一个超参数C,它调节了我们希望避免对每个训练示例进行错误分类的程度。选择C值的理想方法是让模型尝试几个值,然后选择性能最好的一个。这应该通过在已经定义的CV中添加一个额外的CV来完成,从而创建一个嵌套CV,其中不同的C值被用于训练集并在验证集中进行测试;然后用性能最好的C的值将模型拟合到外部的CV定义的训练集上(参见第2章)。
幸运的是,sklearn有一组有用的工具来实现这一点。在这里,我们将使用网格搜索,这是脑疾病文献中一个流行的选择。关于网格搜索和其他超参数优化方法的更多信息可以在https://scikit-learn.org/stable/modules/grid_search.html。
为了实现网格搜索,我们首先需要为C提供一个可能范围;这是我们的搜索空间。接下来,我们为GridSearchCV指定参数。我们将再次使用分层10-fold,就像前面定义的外部CV一样。读者可以参考图19.1以获得模型设计的可视化表示。
现在,我们准备将SVM模型与训练数据进行拟合。我们通过将fit命令应用于训练集中的特征和标签来实现这一点。
下面的代码显示了GridSearchCV是如何工作的:我们可以看到内部CV中验证集中不同C值的性能。
在验证集中产生最佳性能的C的值显示在顶部。这个值为C的SVM模型再次被用来在整个训练集中(由外部CV定义)训练一个SVM模型,并被存储在一个名为best_estimator_的对象中,我们将使用它来定义第二个分类器best clf。我们稍后将使用这个模型在测试集中进行预测。
19.5.7.2模型系数
除了模型性能之外,我们还对那些驱动模型预测的特征感兴趣。对于具有线性核的SVM,该信息被自动存储在coef_ inside best_clf 中。我们将把每个特征的系数存储在我们之前创建的系数coef_cv的空列表中(代码片段21)。
19.5.8 模型评估
最后,我们使用最终训练的模型best_clf对测试集进行预测。预测存储在target_test_predicted中。然后,这个变量被用来填充之前创建的空dataframe叫做predictions_df (在代码片段21中创建)。
一旦我们有了预测的标签,我们就可以估计测试集中的性能。首先,我们计算混淆矩阵。从这里,我们估算bac、sens和spec。在sklearn中有更多的指标可供选择。
在CV的10次迭代中,每一次都重复从代码片段22到31的步骤。这意味着在这个过程的最后,我们将有10个模型性能的估计,每个迭代一个。然后通过平均迭代中的性能指标来计算总体性能。
从上面的输出可以看出,我们的模型能够对SZ和HC患者进行分类,bac为74%。我们必须记住将主要结果保存在我们的专用目录中,包括系数、预测和性能指标。
这个嵌套的CV需要几分钟的时间。然而,其他的分析可能需要更长的时间,这取决于数据的大小和性质以及机器学习管道。
19.5.9 事后分析
一旦我们有了最终的模型,我们可以运行几个额外的分析。在这里,我们将运行以下内容:
1、通过置换检验测试平衡的准确性,敏感性和特异性的统计显著性;
2、确定对任务贡献最大的特性;
我们首先在这个目录中创建一个单独的文件夹,用于存储置换测试的结果。
接下来,我们存储模型的最终bac、sens和spec。这将在以后派上用场。
正如在第二章中所解释的,置换检验涉及到多次运行相同的模型,每次标签都是随机打乱的。因此,我们需要首先定义置换次数。通常,研究使用1000到10000。这可能需要一些时间来运行。为了存储每次置换的结果,我们首先创建四个空对象,我们将在每次置换之后填充它们。
接下来,我们设置了一个for循环,用于迭代每次置换。由于在for循环之后存在缩进,对于每次置换,这个for循环中的所有命令都将重复执行(代码片段37-48)。在每次迭代中,受试者的诊断将使用随机函数进行随机洗牌。这种方法将消除特征和目标之间的任何关联。因为我们希望这种洗牌在每次迭代时都不同,所以我们将numpy使用的随机种子设置为一个新的固定值。
然后,我们将完全相同的管道应用到具有打乱标签的相同数据集。请注意下面的代码是如何遵循与代码片段21到31相同的指令的。
通过下面的代码,我们估计了平均bac、sens、spec以及10个CV迭代中的模型系数,并将它们保存在目录中。
最后,我们计算bac、sens和spec的p值,方法是用置换后的数据集性能优于我们的模型性能的次数除以置换的次数。得到的p值将表明我们的模型的行为与随机分类器相似还是明显更好。
所有p值都表明,我们的模型能够对HC和SZ进行分类,并且分类性能高于机会水平(即随机分类器)。让我们也估计模型系数的统计显著性。这将允许我们检查哪些特征在统计上对任务做出了重要贡献。
接下来,我们创建一个dataframe来存储系数值和相应的p值。
在最后一步中,我们将总体性能指标和相应的p值以及系数保存在两个单独的CSV文件中。
19.5.10本教程的主要结果
我们实例的结果表明,我们能够以75%的平衡准确度,72%的灵敏度和77%的特异性对SZ和HC进行分类。推动模型预测的主要特征:包括第三脑室、双侧海马旁回、左侧颞中、内侧眶额、喙侧前扣带回的厚度,以及双侧杏仁核、左侧海马和颞中回的体积。
以下是文件和数据:
19.6结论
在本教程中,我们能够以75%的准确率在个体水平上区分SZ和HC。然而,更复杂的机器学习方法应该会带来更高的性能。有几种策略可以用来改进我们的模型。也许最明显和直接的策略之一是尝试不同的分类器。实际上,可以实现几个最常用的分类器,而不必对上面的代码做太多更改。另一种可能的策略是添加一个功能选择步骤来删除不太相关的功能。然而,管道中对性能影响最大的元素可能是用作输入的特征的类型。因此,进一步的策略是尝试其他类型的特征,例如体素级数据(而不是脑区级),它们可能会为分类任务传递更多有用的信息。我们也可以尝试在同一个模型中使用不同类型特征的组合,基于不同特征可能捕捉疾病的不同方面的概念。然而,这将引发其他问题,如需要考虑和解决的高维问题。在我们的模型中添加一个降维步骤,例如第12章所述的主成分分析,将有助于处理这个问题。总的来说,尝试不同的方法被认为是很好的实践。然而,重要的是要避免构建特定的管道,这种管道适合一个特定的数据集,但如果在另一个数据集上测试,则不太可能很好地执行。这对于大脑疾病尤其重要,因为大脑疾病的数据集通常很小,导致过拟合的风险很高。
鉴于人们对应用机器学习方法研究大脑疾病的兴趣日益增加,研究人员和临床医生对其潜力和局限性有更大的认识,这是很重要的。学习如何应用机器学习,或者至少理解它的实际实现,是洞察它的优点和缺点的好方法。例如,在本教程中,我们学习了机器学习分析的灵活性,在每个阶段都可以选择几个可能的选项。另一方面,我们也讨论了几个需要解决的问题,以最小化偏倚风险,如缺失数据、数据不平衡、混杂变量,以及适当使用嵌套CV进行超参数调整。我们希望本教程将鼓励机器学习新手迈出设计、构建和测试他们自己的机器学习模型的第一步。