Classer les Documents dans des Catégories
J'ai environ 300k des documents stockés dans une base de données Postgres qui sont marqués avec le thème catégories (il y a environ 150 catégories au total). J'ai une autre 150k documents qui n'ont pas de catégories. J'essaie de trouver la meilleure façon de programmaticly les classer.
J'ai été d'explorer NLTK et son Naïf Classificateur de Bayes. Semble être un bon point de départ (si vous pouvez proposer un meilleur algorithme de classification pour cette tâche, je suis preneuse).
Mon problème est que je n'ai pas assez de RAM pour former le NaiveBayesClassifier sur tous les 150 catégories/300k documents à la fois (formation en 5 catégories utilisées 8GO). En outre, la précision du classificateur semble tomber comme je m'entraîne sur plusieurs catégories (90% de précision avec 2 catégories, 81% avec 5, 61% à 10).
Dois-je juste en train de classificateur en 5 catégories à la fois, et d'exécuter toutes les 150k de documents par le classificateur pour voir si il y a des matches? Il semble que ce serait le travail, sauf qu'il y aurait beaucoup de faux positifs, où les documents qui ne sont pas vraiment correspondre à l'une des catégories d'obtenir chaussure cornes en sur par le classificateur juste parce que c'est le meilleur match de disponible... Est-il un moyen d'avoir un "none of the above" option pour le classificateur juste au cas où le document ne rentre pas dans l'une des catégories?
Voici ma classe de test http://gist.github.com/451880
- Peut-être en ligne/incrémentielle mode de formation permettra de résoudre les problèmes de mémoire: en.wikipedia.org/wiki/Online_machine_learning
Vous devez vous connecter pour publier un commentaire.
Vous devriez commencer par la conversion de vos documents dans TF-log(1 + RI) des vecteurs: terme fréquences sont rares, donc vous devez utiliser python dict à terme que les clés et le comte de valeurs et de diviser par le nombre total pour obtenir le mondial de fréquences.
Une autre solution est d'utiliser l'abs(de hachage(terme)), comme par exemple l'entier positif clés. Ensuite, vous utilisez scipy.éparses vecteurs qui sont plus pratique et plus efficace pour effectuer l'algèbre linéaire fonctionnement de python dict.
Aussi construire des les 150 fréquences de vecteurs en faisant la moyenne des fréquences de toutes marquées de documents appartenant à la même catégorie. Alors pour le nouveau document d'étiquette, vous pouvez calculer l' similarité cosinus entre le document et vecteur de chaque catégorie de vecteur et de choisir la plus de la même catégorie que l'étiquette de votre document.
Si ce n'est pas assez bon, alors, vous devriez essayer de former un modèle de régression logistique à l'aide d'une L1 peine, comme expliqué dans cet exemple de scikit-learn (ce qui est un wrapper pour liblinear comme expliqué par @ephes). Les vecteurs utilisés pour former votre modèle de régression logistique doit être préalablement introduit TD-log(1+RI) vecteurs pour obtenir de bonnes performances (précision et rappel). Le scikit learn lib propose un sklearn.les métriques de module avec les routines de calcul de ces score pour un modèle donné et compte tenu de l'ensemble des données.
Pour les plus grands ensembles de données: essayez-vous à la vowpal wabbit qui est probablement le plus rapide de lapin sur la terre à grande échelle de classification des documents de problèmes (mais pas facile à utiliser python wrappers autant que je sache).
Quelle 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 si vous avez plusieurs catégories, avec seulement quelques exemples de formation ou très bruyant trainingdata. Mais en général, linéaire Machines à Vecteurs de Support font beaucoup mieux.
Est votre problème multiclasse (un document appartient à une seule catégorie exclusif) ou multilabel (un document appartient à une ou plusieurs catégories)?
Précision est un mauvais choix pour juger de la performance du classificateur. Vous devriez plutôt utiliser la précision vs rappel, de précision, de rappel de point d'équilibre (prbp), de f1, de l'asc et de regarder la précision vs rappel de la courbe où le rappel (x) est tracée en fonction de la précision (y) basé sur la valeur de votre confiance-seuil (si un document appartient à une catégorie ou pas). Habituellement, vous devez construire un classificateur binaire par catégorie (positif exemples destinés à la formation d'une catégorie de vs tous les autres trainingexamples qui n'appartiennent pas à votre catégorie actuelle). Vous devrez choisir une optimale seuil de confiance par catégorie. Si vous souhaitez combiner ces mesures par catégorie dans un mondial de la mesure de la performance, vous aurez pour micro (la somme de tous les vrais positifs, faux positifs et faux négatifs vrais négatifs et calc scores combinés) ou macro (calc score par catégorie, puis la moyenne de ces scores sur toutes les catégories) de la moyenne.
Nous disposons d'un corpus de plusieurs dizaines de millions de documents, des millions d'exemples de formation et des milliers de catégories (multilabel). Depuis que nous avons face à de sérieux de la formation les problèmes de temps (le nombre de documents sont nouvelles, mises à jour ou effacées par jour est assez élevé), nous utilisons une version modifiée de liblinear. Mais pour les petits problèmes à l'aide de l'un des wrappers python autour de liblinear (liblinear2scipy ou scikit-learn) devrait fonctionner correctement.
Vous pourriez obtenir cet effet en ayant simplement un "none of the above" pseudo-catégorie formés à chaque fois. Si le max que vous pouvez vous entraîner est de 5 catégories (même si je ne suis pas sûr pourquoi il est de manger beaucoup de RAM), en train 4 véritables catégories de leur 2K docs chacun, et un "none of the above" avec son 2K documents pris au hasard dans toutes les 146 autres catégories (environ 13-14 de chaque si vous voulez que la "méthode d'échantillonnage stratifié" approche, qui peut être sondeur).
Se sent toujours comme un peu de bidouille et vous pourriez être mieux avec une approche complètement différente -- trouver un multi-dimensionnelle doc de mesure qui définit votre 300K pré-étiqueté docs en 150 raisonnablement séparables clusters, alors il suffit d'attribuer à chaque d'autres encore-untagged docs pour le cluster approprié ainsi déterminé. Je ne pense pas que NLTK a tout ce qui est directement disponible pour soutenir ce genre de chose, mais, hé, NLTK a été si rapide que je peut très bien avoir manqué quelque chose...;-)