civio / verba

Explora los Telediarios de RTVE desde 2014
https://verba.civio.es
GNU Affero General Public License v3.0
31 stars 5 forks source link

Clasificar textos en categorías (topic classification) #12

Open dcabo opened 5 years ago

dcabo commented 5 years ago

Queremos clasificar cada bloque de texto en categorías, en función de su contenido.

En este punto no tenemos del todo claro la granularidad de la clasificación: es decir, ¿queremos decir simplemente "política" y "deporte", o queremos/podemos decir "caso Gürtel" y "Champions League"/"fútbol"? En teoría parecería que cuanto más detalle mejor, pero es posible que llegar a ese nivel requiera hacer cosas más elaboradas, como sacar la lista de etiquetas de la web de RTVE. Para empezar, lo mejor parece hacer unas primeras pruebas clasificando por áreas generales y luego vamos viendo.

Hay una cierta inter-dependencia entre esto y lo de la segmentación de la transcripción (#7): para que el topic modelling funcione bien es posible que haga falta tener bloques medianamente extensos, pero a la vez es posible que la segmentación funcione mejor si podemos clasificar los fragmentos (si dos fragmentos hablan del mismo tema los podemos unir). No sabemos aún cual es la mejor forma de organizar esto, hay que hacer pruebas.

Algunos enlaces sobre creación de modelos de clasificación en Flair:

dcabo commented 4 years ago

Como comento en #23, lo que hace gente como Vox es usar bloques fijos de 15 segundos. Podemos empezar por ahí para probar cómo de bien funciona la categorización (porque está claro que a nivel de sentencia va a ser imposible que acierte), y según lo que salga vemos.

dcabo commented 4 years ago

Tengo una primera versión de un modelo de clasificación en el repo telelediario. He hecho unas primeras pruebas con un corpus pequeño (2000 noticias) y a veces funciona:

$ python3 test.py "Las encuestas dan 178 escaños a Pedro Sánchez"
[Elecciones (0.37633806467056274)]

$ python3 test.py "MasterChef sigue siendo lider de audiencia todas las noches"
[Comunicación-RTVE (0.261417418718338)]

$ python3 test.py 'El Real Madrid, nuevo campeón de Europa gracias a Zidane.'
[Fútbol (0.7414063215255737)]

He hecho unas primeras pruebas usando el ejemplo de entrenamiento básico de Flair con los embeddings de BERT:

EPOCH   TIMESTAMP   BAD_EPOCHS  LEARNING_RATE   TRAIN_LOSS  DEV_LOSS    DEV_PRECISION   DEV_RECALL  DEV_F1
1   18:14:12    0   0.1000  3.4310358875202684  2.7845988273620605  0.2193  0.2203  0.2198
2   18:17:08    0   0.1000  2.589394747086291   2.1581220626831055  0.4123  0.4141  0.4132
3   18:20:10    1   0.1000  2.132350602239933   3.4886841773986816  0.1974  0.1982  0.1978
4   18:23:01    0   0.1000  1.8675508319206957  2.0329349040985107  0.4825  0.4846  0.4835
5   18:26:06    0   0.1000  1.6731717181655597  1.6564441919326782  0.5307  0.533   0.5318
6   18:29:02    1   0.1000  1.5272935763844904  1.6470911502838135  0.5088  0.511   0.5099
7   18:32:11    0   0.1000  1.334731230195963   1.340096116065979   0.5921  0.5947  0.5934
8   18:35:16    1   0.1000  1.2472548541033044  1.6981245279312134  0.5044  0.5066  0.5055
9   18:38:15    0   0.1000  1.2092748481147695  1.5045700073242188  0.6009  0.6035  0.6022
10  18:41:18    1   0.1000  1.078577993051061   1.8205885887145996  0.4825  0.4846  0.4835

Y BERT + Flair:

EPOCH   TIMESTAMP   BAD_EPOCHS  LEARNING_RATE   TRAIN_LOSS  DEV_LOSS    DEV_PRECISION   DEV_RECALL  DEV_F1
1   18:49:23    0   0.1000  3.4596951435197076  3.9939112663269043  0.0658  0.0661  0.0659
2   18:53:19    0   0.1000  2.6823639577289797  2.7456209659576416  0.25    0.2511  0.2505
3   18:57:16    0   0.1000  2.2574026022317275  2.417908191680908   0.3114  0.3128  0.3121
4   19:01:30    0   0.1000  1.9070523572417926  1.9924359321594238  0.4781  0.4802  0.4791
5   19:05:42    0   0.1000  1.7100887388553259  1.5674718618392944  0.5132  0.5154  0.5143
6   19:09:55    0   0.1000  1.5516143452446416  1.6284558773040771  0.5219  0.5242  0.523
7   19:14:01    1   0.1000  1.3996716704008714  1.721571922302246   0.5088  0.511   0.5099
8   19:18:02    2   0.1000  1.281477393406742   2.301140546798706   0.4254  0.4273  0.4263
9   19:22:12    3   0.1000  1.2047091103949636  1.7832567691802979  0.5132  0.5154  0.5143
10  19:26:10    4   0.1000  1.0799569363863963  1.7839747667312622  0.4868  0.489   0.4879

Es poco entrenamiento, 10 epochs, menos de una hora en mi portátil, y llegamos a F1=0.6, que no es la hostia, pero bueno, es el principio. Aún hay muchas cosas que decidir de cara a optimizar esto:

La idea ahora sería:

dcabo commented 4 years ago

Tenemos 40K artículos descargados de RTVE. Quitando los que no son en castellano y algunas categorías que no tienen sentido ("PLAYZ") o que son confusas ("Radio", "Televisión"), tenemos un corpus ahora de 31 276 artículos.

Por empezar con lo más sencillo, vamos a entrenar al modelo para reconocer solo Noticias, Deportes y RTVE (novedades sobre RTVE en sí). Usando solo BERT, y una sola epoch, que ahora tarda casi una hora, alcanzamos ahora un F1 de 0.95, porque es mucho más sencillo:

MICRO_AVG: acc 0.8967 - f1-score 0.9455
MACRO_AVG: acc 0.8796 - f1-score 0.9355666666666668
Deportes   tp: 658 - fp: 23 - fn: 61 - tn: 2269 - precision: 0.9662 - recall: 0.9152 - accuracy: 0.8868 - f1-score: 0.9400
Noticias   tp: 1743 - fp: 69 - fn: 86 - tn: 1113 - precision: 0.9619 - recall: 0.9530 - accuracy: 0.9183 - f1-score: 0.9574
RTVE       tp: 446 - fp: 72 - fn: 17 - tn: 2476 - precision: 0.8610 - recall: 0.9633 - accuracy: 0.8336 - f1-score: 0.9093

Esto es "demasiado fácil", hay que añadir más detalle a las categorías, pero es suficientemente interesante como para probarlo con los datos reales, las transcripciones de los Telediarios.

dcabo commented 4 years ago

Hemos estado un par de días haciendo pruebas varias para ver el rendimiento del entrenamiento de modelos en distintos entornos. Ahora que tenemos unas ideas básicas del coste de todo esto y de distintas opciones, la idea es seguir mejorando el modelo y aplicándolo a lo que realmente queremos clasificar: los subtítulos.

rafaharo commented 4 years ago

Buenas @dcabo . Veo que lo que habéis llamado en esta issue "Topic Modelling" es más bien una clasificación por categorías. Sin embargo, creo que en lo que consiste formalmente el Topic Modelling también podría ser de interés en este proyecto. De hecho se suele usar cuando no tienes un conjunto de categorías predefinidas para la clasificación o cuando quieres ver como se agrupan semánticamente los términos en tu corpus de texto.

En python hay una librería clásica que se llama gensim con la que se puede experimentar de forma relativamente sencilla. Os dejo un enlace a un post en el que lo usan para que tengáis un ejemplo de lo que se puede obtener a partir de un proceso de Topic Modelling:

https://medium.com/@armandj.olivares/topic-modeling-on-spanish-text-f7a5e998fb90

Si lo veis de interés os podría ayudar a montar esto.

dcabo commented 4 years ago

@rafaharo en efecto, inicialmente yo -novato en PLN- lo llamaba a todo "topic modelling", así en general. Luego, pensando, y viendo que iba a ser más útil clasificar en función de categorías pre-existentes (las que usan los periodistas en general, y los que publican en la web de RTVE en particular), vi que era más correcto decir "topic classification".

Yo estoy de viaje el resto de la semana, pero en cuanto tenga un momento publico los datos originales en crudo para que haya un corpus sobre el que trabajar, y me leo el artículo que enlazas. Mi miedo -sin haberlo leido- es que salgan clusters que no sean fácilmente "entendibles". Cuando lo lea te digo.

anavaldi commented 4 years ago

Tu miedo (@dcabo ) es totalmente cierto. No he conocido a nadie que utilice LDA y le salgan unos temas (listas de palabras) intuitivos de agrupar...

davidhguerrero commented 4 years ago

Hace casi tres años trabaje con LDA estos temas, percisamente con gensim. Se crearon modelos y con los que se consiguieron tasas entorno 60% para un conjuntos de textos cientificos.

El ajuste de los parámetros de LDA se hizo por tanteo con el conjunto de muestras que se disponia =)

rafaharo commented 4 years ago

Es un experimento relativamente sencillo de llevar a cabo en plan baseline y puede dar resultados interesantes. Igualmente aunque no sea para clasificar te puede servir para otras tareas como agrupación.

dcabo commented 4 years ago

Comentar aquí (porque es el issue más popular y le llega a distinta gente) que he publicado una primera versión del corpus con todo el contenido en #96. (Tengo pendiente además abrir el código que descargar y parte los subtítulos, en #95.) En unos días haremos esto más oficial, subiremos los datos a la web de Datos Civio y tal, pero quería avisaros aquí por si alguno tenéis comentarios para que sea más útil. Si tenéis sugerencias / peticiones / dudas, hacedlas en #96 please, y veo si son factibles.