SVM(下):如何进行乳腺癌检测?

SVM(下):如何进行乳腺癌检测?

如何在sklearn中使用SVM

在Python的sklearn工具包中有SVM算法,首先引用工具包

from sklearn import svm

SVM可以做回归可以做分类器,当用SVM做回归的时候,使用SVR,当做分类器的时候,用的是SVC,SVC是个线性分类器,用于处理线性可分的数据,只能使用线性核函数,SVM就是通过核函数将样本从原始空间映射到一个更高维的特质空间中,使得样本在新的空间中线性可分。针对非线性的数据需要用到SVC,在SVC中既可以使用到线性核函数(进行线性划分),也能使用高维的核函数(进行非线性划分)。

如何创建一个SVM分类器?首先使用SVC的构造函数:model=svm.SVC(kernel='rbf',C=1.0,gamma='auto')三个重要参数kernel、C、gamma,kernel代表核函数的选择,默认rbf即高斯核函数

  • linear:线性核函数
  • poly:多项式核函数
  • rbf:高斯核函数
  • sigmoid:sigmoid核函数
  1. 线性核函数,是在数据线性可分的情况下使用的,运算速度快、效果好,但是它不能处理线性不可分的数据

  2. 多项式核函数可以将数据从低维空间映射到高维空间,但是参数多,计算量大

  3. 高斯核函数同样可以将样本映射到高维空间,相比于多项式核函数来说所需要的参数比较少,性能好,默认使用高斯核函数

  4. sigmoid核函数经常用于神经网络映射中,SVM实现的是多层神经网络

    除了第一种线性核函数外,其余都可以处理线性不可分数据

C代表目标函数的惩罚系数,惩罚系数指的是分错样本时的惩罚系数,默认为1,当C越大的时候分类器的准确性越高,但同样容错率越低,泛化能力变差,C越小,泛化能力越强,准确性降低

gamma代表核函数的系数,默认为样本特征数的倒数,即gamma=1/n_features

创建SVM分类器之后,输入训练集对它进行训练,使用model.fit(train_X,train_y),传入训练集中的特征值矩阵train_X和分类标识train_y,特征值矩阵就是我们在特征选择后抽取的特征值矩阵(可以用全部数据作为特征值矩阵);分类标识就是人工事先针对每个样本标识的分类结果,这样模型自动进行分类器的训练,使用prediction=model.predict(test_X)来对结果进行预测,传入测试集中的样本特征矩阵test_X,得到测数据的预测分类结果prediction,同样可以创建线性SVM分类器使用model=svm.LinearSVC(),在linearSVC中没有kernel这个参数,限制我们只能使用线性核函数,因为linearSVC对线性分类做了优化,对于数据量大的线性可分问题使用linearSVC的效率要高于SVC

如果你不知道数据集是否为线性,直接使用SVC类创建SVM分类器,在预测和训练中,linearSVC和SVC一样,使用model.fit(train_X,train_y)和model.predict(test_X)

如何用SVM进行乳腺癌检测

来自美国威斯康星洲的乳腺癌诊断数据集< https://github.com/cystanford/breast_cancer_data/ >

采集了患者乳腺肿块经过细针穿刺(FNA)后的数字化图像,并对这些数字图像进行了特征提取,这些特征描述图像中的细胞核呈现,肿瘤分为良性和恶性

表包括了32个字段:

img

mean代表平均值,se代表标准差,worst代表最大值(3个最大值的平均值),每张图像都计算了相应的特征,得出了这30个特征值,实际上是10个特征值(redius、texture、perimeter、area、smoothness、compactness、concavity、concave、points、symmetry和fractal_dimension_mean)的3个维度,平均、标准差和最大值,这些特征值都保留了4位数字,在569个患者中,357个是良性、212个是恶性的。

