Quant500 Academy

2. La sigmoide y la función de error que vas a minimizar

Nivel 11: Redes Neuronales para Trading

La función de activación que aplica cada unidad oculta suele ser la sigmoide. En palabras: toma un número cualquiera, lo pasa por una exponencial negativa y devuelve un valor estrictamente entre 0 y 1. En código plano:

import numpy as np
import matplotlib.pyplot as plt

def sigmoide(v, s=1.0):
    # 1 dividido entre 1 mas la exponencial de menos s por v
    return 1 / (1 + np.exp(-s * v))

v = np.linspace(-10, 10, 200)
plt.plot(v, sigmoide(v, 1), color='C3', label='s = 1')
plt.plot(v, sigmoide(v, 0.5), '--', color='C0', label='s = 0.5')
plt.plot(v, sigmoide(v, 10), '--', color='C4', label='s = 10')
plt.xlabel('v')
plt.ylabel('sigmoide')
plt.legend()
plt.show()

El parámetro de escala s controla la velocidad de activación. Un s grande equivale a una activación dura en v igual a cero: la curva se parece a un escalón, la unidad está apagada o encendida y casi nada intermedio. Un s pequeño la aplana hasta hacerla casi lineal en el centro. Y si escribes sigmoide de s por (v menos v0), lo que haces es desplazar el umbral de activación de cero a v0 — que es exactamente el papel del término de sesgo dentro de la unidad.

Esto tiene una consecuencia práctica enorme, que te va a morder en cuanto entrenes: saturación. Con valores de entrada muy grandes o muy pequeños, la sigmoide se aplana y su pendiente tiende a cero. Una unidad saturada casi no propaga gradiente y deja de aprender. Por eso las entradas se estandarizan antes de entrenar y por eso los pesos se inicializan pequeños.

Los parámetros. Al conjunto completo de pesos lo llamamos theta. Está formado por los pesos y sesgos de la capa oculta — hay M por (p más 1) de ellos, siendo p el número de entradas y M el número de unidades ocultas — y por los pesos y sesgos de la capa de salida, que son K por (M más 1). Cuenta esos números antes de entrenar: son la medida honesta de cuántos grados de libertad le estás dando al modelo. Con 8 señales técnicas, 32 unidades ocultas y una salida son 32 por 9 más 33, es decir 321 parámetros, para ajustar quizá 1000 días de bolsa. Si eso te suena a sobreajuste, te suena bien.

La función de error. Para regresión usamos la suma de errores al cuadrado: sumas, sobre todas las observaciones y todas las salidas, el cuadrado de la diferencia entre el valor real y el predicho. Para clasificación puedes usar el error cuadrático o, mejor, la entropía cruzada (deviance): menos la suma, sobre observaciones y clases, del objetivo real multiplicado por el logaritmo de la probabilidad predicha. El clasificador resultante asigna a cada observación la clase con la probabilidad predicha más alta.

Hay un detalle elegante que conviene retener: con activación softmax en la salida y entropía cruzada como error, la red neuronal es exactamente una regresión logística lineal sobre las unidades ocultas, y todos los parámetros se estiman por máxima verosimilitud. Dicho de otro modo: la red no inventa un paradigma nuevo, aprende una representación no lineal de los datos y luego hace encima el modelo lineal de toda la vida.

def error_cuadratico(y, f):
    return np.sum((y - f) ** 2)

def entropia_cruzada(y, f, eps=1e-12):
    # y son etiquetas 0-1, f son probabilidades predichas
    return -np.sum(y * np.log(f + eps))

El resto de Quant500

Lo que estás aprendiendo, aplicado al índice todos los días:

La cartera del modelo, cada semana en tu correo

Cada sábado, su semana en un minuto: cómo fue, lo mejor y lo peor, y qué directivos compraron con su dinero. Y el día que el modelo se rehace, qué entra y qué sale. Es una simulación, no un consejo. Como mucho un correo a la semana, sin publicidad y sin cuenta; te das de baja con un clic. Lo hace una persona: Pol Gracia.

Cartera modelo con resultados simulados, no una recomendación personalizada. Tu correo se usa solo para esto: privacidad.

Detrás de la Academia y del resto de Quant500 hay una sola persona: Pol Gracia Serrahima.