1 目的
在机器学习领域,模型性能评估是一个至关重要的环节。我们的核心目的是通过采用科学、合理的模型性能评估方法,对机器学习在实际案例中的应用效果进行准确、全面的评价。这种评估不仅能够帮助我们了解模型在特定场景下的表现,还能为后续的模型优化和改进提供有力依据。
2 度量分类方法性能指标
2.1 预测值
运行代码:
data1<-read.csv("F:\\sms_results.csv") #读取数据 head(data1) #查看数据前六行
结果展示:
## actual_type predict_type prob_spam prob_ham ## 1 ham ham 0.000000256 1.00e+00 ## 2 ham ham 0.000130984 1.00e+00 ## 3 ham ham 0.000080900 1.00e+00 ## 4 ham ham 0.000139651 1.00e+00 ## 5 spam spam 1.000000000 8.58e-11 ## 6 ham ham 0.003504181 9.96e-01
根据结果可以看到案列分类属于垃圾信息和非垃圾信息预测概率情况,前六行数据真实值和预测值结果一致,且预测概率都很接近0或1,说明该判别可信度很高。
运行代码:
head(subset(data1,prob_spam>0.4&prob_ham<0.6))
结果展示:
## actual_type predict_type prob_spam prob_ham ## 5 spam spam 1.0000000 8.58e-11 ## 10 spam spam 1.0000000 2.90e-10 ## 14 spam spam 0.9999996 3.82e-07 ## 15 spam spam 1.0000000 4.85e-12 ## 35 spam spam 0.9995596 4.40e-04 ## 40 spam spam 0.9999986 1.38e-06
运行代码:
head(subset(data1,actual_type != predict_type))
结果展示:
## actual_type predict_type prob_spam prob_ham ## 53 spam ham 0.000679622 0.999 ## 59 spam ham 0.133396102 0.867 ## 73 spam ham 0.358266535 0.642 ## 76 spam ham 0.122462553 0.878 ## 81 spam ham 0.022486322 0.978 ## 184 spam ham 0.032005962 0.968
通过结果,我们可以看到部分样本数据的预测可信度偏低,且存在真实值与预测值结果不一致的情况。
2.2 深入探讨混淆矩阵
运行代码:
table(data1$actual_type,data1$predict_type)
结果展示:
## ## ham spam ## ham 1202 5 ## spam 29 154
运行代码:
library("gmodels") CrossTable(data1$actual_type,data1$predict_type)
结果展示:
## ## ## Cell Contents ## |-------------------------| ## | N | ## | Chi-square contribution | ## | N / Row Total | ## | N / Col Total | ## | N / Table Total | ## |-------------------------| ## ## ## Total Observations in Table: 1390 ## ## ## | data1$predict_type ## data1$actual_type | ham | spam | Row Total | ## ------------------|-----------|-----------|-----------| ## ham | 1202 | 5 | 1207 | ## | 16.565 | 128.248 | | ## | 0.996 | 0.004 | 0.868 | ## | 0.976 | 0.031 | | ## | 0.865 | 0.004 | | ## ------------------|-----------|-----------|-----------| ## spam | 29 | 154 | 183 | ## | 109.256 | 845.876 | | ## | 0.158 | 0.842 | 0.132 | ## | 0.024 | 0.969 | | ## | 0.021 | 0.111 | | ## ------------------|-----------|-----------|-----------| ## Column Total | 1231 | 159 | 1390 | ## | 0.886 | 0.114 | | ## ------------------|-----------|-----------|-----------| ## ##
通过代码运行输出简略混淆矩阵和更详细的混淆矩阵。
2.2.1 准确度和错误率
运行代码:
actual<-(1202+154)/1390 actual ##准确率 error<-1-actual error ##错误率
结果展示:
> actual ## [1] 0.9755396 > error ## [1] 0.02446043
根据结果显示,该模型的预测准确率达97.55%,错误率大约为2.45%。
2.2.2 Kappa统计量
运行代码:
library("e1071") library("caret") confusionMatrix(data1$predict_type,data1$actual_type,positive = "spam")
结果展示:
## Confusion Matrix and Statistics ## ## Reference ## Prediction ham spam ## ham 1202 29 ## spam 5 154 ## ## Accuracy : 0.9755 ## 95% CI : (0.966, 0.983) ## No Information Rate : 0.8683 ## P-Value [Acc > NIR] : < 2.2e-16 ## ## Kappa : 0.8867 ## ## Mcnemar's Test P-Value : 7.998e-05 ## ## Sensitivity : 0.8415 ## Specificity : 0.9959 ## Pos Pred Value : 0.9686 ## Neg Pred Value : 0.9764 ## Prevalence : 0.1317 ## Detection Rate : 0.1108 ## Detection Prevalence : 0.1144 ## Balanced Accuracy : 0.9187 ## ## 'Positive' Class : spam ##
根据结果可以看到一些其他性能指标,例如Kappa统计量值为0.8867、灵敏度为0.8415、特异性为0.9959。
运行代码:
pr_a<-1202/1390+154/1390 #分类器和真实值之间的真实一致性比例 pr_e<-0.868*0.886+0.132*0.114 #分类器和真实值之间的期望一致性比例 k<-(pr_a-pr_e)/(1-pr_e) k library("vcd") #加载包 Kappa(table(data1$actual_type,data1$predict_type)) #Kappa值 library("irr") #加载包 kappa2(data1[1:2]) #kappa值
结果展示:
> k ## [1] 0.8867069 > actual ## value ASE z Pr(>|z|) ## Unweighted 0.8867 0.01909 46.45 0 ## Weighted 0.8867 0.01909 46.45 0 > kappa2(data1[1:2]) #kappa值 ## Cohen's Kappa for 2 Raters (Weights: unweighted) ## ## Subjects = 1390 ## Raters = 2 ## Kappa = 0.887 ## ## z = 33.2 ## p-value = 0
三种方法显示Kappa值均为0.887,表示该分类器分类结果具有不错的一致性。
2.2.3 灵敏度和特异性
运行代码:
sens<-154/(29+154) sens spec<-1202/(1202+5) spec sensitivity(data1$predict_type,data1$actual_type,positive = "spam") sensitivity(data1$predict_type,data1$actual_type,positive = "ham")
结果展示:
> sens ## [1] 0.8415301 > spec ## [1] 0.9958575 > sensitivity(data1$predict_type,data1$actual_type,positive = "spam") ## [1] 0.8415301 > sensitivity(data1$predict_type,data1$actual_type,positive = "ham") ## [1] 0.9958575
两种方法结果相同,灵敏度为0.8415、特异性为0.9959,表示84.15%的垃圾信息被正确分类,99.59%的非垃圾信息被正确分类。
2.2.4 预测精确度和回溯精确度
运行代码:
prec<-154/(154+5) prec rec<-154/(154+29) rec posPredValue(data1$predict_type,data1$actual_type,positive = "spam") sensitivity(data1$predict_type,data1$actual_type,positive = "spam")
结果展示:
prec ## [1] 0.9685535 > rec ## [1] 0.8415301 > posPredValue(data1$predict_type,data1$actual_type,positive = "spam") ## [1] 0.9685535 > sensitivity(data1$predict_type,data1$actual_type,positive = "spam") ## [1] 0.8415301
两种方法结果相同,其中预测精确度为96.86%,回溯精确度为84.15%,表示被正确分类的垃圾信息在预测的垃圾信息中占比96.86%,被正确分类的垃圾信息占所有垃圾信息的84.15%。
2.2.5 F度量
运行代码:
f<-(2*prec*rec)/(prec+rec) f f<-(2*154)/(2*154+5+29) f
结果展示:
f ## [1] 0.9005848 > f ## [1] 0.9005848
两种方法结果相同,根据结果显示,F度量值为0.9005848,它能描述变化率的平均值。
2.3 性能权衡的可视化
运行代码:
library("ROCR") pred<-prediction(predictions=data1$prob_spam,labels=data1$actual_type) pref<-performance(pred,measure = "tpr",x.measure = "fpr") plot(pref,main="ROC curve for SMS spam filter",col="blue",lwd=3) abline(a=0,b=1,lwd=2,lty=2) text(x=0.6,y=0.4,"没有预测价值的分类器") text(x=0.1,y=0.8,"测试分类器") text(x=0.05,y=1.0,"完美分类器")
结果展示:
运行代码:
pref.auc<-performance(pred,measure="auc") str(pref.auc)
结果展示:
## Formal class 'performance' [package "ROCR"] with 6 slots ## ..@ x.name : chr "None" ## ..@ y.name : chr "Area under the ROC curve" ## ..@ alpha.name : chr "none" ## ..@ x.values : list() ## ..@ y.values :List of 1 ## .. ..$ : num 0.983 ## ..@ alpha.values: list()
运行代码:
unlist(pref.auc@y.values)
结果展示:
## [1] 0.9829999
通过ROC曲线及AUC=0.9829999,说明此分类器接近于完美分类器,分类效果较好。
2.4 评估未来的性能
2.4.1 保持法
运行代码:
credit<-read.csv("F:\\机器学习\\第三次作业\\credit.csv")#读取数据 random_ids<-order(runif(1000)) #生成随机1000个随机ID并排序 credit_train<-credit[random_ids[1:500],] #创建训练集 credit_validata<-credit[random_ids[501:750],] #创建验证数据集 credit_test<-credit[random_ids[751:1000],] #创建测试集 in_train<-createDataPartition(credit$default,p=0.75,list=F) credit_train<-credit[in_train,] #训练集 credit_test<-credit[-in_train,] #测试集
首先利用典型划分方法划分50%的数据为训练集、25%的数据为验证数据集、25%的数据为测试集。然后利用分层随机抽样的方法划分数据。
2.4.2 10折交叉验证法
运行代码:
folds<-createFolds(credit$default,k=10) #创建10折 str(folds) #查看数据类型
结果展示:
## List of 10 ## $ Fold01: int [1:100] 4 20 29 30 46 51 57 62 65 69 ... ## $ Fold02: int [1:100] 3 25 45 74 78 80 95 103 121 134 ... ## $ Fold03: int [1:100] 2 13 14 18 23 61 67 75 76 98 ... ## $ Fold04: int [1:100] 9 11 12 16 26 28 43 73 87 89 ... ## $ Fold05: int [1:100] 5 6 10 21 42 44 64 82 83 84 ... ## $ Fold06: int [1:100] 24 33 63 86 101 102 108 109 128 131 ... ## $ Fold07: int [1:100] 7 34 35 41 47 48 52 54 58 70 ... ## $ Fold08: int [1:100] 31 36 50 60 68 77 79 96 122 133 ... ## $ Fold09: int [1:100] 15 17 27 32 37 40 49 53 55 66 ... ## $ Fold10: int [1:100] 1 8 19 22 38 39 56 59 72 92 ...
运行代码:
credit01_test<-credit[folds$Fold01,] #训练集 credit01_train<-credit[-folds$Fold01,] #测试集 library("C50") #加载包 set.seed(123) #设置随机种子 folds<-createFolds(credit$default,k=10) cv_results<-lapply(folds,function(x){ #创建循环决策树模型函数 credit_train<-credit[-x,] credit_test<-credit[x,] credit_model<-C5.0(default~.,data=credit_train) credit_pred<-predict(credit_model,credit_test) credit_actual<-credit_test$default kappa<-kappa2(data.frame(credit_actual,credit_pred))$value return(kappa) }) str(cv_results) #查看Kappa统计量
结果展示:
## List of 10 ## $ Fold01: num 0.381 ## $ Fold02: num 0.525 ## $ Fold03: num 0.247 ## $ Fold04: num 0.316 ## $ Fold05: num 0.387 ## $ Fold06: num 0.368 ## $ Fold07: num 0.122 ## $ Fold08: num 0.141 ## $ Fold09: num 0.0691 ## $ Fold10: num 0.381
运行代码:
mean(unlist(cv_results)) #平均Kappa统计量
结果展示:
## [1] 0.2939567
根据结果发现平均Kappa值为0.2939567,在评价体系的解释中对应着”很差”,说明这个信用计分模型的效果并不比随机猜测好很多。
2.4.3 0.632自助法
运行代码:
library("C50") data1_train<-credit[random_ids[1:632],] #训练集 data1_test<-credit[random_ids[633:1000],] #测试集 data1_model<-C5.0(default~.,data=data1_train) data1_pred<-predict(data1_model,data1_train) data1_pred1<-predict(data1_model,data1_test) table(data1_train$default,data1_pred)
结果展示:
## data1_pred ## no yes ## no 427 18 ## yes 93 94
运行代码:
table(data1_test$default,data1_pred1)
结果展示:
## data1_pred1 ## no yes ## no 224 31 ## yes 73 40
运行代码:
error1<-0.632*(22+66)/632+0.368*(37+65)/368 error1
结果展示:
## [1] 0.19
根据结果显示,0.632自助法错误率为19%。