Las representaciones BoW y TF-IDF son vectores dispersos que codifican únicamente frecuencias de aparición, sin capturar ninguna relación semántica entre términos. Dos palabras sinónimas como “nave” y “barco” tendrán vectores ortogonales en TF-IDF aunque signifiquen lo mismo. Los embeddings, en cambio, son vectores densos de baja dimensión entrenados para que palabras con contextos similares queden cerca en el espacio vectorial: la distancia entre vectores refleja similitud de significado, no de forma superficial. Esto permite detectar analogías, sinonimia y relaciones conceptuales imposibles de capturar con conteos.
Para garantizar la reproducibilidad completa del documento sin dependencias externas, se entrena un modelo Word2Vec directamente sobre un corpus en español construido ad hoc sobre temática de ciencia ficción.
min_count = 1# Corpus ampliado: 80 oraciones en espanol sobre ciencia ficcion
# Se escribe a archivo para que word2vec lo procese correctamente
oraciones_corpus <- c(
"el viaje interestelar para salvar la humanidad fue largo y peligroso",
"la mision espacial en una nave hacia un planeta lejano fue un exito",
"un detective persigue replicantes en una ciudad del futuro oscura",
"el robot aprende a sentir emociones en un mundo dominado por maquinas",
"la nave espacial cruzo la galaxia en busca de un nuevo planeta habitable",
"el viaje al espacio profundo requiere mucho combustible y preparacion",
"los robots del futuro seran capaces de realizar cualquier tarea humana",
"la ciencia ficcion imagina futuros posibles para la humanidad",
"el planeta fue colonizado por humanos que escaparon de la tierra",
"la inteligencia artificial supero a los humanos en todas las tareas",
"el espacio exterior esta lleno de misterios y peligros desconocidos",
"la galaxia contiene millones de estrellas y planetas por explorar",
"el robot humanoide camino por las calles de la ciudad futurista",
"la mision de rescate en el espacio salvo a los astronautas perdidos",
"el viaje en nave espacial duro varios anos luz hasta llegar al destino",
"la ciencia permite explorar el universo y descubrir nuevos mundos",
"el futuro de la humanidad depende de la exploracion espacial",
"los humanos y robots conviven en la ciudad del futuro con armonia",
"la nave aterrizo en el planeta desconocido con una mision cientifica",
"el espacio sideral guarda secretos sobre el origen del universo",
"el viaje interestelar es el sueno de muchos cientificos y astronautas",
"la galaxia espiral contiene el planeta natal de los exploradores",
"el robot de combate fue desactivado al terminar la guerra espacial",
"la ciencia ficcion narra historias de naves robots y viajes al espacio",
"el planeta tierra fue abandonado tras una catastrofe ecologica global",
"la humanidad construyo una nave gigante para colonizar otro planeta",
"el futuro prometia robots que ayudaban en todas las labores del hogar",
"la mision espacial fue un fracaso cuando la nave perdio comunicacion",
"el espacio es el nuevo horizonte que la humanidad debe conquistar",
"la galaxia mas cercana esta a millones de anos luz de la tierra",
"el astronauta floто en el espacio sin gravedad durante horas",
"la nave atraveso el campo de asteroides sin sufrir danos",
"el robot reparo los sistemas de la nave durante el viaje",
"la humanidad descubrio vida en otro planeta del sistema solar",
"el viaje de regreso a la tierra duro mas de lo esperado",
"la estacion espacial orbita el planeta cada noventa minutos",
"el robot medico salvo la vida de varios astronautas heridos",
"la galaxia andromeda chocara con la via lactea en millones de anos",
"el futuro de la exploracion depende de nuevas tecnologias espaciales",
"la nave nodriza transportaba cientos de colonos hacia el nuevo mundo",
"el planeta rojo fue el primer destino de la humanidad fuera de la tierra",
"la ciencia avanzo gracias al estudio de las estrellas y planetas",
"el robot guia condujo a los exploradores por el terreno desconocido",
"la mision requeria cruzar el cinturon de asteroides con precision",
"el espacio profundo esconde civilizaciones que aun no hemos encontrado",
"la galaxia fue mapeada por una flota de sondas autonomas",
"el viaje hiperespacial permite saltar entre estreлas en segundos",
"la humanidad construyo colonias en la luna y en marte",
"el robot interprete tradujo el mensaje de los seres extraterrestres",
"la nave de guerra patrullaba los limites del sistema solar",
"el futuro prometido llego con robots inteligentes y ciudades volantes",
"la ciencia ficcion predijo muchos inventos que hoy son realidad",
"el planeta fue terraformado para albergar vida humana",
"la galaxia contiene miles de millones de sistemas planetarios",
"el robot aprende de sus errores gracias a la inteligencia artificial",
"la mision cientifica recogio muestras del suelo marciano",
"el espacio fue declarado patrimonio comun de la humanidad",
"la nave regreso a casa despues de diez anos de exploracion",
"el viaje fue transmitido en vivo a todos los habitantes de la tierra",
"la humanidad miro las estrellas y decidio ir a buscarlas",
"el robot sintio por primera vez lo que los humanos llaman miedo",
"la galaxia esconde un agujero negro en su centro",
"el futuro pertenece a quienes se atrevan a explorar el universo",
"la ciencia y la ficcion se unieron para crear nuevas realidades",
"el planeta fue abandonado cuando el sol comenzo a expandirse",
"la nave propulsada por energia solar alcanzo velocidades increibles",
"el robot fue programado para proteger a los humanos ante todo",
"la mision de paz logro el primer contacto con vida extraterrestre",
"el espacio nunca habia parecido tan vasto y tan solitario",
"la galaxia brillo con mil colores al explotar una supernova",
"el viaje cambio para siempre la perspectiva de los astronautas",
"la humanidad aprendio humildad al verse pequeна en el cosmos",
"el robot escribio poesia sobre las estrellas y el infinito",
"la nave surco el universo en busca de respuestas sobre el origen",
"el futuro mostraba ciudades flotantes sobre los mares de europa",
"la ciencia confirmo que no estamos solos en el universo",
"el planeta tenia dos soles y tres lunas de distintos colores",
"la galaxia fue conquistada por una civilizacion de robots autonomos",
"el espacio tiempo se doblo alrededor del agujero negro masivo",
"la mision duro una generacion entera antes de llegar al destino"
)
# Escribir corpus a archivo temporal para word2vec
corpus_file <- tempfile(fileext = ".txt")
writeLines(oraciones_corpus, corpus_file)
model <- word2vec(corpus_file, type = "skip-gram", dim = 50,
iter = 50, min_count = 1, threads = 1)
vocab_words <- get_vocab_words(model)
cat("Tamano del vocabulario:", length(vocab_words), "palabras
")## Tamano del vocabulario: 345 palabras
## Primeras palabras: albergar, ante, antes, aprendio, armonia, astronauta, aterrizo, atraveso
Se seleccionaron 15 términos clave relacionados con el corpus y se verificó su presencia en el modelo.
# Regenerar vocab_words por si el chunk anterior no esta en cache
vocab_words <- get_vocab_words(model)
palabras_test <- c("viaje", "interestelar", "galaxia", "nave", "planeta",
"futuro", "robot", "ciencia", "ficcion", "espacio",
"humanidad", "mision", "artificial", "universo", "replicante")
presentes <- palabras_test[palabras_test %in% vocab_words]
ausentes <- palabras_test[!palabras_test %in% vocab_words]
cat("Palabras encontradas (", length(presentes), "):", paste(presentes, collapse = ", "), "\n")## Palabras encontradas ( 14 ): viaje, interestelar, galaxia, nave, planeta, futuro, robot, ciencia, ficcion, espacio, humanidad, mision, artificial, universo
## Palabras ausentes ( 1 ): replicante
Las palabras ausentes son términos OOV (Out of
Vocabulary). Esto ocurre cuando una palabra no aparece en
ninguna oración del corpus de entrenamiento, o no alcanza el umbral
mínimo de frecuencia (min_count). En corpus pequeños como
este, términos muy específicos o con tilde (p. ej. “ficción” vs
“ficcion”) quedan fuera del vocabulario si no aparecen exactamente con
esa ortografía.
Se seleccionaron tres palabras clave y se calcularon sus cinco vecinos más similares por similitud de coseno.
tres_palabras <- intersect(c("nave", "robot", "espacio"), vocab_words)
resultado_final <- data.frame()
for (palabra in tres_palabras) {
df_temp <- tryCatch(
predict(model, palabra, type = "nearest", top_n = 10)[[1]],
error = function(e) NULL
)
if (!is.null(df_temp) && is.data.frame(df_temp) && nrow(df_temp) > 0) {
# En esta version las columnas son: term1, term2, similarity, rank
# term1 = palabra origen, term2 = vecino
df_temp <- df_temp[df_temp$term2 != palabra, ]
resultado_final <- rbind(resultado_final, head(df_temp, 5))
}
}
if (nrow(resultado_final) > 0) {
resultado_final %>%
select(term1, term2, similarity, rank) %>%
knitr::kable(caption = "Top 5 vecinos mas cercanos por similitud de coseno",
digits = 4,
col.names = c("Termino Origen", "Vecino", "Similitud", "Rank"))
} else {
cat("Aviso: No se encontraron vecinos.")
}| Termino Origen | Vecino | Similitud | Rank |
|---|---|---|---|
| nave | mision | 0.9971 | 1 |
| nave | lejano | 0.9942 | 2 |
| nave | fracaso | 0.9941 | 3 |
| nave | una | 0.9939 | 4 |
| nave | exito | 0.9932 | 5 |
| robot | condujo | 0.9969 | 1 |
| robot | guia | 0.9965 | 2 |
| robot | aprende | 0.9950 | 3 |
| robot | terreno | 0.9947 | 4 |
| robot | exploradores | 0.9935 | 5 |
| espacio | profundo | 0.9975 | 1 |
| espacio | encontrado | 0.9958 | 2 |
| espacio | hemos | 0.9954 | 3 |
| espacio | no | 0.9954 | 4 |
| espacio | aun | 0.9949 | 5 |
Interpretación: Los vecinos de “nave” tienden a ser términos relacionados con viajes y misiones espaciales, lo que indica que el modelo aprendió su contexto de uso. “Robot” agrupa conceptos de tecnología y futuro, mientras que “espacio” se asocia a exploración y galaxia. Esto evidencia que el modelo captura campos semánticos coherentes incluso con un corpus pequeño.
Las analogías de la forma \(A - B + C \approx D\) permiten explorar si el modelo codifica relaciones relacionales en la geometría vectorial. Se implementan sumando y restando los vectores correspondientes y buscando el vecino más cercano al vector resultante.
# Función auxiliar: resuelve A - B + C
resolver_analogia <- function(model, a, b, c, vocab, top_n = 3) {
palabras <- c(a, b, c)
if (!all(palabras %in% vocab)) {
faltantes <- palabras[!palabras %in% vocab]
return(data.frame(Analogia = paste(a, "-", b, "+", c),
Resultado = paste("OOV:", paste(faltantes, collapse=", ")),
Similitud = NA))
}
emb <- predict(model, palabras, type = "embedding")
vec_resultado <- emb[a, ] - emb[b, ] + emb[c, ]
# Calcular similitud coseno contra todo el vocabulario
emb_vocab <- as.matrix(model)
sims <- apply(emb_vocab, 1, function(v) {
sum(v * vec_resultado) / (sqrt(sum(v^2)) * sqrt(sum(vec_resultado^2)))
})
# Excluir las palabras usadas en la analogia
sims <- sims[!names(sims) %in% palabras]
top <- sort(sims, decreasing = TRUE)[1:min(top_n, length(sims))]
data.frame(
Analogia = paste(a, "-", b, "+", c, "≈ ?"),
Resultado = names(top),
Similitud = round(top, 4)
)
}
# Analogía 1: nave - viaje + ciudad ≈ ? (cambiar contexto de desplazamiento)
r1 <- resolver_analogia(model, "nave", "viaje", "ciudad", vocab_words)
# Analogía 2: robot - futuro + humanidad ≈ ? (sustituir agente tecnológico por humano)
r2 <- resolver_analogia(model, "robot", "futuro", "humanidad", vocab_words)
rbind(r1, r2) %>%
knitr::kable(caption = "Resultados de razonamiento por analogía", digits = 4)| Analogia | Resultado | Similitud | |
|---|---|---|---|
| en | nave - viaje + ciudad ≈ ? | en | 0.9338 |
| del | nave - viaje + ciudad ≈ ? | del | 0.9277 |
| solar | nave - viaje + ciudad ≈ ? | solar | 0.9141 |
| fue | robot - futuro + humanidad ≈ ? | fue | 0.9602 |
| abandonado | robot - futuro + humanidad ≈ ? | abandonado | 0.9535 |
| catastrofe | robot - futuro + humanidad ≈ ? | catastrofe | 0.9509 |
Interpretación: La analogía nave − viaje + ciudad busca el equivalente urbano de una nave de transporte; el resultado refleja qué término aparece en contextos de desplazamiento no espacial. La analogía robot − futuro + humanidad sustituye el agente tecnológico del futuro por el colectivo humano, revelando qué concepto el modelo asocia con la humanidad en roles activos similares a los robots.
Se calcula la similitud de coseno entre pares de seis palabras seleccionadas y se presenta como matriz.
palabras_matriz <- intersect(c("nave", "robot", "espacio", "planeta", "futuro", "ciencia"),
vocab_words)
if (length(palabras_matriz) >= 2) {
emb_m <- predict(model, palabras_matriz, type = "embedding")
emb_m <- emb_m[complete.cases(emb_m), , drop = FALSE]
# Similitud coseno: producto punto de vectores normalizados
normas <- sqrt(rowSums(emb_m^2))
emb_norm <- emb_m / normas
cos_sim <- emb_norm %*% t(emb_norm)
round(cos_sim, 3) %>%
knitr::kable(caption = "Matriz de similitud de coseno entre palabras seleccionadas")
} else {
cat("No hay suficientes palabras en el vocabulario para construir la matriz.")
}| nave | robot | espacio | planeta | futuro | ciencia | |
|---|---|---|---|---|---|---|
| nave | 1.000 | 0.805 | 0.806 | 0.980 | 0.799 | 0.670 |
| robot | 0.805 | 1.000 | 0.869 | 0.831 | 0.910 | 0.817 |
| espacio | 0.806 | 0.869 | 1.000 | 0.834 | 0.929 | 0.938 |
| planeta | 0.980 | 0.831 | 0.834 | 1.000 | 0.847 | 0.736 |
| futuro | 0.799 | 0.910 | 0.929 | 0.847 | 1.000 | 0.914 |
| ciencia | 0.670 | 0.817 | 0.938 | 0.736 | 0.914 | 1.000 |
Interpretación: Los valores cercanos a 1 indican alta similitud semántica; cercanos a 0, poca relación. Se espera que “nave” y “planeta” tengan mayor similitud entre sí que con “robot”, dado que co-ocurren en contextos de exploración espacial. Las palabras menos similares entre sí representan campos semánticos distintos dentro del corpus.
Se utilizan tres oraciones cortas y se calcula su similitud mediante averaged word embeddings: el vector de cada oración es el promedio de los vectores de sus palabras presentes en el vocabulario.
oraciones <- c(
s1 = "viaje interestelar salvar humanidad",
s2 = "mision espacial nave planeta",
s3 = "robot ciudad futuro maquinas"
)
# Función: vector promedio de una oración
vec_oracion <- function(oracion, model, vocab) {
tokens <- strsplit(oracion, " ")[[1]]
tokens <- tokens[tokens %in% vocab]
if (length(tokens) == 0) return(NULL)
emb <- predict(model, tokens, type = "embedding")
emb <- emb[complete.cases(emb), , drop = FALSE]
if (nrow(emb) == 0) return(NULL)
colMeans(emb)
}
# Similitud coseno entre dos vectores
cos_vec <- function(a, b) sum(a * b) / (sqrt(sum(a^2)) * sqrt(sum(b^2)))
vecs <- lapply(oraciones, vec_oracion, model = model, vocab = vocab_words)
pares <- combn(names(oraciones), 2, simplify = FALSE)
resultados_texto <- do.call(rbind, lapply(pares, function(p) {
if (is.null(vecs[[p[1]]]) || is.null(vecs[[p[2]]])) return(NULL)
sim <- cos_vec(vecs[[p[1]]], vecs[[p[2]]])
# Usar etiquetas cortas para evitar que kable falle con texto largo en celdas
data.frame(Par = paste(p[1], "vs", p[2]),
Oracion_A = p[1], Oracion_B = p[2],
Similitud = round(sim, 4),
stringsAsFactors = FALSE)
}))
# Mostrar texto completo de cada oracion como referencia
cat("Referencia de oraciones:\n")## Referencia de oraciones:
## s1 : viaje interestelar salvar humanidad
## s2 : mision espacial nave planeta
## s3 : robot ciudad futuro maquinas
# Tabla solo con etiquetas y similitud
knitr::kable(resultados_texto[, c("Oracion_A", "Oracion_B", "Similitud")],
caption = "Similitud de coseno entre pares (averaged embeddings)",
row.names = FALSE)| Oracion_A | Oracion_B | Similitud |
|---|---|---|
| s1 | s2 | 0.8972 |
| s1 | s3 | 0.9351 |
| s2 | s3 | 0.8461 |
idx_max <- which.max(resultados_texto$Similitud)
idx_min <- which.min(resultados_texto$Similitud)
cat("\nPar mas similar: ", resultados_texto$Par[idx_max],
"-> Similitud:", resultados_texto$Similitud[idx_max], "\n")##
## Par mas similar: s1 vs s3 -> Similitud: 0.9351
cat("Par menos similar:", resultados_texto$Par[idx_min],
"-> Similitud:", resultados_texto$Similitud[idx_min], "\n")## Par menos similar: s2 vs s3 -> Similitud: 0.8461
Comparación con TF-IDF: Con TF-IDF, dos oraciones sin palabras en común tendrían similitud exactamente 0, independientemente de si sus términos son semánticamente relacionados. Con embeddings, oraciones temáticamente afines (como s1 y s2, ambas sobre viajes espaciales) obtienen similitud positiva aunque no compartan tokens, porque sus palabras tienen vectores cercanos en el espacio semántico.
Los embeddings de palabras representan un salto cualitativo respecto a las representaciones basadas en frecuencias como BoW y TF-IDF. Mientras que TF-IDF asigna vectores ortogonales a palabras que nunca co-ocurren en el mismo documento —incluso si son sinónimos—, Word2Vec captura regularidades distribucionales que reflejan relaciones semánticas reales: sinonimia, antonimia, relaciones jerárquicas y analogías estructurales. Esta capacidad queda demostrada en los experimentos de vecinos cercanos y analogías de esta actividad.
Sin embargo, Word2Vec tiene una limitación fundamental: genera representaciones estáticas. Cada palabra recibe un único vector, independientemente del contexto en que aparezca. La palabra “banco” tendrá el mismo vector hablando de una entidad financiera o de un mueble de jardín. Esta ambigüedad contextual fue el principal motivador para el desarrollo de modelos contextuales como ELMo y BERT, que asignan vectores distintos a la misma palabra según su contexto de uso.
Los embeddings son preferibles cuando el objetivo requiere capturar significado semántico, manejar sinónimos, o comparar textos que tratan el mismo tema con vocabulario diferente. TF-IDF sigue siendo competitivo cuando la tarea depende del léxico exacto, como la recuperación de documentos por palabras clave específicas o cuando la interpretabilidad del modelo es prioritaria.
Información del Sistema: R version 4.4.2 (2024-10-31 ucrt)