En la entrada anterior vimos n-gramas, cuyo concepto es fundamental para entender la generación de texto, característica que será clave para construir el LLM que tenemos en mente. Como mencionamos en una entrada pasada, si bien el algoritmo de generación de texto es importante a la hora de desarrollar un LLM, los datos en que el modelo es entrenado son igualmente importantes. Es por esto que aprender a clasificar textos es relevante para este proyecto.
En esta nueva publicación veremos en detalle la regresión logística, y cómo se puede aplicar a la clasificación de texto. Como es habitual, usaremos como referencia el libro de Jurafsky y Martin, 2025 (capítulo 4).
¿Qué entenderemos por clasificar?
De acuerdo con Jurafsky y Martin (2025), el objetivo principal de clasificar, cuando se trata de un texto, es extraer características relevantes de este y, a partir de ellas, asignarlo a una categoría. A modo de ejemplo, supongamos que queremos etiquetar un texto entre dos categorías mutuamente excluyentes. Concretamente, deseamos determinar si está escrito en castellano medieval. En ese caso, tendremos una variable llamada si el texto está escrito en castellano medieval, y en caso contrario. Ahora bien, en consecuencia con esta definición, debemos determinar cuáles serán las características relevantes para la clasificación. En este sentido, es sabido que en castellano medieval, “suso” y “yuso” eran adverbios de lugar comúnmente utilizados. Por tanto, una variable aparentemente válida para identificar si un texto es medieval podría ser el número de veces que aparecen las palabras “suso” o “yuso”. Llamaremos a esta variable yu_su.
En este punto nos enfrentamos a los primeros desafíos. Por una parte, que esas palabras no aparezcan no implica que el texto no sea medieval, y que aparezcan tampoco implica necesariamente que lo sea. En otras palabras, si nos basáramos sólo en esta variable, podríamos cometer tanto falsos positivos como falsos negativos. Por este motivo, es preciso añadir variables que nos entreguen más indicios sobre la naturaleza del texto. Para ello, podríamos pensar en una variable binaria, llamada cont_words, que tome el valor de 1 si el texto contiene palabras como internet, blog, ordenador, teléfono, electrónico, fútbol, globalización, etc., es decir, palabras que no existían en el castellano medieval o que, al menos, no eran comunes. En la práctica, podríamos repetir este ejercicio incorporando múltiples variables. No obstante, para efectos de este ejemplo consideraremos sólo estas dos.
A partir de aquí, es preciso definir un umbral de decisión para discernir si el texto es medieval o no. A modo de ejemplo, podemos imponer la siguiente regla:
Si
yu_sues mayor que 5 ycont_wordses igual a 0, entonces el texto es medieval.
En este caso, 5 y 0 son umbrales arbitrarios elegidos únicamente para ilustrar el ejemplo. Sin embargo, si analizáramos un conjunto grande de textos medievales y no medievales, podríamos encontrar puntos de corte relativamente buenos para discriminar entre ambas clases.
Claro está que, además del criterio anterior, podríamos proponer muchas otras reglas. No obstante, en esta entrada nos enfocaremos en la regresión logística binaria.
Regresión binaria logística
Supongamos que disponemos de un vector de características , donde corresponde al número total de veces que aparece la palabra “yuso” o “suso” (yu_su), y es una variable binaria que indica si existen palabras contemporáneas (cont_words). Dado ese vector, nuestro objetivo es calcular . Esta cantidad nos dirá qué tan probable es que el texto de entrada sea medieval, condicional a las características extraídas. Para obtener esta probabilidad, la regresión logística supone la siguiente estructura:
donde representa el peso asociado a cada variable al momento de determinar si el texto es medieval o no, y corresponde al término de sesgo.
Puesto que puede tomar cualquier valor real, no necesariamente estará entre 0 y 1. Por esa razón, no podemos interpretarlo directamente como una probabilidad. Para hacerlo, lo pasaremos por la función sigmoide, es decir,
Esto asegura que
Por tanto, siempre tomará valores entre 0 y 1. Además, nuestras probabilidades deben cumplir que
de modo que podemos definir
Esto implica que
Con esto presente, ya podemos calcular . Ahora solo falta definir el umbral que determinará cuándo un texto será clasificado como medieval o no. Usualmente, se considera que una probabilidad superior a es suficiente para asignar el texto a la clase positiva, es decir,
Definido el umbral, ya estamos en condiciones de aprender los parámetros del modelo. En la siguiente sección veremos cómo hacerlo.
Aprendiendo los parámetros del modelo
Queremos elegir unos parámetros tales que, si el texto que estamos analizando es medieval, es decir, si , la probabilidad estimada sea lo más alta posible, esto es, .
Para lograrlo, comúnmente se utiliza una función que mide qué tan distinta es la predicción del modelo respecto del valor real. Esta función, llamada función de pérdida, debe ser lo más pequeña posible. En el caso de la regresión logística, la pérdida que se usa habitualmente es la cross-entropy loss, que también puede interpretarse como la negative log likelihood.
En términos matemáticos, la función de pérdida puede escribirse como , donde
En este caso, la estrategia que emplearemos para encontrar , y será la máxima verosimilitud. La idea es simple: escogeremos los parámetros que hagan lo más probable posible observar las etiquetas correctas en los datos de entrenamiento. Como la log-verosimilitud debe maximizarse, y la función de pérdida se define como su negativo, maximizar la verosimilitud es equivalente a minimizar la función de pérdida.
Para derivar la función de pérdida, debemos empezar por expresar la probabilidad de una observación individual. Puesto que tenemos una variable binaria, dicha probabilidad viene dada por:
Al tomar logaritmos obtenemos:
Esta es la log-verosimilitud que queremos maximizar. Sin embargo, como en aprendizaje automático solemos trabajar minimizando una pérdida, definimos:
Reemplazando, llegamos a:
y, usando , obtenemos finalmente:
Esta es la función de pérdida que usaremos para aprender los parámetros del modelo.
En este punto, estamos en condiciones de trabajar con los datos, y así obtener , , , y . Para esto, extraeremos 20 textos escritos en castellano medieval de esta web, y 20 textos contemporáneos: 19 periodísticos y un artículo académico referente a las palabras “yuso” y “suso”. La siguiente tabla muestra el valor de cada variable:
medieval | yu_su | cont_words |
| 1 | 74 | 0 |
| 1 | 18 | 0 |
| 1 | 3 | 0 |
| 1 | 8 | 0 |
| 1 | 19 | 0 |
| 1 | 0 | 0 |
| 1 | 6 | 0 |
| 1 | 57 | 1 |
| 1 | 26 | 0 |
| 1 | 166 | 0 |
| 1 | 2 | 0 |
| 1 | 396 | 0 |
| 1 | 1 | 0 |
| 1 | 65 | 1 |
| 1 | 1 | 0 |
| 1 | 62 | 0 |
| 1 | 8 | 0 |
| 1 | 11 | 1 |
| 1 | 3 | 1 |
| 1 | 65 | 0 |
| 0 | 194 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 1 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
| 0 | 0 | 0 |
Curiosamente, cont_words, que es una dummy cuyo valor es 1 si el texto contiene palabras contemporáneas, toma el valor 1 con mayor frecuencia en los textos medievales. Esto se debe la palabra ordenador aparece en esta clase de textos, como se puede ver en el siguiente fragmento de castellano medieval:
se<n>naladamientre q<ue> fue mayor dellos;
de qui tiene logar. E aun onrran a
toda la xp<ist>iandat; cuya cabeça es. cuemo ordenador & mantenedor de la ley.
Además, podemos observar que existe un texto no medieval cuyo conteo de palabras «yuso» o «suso» es alto. Como mencionamos anteriormente, esa observación corresponde al artículo académico que analiza ambas palabras. Dicho esto, a continuación, mostramos los resultados de la estimación:

Los pesos de yu_su y cont_words son positivos, eso quiere decir que aportan positivamente a la probabilidad de que un texto sea medieval. En la siguiente sección veremos cómo emplear la información de la tabla para predecir si un texto fuera de nuestro conjunto de entrenamiento es medieval.
Predicción de categoría
Con la información de la tabla, podemos escribir la siguiente ecuación:
En este punto, sólo necesitamos calcular yu_su y cont_words para el texto que queramos analizar, que en este caso será el Libro de Apolonio, escrito en castellano medieval. Sus valores son:
yu_su | cont_words |
| 1 | 0 |
Puesto que este texto solo contiene la palabra “suso”, y cont_words es cero, la probabilidad de que el texto sea medieval es relativamente baja con respecto al umbral (0.386), por tanto, el clasificador lo etiqueta como texto no medieval.
Ahora, por el contrario, si tomamos un texto periodístico sobre deportes, tenemos los siguientes valores:
yu_su | cont_words |
| 0 | 1 |
Debido a que en este texto aparece la palabra fútbol, cont_words vale 1, y la probabilidad de que el texto sea medieval se dispara (0.741), clasificando nuevamente el texto de forma errónea, es decir, esta vez es etiquetado como medieval.
Claramente, en este caso necesitamos añadir más variables, y revisar los criterios actuales, entre ellos, definir uno en el que el peso de cont_words no sea positivo.
Como pudimos observar en este ejercicio, el rendimiento del modelo es visiblemente deficiente, no obstante, en muchos casos, calificar su performance no es trivial. Por este motivo, en la siguiente sección introduciremos un método para evaluar el desempeño del clasificador.
Evaluación
Antes de abordar las estrategias de evaluación, conviene definir qué entendemos por gold label. En nuestro caso, el objetivo del modelo es clasificar si un texto es medieval o no. Para ello, la regresión logística no entrega directamente una etiqueta definitiva, sino una probabilidad , es decir, una estimación de cuán probable es que el texto pertenezca a la clase “medieval”. Sin embargo, desde el punto de vista del conjunto de datos, cada texto sí tiene una clasificación de referencia: o es medieval, o no lo es. Esa etiqueta correcta, asignada por criterio humano, es lo que llamamos gold label.
Una métrica para evaluar el desempeño de nuestro modelo, es construir una matriz de confusión, que en pocas palabras grafica como se desempeña en términos de los gold labels y las etiquetas que este predice. La siguiente imagen muestra cómo se vería esta matriz:

En esta matriz podemos observar tres métricas importantes: precisión, recall y accuracy. Usualmente, accuracy no es una buena métrica por dos motivos. El primero es que, si las categorías están desbalanceadas, es decir, si hay muchos más textos no medievales que textos medievales, un clasificador que prediga siempre la clase mayoritaria podría obtener un accuracy alto, aun cuando fuera incapaz de detectar textos medievales. Si bien en nuestra aplicación estamos trabajando con una cantidad balanceada de textos medievales y no medievales, en la práctica esto no siempre ocurre. El segundo problema de esta métrica es que combina en un solo valor los verdaderos positivos (VP) y los verdaderos negativos (VN). Esto puede ser problemático si queremos que el modelo sea especialmente bueno encontrando textos medievales, ya que, mirando únicamente el accuracy, no podemos distinguir si el modelo destaca por identificar bien los textos medievales o simplemente por clasificar correctamente los textos no medievales.
Por este motivo, precisión y recall suelen ser métricas más informativas que accuracy. En nuestro caso, la precisión sería especialmente útil si queremos que, cada vez que el modelo clasifique un texto como medieval, esa predicción sea confiable. En otras palabras, la precisión mide qué proporción de los textos etiquetados por el modelo como medievales efectivamente pertenece a esa categoría.
No obstante, recall también puede ser de gran utilidad, ya que mide qué proporción de los textos medievales reales fue efectivamente identificada por el modelo.
Puesto que ambos indicadores aportan información relevante, es posible combinarlos en una sola métrica llamada F-measure:
donde mide la importancia de recall o precisión. favorece recall, favorece precisión, y asigna el mismo peso a ambas.
Regularización
El diseño original de este ejemplo contemplaba solo la variable yu_su, de modo que el modelo quedaba reducido a
Además, el texto del artículo académico en el que aparecían las palabras “yuso” y “suso” no formaba parte del conjunto de entrenamiento. En nuestra muestra, todos los textos medievales contenían al menos una vez una de esas palabras y, al mismo tiempo, ningún texto contemporáneo las contenía. Como consecuencia, la variable yu_su funcionaba como un predictor perfecto dentro del training set.
Esto generaba un problema importante: el modelo aprendía a asociar de manera excesivamente fuerte la presencia de “yuso” o “suso” con la clase medieval. En otras palabras, se ajustaba demasiado bien a los datos de entrenamiento. Así, cuando enfrentábamos al modelo a un texto nuevo —por ejemplo, un artículo académico contemporáneo que mencionaba esas palabras—, este tendía a clasificarlo como medieval, aunque en realidad no lo fuera.
En términos generales, este fenómeno se conoce como overfitting: el modelo reproduce muy bien los patrones del conjunto de entrenamiento, pero pierde capacidad de generalización sobre datos no vistos. La regularización busca mitigar justamente este problema, penalizando pesos demasiado grandes y obligando al modelo a aprender reglas menos extremas.
Si bien, para mitigar el problema original que tuvimos en el diseño del ejemplo, una solución es añadir más variables que capturen características más generales del castellano medieval, otra estrategia para evitar el overfitting consiste en incorporar un término de regularización a la función objetivo, de la siguiente forma:
El objetivo de este nuevo término es penalizar pesos demasiado grandes. De este modo, una configuración de parámetros que ajusta perfectamente el conjunto de entrenamiento, pero lo hace mediante pesos muy altos, será menos preferida que otra que ajuste un poco peor, aunque con pesos más pequeños. En este sentido, mientras mayor sea , mayor será la penalización y, por tanto, menor tenderá a ser la magnitud de los parámetros del modelo.
Existen dos tipos de regularización especialmente populares. La primera es lasso, que corresponde a la regularización L1:
La segunda es ridge, que corresponde a la regularización L2:
Qué enfoque conviene usar dependerá de la aplicación. Por una parte, ridge suele ser más fácil de optimizar, ya que su derivada es simple, mientras que lasso es más complejo porque el valor absoluto no es diferenciable en cero. Por otra parte, en términos de los pesos resultantes, ridge tiende a preferir vectores con muchos pesos pequeños, mientras que lasso favorece soluciones dispersas: algunos pesos pueden conservar valores relativamente grandes, pero muchos otros son llevados exactamente a cero. En consecuencia, lasso tiende a producir modelos con menos variables activas que ridge.
Notas finales, y próxima entrada…
En esta entrega vimos cómo clasificar texto mediante regresión logística, así como algunas de las complicaciones que pueden surgir en su aplicación. Aunque trabajamos con el caso de una variable dependiente binaria, este modelo puede generalizarse a categorías. Esa versión más general se explica en detalle en el capítulo 4 de Jurafsky y Martin.
En la próxima entrada veremos que son los embeddings y por qué son una forma central de representar el significado de las palabras en NLP. Stay tuned!
José Miguel Muñoz Urra – jmunozu@pulki.es