Tabla de Contenidos
Trabajo Práctico 1 - Modelado de Lenguaje
(volver a la página principal)
En este trabajo práctico implementaremos varios modelos de lenguaje y realizaremos algunos experimentos con ellos.
- Fecha de entrega:
- Ejercicios 1 al 5: 13/04 a las 23:59.
- Ejercicios 6,7,8: 20/04 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 languagemodeling
.
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
- Elegir corpus de texto en lenguaje natural de más de 5Mb de tamaño.
- Cargar el corpus usando un “corpus reader” de NLTK (e.g.
PlaintextCorpusReader
) o definiendo uno propio.- El “corpus reader” debe proveer un método
sents
que permita iterar sobre las oraciones tokenizadas del corpus.
- Revisar a ojo la correcta tokenización y segmentado en oraciones. De ser necesario, probar otras formas de tokenización/segmentado.
- Modificar el script
train.py
para utilizar nuestro corpus.
Documentación:
- Ejemplo dado en clase de cómo tokenizar con expresiones regulares: http://nbviewer.ipython.org/url/cs.famaf.unc.edu.ar/~francolq/Tokenizaci%C3%B3n%20con%20NLTK.ipynb
Ejercicio 2: Modelo de n-gramas
Implementar un modelo de n-gramas con marcadores de comienzo y fin de oración
(<s>
y </s>
).
Interfaz de la clase NGram
(en ngram.py
):
class NGram: def __init__(self, n, sents): """ n -- order of the model. sents -- list of sentences, each one being a list of tokens. """ def count(self, tokens): """Count for an n-gram or (n-1)-gram. tokens -- the n-gram or (n-1)-gram tuple. """ def cond_prob(self, token, prev_tokens=None): """Conditional probability of a token. token -- the token. prev_tokens -- the previous n-1 tokens (optional only if n = 1). """ def sent_prob(self, sent): """Probability of a sentence. Warning: subject to underflow problems. sent -- the sentence as a list of tokens. """ def sent_log_prob(self, sent): """Log-probability of a sentence. sent -- the sentence as a list of tokens. """
Tests:
$ nosetests languagemodeling/tests/test_ngram.py
Ejercicio 3: Generación de Texto
- Implementar en
ngram.py
una claseNGramGenerator
para generar oraciones de lenguaje natural. - Programar un script
generate.py
para cargar un modelo de n-gramas y generar oraciones con él. - Generar oraciones usando n-gramas con n en {1, 2, 3, 4}. Armar una figura similar a la Figura 4.3 de Jurafsky & Martin (2008). Incluirla en el README.
Funciones a implementar en ngram.py
:
class NGramGenerator: def __init__(self, model): """ model -- n-gram model. """ def generate_sent(self): """Randomly generate a sentence.""" def generate_token(self, prev_tokens=None): """Randomly generate a token, given prev_tokens. prev_tokens -- the previous n-1 tokens (optional only if n = 1). """
Interfaz de generate.py
:
$ python languagemodeling/scripts/generate.py --help Generate natural language sentences using a language model. Usage: generate.py -i <file> -n <n> generate.py -h | --help Options: -i <file> Language model file. -n <n> Number of sentences to generate. -h --help Show this screen.
Tests:
$ nosetests languagemodeling/tests/test_ngram_generator.py
Documentación:
Ejercicio 4: Suavizado "add-one"
- Implementar el suavizado “add-one” en
ngram.py
en una claseAddOneNGram
. - La clase debe tener la misma interfaz que
NGram
más el métodoV
especificado abajo. - Calcular V como el tamaño del alfabeto incluyendo el marcador
</s>
. - Agregar al script de entrenamiento (train.py) una opción de línea de comandos que permita utilizar add-one en lugar de n-gramas clásicos.
- Entrenar sobre nuestro corpus y guardar los modelos resultantes para varios valores de n (1, 2, 3 y 4).
Interfaz de la clase AddOneNGram
(en ngram.py
):
class AddOneNGram: """ Todos los métodos de NGram. """ def V(self): """Size of the vocabulary. """
Nueva interfaz de train.py
:
$ python languagemodeling/scripts/train.py --help Train an n-gram model. Usage: train.py -n <n> [-m <model>] -o <file> train.py -h | --help Options: -n <n> Order of the model. -m <model> Model to use [default: ngram]: ngram: Unsmoothed n-grams. addone: N-grams with add-one smoothing. -o <file> Output model file. -h --help Show this screen.
Tests:
$ nosetests languagemodeling/tests/test_addone_ngram.py
Ejercicio 5: Evaluación de Modelos de Lenguaje
- Separar el corpus en entrenamiento y test (90% y 10% resp.).
- Implementar el cálculo de log-probability, cross-entropy y perplejidad.
- Programar un script
eval.py
para cargar un modelo de lenguajes y evaluarlo sobre el conjunto de test. - Calcular perplejidad de los modelos entrenados en el ejercicio anterior. Reportar los resultados en el README.
Interfaz de eval.py
:
$ python languagemodeling/scripts/eval.py --help Evaulate a language model using the test set. Usage: eval.py -i <file> eval.py -h | --help Options: -i <file> Language model file. -h --help Show this screen.
Ejercicio 6: Suavizado por Interpolación
- Implementar el suavizado por interpolación en
ngram.py
en una claseInterpolatedNGram
. - Calcular lambdas en términos de un único parámetro gamma (ver documentación abajo).
- Usar add-one para el nivel más bajo (unigramas).
- Usar datos held-out (un 10% de train) y barrido para elegir valor para gamma.
- Agregar al script de entrenamiento (train.py) una opción de línea de comandos que permita utilizar este modelo.
- Calcular y reportar perplejidad para varios valores de
n
(1, 2, 3 y 4). Reportar los resultados en el README.
Interfaz de la clase InterpolatedNGram
(en ngram.py
):
class InterpolatedNGram: def __init__(self, n, sents, gamma=None, addone=True): """ n -- order of the model. sents -- list of sentences, each one being a list of tokens. gamma -- interpolation hyper-parameter (if not given, estimate using held-out data). addone -- whether to use addone smoothing (default: True). """ """ Todos los métodos de NGram. """
Tests:
$ nosetests languagemodeling/tests/test_interpolated_ngram.py
Documentación:
Ejercicio 7: Suavizado por Back-Off con Discounting
- Implementar el suavizado por back-off con discounting en
ngram.py
en una claseBackOffNGram
. - Usar add-one para el nivel más bajo (unigramas).
- Usar datos held-out (un 10% de train) y barrido para elegir valor para beta.
- Agregar al script de entrenamiento (train.py) una opción de línea de comandos que permita utilizar este modelo.
- Calcular y reportar perplejidad para varios valores de
n
(1, 2, 3 y 4). Reportar los resultados en el README.
Interfaz de la clase BackOffNGram
(en ngram.py
):
class BackOffNGram: def __init__(self, n, sents, beta=None, addone=True): """ Back-off NGram model with discounting as described by Michael Collins. n -- order of the model. sents -- list of sentences, each one being a list of tokens. beta -- discounting hyper-parameter (if not given, estimate using held-out data). addone -- whether to use addone smoothing (default: True). """ """ Todos los métodos de NGram. """ def A(self, tokens): """Set of words with counts > 0 for a k-gram with 0 < k < n. tokens -- the k-gram tuple. """ def alpha(self, tokens): """Missing probability mass for a k-gram with 0 < k < n. tokens -- the k-gram tuple. """ def denom(self, tokens): """Normalization factor for a k-gram with 0 < k < n. tokens -- the k-gram tuple. """
Tests:
$ nosetests languagemodeling/tests/test_backoff_ngram.py
Documentación:
- Discounting Methods - Part I (Michael Collins, Columbia University)
- Discounting Methods - Part II (Michael Collins, Columbia University)
Ejercicio 8 (punto bonus): Reordenamiento de Palabras ó Atribución de Autoría
- Elegir y resolver uno de los dos ejercicios siguientes de Jurafsky & Martin (2008):
- Ejercicio 4.9: Reordenamiento de palabras.
- Ejercicio 4.10: Atribución de autoría (Stylometry).
- Sobre el ejercicio 4.9:
- Implementar una clase que, dada una lista de palabras desordenadas de una oración, devuelva el ordenamiento más probable de acuerdo a un modelo de lenguaje.
- Implementar un script que tome el conjunto de test y para cada oración, la desordene y la vuelva a ordenar usando un modelo de lenguaje dado como parámetro.
- Usar las métricas BLEU y distancia de edición para evaluar la calidad de los reordenamientos (respecto de las oraciones originales). En NLTK:
nltk.metrics.distance.edit_distance
nltk.align.bleu_score.bleu
- Sobre el ejercicio 4.10:
- Se requiere tener documentos de dos o más clases diferentes. Por ejemplo, escritos de dos autores diferentes.
- Definir conjuntos de entrenamiento y test para cada clase (90% y 10% resp.).
- Entrenar un modelo de lenguaje para cada clase, siguiendo las indicaciones del libro.
- Implementar un script que tome los conjuntos de test y adivine a qué clase corresponde cada uno.