Herramientas de usuario

Herramientas del sitio


clase:iabd:pia:1eval:tema06-apendices

¡Esta es una revisión vieja del documento!


6. Redes neuronales: Apendices

Inicialización de parámetros

El siguiente código en Python nos muestra las funciones de distribución de cada uno de los inicializadores. El ejemplo no tiene utilidad real mas allá de mostrar los datos y las gráficas de los inicializadores.

import tensorflow as tf
import keras as keras
from keras.models import Sequential
from keras.layers import Dense
import pandas as pd

initializers=["random_uniform","random_normal","glorot_uniform","glorot_normal","he_uniform","he_normal","lecun_uniform","lecun_normal","zeros","ones"]
model=Sequential()
for initializer in initializers:
    model.add(Dense(1000, input_dim=1000,kernel_initializer=initializer))
model.add(Dense(1000))
model.compile()

df=pd.DataFrame()
for index,initializer in enumerate(initializers):
    pesos=(model.layers[index].get_weights()[0]).reshape(-1)
    df[initializer]=pesos

df.describe()

df.iloc[:,0:8].plot(kind = 'density', subplots = True,  layout = (5,2),figsize=(15,20),sharex = False)

	random_uniform	random_normal	glorot_uniform	glorot_normal	he_uniform	he_normal	lecun_uniform	lecun_normal	zeros		ones
count	1000000.000000	1000000.000000	1000000.000000	1000000.000000	1000000.000000	1000000.000000	1000000.000000	1000000.000000	1000000.0	1000000.0
mean	-0.000022	-0.000005	-0.000010	 0.000020	 0.000054	 0.000019	-0.000008	-0.000040	0.0		1.0
std	 0.028850	 0.049970	 0.031639	 0.031590	 0.044715	 0.044714	 0.031611	 0.031635	0.0		0.0
min	-0.050000	-0.238984	-0.054772	-0.071899	-0.077459	-0.101682	-0.054772	-0.071899	0.0		1.0
25%	-0.025000	-0.033713	-0.027437	-0.022938	-0.038669	-0.032442	-0.027381	-0.023074	0.0		1.0
50%	-0.000047	 0.000047	-0.000014	 0.000056	 0.000099	 0.000064	 0.000006	-0.000038	0.0		1.0
75%	 0.024980	 0.033729	 0.027406	 0.022980	 0.038725	 0.032528	 0.027364	 0.022952	0.0		1.0
max	 0.050000	 0.232416	 0.054772	 0.071900	 0.077460	 0.101682	 0.054772	 0.071900	0.0		1.0

Ahora vamos a ver como se comportan 4 redes distintas según el número de capas, el inicializador y la función de activación usada

Mas información:

Usando funciones de activación en Keras

Funciones personalizadas

Podemos crear nuestra propia función de activación

from tensorflow.keras import backend as K

def my_relu(x):
    return K.maximum(0.3*x, x)
  

Y usarla de las siguientes formas

  • Usando directamente la función de activación

model.add(Dense(3, input_dim=1,activation=my_relu))

model.add(Dense(3, input_dim=1))
model.add(Dense(3, input_dim=1,activation=tf.keras.layers.Activation(my_relu)))

model.add(Dense(3, input_dim=1))
model.add(Dense(3, input_dim=1,activation=tf.keras.layers.Lambda(my_relu)))

Funciones personalizadas parametrizadas

Pero si nuestra función tiene un parámetro

from tensorflow.keras import backend as K

def my_relu(x,alpha):
    return K.maximum(alpha*x, x)
  

Solo podremos usar tf.keras.layers.Lambda

model.add(Dense(3, input_dim=1))
model.add(tf.keras.layers.Lambda(lambda x: my_relu(x,0.3)))

Funciones con nombre

Para acabar vamos a ver como poder usar el nombre en una capa que nos hayamos creado nosotros usando el método tf.keras.utils.get_custom_objects

Vamos a definir un nombre de función de activación llamado relu_0_3 usando get_custom_objects()

from tensorflow.keras import backend as K
from tensorflow.keras.utils import get_custom_objects

def my_relu(x,alpha):
    return K.maximum(alpha*x, x)

get_custom_objects()['relu_0_3']=tf.keras.layers.Lambda(lambda x: my_relu(x,0.3))

Y simplemente lo usamos indicando el nombre de relu_0_3

model.add(Dense(3, input_dim=1,activation="relu_0_3"))

Tipos de funciones de activación en capas ocultas

sigmoid

La fórmula de la sigmoide se obtiene a partir de la función $logit$ o $log odds$.

$$odds(p) = \frac{p}{1-p} $$ $$logit(p) = log(odds(p))=log(\frac{p}{1-p}) $$

Ahora:

$$logit(p) = ax+b $$ $$log(\frac{p}{1-p}) = ax+b $$

Si despejamos $p$ de la anterior fórmula:

$$ log(\frac{p}{1-p}) = ax+b \\ e^{log(\frac{p}{1-p})} = e^{ax+b} \\ \frac{p}{1-p}=e^{ax+b} \\ p=e^{ax+b} \cdot (1-p) \\ p=e^{ax+b}-pe^{ax+b} \\ p+pe^{ax+b}=e^{ax+b} \\ p(1+e^{ax+b})=e^{ax+b} \\ p=\frac{e^{ax+b}}{1+e^{ax+b}} \\ p=\frac{ \frac{e^{ax+b}}{e^{ax+b}} }{ \frac{1+e^{ax+b}}{e^{ax+b}} } \\ p=\frac{ 1 }{ 1+\frac{1}{e^{ax+b}} } \\ p=\frac{ 1 }{ 1+e^{-(ax+b)} } \\ $$

