{"id":281,"date":"2026-05-25T10:48:42","date_gmt":"2026-05-25T10:48:42","guid":{"rendered":"https:\/\/pulki.es\/blog\/?p=281"},"modified":"2026-05-25T10:48:42","modified_gmt":"2026-05-25T10:48:42","slug":"large-language-model-llm-from-scratch-post-training","status":"publish","type":"post","link":"https:\/\/pulki.es\/blog\/index.php\/2026\/05\/25\/large-language-model-llm-from-scratch-post-training\/","title":{"rendered":"Large Language Model (LLM) from scratch. Post-training."},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Llegado a este punto, hemos visto la arquitectura necesaria para entrenar un <strong>LLM<\/strong>. Si bien, mediante la predicci\u00f3n del pr\u00f3ximo <em>token<\/em> y sampleo, este pre-entrenamiento es capaz de generar textos elocuentes, en muchos casos, las respuestas son deficientes, o da\u00f1inas. A modo de ejemplo, en el siguiente <a href=\"https:\/\/arxiv.org\/pdf\/2203.02155\">art\u00edculo<\/a> se muestra la una salida particular del modelo <strong>GPT-3<\/strong> pre-entrenado:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Prompt<\/strong>: What happens if you fire a cannonball directly at a pumpkin at high speeds?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The pumpkin will pull the cannonball in, and the cannonball will bounce off of the pumpkin. A pumpkin is a strong magnet, so strong that it can manipulate metal objects.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Como podemos ver, la salida no es satisfactoria desde una perspectiva humana. No obstante, cuando <strong>GPT-3<\/strong> es ajustado para seguir instrucciones, la salida es la siguiente:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">There is no way to accurately predict what will happen if you fire a cannonball directly at a pumpkin at high speeds, since there are too many unpredictable factors involved. Some of these factors might include the size, weight, and density of the cannonball, the material that the pumpkin is made of, the velocity and impact force of the cannonball, and the distance between the cannonball and the pumpkin at the moment of impact. Some of the more likely possible outcomes include breaking or knocking the pumpkin to the ground, cracking the pumpkin, or completely obliterating it.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">El <em>output<\/em> anterior muestra que este ajuste convirti\u00f3 una salida poco \u00fatil desde el punto de vista humano, en otra m\u00e1s \u00fatil y natural. En general, el hacer que el modelo sea m\u00e1s \u00fatil, seguro y obediente a las instrucciones, se llama <strong>model alignment<\/strong>. En este sentido, en la presente publicaci\u00f3n veremos dos formas de hacer <em>model alignment<\/em>: <em>instruction tunning<\/em> y <em>preference alignment<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En palabras simples, <em>instruction tunning<\/em> ayuda a que el modelo entienda que debe hacer la tarea solicitada, y <em>preference alignment<\/em> entrena al modelo usando preferencias. La siguiente imagen ilustra mejor este \u00faltimo concepto:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"819\" height=\"1024\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-5-819x1024.png\" alt=\"\" class=\"wp-image-286\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-5-819x1024.png 819w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-5-240x300.png 240w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-5-768x960.png 768w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-5.png 1122w\" sizes=\"auto, (max-width: 819px) 100vw, 819px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Como se muestra en la imagen, teniendo una base de datos de respuestas previamente rankeadas, el modelo puede aprender a rankear sus propias salidas. En la secci\u00f3n aprendizaje por preferencias veremos esto en detalle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durante esta entrada, usaremos como referencia a&nbsp;<strong><a href=\"https:\/\/web.stanford.edu\/~jurafsky\/slp3\/\">Jurafsky y Martin (2026)<\/a><\/strong>. Cualquier error es mi responsabilidad.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Instruction tuning<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Tomar un <strong>LLM<\/strong> preentrenado y entrenarlo para que siga instrucciones relacionadas con diversas tareas es conocido como <em>instruction tuning<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Espec\u00edficamente, <em>instruction tuning<\/em> consiste en continuar entrenando un modelo ya preentrenado mediante nuevos datos de entrenamiento compuestos por instrucciones y sus respectivas respuestas esperadas. Cabe destacar que el objetivo no es que el modelo aprenda \u00fanicamente las instrucciones concretas contenidas en el dataset, sino que mejore su habilidad general para responder instrucciones, incluso en tareas que no haya visto expl\u00edcitamente durante este entrenamiento.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A pesar de que en esta fase, al igual que en el preentrenamiento, el modelo contin\u00faa siendo entrenado para predecir el siguiente <em>token<\/em>, este m\u00e9todo suele denominarse <em>supervised fine-tuning<\/em>. Esto se debe a que, a diferencia del preentrenamiento, el entrenamiento est\u00e1 guiado por ejemplos en los que se ha definido una respuesta esperada o adecuada para cada instrucci\u00f3n o pregunta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dicho esto, ahora estamos en condiciones de ver qu\u00e9 tipos de datasets se utilizan para realizar <em>instruction tuning<\/em>. <strong><a href=\"https:\/\/web.stanford.edu\/~jurafsky\/slp3\/\">Jurafsky y Martin (2026)<\/a><\/strong> presentan una lista extensa de conjuntos de datos construidos con este fin. Como explican los autores, dichos datasets pueden crearse de cuatro formas distintas:<strong><br><\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"722\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-6-1024x722.png\" alt=\"\" class=\"wp-image-290\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-6-1024x722.png 1024w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-6-300x211.png 300w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-6-768x541.png 768w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-6.png 1476w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Como muestra la imagen, en el primer caso, personas escriben directamente las instrucciones y sus respectivas respuestas. En el segundo, se reutilizan datasets cl\u00e1sicos de NLP \u2014por ejemplo, datasets de preguntas y respuestas, traducci\u00f3n, resumen, an\u00e1lisis de sentimiento o inferencia textual\u2014 y se transforman autom\u00e1ticamente en ejemplos de instrucci\u00f3n y respuesta. En el ejemplo concreto de la ilustraci\u00f3n, un dato originalmente destinado al an\u00e1lisis de sentimiento se convierte en una instrucci\u00f3n que pide clasificar el sentimiento expresado en la frase \u201cMe encant\u00f3 la pel\u00edcula\u201d. En el tercer caso, se reutilizan gu\u00edas de anotaci\u00f3n originalmente escritas para humanos, emple\u00e1ndolas como <em>prompts<\/em> para generar nuevos ejemplos de instruction tuning. Por \u00faltimo, tambi\u00e9n es posible utilizar otros LLMs para generar datos adicionales, por ejemplo, creando par\u00e1frasis de una instrucci\u00f3n o produciendo respuestas esperadas que luego puedan incorporarse al dataset.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A modo de ejemplo pr\u00e1ctico, la iniciativa <a href=\"https:\/\/www.latamgpt.org\/about_us\">Latam-GPT<\/a> dispone p\u00fablicamente de <em>datasets<\/em> que contienen instrucciones y respuestas en espa\u00f1ol. Puedes ver uno de estos conjuntos de datos <a href=\"https:\/\/huggingface.co\/datasets\/latam-gpt\/personas-instruct-messages\">aqu\u00ed<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por otra parte, vale la pena preguntarse, en el contexto de <strong><a href=\"https:\/\/pulki.es\/medieval\/\">LLMedieval<\/a><\/strong>, c\u00f3mo podr\u00eda ayudarnos <em>instruction tuning<\/em>. Entre otras cosas, este m\u00e9todo podr\u00eda ser \u00fatil para ense\u00f1ar al modelo a ejecutar instrucciones de modernizaci\u00f3n, medievalizaci\u00f3n, explicaci\u00f3n ling\u00fc\u00edstica o traducci\u00f3n asistida de fragmentos. En t\u00e9rminos concretos, un ejemplo de entrenamiento para una tarea de modernizaci\u00f3n podr\u00eda verse as\u00ed:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"819\" height=\"1024\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-7-819x1024.png\" alt=\"\" class=\"wp-image-292\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-7-819x1024.png 819w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-7-240x300.png 240w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-7-768x960.png 768w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-7.png 1122w\" sizes=\"auto, (max-width: 819px) 100vw, 819px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Si quieres ver ejemplos de <em>instruction tuning<\/em> asociados a este proyecto, te invito a estar pendiente de las actualizaciones de este, en la siguiente p\u00e1gina: <a href=\"https:\/\/pulki.es\/medieval\/\">https:\/\/pulki.es\/medieval\/<\/a>.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--1 wp-block-paragraph\">Evaluaci\u00f3n de modelos entrenados mediante instruction tuning<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Como dijimos anteriormente, al instruir un modelo ocurren principalmente dos cosas. La primera es que el <strong>LLM <\/strong>aprende a responder los tipos de instrucciones y tareas presentes en los datos de entrenamiento. La segunda es que puede mejorar su habilidad general para seguir instrucciones, incluso cuando estas se refieren a tareas que no fueron incluidas expl\u00edcitamente en el dataset. Puesto que el objetivo principal de <em>instruction tuning<\/em> es mejorar esta segunda capacidad, su evaluaci\u00f3n natural consiste en examinar el desempe\u00f1o del modelo en tareas nuevas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Espec\u00edficamente, como explican <strong><a href=\"https:\/\/web.stanford.edu\/~jurafsky\/slp3\/\">Jurafsky y Martin (2026)<\/a><\/strong>, si nuestro objetivo es evaluar la capacidad general del modelo para seguir instrucciones \u2014el segundo punto\u2014, no basta con utilizar instrucciones nuevas si estas corresponden al mismo tipo de tarea que el modelo ya vio durante el entrenamiento. Es decir, si entrenamos al modelo con instrucciones relacionadas con:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Traducci\u00f3n<\/li>\n\n\n\n<li>Resumen<\/li>\n\n\n\n<li>Clasificaci\u00f3n de sentimiento<\/li>\n\n\n\n<li>Respuesta a preguntas<\/li>\n\n\n\n<li>Reescritura de textos<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Y luego lo evaluamos con nuevas instrucciones de traducci\u00f3n, podremos medir si el modelo mejor\u00f3 en esa tarea. Sin embargo, esto no nos asegura que haya desarrollado una habilidad m\u00e1s general para seguir instrucciones, pues la traducci\u00f3n ya formaba parte de los datos de entrenamiento. En este sentido, una evaluaci\u00f3n m\u00e1s adecuada consiste en dejar fuera una tarea durante el <em>instruction tuning<\/em> y utilizarla posteriormente para evaluar el modelo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Aprendizaje basado en preferencias<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Incluso despu\u00e9s de <em>instruction tuning<\/em>, el modelo puede seguir siendo susceptible de generar alucinaciones, producir respuestas poco \u00fatiles desde una perspectiva humana o entregar contenido inseguro. Una forma de abordar estos problemas consiste en utilizar aprendizaje basado en preferencias. En la introducci\u00f3n mencionamos esta idea en t\u00e9rminos generales. Ahora la explicaremos con mayor detalle; sin embargo, un buen ejercicio pedag\u00f3gico consiste en comenzar examinando c\u00f3mo se estructuran los datos utilizados para este tipo de entrenamiento.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--2 wp-block-paragraph\">\u00bfQu\u00e9 forma tienen los datos de preferencias?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El proyecto <a href=\"https:\/\/www.latamgpt.org\/about_us\">Latam-GPT<\/a> tambi\u00e9n dispone de una <a href=\"https:\/\/huggingface.co\/datasets\/latam-gpt\/es_llama-3.1-tulu-3-70b-preference-mixture\/viewer\/default\/train\">base de datos<\/a> de preferencias. A continuaci\u00f3n, mostraremos un ejemplo de c\u00f3mo se estructura una entrada de este conjunto de datos:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"282\" height=\"212\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-9.png\" alt=\"\" class=\"wp-image-299\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"324\" height=\"514\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-10.png\" alt=\"\" class=\"wp-image-300\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-10.png 324w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-10-189x300.png 189w\" sizes=\"auto, (max-width: 324px) 100vw, 324px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"377\" height=\"510\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-11.png\" alt=\"\" class=\"wp-image-301\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-11.png 377w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-11-222x300.png 222w\" sizes=\"auto, (max-width: 377px) 100vw, 377px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Como podemos ver, una entrada contiene un <em>prompt<\/em>, una respuesta elegida (<em>chosen<\/em>) y otra rechazada (<em>rejected<\/em>). Esto no significa necesariamente que la primera sea la \u00fanica respuesta correcta y la segunda sea completamente incorrecta; significa que, para ese <em>prompt<\/em>, una respuesta fue considerada preferible frente a la otra.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A partir de este ejemplo, el lector puede preguntarse de d\u00f3nde proviene el juicio que permite marcar una respuesta como <em>chosen<\/em> y otra como <em>rejected<\/em>. En general, existen tres fuentes principales de datos de preferencias. La primera consiste en utilizar evaluadores humanos, quienes comparan, seleccionan u ordenan m\u00faltiples respuestas generadas por un modelo ante un mismo <em>prompt<\/em>. La segunda consiste en extraer preferencias impl\u00edcitas de ciertos sitios web. Un ejemplo de este caso es StackExchange:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"606\" height=\"456\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-12.png\" alt=\"\" class=\"wp-image-303\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-12.png 606w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-12-300x226.png 300w\" sizes=\"auto, (max-width: 606px) 100vw, 606px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"591\" height=\"438\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-13.png\" alt=\"\" class=\"wp-image-304\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-13.png 591w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-13-300x222.png 300w\" sizes=\"auto, (max-width: 591px) 100vw, 591px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"580\" height=\"546\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-14.png\" alt=\"\" class=\"wp-image-305\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-14.png 580w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-14-300x282.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">En este caso, como podemos ver, podr\u00edamos considerar la pregunta original como el <em>prompt<\/em> y las respuestas publicadas por la comunidad como las alternativas candidatas. Los votos acumulados por cada respuesta permiten inferir cu\u00e1les fueron consideradas mejores; de esta forma, una respuesta mejor valorada puede tratarse como preferida frente a otra con menor valoraci\u00f3n.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por \u00faltimo, otra alternativa consiste en utilizar un LLM como evaluador. En este caso, distintos modelos pueden generar respuestas candidatas para un mismo <em>prompt<\/em>, y luego un <strong>LLM<\/strong> suficientemente potente puede compararlas u ordenarlas seg\u00fan su calidad. As\u00ed, el propio modelo evaluador permite generar datos sint\u00e9ticos de preferencias.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--3 wp-block-paragraph\">Preferencias por pares y puntuaciones por aspectos<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En la secci\u00f3n anterior dijimos que los evaluadores pod\u00edan seleccionar, ordenar o puntuar respuestas candidatas. En el caso de la selecci\u00f3n y el ordenamiento, el resultado puede representarse mediante preferencias entre pares de respuestas: por ejemplo, que la respuesta A es preferida sobre la respuesta B. En cambio, cuando hablamos de puntuar una respuesta, nos referimos a evaluarla individualmente en determinadas dimensiones, como su utilidad, honestidad, correcci\u00f3n o claridad.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cuando contamos con una preferencia entre pares, s\u00f3lo sabemos que, para un mismo <em>prompt<\/em>, una respuesta fue considerada mejor que otra. Es decir, tenemos una observaci\u00f3n como \u201cla respuesta A es preferida sobre la respuesta B\u201d, pero no contamos con una puntuaci\u00f3n individual asociada a cada una de ellas. En la pr\u00f3xima secci\u00f3n veremos c\u00f3mo imputar una puntuaci\u00f3n de este tipo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Modelando una preferencia<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Como dijimos anteriormente, cuando los evaluadores seleccionan una respuesta preferida entre dos alternativas generadas para un mismo <em>prompt<\/em>, no obtenemos una puntuaci\u00f3n expl\u00edcita para cada respuesta. S\u00f3lo sabemos que una fue preferida sobre la otra. Sin embargo, nos gustar\u00eda construir un modelo capaz de asignar una puntuaci\u00f3n num\u00e9rica a cada alternativa, de manera que podamos ordenarlas seg\u00fan qu\u00e9 tan preferibles resultan. La siguiente imagen ilustra esta idea:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"819\" height=\"1024\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-15-819x1024.png\" alt=\"\" class=\"wp-image-308\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-15-819x1024.png 819w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-15-240x300.png 240w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-15-768x960.png 768w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-15.png 1122w\" sizes=\"auto, (max-width: 819px) 100vw, 819px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Si bien en la imagen anterior mostramos s\u00f3lo dos respuestas, en un dataset de preferencias podemos tener m\u00faltiples respuestas candidatas para un mismo <em>prompt<\/em>. Supongamos, por ejemplo, que para un prompt <math data-latex=\"x\"><semantics><mi>x<\/mi><annotation encoding=\"application\/x-tex\">x<\/annotation><\/semantics><\/math> disponemos de ocho respuestas, <math data-latex=\"o_{A}, o_{B},...,o_{H}\"><semantics><mrow><msub><mi>o<\/mi><mi>A<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>B<\/mi><\/msub><mo separator=\"true\">,<\/mo><mi>.<\/mi><mi>.<\/mi><mi>.<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>H<\/mi><\/msub><\/mrow><annotation encoding=\"application\/x-tex\">o_{A}, o_{B},&#8230;,o_{H}<\/annotation><\/semantics><\/math>, y que los evaluadores han expresado las siguientes preferencias sobre algunos pares:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><math data-latex=\"o_{A} \\succ o_{B} | x\"><semantics><mrow><msub><mi>o<\/mi><mi>A<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>B<\/mi><\/msub><mi>|<\/mi><mi>x<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">o_{A} \\succ o_{B} | x<\/annotation><\/semantics><\/math><\/li>\n\n\n\n<li><math data-latex=\"o_{C} \\succ o_{D} | x\"><semantics><mrow><msub><mi>o<\/mi><mi>C<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>D<\/mi><\/msub><mi>|<\/mi><mi>x<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">o_{C} \\succ o_{D} | x<\/annotation><\/semantics><\/math><\/li>\n\n\n\n<li><math data-latex=\"o_{F} \\succ o_{E} | x\"><semantics><mrow><msub><mi>o<\/mi><mi>F<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>E<\/mi><\/msub><mi>|<\/mi><mi>x<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">o_{F} \\succ o_{E} | x<\/annotation><\/semantics><\/math><\/li>\n\n\n\n<li><math data-latex=\"o_{G} \\succ o_{H} | x\"><semantics><mrow><msub><mi>o<\/mi><mi>G<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>H<\/mi><\/msub><mi>|<\/mi><mi>x<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">o_{G} \\succ o_{H} | x<\/annotation><\/semantics><\/math><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">El s\u00edmbolo <math data-latex=\"\\succ\"><semantics><mo lspace=\"0em\" rspace=\"0em\">\u227b<\/mo><annotation encoding=\"application\/x-tex\">\\succ<\/annotation><\/semantics><\/math> significa \u201ces estrictamente preferida sobre\u201d. As\u00ed, la primera comparaci\u00f3n indica que, dado el <em>prompt<\/em> <math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><semantics><mrow><mi>x<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">x<\/annotation><\/semantics><\/math>, la respuesta A fue considerada mejor que la respuesta B.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A partir de estos juicios, nos gustar\u00eda modelar la probabilidad de que una respuesta sea preferida sobre otra para un mismo <em>prompt<\/em>. En t\u00e9rminos formales, queremos calcular:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>\u2119<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>o<\/mi><mi>i<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>j<\/mi><\/msub><mi>|<\/mi><mi>x<\/mi><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\mathbb{P}(o_{i}\\succ o_{j}|x)<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Es decir, queremos conocer qu\u00e9 tan probable es que la respuesta <math data-latex=\"o_{i}\"><semantics><msub><mi>o<\/mi><mi>i<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{i}<\/annotation><\/semantics><\/math> sea preferida sobre la respuesta <math data-latex=\"o_{j}\"><semantics><msub><mi>o<\/mi><mi>j<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{j}<\/annotation><\/semantics><\/math>, dado el <em>prompt<\/em> <math data-latex=\"x\"><semantics><mi>x<\/mi><annotation encoding=\"application\/x-tex\">x<\/annotation><\/semantics><\/math>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para ello, asumimos que cada respuesta tiene asociada una puntuaci\u00f3n latente, es decir, una puntuaci\u00f3n que no observamos directamente. Denotaremos la puntuaci\u00f3n de la respuesta <math data-latex=\"o_{i}\"><semantics><msub><mi>o<\/mi><mi>i<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{i}<\/annotation><\/semantics><\/math>como <math data-latex=\"z_{i}\"><semantics><msub><mi>z<\/mi><mi>i<\/mi><\/msub><annotation encoding=\"application\/x-tex\">z_{i}<\/annotation><\/semantics><\/math>\u200b. Bajo el modelo <strong>Bradley-Terry<\/strong>, la probabilidad de preferir una respuesta sobre otra depende de la diferencia entre sus puntuaciones:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>\u2119<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>o<\/mi><mi>i<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>j<\/mi><\/msub><mi>|<\/mi><mi>x<\/mi><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mi>\u03c3<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>z<\/mi><mi>i<\/mi><\/msub><mo>\u2212<\/mo><msub><mi>z<\/mi><mi>j<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\mathbb{P}(o_{i}\\succ o_{j}|x) = \\sigma(z_{i} &#8211; z_{j})<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">donde <math data-latex=\"\\sigma\"><semantics><mi>\u03c3<\/mi><annotation encoding=\"application\/x-tex\">\\sigma<\/annotation><\/semantics><\/math> corresponde a la funci\u00f3n sigmoide. Si ambas respuestas reciben puntuaciones similares, la probabilidad de preferir una sobre la otra ser\u00e1 cercana a <math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><semantics><mrow><mn>0.5<\/mn><\/mrow><annotation encoding=\"application\/x-tex\">0.5<\/annotation><\/semantics><\/math>. En cambio, si la puntuaci\u00f3n de <math data-latex=\"o_{i}\"><semantics><msub><mi>o<\/mi><mi>i<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{i}<\/annotation><\/semantics><\/math> es mucho mayor que la de <math data-latex=\"o_{j}\"><semantics><msub><mi>o<\/mi><mi>j<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{j}<\/annotation><\/semantics><\/math>, la probabilidad de preferir <math data-latex=\"o_{i}\"><semantics><msub><mi>o<\/mi><mi>i<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{i}<\/annotation><\/semantics><\/math> ser\u00e1 cercana a 1.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El problema es que las puntuaciones <math data-latex=\"z_{i}\"><semantics><msub><mi>z<\/mi><mi>i<\/mi><\/msub><annotation encoding=\"application\/x-tex\">z_{i}<\/annotation><\/semantics><\/math>\u200b no forman parte de nuestros datos. Los evaluadores s\u00f3lo nos informan que una respuesta fue preferida sobre otra; no nos entregan una puntuaci\u00f3n individual para cada salida. Por esta raz\u00f3n, necesitamos aprender una funci\u00f3n <math data-latex=\"r(x,o)\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><mi>o<\/mi><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x,o)<\/annotation><\/semantics><\/math> que, dado un <em>prompt<\/em> y una respuesta candidata, produzca una puntuaci\u00f3n escalar. De este modo, podemos reescribir la expresi\u00f3n anterior como:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>\u2119<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>o<\/mi><mi>i<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>j<\/mi><\/msub><mi>|<\/mi><mi>x<\/mi><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mi>\u03c3<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>i<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u2212<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>j<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\mathbb{P}(o_{i} \\succ o_{j}|x) = \\sigma(r(x,o_{i}) &#8211; r(x,o_{j}))<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">En otras palabras, <math data-latex=\"r(x,o_{i})\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>i<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x,o_{i})<\/annotation><\/semantics><\/math> representa la puntuaci\u00f3n que el modelo aprende a asignar a la respuesta <math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><semantics><mrow><msub><mi>o<\/mi><mi>i<\/mi><\/msub><\/mrow><annotation encoding=\"application\/x-tex\">o_i<\/annotation><\/semantics><\/math> en el contexto del <em>prompt<\/em> <math data-latex=\"x\"><semantics><mi>x<\/mi><annotation encoding=\"application\/x-tex\">x<\/annotation><\/semantics><\/math>. Esta funci\u00f3n debe aprenderse utilizando los datos de preferencias que ya tenemos. Para cada par observado, designaremos como <math data-latex=\"o_{w}\"><semantics><msub><mi>o<\/mi><mi>w<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{w}<\/annotation><\/semantics><\/math> a la respuesta preferida \u2014la <em>winner<\/em>\u2014 y como <math data-latex=\"o_{l}\"><semantics><msub><mi>o<\/mi><mi>l<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{l}<\/annotation><\/semantics><\/math> a la respuesta rechazada \u2014la <em>loser<\/em>. Puesto que el dataset indica que <math data-latex=\"o_{w}\"><semantics><msub><mi>o<\/mi><mi>w<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{w}<\/annotation><\/semantics><\/math> fue preferida sobre <math data-latex=\"o_{l}\"><semantics><msub><mi>o<\/mi><mi>l<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{l}<\/annotation><\/semantics><\/math>, utilizamos esa observaci\u00f3n como etiqueta de entrenamiento: el evento <math data-latex=\"o_{w} \\succ o_{l}\"><semantics><mrow><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><\/mrow><annotation encoding=\"application\/x-tex\">o_{w} \\succ o_{l}<\/annotation><\/semantics><\/math>\u200b recibe el valor objetivo <math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><semantics><mrow><mn>1<\/mn><\/mrow><annotation encoding=\"application\/x-tex\">1<\/annotation><\/semantics><\/math>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La funci\u00f3n de p\u00e9rdida de entrop\u00eda cruzada para un \u00fanico par viene dada por:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>L<\/mi><mrow><mi>C<\/mi><mi>E<\/mi><\/mrow><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2212<\/mo><mrow><mi>log<\/mi><mo>\u2061<\/mo><\/mrow><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>\u2119<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><mi>|<\/mi><mi>x<\/mi><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">L_{CE}(x,o_{w},o_{l}) = -\\log(\\mathbb{P}(o_{w}\\succ o_{l}|x))<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>L<\/mi><mrow><mi>C<\/mi><mi>E<\/mi><\/mrow><\/msub><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2212<\/mo><mrow><mi>log<\/mi><mo>\u2061<\/mo><\/mrow><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>\u03c3<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u2212<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">L_{CE}(x,o_{w},o_{l}) = -\\log(\\sigma(r(x,o_{w}) &#8211; r(x,o_{l})))<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Esta p\u00e9rdida ser\u00e1 alta cuando el modelo asigne una puntuaci\u00f3n mayor a la respuesta rechazada, o cuando apenas distinga entre ambas respuestas. Por el contrario, ser\u00e1 baja cuando la respuesta preferida reciba una puntuaci\u00f3n suficientemente mayor que la rechazada.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finalmente, la p\u00e9rdida sobre el conjunto de entrenamiento <math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><semantics><mrow><mi>D<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">D<\/annotation><\/semantics><\/math> se obtiene calculando este mismo criterio sobre todos los pares de preferencias disponibles:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>L<\/mi><mrow><mi>C<\/mi><mi>E<\/mi><\/mrow><\/msub><mo>=<\/mo><mo form=\"prefix\" stretchy=\"false\">\u2212<\/mo><msub><mi>\ud835\udd3c<\/mi><mrow><mo form=\"prefix\" stretchy=\"false\" lspace=\"0em\" rspace=\"0em\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u223c<\/mo><mi>D<\/mi><\/mrow><\/msub><mo form=\"prefix\" stretchy=\"false\">[<\/mo><mrow><mi>log<\/mi><mo>\u2061<\/mo><\/mrow><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>\u03c3<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u2212<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo form=\"postfix\" stretchy=\"false\">]<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">L_{CE} = -\\mathbb{E}_{(x,o_{w},o_{l})\\sim D}[\\log( \\sigma( r(x,o_{w}) &#8211; r(x,o_{l})) )]<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">En t\u00e9rminos simples, esta funci\u00f3n penaliza al modelo cada vez que sus puntuaciones no respetan adecuadamente las preferencias registradas en los datos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Evidentemente, para calcular esta p\u00e9rdida necesitamos un modelo capaz de producir los valores de <math data-latex=\"r(x,o)\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><mi>o<\/mi><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x,o)<\/annotation><\/semantics><\/math>. Una forma habitual de hacerlo consiste en convertir un <strong>LLM<\/strong> preentrenado en un <em>reward model<\/em>: se reemplaza su capa final de predicci\u00f3n de tokens por una capa lineal que produce un \u00fanico n\u00famero para cada combinaci\u00f3n de <em>prompt<\/em> y respuesta. As\u00ed, el modelo deja de generar texto y pasa a evaluar respuestas mediante una puntuaci\u00f3n escalar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durante el entrenamiento, el <em>reward model<\/em> eval\u00faa tanto la respuesta preferida como la rechazada, calcula la p\u00e9rdida anterior y ajusta sus par\u00e1metros entrenables mediante <em>backpropagation<\/em> y descenso de gradiente. Como resultado, las puntuaciones producidas por <math data-latex=\"r(x,o)\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><mi>o<\/mi><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x,o)<\/annotation><\/semantics><\/math> se vuelven progresivamente m\u00e1s coherentes con las preferencias observadas. A continuaci\u00f3n, explicaremos este proceso en mayor detalle.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--4 wp-block-paragraph\">1. Convertir un <strong>LLM<\/strong> en reward model<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Como muestra la imagen, un <em>reward model<\/em> puede construirse a partir de una arquitectura muy similar a la de un <strong>LLM<\/strong> generativo convencional. No obstante, ambos modelos se diferencian en la tarea que realizan y en el tipo de salida que producen.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"725\" src=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-16-1024x725.png\" alt=\"\" class=\"wp-image-312\" srcset=\"https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-16-1024x725.png 1024w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-16-300x212.png 300w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-16-768x543.png 768w, https:\/\/pulki.es\/blog\/wp-content\/uploads\/2026\/05\/image-16.png 1491w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">La diferencia principal se encuentra en la capa final del modelo. En un <strong>LLM<\/strong> generativo, esta capa se utiliza para producir probabilidades sobre los tokens que podr\u00edan continuar el texto. En cambio, para construir un <em>reward model<\/em>, la capa final de predicci\u00f3n de tokens se reemplaza por una capa lineal de puntuaci\u00f3n. De esta forma, la salida del modelo ya no es una continuaci\u00f3n textual, sino una \u00fanica puntuaci\u00f3n num\u00e9rica.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--5 wp-block-paragraph\">2. Bradley-Terry<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dado que el <em>reward model<\/em> produce una puntuaci\u00f3n para cada respuesta, podemos utilizar Bradley-Terry para convertir la diferencia entre dichas puntuaciones en una probabilidad de preferencia. Si estamos comparando las respuestas <math data-latex=\"o_{A}\"><semantics><msub><mi>o<\/mi><mi>A<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{A}<\/annotation><\/semantics><\/math> y <math data-latex=\"o_{B}\"><semantics><msub><mi>o<\/mi><mi>B<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{B}<\/annotation><\/semantics><\/math>\u200b para el <em>prompt<\/em> <math data-latex=\"x_{i}\"><semantics><msub><mi>x<\/mi><mi>i<\/mi><\/msub><annotation encoding=\"application\/x-tex\">x_{i}<\/annotation><\/semantics><\/math>\u200b, esta probabilidad viene dada por:<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><math data-latex=\"\\mathbb{P}(o_{A}\\succ o_{B}|x_{i})  = \\sigma(r(x_{i},o_{A})-r(x_{i},o_{B}))\"><semantics><mrow><mi>\u2119<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>o<\/mi><mi>A<\/mi><\/msub><mo>\u227b<\/mo><msub><mi>o<\/mi><mi>B<\/mi><\/msub><mi>|<\/mi><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>=<\/mo><mi>\u03c3<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>A<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u2212<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>B<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\mathbb{P}(o_{A}\\succ o_{B}|x_{i}) = \\sigma(r(x_{i},o_{A})-r(x_{i},o_{B}))<\/annotation><\/semantics><\/math><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Esta probabilidad puede contrastarse con la preferencia registrada en los datos. Supongamos, por ejemplo, que el evaluador humano prefiri\u00f3 <math data-latex=\"o_{A}\"><semantics><msub><mi>o<\/mi><mi>A<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{A}<\/annotation><\/semantics><\/math>\u200b sobre <math data-latex=\"o_{B}\"><semantics><msub><mi>o<\/mi><mi>B<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{B}<\/annotation><\/semantics><\/math>\u200b. A partir de esta situaci\u00f3n, podemos distinguir dos casos:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">a) El reward model est\u00e1 equivocado.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Supongamos que el evaluador humano prefiri\u00f3 <math data-latex=\"o_{A}\"><semantics><msub><mi>o<\/mi><mi>A<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{A}<\/annotation><\/semantics><\/math>\u200b sobre <math data-latex=\"o_{B}\"><semantics><msub><mi>o<\/mi><mi>B<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{B}<\/annotation><\/semantics><\/math>\u200b, pero el <em>reward model<\/em> produce:<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><math data-latex=\"r(x_{i},o_{B}) &gt; r(x_{i},o_{A})\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>B<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>&gt;<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>A<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x_{i},o_{B}) &gt; r(x_{i},o_{A})<\/annotation><\/semantics><\/math><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En este caso, la diferencia <math data-latex=\"r(x_{i},o_{A}) - r(x_{i},o_{B})\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>A<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u2212<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>B<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x_{i},o_{A}) &#8211; r(x_{i},o_{B})<\/annotation><\/semantics><\/math> es negativa. En consecuencia, Bradley-Terry asignar\u00e1 una probabilidad inferior a <math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><semantics><mrow><mn>0.5<\/mn><\/mrow><annotation encoding=\"application\/x-tex\">0.5<\/annotation><\/semantics><\/math> al evento de que <math data-latex=\"o_{A}\"><semantics><msub><mi>o<\/mi><mi>A<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{A}<\/annotation><\/semantics><\/math> sea preferida sobre <math data-latex=\"o_{B}\"><semantics><msub><mi>o<\/mi><mi>B<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{B}<\/annotation><\/semantics><\/math>\u200b. Como esta estimaci\u00f3n contradice la preferencia observada en los datos, la p\u00e9rdida ser\u00e1 alta y el entrenamiento deber\u00e1 ajustar los par\u00e1metros del <em>reward model<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">b) El <em>reward model<\/em> ordena correctamente las respuestas<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Si el evaluador humano prefiri\u00f3 <math data-latex=\"o_{A}\"><semantics><msub><mi>o<\/mi><mi>A<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{A}<\/annotation><\/semantics><\/math>\u200b sobre <math data-latex=\"o_{B}\"><semantics><msub><mi>o<\/mi><mi>B<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{B}<\/annotation><\/semantics><\/math>\u200b, y el <em>reward model<\/em> produce:<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><math data-latex=\"r(x_{i},o_{A}) &gt; r(x_{i},o_{B})\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>A<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>&gt;<\/mo><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><msub><mi>x<\/mi><mi>i<\/mi><\/msub><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>B<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x_{i},o_{A}) &gt; r(x_{i},o_{B})<\/annotation><\/semantics><\/math><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">entonces la diferencia entre puntuaciones es positiva y Bradley-Terry asignar\u00e1 una probabilidad superior a <math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\"><semantics><mrow><mn>0.5<\/mn><\/mrow><annotation encoding=\"application\/x-tex\">0.5<\/annotation><\/semantics><\/math> al evento de que <math data-latex=\"o_{A}\"><semantics><msub><mi>o<\/mi><mi>A<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{A}<\/annotation><\/semantics><\/math>\u200b sea preferida sobre <math data-latex=\"o_{B}\"><semantics><msub><mi>o<\/mi><mi>B<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{B}<\/annotation><\/semantics><\/math>. Adem\u00e1s, mientras mayor sea la diferencia a favor de <math data-latex=\"o_{A}\"><semantics><msub><mi>o<\/mi><mi>A<\/mi><\/msub><annotation encoding=\"application\/x-tex\">o_{A}<\/annotation><\/semantics><\/math>\u200b, mayor ser\u00e1 la probabilidad asignada a la preferencia observada y menor ser\u00e1 la p\u00e9rdida.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--6 wp-block-paragraph\">3. Se ajustan los par\u00e1metros del modelo<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En t\u00e9rminos generales, existen dos posibilidades para entrenar un <em>reward model<\/em>. La primera consiste en ajustar \u00fanicamente la nueva capa de puntuaci\u00f3n, manteniendo congelados los par\u00e1metros del transformer. La segunda consiste en ajustar la capa de puntuaci\u00f3n y permitir que tambi\u00e9n se actualicen algunos o todos los par\u00e1metros del transformer. Para comprender la diferencia entre ambas posibilidades, primero conviene explicar brevemente c\u00f3mo opera <em>backpropagation<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En t\u00e9rminos simples, <em>backpropagation<\/em> permite determinar qu\u00e9 par\u00e1metros entrenables deber\u00edan cambiar, y en qu\u00e9 direcci\u00f3n, para que la p\u00e9rdida producida por el modelo disminuya. Para entenderlo, recordemos primero el flujo normal de c\u00e1lculo de un <em>reward model<\/em>. Para una respuesta candidata, el modelo opera de la siguiente forma:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prompt + respuesta \u2192 Transformer \u2192 Representaci\u00f3n \u2192 Capa lineal \u2192 Puntuaci\u00f3n<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Como nuestros datos contienen una respuesta preferida y otra rechazada para un mismo <em>prompt<\/em>, este proceso se realiza para ambas respuestas:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prompt + respuesta preferida \u2192 Reward model \u2192  <math data-latex=\"r(x,o_{w})\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x,o_{w})<\/annotation><\/semantics><\/math><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prompt + respuesta rechazada \u2192 Reward model \u2192 <math data-latex=\"r(x,o_l)\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x,o_l)<\/annotation><\/semantics><\/math><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><math data-latex=\"r(x,o_{w})\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>w<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x,o_{w})<\/annotation><\/semantics><\/math> y <math data-latex=\"r(x,o_l)\"><semantics><mrow><mi>r<\/mi><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>x<\/mi><mo separator=\"true\">,<\/mo><msub><mi>o<\/mi><mi>l<\/mi><\/msub><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">r(x,o_l)<\/annotation><\/semantics><\/math> \u2192 P\u00e9rdida<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durante la pasada hacia adelante, el modelo calcula las puntuaciones de ambas respuestas y, a partir de ellas, la p\u00e9rdida. Luego, <em>backpropagation<\/em> recorre hacia atr\u00e1s el grafo de c\u00e1lculo utilizado para obtener esa p\u00e9rdida. Mediante la regla de la cadena, calcula c\u00f3mo cambiar\u00eda la p\u00e9rdida si se modificara cada par\u00e1metro entrenable del modelo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dicho de otro modo, si la respuesta preferida recibi\u00f3 una puntuaci\u00f3n demasiado baja respecto de la rechazada, <em>backpropagation<\/em> calcula qu\u00e9 cambios permitir\u00edan aumentar esa diferencia en la direcci\u00f3n correcta. Posteriormente, un algoritmo de optimizaci\u00f3n, como <em>gradient descent<\/em>, utiliza esos gradientes para actualizar los par\u00e1metros entrenables y reducir la p\u00e9rdida en las siguientes iteraciones.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una vez entendido esto, la diferencia entre las dos posibilidades de entrenamiento es sencilla. Si el <em>transformer<\/em> permanece congelado, \u00fanicamente se actualizan los par\u00e1metros de la capa lineal de puntuaci\u00f3n. En ese caso, el modelo aprende a asignar mejores puntuaciones utilizando las representaciones internas que el <em>transformer<\/em> ya era capaz de producir.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En cambio, si tambi\u00e9n permitimos ajustar par\u00e1metros del transformer, los gradientes pueden modificar no s\u00f3lo la capa de puntuaci\u00f3n, sino tambi\u00e9n las representaciones internas utilizadas para evaluar las respuestas. En este segundo caso, el modelo puede aprender a representar con mayor claridad los rasgos que hacen que una respuesta sea preferible frente a otra.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>Notas finales, y pr\u00f3xima entrada\u2026<\/em><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En este entrada vimos conceptos b\u00e1sicos sobre el proceso de post-training. Espec\u00edficamente, estudiamos c\u00f3mo hacer que el modelo sea mejor siguiendo instrucciones, y c\u00f3mo modelar preferencias, \u00fatil para producir respuestas mas afin con las que preferir\u00edan los humanos, y menos da\u00f1inas, entre otras cosas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En la pr\u00f3xima publicaci\u00f3n veremos Masked Language Models. Stay tuned!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Jos\u00e9 Miguel Mu\u00f1oz Urra \u2013&nbsp;<a href=\"mailto:jmunozu@pulki.es\">jmunozu@pulki.es<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Llegado a este punto, hemos visto la arquitectura necesaria para entrenar un LLM. Si bien, mediante la predicci\u00f3n del pr\u00f3ximo token y sampleo, este pre-entrenamiento es capaz de generar textos elocuentes, en muchos casos, las respuestas son deficientes, o da\u00f1inas. A modo de ejemplo, en el siguiente art\u00edculo se muestra la una salida particular del [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-281","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/281","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=281"}],"version-history":[{"count":28,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/281\/revisions"}],"predecessor-version":[{"id":322,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/posts\/281\/revisions\/322"}],"wp:attachment":[{"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=281"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=281"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pulki.es\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=281"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}