02 实战_KNN方法案例

## 以上为中继点老师课堂笔记,请注意版权
##设置工作目录
setwd('D:/r-macine-trading')
wdbc=read.csv("./wdbc.data",header = F)
head(wdbc)
##将名字放入list,对数字正确的命名
wdbc.names=c("Radius","Texture","Perimeter","Area","Smothness","Compactness",
             "Concavity","Concave points","Symmetry","Fractal dimension")
##对names进行重构
wdbc.names=c(wdbc.names,paste(wdbc.names,"_mean",sep=""),paste(wdbc.names,"_worst",sep=""))
names(wdbc)=c("id","diagnosis",wdbc.names)
wdbc.names

str(wdbc)
dim(wdbc)

##诊断结果
table(wdbc$diagnosis)


##给诊断结果的B/M 加上标签
wdbc$diagnosis=factor(wdbc$diagnosis,levels=c("B","M"),labels=c("Begin","Malignant"))

round(prop.table(table(wdbc$diagnosis))*100,digits = 1)
wdbc=wdbc[-1]

str(wdbc)

###汇总数据
summary(wdbc[c("Radius_mean","Area_mean","Smothness_mean")])

###最大最小数据[max/min]差距太大
###显示数据需要转换,我们定义转换函数为

##编写一个函数处理最大最小数
normalize <- function(x){
  return((x-min(x))/(max(x)-min(x)))
}

###接下来对数据转换后,执行'summary'可以看出特征区间分布已经统一

wdbc_n <- as.data.frame(lapply(wdbc[2:31], normalize))   ###使用函数lapply对wdbc的2到31列做normalize函数计算
summary(wdbc_n[c("Radius_mean","Area_mean","Smothness_mean")])

##接下来我们需要构造训练数据与测试数据,实际通常的做法是training(培训),validation(验证)
##test三个数据集,validataion用来校正提高模型准确性,这里简单起见我们只用training和test数据集,最简单的方法如下

##第一种方法
##取1:469行的数据为训练数据
wdbc_train = wdbc_n[1:469,]
#取470到569行的数据作为测试数据
wdbc_test = wdbc_n[470:569,]

##每个都对应一个标签
wdbc_train_label = wdbc[1:469,1]
wdbc_test_label = wdbc[470:569,1]
mal_rate=table(wdbc_train_label)
round(mal_rate[2]/sum(mal_rate),digits = 2)

####这个方法虽然简单,但需要注意我们不是随机采样,如果样本的恶性肿瘤大部分分布在1:469显然就有大问题.
##当然另一种方法就是用sample函数,例如

##第二种方法
##训练数据,测试数据

set.seed(2014)
inTrain = sample(1:dim(wdbc_n)[1],469,replace = F)
wdbc_train = wdbc_n[inTrain,]
wdbc_test = wdbc_n[-inTrain,]

##诊断结果
wdbc_train_label = wdbc[inTrain,1]
wdbc_test_label = wdbc[-inTrain,1]


mal_rate = table(wdbc_train_label)
round(mal_rate[2]/sum(mal_rate),digits = 2)

##第三种方法

####除此之外,还可以用'caret'包的'createDataPartition'来完成这一工作(caret对数据进行分区)

install.packages("caret")
require(caret)
set.seed(2014)
inTrain=createDataPartition(y=wdbc$diagnosis,p=0.8,list=FALSE)
wdbc_train=wdbc_n[inTrain,]
wdbc_test=wdbc_n[-inTrain,]

wdbc_train_label=wdbc[inTrain,1]
wdbc_test_label=wdbc[-inTrain,1]
mal_rate=table(wdbc_train_label)
round(mal_rate[2]/sum(mal_rate),digits = 2)


###构建模型

##这里KNN实现,我们采用'class'包的实现,当然其它实现可以参考,例如'caret'包里面的'knn3'

require(class)
wdbc_test_pred <- knn(train = wdbc_train,test=wdbc_test,cl=wdbc_train_label,k=21)
##这里的k=21,是基于"length(wdbc_train_label"的平方根,'knn'的使用说明如下,
##长度的平方根,
length(wdbc_train_label)
sqrt(456)

##train:训练数据集
##test:测试数据集
##cl:factor,训练数据对应分类

head(wdbc_test_pred)


##模型评估
##这里采用'gmodels'的CrossTable函数

install.packages("gmodels")
require(gmodels)
CrossTable(x=wdbc_test_label,y=wdbc_test_pred,prop.chisq = FALSE)


##分别得到TN=71,TP=39,FN=3,FP=0.因

#accuracy=(TN+TP)/113=92.345%
#sensitivity=TP/(TP+FN)=92.86%
#specificity=TN/(TN+FP)=100%


###前面我们采用了最大最小标准化,还可以用z-score来实验一次.最大最小值标准化强制把
###数据压缩在0~1之间,也许减少了极值的影响,不过可能极值正好是恶性的标志呢?
###以下采用z-score重复前面的步骤

wdbc_z=as.data.frame(scale(wdbc[-1])) ##把第一个列排出,诊断结果
summary(wdbc_z$Area_mean)
set.seed(2014)
inTrain=createDataPartition(y=wdbc$diagnosis,p=0.8,list=FALSE)

wdbc_train=wdbc_z[inTrain,]
wdbc_test=wdbc_z[-inTrain,]

wdbc_train_label=wdbc[inTrain,1]
wdbc_test_label=wdbc[-inTrain,1]
wdbc_test_pred=knn(train=wdbc_train,test=wdbc_test,cl=wdbc_train_label,k=21)
CrossTable(x=wdbc_test_label,y=wdbc_test_pred,prop.chisq = FALSE)


#accuracy = (TN+TP)/113=96.46%
sensitivity=TP/(TP+FN)=90.47%
specificity=TN/(TN/FP)=100%

你可能感兴趣的:(02 实战_KNN方法案例)