Introducción a las Redes Neuronales: Parte #2 - Aprendiendo matemáticas usando Redes Neuronales

Introducción:

Nuestro objetivo es construir y entrenar una red  neuronal, que pueda predecir la salida de una expresión matemática sin conocer su formula exacta. Considerando la siguiente expresión: (a+b)*2.
Lo que único que utilizaremos sera la librería numpy.

Resultado de imagen para inteligencia artificial

Matemáticas con redes neuronales:

Sera un ejemplo muy sencillo, que nos permitirá reforzar nuestras habilidades. La neurona tendrá 2 entradas y una salida.

El conjunto de entrenamiento constara de las siguientes entradas y salidas:

Inputs  Output
2, 3         10
1, 1         4
5, 2         14
12, 3       30

Tomaremos las entradas para el entrenamiento y las usaremos para ajustar los pesos y mediante una formula poder calcular la salida de la neurona.

Luego calcularemos el error comparando la salida esperada con la de la neurona. Dependiendo del valor del error calculado se ajustaran los pesos.

Todo esto se repetirá 10,000 de esta manera la neurona sera más eficaz. Este proceso es conocido como propagación hacia atrás.

Implementación:

from numpy import array, dot, random

# Declaramos la clase
class neural_network:
    def __init__(self):
        random.seed(1)
        # Pesos aleatorios. 2 entradas y una salida
        self.weights = 2 * random.random((2,1)) - 1
        
    def train(self, inputs, outputs, num):
        for iteration in range(num):
            output = self.predict(inputs) # Salida de la neurona
            error = outputs - output # Calculamos el error
            # Formula Ajuste: 0.01 * entradas * array(entradas) 
            ajuste = 0.01*dot(inputs.T, error)
            self.weights += ajuste
        
    def predict(self, inputs):
        # Calcular la salida de la neurona
        return dot(inputs, self.weights)
    
# Entradas
x = array([[2,3],[1,1],[5,2],[12,3]])

# Salidas
y = array([[10,4,14,30]]).T

# Entrenamiento de la red
red = neural_network()
red.train(x,y,10000)

# Dato de prueba
test1 = array([15,2])

# Mostramos la salida de la red
print("Resultado: %s" % red.predict(test1))

Resultado: [34.]

Efectivamente, (15+2)*2 es igual a 34.

Como pueden observar, es un ejemplo muy sencillo y practico. 

¿Alguna duda? No dudes en dejar tu comentario.
  1. Unknown dice:

    Haré mi comentario oportunamente , una vez explore los contenidos e ilustraciones.
    Gracias

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Introducción a las Redes Neuronales: Parte #2 - Red Neurona para el reconocimiento de patrones

Introducción:

Ya hemos adquirido los conocimientos suficientes para crear nuestro primer perceptrón, y lo hicimos de manera fácil y comprensible.

Lo siguiente que haremos, sera programar una red neuronal para el reconocimiento de patrones. 

Utilizaremos la librería numpy, de la cual utilizaremos algunos métodos para ahorrar algo de tiempo. Aunque te darás cuenta que son métodos que se pueden implementar de manera rápida en una función, todo depende de ti.

Por ultimo quiero advertirles que utilizaremos la función de activación sigmoide. Ya hemos hablado de las funciones de activación y de la función sigmoide en la parte #1 de la guía.


Red Neuronal para el reconocimiento de patrones:

¿A que me refiero con "Reconocimiento de Patrones"? 

111 = 1
101 = 1
011 = 0
010 = 0

El cerebro humano tiene la capacidad de aprender de su entorno gracias a que podemos reconocer patrones de manera rápida. 

En secuencia mostrada anteriormente, podemos ver un patrón muy sencillo. Si la cadena comienza o termina con el uno (1), esta cadena o datos, se clasificara como "1". Si la cadena empieza o termina con un cero (0) se clasificara como "0".

Nuestro objetivo es programar una red neuronal que pueda hacer lo que nosotros hemos hecho, reconocer este patrón.

# Importamos los métodos de numpy que utilizaremos
from numpy import exp, array, random, dot

# exp: Calcular la exponencialidad de los elementos de la matriz de entrada
# dot: Método para realizar producto de matrices

class neural_network_patterns():
    def __init__(self):
        random.seed(1)
        # Pesos iniciales
        # Red neuronal con 3 entradas y una salida
        self.weights = 2 * random.random((3,1)) - 1
        
    def sigmoide(self, x):
        return 1 / (1 + exp(-x))
    
    def train(self, inputs, outputs, num):
        for i in range(num): # Iteración
            output = self.prediction(inputs) # Salida 
            error = outputs - output # Calculo de error
            # Ajustamos los pesos
            # Formula: error * input * output * (1-output)
            ajuste = dot(inputs.T, error * output * (1-output)) 
            self.weights += ajuste
            
    def prediction(self, inputs):
        # Función sigmoide
        resultado = self.sigmoide(dot(inputs, self.weights))
        return resultado

