Perceptrón, primeros pasos hacia la inteligencia artificial basada en redes neuronales

AUTOR: Hugo Miguez CREADO: 2018-05-23 15:30:03

En este último tiempo de habla mucho de la inteligencia artificial basada en redes neuronales. Explicaremos de forma práctica el algoritmo más básico de una red neuronal. El Perceptrón.

Perceptrón

El Perceptrón es el algorítmo más simple dentro del campo de la inteligencia artificial. Se lo conoce también como red neuronal de una sola capa y fue creada por el psicólogo americano Frank Rosenblatt en el año 1957.

Puedes leer el siguiente artículo en wikipedia sobre Perceptrones. Este tutorial está basado en éste artículo con el código del algoritmo original en Python.

En la siguiente imagen puedes apreciar la estructura de un perceptrón, el cual está compuesto por unas entradas o señales (datos de entradas), los pesos (w1, w2, etc) y todo genera una única salida Y. 

entradas y pesos de un perceptron

El algoritmo del perceptrón necesita de datos de entrada, los cuales utilizará para "aprender" de ellos. Estos datos de entrada se le deben incorporar un dato de salida tipo binaria ( 0 o 1) el cual será el resultado correcto. 

El perceptrón simple solo es eficaz con datos que pueden ser serapables linealmente como puedes ver en la siguiente imagen.

separación lineal de los resultados de un perceptron

  • A: los resultados pueden ser separado linealmente.
  • B: los resultados no pueden ser separados linealmente y requiere más de una linea para su separación. Para este este tipo de salidas no puede ser aprendida por un perceptrón simple.
El Perceptrón simple solo es funcional con los resultados separados linealmente (Figura A de la imagen anterior).

Un ejemplo básico para entender el funcionamiento de aprendizaje del perceptrón:

Tenemos una tabla con una serie de datos: altura, peso, número de pie y sexo. Los tres primeros datos formarán las entradas del perceptrón (altura, peso y número de pie) la salida será el sexo (salida binaria 0 = hombre, 1 = mujer).

AlturaPesoNúmero de pieSexo
1.7056381
1.7263410
1.6050361
1.7063410
1.5855351
1.8380450
1.6564361
ok
?

Al algoritmo solo tendremos que indicarle una nueva entrada con la altura, peso y número de pie. Y nos indicará en función de lo aprendido con los datos anteriores de que sexo se trata. Puedes modificar los valores de altura, peso y tamaño de pie para probar su funcionamiento !.

Ahora que ya comprendes como funciona un Perceptrón nos pondremos con la fórmula y el código en javascript.



En la imagen anterior puedes ver la fórmula del perceptrón. La descripción textual en wikipedia es: 

El perceptrón usa una matriz para representar las redes neuronales y es un discriminador terciario que traza su entrada x (un vector binario) a un único valor de salida f(x) (un solo valor binario) a través de dicha matriz.
Donde w es un vector de pesos reales y w * x es el producto escalar (que computa una suma ponderada). u es el 'umbral', el cual representa el grado de inhibición de la neurona, es un término constante que no depende del valor que tome la entrada. 

Código del perceptrón

Datos iniciales de aprendizaje con sus respetivos resultados

var inp = [
    {in:[1.7,56,38], out:1},
    {in:[1.72,63,41], out:0},
    {in:[1.6,50,36], out:1},
    {in:[1.7,63,41], out:0},
    {in:[1.74,66,42], out:0},
    {in:[1.58,55,35], out:1},
    {in:[1.83,80,45], out:0},
    {in:[1.65,54,36], out:1}
];

En el código anterior puedes ver los datos iniciales compuesto por la variable in con los datos de entrada (altura, peso y número de pie) y con out el dato de salida binaria (si es hombre o mujer | 0 o 1)

Inicialización de los pesos del perceptrón

for(var n=0; n < inputs[0].in.length; n++){
    //w.push(0);
    w.push(Math.random());
}

Debemos inicializar los pesos del perceptrón. La variable  w  es de tipo array ( var w = []; ) y añadimos un elemento por cada elemento que contiene el elemento  in  ( en nuestro ejemplo  inp[0].in  ). El código original en python de wikipedia inicializa con el valor 0 (cero) pero en muchas otras documentaciones se inicializan con valores aleatorios. Ambos funcionan sin problema alguno.

Definiciones
  • variables
  • constantes

Función sumadora

var sum = 0;
for(var i=0; i < input.in.length; i++){
    sum += w[i]*input.in[i];
}
return sum;

La función sumadora suma todas las entradas  inp[ 0 a n ].in  de una posición del vector de entrada más los pesos w[ 0 a n ].

