Apuntes / Procesamiento de Lenguaje Natural / Apunte 5 de 8
Read in Englishword2vec: aprender de las vecinas de una palabra
Cómo una bolsa de palabras pierde el orden de un texto, cómo los n-gramas y los skip-gramas recuperan parte de él, y cómo word2vec aprende un vector para cada palabra adivinando las que la rodean, un entrenamiento que el muestreo negativo abarata.
Los apuntes anteriores convirtieron un texto en conteos: cuántas veces aparece cada palabra en un capítulo o en un parlamento. Los conteos guardan qué palabras usa un texto y pierden lo demás, incluido qué palabras van al lado de cuáles. Y sin embargo, las palabras que rodean a una palabra dicen mucho de ella. En 2013, Tomáš Mikolov y sus colegas de Google construyeron word2vec sobre esa idea. Su modelo skip-gram es un clasificador entrenado para adivinar, a partir de cada palabra de un texto, qué palabras tiene cerca, y las respuestas están en el propio texto: el Quijote, por sí solo, da más de un millón y medio de ejemplos así. Y nadie necesita esas predicciones: lo que se guarda es lo que el clasificador aprende en el camino, una lista corta de números para cada palabra, su vector.
-
Cada palabra, con las que la rodean
-
Un clasificador las adivina a partir de la palabra
-
Lo que queda: un vector corto por palabra
La sección 1 muestra el orden que se pierde al contar palabras y cuánto de él recuperan los n-gramas, los tramos de palabras seguidas; la sección 2 empareja cada palabra con sus vecinas; la sección 3 construye el clasificador que las adivina, con sus dos tablas de vectores; la sección 4 abarata su entrenamiento con el muestreo negativo, y la sección 5 muestra cómo se sortean las palabras contra las que entrena. Lo que los vectores terminan capturando, y lo que otros modelos hacen con ellos, es el tema del próximo apunte.
1El orden y los n-gramas
Una bolsa de palabras x cuenta cada palabra del vocabulario en un texto, como el apunte de los modelos lineales contó las palabras de cada parlamento. Llamemos w1, …, wN a las N palabras de un texto, en su orden (en este apunte w es siempre una palabra, nunca un peso). Reordenarlas deja cada conteo como estaba:
para cualquier permutación π de las palabras. Ante los molinos, en el capítulo VIII de la primera parte del Quijote, Sancho le advierte a su amo: «aquellos que allí se parecen no son gigantes, sino molinos de viento». Intercambia gigantes y molinos de viento, y las mismas palabras dicen lo que cree don Quijote. Los dos órdenes dan el mismo x, así que un modelo que solo lee x los trata igual, por bien entrenado que esté. Para distinguir a Sancho de don Quijote, como hizo el apunte de los modelos lineales, eso costaba poco, porque merced y tú delatan a cada uno estén donde estén; aquí el orden es lo esencial, porque decide cuál de las dos cosas se niega.
Contar tramos cortos de palabras conserva algo del orden. Un tramo de n palabras seguidas es un n-grama: desliza una ventana de n palabras por el texto, una palabra por paso, y en cada posición i la ventana encierra uno,
una posición por cada palabra que todavía tiene n − 1 palabras después. Los tramos de dos palabras se llaman bigramas y los de tres, trigramas, y con n = 1 los tramos vuelven a ser las palabras sueltas. En la figura, elige el orden de la línea de Sancho y el largo n.
Orden
Largo n
Elige un orden de la línea y un largo.
Los bigramas que separan los dos órdenes son el que empieza en son y los dos que rodean a sino: «son gigantes» es lo que Sancho niega. El precio está en el vocabulario. Cada n-grama distinto necesita una coordenada propia: el libro tiene 152 433 bigramas distintos, casi siete veces sus 22 605 palabras distintas, y cuanto más largos los tramos, más de ellos aparecen una sola vez:
| Distintos | Vistos una vez | |
|---|---|---|
| Palabras | 22 605 | 48.7% |
| Bigramas | 152 433 | 75.1% |
| Trigramas | 295 186 | 89.8% |
| 4-gramas | 354 497 | 96.6% |
Una coordenada vista una vez dice poco del próximo texto, donde ese mismo tramo rara vez vuelve: el orden recuperado se paga con la repetición que hacía informativos los conteos.
2Skip-gramas: una palabra y sus vecinas
word2vec conserva la ventana, pero lo que encierra ya no se convierte en coordenadas, sino en ejemplos con los que aprender el vector de cada palabra, así que el vocabulario se queda en las 22 605 palabras del libro. La ventana se centra en una palabra, el objetivo, y la empareja con cada palabra que esté a m posiciones o menos a cada lado, sus palabras de contexto:
una ventana de 2m + 1 palabras. Un par se escribe (o, c), con o el objetivo y c la palabra de contexto, y S es el conjunto de todos los pares, |S| su número. Con m = 2, la palabra allí forma pares con que y se, a su lado, y con aquellos y parecen, una posición más lejos; el par (allí, aquellos) deja fuera la palabra que, y esa palabra saltada da su nombre a los skip-gramas. En la figura, elige un objetivo en la línea de Sancho y el radio m.
Radio m
Haz clic en una palabra para que sea el objetivo, o recorre la línea con las flechas del teclado, y elige el radio.
En todo el libro, con m = 2, sus N = 376 597 tokens dan 1 506 382 pares, los ejemplos que prometía el comienzo. El programa original de word2vec no usa el mismo radio para todos los objetivos: sortea uno entre 1 y m para cada uno, así que las palabras más cercanas forman más pares. El clasificador de la sección siguiente ignora j: adivina qué palabras aparecen a m posiciones o menos del objetivo, no dónde.
3Adivinar las vecinas
word2vec tiene dos modelos, y este apunte sigue el skip-gram, que adivina las vecinas a partir de la palabra (el otro, CBOW, por continuous bag of words, adivina la palabra a partir de sus vecinas). Dado un objetivo o, le da a cada palabra c del vocabulario una probabilidad de aparecer a su alrededor: es la softmax del apunte de los modelos lineales con una clase por palabra, V clases en total:
Cada palabra w tiene dos vectores de d números, vw para cuando es el objetivo y uw para cuando es una palabra de contexto, así que un par (o, c) se puntúa con ucTvo, como se puntuaba un parlamento en el apunte de los modelos lineales, pesos por conteos: uc ocupa el lugar de los pesos de la clase c, y vo el de los conteos.
Los vectores llenan dos tablas, los pesos de una pequeña red: un modelo hecho de capas, cada una de las cuales multiplica lo que recibe por una tabla de pesos y a menudo le aplica al resultado una función fija; aquí la primera capa solo multiplica y la segunda agrega la softmax. Win ∈ ℝV×d, V filas de d números, guarda los vectores de los objetivos, y su fila o es vo; Wout ∈ ℝd×V, V columnas de d números, guarda los de las palabras de contexto, y su columna c es uc.
El objetivo entra como un vector one-hot x, con un 1 en o y 0 en todo lo demás: la bolsa de palabras de un texto de una sola palabra. La red lo lleva por sus dos capas con tres ecuaciones, sus ecuaciones de transferencia, que seleccionan una fila, puntúan cada palabra y normalizan las puntuaciones:
WinTx suma las filas de Win ponderadas por las componentes de x, y un one-hot deja solo la fila o: el vector que pasa de una capa a la otra, la capa oculta (oculta porque ningún dato la entrega), es el propio vo. Cada componente de z es la puntuación de una palabra, zc = ucTvo, y y guarda p(c | o) para cada palabra c. Entrenar cambia los números de ambas tablas por descenso de gradiente, como en el apunte de los modelos lineales, para achicar el −log p de ese apunte, con p ahora la probabilidad que el modelo le dio a la palabra que de verdad apareció; promediado sobre los pares, es la entropía cruzada
La figura muestra un modelo entrenado así con los 42 pares de la línea de Sancho, con V = 12 palabras y vectores de d = 3 números. Elige un objetivo y sigue los tres pasos.
Haz clic en una palabra de la primera tabla para que sea el objetivo, o recorre la tabla con las flechas del teclado.
Una palabra del interior de la línea le da cerca de un cuarto a cada una de sus cuatro vecinas y mucho menos a las demás. La predicción que minimiza ℒ le da a cada palabra la fracción de los pares del objetivo en que aparece, un cuarto a cada vecina y nada a las demás, y con estos pares deja ℒ en 1.28; la pérdida del modelo, 1.39, queda cerca. El entrenamiento conserva Win: sus filas son los vectores que busca este apunte. Las columnas de Wout también podrían servir de vectores de palabras, y algunos sistemas suman ambas tablas, pero el programa original solo guarda Win.
En las colecciones de texto, o corpus, para las que se hizo word2vec, d es de unos cientos y V de cientos de miles o más. Con unos cientos de números para cada una de tantas palabras, el modelo no puede guardar una predicción aparte para cada palabra, como casi lo logran las doce palabras de la figura con tres: las palabras con vecinas parecidas terminan con números parecidos, que es lo que estudia el próximo apunte.
4Muestreo negativo
Para normalizar, cada par necesita las V puntuaciones, 22 605 solo para este libro, y la suma de sus exponenciales. El muestreo negativo se deshace de ellas. Toma el par (gigantes, molinos) de la línea de Sancho. El muestreo negativo pone a su lado k pares de gigantes con palabras sorteadas del libro, como (gigantes, atrevió): los negativos. Al par observado le da la etiqueta y = 1; a los sorteados, la etiqueta y = 0. De cada par solo pregunta si lo produjo el texto, y responde con la probabilidad de que así sea, escrita P(+ | o, c): la función logística de su puntuación,
donde σ es la función logística que el apunte de los modelos lineales escribía θ. Con S conteniendo ahora ambos tipos de pares, la pérdida es la entropía cruzada binaria de ese apunte:
Cada par observado necesita ahora k + 1 puntuaciones en lugar de V. Mikolov y sus colegas propusieron el método a fines de 2013, en su segundo artículo sobre word2vec, donde k entre 5 y 20 funcionó en corpus pequeños, mientras que en corpus grandes podía bastar con 2 a 5; el artículo probó el muestreo negativo con mil millones de palabras de noticias y un vocabulario de 692 000 palabras. Cada par aporta el (h − y)x del apunte de los modelos lineales, con el otro vector en el lugar de x: (h − y)vo a su vector de contexto y (h − y)uc al del objetivo; promediados sobre los pares, como ese apunte promediaba sobre los parlamentos, dan el gradiente de ℒ.
Un producto punto se lee igual desde cualquiera de los dos lados, así que los papeles de la sección 3 pueden intercambiarse: visto desde el objetivo, el muestreo negativo es una regresión logística, con vo como los pesos y cada vector de contexto como un punto. La recta donde uTvo = 0 separa los puntos cuyos pares parecen reales del resto y, a diferencia del apunte de los modelos lineales, los puntos también se mueven.
La figura sigue el par (gigantes, molinos) y tres palabras sorteadas del libro, con vectores de dos números para poder dibujarlos, y cada palabra lleva la h de su par. En ella, el paso de ese ejemplo se repite diez veces, con las mismas palabras sorteadas, para mostrar adónde llevan los pasos; al entrenar, cada par da un solo paso en cada lectura del texto, siempre con palabras sorteadas nuevas: descenso de gradiente estocástico, un paso por ejemplo en vez de uno sobre el promedio de todos. Da pasos de descenso de gradiente con una tasa de aprendizaje η = 1.2.
Siguiente da un paso de descenso de gradiente, Atrás retrocede. Teclas: → y ←.
La h del par observado sube hacia 1 y la de las palabras sorteadas baja hacia 0: el vector del objetivo gira hacia molinos y se aleja de las sorteadas, que también se apartan de él. En el libro, cada uno de los 1 506 382 pares da pasos así, y los vectores se asientan donde todos esos tirones se equilibran.
5Cómo se sortean los negativos
¿Qué palabras sortear? Si todas las palabras del vocabulario tuvieran la misma probabilidad, casi la mitad de los sorteos darían palabras vistas una sola vez en todo el libro: negativos fáciles, porque una palabra así casi nunca está cerca de ningún objetivo, y rechazarla le enseña poco al modelo. Sortear según la frecuencia, en cambio, haría que más de una cuarta parte de los sorteos fuera alguna de las diez palabras más frecuentes, encabezadas por que, y, de y la, que aparecen junto a cualquier otra y por eso tampoco ayudan a distinguir unas de otras. word2vec sortea según la frecuencia elevada a una potencia β entre 0 y 1:
donde f(w) es el número de veces que w aparece en el texto con que se entrena (en la figura, el libro) y la suma recorre el vocabulario; β = 0 le da a cada palabra la misma probabilidad y β = 1 sortea según la frecuencia. Mikolov y sus colegas eligieron ¾ por experimento, porque funcionó mejor que β = 0 y que β = 1. En la figura, elige β y sortea diez palabras del libro; la curva tenue, β = 1, queda como referencia.
Elige β y sortea otras diez palabras.
En los ejes log–log del primer apunte, las frecuencias del libro caen cerca de una recta, la ley de Zipf. Elevarlas a la potencia β multiplica su pendiente por β, así que β = ¾ deja la recta más plana: las palabras frecuentes pierden y las raras ganan. Las dos rectas se cruzan en las palabras vistas unas 170 veces, y modo, en el rango 231, es la primera palabra que β = ¾ sortea más que β = 1. La palabra que, la más frecuente, baja del 5.4% de los sorteos al 1.6%, y molinos, que aparece 12 veces, casi duplica su probabilidad.
6Resumen
Las ideas del apunte en NumPy. words es un texto como lista de palabras; w_in y w_out son las dos matrices, con una fila de w_in y una columna de w_out por palabra del vocabulario; o y c son posiciones de palabras en el vocabulario, y neg las de las k palabras sorteadas; f tiene los conteos de las palabras, beta es β y rng es un generador aleatorio de NumPy.
grams = list(zip(*[words[i:]
for i in range(n)]))N = len(words)
pairs = [(words[i], words[i + j])
for i in range(N)
for j in range(-m, m + 1)
if j and 0 <= i + j < N]v_o = w_in[o]z = v_o @ w_oute = np.exp(z - z.max())
y_hat = e / e.sum()loss = -np.log(y_hat[c])cs = np.r_[c, neg]
h = 1 / (1 + np.exp(
-(v_o @ w_out[:, cs])))y = np.r_[1, np.zeros(k)]
loss = -np.mean(y * np.log(h)
+ (1 - y) * np.log(1 - h))(1/|S|) ∑ (h − y)uc para vo
g = (h - y) / len(cs)
grad_u = np.outer(v_o, g)
grad_v = w_out[:, cs] @ gp = f ** beta
p = p / p.sum()
neg = rng.choice(len(f),
size=k, p=p)