两性-伪娘 拳交 R谈话KNN(K最隔邻、ROC、PR弧线、校准弧线、有筹画弧线)
你的位置:两性 > 夏雨荷 麻豆 > 伪娘 拳交 R谈话KNN(K最隔邻、ROC、PR弧线、校准弧线、有筹画弧线)
伪娘 拳交 R谈话KNN(K最隔邻、ROC、PR弧线、校准弧线、有筹画弧线)
发布日期:2025-07-03 15:48    点击次数:102

伪娘 拳交 R谈话KNN(K最隔邻、ROC、PR弧线、校准弧线、有筹画弧线)

图片

反差 裸

图片

图片

图片

图片

图片

图片

图片

本文主要先容如何使用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。使用的评价看法不同,具体贪图的法子也不相通,得出的成果不相通是很平淡的。

本站仅提供存储办事,通盘本色均由用户发布,如发现存害或侵权本色,请点击举报。

相关资讯