Clasificación de Documentos en Categorías


Tengo alrededor de 300k documentos almacenados en una base de datos Postgres que están etiquetados con categorías de temas (hay alrededor de 150 categorías en total). Tengo otros 150k documentos que aún no tienen categorías. Estoy tratando de encontrar la mejor manera de categorizarlos programáticamente.

He estado explorando NLTK y su Ingenuo Clasificador Bayes. Parece un buen punto de partida (si puedes sugerir un algoritmo de clasificación mejor para esta tarea, soy todo oídos).

Mi problema es que no tengo suficiente RAM para entrenar al NaiveBayesClassifier en todos los documentos de 150 categoies / 300k a la vez (el entrenamiento en 5 categorías usó 8GB). Además, la precisión del clasificador parece disminuir a medida que entreno en más categorías (90% de precisión con 2 categorías, 81% con 5, 61% con 10).

¿Debo entrenar a un clasificador en 5 categorías a la vez y ejecutar todos los documentos de 150k a través del clasificador para ver si hay coincidencias? Parece que esto funcionaría, excepto que habría ser un montón de falsos positivos donde los documentos que realmente no coinciden con ninguna de las categorías obtener zapato-cuernos en por el clasificador solo porque es el mejor partido disponible... ¿Hay alguna manera de tener una opción "ninguna de las anteriores" para el clasificador en caso de que el documento no encaje en ninguna de las categorías?

Aquí está mi clase de prueba http://gist.github.com/451880

Author: erikcw, 2010-06-24

3 answers

Debe comenzar por convertir sus documentos en vectores TF-log(1 + IDF) : las frecuencias de los términos son escasas, por lo que debe usar dict de python con términos como claves y contar como valores y luego dividir por conteo total para obtener las frecuencias globales.

Otra solución es usar el abs(hash(term)) por ejemplo como claves enteras positivas. Entonces usa scipy.vectores dispersos que son más útiles y más eficientes para realizar operaciones de álgebra lineal que python dict.

También construya los vectores de 150 frecuencias promediando las frecuencias de todos los documentos etiquetados que pertenecen a la misma categoría. Luego, para etiquetar un nuevo documento, puede calcular la similitud del coseno entre el vector del documento y cada vector de categoría y elegir la categoría más similar como etiqueta para su documento.

Si esto no es lo suficientemente bueno, entonces debe tratar de entrenar un modelo de regresión logística utilizando una penalización L1 como se explica en este ejemplo de scikit-learn (este es un envoltorio para liblinear como lo explica @ephes). Los vectores utilizados para entrenar su modelo de regresión logística deben ser los vectores TD-log(1+IDF) previamente introducidos para obtener un buen rendimiento (precisión y recuperación). El scikit learn lib ofrece un sklearn.módulo de métricas con rutinas para calcular esas puntuaciones para un modelo y un conjunto de datos determinados.

Para conjuntos de datos más grandes: debe probar el vowpal wabbit que es probablemente el conejo más rápido en la tierra para problemas de clasificación de documentos a gran escala (pero no es fácil de usar python wrappers AFAIK).

 32
Author: ogrisel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-09 16:32:58

¿Qué tamaño (número de palabras) tienen sus documentos? El consumo de memoria a 150K trainingdocs no debería ser un problema.

Naive Bayes es una buena opción, especialmente cuando tiene muchas categorías con solo unos pocos ejemplos de entrenamiento o datos de entrenamiento muy ruidosos. Pero en general, las máquinas de Vectores de Soporte lineal funcionan mucho mejor.

¿Su problema es multiclase (un documento pertenece exclusivamente a una categoría) o multilabel (un documento pertenece a una o más categorías)?

La precisión es una mala elección para juzgar el rendimiento del clasificador. En su lugar, debe usar precisión vs recuperación, punto de equilibrio de recuperación de precisión (prbp), f1, auc y tener que mirar la curva de precisión vs recuperación donde la recuperación (x) se representa contra la precisión (y) en función del valor de su umbral de confianza (ya sea que un documento pertenezca a una categoría o no). Por lo general, construiría un clasificador binario por categoría (ejemplos de entrenamiento positivos de una categoría frente a todos los demás ejemplos de entrenamiento que no pertenecen a su categoría actual). Tendrás que elegir un umbral de confianza óptimo por categoría. Si desea combinar esas medidas individuales por categoría en una medida de rendimiento global, tendrá que micro (resumir todos los verdaderos positivos, falsos positivos, falsos negativos y verdaderos negativos y puntuaciones combinadas de calc) o macro (puntuación de calc por categoría y luego promediar esas puntuaciones en todas las categorías) promedio.

Tenemos un corpus de decenas de millones de documentos, millones de ejemplos de formación y miles de categorías (multilabel). Dado que nos enfrentamos a serios problemas de tiempo de entrenamiento (el número de documentos nuevos, actualizados o eliminados por día es bastante alto), utilizamos una versión modificada de liblinear. Pero para problemas más pequeños usar uno de los wrappers de python alrededor de liblinear (liblinear2scipy o scikit-learn) debería funcionar bien.

 11
Author: ephes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-24 20:45:05

Hay una manera de tener un "ninguno de los arriba " opción para el clasificador solo en caso de que el documento no encaje en ninguna de las categorías?

Puede obtener este efecto simplemente teniendo una pseudo-categoría "ninguna de las anteriores" entrenada cada vez. Si el máximo que puedes entrenar es de 5 categorías (aunque no estoy seguro de por qué está consumiendo tanta RAM), entrena 4 categorías reales de sus documentos 2K reales cada una, y una "ninguna de las anteriores" con sus documentos 2K tomados aleatoriamente de todas las otras 146 categorías (aproximadamente 13-14 de cada una si desea el enfoque de "muestreo estratificado", que puede ser más sólido).

Todavía se siente como un poco de un kludge y usted podría estar mejor con un enfoque completamente diferente find encontrar una medida doc multidimensional que define sus 300K documentos pre-etiquetados en 150 clústeres razonablemente separables, a continuación, simplemente asignar cada uno de los otros documentos aún no etiquetados al clúster apropiado como se determina de esta manera. No creo que NLTK tenga cualquier cosa directamente disponible para apoyar este tipo de cosas, pero, oye, NLTK ha estado creciendo tan rápido que bien puede que me haya perdido algo...;-)

 2
Author: Alex Martelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-24 20:42:55