11 feb. 2018

Construir una red neuronal en pocos minutos

En el artículo anterior se mostró una red neuronal que clasificaba unos datos( Introducción al perceptron).

Como lo dice el vídeo de como construir una red neuronal en 4 minutos, los pasos para trabajar con Machine Learning son:

  1. Construir
  2. Entrenar 
  3. Probar


El vídeo a continuación de la explicación de la red neuronal:


Este artículo como el del vídeo se basa en un artículo publicado en medium que se llama How to build a simple neural network in 9 lines of Python code y en el artículo A Neural Network in 11 lines of Python (Part 1).

La idea es que se tiene una entrada de datos de 1 y 0 y se tiene una salida el cual es un 1 o un 0,  esta muestra de datos se usarán para entrenar a la red neuronal, luego al terminar el aprendizaje y se ajusten los pesos de la red neuronal, se le pasará un nuevo escenario de datos de entrada y la red calculará el valor de salida.

A continuación una imagen de las muestras de datos de entrada, la salida que se genera y el nuevo escenario de datos que se recibirá.


La ecuación para calcular la salida de una neurona es:




Como función  de activación de la red neuronal se usará un sigmoide:

Su ecuación es:

Y la gráfica:


Al sustituir la ecuación de la sumatoria con la función de la sigmoide se tiene la salida de una neurona:



A continuación el código de la construcción de la red neuronal, del entrenamiento y de la prueba:


In [1]:
# Datos de entrada y de salida
Entradas Salida
001 0
111 1
101 1
011 0
100 ?
In [2]:
#Se importan:
# exp: valor e
# array: manejo de arreglos
#random: números aleatorios
#dot: multiplicación de matrices.
from numpy import exp, array, random, dot
In [3]:
class RedNeuronal(object):
    def __init__(self,seed=1):
        # Seed el generador de números aleatorios, generará los mismos números
        #cada vez que el programa corra.
        random.seed(seed)

        # se modelará una simple neurona con 3 entradas y una salida.
        
        # se asignan pesos aleatorios a una matrix 3x1 con valores en el rango de -1 a 1
        # y media de cero
        self.pesos_sinaptico = 2 * random.random((3, 1)) - 1

    # La función sigmoid, describe una curva S.
    #Se pasa la suma de los pesos de las entradas a esta función
    # se normaliza entre 0 y 1.
    def __sigmoide(self, x):
        return 1 / (1 + exp(-x))

    # La derivada de la función sigmoid es el gradiente de la curva sigmoide
    def __derivada_sigmoide(self, x):
        return x * (1 - x)
    

    # Se entrena la red neuronal desde un proceso de ensayo y error
    # ajustando los pesos de las sinapcis cada vez
    def entrenar(self, datos_entrenamiento_entrada, datos_entrenamiento_salida, numero_iteraciones):
        for iteracion in range(numero_iteraciones):
            # Se para  los datos de entrenamiento a la red neuronal (una neurona)
            salida = self.pensar(datos_entrenamiento_entrada)

            # calculo del error (la diferencia entre la salida deseada y la que se predice
            error = datos_entrenamiento_salida - salida

            # multiplicar el error por la entrada y de nuevo por el gradiente de la curva sigmoide
            # Esto significa menos presos cercanos son ajustados más
            # esto significa las entradas las cuales son ceros, no causan
            # cambios a los pesos.
            ajuste = dot(datos_entrenamiento_entrada.T, error * self.__derivada_sigmoide(salida))

            # se ajustan los pesos
            self.pesos_sinaptico += ajuste

    # la neurona piensa.se le pasa las entradas.
    def pensar(self, entradas):
        # pasas las entradas a la red neuronal, se devuelve la función de activación(sigmoide)
        #se hace el producto punto de las entradas junto con los pesos.
        return self.__sigmoide(dot(entradas, self.pesos_sinaptico))
In [4]:
#Se inicializa una neurona de la red neuronal.
red_neuronal = RedNeuronal()

print ("Pesos iniciales de la sinaptic:\n {}".format(red_neuronal.pesos_sinaptico))

# Conjunto de datos de entradas y salidas para el entrenamiento de la neurona.
#se tienen 4 muestras, cada consiste de 3 valores de entrada y 1 no de salida
datos_entrada = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]])
datos_salida = array([[0, 1, 1, 0]]).T

# Se entrena a la red neuronal con el conjunto de datos
#Se entrena unas 10 mil veces y se hace un pequeño ajuste cada vez
red_neuronal.entrenar(datos_entrada, datos_salida, 100000)

print ("Nuevos pesos sinapticos luego del entrenamiento:\n{}".format(red_neuronal.pesos_sinaptico))

# Se prueba la red neuronal con un nuevo escenario de datos
print ("Considere la nueva situación [1, 0, 0] -> ?: {}".format(red_neuronal.pensar(array([1, 0, 0]))))
Pesos iniciales de la sinaptic:
 [[-0.16595599]
 [ 0.44064899]
 [-0.99977125]]
Nuevos pesos sinapticos luego del entrenamiento:
[[12.00870061]
 [-0.2044116 ]
 [-5.8002822 ]]
Considere la nueva situación [1, 0, 0] -> ?: [0.99999391]

El resultado para el caso de [1,0,0] es 1.


Publicar un comentario