# Instancia de nuestra clase
red = neural_network_patterns()

# Datos de entrenamiento
inputs = array([[1,1,1],[1,0,1],[0,1,1]])
outputs = array([[1,1,0]]).T # Salidas de los datos de entrenamiento
        
# Entrenamiento de la red neuronal
# inputs = datos de entrada
# outputs = salida de cada entrada
# 10000 = cuantas veces se repetira el entrenamiento de la red
red.train(inputs, outputs, 10000)

# Prueba 1
pre_1 = red.prediction(array([1,1,1]))[0]

# Prueba 2
pre_2 = red.prediction(array([0,1,0]))[0]

# round nos permitira redondear el numero
# y saber con más precisión la predicción
print("[1,1,1] = %s" % round(pre_1))
print("[0,1,0] = %s" % round(pre_2))

[1,1,1] = 1.0
[0,1,0] = 0.0


¿Alguna duda? No dudes en dejar tu comentario.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Introducción a las Redes Neuronales - Parte #2: Nuestra primera red neuronal

Introducción:

Ya hemos terminado la primera parte de este proyecto. Vimos cuales eran las características y conceptos básicos de una red neuronal. Ahora es momento de emplear todo lo aprendido para crear nuestras propias redes neuronales.

En esta segunda parte, nos dedicaremos a la creación de las distintas redes neuronales. En este primer articulo practico, construiremos un Perceptrón el cual ya hemos visto y analizado anteriormente. 

Por supuesto, si no has visto la primera parte, te recomiendo que lo hagas:
https://www.pythondiario.com/2018/08/introduccion-las-redes-neuronales-parte.html

Creación de nuestra propia red neuronal:

Existen miles de herramientas que nos ofrecen modelos y redes neuronales pre entrenadas. Incluso ya hemos visto algunas de esas librerías en este blog.

Pero no hay nada como crear nuestras propias herramientas. Esto nos permite conocer con exactitud con funciona el programa y sus procedimientos. Podemos acceder a ellas y alterarlas de la manera que creamos correcta.

Por ello en esta segunda parte de este proyecto, realizaremos redes neuronales desde cero, es decir que las programaremos nosotros mismos sin necesidad de una librería externa. 

En este caso realizaremos un Perceptrón , ya que es uno de los más sencillo y necesarios de conocer. Ya hemos hablado de el perceptrón y de sus características.

Sabemos que la forma de entrenar a un Perceptrón es la siguiente:

w = w + N(d(k)-y) x(k)

Donde:


W = El peso actual asociado a la sinapsis que une la neurona i de la capa de entrada y la neurona j de la capa de salida.
N = Es una constante entre 0 y 1 que indica cuanto aprende la red.
d(k) = El estado de la neurona de la capa de salida j.
y = El valor deseado para esa neurona.
x(k) = El estado de la neurona de la capa de entrada i.

Teniendo esto en cuenta, podemos entrenar a nuestra red neuronal.

Nuestro Primer Perceptrón:

Pateamiento del problema:
Nuestro objetivo es entrenar a un Perceptrón que pueda clasificar un conjuntos de datos sin clasificar.

Lo que haremos, sera crear un clase llamada Perceptron, de esta manera podremos crear todos los perceptrones que necesitemos y emplearlos para diferentes objetivos.

Tendrá dos entradas y una salida (p1, p2). 


Cada neurona de la red es una unidad de procesamiento de información; es decir, recibe información a través de las conexiones con las neuronas de la capa anterior, procesa la información, y emite el resultado a través de sus conexiones con las neuronas de la capa siguiente, siempre y cuando dicho resultado supere un valor "umbral".



En una red neuronal ya entrenada, las conexiones entre neuronas tienen un determinado peso ("peso sináptico").


El procesamiento de la información llevado a cabo por cada neurona Y, consiste en una función (F) que opera con los valores recibidos desde las neuronas de la capa anterior (Xi, generalmente 0 o 1), y que tiene en cuenta el peso sináptico de la conexión por la que se recibieron dichos valores (Wi). Así, una neurona dará mas importancia a la información que le llegue por una conexión de peso mayor que no a aquella que le llegue por una conexión de menor peso sináptico.