目标是生成一个乳腺癌诊断的SVM分类器并计算这个分类器的准确率,执行流程是:

  1. 需要加载数据源

  2. 在准备阶段,需要对加载的数据源进行探索,查看样本特征和特征值,这个过程使用数据可视化,按照“完全合一”的准备来评估数据的质量,如果数据质量不高需要做数据清洗,清洗之后,可以做特征选择,方便模型训练

  3. 分类阶段,选择核函数进行训练,如果不知道数据是否为线性,考虑使用SVC,就是高斯核函数的SVM分类器,然后对训练好的模型用测试集进行评估

    # 加载数据集,你需要把数据放到目录中
    data = pd.read_csv("./data.csv")
    # 数据探索
    # 因为数据集中列比较多,我们需要把dataframe中的列全部显示出来
    pd.set_option('display.max_columns', None)
    print(data.columns)
    print(data.head(5))
    print(data.describe())
    

32个字段里,ID是没有实际意义的,diagnosis字段的取值为B或者M,可以用0或1来代替,其余30个字段,可以分成三组字段,下划线后面的mean、se、worst代表了每组字段不同的度量方式,分别是平均值、标准差和最大值

# 将特征字段分成3组
features_mean= list(data.columns[2:12])
features_se= list(data.columns[12:22])
features_worst=list(data.columns[22:32])
# 数据清洗
# ID列没有用,删除该列
data.drop("id",axis=1,inplace=True)
# 将B良性替换为0,M恶性替换为1
data['diagnosis']=data['diagnosis'].map({'M':1,'B':0})

做特征字段的筛选,首先需要观察下features_mean各变量之间的关系,用dataframe的corr()函数,用热力图呈现,可以看整体良性、恶性肿瘤的诊断情况

# 将肿瘤诊断结果可视化
sns.countplot(data['diagnosis'],label="Count")
plt.show()
# 用热力图呈现features_mean字段之间的相关性
corr = data[features_mean].corr()
plt.figure(figsize=(14,14))
# annot=True显示每个方格的数据
sns.heatmap(corr, annot=True)
plt.show()

热力图中对角线上的为单变量自身的相关系数是1,颜色越浅代表相关性越大,所以redius_mean、perimeter_mean和area_mean相关性很大,compactness_mean、concavity_mean、concave_points_mean三个字段也是相关的,可以取其中的一个作为代表

img

如何进行特征选择?

特征选择的目的是降维,用少量的特征代表数据的特性,可以增强分类器的泛化能力,避免数据过拟合

看到mean、se、worst三组特征是对同一组内容的不同度量方式,可以保留mean这组特征中,可以看到mean这组特征中,redius_mean、perimeter_mean和area_mean相关性很大,compactness_mean、daconcavity_mean、concave_points_mean三个字段也是相关的,分别从这2类中选择1个属性作为代表,比如redius_mean和compactness_mean,把10个属性缩减为6个属性:

# 特征选择
features_remain = ['radius_mean','texture_mean', 'smoothness_mean','compactness_mean','symmetry_mean', 'fractal_dimension_mean'] 

对特征进行选择之后,准备训练集和测试集:

# 抽取30%的数据作为测试集,其余作为训练集
train, test = train_test_split(data, test_size = 0.3)# in this our main data is splitted into train and test
# 抽取特征选择的数值作为训练和测试数据
train_X = train[features_remain]
train_y=train['diagnosis']
test_X= test[features_remain]
test_y =test['diagnosis']

训练之前,需要对数据进行规范化,让数据同在同一个量级上,避免因为维度问题造成数据误差:

# 采用Z-Score规范化数据,保证每个特征维度的数据均值为0,方差为1
ss = StandardScaler()
train_X = ss.fit_transform(train_X)
test_X = ss.transform(test_X)

让SVM做训练和预测了:

# 创建SVM分类器
model = svm.SVC()
# 用训练集做训练
model.fit(train_X,train_y)
# 用测试集做预测
prediction=model.predict(test_X)
print('准确率: ', metrics.accuracy_score(prediction,test_y))

准确率: 0.9181286549707602

GitHub整体代码:< https://github.com/cystanford/breast_cancer_data >

metrics.accuracy_score(prediction,test_y))


> 准确率:  0.9181286549707602

GitHub整体代码:< https://github.com/cystanford/breast_cancer_data >


版权声明:本文为ywangjiyl原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。