1
$\begingroup$

I am using the classic iris dataset and trying to learn the Knn algorithm for different values of k. I perform a train-test-validation split to generate 3 partitions. After this, I use the train and test to fit a knn classifier. But I get an error after splitting.

My approach

spec = c(train = .5, test = .25, validate = .25)

byparts = sample(cut(
  seq(nrow(iris)), 
  nrow(iris)*cumsum(c(0,spec)),
  labels = names(spec)
))

res = split(iris, byparts)

addmargins(prop.table(table(byparts)))

#Model fit
library(class)
train_feat <- res$train[,1:4] 
test_feat <- res$test[,1:4]

set.seed(1)
train_pred <- knn(train_feat, train_feat, res$train["Species"], k=1)
train_acc <- mean(train_pred == res$train["Species"])

set.seed(1)
test_pred <- knn(train_feat, test_feat, res$train["Species"], k=1)
test_acc <- mean(valid_pred == res$test["Species"])

cat('Training Accuracy:   ', train_acc, '\n',
    'Validation Accuracy: ', valid_acc, sep='')

It says the train and class have different lengths

Error in knn(train_feat, train_feat, res$train["Species"], k = 1) : 
  'train' and 'class' have different lengths

Is this due to the way how I split the partition or should I re-split it again? Would like to know what am I doing wrong?

$\endgroup$
5
  • $\begingroup$ Why not print the lengths of these and debug? $\endgroup$ Apr 20 at 22:08
  • $\begingroup$ I pretty much tried but cannot proceed. Stuck for hour on this issue. $\endgroup$
    – Ranji Raj
    Apr 20 at 22:13
  • $\begingroup$ It would be helpful if we, too, could see the lengths that were printed. $\endgroup$ Apr 20 at 22:15
  • $\begingroup$ > length(train_feat) [1] 4 > length(res$train["Species"]) [1] 1 $\endgroup$
    – Ranji Raj
    Apr 20 at 22:16
  • $\begingroup$ I tried this approach earlier but there it worked well with no issues. It's only here, not sure whether due to the 3-split that I made or so. $\endgroup$
    – Ranji Raj
    Apr 20 at 22:19
2
$\begingroup$

I was able to fix this by changing the type of your data, based on what happens inside the knn function.

train_targets = as.matrix(res$train["Species"])  # Fixes the length calculation.
train_pred = knn(train_feat, train_feat, train_targets, k=1)
train_acc = mean(train_pred == train_targets)

You should make a similar adjustment for the test and validation sets.


Why did this happen? Check the source code of knn by printing knn in your R interpreter. It checks whether the lengths match, according to length. length(res$train["Species"]) is 1, even though dim(res$train["Species"]) is 75×1. When you convert it to a matrix with as.matrix, the issue goes away.

$\endgroup$
1
  • 1
    $\begingroup$ appreciate your precious time in debugging this issue. I pretty much now understand that there are lot many things internally happening when we do data transformation :) $\endgroup$
    – Ranji Raj
    Apr 20 at 22:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.