sents = [
'el gato come pescado .'.split(),
'la gata come salmón .'.split(),
]
Luego, los conteos de bigramas y unigramas incluirán, entre otras cosas, los siguientes elementos:
count = {
('el',): 1,
('come',): 2,
# ... mas unigramas ...
('el', 'gato'): 1,
('come', 'pescado'): 1,
('come', 'salmón'): 1,
# ... mas bigramas ...
}
Calculemos algunas probabilidades sin "add one" de ejemplo:
def cond_prob(token, prev_tokens):
tokens = prev_tokens + (token,)
return float(count.get(tokens, 0)) / float(count.get(prev_tokens, 0))
print(cond_prob('gato', ('el',)))
print(cond_prob('pollo', ('el',)))
# print(cond_prob('pollos', ('los',)))
print(cond_prob('pescado', ('come',))) # o salmón
print(cond_prob('salame', ('come',))) # o salmón
1.0 0.0 0.5 0.0
Ahora calculemos las mismas probabilidades pero con el suavizado "add one":
voc = {'el', 'gato', 'come', 'pescado', '.', '</s>', 'la', 'gata', 'salmón'}
V = len(voc)
def add_one_cond_prob(token, prev_tokens):
tokens = prev_tokens + (token,)
return float(count.get(tokens, 0) + 1) / float(count.get(prev_tokens, 0) + V)
print(add_one_cond_prob('gato', ('el',)))
print(add_one_cond_prob('pollo', ('el',)))
# print(cond_prob('pollos', ('los',)))
print(add_one_cond_prob('pescado', ('come',))) # o salmón
print(add_one_cond_prob('salame', ('come',))) # o salmón
0.2 0.1 0.18181818181818182 0.09090909090909091
Tareas pendientes:
Esta vez probamos con un modelo de trigramas. Supongamos los siguientes conteos:
count = {
('come',): 2,
# ... más unigramas ...
('gato', 'come'): 1,
('come', 'pescado'): 1,
('come', 'salmón'): 1,
# ... más bigramas ...
('gato', 'come', 'pescado'): 1,
# ... más trigramas ...
}
def cond_prob(token, prev_tokens):
tokens = prev_tokens + (token,)
return float(count.get(tokens, 0)) / float(count.get(prev_tokens, 0))
Y veamos el caso de interpolación específico para 3-gramas:
gamma = 1
def interpolated_cond_prob(token, prev_tokens):
cond_ml1 = cond_prob(token, prev_tokens) # 2-uple: (u,v)
cond_ml2 = cond_prob(token, prev_tokens[1:]) # 1-uple: (v,)
cond_ml3 = add_one_cond_prob(token, prev_tokens[2:]) # 0-uple: ()
lambda1 = count[prev_tokens] / (count[prev_tokens] + gamma)
lambda2 = (1 - lambda1) * count[prev_tokens[1:]] / (count[prev_tokens[1:]] + gamma)
lambda3 = 1 - (lambda1 + lambda2)
prob = lambda1 * cond_ml1 + lambda2 * cond_ml2 + lambda3 * cond_ml3
return prob
# cond_prob('pescado', ('gato', 'come'))
print(interpolated_cond_prob('pescado', ('gato', 'come')))
print(interpolated_cond_prob('salmón', ('gato', 'come')))
print(interpolated_cond_prob('salame', ('gato', 'come')))
0.6851851851851851 0.18518518518518517 0.018518518518518524
Puede verse cómo afecta el parámetro gamma al suavizado (a maś grande, más fuerte el suavizado).
Tareas pendientes: