13 feb. 2018

Funciones de activación para un perceptron


En el artículo (introducción al perceptron), se muestra el perceptron con la función de activación que en la figura es una onda cuadrada, pero puede ser también otro tipo de función.


En el artículo  (construir una red neuronal en pocos minutos), se muestra la función de activación llamada sigmoide.

Y en el artículo (Una red Neuronal para aprendizaje supervisado usando Scikit-learn) se usa la función tanh.

Scikit-learn para  multi-layer perceptron maneja varios tipos de funciones de activación (documentación) como lo son:

  • identity: La función de activación es f(x)=x.
  • logistic: La función de activación es la función sigmoide f(x)=1/(1+exp(-x)).
  • tanh: La función de activación es la función tangente hiperbolico f(x)=tanh(x).
  • relu: La función de activación es función rectificada de recta unitaria f(x)=max(0,x).


El código mostrará las distintas funciones y sus gráficas, luego se toma la red neuronal del artículo Una red Neuronal para aprendizaje supervisado usando Scikit-learn, usando distintas funciones de activación, se entrena a la neurona con cada función de activación y se busca predecir el resultado.

A continuación el código:


In [1]:
#Se importa numpy y matplotlib
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
In [2]:
#Se define el rango de valores
z = np.linspace(-10,10,100)
In [3]:
#Onda cuadrada
def cuadrada(z):
    return 1*(z>0)
In [4]:
#Se calcula la onda cuadrada a partir del rango de valores
a = cuadrada(z)
In [5]:
#Se gráfica la onda cuadrada
plt.plot(z,a)
Out[5]:
[<matplotlib.lines.Line2D at 0x7f90ba52c278>]
In [6]:
#Se define la función Identidad
def identidad(z):
    return z
In [7]:
#Se calcula la función identidad a partir del rango de valores
b = identidad(z)
In [8]:
#Se gráfica.
plt.plot(z,b)
Out[8]:
[<matplotlib.lines.Line2D at 0x7f90ba49e7f0>]
In [9]:
#Función ReLU
def ReLU(z):
    return z * (z > 0)
In [10]:
#Se calcula la función ReLU a partir del rango de valores
c = ReLU(z)
In [11]:
#Se gráfica la función
plt.plot(z,c)
Out[11]:
[<matplotlib.lines.Line2D at 0x7f90ba46c6d8>]
In [12]:
#Función tangente hiperbolico
def tanh(z):
    return(np.exp(z)-np.exp(-z))/(np.exp(z)+np.exp(-z))
In [13]:
#Se calcula la tangente hiperbolica a partir del rango de valores
d = tanh(z)
In [14]:
#Se gráfica
plt.plot(z,d)
Out[14]:
[<matplotlib.lines.Line2D at 0x7f90ba42e550>]
In [15]:
#Función sigmoide
def sigmoide(z):
    return 1/(1+np.exp(-z))
In [16]:
#Se calcula la sigmoide a partir del rango de valores
e = sigmoide(z)
In [17]:
#Se gráfica la función
plt.plot(z,e)
Out[17]:
[<matplotlib.lines.Line2D at 0x7f90ba3f0be0>]

La diferencia entre las funciones de activación es lo suavizada o no de cada curva. Osea, que tan abrupta es su pendiente, o la derivada de la función

A continuación se crea una red neuronal usando scikit-learn

In [18]:
#Se importa de la red neuronal MLPClassifier
from sklearn.neural_network import MLPClassifier
In [19]:
#Se definen los datos de entrada
datos_entrada = np.array([
    0, 0,
    0, 1,
    1, 0,
    1, 1
]).reshape(4, 2)
In [20]:
#Se definen los datos de salida
datos_salida = np.array([0, 1, 1, 0]).reshape(4,)
In [21]:
#Se crea la red neuronal con función de activación relu y 100 mil iteraciones
model = MLPClassifier(activation='relu', max_iter=100000, hidden_layer_sizes=(4,2))
In [22]:
#Se entrena a la red neuronal
model.fit(datos_entrada,datos_salida)
Out[22]:
MLPClassifier(activation='relu', alpha=0.0001, batch_size='auto', beta_1=0.9,
       beta_2=0.999, early_stopping=False, epsilon=1e-08,
       hidden_layer_sizes=(4, 2), learning_rate='constant',
       learning_rate_init=0.001, max_iter=100000, momentum=0.9,
       nesterovs_momentum=True, power_t=0.5, random_state=None,
       shuffle=True, solver='adam', tol=0.0001, validation_fraction=0.1,
       verbose=False, warm_start=False)
