在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
相关产品推荐
相关产品推荐

