python - scikit - sklearn classify text
Clasificando documentos en categorÃas (3)
Tengo alrededor de 300k documentos almacenados en una base de datos de 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 clasificador Naive Bayes. Parece un buen punto de partida (si puedes sugerir un mejor algoritmo de clasificación para esta tarea, soy todo oídos).
Mi problema es que no tengo suficiente RAM para entrenar el NaiveBayesClassifier en los 150 documentos de catego / 300k a la vez (entrenamiento en 5 categorías usadas de 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).
¿Debería entrenar un clasificador en 5 categorías a la vez, y ejecutar todos los 150k documentos a través del clasificador para ver si hay coincidencias? Parece que esto funcionaría, excepto que habría muchos falsos positivos en los documentos que realmente no concuerdan con ninguna de las categorías, y que el clasificador los calificará por el mejor calce disponible ... ¿Hay ¿una forma de tener una opción "ninguna de las anteriores" para el clasificador en caso de que el documento no se ajuste a ninguna de las categorías?
Aquí está mi clase de prueba http://gist.github.com/451880
¿Hay alguna manera de tener una opción "ninguna de las anteriores" para el clasificador en caso de que el documento no se ajuste a ninguna de las categorías?
Puede obtener este efecto simplemente por tener una pseudo-categoría "ninguna de las anteriores" entrenada cada vez. Si el máximo que puede entrenar es de 5 categorías (aunque no estoy seguro de por qué está consumiendo tanta RAM), entrene 4 categorías reales de sus documentos de 2K reales cada una, y una "ninguna de las anteriores" con sus documentos 2K tomado al azar 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 complicado y podría estar mejor con un enfoque completamente diferente: encuentre una medida de doc multidimensional que defina sus documentos preetiquetados 300K en 150 clústeres razonablemente separables, luego simplemente asigne cada uno de los otros -Doblado de documentos al clúster apropiado como así se determina. No creo que NLTK tenga algo directamente disponible para apoyar este tipo de cosas, pero, hey, NLTK ha estado creciendo tan rápido que bien podría haberme perdido algo ... ;-)
¿Qué tan grande (número de palabras) son sus documentos? El consumo de memoria en 150K trainingdocs no debería ser un problema.
Naive Bayes es una buena opción, especialmente cuando tienes muchas categorías con solo algunos ejemplos de entrenamiento o datos de entrenamiento muy ruidosos. Pero, en general, las Máquinas de Vector de Soporte lineal funcionan mucho mejor.
¿Su problema es multiclase (un documento pertenece solo a una categoría de manera exclusiva) o multilable (un documento pertenece a una o más categorías)?
La precisión es una mala elección para juzgar el rendimiento del clasificador. Debería utilizar precisión vs recall, punto de equilibrio de recuperación de precisión (prbp), f1, auc y tener que mirar la curva precisión vs recall donde recall (x) se traza contra precisión (y) basado en el valor de su umbral de confianza (si un documento pertenece a una categoría o no). Por lo general, crearía un clasificador binario por categoría (ejemplos de entrenamiento positivo de una categoría frente a todos los demás modelos de trenes que no pertenecen a su categoría actual). Deberá elegir un umbral de confianza óptimo por categoría. Si desea combinar esas medidas únicas por categoría en una medida de rendimiento global, tendrá que micro (sumar todos los verdaderos positivos, falsos positivos, falsos negativos y negativos verdaderos y calcular los puntajes combinados) o macro (puntuación de calc por categoría y luego promedia esos puntajes en todas las categorías) promedio.
Tenemos un corpus de decenas de millones de documentos, millones de ejemplos de capacitación y miles de categorías (multilabel). Debido a que enfrentamos serios problemas de tiempo de capacitación (la cantidad de documentos nuevos, actualizados o eliminados por día es bastante alta), usamos una versión modificada de liblinear . Pero para problemas menores, el uso de uno de los contenedores de Python alrededor de liblinear ( liblinear2scipy o scikit-learn ) debería funcionar bien.
Debería comenzar convirtiendo sus documentos en vectores TF-log (1 + IDF) : las frecuencias de los términos son escasas, por lo que debe usar el dict de python con el término como claves y contar como valores y luego dividir por recuento total para obtener las frecuencias globales.
Otra solución es usar los abs (hash (term)), por ejemplo, como enteros positivos. Entonces usted usa vectores scipy.sparse que son más útiles y eficientes para realizar operaciones de álgebra lineal que python dict.
También construya los 150 vectores de frecuencias promediando las frecuencias de todos los documentos etiquetados que pertenecen a la misma categoría. Luego, para el nuevo documento para etiquetar, puede calcular la similitud del coseno entre el vector de 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 debes tratar de entrenar un modelo de regresión logística usando una penalización L1 como se explica en este ejemplo de scikit-learn (esto es un contenedor para liblinear según lo explicado por @ephes). Los vectores utilizados para entrenar su modelo de regresión logística deberían ser los vectores TD-log (1 + IDF) introducidos previamente para obtener un buen rendimiento (precisión y recuperación). El scikit learn lib ofrece un módulo sklearn.metrics con rutinas para calcular esos puntajes para un modelo dado y conjunto de datos dado.
Para conjuntos de datos más grandes: debe probar el wabbit vowpal, 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 utilizar los wrappers de pitón AFAIK).