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

在CIFAR数据集上运行KNN时出现NA强制转换错误的技术求助

问题描述

在CIFAR-10数据集上运行KNN算法时,持续出现以下错误:

Warning: NAs introduced by coercion
Warning: NAs introduced by coercionError in knn(train_data_fold, val_data_fold, train_labels_fold, k = k) :
NA/NaN/Inf in foreign function call (arg 6)

已将标签转换为因子类型,但问题仍未解决,相关R代码如下:

library(keras)
library(e1071)
library(class)
cifar10 <- dataset_cifar10()

# For the hyperparameter testing we will be using only 10 percent of the data.
num_samples <- floor(0.1 * dim(cifar10$train$x)[1])
# Generate a random sample of indices
sample_indices <- sample(1:dim(cifar10$train$x)[1], num_samples)
# Use the random indices to select a subset of the training data and labels
partial_train_images <- cifar10$train$x[sample_indices, , , ] / 255
partial_train_labels <- cifar10$train$y[sample_indices]
all_train_images <- cifar10$train$x / 255
all_train_labels <- cifar10$train$y
test_images <- cifar10$test$x / 255
test_labels <- cifar10$test$y

# Flatten the image data into matrices
partial_train_matrix <- array_reshape(partial_train_images, c(dim(partial_train_images)[1], 32*32*3))
test_matrix <- array_reshape(test_images, c(dim(test_images)[1], 32*32*3))
all_train_matrix <- array_reshape(all_train_images, c(dim(all_train_images)[1], 32*32*3))

# Perform PCA:
partial_pca_result <- prcomp(partial_train_matrix, center = TRUE, scale. = TRUE)

# Calculate the cumulative proportion of variance explained
cum_prop_var_explained <- cumsum(partial_pca_result$sdev^2) / sum(partial_pca_result$sdev^2)
num_components <- which(cum_prop_var_explained >= 0.85)[1]

# Transform the original training and test data using the selected principal components.
# We use the PCA on the partial train data, as otherwise it will take a long time
pca_test_matrix <- predict(partial_pca_result, newdata = test_matrix)[, 1:num_components]
all_pca_train_matrix <- predict(partial_pca_result, newdata = all_train_matrix)[, 1:num_components]
partial_pca_train_matrix <- partial_pca_result$x[, 1:num_components]


# Convert labels to factors and specify levels
partial_train_labels <- as.factor(as.vector(partial_train_labels))
levels(partial_train_labels) <- c("airplane", "automobile", "bird", "cat", "deer", 
                          "dog", "frog", "horse", "ship", "truck")
test_labels <- as.factor(as.vector(test_labels))
levels(test_labels) <- c("airplane", "automobile", "bird", "cat", "deer", 
                         "dog", "frog", "horse", "ship", "truck")
all_train_labels <- as.factor(as.vector(all_train_labels))
levels(all_train_labels) <- c("airplane", "automobile", "bird", "cat", "deer", 
                              "dog", "frog", "horse", "ship", "truck")

# combining to data frame
partial_pca_train_data <- data.frame(partial_pca_train_matrix, label = partial_train_labels)
test_data <- data.frame(test_matrix, label = test_labels)
all_pca_train_data <- data.frame(all_pca_train_matrix, label = all_train_labels)


num_folds <- 5
folds <- sample(1:num_folds, size = nrow(partial_pca_train_data), replace = TRUE)

# potential k values for kNN
k_values <- c(8, 9, 10, 11, 12, 13, 14, 15, 20)

# Run cv manually as tune doesn't work for this call.
results <- data.frame(k = integer(), accuracy = numeric())
for (k in k_values) {
  accuracies <- numeric(num_folds)
  
  for (fold in 1:num_folds) {
    # Split data into training and validation sets
    train_indices <- which(folds != fold)
    val_indices <- which(folds == fold)
    
    train_data_fold <- partial_pca_train_data[train_indices, ]
    train_labels_fold <- partial_train_labels[train_indices]
    val_data_fold <- partial_pca_train_data[val_indices, ]
    val_labels_fold <- partial_train_labels[val_indices]
    
    # Run kNN
    predictions <- knn(train_data_fold, val_data_fold, train_labels_fold, k = k)
    
    # Calculate accuracy
    accuracies[fold] <- sum(predictions == val_labels_fold) / length(val_labels_fold)
  }
  
  # Store average accuracy for this k value
  results <- rbind(results, data.frame(k = k, accuracy = mean(accuracies)))
}
print(results)
错误原因分析

问题核心在于knn函数的输入数据不符合要求:

  • 你传入的train_data_fold和val_data_fold是包含label列的完整数据框,但knn要求前两个参数必须是仅包含数值型特征的矩阵/数据框。
  • label列是因子类型,当knn尝试将其作为特征处理时,会强制把因子转换为数值,这个过程中产生了NA(对应警告信息),最终导致函数调用时出现NA/NaN/Inf的错误。
解决方法

修改交叉验证循环中提取训练和验证数据的代码,排除label列,只保留特征部分:

for (fold in 1:num_folds) {
  # Split data into training and validation sets
  train_indices <- which(folds != fold)
  val_indices <- which(folds == fold)
  
  # 仅提取特征列,排除最后一列的label
  train_data_fold <- partial_pca_train_data[train_indices, -ncol(partial_pca_train_data)]
  train_labels_fold <- partial_train_labels[train_indices]
  val_data_fold <- partial_pca_train_data[val_indices, -ncol(partial_pca_train_data)]
  val_labels_fold <- partial_train_labels[val_indices]
  
  # Run kNN
  predictions <- knn(train_data_fold, val_data_fold, train_labels_fold, k = k)
  
  # Calculate accuracy
  accuracies[fold] <- sum(predictions == val_labels_fold) / length(val_labels_fold)
}

另一种更清晰的方式是单独保存特征矩阵和标签,避免后续混淆:

# 拆分特征和标签,不合并成带label的数据框
partial_pca_train_features <- partial_pca_train_matrix
partial_pca_train_labels <- partial_train_labels

# 后续交叉验证时直接使用特征矩阵
train_data_fold <- partial_pca_train_features[train_indices, ]
val_data_fold <- partial_pca_train_features[val_indices, ]

这样就能确保knn的输入只有数值型特征,不会出现强制转换产生的NA问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:32:03