KNN算法
优点:
简单有效;对数据的分布没有要求;训练阶段很快。
缺点:
不产生模型,在发现特征之间的关系上的能力有限;分类阶段很慢;需要大量的内存;名义变量(特征)和缺失数据需要额外处理。
之所以被称为懒惰学习算法,是因为从技术上说,没有抽象化的步骤。抽象过程与一般过程都被跳跃过去了。由于高度依赖训练案例,所以懒惰学习又称为机械学习。机械学习不会建立一个模型,所以该方法被归类为非参数学习方法。
案例用KNN算法诊断乳腺癌
第一步——收集数据
数据来源于UCI机器学习数据仓库的“威斯康星乳腺癌诊断”(Brest Cancer Wisconsin Diagnostic)数据集,网址:http://archive.ics.uci.edu/ml/
数据集包括569个细胞活检案例,每个案例32个特征。一个特征是识别号,一个特征是诊断结果,其他30个特征是数值型测量结果,诊断结果用“M”表示恶性,“B”表示良性。
第二步——探索和准备数据
首先导入CSV文件:
wbcd<-read.csv("wisc_bc_data.csv",header=F)第一个变量信息id不能提供有用信息,所以删除:
wbcd<-wbcd[-1]使用table函数查看恶性和良性肿瘤个数:
table(wbcd$V2) B M 357 212许多R机器学习分类器要求将目标属性编码为因子变量,所以重新编码wbcd的第一列,同时用labels参数对B值和M值给出更多信息:
wbcd$V2<-factor(wbcd$V2,levels=c("B","M"),labels=c("Benign","Malignant")) round(prop.table(table(wbcd$V2))*100,digits=1) Benign Malignant 62.7 37.3由上述代码可知,Benign和Malignant分别有62.7%与37.3%。
1. 转换——min-max标准化数值型数据
首先建立一个函数:
normalize<-function(x){ return((x-min(x))/(max(x)-min(x))) }把函数normalize应用于30个数值化特征,使用lapply函数,再用as.data.frame函数把lapply函数返回的列表转化成数据框:
wbcd_n<-as.data.frame(lapply(wbcd[2:31],normalize))2. 数据准备——创建训练数据集和测试数据集
wbcd_train<-wbcd_n[1:469,] wbcd_test<-wbcd_n[470:569,]再把类的标签存储在一个引子类型的向量中:
wbcd_train_labels<-wbcd[1:469,1] wbcd_test_labels<-wbcd[470:569,1]第三步——基于数据训练模型
使用class包中的knn函数:
library(class) wbcd_test_pred<-knn(train=wbcd_train,test=wbcd_test,cl=wbcd_train_labels,k=21)其中,train是一个包含数值型训练数据的数据框;test是一个包含数值型测试数据的数据框;class是包含训练数据每一行分类的一个因子向量;k是标识最近邻树木的一个整数。k的值应该为训练数据样本的平方根数。即由于训练数据集含有469个实例,则尝试k=21。
第四步——评估模型的性能
该过程就是评估wbcd_test_pred与wbcd_test_labels中已知的值的匹配程度。使用gmodels包中的CrossTable函数:
library(gmodels) CrossTable(x=wbcd_test_labels,y=wbcd_test_pred,prop.chisq=F) Cell Contents |-------------------------| | N | | N / Row Total | | N / Col Total | | N / Table Total | |-------------------------| Total Observations in Table: 100 | wbcd_test_pred wbcd_test_labels | Benign | Malignant | Row Total | -----------------|-----------|-----------|-----------| Benign | 77 | 0 | 77 | | 1.000 | 0.000 | 0.770 | | 0.975 | 0.000 | | | 0.770 | 0.000 | | -----------------|-----------|-----------|-----------| Malignant | 2 | 21 | 23 | | 0.087 | 0.913 | 0.230 | | 0.025 | 1.000 | | | 0.020 | 0.210 | | -----------------|-----------|-----------|-----------| Column Total | 79 | 21 | 100 | | 0.790 | 0.210 | | -----------------|-----------|-----------|-----------|从表格中看出假阴性有2个,假阳性0个,正确率98%。
第五步——提高模型性能
对前面的分类器,尝试两种改变,一种是用另一种方法标准化,另一个是尝试不同的k值。
1. 转换——z-score标准化
wbcd_z<-as.data.frame(scale(wbcd[-1]))再进行同样的步骤:
wbcd_train<-wbcd_z[1:469,] wbcd_test<-wbcd_z[470:569,] wbcd_train_labels<-wbcd[1:469,1] wbcd_test_labels<-wbcd[470:569,1] wbcd_test_pred<-knn(wbcd_train,wbcd_test,cl=wbcd_train_labels,k=21) CrossTable(x=wbcd_test_labels,y=wbcd_test_pred,prob.chisq=F) Cell Contents |-------------------------| | N | | Chi-square contribution | | N / Row Total | | N / Col Total | | N / Table Total | |-------------------------| Total Observations in Table: 100 | wbcd_test_pred wbcd_test_labels | Benign | Malignant | Row Total | -----------------|-----------|-----------|-----------| Benign | 77 | 0 | 77 | | 4.298 | 16.170 | | | 1.000 | 0.000 | 0.770 | | 0.975 | 0.000 | | | 0.770 | 0.000 | | -----------------|-----------|-----------|-----------| Malignant | 2 | 21 | 23 | | 14.390 | 54.134 | | | 0.087 | 0.913 | 0.230 | | 0.025 | 1.000 | | | 0.020 | 0.210 | | -----------------|-----------|-----------|-----------| Column Total | 79 | 21 | 100 | | 0.790 | 0.210 | | -----------------|-----------|-----------|-----------|可以看出结果没有改变。另一种方法是改变k值,在此就不在列出。
