Dans quelle mesure R est-il adapté aux tâches de classification de texte? [fermé]

30

J'essaye d'obtenir jusqu'à la vitesse avec R. Je veux finalement utiliser les bibliothèques R pour faire la classification de texte. Je me demandais simplement quelles sont les expériences des gens en ce qui concerne l'évolutivité de R quand il s'agit de faire une classification de texte.

Je suis susceptible de rencontrer des données dimensionnelles élevées (~ 300k dimensions). Je cherche à utiliser SVM et Random Forest en particulier comme algorithmes de classification.

Les bibliothèques R s'adapteraient-elles à la taille de mon problème?

Merci.

EDIT 1: Juste pour clarifier, mon ensemble de données est susceptible d'avoir 1000-3000 lignes (peut-être un peu plus) et 10 classes.

EDIT 2: Étant donné que je suis très nouveau à R, je demanderai que les affiches soient plus spécifiques dans la mesure du possible. Par exemple, si vous proposez un workflow / pipeline, assurez-vous de mentionner si possible les bibliothèques R impliquées dans chaque étape. Certains pointeurs supplémentaires (vers des exemples, des exemples de code, etc.) seraient la cerise sur le gâteau.

EDIT 3: Tout d'abord, merci à tous pour vos commentaires. Et deuxièmement, je m'excuse, j'aurais peut-être dû donner plus de contexte au problème. Je suis nouveau dans R mais pas tellement dans la classification des textes. J'ai déjà fait un prétraitement (stemming, suppression des mots vides, conversion tf-idf, etc.) sur une partie de mes données en utilisant le paquet tm , juste pour avoir une idée des choses. tm était si lent, même sur environ 200 documents, que je me suis inquiété de l'évolutivité. Ensuite, j'ai commencé à jouer avec FSelector et même cela a été très lent. Et c'est à ce moment-là que j'ai fait mon OP.

EDIT 4: Je viens de penser que j'ai 10 classes et environ ~ 300 documents de formation par classe, et je construis en fait la matrice termXdoc à partir de l'ensemble de la formation, ce qui entraîne une très grande dimensionnalité. Mais que diriez-vous de réduire chaque problème de classification 1 sur k en une série de problèmes de classification binaire? Cela réduirait considérablement le nombre de documents de formation (et donc la dimensionnalité) à chacune des étapes k-1, n'est-ce pas? Cette approche est-elle donc bonne? Comment se compare-t-elle en termes de précision à l'implémentation multi-classes habituelle?

Andy
la source
1
300k dimensions avec combien de lignes? Malheureusement, les objets R doivent être en mémoire (du moins à moins que vous ne songiez à des ajustements majeurs, vous obligeant essentiellement à réécrire ces algorithmes vous-même). Cela signifie qu'avec, disons, 8 Go de RAM, je ne pense pas que vous puissiez stocker plus de quelques centaines de lignes avec 300k colonnes.
crayola
@crayola: le nombre de lignes peut varier de 1000 à 3000.
Andy
2
Les objets R n'ont pas besoin d'être en mémoire. Le mappage de la mémoire est très simple. Les dimensions de 300k ne sont pas un problème. Je suppose également que vos données sont rares, comme c'est le cas avec presque tous les problèmes de texte.
Iterator
Je viens de remarquer le commentaire ci-dessus: seulement 1000-3000 lignes? C'est très petit. Pouvez-vous expliquer quel est votre corpus? Un lot d'emails? Descriptions des packages dans CRAN? Vous pouvez avoir plus de problèmes statistiques avec P >> N qu'avec tout problème de stockage.
Iterator
1
@Iterator: Nous avons quelques ressources pédagogiques (dissertations, essais, etc.) que nous voulons classer.
Andy

Réponses:

17

