图片
图片
图片
图片
图片
图片
图片
图片
本文主要先容若何使用R言语达成K最足下算法。
本文目次:
算法简介
准备数据
class包
建造模子
模子评价
超参数调优
kknn包
建造模子
模子评价
超参数调优
算法简介K最足下(K-Nearest-Neighbor,KNN)是一种非线性的分类算法,KNN处理分类问题的顺次是:找K个距离待瞻望样本最近的点,然后凭证这几个点的类别来详情新样本的类别。
芝兰之室,近墨者黑。
底下以一个二分类问题为例讲明KNN的念念想。
下图有两个特征不错用来瞻望肿瘤是”良性”照旧”恶性”。图中的X暗意咱们要瞻望的新样本。要是算法设定k=3,那么圆圈中包含的3个不雅测即是样本X的最足下。因为其中占多量比例的类别是”恶性”,是以样本X被分类为”恶性”。
图片
念念想是不是很浮浅?K的选拔对于KNN的瞻望后果黑白常困难的。
KNN中另一个需要指出的困难问题是距离的臆测顺次,概况说是特征空间中数据点的左近度的臆测。默许的距离是欧氏距离,也即是从点A到点B的浮浅直线距离。
Note
两点间的距离利害依赖于测量特征时使用的单元,是以必须对其进行尺度化,况兼条目数据不成有缺失值。
准备数据演示数据为印第安东说念主糖尿病数据集,这个数据一共有768行,9列,其中diabetes是后果变量,为二分类,其余列是瞻望变量。
该数据集的原始版块是有缺失值的,我这里使用的是插补过的版块,详备历程请参考数据准备这一章。
rm(list = ls())load(file = "../000机器学习/pimadiabetes.rdata")dim(pimadiabetes)## [1] 768 9str(pimadiabetes)## 'data.frame': 768 obs. of 9 variables:## $ pregnant: num 6 1 8 1 0 5 3 10 2 8 ...## $ glucose : num 148 85 183 89 137 116 78 115 197 125 ...## $ pressure: num 72 66 64 66 40 ...## $ triceps : num 35 29 22.9 23 35 ...## $ insulin : num 202.2 64.6 217.1 94 168 ...## $ mass : num 33.6 26.6 23.3 28.1 43.1 ...## $ pedigree: num 0.627 0.351 0.672 0.167 2.288 ...## $ age : num 50 31 32 21 33 30 26 29 53 54 ...## $ diabetes: Factor w/ 2 levels "pos","neg": 2 1 2 1 2 1 2 1 2 2 ...
各个变量的含义:
pregnant:孕珠次数glucose:血浆葡萄糖浓度(葡萄糖耐量执行)pressure:舒张压(毫米汞柱)triceps:三头肌皮褶厚度(mm)insulin:2小时血清胰岛素(mu U/ml)mass:BMIpedigree:糖尿病谱系功能,是一种用于瞻望糖尿病发病风险的目的,该目的是基于家眷史的糖尿病遗传风险身分的臆测得出的。它臆测了患者的家眷成员是否患有糖尿病以及他们与患者的亲缘讨论,从而得出一个抽象评分,用于瞻望患糖尿病的概率。age:年事diabetes:是否有糖尿病先对数据进行尺度化:
# 对数值型变量进行尺度化pimadiabetes[,-9] <- scale(pimadiabetes[,-9])str(pimadiabetes)## 'data.frame': 768 obs. of 9 variables:## $ pregnant: num 0.64 -0.844 1.233 -0.844 -1.141 ...## $ glucose : num 0.863 -1.203 2.011 -1.072 0.503 ...## $ pressure: num -0.0314 -0.5244 -0.6887 -0.5244 -2.6607 ...## $ triceps : num 0.63124 -0.00231 -0.64853 -0.63586 0.63124 ...## $ insulin : num 0.478 -0.933 0.63 -0.631 0.127 ...## $ mass : num 0.172 -0.844 -1.323 -0.626 1.551 ...## $ pedigree: num 0.468 -0.365 0.604 -0.92 5.481 ...## $ age : num 1.4251 -0.1905 -0.1055 -1.0409 -0.0205 ...## $ diabetes: Factor w/ 2 levels "pos","neg": 2 1 2 1 2 1 2 1 2 2 ...class包
数据分裂为磨真金不怕火集和测试集,分裂比例为7:3。
可是R言语里class包在使用时需要把真确后果去掉,是以咱们把真确后果去掉,只保留瞻望变量。
# 分裂是立时的,竖立种子数不错让后果复现set.seed(123)ind <- sample(1:nrow(pimadiabetes), size = 0.7*nrow(pimadiabetes))# 去掉真确后果列train <- pimadiabetes[ind,-9]test <- pimadiabetes[-ind, -9]dim(train)## [1] 537 8dim(test)## [1] 231 8str(train)## 'data.frame': 537 obs. of 8 variables:## $ pregnant: num -1.141 1.233 0.343 -0.251 1.233 ...## $ glucose : num 0.535 -1.564 0.699 -1.137 -1.203 ...## $ pressure: num -1.017 -0.196 0.462 -1.017 -1.428 ...## $ triceps : num 0.631 1.159 0.86 -1.164 -0.953 ...## $ insulin : num 0.117 -1.092 1.093 -0.881 -0.767 ...## $ mass : num 0.317 0.419 1.827 -1.541 -1.164 ...## $ pedigree: num 0.1875 0.7036 -0.8507 -0.0841 -1.0137 ...## $ age : num -1.041 0.49 1.17 -1.041 0.745 ...# 把真确后果列单独拿出来,后头用truth_train <- pimadiabetes[ind,9]truth_test <- pimadiabetes[-ind,9]建造模子
在磨真金不怕火集建造模子,1行代码措置:
library(class)f <- knn(train = train, # 磨真金不怕火集,惟有瞻望变量,莫得后果变量 test = test, # 测试集,莫得后果变量 cl = truth_train, # 磨真金不怕火集的真确后果 k = 8, # 使用的足下个数 prob = TRUE # 需要臆测概率 )# 稽察测试集的瞻望后果,只看前6个head(f)## [1] neg neg pos neg neg pos## Levels: pos neg# 稽察测试集的瞻望概率,只看前6个prob <- attr(f,"prob")head(prob)## [1] 0.500 0.750 1.000 0.750 0.625 0.625
此时得到的f这个后果是一个因子型的向量,况兼是闻明字和属性的,大多量模子拟合后果的时势齐是不同样的,使用时需要普遍!
还要普遍这里的概率,并不是阳性后果的概率,而是瞻望后果的概率!比如第一个概率0.500是neg的概率,第二个概率0.750是neg的概率,第三个概率1.000是pos的概率!
是以你要是想要阳性后果(pos)的概率,需要我方臆测一下:
prob <- ifelse(f == "pos", prob, 1-prob)head(prob)## [1] 0.500 0.250 1.000 0.250 0.375 0.625模子评价
模子拟合好之后,下一步即是稽察模子的多样目的,来望望这个模子在磨真金不怕火围聚的领略若何,比如欺凌矩阵、AUC值、准确率等。
岂论是什么类型的模子,要是咱们想要评价它的模子领略,齐是需要用到模子的瞻望后果和真确后果的。
对于追念任务来说,瞻望后果亦然数值型的,对于分类任务来说,模子的瞻望后果不错是某一种类别的概率,也不错是瞻望出的具体类别。大多量模子齐是既撑执臆测类别概率又撑执臆测具体类别的,可是有些模子可能只撑执一种类型。
最初稽察欺凌矩阵,咱们借助caret包展示,这个包现时仍然是稽察混线矩阵最全面的,,莫得之一,终点好用!
# 借助caret包,f是瞻望的类别,truth_test是真确的后果caret::confusionMatrix(f,truth_test)## Confusion Matrix and Statistics## ## Reference## Prediction pos neg## pos 131 32## neg 19 49## ## Accuracy : 0.7792 ## 95% CI : (0.7201, 0.831)## No Information Rate : 0.6494 ## P-Value [Acc > NIR] : 1.269e-05 ## ## Kappa : 0.4966 ## ## Mcnemar's Test P-Value : 0.09289 ## ## Sensitivity : 0.8733 ## Specificity : 0.6049 ## Pos Pred Value : 0.8037 ## Neg Pred Value : 0.7206 ## Prevalence : 0.6494 ## Detection Rate : 0.5671 ## Detection Prevalence : 0.7056 ## Balanced Accuracy : 0.7391 ## ## 'Positive' Class : pos ##
后果终点全面,最上头是欺凌矩阵,然后给出了:
准确率(Accuracy)和准确率真的切区间(95% CI)无信息率(No Information Rate)和P值(P-Value Acc>NIR])、Kappa值(Kappa一致性指数)Mcnemar磨真金不怕火的P值(Mcnemar’s Test P-Value)明锐性、特异性阳性瞻望值、阴性瞻望值流行率(Prevalence)检出率(Detection Rate)(Detection Prevalence)平衡准确率(Balanced Accuracy)临了告诉你参考类别是pos。
虽然这些值你也不错单独臆测:
caret::precision(f,truth_test) # 精确率## [1] 0.803681caret::recall(f,truth_test) # 调回率,奢睿度## [1] 0.8733333caret::F_meas(f,truth_test) # F1分数## [1] 0.8370607
然后再画个ROC弧线。最初使用ROCR进行演示,岂论是什么包,齐遵照前边说过的规矩,画ROC弧线是需要真确后果和瞻望概率的!
library(ROCR)# ROCR画ROC弧线即是2步,先prediction,再performancepred <- prediction(prob,truth_test) # 瞻望概率,真确类别perf <- performance(pred, "tpr","fpr") # ROC弧线的横纵坐标,不要写错了auc <- round(performance(pred, "auc")@y.values[[1]],digits = 4) # 索要AUC值auc## [1] 0.8477# 绘图plot(perf,lwd=2,col="tomato")abline(0,1,lty=2) # 添加对角线# 添加图例legend("bottomright", legend=paste("AUC: ",auc), col="tomato", lwd=2,bty = "n")
图片
另一种顺次,使用pROC进行演示,照旧那句话,岂论是哪种顺次,画ROC弧线齐是需要提供真确后果和瞻望概率!
library(pROC)rocc <- roc(truth_test, prob) # 瞻望概率,真确后果rocc # 看下后果## ## Call:## roc.default(response = truth_test, predictor = prob)## ## Data: prob in 150 controls (truth_test pos) > 81 cases (truth_test neg).## Area under the curve: 0.8477# 绘图plot(rocc, print.auc=TRUE, auc.polygon=TRUE, max.auc.polygon=TRUE, auc.polygon.col="skyblue", grid=c(0.1, 0.2), grid.col=c("green", "red"), print.thres=TRUE)
图片
对于ROC弧线绘制的书籍,共13篇著作,连结:ROC弧线绘制书籍
顺遂再展示下PR弧线,亦然用ROCR达成:
library(ROCR)# ROCR画ROC弧线即是2步,先prediction,再performancepred <- prediction(prob,truth_test) # 瞻望概率,真确类别perf <- performance(pred, "rec","prec") # ROC弧线的横纵坐标,不要写错了auc <- round(performance(pred, "auc")@y.values[[1]],digits = 4) # 索要AUC值auc# 绘图plot(perf,lwd=2,col="tomato")# 添加图例legend("bottomright", legend=paste("AUC: ",auc), col="tomato", lwd=2,bty = "n")
图片
经典成人故事image-20240502163045511是不黑白常easy?
顺遂再画个校准弧线,公众号后台回应校准弧线即可赢得书籍,也黑白常浮浅:
我这里给大众先容最新的顺次(其实之前也先容过了),用probably这个包绘制:
library(probably)cali_data <- data.frame(.pred_pos = prob, diabetes=truth_test)cal_plot_breaks(cali_data,diabetes, .pred_pos,conf_level = 0.95)
图片
可是现时这个版块(1.0.3)有个bug,第3个参数estimate,必须是.pred_xxx,其中的xxx必须是真确后果中的某一个类别,比如我这个数据diabetes中的类别即是pos和neg,那么这个名字就必须是.pred_pos概况.pred_neg,其他齐会报错(下标出界)!!
顺遂再画个有规画弧线,这个有规画弧线是临床瞻望模子中才有的本体,其他本体基本上齐是机器学习的基础常识。后台回应有规画弧线即可赢得书籍:
source("datasets/dca.r")# 把概率加到测试围聚dca_data <- pimadiabetes[-ind,]dca_data$prob <- prob# 后果变量酿成0,1dca_data$diabetes <- ifelse(dca_data$diabetes=="pos",1,0)dc <- dca(data = dca_data, # 测试集 outcome = "diabetes", predictors = "prob", probability = T )
图片
前几年stdca.r和dca.r这两个剧本是不错在文中给出的网址中免费下载的,可是从2022年底傍边这个网站就不提供这两段代码的下载了。因为我很早就下载好了,是以我把这两段代码放在粉丝qq群文献里,大众有需要的加群下载即可。
超参数调优KNN算法惟有一个超参数,即是足下的数目,是以KNN的超参数调优其实即是若何详情最好的K值,到底用几个足下是能得到最好的后果呢?
现时有许多好用的器用不错达成调优历程了,比如caret、tidymodels、mlr3等,可是这里我给大众演示下for轮回的作念法,因为它惟有1个超参数,很合适这种顺次,还不错绘制学习弧线。
模子评价目的选拔AUC。
aucs <- list()for (i in 1:50) { # K的值选拔1~50 f <- knn(train = train, # 磨真金不怕火集 test = test, # 测试集 cl = truth_train, # 磨真金不怕火集的真确类别 k = i, # 使用的足下个数 prob = TRUE # 需要臆测概率 ) prob <- attr(f,"prob") prob <- ifelse(f == "pos", prob, 1-prob) pred <- prediction(prob,truth_test) perf <- performance(pred, "tpr","fpr") auc <- round(performance(pred, "auc")@y.values[[1]],digits = 4) aucs[[i]] <- auc}aucs <- do.call(rbind,aucs)[,1]aucs # 50个AUC值,分别对应50个K值## [1] 0.7068 0.7870 0.8180 0.8264 0.8505 0.8510 0.8481 0.8477 0.8586 0.8540## [11] 0.8543 0.8580 0.8537 0.8513 0.8500 0.8451 0.8449 0.8453 0.8488 0.8467## [21] 0.8450 0.8473 0.8464 0.8462 0.8474 0.8492 0.8483 0.8508 0.8519 0.8500## [31] 0.8499 0.8504 0.8497 0.8491 0.8460 0.8455 0.8460 0.8427 0.8439 0.8417## [41] 0.8422 0.8402 0.8393 0.8384 0.8393 0.8377 0.8377 0.8374 0.8356 0.8342
画个图看下不同的K值对应的AUC变化的情况,看图愈加直不雅:
plot_df <- data.frame(k=1:50,auc=aucs)library(ggplot2)ggplot(plot_df, aes(k,auc))+ geom_line(linewidth=1)+ geom_point(size=2)+ geom_hline(yintercept = 0.85,linetype = 2)+ geom_vline(xintercept = 9,linetype = 2,color="red")
图片
后果露馅当K=9的时辰,AUC值是最大的,此时是0.8586。
这个图其实是一个学习弧线图,是一种经典的进行超参数调优时使用的图,我在先容有规画树的超参数调优时先容过了,不知说念大众有莫得印象?
是以此时你不错用K=9再再行跑一遍模子,行为你最终的后果。
final_f <- knn(train = train, # 磨真金不怕火集,惟有瞻望变量,莫得后果变量 test = test, # 测试集,莫得后果变量 cl = truth_train, # 磨真金不怕火集的真确后果 k = 9, # 这里的K值选拔9哦!!! prob = TRUE # 需要臆测概率 )
后续模子评价、画ROC弧线即是同样的代码了,就不再重迭了。
kknn包数据分裂为磨真金不怕火集和测试集,分裂比例为7:3。
kknn包不需要把后果变量去掉。
# 分裂是立时的,竖立种子数不错让后果复现set.seed(123)ind <- sample(1:nrow(pimadiabetes), size = 0.7*nrow(pimadiabetes))# 磨真金不怕火集、测试集train <- pimadiabetes[ind,]test <- pimadiabetes[-ind, ]# 把真确后果列单独拿出来,后头用truth_train <- pimadiabetes[ind,9]truth_test <- pimadiabetes[-ind,9]建造模子
在磨真金不怕火集拟合模子,撑执R言语经典的formula花样:
library(kknn)fit <- kknn::kknn(diabetes ~ ., train, test, scale = F, # w咱们如故对数据进行过尺度化了,这里就无须了 )# 径直summary不错稽察瞻望类别和瞻望概率,太长不展示#summary(fit)
咱们最柔顺的东西其实惟有瞻望类别和瞻望概率费力,是以不错单独稽察它们:
# 瞻望类别pred_class <- fit[["fitted.values"]]head(pred_class)## [1] neg neg pos neg pos pos## Levels: pos neg# 瞻望概率pred_prob <- fit[["prob"]]head(pred_prob)## pos neg## [1,] 0.3860350 0.6139650## [2,] 0.3440688 0.6559312## [3,] 1.0000000 0.0000000## [4,] 0.2768308 0.7231692## [5,] 0.6679614 0.3320386## [6,] 0.5939196 0.4060804
况兼这个包的后果给出了两种类别的概率,无须再我方臆测了。
模子评价最初照旧借助caret包稽察欺凌矩阵等多样信息:
caret::confusionMatrix(pred_class,truth_test)## Confusion Matrix and Statistics## ## Reference## Prediction pos neg## pos 131 34## neg 19 47## ## Accuracy : 0.7706 ## 95% CI : (0.7109, 0.8232)## No Information Rate : 0.6494 ## P-Value [Acc > NIR] : 4.558e-05 ## ## Kappa : 0.4738 ## ## Mcnemar's Test P-Value : 0.05447 ## ## Sensitivity : 0.8733 ## Specificity : 0.5802 ## Pos Pred Value : 0.7939 ## Neg Pred Value : 0.7121 ## Prevalence : 0.6494 ## Detection Rate : 0.5671 ## Detection Prevalence : 0.7143 ## Balanced Accuracy : 0.7268 ## ## 'Positive' Class : pos ##
然后是绘制ROC弧线,十足同样的代码:
library(ROCR)pred <- prediction(pred_prob[,1],truth_test) # 瞻望概率,真确类别perf <- performance(pred, "tpr","fpr")auc <- round(performance(pred, "auc")@y.values[[1]],digits = 4)auc## [1] 0.8491plot(perf,lwd=2,col="tomato")abline(0,1,lty=2)legend("bottomright", legend=paste("AUC: ",auc), col="tomato", lwd=2,bty = "n")
图片
easy!同样的用法,基本没啥变化,是以pROC的画法就不再重迭了,大众想要学习的就我方写一下即可。
超参数调优借助for轮回也不错,这里再给大众演示下若何使用e1071包达成轻量化的超参数调优。
library(e1071)set.seed(123)tune.knn(x=train[,-9], # 瞻望变量 y=truth_train,# 后果变量 k=1:50 # k的值 )## ## Parameter tuning of 'knn.wrapper':## ## - sampling method: 10-fold cross validation ## ## - best parameters:## k## 25## ## - best performance: 0.2198113
1行代码出后果,默许是使用10折交叉考据,比咱们的手动for轮回愈加慎重,后果最好的k值是25。使用的评价目的不同艳照门图片,具体臆测的才智也不同样,得出的后果不同样是很通俗的。
本站仅提供存储工作,总共本体均由用户发布,如发现存害或侵权本体,请点击举报。