Tabla de Contenidos
Trabajo Práctico 2 - Etiquetado de Secuencias
(volver a la página principal)
En este trabajo práctico implementaremos varios modelos de etiquetado de secuencias y realizaremos algunos experimentos con ellos.
- Repositorio: https://github.com/PLN-FaMAF/PLN-UBA2018.
- Fecha de entrega: 22/02 a las 23:59.
Instrucciones
El código base para el proyecto se encuentra en el repositorio de la materia. La entrega del proyecto es a través de github. Por lo tanto, deben hacer un “fork” del repositorio dentro de sus cuentas de github.
Además del código fuente, deben elaborar un README con una breve explicación de lo que hicieron en cada ejercicio. El README puede estar en texto plano (txt), markdown (md) o restrucured text (rst), y debe estar incluído dentro de la carpeta tagging
.
Criterios de Evaluación:
- Estilo de codificación (chequeado con flake8 y a ojo).
- Diseño del código: uso de clases, herencia, etc.
- Uso y aprobación de tests (provistos y definidos por uds.).
- Uso apropiado de git (commits granulares, logs informativos).
- Resultados.
- README.
Ejercicio 1: Corpus AnCora: Estadísticas de etiquetas POS
Programar un script stats.py
que muestre la siguiente información del corpus:
- Estadísticas básicas:
- Cantidad de oraciones.
- Cantidad de ocurrencias de palabras.
- Cantidad de palabras (vocabulario).
- Cantidad de etiquetas (vocabulario de tags).
- Etiquetas más frecuentes: Una tabla con las 10 etiquetas más frecuentes y la siguiente información para cada una:
- Cantidad de veces que aparece (frecuencia), y porcentaje del total.
- Cinco palabras más frecuentes con esa etiqueta.
- En el README, agregar a mano una breve descripción del significado de la etiqueta.
- Niveles de ambigüedad de las palabras: Una figura similar a la Figura 5.10 de Jurafsky & Martin (2008). Para cada nivel de ambigüedad (de 1 a 9) mostrar:
- Cantidad de palabras y porcentaje del total.
- Cinco palabras más frecuentes.
- Incluir todas las estadísticas en el README.
Uso del script:
$ python tagging/scripts/stats.py
Documentación:
Ejercicio 2: Baseline Tagger
- Programar un etiquetador baseline, que elija para cada palabra su etiqueta más frecuente observada en entrenamiento.
- Para las palabras desconocidas, devolver la etiqueta 'nc0s000' (nombre común singular).
- Entrenar y evaluar el modelo baseline del ejercicio anterior. Reportar los resultados en el README.
- Bonus: Graficar la matriz de confusión como un mapa de calor (ver documentación abajo).
Interfaz de BaselineTagger
en baseline.py
:
class BaselineTagger: def __init__(self, n, tagged_sents): """ tagged_sents -- training sentences, each one being a list of pairs. """ def tag(self, sent): """Tag a sentence. sent -- the sentence. """ def tag_word(self, w): """Tag a word. w -- the word. """ def unknown(self, w): """Check if a word is unknown for the model. w -- the word. """
Tests:
$ nosetests tagging/tests/test_baseline.py
Ejemplo de uso de los scripts:
$ python tagging/scripts/train.py -o baseline $ python tagging/scripts/eval.py -i baseline
Documentación:
Ejercicio 3: Features para Etiquetado de Secuencias
- Implementar en
features.py
los siguientes features básicos:word_lower
: la palabra actual en minúsculas.word_istitle
: la palabra actual empieza en mayúsculas.word_isupper
: la palabra actual está en mayúsculas.word_isdigit
: la palabra actual es un número.
- También implementar los siguientes features paramétricos:
NPrevTags(n)
: la tupla de los últimosn
tags.PrevWord(f)
: Dado un featuref
, aplicarlo sobre la palabra anterior en lugar de la actual.
Interfaz de los features paramétricos en features.py
:
class NPrevTags(Feature): def __init__(self, n): """Feature: n previous tags tuple. n -- number of previous tags to consider. """ def _evaluate(self, h): """n previous tags tuple. h -- a history. """ class PrevWord(Feature): def __init__(self, f): """Feature: the feature f applied to the previous word. f -- the feature. """ def _evaluate(self, h): """Apply the feature to the previous word in the history. h -- the history. """
Tests:
$ nosetests tagging/tests/test_features.py
Documentación:
Ejercicio 4: Maximum Entropy Markov Models
- Implementar un MEMM con el siguiente pipeline de scikit-learn:
- Vectorizador (
featureforge.vectorizer.Vectorizer
) con los features definidos en el ejercicio anterior. - Clasificador de máxima entropía (
sklearn.linear_model.LogisticRegression
).
- Implementar un algoritmo de tagging en el método
tag
usando beam inference con un beam de tamaño 1. - Agregar al script de entrenamiento (train.py) una opción de línea de comandos que permita utilizar el MEMM con distintos valores de
n
. - Entrenar y evaluar para varios valores de
n
(1, 2, 3 y 4). - Probar también los siguientes clasificadores:
sklearn.naive_bayes.MultinomialNB
sklearn.svm.LinearSVC
- Reportar los resultados en el README. Reportar también tiempo de evaluación.
- Bonus: Inventar y agregar features que mejoren la calidad del tagger.
Interfaz de MEMM
en memm.py
:
class MEMM: def __init__(self, n, tagged_sents): """ n -- order of the model. tagged_sents -- list of sentences, each one being a list of pairs. """ def sents_histories(self, tagged_sents): """ Iterator over the histories of a corpus. tagged_sents -- the corpus (a list of sentences) """ def sent_histories(self, tagged_sent): """ Iterator over the histories of a tagged sentence. tagged_sent -- the tagged sentence (a list of pairs (word, tag)). """ def sents_tags(self, tagged_sents): """ Iterator over the tags of a corpus. tagged_sents -- the corpus (a list of sentences) """ def sent_tags(self, tagged_sent): """ Iterator over the tags of a tagged sentence. tagged_sent -- the tagged sentence (a list of pairs (word, tag)). """ def tag(self, sent): """Tag a sentence. sent -- the sentence. """ def tag_history(self, h): """Tag a history. h -- the history. """ def unknown(self, w): """Check if a word is unknown for the model. w -- the word. """
Tests:
$ nosetests tagging/tests/test_memm.py
Documentación:
- Introducción a scikit-learn para clasificación de textos:
- Beam inference:
- video lecture (ir al minuto 07:10)
Ejercicio 5 (punto bonus): Algoritmo de Viterbi para MEMMs (con Beam)
Implementar el algoritmo de Viterbi para obtener la secuencia de tags de máxima probabilidad de acuerdo a un MEMM:
- Para obtener las probabilidades de los tags, usar el método
predict_proba
si el clasificador lo tiene (e.g.LogisticRegression
yMultinomialNB
). Si no, usar la exponenciación (base 2) del métododecision_function
(e.g.LinearSVC
). - Beam: En cada paso del Viterbi, guardar sólo los
k
taggings más probables, a dondek
es un parámetro de la clase. - Evaluar para varios clasificadores (
LogisticRegression
yLinearSVC
), para varios valores den
(1, 2, 3 y 4), y para varios valores dek
(1, 2 y 3). Reportar los resultados en el README. Reportar también tiempo de evaluación.