In [23]:
#Se hace la predicción
print('prediccion:', model.predict(datos_entrada))
prediccion: [0 1 0 1]

El resultado que devuelve la red neuronal debería ser [0,1,1,0] y devuelve [0,1,0,1] el cual es errado

Se repite la construcción de la red neuronal, pero ahora usando la función de activación identity

In [24]:
model = MLPClassifier(activation='identity', max_iter=100000, hidden_layer_sizes=(4,2))
In [25]:
#Se entrena a la red neuronal
model.fit(datos_entrada,datos_salida)
Out[25]:
MLPClassifier(activation='identity', alpha=0.0001, batch_size='auto',
       beta_1=0.9, beta_2=0.999, early_stopping=False, epsilon=1e-08,
       hidden_layer_sizes=(4, 2), learning_rate='constant',
       learning_rate_init=0.001, max_iter=100000, momentum=0.9,
       nesterovs_momentum=True, power_t=0.5, random_state=None,
       shuffle=True, solver='adam', tol=0.0001, validation_fraction=0.1,
       verbose=False, warm_start=False)
In [26]:
#Se hace la predicción
print('prediccion:', model.predict(datos_entrada))
prediccion: [0 0 0 0]

El resultado que devuelve la red neuronal debería ser [0,1,1,0] y devuelve [0,0,0,0] el cual es errado

Se repite la construcción de la red neuronal, pero ahora usando la función de activación sigmoide (logistic)

In [27]:
model = MLPClassifier(activation='logistic', max_iter=100000, hidden_layer_sizes=(4,2))
In [28]:
#Se entrena a la red neuronal
model.fit(datos_entrada,datos_salida)
Out[28]:
MLPClassifier(activation='logistic', alpha=0.0001, batch_size='auto',
       beta_1=0.9, beta_2=0.999, early_stopping=False, epsilon=1e-08,
       hidden_layer_sizes=(4, 2), learning_rate='constant',
       learning_rate_init=0.001, max_iter=100000, momentum=0.9,
       nesterovs_momentum=True, power_t=0.5, random_state=None,
       shuffle=True, solver='adam', tol=0.0001, validation_fraction=0.1,
       verbose=False, warm_start=False)
In [29]:
#Se hace la predicción
print('prediccion:', model.predict(datos_entrada))
prediccion: [1 1 1 1]

El resultado que devuelve la red neuronal debería ser [0,1,1,0] y devuelve [1,1,1,1] el cual es errado

Se repite la construcción de la red neuronal, pero ahora usando la función de activación tanh

In [33]:
model = MLPClassifier(activation='tanh', max_iter=100000, hidden_layer_sizes=(4,2))
In [34]:
#Se entrena a la red neuronal
model.fit(datos_entrada,datos_salida)
Out[34]:
MLPClassifier(activation='tanh', alpha=0.0001, batch_size='auto', beta_1=0.9,
       beta_2=0.999, early_stopping=False, epsilon=1e-08,
       hidden_layer_sizes=(4, 2), learning_rate='constant',
       learning_rate_init=0.001, max_iter=100000, momentum=0.9,
       nesterovs_momentum=True, power_t=0.5, random_state=None,
       shuffle=True, solver='adam', tol=0.0001, validation_fraction=0.1,
       verbose=False, warm_start=False)
In [35]:
#Se hace la predicción
print('prediccion:', model.predict(datos_entrada))
prediccion: [0 1 1 0]

El resultado que devuelve la red neuronal debería ser [0,1,1,0] y devuelve [0,1,1,0] el cual es el resultado esperado. Esto demuestra que es muy importante seleccionar la función de activación correcta a la hora de definir una red neuronal y entrenarla.


12 feb. 2018

