Capítulo 4

Series de Taylor

4.1 Expansión en Serie de Taylor (1D)

Aproximamos una función suave alrededor de un punto usando sus derivadas:

f(x)=k=0f(k)(a)k!(xa)kf(x) = \sum_{k=0}^{\infty} \frac{f^{(k)}(a)}{k!} (x - a)^k

Hasta primer orden: f(x)f(a)+f(a)(xa)f(x) \approx f(a) + f'(a)(x-a) (aproximación lineal). Hasta segundo orden: f(x)f(a)+f(a)(xa)+12f(a)(xa)2f(x) \approx f(a) + f'(a)(x-a) + \frac{1}{2}f''(a)(x-a)^2.

4.2 Taylor Multivariada

Para f:RnRf: \mathbb{R}^n \to \mathbb{R}:

f(x)f(a)+f(a)T(xa)+12(xa)THf(a)(xa)f(\mathbf{x}) \approx f(\mathbf{a}) + \nabla f(\mathbf{a})^T (\mathbf{x} - \mathbf{a}) + \frac{1}{2} (\mathbf{x} - \mathbf{a})^T H_f(\mathbf{a}) (\mathbf{x} - \mathbf{a})

donde HfH_f es la matriz Hessiana de segundas derivadas:

Hij=2fxixjH_{ij} = \frac{\partial^2 f}{\partial x_i \partial x_j}
python
import numpy as np

# Hessiana de f(x,y) = x^2 + y^2 + xy
def hessian(xy):
    x, y = xy
    return np.array([[2, 1],  # d²f/dx², d²f/dxdy
                     [1, 2]]) # d²f/dydx, d²f/dy²

# Verificar con numérico
from scipy.optimize import approx_fprime

def grad_f(xy):
    return np.array([2*xy[0] + xy[1], 2*xy[1] + xy[0]])

xy = np.array([1.0, 2.0])
H_num = approx_fprime(xy, lambda p: grad_f(p)[0], 1e-6)
print("Hessiana:
", hessian(xy))
print("Eigenvalores:", np.linalg.eigvalsh(hessian(xy)))
# Si todos > 0 → mínimo local

4.3 Aproximación Lineal y Newton

El método de Newton usa la expansión de segundo orden para optimizar:

xt+1=xtHf(xt)1f(xt)\mathbf{x}_{t+1} = \mathbf{x}_t - H_f(\mathbf{x}_t)^{-1} \nabla f(\mathbf{x}_t)

Newton vs Gradiente

  • • GD: usa solo gradiente (1er orden)
  • • Newton: usa Hessiana (2do orden)
  • • Newton converge en menos pasos pero cada paso es más caro
  • • GD es más escalable a altas dimensiones (ML)

Serie de Taylor en ML

  • • Gradiente: término de 1er orden
  • • Hessiana: usada en Newton, optimización de hiperparámetros
  • • Laplace approximation: aproximación Gaussiana de la posterior
  • • La linearización de modelos es Taylor de 1er orden
python
import numpy as np

# Newton vs GD para f(x) = x^2 + sin(3x)*0.5
def f(x):
    return x**2 + 0.5*np.sin(3*x)
def df(x):
    return 2*x + 1.5*np.cos(3*x)
def d2f(x):
    return 2 - 4.5*np.sin(3*x)

x_gd, x_nt = 2.0, 2.0
lr = 0.1

for i in range(10):
    x_gd -= lr * df(x_gd)
    x_nt -= df(x_nt) / d2f(x_nt)  # Newton: H^{-1} * grad
    print(f"Paso {i+1}: GD x={x_gd:.4f} | Newton x={x_nt:.4f}")

print(f"
GD final:    {x_gd:.6f}, f={f(x_gd):.6f}")
print(f"Newton final: {x_nt:.6f}, f={f(x_nt):.6f}")

4.4 Linearización en ML

En muchos problemas de ML, linealizamos modelos no lineales alrededor de una estimación inicial (ej: filtro de Kalman, sistema de recomendación).

python
# Linearización de un modelo no lineal
import numpy as np

# Modelo: y = exp(x) + ruido
x0 = 0.0
# Taylor 1er orden alrededor de x0: exp(x) ≈ 1 + x
# Modelo linealizado: y ≈ 1 + x

# Para funciones vectoriales, la Jacobiana es la linearización
# f(x) = [exp(x), sin(x)] ≈ f(x0) + J(x0) * (x - x0)
x0 = np.array([0.0])
J = np.array([[np.exp(x0[0])],
              [np.cos(x0[0])]])
print("Jacobiana en x=0:
", J)
print("f(0) ≈", np.array([np.exp(0), np.sin(0)]))
print("f(0.1) ≈", np.array([np.exp(0), np.sin(0)]) + J.flatten() * 0.1)