Jesús Manuel Mager Hois

Introducción

El perceptrón es un algoritmo bio inspirado desarrollado por Frank Rosenblatt y es capás de clasificar elementos que sean linealmente separables, generando un hiperplano que separe estos en n  dimensiones. Esto quiere decir, que si dibujamos datos que previamente separamos en clases, digamos una clase C1 y Cdonde C1 son buenos clientes y C2 son malos clientes, el algoritmo únicamente podrá clasificarlos si estos pueden ser separados por un plano. ¿Por qué un plano? Si cada cliente tuviera tres características, digamos calificación del buró de crédito, edad y compras pasadas en nuestra tienda, entonces los clientes tendrían tres dimensiones. Se pueden agregar n dimensiones, y el si se puede dibujar un hiperplano que atraviese estas n dimensiones, entonces el perceptrón será capáz de clasificar los datos.

La idea básica del perceptrón es es un vector de entrada xT = [x1, x2, ... xn], una unidad sumatoria, la función de evaluación y la salida de la misma, como se muestra en la siguiente figura. 

(Tomado de wikipedia, Alejandro Cartas )

 

En el trabajo se presentará un breve ejemplo de cómo realizar esta clasificación y cómo varían los resultados con algunas modificaciones. 

 

Desarrollo

Dadas dos clases de patrones de tres atributos cada uno, y donde cada clase contiene exactamente cuatro patrones, con los siguientes valores:

\[  C_1=\quad \begin{bmatrix} 0 & 0 & 0 \\ 1 & 0 & 1 \\ 1 & 0 & 0 \\ 1 & 1 & 0 \end{bmatrix}\]
\[ C_2=\quad \begin{bmatrix} 0 & 0 & 1 \\ 0 & 1 & 1 \\ 0 & 1 & 0 \\ 1 & 1 & 1 \end{bmatrix}  \]

Se va a utilizar un perceptrón para clasificar nuevos vectores. La regla de clasificación a usar será: 

 

\[ x^T\omega + \theta < 0, \wedge x\in C_1 \\ x^T\omega + \theta \geq 0, \wedge x\in C_2 \]

 

En dado caso de que no se cumpla las reglas de clasificación se generará una penalización sobre $\omega$ y en caso de corresponder a la regla no se realizará acción alguna. Las penalizaciones serán:

 

\[ x_n^T\omega>0 \wedge x_n\in C_1 \rightarrow \omega_{n+1}=\omega_n - rx_n\\ x_n^T\omega<0 \wedge x_n\in C_2 \rightarrow \omega_{n+1}=\omega_n + rx_n \]

Para tener una mejor comprensión del espacio donde se encuentran los patrones de entrenamiento se muestra a continuación su gráfica en el espacio R3:

Ahora se va a inicializar el vector omegai = 0  y el tamaño de paso r=1, que nos genera una convergencia en cuatro pasos. A continuación se presenta los puntos cortados en dos partes por el plano generado a con el perceptrón.

Para verificar que el perceptrón clasifique de manera correcta un nuevo vector se presenta xp = [1, 0.5, 0]t. La suma de los productos de los elementos de este vector y los pesos generados [-1, 1, 1] El punto xp pertenece a la clase 2, dado que

 

\[ x^T\omega + \theta \geq 0, \wedge x\in C_2 \\ .5 \geq 0, \wedge x\in C_2 \]

i el valor de $r$ cambia la manera de acercase al punto de convergencia va a cambiar. Se va a probar para $r=\{1, 0.5, 0,2, 0.1\}$. En la siguiente gráfica se muestra que entre más chico sea el valor de $r$ más ciclos va a requerir para llevar a la convergencia. Pero a partir de 0.5 no se suscede mejora alguna en los ciclos necesarios, por lo que 3 ciclos es el mejor resultado. 

 

Conclusiones

El perceptrón es un algoritmo simple que es útil en ciertas circunstancias, donde los datos son linealmente separables. Este no va a garantizar el resultado óptimo, pero su uno factible, y su convergencia va a estar dado por r que permitirá moverse en el espacio al plano. El valor ideal para este factor de convergencia está en .5 a 1, donde requiere menos ciclos. 

 

 

import numpy as np

# Vectores con los cuales se va a entrenar
d = np.matrix([[0,0,0],
              [1,0,1],
              [1,0,0],
              [1,1,0],
              [0,0,1],
              [0,1,1],
              [0,1,0],
              [1,1,1]])
#Matriz transpuesta
nd = np.transpose(d)

x3 = nd[0].tolist()
y3 = nd[1].tolist()
z3 = nd[2].tolist()

x3 = x3[0]
y3 = y3[0]
z3 = z3[0]

print(nd[0][0])
print(nd[1][0])
print(nd[2][0])


#Agregamos en el cuarto elemento del vector un 1
data = []
data.append(np.array([0,0,0,1]))
data.append(np.array([1,0,1,1]))
data.append(np.array([1,0,0,1]))
data.append(np.array([1,1,0,1]))
data.append(np.array([0,0,1,1]))
data.append(np.array([0,1,1,1]))
data.append(np.array([0,1,0,1]))
data.append(np.array([1,1,1,1]))


ciclosx= []
ciclosy= []
# Probamos con diferentes factores de convergencia
rlista = [1, 0.5, 0.2, 0.1]
for r in rlista:
    wn = np.array([1,1,1,r])
    newvec = 0
    clase = 0
    itr = 0
    # Ciclo principal del perceptron
    while True:
        itr = itr + 1
        errors = 0
        j = 0
        print("-"*75)
        for x in data:
            clasereal = 0
            xnwn = 0
            
            # Se prueba si genera la clase correcta
            for i in range(len(x)):
                xnwn= xnwn + x[i] * wn[i]
            if j < 4:
                clasereal = 1
            else:
                clasereal = 2

            if xnwn < 0: 
                clase = 1
            else:
                clase = 2
         
            pen = "0"
            # Penalizaciones
            if clase == 2 and clase != clasereal:
                newvec = wn - r*x
                errors = errors + 1
                pen = "-x"
            if clase == 1 and clase != clasereal:
                newvec = wn + r*x
                errors = errors + 1
                pen = "+x"

            # Se imprime en pantalla
            print(str(x), "\t|", str(wn), "\t|", str(xnwn), "\t|", str(clase), "\t|", str(clasereal), "\t|", pen)

            wn = newvec
            
            j = j + 1
        # Si todos los vectores tienen la clase correcta se 
        # termina el ciclo
        if errors == 0:
            break


    # Se calcula el numero de iteraciones
    print("Número de iteraciones:", str(itr)) 
    ciclosx.append(r)
    ciclosy.append(itr)

Share This