El objetivo de la entrada, es profundizar en el funcionamiento del perceptrón, tanto a nivel conceptual como algorítmico, por eso evitaré todo lo que envuelve al perceptrón (historia orígenes). No es que no sea interesante, sino que se escapa del scope.

Lo único que mencionaré para que tengáis un puto de referencia es que esta entrada esta basada en la neurona de McCulloch y Pitts.

El objetivo de la entrada, es profundizar en el funcionamiento del perceptrón, tanto a nivel conceptual como algorítmico, por eso evitaré todo lo que envuelve al perceptrón (historia orígenes). No es que no sea interesante, sino que se escapa del scope.

Lo único que mencionaré para que tengáis un puto de referencia es que esta entrada esta basada en la neurona de McCulloch y Pitts.

Visión de una neurona como entidad de calculo

He visto muchos ejemplos donde explican de manera genérica, el perceptrón, en este caso me focalizaré en explicar de manera concreta, con datos limitados. De esta manera creo que es más sencillo entender el perceptrón y todo su potencial.

¿ Resulta complejo ?. Realmente cómo podéis ver, un perceptrón, es una función de umbral con dos vectores de entrada, la cual devuelve una salida o predicción (una vez entrenado) aplicando un umbral.

Función de umbral (threshold function)

Podéis ver información de la función de umbral en cualquier lado, no es algo complejo una vez que entiendes el funcionamiento y realmente es el “core” de nuestro perceptrón

Cómo podéis deducir esta función devuelve 0 o 1, dependiendo de la función de predicción. En nuestra implementación devolverá 1 o -1, para poder aplicar mas tarde una modificación de los pesos, pero eso lo veremos mas adelante

Y así de sencilla es la formula formal de una función de umbral, donde recibe x (entrada) w (peso) y dependiendo del resultado, de la función, estamos en un lado u otro del umbral. Concretamente si el resultado de operar nuestros vectores nos devuelve más de un umbral establecido nos dará 1 o 0

Entrenando el perceptrón

Llegados hasta este punto, ya tenemos claro las bases matemáticas implicadas. Ahora vamos a ver con detalle, que pasa con la entrada de unos datos cualesquiera en nuestro perceptrón.

Ahora tocaría pasar todos los datos de entrenamiento por nuestro perceptrón.

¿Pero, una iteración devolvería los pesos adecuados, como para diferenciar de manera inequívoca los nuevos datos a predecir?. La respuesta es no.

Por ese motivo haremos varias iteraciones sobre el feet de datos de entrenamiento, ajustando en cada iteración los pesos en nuestra función de umbral.

¿Pero, cómo hacemos los cálculos con los pesos y las entradas?.

Ejemplo:

Si tenemos que la predicción falla y devuelve un resultado diferente de 0, le aplicamos el “learnign rate”, realmente se lo aplicamos siempre, pero obviamente 0*any es 0. 

Formalizando: w = learning rate * (resultado esperado – predicción) * entrada

Pero… Que carajos es “learning rate”, es un ratio que se aplica a la predicción para ajustar cuanto se modificará o aproximará el umbral. En el ejemplo de implementación esta 0.5

Entrenando el perceptrón los limites del aprendizaje

Cómo ya he explicado arriba, debemos valorar, cuantas iteraciones necesitamos para que nuestro perceptrón sepa o calcule el umbral que separe o diferencie entre dos tipos diferentes.

En otras entradas veremos cómo linealmente no es possible pero hay otros mecanismos. Cómo podéis ver no todos los casos son linealmente separables, por lo tanto por muchas iteraciones que pongamos, no será capaz nuestro perceptrón de definir un umbral adecuado, aunque tendremos una predicción no será del todo fiable.

¿ Pero como ?. La precisión de la predicción la determina, el encontrar una respuesta única en el caso de la primera gráfica y una errónea en el resto, pero cabe la posibilidad de pequeños errores asumibles. Después de x iteraciones tendrás unos determinados pesos que definirán el resultado de la predicción ( es un poco complicado pero creo que se entiende)

Perceptrón el algoritmo de aprendizaje (CODE)

Enlace: Github repo (Python)

Ha llegado la hora de poner un poco de código a tanta letra. La implementación la hice en Python, hay muchas y de diferentes tipos/lenguajes. He intentado darle la suficiente semántica como para que el lector, con sólo ver el código sepa que hace y a que esta referido.

Disclaimer: En este código, veremos como aprende y el resultado de las modificaciones en los pesos. Por ese motivo hay una parte de prediction_error, para mostrar la evolución del aprendizaje.

Perceptrón

import numpy


class Perceptron(object):

    def __init__(self, learning_rate=0.01, iterations=50, random_state=1):
        self.weight = None
        self.prediction_error = []
        self.learning_rate = learning_rate
        self.iterations = iterations
        self.random_state = random_state

    def generate_random_weight(self, shape):
        random_state = numpy.random.RandomState(self.random_state)
        return random_state.normal(loc=0.0, scale=0.01, size=1 + shape)

    def training(self, x, y):
        self.weight = self.generate_random_weight(x.shape[1])
        for _ in range(self.iterations):
            prediction_fail = 0
            for entry, target in zip(x, y):
                update = self.learning_rate * (target - self.threshold_function(entry))
                if update != 0.0:
                    self.weight[1:] += update * entry
                    self.weight[0] += update
                    prediction_fail += 1
            self.prediction_error.append(prediction_fail)
        return self

    def scalar(self, x):
        return numpy.dot(x, self.weight[1:]) + self.weight[0]

    def threshold_function(self, entry):
        return numpy.where(self.scalar(entry) >= 0.0, 1, -1)

Ejemplo de uso

En principio aparecerá una gráfica, de los puntos que vamos a tratar, si la cerramos aparecerán los errores/ajustes en el aprendizaje como gráfica

import matplotlib.pyplot as pyplot
import pandas
import numpy
import perceptron as p


def show_data_in_graph(entries):
    pyplot.scatter(entries[:50, 0], entries[:50, 1], color='red', marker='o', label='setosa')
    pyplot.scatter(entries[50:100, 0], entries[50:100, 1], color='blue', marker='x', label='versicolor')
    pyplot.xlabel('sepal [cm]')
    pyplot.ylabel('petal [cm]')
    pyplot.legend(loc='lower right')
    pyplot.show()


def show_training_data(perceptron):
    pyplot.plot(range(1, len(perceptron.prediction_error) + 1), perceptron.prediction_error, marker='o')
    pyplot.xlabel('Iterations')
    pyplot.ylabel('Number of prediction errors')
    pyplot.show()


if __name__ == '__main__':
    data = pandas.read_csv('iris.data', header=None)
    entries = data.iloc[0:100, [0, 2]].values

    show_data_in_graph(entries)

    target = data.iloc[0:100, 4].values
    target_weight = numpy.where(target == 'Iris-setosa', -1, 1)

    perceptron = p.Perceptron(learning_rate=0.1, iterations=10)
    perceptron.training(entries, target_weight)
    show_training_data(perceptron)M

Deja una respuesta