Visualización de objetos Graph con Tensorboard

Continuando con los artículos sobre TensorFlow, en este caso se mostrará como se visualiza el objeto Graph por medio de TensorBoard.

Los artículos de la serie de TensorFlow los pueden revisar a continuación:

  1. Hola mundo desde Tensorflow
  2. Matemáticas básicas con Tensorflow
  3. Manejo de matrices con Tensorflow
  4. Variables y placeholders en Tensorflow
  5. Objeto Graph de Tensorflow



Este artículo se basa en el tutorial en inglés Visualization y la documentación de la página de TensorFlow

Se va a tener dos formas de realizar el mismo ejercicio, el primero simplemente identificando las operaciones en el Objeto Graph, suma, multiplicación y división, luego se guarda el log de la sesión y se visualizará. 

En el siguiente ejercicio, se harán las mismas operaciones, pero ahora se identifica los Objetos Graph con scopes, esto permitirá visualizar  mejor dichos objetos y sus operaciones. 

A continuación el primer ejercicio:



In [1]:
#Se importa Tensorflow
import tensorflow as tf
In [2]:
#Se suma 1+2
a = tf.add(1, 2,name="Suma_estos_numeros")
In [3]:
#Se multiplica el valor de la suma anterior por 3
b = tf.multiply(a, 3)
In [4]:
#se suma 4+5
c = tf.add(4, 5,name="Suma_estos")
In [5]:
#Se multiplica el resultado de la suma anterior por 6
d = tf.multiply(c, 6,name="Multiplica_estos_numeros")
In [6]:
#Se multiplica 4*5
e = tf.multiply(4, 5,name="B_suma")
In [7]:
#Se divide el resultado de la suma de 4+5 entre 6
f = tf.div(c, 6,name="B_mul")
In [8]:
#Se suma la multiplicación de a*3 más la multiplicación de c*6
g = tf.add(b, d)
In [9]:
#Se multiplica el resultado de la suma de b+d con el resultado de la división de c/6
h = tf.multiply(g, f)
In [10]:
#Se crea la sesión y se corre el resultado del objeto h y se salva en el directorio output.
with tf.Session() as sess:
    writer = tf.summary.FileWriter("output", sess.graph)
    print(sess.run(h))
    writer.close()
63
In [ ]:
 


Ahora se ejecutará tensorboard, pasandole el directorio output donde se guardó el log de la sesión con sus operaciones.

tensorboard --logdir=./output/

El comando iniciará una sesión web de la aplicación tensorboard como lo muestra la siguiente figura:

Al abrir el navegador en localhost:6006 se tiene lo que muestra la siguiente figura:

Allí se visualiza las operaciones realizadas en la sesión y en el objeto Graph.

Pero, se puede agrupar los objetos Graph, y las operaciones para facilitar la visualización de los Objetos y sus operaciones.

A continuación la rescritura del mismo ejercicio:

In [1]:
import tensorflow as tf
In [2]:
#Se define el nombre del objeto graph y los scopes A,B y C.
with tf.name_scope("GrupoOperacion"):
    with tf.name_scope("Scope_A"):
        a = tf.add(1, 2, name="Suma_estos_numeros")
        b = tf.multiply(a, 3)
    with tf.name_scope("Scope_B"):
        c = tf.add(4, 5, name="Y_estos")
        d = tf.multiply(c, 6, name="Multiplica_estos_numeros")

with tf.name_scope("Scope_C"):
    e = tf.multiply(4, 5, name="B_suma")
    f = tf.div(c, 6, name="B_mult")
g = tf.add(b, d)
h = tf.multiply(g, f)
In [3]:
#Se crea la sesión y se corre el resultado del objeto h
with tf.Session() as sess:
    writer = tf.summary.FileWriter("output2", sess.graph)
    print(sess.run(h))
    writer.close()
63



Se vuelve a ejecutar tensorboard, pero en este caso abriendo el directorio output2:

tensorboard --logdir=./output2/

En la siguiente imagen se muestra los distintos Graph y cada operación que  manejan cada uno. 

De esta manera se tiene una mejor visualización de cada Objeto Graph y sus operaciones.