Clase 6: Training Tips & Tricks
El entrenamiento de un modelo tiene demasiadas variables que pueden influir en el éxito del modelo. Algunos aspectos relevantes a los que hay que poner énfasis al momento de entrenar:
Muchas de las técnicas que veremos acá permiten abordar mejoras en nuestros modelos para uno o más aspectos de los mencionados anteriormente.
En general el término Normalización está muy trillado y en la práctica se utiliza para referirse a muchos temas distintos. Algunas definiciones conocidas:
\[x_{i\_norm} = \frac{x_i-x_{min}}{x_{max} - x_{min}}\] Esta operación se puede hacer mediante MinMaxScaler de Scikit-Learn.
\[ x_{i\_est} = \frac{x_i - E[x]}{\sqrt(Var[x])}\]
Esta operación se puede hacer mediante StandardScaler de Scikit-Learn.
Paper 2015: Batch Normalization
¿Por qué?
Cálculo de Estadísticos
\[ \mu_B = \frac{1}{B} \sum_{i=1}^B z^{(i)} = \frac{1}{3}(4 + 7 + 5) = 5.33\] \[ \sigma_B^2 = \frac{1}{B} \sum_{i=1}^B (z^{(i)} - \mu_B)^2 = 1.555\]
Normalización
\[\widehat{z^{(i)}} = \frac{z^{(i)} - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}\]
Scale and Shift: \(\gamma\) y \(\beta\) son parámetros.
\[BN_{\gamma,\beta}(z_i)= \gamma \widehat{z_i} + \beta \]
Problema
La predicción de una instancia \(i\) específica, ahora depende de otros elementos dentro del Batch. ¿Cómo funciona entonces el modelo en Test Time?
Se estiman valores de \(\mu_B\) y \(\sigma_B\) para usar en inferencia basados en los valores obtenidos en entrenamiento.
Estimación de Estadísticos
Normalización
\[\widehat{z^{(i)}} = \frac{z^{(i)} - \mu_B^{inf}}{\sqrt{(\sigma_B^{inf})^2 + \epsilon}}\]
Scale and Shift: \(\gamma\) y \(\beta\) son parámetros.
\[BN_{\gamma,\beta}(z_i)= \gamma \widehat{z_i} + \beta \]
Los parámetros \(\gamma\) y \(\beta\) son los aprendidos durante el proceso de entrenamiento.
Entonces, la posición del BatchNorm termina siendo parte de la Arquitectura, y se debe comprobar donde tiene un mejor efecto.
Batchnorm tiene efectos distintos al momento de entrenar o de evaluar/predecir en un modelo. Por lo tanto, de usar Batchnorm es imperativo utilizar los modos model.train()
y model.eval()
de manera apropiada.
Paper 2016: Layer Normalization
Batch Norm tiene algunos problemas:
Beneficios de Layer Norm
En general el gran problema de las Redes Neuronales es el Overfitting. Esto porque las redes neuronales normalmente se denominan como Overparametrized Models. ¿Qué significa esto?
Corresponde a una penalización que se da a los modelos para limitar su complejidad y asegurar que pueda generalizar correctamente en datos no vistos.
\[ \underset{W_{i:L}}{minimize} \frac{1}{m} \sum_{i=1}^m l(h_\theta(x^{(i)}),y^{(i)}) + \frac{\lambda}{2} \sum_{i=1}^L ||W_i||_f^2\]
Eso implica una transformación a nuestro Update Rule:
\[W_i := W_i - \alpha \nabla \frac{1}{m} \sum_{i=1}^m l(h_\theta(x^{(i)}),y^{(i)}) - \alpha \lambda W_i = (1-\alpha\lambda)W_i - \alpha \nabla l(h_\theta(x^{(i)}),y^{(i)})\]
Se puede ver que los pesos (weights) se contraen (decaen) antes de actualizarse en la dirección del gradiente.
Por alguna razón Pytorch decidió implementarlo como una propiedad de los Optimizers cuando en realidad debió ser de la Loss Function.
A diferencia de la estrategia anterior, este tipo de regularización se aplica a las activaciones de la red (resultados de la Transformación Affine, previo a la transformación no lineal).
Definiremos el Dropout como:
\[Z_{i+1} = \sigma(W_i^T Z_i + b_i)\] \[\widehat{Z_{i+1}} = D(Z_{i+1})\]
donde \(D\) implica la aplicación de Dropout a la capa \(i+1\). El elemento \(j\) de la capa \(\widehat{Z_i}\) se calcula como:
\[(\widehat{Z_{i+1}})_j = \begin{cases} \frac{(Z_{i+1})_j}{1-p} & \text{with prob 1-p} \\ 0, & \text{with prob p} \end{cases}\]
\(p\) se conoce como el Dropout Rate
.
El factor \(\frac{1}{1-p}\) se aplica para mantener la varianza estable luego de haber eliminado activaciones con probabilidad \(p\).
Dropout se aplica normalmente al momento de entrenar el modelo. Por lo tanto, de usar Dropout es imperativo cambiar al modo model.eval()
al momento de predecir.
Paper 2010: Xavier Initialization Paper 2015: Kaiming Initialization
Hemos hablado que los métodos basados en SGD normalmente utilizan valores aleatorios para partir su entrenamiento, lo cual deja un poco al azar el éxito de un proceso de entrenamiento.
Existen diversos estudios de cómo inicializar
los parámetros para una convergencia óptima. Algunas de las inicializaciones son:
Activaciones Triviales
Se inicia con valores provenientes de una distribución uniforme: \(\mathcal{U}(-a,a)\)
\[ a = gain \cdot \sqrt{\frac{6}{fan_{in} + fan_{out}}}\]
Se inicia con valores provenientes de una distribución uniforme: \(\mathcal{N}(0,std^2)\)
\[ std = gain \cdot \sqrt{\frac{2}{fan_{in} + fan_{out}}}\]
Se inicia con valores provenientes de una distribución uniforme: \(\mathcal{U}(-bound,bound)\)
\[ bound = gain \cdot \sqrt{\frac{3}{fan\_mode}}\]
Se inicia con valores provenientes de una distribución uniforme: \(\mathcal{N}(0,std^2)\)
\[std =\sqrt{\frac{gain}{fan\_mode}}\]
El entrenamiento de una red neuronal puede tomar mucho tiempo. Es por eso que algunas buenas prácticas serían:
Early Stopping
patience
epochs sin mejorar el validation loss u otro criterio.Checkpointing
Es importante mencionar que normalmente no se utilizan redes neuronales para poder entrenar datos tabulares. Pero de hacerlo, es muy probable que nos encontremos con variables categóricas. Para ello existen dos técnicas que son las más comunes en redes neuronales.
Sparse
de los datos.
En Pytorch se puede implementar como F.one_hot()
, pero mi recomendación es utilizar las herramientas de Scikit-Learn para evitar Data Leakage
.
En Pytorch esto se puede realizar mediante: nn.Embedding()
.