Para simplificar el sistema de entrenamiento, el valor umbral (U) pasa a expresarse como un peso sináptico más (-W0), pero asociado a una neurona siempre activa (X0). Esta neurona siempre activa, se denomina "bias", y se sitúa en la capa anterior a la neurona Y.

Neurona bias y su peso sináptico asociado (-W0), en substitución del valor umbral (U).
http://perso.wanadoo.es/alimanya/funcion.htm


Teniendo todo esto en cuenta, podemos empezar a implementarlo todo en el lenguaje de programación Python.

Perceptron.py

Empezaremos declarando nuestra clase con sus respectivos atributos:

 # Importamos la librerias necesarias
import random

# Declaramos la clase
class Perceptron:
    def __iniit__(self, sample, exit, learn_rate=0.01, epoch_number=1000, bias=-1):
        # Atributos de la clase
        self.sample = sample # Datos de entrenamiento
        self.exit = exit # Salida esperada para cada dato
        self.learn_rate = learn_rate # Que tanto aprendera la red
        self.epoch_number = epoch_number
        self.bias = bias # Bias de la red
        self.number_sample = len(sample) # Numero de ejemplos
        self.col_sample = len(sample[0]) # Columnas de los datos
        self.weight = [] # Lista de pesos



Estos serán los atributos que utilizara la red. Cada parámetro determinara la configuración de la red así como su eficiencia. Es recomendable ir cambiando los valored de los parametros para conseguir los resultados más eficientes. 




def trannig(self): # Metodo de entrenamiento
    
        for sample in self.sample: # Se recorren los datos de entrenamiento
            sample.insert(0, self.bias) # Se inserta el bias en la primera pocisión
        
        for i in range(self.col_sample):
            self.weight.append(random.random()) # Asignamos pesos aleatorios
            
        self.weight.insert(0, self.bias) # Insertamos el bias en los pesos
        
        epoch_count = 0
        
        while True:
            erro = False
            for i in range(self.number_sample):
                u = 0
                for j in range(self.col_sample + 1):
                    # Función de activación

u = u + self.weight[j] * self.sample[i][j]
y = self.sign(u) # Comprobar el valor del umbral
if y != self.exit[i]:

for j in range(self.col_sample+1):
# Función de entrenamiento
# w = w + N(d(k)-y) x(k)
self.weight[j] = self.weight[j] + self.learn_rate * (self.ex it[i]-y) * self.sample[i][j]
erro = True
epoch_count = epoch_count+1 # Se aumenta el numero de epoch
if erro == False:
print(('nEpoch: n', epoch_count)) # Mostramos el valor de epoch
print('-'*20)
print("n")
break


Aquí hay otro tema a tener en cuenta. Epoch: Cada presentación completa al perceptrón multicapa del set de entrenamiento se denomina epoch. Así, el proceso de aprendizaje se repite epoch tras epoch hasta que los pesos sinápticos se estabilizan y la performance de la red converge a un valor aceptable.


def sort(self, sample):
        """
        Se inserta el bias, ya que como discutimos antes,
        sera una neurona que siempre estara activada.
        """
        sample.insert(0, self.bias)
        u = 0
        for i in range(self.col_sample + 1):
            # Función de activación
            u = u + self.weight[i] * sample[i]
        
        # Comprobamos el valor de la función de activación
        y = self.sign(u) 
    
        # Si y es igual a -1, la clasificación corresponde a P1
        if  y == -1:
            print(('Ejemplo: ', sample))
            print('Clasificación: P1')
        # Si y es igual a 1, la clasificación corresponde a P1
        elif y == 1:
            print(('Ejemplo: ', sample))
            print('Clasificación: P2')
            
def sign(self, u):
    return 1 if u >= 0 else -1



El método sort utilizara la función de activación. Luego se comprobara la salida y se le asignara una clasificación a cada uno de los datos. Si y = -1 se asignara la clasificación P1 de lo contrario, se le asignara la clasificación P2.

# Datos de entrenamiento
samples = [
    [0, 2],
    [-2, 2],
    [0, -2],
    [2, 0],
    [-2,2],
    [-2,-2],
    [2,-2],
    [2,2],
]

# Clasificación de los datos de entrenamiento (salidas que esperamos para cada conjunto de dato)
"""
[0,2] = 1
[-2,-2] = 1
[0,-2] = 0
...
"""
exit = [1, 1, 0, 0, 1, 1, 0, 1]

#Intancia de nuestra neurona
network = Perceptron(sample=samples, exit = exit, learn_rate=0.01, epoch_number=1000, bias=-1)
 
# Entrenamos a la neurona
network.trannig()