Comme demandé dans un commentaire, voici quelques conseils pour les étapes de traitement. Un certain nombre d'outils peuvent être trouvés dans la vue des tâches CRAN pour le traitement du langage naturel . Vous pouvez également consulter cet article sur le tmpaquet (text mining) R .

  1. Avant le traitement, envisagez la normalisation des jetons de mot. openNLP(pour lequel il existe un package R) est un itinéraire.
  2. Pour le traitement de texte, une étape courante de prétraitement consiste à normaliser les données via tf.idf- la fréquence du terme * la fréquence inverse du document - voir l'entrée Wikipedia pour plus de détails. Il existe d'autres normalisations plus récentes, mais c'est une méthode du pain et du beurre, il est donc important de la connaître. Vous pouvez facilement l'implémenter dans R: stockez simplement (docID, wordID, freq1, freq2) où freq1 est le nombre de fois où le mot indexé par wordID est apparu dans le document donné et freq2 est le # de documents dans lequel il apparaît. Pas besoin de stocker ce vecteur pour les mots qui n'apparaissent pas dans un document donné. Ensuite, prenez simplement freq1 / freq2 et vous avez votre valeur tf.idf.
  3. Après avoir calculé les valeurs tf.idf, vous pouvez travailler avec la pleine dimensionnalité de vos données ou filtrer les mots qui sont essentiellement non informatifs. Par exemple, n'importe quel mot qui apparaît dans un seul document ne donnera pas beaucoup d'informations. Cela peut réduire considérablement votre dimensionnalité. Étant donné le petit nombre de documents examinés, il se peut que la réduction à seulement 1 000 dimensions soit appropriée.
  4. Je ne recentrerais pas les données (par exemple pour PCA), mais vous pouvez maintenant stocker les données maintenant dans une matrice de termes (où les entrées sont maintenant des valeurs tf.idf) avec facilité, en utilisant les matrices clairsemées, comme le soutient le Matrixpackage.

À ce stade, vous disposez d'un ensemble de données bien prétraité. Je recommanderais de continuer avec les outils cités dans la vue des tâches CRAN ou le package d'exploration de texte. Le regroupement des données, par exemple en projetant sur les 4 ou 6 premières composantes principales, pourrait être très intéressant pour votre groupe lorsque les données sont tracées.

Une autre chose: vous pouvez constater que la réduction de la dimensionnalité selon les principes de l'ACP (*) peut être utile lorsque vous utilisez diverses méthodes de classification, car vous agrégez essentiellement les mots associés. Les 10 à 50 premiers composants principaux peuvent être tout ce dont vous avez besoin pour la classification des documents, compte tenu de la taille de votre échantillon.

(*) Remarque: l'ACP n'est qu'une première étape. Cela peut être très intéressant pour quelqu'un qui débute avec l'exploration de texte et l'ACP, mais vous finirez peut-être par trouver que c'est un peu gênant pour les ensembles de données clairsemés. Dans un premier temps, jetez-y un œil, en particulier via les fonctions prcompet princomp.

Mise à jour: je n'ai pas indiqué de préférence dans cette réponse - je recommande prcompplutôt que princomp.

Itérateur
la source
+1 Belle réponse; Je suis seulement curieux de savoir pourquoi dites-vous qu'un petit nombre de quais implique un nombre inférieur de variables importantes - cela ne semble-t-il pas un peu excessif?
Je ne suis pas sûr de comprendre ce que tu veux dire. Les conserver est certainement sur-ajusté, donc ces variables seraient éliminées dans toute régularisation raisonnable. De plus, le vocabulaire (P) croît avec le nombre de documents ou d'échantillons (N), donc la première fois qu'un terme apparaît n'est pas révélateur de beaucoup. Continuez à ajouter des documents, puis la récurrence d'un terme dans tous les documents deviendra informative.
Iterator
@Iterator: Merci pour votre réponse. Donc prcompet / ou princompva évoluer vers ce type de données que vous estimez? De plus, je viens de modifier ma question et d'ajouter quelques informations supplémentaires.
Andy
Non, ceux-ci ne seront probablement pas mis à l'échelle lorsque vous atteindrez 300 Ko de colonnes. :) (Juste pour souligner: X'X dans ce cas aura 90 entrées - un problème de stockage.) Au lieu de cela, filtrez d'abord par tf.idf. S'il n'y a que, disons, 10 classes distinctes, alors un petit multiple de 10 devrait suffire pour une plus grande dimensionnalité de séparation des classes. Ainsi, 1000 dimensions devraient être plus que suffisantes. Les deux méthodes PCA (en fait, je recommande prcomp) conviendront parfaitement.
Iterator du
Une fois que vous limitez à 1000 dimensions ou peut-être quelques autres (par exemple 2K), et faites PCA, vous pouvez prendre les projections sur disons 100 dimensions (qui peuvent être exagérées, mais il n'y a pas de mal à cela) et ensuite faire la classification. À ce stade, il n'y a rien de trop excitant.
Iterator du
5

Bienvenue d'abord! Le traitement de texte est très amusant, et le faire en R devient toujours plus facile.

La réponse courte: oui - les outils de R sont maintenant assez bons pour gérer ce type de données. En fait, il n'y a rien de spécial à propos de R, C ++, Groovy, Scala ou de tout autre langage en ce qui concerne le stockage de données dans la RAM: chaque langue stocke un flottant double de 8 octets dans ... attendez ... attendez. .. 8 octets!

Les algorithmes et leur implémentation sont importants, surtout s'ils sont très mal implémentés en ce qui concerne les structures de données et la complexité de calcul. Si vous implémentez vos propres algorithmes, faites attention. Si vous utilisez un autre code, caveat emptor s'applique, comme il le fait dans n'importe quel environnement.

Pour R, vous devrez considérer:

  1. Votre représentation des données (regardez les matrices clairsemées, en particulier dans le Matrixpackage)
  2. Stockage de données (peut-être mappé en mémoire, en utilisant bigmemoryou ff; ou distribué, en utilisant Hadoop)
  3. Votre partitionnement des données (combien pouvez-vous tenir dans la RAM dépend de la quantité de RAM que vous avez)

Le dernier point est vraiment sous votre contrôle.

En ce qui concerne cette dimensionnalité, elle n'est plus particulièrement grande. Le nombre d'observations aura plus d'impact, mais vous pouvez partitionner vos données pour les ajuster à l'utilisation de la RAM, donc il n'y a pas vraiment de quoi s'inquiéter.

Itérateur
la source
3

Je suis d'accord avec crayola que le nombre de lignes est crucial ici. Pour RF, vous aurez besoin d'au moins 3 fois plus de RAM que le poids de votre jeu de données et probablement beaucoup de temps (un tel nombre d'attributs nécessite généralement beaucoup d'arbres dans la forêt - et notez qu'il n'y a pas d'implémentation parallèle de RF dans R).

À propos de SVM, je doute que ce soit une bonne idée de se battre avec des dimensions de 300k alors que vous pouvez probablement développer une fonction de noyau qui sera équivalente à vos descripteurs de texte.

EDIT: la matrice 3k x 30k (réelle) occuperait quelque chose comme 7 Go, donc tout ce dont vous avez besoin pour faire des RF (en utilisant randomForest) sur ces données est un ordinateur avec 16 Go de RAM, un peu de chance et pas mal de temps ou juste un ordinateur avec 24 Go RAM et pas mal de temps.


la source
Eh bien, j'allais certainement faire une sélection de fonctionnalités (chi carré, basé sur l'entropie) mais encore une fois, je n'ai pas pu trouver de bibliothèque R à l'échelle pour cette tâche non plus. Compte tenu de tout cela, est-il exact de dire alors que je devrais peut-être commencer à chercher des solutions non R?
Andy
1
"notez qu'il n'y a pas d'implémentation parallèle de RF dans R". Ce n'est que partiellement correct, car le foreachpackage fonctionne bien avec le randomForestpackage. Je pense qu'il y a un tel exemple dans la vignette pour foreach. (Ou peut-être doMC.)
crayola
@Andy Le problème est que, à moins de réécrire les algorithmes dans un langage de programmation de bas niveau, je ne sais pas quel logiciel sera en mesure d'appliquer ces algorithmes à vos données. Si j'étais dans votre situation, je suppose que je m'en tiendrais à R et réécrirais des parties de randomForesttelle sorte qu'il interrogerait les colonnes choisies au hasard, par exemple, dans une base de données SQL à chaque itération (de sorte que l'ensemble des dimensions de 300k n'aurait jamais être dans le bélier). Mais c'est probablement principalement parce que j'en sais plus sur R que sur les autres options possibles.
crayola
Que voulez-vous dire précisément en affirmant que vous n'avez pas pu trouver une bibliothèque adaptée à cela? Des filtres comme celui-ci sont une algèbre de base, ils devraient fonctionner sans problème (à condition d'avoir suffisamment de RAM).
@crayola C'est vrai, mais la partie qui fusionne est horrible. De plus, il ne s'agit pas d'un parallélisme de mem-shared, donc ce serait probablement douloureux (sinon impossible) dans ce contexte.