Que es exactamente la función sigmoide

ReLU y Leaky ReLU

Ahora vamos a complicarlo un poco. Resulta que la función de activación tf.keras.activations.relu tiene un parámetro llamado alpha que hace que comporte como la función Leaky ReLU. Y también la capa tf.keras.layers.ReLU() tiene el mismo parámetro pero llamado negative_slope y obviamente hace exactamente lo mismo. Por lo tanto es igual a Leaky ReLU

model.add(Dense(3, input_dim=1,activation=tf.keras.layers.ReLU(negative_slope=0.3)))
model.add(Dense(3, input_dim=1,activation=tf.keras.layers.Lambda(lambda x: tf.keras.activations.relu(x,alpha=0.3))))

Con el siguiente código podemos ver el resultado:

class_relu=tf.keras.layers.ReLU(negative_slope=0.3)
class_leaky_relu=tf.keras.layers.LeakyReLU()

x=np.linspace(-5,5,500)
y_class_relu=class_relu(x)
y_relu=tf.keras.activations.relu(x, alpha=0.3).numpy()
y_class_leaky_relu=class_leaky_relu(x)


np.set_printoptions(threshold=np.inf)
np.set_printoptions(suppress=True)
np.column_stack((y_relu,y_class_leaky_relu,y_class_relu,y_relu-y_class_leaky_relu,y_class_relu-y_class_leaky_relu))

Además en el código cuente de TensorFlow podemos ver como realmente son iguales:

PReLU

Existe otra capa de activación llamada PReLU que es similar a Leaky ReLU pero el valor de $\alpha$ se calcula automáticamente durante el entrenamiento, es decir que es como un parámetro mas de la red.

Mas información:

GELU

GELU es de la últimas funciones de activación "famosas" que han aparecido. GELU: Se usa con Transformers. La usa Google con BERT y OpenAI en GPT-2 y GPT-3.1)

$$ GELU(x)=0.5x(1+ \frac {2}{ \sqrt {\pi} } \int_{0}^{ \frac {x}{ \sqrt {2}}} e ^ {-t^{2}}dt) $$

  • Uso en Keras

model.add(Dense(3, input_dim=1,activation=tf.keras.activations.gelu))
model.add(Dense(3, input_dim=1,activation="gelu"))

Mas información:

Swish

Se usa cuando ReLU pero es un poco más lenta pero es mejor.

$$swish(x)=x \cdot sigmoid(x)=x \cdot \frac{1}{1+e^{-x}}=\frac{x}{1+e^{-x}}$$

  • Uso en Keras

model.add(Dense(3, input_dim=1,activation=tf.keras.activations.swish))
model.add(Dense(3, input_dim=1,activation="swish"))

Mish

Se usa cuando ReLU pero aunque es un poco más lenta es mejor. Es muy similar a Swish

$$ mish(x)=x \cdot tanh(softplus(x)) $$

Poetry

Para usar Mish deberemos instalar TensorFlow Addons. Desde conda a veces falla la instalación así que lo recomendable es usar Poetry

Para usar poetry debemos primero instalarlo en el sistema operativo mediante los comandos:

pip install --user poetry
poetry config virtualenvs.in-project true 

Una vez instalado (se puede comprobar con poetry --version) iremos a la carpeta donde tenemos nuestro programa en Python (o donde lo vamos a tener) y ejecutaremos lo siguiente:

poetry init
poetry add libclang = "<12.0.0" numpy pandas matplotlib seaborn scikit-learn tensorflow tabulate PyMySQL SQLAlchemy ipympl keras-tuner tensorflow-addons statsmodels
poetry install

Si al hacer el poetry add se produce el error: [org.freedesktop.DBus.Error.UnknownObject] ("No such object path '/org/freedesktop/secrets/aliases/default'",) deberemos crear la siguiente variable de entorno: export PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring

Para ejecutar el código hay 2 formas:

  • Desde la línea de comandos:

poetry run python my_script.py

  • Desde VS Code seleccionar en los entornos de ejecución la carpeta .venv del propio proyecto:

  • Si queremos usar el entorno de poetry pero no está en nuestra carpeta se puede indicar a VS Code cual es el ejecutable de python que debe usar siempre para ello hay que crear en la carpeta de nuestro proyecto el fichero $HOME/.config/Code/User/settings.json

{    
    "python.defaultInterpreterPath": "/home/logongas/python_default_env/.venv/bin/python",
}

Tiempo de cálculo

Para cada problema puede que una función sea mejor que otra, es decir que cosiga entrenar en un menor número de épocas. Aun así a veces no puede preocupar el tiempo de CPU/GPU que usa cada función de activación.

En la siguiente gráfica se puede ver el tiempo de entrenamiento de una red neuronal con 14 capas y 1521 neuronas usando cada una de las funciones de activación.

clase/iabd/pia/1eval/tema06-apendices.1675011475.txt.gz · Última modificación: 2023/01/29 17:57 por admin