from nltk.corpus import gutenberg
sents = list(gutenberg.sents('austen-emma.txt'))
Primero vemos cómo imprimir todos los trigramas de una sola oración:
sent = sents[0]
n = 3 # trigramas
for i in range(len(sent) - n + 1):
print(sent[i:i+n])
['[', 'Emma', 'by'] ['Emma', 'by', 'Jane'] ['by', 'Jane', 'Austen'] ['Jane', 'Austen', '1816'] ['Austen', '1816', ']']
Ahora veamos cómo contar los trigramas de todas las oraciones:
from collections import defaultdict
count = defaultdict(int)
for sent in sents:
for i in range(len(sent) - n + 1):
ngram = tuple(sent[i:i+n]) # los diccionarios no pueden guardar listas, pero sí tuplas
count[ngram] += 1
# count
El código sirve para n-gramas en general.
Tareas pendientes:
El siguiente modelo de bigramas se aprende a partir de dos oraciones:
probs = {
'<s>': {'el': 0.5, 'la': 0.5},
# '<s>': {'el': 0.6, 'la': 0.2, 'los': 0.1, 'las': 0.1},
'el': {'gato': 1.0},
'gato': {'come': 1.0},
'come': {'pescado': 0.5, 'salmón': 0.5},
'pescado': {'.': 1.0},
'.': {'</s>': 1.0},
'la': {'gata': 1.0},
'gata': {'come': 1.0},
'salmón': {'.': 1.0},
}
list(probs['<s>'].items()) # convertir un diccionario a lista de pares
[('la', 0.5), ('el', 0.5)]
Cada entrada del diccionario contiene una distribución discreta finita para la palabra siguiente dada la palabra anterior. Samplear de una distribución discreta finita es tan fácil como samplear un número al azar entre 0 y 1 y ver en qué región cae (ver Wikipedia).
Empezamos sampleando la primer palabra:
from random import random
def sample(problist):
r = random() # entre 0 y 1
i = 0
word, prob = problist[0]
acum = prob
while r > acum:
i += 1
word, prob = problist[i]
acum += prob
return word
sample(list(probs['<s>'].items()))
'la'
Podemos ver que el resultado del sampleo se corresponde con las probabilidades:
results = [sample(list(probs['<s>'].items())) for i in range(1000)]
from collections import Counter
print(Counter(results))
Counter({'el': 505, 'la': 495})
Observaciones:
ó random.choice de numpy.
Ahora veamos cómo samplear una oración completa:
word = '<s>'
while word != '</s>':
problist = list(probs[word].items())
word = sample(problist)
print(word)
la gata come pescado . </s>
Acá se ve que se pueden generar oraciones nuevas (no vistas en tiempo de entrenamiento).
Tareas pendientes: