Curso de Matemáticas para IA · Lección 8 de 180

Logaritmos para IA: evita que desaparezcan los productos de probabilidad diminutos

Aprende los logaritmos como potencias inversas, deriva las leyes que convierten productos en sumas y usa puntuaciones logarítmicas de NumPy para distinguir productos de probabilidad que float64 redondea a cero.

Comparte este artículo

En un ejemplo simplificado de puntuación de secuencias, un modelo de lenguaje pequeño asigna una probabilidad de 0.10.1 a cada token elegido. Una secuencia con 400 elecciones de este tipo tiene el producto matemáticamente distinto de cero

0.1×0.1××0.1400 factors=(0.1)400=10400.\underbrace{0.1\times0.1\times\cdots\times0.1}_{400\text{ factors}} =(0.1)^{400}=10^{-400}.

Añade un token más con la misma probabilidad y el producto es 1040110^{-401}. Son dos números positivos distintos, pero NumPy almacena ambos productos como 0.0 al calcularlos con números de coma flotante de 64 bits. Una clasificación basada en los productos almacenados ha perdido la diferencia.

Los logaritmos conservan una representación más útil: los dos productos se convierten en las sumas finitas 400ln(0.1)921.034037400\ln(0.1)\approx-921.034037 y 401ln(0.1)923.336622401\ln(0.1)\approx-923.336622. Al terminar esta lección podrás leer un logaritmo como una potencia inversa, derivar las leyes que convierten productos en sumas, calcular a mano la puntuación de una secuencia corta e implementar la misma idea sin fingir que el espacio logarítmico elimina todos los límites numéricos.

Esta lección invierte la operación de exponenciación desarrollada en Lección 7: Potencias para IA, que es la página localizada correspondiente del Translation Set de cuatro idiomas del curso. El Mathematics for Machine Learning companion oficial divide su recorrido entre los fundamentos matemáticos y los problemas de aprendizaje automático que los utilizan. Su capítulo introductorio motiva construir fundamentos antes de apoyarse en modelos probabilísticos; las matemáticas de logaritmos que siguen son un puente original hacia la probabilidad, no una definición atribuida al capítulo 1.

La respuesta que falta es un exponente

Un logaritmo plantea una pregunta precisa: ¿qué exponente produce este número positivo a partir de la base elegida?

Por ejemplo, log2(8)=3\log_2(8)=3 porque 23=82^3=8, mientras que log10(0.01)=2\log_{10}(0.01)=-2 porque 102=0.0110^{-2}=0.01. La respuesta negativa es un exponente, no una entrada negativa.

En computación aparecen a menudo tres bases:

NombreNotación usada aquíBaseUna lectura útil
Logaritmo comúnlog10(x)\log_{10}(x)1010Órdenes de magnitud decimales
Logaritmo naturalln(x)=loge(x)\ln(x)=\log_e(x)e2.71828e\approx2.71828Fórmulas de probabilidad y optimización
Logaritmo binariolog2(x)\log_2(x)22Duplicaciones y potencias de dos

Algunos campos escriben log sin base, pero la convención no es universal. En esta lección escribimos ln\ln para el logaritmo natural e incluimos un subíndice para las demás bases. NumPy sigue la misma elección práctica: numpy.log calcula el logaritmo natural elemento por elemento.

La relación inversa proporciona dos comprobaciones cuando ambas expresiones están en sus dominios reales:

logb(by)=yandblogb(x)=x.\log_b(b^y)=y \qquad\text{and}\qquad b^{\log_b(x)}=x.

La multiplicación deja un rastro aditivo

La ley del producto no es un patrón que haya que memorizar de forma aislada. Se deduce directamente de la ley de los exponentes de la lección 7.

Toma números positivos aa y cc, y usa una base de logaritmo válida b>0b>0, b1b\ne1. Sea

u=logb(a)andv=logb(c).u=\log_b(a)\quad\text{and}\quad v=\log_b(c).

La definición dice que a=bua=b^u y c=bvc=b^v. Al multiplicar y aplicar la ley de exponentes de la misma base obtenemos

ac=bubv=bu+v.ac=b^u b^v=b^{u+v}.

Por tanto, el exponente que produce acac es u+vu+v:

logb(ac)=logb(a)+logb(c).\boxed{\log_b(ac)=\log_b(a)+\log_b(c)}.

La división resta exponentes bajo los mismos supuestos:

ac=bubv=buvlogb ⁣(ac)=logb(a)logb(c).\frac{a}{c}=\frac{b^u}{b^v}=b^{u-v} \quad\Longrightarrow\quad \boxed{\log_b\!\left(\frac{a}{c}\right)=\log_b(a)-\log_b(c)}.

Elevar un número positivo a una potencia real rr multiplica su exponente:

ar=(bu)r=brulogb(ar)=rlogb(a).a^r=(b^u)^r=b^{ru} \quad\Longrightarrow\quad \boxed{\log_b(a^r)=r\log_b(a)}.

La positividad es esencial en las tres leyes: a>0a>0 y c>0c>0 mantienen definidos todos los logaritmos reales, y c>0c>0 también mantiene distinto de cero el denominador del cociente.

La suma no sigue la ley del producto. Como contraejemplo rápido,

ln(2+3)=ln(5)1.609438,\ln(2+3)=\ln(5)\approx1.609438,

pero

ln(2)+ln(3)=ln(6)1.791759.\ln(2)+\ln(3)=\ln(6)\approx1.791759.

Por tanto, en general log(a+c)log(a)+log(c)\log(a+c)\ne\log(a)+\log(c). Más adelante se presenta una operación estable para sumar valores que ya están almacenados como logaritmos, deliberadamente distinta de la conversión de producto a suma.

Cuatro elecciones de tokens, resueltas en ambas representaciones

Supón que dos continuaciones candidatas contienen cuatro elecciones de tokens cada una. Para este cálculo pequeño, considera cada pip_i indicado como la probabilidad condicional positiva del modelo para el token elegido en la posición ii. Multiplicar los cuatro factores produce una puntuación de secuencia; sumar sus logaritmos naturales produce la log-probabilidad correspondiente. Para una secuencia observada fija bajo el modelo, estas puntuaciones también se llaman su verosimilitud y log-verosimilitud. Las lecciones posteriores desarrollarán toda la maquinaria de probabilidad y estimación; aquí solo hay que calcular y comparar las dos representaciones.

El producto de la candidata A es el doble que el de la candidata B. Su puntuación logarítmica también es mayor: 7.824046>8.517193-7.824046>-8.517193. Ese orden está garantizado porque ln\ln tiene base e>1e>1 y es estrictamente creciente. “Mayor” entre puntuaciones logarítmicas negativas significa más cerca de cero. La puntuación no se convirtió en una probabilidad después del logaritmo; se convirtió en una representación de esta que facilita la comparación.

Binary64 llega a cero mientras la puntuación logarítmica sigue cambiando

Los ordenadores no pueden almacenar todos los números reales. Number de JavaScript y float64 de NumPy usan el formato de coma flotante binary64. NumPy informa de sus límites de máquina mediante numpy.finfo: el valor float64 normal positivo más pequeño es aproximadamente 2.2250738585072014×103082.2250738585072014\times10^{-308}. Los valores subnormales positivos llenan parte de la brecha entre ese número y cero, pero con menor precisión; el subnormal positivo más pequeño es aproximadamente 4.9406564584124654×103244.9406564584124654\times10^{-324}. numpy.nextafter confirma que este es el siguiente flotante representable después de cero en la dirección positiva.

Mueve cualquiera de los controles deslizantes con el puntero o las flechas. El panel superior sigue la multiplicación binary64 directa por la región normal, la estrecha franja subnormal y el cero. El panel inferior sigue el valor aditivo finito nln(p)n\ln(p). La línea continua con un círculo y la discontinua con un cuadrado siguen siendo distinguibles sin color, y la tabla muestra el estado seleccionado y las filas de transición.

Repite una probabilidad positiva p hasta 2.000 factores. El producto binary64 directo puede pasar de normal a subnormal y luego a cero, mientras la suma acumulada de logaritmos naturales permanece finita. La lectura usa cuatro cifras significativas para productos diminutos en lugar de insinuar una precisión no disponible.

Elige p entre 0.01 y 0.50. Las flechas lo cambian en 0.01.

0,10

Elige entre 1 y 2.000 factores repetidos. Las flechas cambian el número de uno en uno.

400
Producto directo: línea continua y círculoSuma logarítmica: línea discontinua y cuadradoNúmero seleccionado: guía punteada
Producto de probabilidad directo y suma logarítmica acumuladaDos gráficos apilados verticalmente comparten el número de factores en el eje horizontal. La línea continua superior con un círculo desciende por las regiones binary64 normal y subnormal antes de continuar como una línea de cero punteada. La línea discontinua inferior con un cuadrado sigue siendo una suma acumulada finita y recta de logaritmos naturales. Las guías verticales punteadas marcan el número seleccionado.Producto binary64 directo y representabilidad0-100-200-300Valores normalesSubnormal: franja estrecha sobre el límite inferiorCero: límite inferior punteadomagnitud log₁₀ de pⁿSuma de logaritmos naturales acumulada-0-1151-2303-3454-46050500100015002000n ln(p)Número de factores n
Producto binary64 directo
0
Suma logarítmica acumulada
-921,034037
Estado del producto directo
Cero
Primer número de factores con producto subnormal
308
Primer número de factores con producto cero
324

Para p = 0,10 repetido 400 veces, el producto binary64 directo es 0 (Cero); la suma logarítmica acumulada es -921,034037.

Para p = 0,10 repetido 400 veces, el producto binary64 directo es 0 (Cero); la suma logarítmica acumulada es -921,034037.

Los productos directos diminutos se redondean a cuatro cifras significativas en esta vista. La tabla y las etiquetas de estado, no los decimales adicionales, identifican la transición de representabilidad.

Mostrar los valores seleccionados y de frontera como tabla
Productos binary64 directos y sumas de logaritmos naturales acumuladas en los valores seleccionados y los hitos de representabilidad
Número de factores nProducto directoSuma logarítmica acumuladaEstado del producto directo
11.000e-1-2,302585Normal
3071.000e-307-706,893624Normal
3081.000e-308-709,196209Subnormal
3239.881e-324-743,734985Subnormal
3240-746,037570Cero
4000-921,034037Cero ← Seleccionado
20000-4605,170186Cero

En el estado inicial renderizado por el servidor, p=0.10p=0.10 y n=400n=400. La multiplicación directa ya ha producido cero, pero 400ln(0.10)=921.034037400\ln(0.10)=-921.034037\ldots es finita. El valor logarítmico conserva una puntuación aditiva para los factores positivos. Llamar a exp(921.034037)\exp(-921.034037\ldots) en float64 sigue devolviendo cero, porque cambiar la representación no puede crear un valor float64 positivo por debajo del rango del formato.

La transición exacta depende del tipo de datos, los valores y el orden de las operaciones de coma flotante. El explorador modela deliberadamente la multiplicación binary64 repetida; no es un umbral universal para todos los programas de probabilidad.

NumPy refleja la ruta segura

El siguiente programa se ejecutó con NumPy 2.5.2. La multiplicación directa usa np.prod, mientras que la acumulación en el espacio logarítmico usa el logaritmo natural elemento a elemento documentado por numpy.log, seguido de una suma.

import numpy as np

for n in (323, 324, 400, 401):
    factors = np.full(n, 0.1, dtype=np.float64)
    direct = np.prod(factors)
    log_score = np.log(factors).sum()
    print(f"n={n}: direct={direct:.4e}, log_score={log_score:.6f}")

limits = np.finfo(np.float64)
print(f"smallest normal:    {limits.smallest_normal:.4e}")
print(f"smallest subnormal: {limits.smallest_subnormal:.4e}")
print(f"next after zero:    {np.nextafter(0.0, 1.0):.4e}")
n=323: direct=9.8813e-324, log_score=-743.734985
n=324: direct=0.0000e+00, log_score=-746.037570
n=400: direct=0.0000e+00, log_score=-921.034037
n=401: direct=0.0000e+00, log_score=-923.336622
smallest normal:    2.2251e-308
smallest subnormal: 4.9407e-324
next after zero:    4.9407e-324

Los productos de 400 y 401 factores coinciden en cero al almacenarse, mientras sus puntuaciones logarítmicas mantienen el orden. En la práctica, un sistema que necesite comparar productos candidatos puede conservar las puntuaciones logarítmicas y elegir la mayor sin exponenciar cada puntuación. Este es el beneficio numérico concreto: los factores multiplicativos positivos se convierten en puntuaciones aditivas finitas. No repara entradas inválidas, redondeos de otras operaciones ni una conversión final cuyo resultado sea demasiado pequeño para el tipo elegido.

Sumar probabilidades alternativas requiere otra identidad. Si x=ln(a)x=\ln(a) y y=ln(c)y=\ln(c), entonces

ln(a+c)=ln(ex+ey),\ln(a+c)=\ln(e^x+e^y),

no x+yx+y. La función de NumPy numpy.logaddexp calcula directamente ese logaritmo de una suma. Para dos alternativas ya logaritmadas, x=1000x=-1000 y y=1001y=-1001:

x, y = -1000.0, -1001.0

with np.errstate(divide="ignore"):
    naive = np.log(np.exp(x) + np.exp(y))

stable = np.logaddexp(x, y)
print(naive)
print(stable)
print(np.exp(stable))
-inf
-999.6867383124818
0.0

La ruta ingenua exponencia demasiado pronto y convierte ambas alternativas en cero. np.logaddexp conserva su puntuación logarítmica combinada finita. Exponenciar esa puntuación aún produce underflow, exactamente como muestra la última línea. Usa sum(log_factors) para un producto de factores positivos; usa logaddexp al sumar alternativas que ya están representadas por valores logarítmicos.

Límites que conviene hacer explícitos

El dominio y las condiciones de base del logaritmo real evitan varios errores comunes:

Entrada o afirmaciónResultado del log realMotivo
x>0x>0, b>0b>0, b1b\ne1VálidoExiste un único exponente real
x=0x=0No definido como logaritmo realNingún exponente finito hace que una base positiva sea cero
x<0x<0No definido en los realesUna base válida elevada a un exponente real permanece positiva
b=1b=1Base no válida1y=11^y=1 para todo yy, así que no existe función inversa
b0b\le0No válido para esta definiciónLas potencias reales no producen todos los argumentos positivos de forma coherente
logb(a+c)=logb(a)+logb(c)\log_b(a+c)=\log_b(a)+\log_b(c)Falso en generalEl lado derecho equivale a logb(ac)\log_b(ac)

Para arrays de valores reales, NumPy sigue las convenciones de coma flotante en torno a este límite: np.log(0.0) devuelve -inf y señala una división por cero, mientras que np.log(-1.0) devuelve nan y señala una operación no válida. Son valores de máquina útiles, no permiso para borrar la distinción matemática. Un factor cuya probabilidad es realmente cero aporta -\infty a la puntuación logarítmica; un producto positivo que se redondeó a cero de coma flotante debería haberse pasado a logaritmo antes de multiplicar. Una vez que el producto ya es cero, np.log(product) no puede reconstruir los factores perdidos.

Sustituir ceros silenciosamente por una constante positiva pequeña también cambia los valores declarados por el modelo. Si el recorte es una decisión de modelado intencional, registra la regla en lugar de presentarlo como aritmética exacta.

Por último, la dirección de la clasificación depende de la base. Para toda base b>1b>1 —incluidas ee, 22 y 1010— el logaritmo es creciente, de modo que el producto positivo mayor tiene el valor logarítmico mayor. Una base válida entre cero y uno produce un logaritmo decreciente e invierte ese orden. Las implementaciones de log-probabilidad suelen usar e>1e>1; por eso la puntuación logarítmica menos negativa ocupa una posición superior.

Una puntuación finita puede ser el resultado útil

