La página que no comparte ninguna palabra
Un embedding es una lista de números que representa el significado de un texto. Dos textos de significado parecido dan listas que apuntan en la misma dirección, y así un programa puede comparar significados con cálculo.
Una persona busca en la web de la biblioteca "normas para llevarse libros". La página que necesita se titula "Condiciones de préstamo". No comparten ni una palabra, así que una búsqueda por palabras no encuentra nada. Los números sí pueden.
Al final de esta lección
Nota
Puedo explicar qué es un embedding y comparar dos con la similitud del coseno.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Embedding | una lista de números que representa un significado | |
| Vector | una lista de números, vista como un punto o una flecha | |
| Producto escalar | la suma de los productos de los números del mismo lugar | |
| Similitud del coseno | una nota de cuánto apuntan igual dos flechas | 0.98 |
| Recuperación | encontrar los trozos de texto que encajan con una pregunta |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Embeddings reales y nuestros sustitutos
Un embedding real tiene cientos de números y lo produce un modelo. Nada de este módulo produce uno.
Las lecciones usan sustitutos pequeños: listas inventadas de tres números y recuentos de palabras que calcula el propio script. Así cada paso se puede ejecutar y comprobar aquí. El método es el mismo.
Un vector es una lista de números
Piensa en una lista de números como un punto en un mapa. Dos números son un punto en un mapa plano. Tres son un punto en una habitación.
Da un significado a cada lugar de la lista. Aquí los tres lugares son animal, vehículo y comida. Un número grande quiere decir que la palabra trata mucho de eso.
Ejemplo resuelto: cuatro vectores inventados
| Palabra | Animal | Vehículo | Comida |
|---|---|---|---|
| gato | 0,9 | 0,1 | 0,1 |
| gatito | 0,8 | 0,1 | 0,2 |
| autobús | 0,1 | 0,9 | 0,0 |
| churro | 0,1 | 0,0 | 0,9 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
El coseno puntúa cuánto se parecen
Para comparar dos vectores hacen falta tres pasos pequeños. El producto escalar multiplica los números del mismo lugar y los suma. La longitud es la raíz cuadrada del producto escalar del vector consigo mismo.
El coseno es el producto escalar dividido entre las dos longitudes. Vale 1 si las flechas apuntan igual, 0 en ángulo recto y menos de 0 si se alejan.
Ejemplo resuelto: dos vectores pequeños
| Paso | Cuenta con a = [1, 2] y b = [2, 1] | Resultado |
|---|---|---|
| Producto escalar | 1 x 2 + 2 x 1 | 4 |
| Longitud de a | raíz cuadrada de (1 x 1 + 2 x 2) | 2,24 |
| Longitud de b | raíz cuadrada de (2 x 2 + 1 x 1) | 2,24 |
| Coseno | 4 dividido entre (2,24 x 2,24) | 0,8 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Escribe la cuenta como un bucle
El siguiente script guarda los cuatro vectores y escribe los tres pasos como funciones pequeñas. Muestra el coseno de cada pareja.
También construye un vector de recuentos: una lista fija de palabras y las veces que aparece cada una en una frase. Dos frases que usan las mismas palabras dan vectores que apuntan igual.
Escribe el script de vectores, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Vectores pequeños inventados: [animal, vehículo, comida]. Un embedding real tiene cientos de números.' 'const vectors = {' ' gato: [0.9, 0.1, 0.1],' ' gatito: [0.8, 0.1, 0.2],' ' autobus: [0.1, 0.9, 0.0],' ' churro: [0.1, 0.0, 0.9],' '};' 'function dot(a, b) {' ' let total = 0;' ' for (let i = 0; i < a.length; i++) total = total + a[i] * b[i];' ' return total;' '}' 'function length(a) { return Math.sqrt(dot(a, a)); }' 'function cosine(a, b) { return dot(a, b) / (length(a) * length(b)); }' > vec.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el script de vectores, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const names = Object.keys(vectors);' 'for (let i = 0; i < names.length; i++) {' ' for (let j = i + 1; j < names.length; j++) {' ' const score = cosine(vectors[names[i]], vectors[names[j]]);' ' console.log(names[i] + \" y \" + names[j] + \": \" + score.toFixed(2));' ' }' '}' '// Un vector de recuentos: cuántas veces aparece cada palabra de una lista fija.' 'const vocabulary = [\"abre\", \"tarde\", \"libro\", \"multa\"];' 'function counts(sentence) {' ' const found = sentence.toLowerCase().split(\" \");' ' return vocabulary.map(function (word) {' ' return found.filter(function (one) { return one === word; }).length;' ' });' '}' >> vec.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el script de vectores, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const one = counts(\"abre tarde abre\");' 'const two = counts(\"libro abre tarde\");' 'console.log(\"Recuentos:\", one.join(\" \"), \"y\", two.join(\" \"));' 'console.log(\"Coseno de los recuentos:\", cosine(one, two).toFixed(2));' >> vec.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecútalo y lee las notas
docker exec -w /home/node/project agent node vec.jsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Lo que muestra
| Línea | Qué indica |
|---|---|
| gato y gatito: 0.99 | Muy parecidos |
| gato y autobus: 0.22 | Poco parecidos |
| autobus y churro: 0.01 | Casi nada en común |
| Coseno de los recuentos: 0.77 | Las frases comparten las palabras abre y tarde |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un error frecuente
Advertencia
Mucha gente cree que un coseno de 0,9 significa "igual al 90 %". No es así. La nota solo sirve para ordenar: 0,9 está más cerca que 0,5. Úsala para poner en orden, nunca como un porcentaje de verdad.