内容导读

  1. 项目分析
  2. 预备知识
  3. 项目实战

一、项目分析

1、提出问题

随着人们生活水平的提升和健康意识的增强,民众定期进行身体健康体检已成为常态,这种早期的疾病检测和筛查可以及早发现身体里已经出现的异常体征信息,做出正确诊断和有效处理措施,将疾病消灭于萌芽时期,为健康提供超前保障,避免出现患病后的痛苦和尽早纠正不良的生活习惯等。

随着医疗AI在医疗领域的攻城掠地,如今已经开启了新纪元的智慧医疗科技,借助“人工智能大脑”,AI辅助诊疗新时代正在到来。利用AI探索生命科技,是当前人工智能医学的一大热点。基于大数据、云计算、机器学习和深度学习的人工智能,正在弥补人类的能力短板,成为医生的得力助手。

传统的医疗诊断只能通过医生的肉眼去看X光、CT、超声、MR等的影像,才能给出患者诊断结论,过程不仅繁琐且重复性高。而现在通过AI辅助诊断技术的应用,能够很大程度地提高医疗机构、医生的工作效率,降低工作强度,降低漏诊率。那么,AI是如何辅助医生进行病情诊断的呢?

下面,我们就以另一类分类器SVM为利器,看它是如何利用女性身上的活检数据,检测号称女性头号杀手的乳腺癌的。

2、解决方法

支持向量机SVM特别适合样本相对少、样本特征数较多的应用场合。

从患者体内切取、钳取或穿刺等取出病变组织,进行病理学检查的得到活检数据不像其他数据容易获取,数据本身成本也比较高,另外还可能涉及到患者的隐私等,如果我们能借助机器学习自动识别癌细胞是良性还是恶性的,那无疑对医生还是医疗系统而言都会有很大的裨益,至少能显著缩短诊断时间,为病人争取更多宝贵的治疗时间,为医生有更多的时间花在治疗疾病上。

利用SVM辅助诊断乳腺癌的解决方案如下图所示。

二、预备知识

用支持向量机SVM来“智慧”识别癌细胞,这个工作无疑是令人兴奋的。

为在后续的工作中合理设计SVM模型,先了解相关的知识。

1、SVM的最优分界面

假设有两分类数据如图所示。

现在就要找出一个最优分界面H,将两类数据分开。显然能将两类数据分开的分界面有无数种,如图所示就是其中的几种情形。

分界面H1、H4靠近样本族群的边界,称为临界分界面。那么哪个分界面是最优的呢?

我们希望所得的最优分界面不仅能准确地将两类数据分离开来,同时希望到两边临界分界面的距离达到最大,这样尽管训练样本中可能存在个别噪声样本和离群样本,但由于最优分界面远离族群,仍能在一定范围内正确分类这些噪声或离群样本,具有较强的抗噪声能力和较小的泛化误差。

临界面上的样本如样本1、7、10被称为支持向量,H0则是最优分界面,因为它到两边临界分界面的距离最大,显然H0是由支持向量决定的,这也是SVM名称的由来。

2、SVM模型参数

在很多情况下,样本变量之间的关系是非线性的,在低维输入空间没法将两类样本通过分界面将它们分开,如图所示左半部分。

支持向量机为了更好地将左半部分两类样本分离开来,使用一种称为核技巧的处理方式将上述问题映射到一个更高维的空间,即通过核函数K(x,y),将输入空间样本变换到高维输出空间,这样原本不能线性可分的问题就突然变得线性可分了,如下图右半部分。

这就有点类似于我们换了一个新的视角看数据,看到了不一样的情形。

核函数有多种形式,通常情况下,需要在模型上一点点地去试错并评估应用效果,在很多场合,核函数的选择可以是任意的,尽管不同的核函数所表现的性能可能只有轻微的变化,但最常用是rbf核函数,它被证明对于许多类型的数据都具有较好的拟合度。

下表就列出SVM模型的常用参数,以便大家在实际应用中合理来选择。

3、样本数据解读

本案例所用的样本数据来自网站UCI Machine Learning Repository,由威斯康星大学研究者公开捐赠的。

该数据集本质上是乳房肿块活检图像的细胞核多项测量值。通过以下代码读取数据集并了解样本的基本特征。

datas=pd.read_csv(r'data\wisc_bc_data.csv',sep=',')

读取的样本数如下图所示:

共有样本569个,即569例乳腺细胞活检案例。每行数据32列,其中id列是编号,无实际意义,在后续数据处理中会被删除或屏蔽。

诊断列diagnosis取值[M|B],分别表示诊断为恶性或良性。

其它30个列是细胞核的10个不同特征的均值mean、标准差se、最差值worst构成。

通过命令datas.columns查看所有的列名,可知10个特征有:

上述10个特征值是用来描述乳腺细胞核的大小和形状,有经验的医生是可以通过这些特征数据或阅读细胞核影像数字来诊断一个病人是否患有乳腺癌,可SVM是如何通过机器学习来一步步揭示这个模式的呢?下面我们来进行实战演练。

三、项目实战

1、准备训练集

为了能让SVM算法用于乳腺癌预测,就要准备所用到的学习数据,为此,我们首先要加载数据,然后对其做适当的处理,最后形成模型所需的训练集和测试集。

相关的代码如下。

import numpy as np
import pandas as pd
import sklearn.model_selection as ms
	datas=pd.read_csv(r'data\wisc_bc_data.csv',sep=',')
	x=datas.iloc[:,2:32]
	y=datas.iloc[:,1:2]
	x_train,x_test,y_train,y_test=ms.train_test_split(x,y,test_size=0.2, random_state=42)
	y_train=y_train.values.ravel()
	y_test=y_test.values.ravel()

