对于应用于Iris 数据集的最佳值是多少?
其中最佳意味着的值导致最低的泛化误差。
对于应用于Iris 数据集的最佳值是多少?
其中最佳意味着的值导致最低的泛化误差。
假设您想使用准确度(或正确百分比)来评估“最佳”,并且您有时间查看 k 的 25 个值。以下 R 代码将使用 15 次重复 10 倍交叉验证来回答您的问题。运行也需要很长时间。
library(caret)
model <- train(
Species~.,
data=iris,
method='knn',
tuneGrid=expand.grid(.k=1:25),
metric='Accuracy',
trControl=trainControl(
method='repeatedcv',
number=10,
repeats=15))
model
plot(model)
> confusionMatrix(model)
Cross-Validated (10 fold, repeated 15 times) Confusion Matrix
(entries are percentages of table totals)
Reference
Prediction setosa versicolor virginica
setosa 33.3 0.0 0.0
versicolor 0.0 31.9 1.2
virginica 0.0 1.4 32.1

因此,按照这个标准,我得到的答案是 17,但看起来“真实”值可能介于 5 到 20 之间。如果需要,您可以替换“Kappa”或其他一些指标,并添加更多 cv-folds也是。您还可以尝试不同的交叉验证方法,例如留一法或自举重采样。
/编辑:为了响应您对多样性的要求,我编写了这个函数来计算多类问题的各种指标:
#Multi-Class Summary Function
#Based on caret:::twoClassSummary
require(compiler)
multiClassSummary <- cmpfun(function (data, lev = NULL, model = NULL){
#Load Libraries
require(Metrics)
require(caret)
#Check data
if (!all(levels(data[, "pred"]) == levels(data[, "obs"])))
stop("levels of observed and predicted data do not match")
#Calculate custom one-vs-all stats for each class
prob_stats <- lapply(levels(data[, "pred"]), function(class){
#Grab one-vs-all data for the class
pred <- ifelse(data[, "pred"] == class, 1, 0)
obs <- ifelse(data[, "obs"] == class, 1, 0)
prob <- data[,class]
#Calculate one-vs-all AUC and logLoss and return
cap_prob <- pmin(pmax(prob, .000001), .999999)
prob_stats <- c(auc(obs, prob), logLoss(obs, cap_prob))
names(prob_stats) <- c('ROC', 'logLoss')
return(prob_stats)
})
prob_stats <- do.call(rbind, prob_stats)
rownames(prob_stats) <- paste('Class:', levels(data[, "pred"]))
#Calculate confusion matrix-based statistics
CM <- confusionMatrix(data[, "pred"], data[, "obs"])
#Aggregate and average class-wise stats
#Todo: add weights
class_stats <- cbind(CM$byClass, prob_stats)
class_stats <- colMeans(class_stats)
#Aggregate overall stats
overall_stats <- c(CM$overall)
#Combine overall with class-wise stats and remove some stats we don't want
stats <- c(overall_stats, class_stats)
stats <- stats[! names(stats) %in% c('AccuracyNull', 'Prevalence', 'Detection Prevalence')]
#Clean names and return
names(stats) <- gsub('[[:blank:]]+', '_', names(stats))
return(stats)
})
这是一个非常强大的功能,因此它会稍微减慢插入符号的速度,但是如果您发布 10 倍 CV 的 1000 次重复的结果,我会非常高兴(我既没有时间也没有计算能力尝试目前这个)。这是我的 15 次重复 10 倍 CV 的代码。请注意,您可以轻松修改此代码以尝试其他重新采样方法,例如引导采样:
library(caret)
set.seed(19556)
model <- train(
Species~.,
data=iris,
method='knn',
tuneGrid=expand.grid(.k=1:30),
metric='Accuracy',
trControl=trainControl(
method='repeatedcv',
number=10,
repeats=15,
classProbs=TRUE,
summaryFunction=multiClassSummary))
ROC和LogLoss似乎都在 8 左右达到峰值:

虽然敏感性和特异性似乎在 15 左右达到峰值:

这是一些将所有图输出为 pdf 的代码:
dev.off()
pdf('plots.pdf')
for(stat in c('Accuracy', 'Kappa', 'AccuracyLower', 'AccuracyUpper', 'AccuracyPValue',
'Sensitivity', 'Specificity', 'Pos_Pred_Value',
'Neg_Pred_Value', 'Detection_Rate', 'ROC', 'logLoss')) {
print(plot(model, metric=stat))
}
dev.off()
如果你用枪指着我的头,我可能会说 8...