You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用LOOCV实现kknn分类报错及LOOCV正确性咨询

kknn留一交叉验证(LOOCV)报错及实现问题

问题背景

你有一份用于kknn分类的样本数据(V4为响应变量,需分类为0或1),尝试通过for循环结合LOOCV构建k=3的模型,但运行代码时出现错误:

Error in model.frame.default(formula, data = train) :
invalid type (list) for variable 'train_data_response'

原始代码如下:

library(kknn)

data <- data.frame(
  V1=c(1.2, 2.5, 3.1, 4.8, 5.2), 
  V2=c(0.7, 1.8, 2.3, 3.9, 4.1), 
  V3=c(2.3, 3.7, 1.8, 4.2, 5.5), 
  V4= c(0, 1, 0, 1, 0)
)
for (i in 1:nrow(data)) {
  train_data <- data[-i, 1:3]
  train_data_response <- data.frame(data[-i, 4])
  colnames(train_data_response) <- "Response"
  test_set <- data[i, 3]
  model <- kknn(formula=train_data_response ~ ., data.frame(train_data), 
                data.frame(test_set), k=3, scale=TRUE) 
}

错误原因分析

  1. 公式参数使用错误:
    kknn的formula参数需要是标准公式对象(如响应列 ~ .),你直接将train_data_response(一个数据框,属于list类型)作为公式左侧,R会把它当作变量名查找,因此抛出"invalid type (list)"错误。kknn确实支持数据框输入,但公式必须引用数据框内的列名,而非直接传入数据框对象。

  2. 测试集维度不匹配:
    你提取的test_set只取了第3列(V3),但训练集包含V1-V3三个特征列,特征维度不一致会导致模型无法正常计算距离。


修正后的代码

以下是修复错误并完善LOOCV逻辑的代码:

library(kknn)

data <- data.frame(
  V1=c(1.2, 2.5, 3.1, 4.8, 5.2), 
  V2=c(0.7, 1.8, 2.3, 3.9, 4.1), 
  V3=c(2.3, 3.7, 1.8, 4.2, 5.5), 
  V4= c(0, 1, 0, 1, 0)
)

# 初始化向量存储每次LOOCV的预测结果
predictions <- numeric(nrow(data))

for (i in 1:nrow(data)) {
  # 构造训练集:保留除第i行外的所有数据(含特征和响应变量)
  train_data <- data[-i, ]
  # 构造测试集:保留第i行的所有特征列(V1-V3)
  test_set <- data[i, 1:3]
  
  # 正确调用kknn:公式引用训练集中的响应列V4,训练数据传完整的train_data
  model <- kknn(formula = V4 ~ ., train = train_data, test = test_set, k=3, scale=TRUE)
  
  # 提取预测类别(kknn返回的fitted.values是概率,用round转换为0/1分类)
  predictions[i] <- round(model$fitted.values)
}

# 输出结果
cat("LOOCV预测结果:", predictions, "\n")
cat("真实响应值:", data$V4, "\n")
cat("LOOCV分类准确率:", mean(predictions == data$V4), "\n")

LOOCV实现的正确性说明

  1. 手动循环的逻辑是正确的:
    你采用的"每次留一行作为测试集,其余作为训练集"的思路完全符合LOOCV的定义,修正后可以正常完成交叉验证流程。

  2. 更简洁的替代方案:
    kknn包提供了cv.kknn()函数,可以直接实现交叉验证(包括LOOCV),无需手动编写循环,示例代码如下:

    # 直接调用cv.kknn实现LOOCV(kcv设为样本量nrow(data))
    cv_result <- cv.kknn(V4 ~ ., data = data, kcv = nrow(data), k = 3, scale = TRUE)
    # 计算准确率
    cv_accuracy <- mean(round(cv_result$prob) == data$V4)
    cat("cv.kknn实现的LOOCV准确率:", cv_accuracy, "\n")
    

内容的提问来源于stack exchange,提问作者myts999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:51:35