El objetivo de este proyecto es construir un modelo de
predicción de texto que pueda anticipar la siguiente palabra
mientras un usuario escribe.
Este informe muestra los primeros pasos: exploración del corpus de
entrenamiento, estadísticas básicas y un plan de trabajo.
El enfoque final será una aplicación Shiny que demuestre cómo funciona el algoritmo de predicción en tiempo real.
Los datos provienen del corpus en inglés de blogs, noticias y Twitter.
cat("WD:", normalizePath(getwd()), "\n")
## WD: /Users/bea
data_dir <- "data"
if (!dir.exists(data_dir)) dir.create(data_dir, recursive = TRUE)
zip_candidates <- path.expand(c(
"~/Desktop/Coursera Swiftkey.zip",
"~/Desktop/Coursera SwiftKey.zip",
"~/Desktop/Coursera-SwiftKey.zip"
))
zip_path <- zip_candidates[file.exists(zip_candidates)][1]
if (is.na(zip_path)) {
stop(
"No encontré el ZIP en el Escritorio.\n",
"Verifica el nombre exacto o renómbralo a 'Coursera SwiftKey.zip'."
)
}
cat("Usando ZIP:", zip_path, "\n")
## Usando ZIP: /Users/bea/Desktop/Coursera-SwiftKey.zip
unzip(zip_path, exdir = data_dir)
# Ruta típica tras descomprimir
final_base <- file.path(data_dir, "final", "en_US")
files <- c(
blogs = file.path(final_base, "en_US.blogs.txt"),
news = file.path(final_base, "en_US.news.txt"),
twitter = file.path(final_base, "en_US.twitter.txt")
)
missing <- files[!file.exists(files)]
if (length(missing) > 0) {
# buscar la carpeta real donde quedaron los .txt
blogs_found <- list.files(data_dir, recursive = TRUE, full.names = TRUE,
pattern = "en_US\\.blogs\\.txt$")
if (length(blogs_found) > 0) {
final_base <- dirname(blogs_found[1])
files <- c(
blogs = file.path(final_base, "en_US.blogs.txt"),
news = file.path(final_base, "en_US.news.txt"),
twitter = file.path(final_base, "en_US.twitter.txt")
)
}
}
# Verificación final
missing <- files[!file.exists(files)]
if (length(missing) > 0) {
stop("Faltan archivos tras descomprimir:\n- ",
paste(basename(missing), collapse = "\n- "),
"\nEsperados en:\n", final_base,
"\nRevisa el contenido del ZIP o descomprime manualmente.")
}
# Carga
blogs <- readLines(files["blogs"], encoding = "UTF-8", skipNul = TRUE)
news <- readLines(files["news"], encoding = "UTF-8", skipNul = TRUE)
twitter <- readLines(files["twitter"], encoding = "UTF-8", skipNul = TRUE)
data_summary <- data.frame(
Fuente = c("Blogs", "News", "Twitter"),
Lineas = c(length(blogs), length(news), length(twitter)),
Tamaño_MB = round(c(object.size(blogs),
object.size(news),
object.size(twitter)) / 1024^2, 2)
)
knitr::kable(data_summary, caption = "Resumen de archivos cargados")
| Fuente | Lineas | Tamaño_MB |
|---|---|---|
| Blogs | 899288 | 255.35 |
| News | 1010242 | 257.34 |
| 2360148 | 318.99 |
library(stringi)
blog_words <- stri_count_words(blogs)
news_words <- stri_count_words(news)
twitter_words <- stri_count_words(twitter)
summary_stats <- data.frame(
Fuente = c("Blogs", "News", "Twitter"),
Promedio_palabras = c(mean(blog_words), mean(news_words), mean(twitter_words)),
Máximo_palabras = c(max(blog_words), max(news_words), max(twitter_words))
)
knitr::kable(summary_stats, caption = "Estadísticas de palabras por línea")
| Fuente | Promedio_palabras | Máximo_palabras |
|---|---|---|
| Blogs | 41.75109 | 6726 |
| News | 34.40997 | 1796 |
| 12.75065 | 47 |
Visualizamos las distribuciones
Blogs: textos largos, con frases más complejas.
News: longitud intermedia, lenguaje formal.
Twitter: mensajes cortos y con mucho ruido (hashtags, emoticonos).
Para ilustrar la frecuencia de palabras, generamos un gráfico con las más comunes en Twitter:
Construir un modelo de n-gramas (secuencias de 1–4 palabras).
Utilizar técnicas de backoff para manejar combinaciones no vistas.
Reducir tamaño con pruning (descartar combinaciones muy raras).
Evaluar precisión y velocidad.
Implementar un prototipo en Shiny que permita al usuario escribir texto y recibir sugerencias en tiempo real.
Se confirmó la correcta carga de los datos.
Se generaron estadísticas y gráficos que muestran diferencias claras entre las tres fuentes.
El corpus está listo para la construcción del modelo de predicción.