document <- c(
"una experiencia gastronomica inolvidable y un muy buen servicio",
"el restaurante supero nuestras expectativas",
"el ambiente ha sido relajado y perfecto y el personal fue muy amable",
"el servicio era inexperto y no sabia como atender una mesa",
"las raciones eran ridiculamente pequenas para el precio pagado",
"el ambiente era ruidoso y desagradable")
category <- c("+", "+", "+", "-", "-", "-")
training <- data.frame(category, document)
training$document <- gsub(",", "", training$document)
cat("Corpus de entrenamiento:\n")
## Corpus de entrenamiento:
training
## category document
## 1 + una experiencia gastronomica inolvidable y un muy buen servicio
## 2 + el restaurante supero nuestras expectativas
## 3 + el ambiente ha sido relajado y perfecto y el personal fue muy amable
## 4 - el servicio era inexperto y no sabia como atender una mesa
## 5 - las raciones eran ridiculamente pequenas para el precio pagado
## 6 - el ambiente era ruidoso y desagradable
test <- "el servicio fue perfecto, con un camarero atento y amable"
test <- gsub(",", "", test)
cat("\n\nFrase a predecir:\n")
##
##
## Frase a predecir:
test
## [1] "el servicio fue perfecto con un camarero atento y amable"
get_bow <- function(documents){
bow <- table(unlist(strsplit(documents, " ")))
bow <- as.data.frame(bow)
names(bow)[1] <- "Word"
bow <- bow[sort.int(bow$Freq,
decreasing = TRUE,
index.return = TRUE)$ix, ]
rownames(bow) <- NULL
return(bow)
}
bow <- get_bow(training$document)
cat("\n\nBolsa de palabras:\n")
##
##
## Bolsa de palabras:
bow
## Word Freq
## 1 el 6
## 2 y 5
## 3 ambiente 2
## 4 era 2
## 5 muy 2
## 6 servicio 2
## 7 una 2
## 8 amable 1
## 9 atender 1
## 10 buen 1
## 11 como 1
## 12 desagradable 1
## 13 eran 1
## 14 expectativas 1
## 15 experiencia 1
## 16 fue 1
## 17 gastronomica 1
## 18 ha 1
## 19 inexperto 1
## 20 inolvidable 1
## 21 las 1
## 22 mesa 1
## 23 no 1
## 24 nuestras 1
## 25 pagado 1
## 26 para 1
## 27 pequenas 1
## 28 perfecto 1
## 29 personal 1
## 30 precio 1
## 31 raciones 1
## 32 relajado 1
## 33 restaurante 1
## 34 ridiculamente 1
## 35 ruidoso 1
## 36 sabia 1
## 37 sido 1
## 38 supero 1
## 39 un 1
bow_neg <- get_bow(training$document[training$category == "-"])
bow_pos <- get_bow(training$document[training$category == "+"])
n_V <- nrow(bow)
n_neg <- sum(bow_neg$Freq)
n_pos <- sum(bow_pos$Freq)
bow_neg$likel <- (bow_neg$Freq + 1)/(n_neg + n_V)
bow_pos$likel <- (bow_pos$Freq + 1)/(n_pos + n_V)
cat("\n\nBolsa de palabras negativas:\n")
##
##
## Bolsa de palabras negativas:
bow_neg
## Word Freq likel
## 1 el 3 0.06153846
## 2 era 2 0.04615385
## 3 y 2 0.04615385
## 4 ambiente 1 0.03076923
## 5 atender 1 0.03076923
## 6 como 1 0.03076923
## 7 desagradable 1 0.03076923
## 8 eran 1 0.03076923
## 9 inexperto 1 0.03076923
## 10 las 1 0.03076923
## 11 mesa 1 0.03076923
## 12 no 1 0.03076923
## 13 pagado 1 0.03076923
## 14 para 1 0.03076923
## 15 pequenas 1 0.03076923
## 16 precio 1 0.03076923
## 17 raciones 1 0.03076923
## 18 ridiculamente 1 0.03076923
## 19 ruidoso 1 0.03076923
## 20 sabia 1 0.03076923
## 21 servicio 1 0.03076923
## 22 una 1 0.03076923
cat("\n\nBolsa de palabras positivas:\n")
##
##
## Bolsa de palabras positivas:
bow_pos
## Word Freq likel
## 1 el 3 0.06060606
## 2 y 3 0.06060606
## 3 muy 2 0.04545455
## 4 amable 1 0.03030303
## 5 ambiente 1 0.03030303
## 6 buen 1 0.03030303
## 7 expectativas 1 0.03030303
## 8 experiencia 1 0.03030303
## 9 fue 1 0.03030303
## 10 gastronomica 1 0.03030303
## 11 ha 1 0.03030303
## 12 inolvidable 1 0.03030303
## 13 nuestras 1 0.03030303
## 14 perfecto 1 0.03030303
## 15 personal 1 0.03030303
## 16 relajado 1 0.03030303
## 17 restaurante 1 0.03030303
## 18 servicio 1 0.03030303
## 19 sido 1 0.03030303
## 20 supero 1 0.03030303
## 21 un 1 0.03030303
## 22 una 1 0.03030303
prior_neg <- mean(training$category == "-")
prior_pos <- mean(training$category == "+")
cat("\n\nProbabilidad a priori de la categoría negativa:", prior_neg)
##
##
## Probabilidad a priori de la categoría negativa: 0.5
cat("\nProbabilidad a priori de la categoría positiva:", prior_pos, "\n")
##
## Probabilidad a priori de la categoría positiva: 0.5
test_words <- unlist(strsplit(test, " "))
post_neg <- prior_neg
post_pos <- prior_pos
for(w in test_words){
if(is.element(w, bow$Word)){
if(is.element(w, bow_neg$Word)){
post_neg <- post_neg*bow_neg$likel[bow_neg$Word == w]
}else{
post_neg <- post_neg/(n_neg + n_V)
}
if(is.element(w, bow_pos$Word)){
post_pos <- post_pos*bow_pos$likel[bow_pos$Word == w]
}else{
post_pos <- post_pos/(n_pos + n_V)
}
}
}
cat("\n\nProbabilidad a posteriori de que la frase sea negativa:", post_neg)
##
##
## Probabilidad a posteriori de que la frase sea negativa: 2.447867e-12
cat("\nProbabilidad a posteriori de que la frase sea positiva:", post_pos, "\n")
##
## Probabilidad a posteriori de que la frase sea positiva: 4.692804e-11
norm_const <- post_neg + post_pos
cat("\nProbabilidad a posteriori normalizada de que la frase sea negativa:", post_neg/norm_const)
##
## Probabilidad a posteriori normalizada de que la frase sea negativa: 0.04957614
cat("\nProbabilidad a posteriori normalizada de que la frase sea positiva:", post_pos/norm_const, "\n")
##
## Probabilidad a posteriori normalizada de que la frase sea positiva: 0.9504239
import nltk
from nltk import ngrams
from collections import defaultdict
from numpy.random import choice
from nltk.corpus import cess_esp
nltk.download('cess_esp')
## True
nltk.download('punkt')
## True
nltk.download('punkt_tab')
## True
Creamos todos los posibles 4-gramas del corpus gracias a la función ngrams.
words = nltk.word_tokenize((' '.join(cess_esp.words())))
quadri_grams = list(ngrams(words, 4))
quadri_grams[0]
## ('El', 'grupo', 'estatal', 'Electricité_de_France')
Creamos un diccionario con la probabilidades que relaciona las tres primeras palabras de un 4-grama con su cuarta palabra.
model = defaultdict(lambda: defaultdict(lambda: 0))
for w1, w2, w3, w4 in quadri_grams:
model[(w1, w2, w3)][w4] += 1
for w1_w2_w3 in model:
total_count = float(sum(model[w1_w2_w3].values()))
for w4 in model[w1_w2_w3]:
model[w1_w2_w3][w4] /= total_count
Usar 4-gramas produce que el modelo conozca menos opciones que con trigramas.
model['no', 'se', 'han']
## defaultdict(<function <lambda>.<locals>.<lambda> at 0x11ff6d940>, {'hallado': 0.14285714285714285, 'encontrado': 0.14285714285714285, 'mostrado': 0.14285714285714285, 'adherido': 0.14285714285714285, 'adoptado': 0.14285714285714285, 'generado': 0.14285714285714285, 'acabado': 0.14285714285714285})
Vamos a crear una función que dadas tres palabras elija la siguiente palabra con mayor probabilidad. Si no hay ninguna palabra devuelve error.
def predict_next_word1(w1, w2, w3):
next_word_probs = model[w1, w2, w3]
if next_word_probs:
return max(next_word_probs, key=next_word_probs.get)
else:
return "█"
print(predict_next_word1('no', 'se', 'han'))
## hallado
También vamos a crear otra función que, gracias a la anterior, nos permita ir prediciendo un cierto número de palabras fijándose siempre en las últimas tres palabras predichas.
def prediction1(w1, w2, w3, n):
result_list = [w1, w2, w3]
for i in range(n):
new_word = predict_next_word1(result_list[i], result_list[i + 1], result_list[i + 2])
result_list.append(new_word)
return(' '.join(result_list))
print(prediction1('no', 'se', 'han', 17)) # Ejemplo con 17 palabras
## no se han hallado pruebas de la colisión , pero * 0 * no se presentará a la reelección en
Si probamos con un mayor número de palabras, puedemos ver que sigue manteniendo el sentido de la oración.
print(prediction1('no', 'se', 'han', 45)) # Ejemplo con 45 palabras
## no se han hallado pruebas de la colisión , pero * 0 * no se presentará a la reelección en el cargo , renovará su compromiso de reavivar la economía del país , mientras_que la oposición atacará a Mori y a su antiguo lugarteniente , el francés Daniel_Derguy
Por último, vamos a crear funciones que nos permitan obtener predicciones basadas en la probabilidad de cada 4-grama. Estas funciones elegirán aleatoriamente la siguiente palabra entre los posibles 4-gramas que determinan las tres palabras dadas según su probabilidad. Si no hay ninguna palabra devuelven error.
def predict_next_word2(w1, w2, w3):
next_word_probs = model[w1, w2, w3]
if next_word_probs:
k_nwp = list(next_word_probs)
p_nwp = list(next_word_probs.values())
return choice(k_nwp, p = p_nwp)
else:
return "█"
print(predict_next_word2('no', 'se', 'han'))
## adherido
Cada vez que se ejecuta se obtienen valores diferentes.
def prediction2(w1, w2, w3, n):
result_list = [w1, w2, w3]
for i in range(n):
new_word = predict_next_word2(result_list[i], result_list[i + 1], result_list[i + 2])
result_list.append(new_word)
return(' '.join(result_list))
print(prediction2('no', 'se', 'han', 20)) # Ejemplo con 22 palabras
## no se han hallado pruebas de la colisión , pero * 0 * vive de su época `` , dijo * 0 *