Question

J'ai au sujet de 300k documents stockés dans une base de données Postgres qui sont marqués avec les catégories de sujets (il y a environ 150 catégories au total). J'ai un autre 150k documents qui ne sont pas encore des catégories. J'essaie de trouver la meilleure façon de les catégoriser programmaticly.

J'ai exploré NLTK et son Naive Bayes Classifier. On dirait un bon point de départ (si vous pouvez proposer un meilleur algorithme de classification pour cette tâche, je suis toutes les oreilles).

Mon problème est que je n'ai pas assez de RAM pour former le NaiveBayesClassifier sur tous les 150 categoies / 300k documents à la fois (formation sur les 5 catégories utilisées 8 Go). En outre, la précision du classificateur semble tomber comme je train sur plus de catégories (précision de 90% avec 2 catégories, 81% à 5%, 61 à 10).

Devrais-je former juste un classificateur sur 5 catégories à la fois, et d'exécuter tous les documents 150k par le classificateur pour voir s'il y a des matchs? Il semble que cela fonctionne, sauf qu'il y aurait beaucoup de faux positifs où les documents qui ne correspondent pas vraiment l'une des catégories obtiennent cornu chaussure en par le classificateur juste parce qu'il est le meilleur disponible ... correspondance est-il une façon d'avoir un « aucune de ces » option pour le classificateur juste au cas où le document ne correspond pas à l'une des catégories?

Voici ma classe de test http://gist.github.com/451880

Était-ce utile?

La solution

Vous devez commencer par convertir vos documents en TF-log (1 + IDF) vecteurs : fréquences terme sont rares vous devez donc utiliser dict python avec terme clés et compter comme valeurs, puis diviser par nombre total pour obtenir les fréquences mondiales.

Une autre solution consiste à utiliser les abs (hachage (terme)), par exemple en tant que touches de nombres entiers positifs. Ensuite, vous vecteurs scipy.sparse une utilisation qui sont plus pratique et plus efficace pour effectuer l'algèbre linéaire opération que dict python.

construire également des 150 fréquences des vecteurs faisant la moyenne des fréquences de tous les documents marqués appartenant à la même catégorie. Ensuite, pour le nouveau document étiquette, vous pouvez calculer le cosinus similitude entre le vecteur de document et chaque vecteur de catégorie et choisissez la catégorie la plus semblable que l'étiquette de votre document.

Si cela ne suffit pas bon, alors vous devriez essayer de former un modèle de régression logistique utilisant une pénalité L1 comme expliqué dans cet exemple de scikit-learn (ce est une enveloppe pour liblinear comme expliqué par @ephes). Les vecteurs utilisés pour former votre modèle de régression logistique devrait être le TD-log introduit précédemment vecteurs (1 + IDF) pour obtenir de bonnes performances (précision et rappel). Le scikit apprendre offres lib un module sklearn.metrics avec des routines pour calculer les points pour un modèle donné et ensemble de données.

Pour grands ensembles de données: vous devriez essayer vowpal Wabbit qui est probablement le lapin le plus rapide sur terre pour les grands problèmes à l'échelle de classification des documents (mais pas facile à utiliser wrappers python) afaik.

Autres conseils

Quelle est la taille (nombre de mots) sont vos documents? La consommation de mémoire à 150K trainingdocs ne devrait pas être un problème.

Naive Bayes est un bon choix surtout quand vous avez beaucoup de catégories avec seulement quelques exemples de formation ou trainingdata très bruyant. Mais en général, linéaire Support Vector Machines ne font beaucoup mieux.

Votre multiclassent problème (un document appartient uniquement à une catégorie exclusivly) ou multilabel (un document appartient à une ou plusieurs catégories)?

La précision est un mauvais choix à la performance du classificateur juge. Vous devriez plutôt utiliser la précision vs rappel, point de rappel de précision le seuil de rentabilité (RPPR), f1, auc et doivent regarder la précision vs courbe de rappel où le rappel (x) est tracée en fonction de précision (y) en fonction de la valeur de votre confiance seuil (wether un document appartient à une catégorie ou non). Généralement, vous construire un classificateur binaire par catégorie (exemples de formation positifs d'une catégorie contre tous les autres trainingexamples qui ne appartiennent à votre catégorie actuelle). Vous devrez choisir un seuil de confiance optimale par catégorie. Si vous voulez combiner ces mesures individuelles par catégorie dans une mesure de performance globale, vous devrez micro (résumez tous les vrais positifs, les faux positifs, faux négatifs et vrais négatifs et calc scores combinés) ou macro (score calc par catégorie et en moyenne alors ces scores sur toutes les catégories) en moyenne.

Nous avons un corpus de dizaines de millions de documents, des millions d'exemples de formation et des milliers de catégories (multilabel). Étant donné que nous sommes confrontés à de sérieux problèmes de temps de formation (le nombre de documents sont nouveaux, mis à jour ou supprimé par jour est assez élevé), nous utilisons une version modifiée de liblinear . Mais pour les petits problèmes en utilisant l'un des wrappers python autour liblinear ( liblinear2scipy ou scikit-learn ) devraient fonctionner correctement.

  

Est-il possible d'avoir un « aucun des   ci-dessus » option pour le classificateur juste   dans le cas où le document ne correspond pas à   l'une des catégories?

Vous pouvez obtenir cet effet simplement en ayant une « aucune de ces » pseudo-catégorie formés à chaque fois. Si le maximum que vous pouvez former est 5 catégories (bien que je ne sais pas pourquoi il mange jusqu'à tout tellement RAM), former 4 catégories réelles de leurs 2K réels docs chacun, et « aucun de ce qui précède » un avec ses 2K documents prélevés au hasard sur tous les autres catégories 146 (environ 13-14 de chaque si vous voulez l'approche, qui peut être plus solide « échantillonnage stratifié »).

se sent toujours comme un peu bidouille et vous pourriez être mieux avec une approche complètement différente - trouver une mesure doc multi-dimensionnelle qui définit vos 300K docs pré-marqués en 150 groupes raisonnablement séparables, puis juste assigner chacun des les autres documents au cluster approprié encore-untagged ainsi déterminé. Je ne pense pas que NLTK n'a rien directement disponible pour soutenir ce genre de chose, mais, hé, NLTK en croissance a été si vite que je l'ai bien manqué quelque chose ...; -)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top