"""
Le pedimos al usuario datos para entrenar.
Luego mostramos el resultados
"""
while True:
    sample = []
    for i in range(2):
        sample.insert(i, float(input('Valor: ')))
    network.sort(sample) # Clasificacipon de nuevos datos
    print("n")



Ahora es momentos de utilizar la clase y empezar a entrenar a la neurona.


Todo el código completo nos quedaría así:

'''
 Perceptron
 w = w + N * (d(k) - y) * x(k)

 p1 = -1
 p2 = 1
'''

import random

class Perceptron:
    def __init__(self, sample, exit, learn_rate=0.01, epoch_number=1000, bias=-1):
        self.sample = sample
        self.exit = exit
        self.learn_rate = learn_rate
        self.epoch_number = epoch_number
        self.bias = bias
        self.number_sample = len(sample)
        self.col_sample = len(sample[0])
        self.weight = []

    def trannig(self):
        for sample in self.sample:
            sample.insert(0, self.bias)

        for i in range(self.col_sample):
           self.weight.append(random.random())

        self.weight.insert(0, self.bias)

        epoch_count = 0

        while True:
            erro = False
            for i in range(self.number_sample):
                u = 0
                for j in range(self.col_sample + 1):
                    u = u + self.weight[j] * self.sample[i][j]
                y = self.sign(u)
                if y != self.exit[i]:

                    for j in range(self.col_sample + 1):

                        self.weight[j] = self.weight[j] + self.learn_rate * (self.exit[i] - y) * self.sample[i][j]
                    erro = True
            epoch_count = epoch_count + 1
            if erro == False:
                break

    def sort(self, sample):
        sample.insert(0, self.bias)
        u = 0
        for i in range(self.col_sample + 1):
            u = u + self.weight[i] * sample[i]

        y = self.sign(u)

        if  y == -1:
            print('Clasificación: P1 (-1)')
        else:
            print('Clasificación: P2 (1)')

    def sign(self, u):
        return 1 if u >= 0 else -1
        
# Datos de entrenamiento
samples = [
    [0, 2],
    [-2, 2],
    [0, -2],
    [2, 0],
    [-2,2],
    [-2,-2],
    [2,-2],
    [2,2],
]

# Clasificación de los datos de entrenamiento (salidas que esperamos para cada conjunto de dato)
"""
[0,2] = 1
[-2,-2] = 1
[0,-2] = 0
...
"""
exit = [1, 1, -1, -1, 1, 1, -1, 1]

network = Perceptron(sample=samples, exit = exit, learn_rate=0.01, epoch_number=1000, bias=-1)

network.trannig()

while True:
    sample = []
    for i in range(2):
        sample.insert(i, float(input('Valor: ')))
    network.sort(sample)
    print("n")



Luego de realizar too esto, ya estamos aptos de ejecutar el algoritmos.

Valor: 1
Valor: -2
Clasificación: P1 (-1)


Valor: 1
Valor: 2
Clasificación: P2 (1)

El programa continuara pidiendo datos para clasificar hasta detener el programa.


Siempre lo digo, y lo volveré a decir. "Entre más datos, mejor", entrena a la red con todos los datos posibles. En la mayoría de los casos, los datos de entrenamiento son los que más influyen en la eficacia de la red neuronal.


Eso ha sido todo por hoy. ¿Alguna duda? No dudes en dejar tu comentario.


Mi nombre es Luis, y fue un placer compartir mis conocimientos con todos ustedes :D.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Introducción a las Redes Neuronales - Parte #1

Las Redes Neuronales son el pilar de la Inteligencia Artificial. En esta pequeña guía, nos enfocamos en conocer los conceptos básicos sobre este tema tan maravilloso.

Introducción a las Redes Neuronales - Parte #1 : Conceptos Básicos


  1. ¿Qué es una Red Neuronal?
  2. Elementos Básicos de una Red Neuronal
  3. Métodos de Aprendizaje
  4. Topología de las Redes Neuronales
  5. Tipos de Redes Neuronales
Este es un proyecto en el cual he trabajado desde hace algunas semanas. Este es el primer proyecto de este tipo que llevo a cabo. Me gustaria que inundaran con sus comentarios constructivos.


En al segunda parte de esta guía, emplearemos toda la teoría vista hasta ahora, para crear nuestra propias redes neuronales desde cero.
  1. Unknown dice:

    Que Modulos de Python nesesitaremos para poder crear la red neural y mi siguiente pregunta con que version de python vas a empezar la 3 o 2

  2. Unknown dice:

    Este tema se vé interesante. Espero continúe 🙂 gracias por dedicarte a compartir estos conocimientos

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir
White Monkey