Las secuencias iniciales no necesitaron convertir sus probabilidades microscópicas de nuevo a forma decimal para seguir siendo distinguibles. Sus puntuaciones logarítmicas conservaron la comparación multiplicativa como una suma ordinaria, y las leyes de producto, cociente y potencia explican por qué funciona esa representación.

Esta base sustentará lecciones posteriores sobre probabilidad, estimación basada en verosimilitud, entropía y cálculos estables de modelos. El siguiente paso del currículo cambia el foco a las ecuaciones como restricciones y a los conjuntos de valores que las satisfacen. Por ahora, el punto práctico de parada es exacto: mantén los factores positivos en el espacio logarítmico al combinarlos y compararlos, y vuelve al espacio de probabilidades solo cuando el resultado sea necesario y representable.

Comprueba tu comprensión

Pregunta 1

Calcula log₂(32) y log₁₀(0.001), y comprueba cada respuesta con una potencia.

Mostrar la solución paso a paso

Para log2(32)\log_2(32), pregunta qué exponente de 22 produce 3232:

25=32log2(32)=5.2^5=32 \quad\Longrightarrow\quad \log_2(32)=5.

Para log10(0.001)\log_{10}(0.001), reescribe el decimal como una potencia de diez:

0.001=11000=103log10(0.001)=3.0.001=\frac{1}{1000}=10^{-3} \quad\Longrightarrow\quad \log_{10}(0.001)=-3.

Ambos argumentos son positivos, y las bases 22 y 1010 son positivas y distintas de 11, por lo que los logaritmos reales cumplen los supuestos necesarios. Las comprobaciones son las potencias 25=322^5=32 y 103=0.00110^{-3}=0.001.

Pregunta 2

Para x > 0 e y > 0, expande ln(x³/y²) en logaritmos de x e y, nombrando la ley usada en cada paso.

Mostrar la solución paso a paso

Empieza con la ley del cociente, porque la operación exterior divide dos cantidades positivas:

ln ⁣(x3y2)=ln(x3)ln(y2).\ln\!\left(\frac{x^3}{y^2}\right) =\ln(x^3)-\ln(y^2).

Después aplica la ley de la potencia a cada término:

ln(x3)ln(y2)=3ln(x)2ln(y).\ln(x^3)-\ln(y^2) =3\ln(x)-2\ln(y).

Los supuestos x>0x>0 e y>0y>0 hacen positivos x3x^3, y2y^2 y el cociente; también garantizan y20y^2\ne0. Por tanto, bajo los supuestos indicados, la expresión expandida tiene el mismo dominio real que la original.

Pregunta 3

Un compañero escribe ln(4 + 5) = ln(4) + ln(5). Refuta la afirmación y enuncia la identidad correcta del producto.

Mostrar la solución paso a paso

Examina qué representa cada lado. El lado izquierdo es

ln(4+5)=ln(9).\ln(4+5)=\ln(9).

La suma del lado derecho usa la ley del producto:

ln(4)+ln(5)=ln(4×5)=ln(20).\ln(4)+\ln(5)=\ln(4\times5)=\ln(20).

Como 9209\ne20, sus logaritmos naturales son distintos. Numéricamente, ln(9)2.197225\ln(9)\approx2.197225, mientras que ln(20)2.995732\ln(20)\approx2.995732. La identidad válida es

ln(ac)=ln(a)+ln(c)\ln(ac)=\ln(a)+\ln(c)

para a>0a>0 y c>0c>0. Convierte la multiplicación, no la suma, en una suma.

Pregunta 4

Una candidata de tres tokens tiene factores positivos 0.5, 0.2 y 0.1. Calcula paso a paso su producto directo y su puntuación logarítmica natural, y luego convierte de nuevo la puntuación.

Mostrar la solución paso a paso

Multiplica de izquierda a derecha:

0.5×0.2=0.1,0.1×0.1=0.01.0.5\times0.2=0.1, \qquad 0.1\times0.1=0.01.

Para la representación logarítmica, calcula y suma los tres términos:

