Números más pequeños, modelo más pequeño
Cuantizar un modelo es guardar cada uno de sus números con menos bits, para que ocupe menos memoria. El precio es que cada número se redondea.
Importa porque redondear es la manera de meter un modelo grande en un equipo pequeño. Debes saber lo que cuesta antes de fiarte del resultado.
Al final de esta lección
Nota
Puedo decir qué se pierde cuando los números se hacen más pequeños.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Cuantizar | redondear números a unos pocos niveles fijos |
| Nivel | uno de los valores a los que se redondea |
| Escala | el mayor valor absoluto de la tabla |
| Error | la distancia entre un número y su copia redondeada |
| Valor atípico | un valor mucho mayor que el resto |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Menos bits significa menos niveles
Con 8 bits un número cabe en 255 niveles. Con 4 bits solo hay 15, y con 2 bits solo 3. Cada número se lleva al nivel más cercano.
Para elegir los niveles, divide cada valor entre la escala (el mayor valor absoluto), multiplica por el nivel más alto y redondea. Para recuperar un número, invierte los pasos.
Ocho números con cuatro precisiones
| Bits | Niveles | Enteros guardados | Peor error |
|---|---|---|---|
| 8 | 255 | 127 -59 10 71 -124 44 -7 90 | 0,0031 |
| 4 | 15 | 7 -3 1 4 -7 2 0 5 | 0,0586 |
| 3 | 7 | 3 -1 0 2 -3 1 0 2 | 0,12 |
| 2 | 3 | 1 0 0 1 -1 0 0 1 | 0,42 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Dónde duele más el redondeo
Los números pequeños sufren primero. Con 4 bits el valor -0,05 pasó a 0, así que se perdió. Con 2 bits, cuatro de los ocho números pasaron a 0.
Un valor atípico perjudica a todos. Si un valor es 9,0, la escala es 9,0. Los niveles quedan muy separados y todos los números pequeños se redondean a 0.
Un error frecuente
Advertencia
Mucha gente cree que con menos bits todo se vuelve un poco borroso por igual. No es parejo. Los números pequeños pueden desaparecer y un valor atípico puede estropear toda la tabla. Mide siempre el error antes de fiarte de una tabla cuantizada.
Escribe el ayudante del modelo, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.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 ayudante del modelo, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"estado \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.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 cuantizador, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const values = [0.9, -0.42, 0.07, 0.5, -0.88, 0.31, -0.05, 0.64];' 'function quantise(list, bits) {' ' const top = Math.pow(2, bits - 1) - 1;' ' const scale = Math.max(...list.map(Math.abs));' ' return list.map(function (v) { return Math.floor(v / scale * top + 0.5); });' '}' > quant.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 cuantizador, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function restore(q, list, bits) {' ' const top = Math.pow(2, bits - 1) - 1;' ' const scale = Math.max(...list.map(Math.abs));' ' return q.map(function (n) { return n * scale / top; });' '}' >> quant.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 cuantizador, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function worst(list, bits) {' ' const back = restore(quantise(list, bits), list, bits);' ' let w = 0;' ' list.forEach(function (v, i) { w = Math.max(w, Math.abs(v - back[i])); });' ' return w;' '}' >> quant.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 cuantizador, parte 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' for (const bits of [8, 4, 3, 2]) {' ' console.log(bits + \" bits: \" + quantise(values, bits).join(\" \") + \" | peor error \" + worst(values, bits).toFixed(4));' ' }' ' console.log(\"con un 9.0 añadido, 4 bits, peor error \" + worst(values.concat([9.0]), 4).toFixed(4));' ' const q = \"En una frase corta, ¿qué se pierde cuando los números se guardan con menos bits?\";' ' const sample = \"Cada número se redondea a un escalón cercano, así que se pierden las diferencias pequeñas entre números.\";' ' const reply = await ask([{ role: \"user\", content: q }], sample, 60);' ' console.log(\"el modelo dijo: \" + reply.text);' '}' 'main();' >> quant.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta el cuantizador
docker exec -w /home/node/project agent node quant.jsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Qué imprime el Run
| Línea | Qué muestra |
|---|---|
| 8 bits: ... peor error 0.0031 | Casi no se pierde nada |
| 4 bits: 7 -3 1 4 -7 2 0 5 ... | El 0.05 pasó a 0 |
| 2 bits: ... peor error 0.4200 | La mayoría de los valores pequeños desaparecen |
| con un 9.0 añadido ... | Un valor atípico agranda el error |
| el modelo dijo: ... | Una frase. Las palabras cambian en cada ejecución |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.