2017-02-20 1 views
0

J'ai posé cette question sur la liste de diffusion R, mais je pense que c'est un meilleur endroit pour trouver des réponses et des conseils.Traitement des différences dans l'espace des caractéristiques concernant la classification de texte en utilisant SVM

Je travaille actuellement sur la classification de texte des essais de l'étudiant, en essayant pour identifier les textes qui correspondent à une certaine classe ou non. J'utilise des textes de un semestre (A) pour la formation et des textes d'un autre semestre (B) pour tester le classificateur. Mon flux de travail est comme ceci:

  • lire tous les textes de A, construire un DTM (A) avec environ 1387 termes (package tm)
  • lire tous les textes de B, construire un DTM (B) avec environ 626 Conditions
  • former le classificateur avec DTM (a), en utilisant un SVM (package e1071)

maintenant, je veux classer tous les textes en DTM (B) en utilisant le classifyer. Mais lorsque j'essaie d'utiliser predict(), j'obtiens toujours le message d'erreur: Erreur dans eval (expr, envir, enclos): objet 'XY' non trouvé. Comme je l'ai découvert, la raison pour cela est que DTM (A) et DTM (B) ont un nombre différent de termes et par conséquent pas tous les termes utilisés pour l'entraînement du modèle est disponible en DTM (B).

Bien sûr, il est problématique de faire une classification avec deux espaces de caractéristiques différents, mais je veux trouver une solution à ce "problème du monde réel". L'idée est d'identifier si un texte écrit par un étudiant correspond ou non aux autres textes. Donc mon idée naïve est de développer un modèle de prédiction avec des textes d'un semestre [DTM (A)] puis d'utiliser ce modèle pour évaluer un nouveau texte d'un autre semestre [DTM (B)]. Comme le nouveau texte ne figure pas dans le DTM d'origine, les espaces d'entités diffèrent. Jusqu'à présent, je n'ai trouvé que du code qui utilise un DTM créé à partir de tous les textes, mais cela nécessiterait de créer un nouveau DTM (A) `et de réentraîner le SVM à chaque fois.

Ma question est: comment dois-je faire face à cela? Devrais-je faire correspondre les termes utilisés dans le DTM (A) et le DTM (B), afin d'obtenir un espace caractéristique identique? Ceci pourrait être réalisé en réduisant le nombre de termes en DTM (A) ou en ajoutant plusieurs colonnes vides/NA au DTM (B). Ou y at-il une autre solution à mon problème?

Amitiés

Björn

+0

Je suppose que http://stackoverflow.com/questions/39721737/how-to-handle-errors-in-predict-function-of-r peut vous aider. – abhiieor

+0

Merci, mais la publication à laquelle vous avez lié ne concerne pas des espaces de caractéristiques différents, ce qui signifie des colonnes différentes dans le MNT, mais à propos de différents niveaux de variables catégorielles. – PsyR

+0

Vous pouvez généraliser. Aucune méthode d'apprentissage automatique ne peut traiter de nouveaux prédicteurs; ce que vous obtenez essentiellement lorsque vous créez des variables fictives pour une variable catégorielle avec de nouveaux niveaux. Donc essentiellement comme indiqué dans ma réponse, vous devez maintenir une liste des variables qui font partie de la formation et donc du modèle. Filtrer vers le bas vos données de test/prédiction en fonction de cette liste et ensuite aller de l'avant avec la notation sur l'objet formé. – abhiieor

Répondre

0

Après quelques expériences plus et quelques recherches, je suis tombé sur le paquet RTextTools et sa fonction "create_matrix()". Cette fonction crée un nouveau DTM et vous pouvez également ajuster la matrice à la matrice d'origine, qui a été utilisée pour former le modèle. C'était exactement ce que je cherchais. Alors j'ai regardé le code d'origine (https://github.com/timjurka/RTextTools/blob/master/RTextTools/R/create_matrix.R) et est venu avec ceci:

# get all the terms which are in the training df, but not in the test df 
terms <- colnames(train.df[,which(!colnames(train.df) %in% colnames(test.df))]) 
# weight is set, this is just in case that weightTfIdf was used, otherwise it should be 0 
weight <- 0.000000001 
# now create a new matrix with the missing terms 
amat <- matrix(weight, nrow = nrow(test.df), ncol = length(terms)) 
colnames(amat) <- terms 
rownames(amat) <- rownames(test.df) 

# create a new test df with the original values plus the new matrix with the missing terms 
test.df.fixed <- cbind(test.df[,which(colnames(test.df) %in% colnames(train.df))],amat) 
test.df.fixed <- test.df.fixed[, sort(colnames(test.df.fixed))] 

Le résultat est une trame de données de test qui a toutes les caractéristiques (colonnes) de la trame de données qui a été utilisé pour la formation. C'est donc fondamentalement un "up-filtering" au lieu d'un down-filtering. Un test rapide a montré que cela fonctionne assez bien (Précision: .91, Kappa: .88).

0

Dans un environnement réel, vos données de formation et de test sont totalement indépendantes. Cela signifie que vous ne savez rien sur vos documents de test à l'avance. La meilleure façon de résoudre votre problème, dans cet esprit, est de baser les TDM pour l'ensemble de données B sur le vocabulaire utilisé dans l'ensemble de données A (par exemple, ne compter que les mots survenus en A).