美文网首页R小推车Python
用kNN算法诊断乳腺癌

用kNN算法诊断乳腺癌

作者: apricoter | 来源:发表于2019-02-05 21:14 被阅读89次

    一、数据准备

    乳腺癌数据包括569例细胞活检案例,每个案例有32个特征。
    第一个特征是识别号码,
    第二个特征是癌症诊断结果(癌症诊断结果用编码“M”表示恶性,用编码“B”表示良性),
    其他30个特征是数值型的实验室测量结果。(其他30个数值型测量结果由数字化细胞核的10个不同特征的均值、标准差和最差值(即最大值)构成)。这些特征包括:
    Radius(半径)、Texture(质地)、Perimeter(周长)、Area(面积)、Smoothness(光滑度)、Compactness(致密性)、Concavity(凹度)、Concave points(凹点)、Symmetry(对称性)、Fractal dimension(分形维数)

    url<-'http://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data'
    #原数据的列名为v1,v2,不好理解,因此header=F
    wdbc<-read.csv(url,header = F)
    

    二、数据预处理

    #根据数据描述,对每一列重命名
    wdbc.name<-c("Radius","Texture","Perimeter","Area","Smoothness","Compactness","Concavity","Concave points","Symmetry","Fractal dimension")
    wdbc.name<-c(wdbc.name,paste(wdbc.name,"_mean",sep=""),paste(wdbc.name,"_worst",sep=""))
    names(wdbc)<-c("id","diagnosis",wdbc.name)
    

    最终的数据为:

    str(wdbc)
    attach(wdbc)
    
    table(diagnosis)
    

    可以得到有357个为良性,有212个为恶性 因为id列没有意义,去掉id列

    wdbc<-wdbc[-1]
    

    并将目标属性编码因子化B良性M恶性

    diagnosis<-factor(diagnosis,levels=c("B","M"),labels=c("Benign","Malignant"))
    diagnosis
    

    并计算各自占比
    round四舍五入round(x,digits=n)
    prop.table得到边缘概率prop.table(x,margin=null)

    round(prop.table(table(diagnosis))*100,digits=1)
    

    通过summary详细地观察3个特征:可以看出不同特征的度量值差别大

    summary(wdbc[c("Radius_mean","Area_mean","Smoothness_mean")])
    

    kNN的距离计算在很大程度上依赖于输入特征的测量尺度。由于光滑度的范围是0.05~0.16,且面积的范围是143.5~2501.0,所以在距离计算中,面积的影响比光滑度的影响大很多,这可能潜在地导致我们的分类器出现问题,所以我们应用min-max标准化方法将特征值重新调整到一个标准范围内,对数据通过归一化来进行无量纲处理
    即显然数据需要转换,转换函数为:

    normalize<-function(x){
      return((x-min(x))/(max(x)-min(x)))
    }
    

    我们并不需要对这30个数值变量逐个进行min-max标准化,这里可以使用R中的一个函数来自动完成此过程
    lapply()函数接受一个列表作为输入参数,然后把一个具体函数应用到每一个列表元素。因为数据框是一个含有等长度向量的列表,所以我们可以使用lapply()函数将normalize()函数应用到数据框中的每一个特征。最后一个步骤是,应用函数as.data.frame()把lapply()返回的列表转换成一个数据框。过程如下所示:

    wdbc_n<-as.data.frame(lapply(wdbc[2:31],normalize))
    

    这里使用的后缀_n是一个提示,即wdbc中的值已经被min-max标准化了。
    为了确认转换是否正确应用,让我们来看看其中一个变量的汇总统计量:

    summary(Area_mean)
    

    正如预期的那样,area_mean变量的原始范围是143.5~2501.0,而现在的范围是0~1。

    三、切分数据集

    接下来需要切分数据集,实际需要构造training、validation、test,其中validation用来校正提高模型准确性,为简单起见,我们只用train和test
    第一种方法:由于我们没有新病人的数据,所以使用前469条记录作为训练数据集,剩下的100条记录用来模拟新的病人

    wdbc_train<-wdbc_n[1:469,]
    wdbc_test<-wdbc_n[470:569,]
    #存储目标变量标签
    wdbc_train_labels<-wdbc[1:469,1]
    wdbc_test_labels<-wdbc[470:569,1]
    mal_rate<-table(wdbc_train_labels)
    round(mal_rate[2]/sum(mal_rate),digits=2)
    

    第二种方法:如果样本中的恶性肿瘤大部分分布在1,则将469作为训练集就有很大问题,此时采用随机取样

    set.seed(1234)
    ratio<-sample(1:dim(wdbc_n)[1],469,replace=F)
    wdbc_train<-wdbc_n[ratio,]
    wdbc_test<-wdbc_n[-ratio,]
    wdbc_train_labels<-wdbc[ratio,1]
    wdbc_test_labels<-wdbc[-ratio,1]
    mal_rate<-table(wdbc_train_labels)
    round(mal_rate[2]/sum(mal_rate),digits=2)
    

    第三种方法:直接利用"caret"包中的crateDataPartition函数可自动分区

    library(caret)
    set.seed(1234)
    ratio<-createDataPartition(y=diagnosis,p=0.8,list=FALSE)
    wdbc_train<-wdbc_n[ratio,]
    wdbc_test<-wdbc_n[-ratio,]
    wdbc_train_labels<-wdbc[ratio,1]
    wdbc_test_labels<-wdbc[-ratio,1]
    mal_rate<-table(wdbc_train_labels)
    round(mal_rate[2]/sum(mal_rate),digits=2)
    

    四、构建模型

    构建模型,class包中的knn函数,由于训练数据集含有469个实例,所以我们可能尝试k = 21,它是一个大约等于469的平方根的奇数。根据二分类的结果,使用奇数将消除各个类票数相等这一情况发生的可能性。
    函数knn()返回一个因子向量,为测试数据集中的每一个案例返回一个预测标签,我们将该因子向量命名为wdbc_test_pred。
    现在,我们可以使用knn()函数对测试数据进行分类:

    library(class)
    wdbc_test_pred<-knn(train=wdbc_train,test=wdbc_test,cl=wdbc_train_labels,k=21)
    

    该过程的下一步就是评估wdbc_test_pred向量中预测的分类与wdbc_test_labels向量中已知值的匹配程度如何。为了做到这一点,我们可以使用gmodels添加包中的CrossTable()函数,它在第2章中介绍过。如果你还没有安装该添加包,可以使用install.packages("gmodels")命令进行安装。
    在使用library(gmodels)命令载入该添加包后,可以创建一个用来标识两个向量之间一致性的交叉表。指定参数prop.chisq = FALSE,将从输出中去除不需要的卡方(chi-square)值,如下所示:

    library(gmodels)
    CrossTable(x=wdbc_test_labels,y=wdbc_test_pred,prop.chisq=FALSE)
    

    行为真实结果,列为预测结果,对角框的数字越小,模型越好
    选取两个变量作为横纵坐标进行画图,观察实际类别与预测的分类结果。

    plot(wdbc_test$Texture_mean,wdbc_test$Radius_mean,col=wdbc_test_pred,pch=as.integer(wdbc_test_labels))
    

    颜色代表分类后得到的结果,形状代表真实的类别。从检测结果和图上都可以看出,分类结果基本与真实结果一致。

    相关文章

      网友评论

        本文标题:用kNN算法诊断乳腺癌

        本文链接:https://www.haomeiwen.com/subject/kjpvsqtx.html