Para los datos de entrada inp[{in:[1.7,56,38], out:1}] será algo asi (teniendo en cuenta que el valor de los pesos estan inicializados a 0):
var sum = 0;
sum += w[0] * inp.in[0];   // sum += 0 * 1.7;
sum += w[1] * inp.in[1];   // sum += 0 * 56;
sum += w[2] * inp.in[2];   // sum += 0 * 38;

Función de entrenamiento

while(true){
    var contador_de_errores = 0;
    //recorremos todos los elementos de entradas del array de datos de entrenamiento
    for(var n=0; n < inputs.length; n++){
        var resultado = 0;
        var sum = getSum(inputs[n]);

        if(sum > umbral){
            resultado = 1;
        }

        var error = inputs[n].out - resultado;

        if (error !== 0){
            //console.log("sum[" + n + "]: " + getSum(inputs[n]));
            contador_de_errores += 1;
            for(var i=0; i < inputs[n].in.length; i++){
                w[i] += tasa_de_aprendizaje * error * inputs[n].in[i];
            }
        }
    }
    if (contador_de_errores === 0){
        break;
    }
}

El bucle principal while se ejecutará hasta que el contador de errores llegue a cero.

Dentro del while recorremos el array de entrada de entrenamiento y llamamos a la función sumatoria getSum(). Si el valor es mayor al umbral (umbral es una constante que hemos creado con el valor de 0.5) asignamos a la variable resultado el valor de 1, en caso contrario resultado valdrá 0.

la variable error es la diferencia entre la salida del array de entrenamiento (en nuestro caso  inp[ 0 a n ].out ) y la variable resultado.

si la variable error es distinto a cero incrementamos la variable contador_de_errores y modificamos los pesos de perceptrón. Para ello recorremos todas las entradas del elemento del array de entrada y reajustamos los pesos (variable w) incrementando el valor de tasa_de_aprendizaje (que es una constante que hemos asignado el valor de 0.1) multiplicado por error y por el valor de la entrada (  inp[ 0 a n ].in  ).

Función de predicción

var value = getSum(input);
return (value > 0)? 1 : 0;

La función para predecir el resultado es muy simple. Se llama a la función sumadora getSum con la entrada de datos de los que se quiere obtener el resultado. En nuestro caso le pasaremos un valor como el siguiente:

 { in:[1.76, 74, 44]} 

Puedes observar que los datos no lleva una salida. Esto es normal ya que es el dato que quieres saber. La función retornará 1 si el resultado de getSum() retorna un valor mayor de cero, en caso contrario devolverá cero.

Código completo del Perceptrón

var Perceptron = function(){
    var umbral = 0.5;
    var tasa_de_aprendizaje = 0.1;
    var w = [];
    
    function init(inputs){
        for(var n=0; n < inputs[0].in.length; n++){
            //w.push(0);
            w.push(Math.random());
        }
        train(inputs);
    }
    
    //suma entradas con pesos
    function getSum(input){
        var sum = 0;
        for(var i=0; i < input.in.length; i++){
            sum += w[i]*input.in[i];
        }
        return sum;
    }
    
    //función para entrenar la neurona, el cual modifica los pesos (w) en función de los valores y resultado (inputs.in , input.out).
    function train(inputs){
        while(true){
            var contador_de_errores = 0;
            for(var n=0; n < inputs.length; n++){
                var resultado = 0;
                var sum = getSum(inputs[n]);

                if(sum > umbral){
                    resultado = 1;
                }
                
                var error = inputs[n].out - resultado;

                if (error !== 0){
                    contador_de_errores += 1;
                    for(var i=0; i < inputs[n].in.length; i++){
                        w[i] += tasa_de_aprendizaje * error * inputs[n].in[i];
                    }
                }
            }
            if (contador_de_errores === 0){
                break;
            }
        }
    }
    
    //funcion para predecir la respuesta
    function predic(input){
        var value = getSum(input);
        return (value > 0)? 1 : 0;
    }
    
    
    return{
        init : init,
        train : train,
        getSum : getSum,
        predic : predic
    };
};

Código javascript para crear el objeto perceptrón, datos de entrada y datos para predecir

<script>    
    var inp = [
        {in:[1.7,56,38], out:1},
        {in:[1.72,63,41], out:0},
        {in:[1.6,50,36], out:1},
        {in:[1.7,63,41], out:0},
        {in:[1.74,66,42], out:0},
        {in:[1.58,55,35], out:1},
        {in:[1.83,80,45], out:0},
        {in:[1.65,54,36], out:1}
    ];

    var p = new Perceptron();

    p.init(inp);

    var r = p.predic({in:[1.76,74,44]});
    console.log("predic: " + r);
</script>

Comentar

Para poder realizar comentarios. Primero debes inicar sesión o crear una cuenta.