web-dev-qa-db-fra.com

Erreur avec la fonction knn

J'essaie de lancer cette ligne:

knn(mydades.training[,-7],mydades.test[,-7],mydades.training[,7],k=5)

mais je reçois toujours cette erreur:

Error in knn(mydades.training[, -7], mydades.test[, -7], mydades.training[,  : 
  NA/NaN/Inf in foreign function call (arg 6)
In addition: Warning messages:
1: In knn(mydades.training[, -7], mydades.test[, -7], mydades.training[,  :
  NAs introduced by coercion
2: In knn(mydades.training[, -7], mydades.test[, -7], mydades.training[,  :
  NAs introduced by coercion

Une idée s'il vous plaît?

PS: mydades.training et mydades.test sont définis comme suit:

N <- nrow(mydades) 
permut <- sample(c(1:N),N,replace=FALSE)
ord <- order(permut)
mydades.shuffled <- mydades[ord,]
prop.train <- 1/3
NOMBRE <- round(prop.train*N)
mydades.training <- mydades.shuffled[1:NOMBRE,]
mydades.test <- mydades.shuffled[(NOMBRE+1):N,]
11
user2443456

Je suppose que votre problème réside dans la présence de champs de données non numériques dans «mydades». La ligne d'erreur:

NA/NaN/Inf in foreign function call (arg 6)

me fait penser que l'appel de la fonction knn à l'implémentation du langage C a échoué. En réalité, de nombreuses fonctions de R appellent des implémentations C plus efficaces sous-jacentes, au lieu d’avoir un algorithme implémenté dans seulement R. Si vous tapez simplement 'knn' dans votre console R, vous pouvez inspecter la mise en oeuvre R de 'knn'. Il existe la ligne suivante:

 Z <- .C(VR_knn, as.integer(k), as.integer(l), as.integer(ntr), 
        as.integer(nte), as.integer(p), as.double(train), as.integer(unclass(clf)), 
        as.double(test), res = integer(nte), pr = double(nte), 
        integer(nc + 1), as.integer(nc), as.integer(FALSE), as.integer(use.all))

où .C signifie que nous appelons une fonction C nommée 'VR_knn' avec les arguments de fonction fournis. Depuis que tu as deux des erreurs 

NAs introduced by coercion

Je pense que deux des appels as.double/as.integer échouent et introduisent les valeurs de NA. Si nous commençons à compter les paramètres, le 6ème argument est:

as.double(train)

cela peut échouer dans des cas tels que:

# as.double can not translate text fields to doubles, they are coerced to NA-values:
> as.double("sometext")
[1] NA
Warning message:
NAs introduced by coercion
# while the following text is cast to double without an error:
> as.double("1.23")
[1] 1.23

Vous obtenez deux des erreurs de contrainte, qui sont probablement données par 'as.double (train)' et 'as.double (test)'. Puisque vous ne nous avez pas fourni de détails précis sur l'état de «mydades», voici certaines de mes meilleures suppositions (et une distribution artificielle multivariée de données normales):

library(MASS)
mydades <- mvrnorm(100, mu=c(1:6), Sigma=matrix(1:36, ncol=6))
mydades <- cbind(mydades, sample(LETTERS[1:5], 100, replace=TRUE))

# This breaks knn
mydades[3,4] <- Inf
# This breaks knn
mydades[4,3] <- -Inf
# These, however, do not introduce the coercion for NA-values error message

# This breaks knn and gives the same error; just some raw text
mydades[1,2] <- mydades[50,1] <- "foo"
mydades[100,3] <- "bar"

# ... or perhaps wrongly formatted exponential numbers?
mydades[1,1] <- "2.34EXP-05"

# ... or wrong decimal symbol?
mydades[3,3] <- "1,23" 
# should be 1.23, as R uses '.' as decimal symbol and not ','

# ... or most likely a whole column is non-numeric, since the error is given twice (as.double problem both in training AND test set)
mydades[,1] <- sample(letters[1:5],100,replace=TRUE)

Je ne garderais pas les données numériques et les étiquettes de classe dans une seule matrice, vous pourriez peut-être séparer les données de la manière suivante:

mydadesnumeric <- mydades[,1:6] # 6 first columns
mydadesclasses <- mydades[,7]

Utiliser des appels 

str(mydades); summary(mydades)

peut également vous aider/nous aider à localiser les entrées de données problématiques et à les corriger en entrées numériques ou en omettant les champs non numériques.

Le reste du code d'exécution (après avoir cassé les données), tel que fourni par vous:

N <- nrow(mydades) 
permut <- sample(c(1:N),N,replace=FALSE)
ord <- order(permut)
mydades.shuffled <- mydades[ord,]
prop.train <- 1/3
NOMBRE <- round(prop.train*N)
mydades.training <- mydades.shuffled[1:NOMBRE,]
mydades.test <- mydades.shuffled[(NOMBRE+1):N,]

# 7th column seems to be the class labels
knn(train=mydades.training[,-7],test=mydades.test[,-7],mydades.training[,7],k=5)
19

Excellente réponse de @ Teemu. 

Comme il s'agit d'une question bien lue, je donnerai la même réponse du point de vue de l'analyse. 

La fonction KNN classifie les points de données en calculant la distance euclidienne entre les points. C'est un calcul mathématique exigeant des chiffres. Toutes les variables de KNN doivent donc être contraignantes pour les calculs. 

La préparation des données pour KNN implique souvent trois tâches:
(1) Fixer toutes les valeurs NA ou ""
(2) Convertissez tous les facteurs en un ensemble de booléens, un pour chaque niveau du facteur.
(3) Normalisez les valeurs de chaque variable dans la plage 0: 1 de sorte qu'aucune plage de variable n'ait un impact excessivement grand sur la mesure de distance. 

11
SpiritusPrana

Je voudrais également souligner que la fonction semble échouer lorsqu’on utilise des entiers. J'avais besoin de tout convertir en "num" avant d'appeler la fonction knn. Cela inclut la fonctionnalité cible, dont la plupart des méthodes dans R utilisent le type de facteur. Ainsi, as.numeric (my_frame $ target_feature) est requis.

0
Cybernetic