行3导入model_selection用于样本数据分割,行4读取csv数据文件到数据框架datas中,行5是将datas中所有行第3列到第32列的数据作为样本输入集x,行6是将datas中第1列到第2列的所有行数据作为样本输出集y,行7是将输入集x和输出集y进行分割,按比例8:2分别形成训练样本和测试样本。

行8-9分别对训练样本和测试样本的输出值降维,将其变为一维数组,以满足模型训练和测试的数据格式要求。

以测试样本为例,准备好的数据如下图所示。

从上图可以浏览整个训练样本特征值的分布情况和标签值,用这些训练样本来估计模型训练后的效果,也就是用这114条记录模拟新的病人,去了解模型诊断结果的好坏。

2、构建和训练模型

有了训练集和标签后,就可以构建一个SVM模型并对它进行训练,代码如下。

import sklearn.svm as svm
#导入支持向量机模块svm
modle=svm.SVC(C=1, kernel='rbf')
#利用高斯核函数rbf构建模型modle,惩罚参数C取值为1
modle.fit(x_train,y_train)
#利用训练样本对模型modle进行训练

模型训练完成后,为了解模型的训练效果,利用以下语句输出模型的训练得分(精确度)。

print(modle.score(x_train,y_train))

模型得分为:

看来模型的得分并不太理想。训练后的模型对于114条测试集而言性能又如何呢?请往下看!

3、评估模型预测效果

下面基于测试集(模拟114个新的病人)对模型的诊断效果进行测试,看它预测的结果与医生事先标注的结果是否一致,如不一致,差异在什么地方,从而判断该模型是否能较好地推广到未知样本(或辅助于临床应用)。

代码如下。

	import sklearn.metrics as sm
	#导入评估模块metrics
	y_pred=modle.predict(x_test)
	#利用模型modle对测试样本进行预测得到预测值y_pred
	print(sm.classification_report(y_test,y_pred))

将实际标签值y_test与预测值y_pred进行比对分析,将结果以报告形式输出,如图所示。

可以看到,在所有114个测试样本中,所有实际标注为良性(B)的病人都被成功识别出来,而实际标注为恶性(M)的病人只有86%被识别出来,剩余14%的恶性肿瘤为错分为良性,在这种情况下,这种错分可能会造成严重的代价,因为误诊的病人可能会为此丧失治疗的黄金时机,导致病情继续蔓延恶化。

因此,有必要对样本数据或模型进行调整,以便训练出性能更好的模型。

观察图中样本的输入特征值,各特征值大小及范围差异较大,例如细胞核半径radius_mean的取值在[6.981, 28.11]内,而光滑度smoothness_mean的取值在[0.05263,0.1634]之间,两者数据量级不一样,有必要进行标准化处理,以消除量纲影响。

代码如下。

from sklearn.preprocessing import MinMaxScaler
x=MinMaxScaler().fit_transform(x)

行1导入min-max标准化类MinMaxScaler,在行2中对所有样本的输入特征值进行归一化处理,然后用任务2中相同的模型进行训练,最后再次对训练后的模型进行测试评估,评估结果如图。

可以发现,仅仅使用一行代码对样本集x进行标准化后,模型对标签为M的样本召回率由原来的86%提高到95%,B和M两种样本的综合评价系数F1也分别提升2和4个百分点,模型性能有比较明显的提升。

在训练样本数据比较下的情况下,能取得97%的预测精度还是比较令人满意的。

4、模型优化

尽管用于诊断乳腺癌的SVM模型有着高达97%的预测精度,但这种性能水平用于癌症诊断还不是非常令人满意的,因为不论是错分为假阴性还是假阳性,后果可能会比较糟糕,应尽量避免产生错分情况。

在这里,有必要从以下几个方面不断尝试,试图找到更好的模型。

1、将样本输入特征集x进行Z-score转换

在之前模型训练中,通过对样本数据进行min-max归一化处理来提升了模型的性能,那么如果对样本数据进行标准化处理,是否还能提高模型效果呢?

利用以下代码对样本输入变量x进行Z-score转换。

from sklearn.preprocessing import StandardScaler
x=StandardScaler().fit_transform(x)

数据转换后,仍用相同参数模型进行训练和预测,测试结果如下:

可以看出,除了训练得分有一点提高外,模型的预测结果没有什么变化。

有点遗憾的是数据标准化后,并没有让模型在诊断方面表现更好。

2、改变模型参数C

前面谈到可以通过变更SVM模型的参数,来改变模型的性能。下面仅以改变惩罚因子C的值,看它是如何引起模型效果或拟合度变化的。

我们的目标是减少模型错分比率,尽可能多地提高模型召回率和精确度,为此,根据C参数的含义,应该增大C的值,加大对错分类的惩罚,以降低训练误差。代码如下。

modle=svm.SVC(C=1.5, kernel='rbf')

上述代码只是将原C=1更新为1.5,核函数和其它参数没有变。C参数变化前后模型的预测结果对比如图所示。

上图左测是C=1的预测交叉表,右侧是C=1.5的预测交叉表,对比可以看出,当C取一个合适的较大值1.5的时候,所有标签为B的样本悉数找回,错分情况有较小的改善,是可以在一定程度上提高模型性能的,但有点遗憾的是,这种改善在标签为M的样本上并没有表现出来。

大家可以尝试用不同的C值或其它核函数对模型进行测试,看是否能找到更完美的分类效果。

更多精彩内容请持继关注本站!

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