ln(0.5)0.693147,\ln(0.5)\approx-0.693147,ln(0.2)1.609438,ln(0.1)2.302585,\ln(0.2)\approx-1.609438, \qquad \ln(0.1)\approx-2.302585,0.6931471.6094382.302585=4.605170.-0.693147-1.609438-2.302585=-4.605170.

La ley del producto dice que esta suma es igual a ln(0.01)\ln(0.01). Aplicar la exponencial inversa da

e4.6051700.01.e^{-4.605170}\approx0.01.

La conversión coincide con el producto directo; la pequeña diferencia implícita en los decimales mostrados solo procede de redondear los términos logarítmicos a seis cifras decimales.

Pregunta 5

Dos candidatas tienen puntuaciones logarítmicas naturales −40 y −42. ¿Qué producto es mayor y por qué factor multiplicativo?

Mostrar la solución paso a paso

El logaritmo natural usa la base e>1e>1, por lo que conserva el orden. Como 40>42-40>-42, la candidata con puntuación logarítmica 40-40 tiene el producto positivo mayor.

Sean los productos A=e40A=e^{-40} y B=e42B=e^{-42}. Su cociente usa la ley del cociente para exponentes:

AB=e40e42=e40(42)=e27.389.\frac{A}{B}=\frac{e^{-40}}{e^{-42}}=e^{-40-(-42)}=e^2\approx7.389.

Por tanto, el producto de la primera candidata es aproximadamente 7.3897.389 veces el de la segunda. Una diferencia de dos puntos en el espacio logarítmico es una razón multiplicativa en el espacio original.

Pregunta 6

Con p = 0.1, el explorador muestra un producto directo subnormal en n = 323 y cero en n = 324. ¿Qué ocurre con la puntuación logarítmica y qué implica al exponenciarla?

Mostrar la solución paso a paso

La puntuación aditiva es nln(p)n\ln(p). Con ln(0.1)2.302585093\ln(0.1)\approx-2.302585093:

323ln(0.1)743.734985,323\ln(0.1)\approx-743.734985,324ln(0.1)746.037570.324\ln(0.1)\approx-746.037570.

Ambas son finitas y siguen siendo diferentes, aunque la multiplicación binary64 directa llega a cero con 324 factores en el ejemplo verificado. La acumulación en el espacio logarítmico aún permite comparar las secuencias de factores positivos.

Sin embargo, exponenciar 746.037570-746.037570 pide a float64 representar aproximadamente 1032410^{-324}, por debajo de su rango positivo después del redondeo, así que el resultado almacenado es cero. La representación logarítmica conserva la puntuación finita; no amplía el rango de salida de binary64.

Pregunta 7

Depura este código para sumar dos alternativas logarítmicas: np.log(np.exp(-1000) + np.exp(-1001)). ¿Por qué devuelve −inf y qué operación de NumPy conserva la puntuación combinada finita?

Mostrar la solución paso a paso

El código exponencia primero. En float64, ambos valores intermedios son demasiado pequeños para representarse:

float64(e1000)=0,float64(e1001)=0.\operatorname{float64}(e^{-1000})=0, \qquad \operatorname{float64}(e^{-1001})=0.

El programa calcula entonces ln(0+0)=ln(0)\ln(0+0)=\ln(0), que NumPy representa como -inf y acompaña de una señal de división por cero.

Usa la operación diseñada para alternativas que ya están en el espacio logarítmico:

combined = np.logaddexp(-1000.0, -1001.0)
# -999.6867383124818

Esto calcula ln(e1000+e1001)\ln(e^{-1000}+e^{-1001}) sin redondear antes ambas exponenciales a cero. No es la ley del producto: un producto de factores positivos usa np.log(factors).sum(), mientras que este ejemplo suma dos alternativas. Finalmente, np.exp(combined) sigue devolviendo 0.0; la puntuación combinada finita se conserva, pero su valor en escala de probabilidad sigue siendo inrepresentable en float64.

Fuentes

  1. Mathematics for Machine Learning companion website
  2. Mathematics for Machine Learning book PDF
  3. NumPy documentation: numpy.log
  4. NumPy documentation: numpy.logaddexp
  5. NumPy documentation: numpy.finfo
  6. NumPy documentation: numpy.nextafter