Redes neuronales en JavaScript con Brain.js

     

    Introducci贸n

    Especialmente en los 煤ltimos a帽os, las redes neuronales (NN) realmente han despegado como una forma pr谩ctica y eficiente de resolver problemas que no se pueden resolver f谩cilmente con un algoritmo, como la detecci贸n de rostros, el reconocimiento de voz y el diagn贸stico m茅dico. Esto se debe en gran parte a los descubrimientos recientes sobre c贸mo entrenar y sintonizar mejor una red, as铆 como al aumento de la velocidad de las computadoras.

    Recientemente, un estudiante del Imperial College London cre贸 un NN llamado Jirafa que podr铆a entrenarse en solo 72 horas para jugar al ajedrez al mismo nivel que un Maestro Internacional de la FIDE. Las computadoras que juegan al ajedrez en este nivel no son realmente nuevas, pero la forma en que se cre贸 este programa es nueva. Estos programas suelen tardar a帽os en construirse y se ajustan con la ayuda de un gran maestro real, mientras que Giraffe, por otro lado, se cre贸 simplemente utilizando una red neuronal profunda, algo de creatividad y un enorme conjunto de datos de juegos de ajedrez. Este es otro ejemplo m谩s de la promesa que las redes neuronales han mostrado recientemente, y solo van a mejorar.

    Brain.js

    La desventaja de las NN, y de la inteligencia artificial en general, es que el campo es muy pesado en matem谩ticas, lo que tiende a asustar a las personas antes de que empiecen. La naturaleza altamente t茅cnica de las NN y toda la jerga que las acompa帽a hace que sea dif铆cil para los no iniciados aprovecharlas. Aqu铆 es donde Brain.js entra en juego. Brain.js hace un gran trabajo simplificando el proceso de creaci贸n y entrenamiento de una NN utilizando la facilidad de uso de JavaScript y limitando la API a unas pocas llamadas y opciones de m茅todos.

    No me malinterpretes, todav铆a necesitas conocer algunos de los conceptos detr谩s de las NN, pero esta simplificaci贸n lo hace mucho menos abrumador.

    Por ejemplo, para entrenar una red para aproximar el XOR funci贸n (que es uno de los ejemplos est谩ndar de NN), todo lo que necesita es:

    var brain = require('brain');
    
    var net = new brain.NeuralNetwork();
    
    net.train([{input: [0, 0], output: [0]},
               {input: [0, 1], output: [1]},
               {input: [1, 0], output: [1]},
               {input: [1, 1], output: [0]}]);
    
    var output = net.run([1, 0]);  // [0.933]
    

    Este c贸digo solo crea una nueva red (net), trains la red usando una serie de ejemplos, y luego runs la red con una entrada de [1, 0], que correctamente da como resultado [0.933] (tambi茅n conocido como 1).

    Si bien Brain.js no tiene un mont贸n de opciones que le permitan personalizar sus redes, la API acepta suficientes par谩metros para que sea 煤til para aplicaciones simples. Puede establecer el n煤mero y el tama帽o de sus capas ocultas, el umbral de error, la tasa de aprendizaje y m谩s:

    var net = new brain.NeuralNetwork({
    	hiddenLayers: [128,64]
    });
    
    net.train({
    	errorThresh: 0.005,  // error threshold to reach before completion
    	iterations: 20000,   // maximum training iterations 
    	log: true,           // console.log() progress periodically 
    	logPeriod: 10,       // number of iterations between logging 
    	learningRate: 0.3    // learning rate 
    });
    

    Consulte la documentaci贸n para obtener una lista completa de opciones.

    Si bien est谩 limitado en los tipos de redes que puede construir, eso no significa que no pueda hacer nada significativo. Tomar este proyecto por ejemplo. El autor reuni贸 un mont贸n de im谩genes captcha para su conjunto de datos, us贸 un procesamiento de im谩genes simple para preprocesar las im谩genes y luego us贸 Brain.js para crear una red neuronal que identifica a cada personaje individual.

    Ventajas

    Como ya mencion茅, Brain.js es excelente para crear r谩pidamente una NN simple en un lenguaje de alto nivel donde puede aprovechar la gran cantidad de bibliotecas de c贸digo abierto. Con un buen conjunto de datos y algunas l铆neas de c贸digo, puede crear algunas funciones realmente interesantes.

    Las bibliotecas altamente cient铆ficas / computacionales escritas en JavaScript como esta tienden a criticado bastante, pero personalmente creo que Brain.js tiene su lugar en JS siempre que tenga las expectativas y la aplicaci贸n adecuadas. Por ejemplo, JS es el lenguaje dominante (驴煤nico?) Que se ejecuta en el lado del cliente en el navegador, as铆 que 驴por qu茅 no aprovechar esta biblioteca para cosas como juegos en el navegador, colocaci贸n de anuncios (aburrido, lo s茅) o reconocimiento de personajes?

    Desventajas

    Si bien definitivamente podemos obtener algo de valor de una biblioteca como esta, no es perfecta. Como mencion茅, la biblioteca limita la arquitectura de su red a un punto en el que solo puede hacer aplicaciones simples. No hay muchas posibilidades de capas Softmax u otra estructura. Ser铆a bueno tener al menos la opci贸n de personalizar m谩s la arquitectura en lugar de ocultarle todo.

    Probablemente mi mayor queja es que la biblioteca est谩 escrita en JavaScript puro. Entrenar a una NN es un proceso lento que puede llevar miles de iteraciones (es decir, millones o miles de millones de operaciones) para entrenar en millones de puntos de datos. JavaScript no es un lenguaje r谩pido de ninguna manera y realmente deber铆a tener plugins para cosas como esta para acelerar los c谩lculos durante el entrenamiento. El cracker de captcha de arriba tom贸 un tiempo de entrenamiento sorprendentemente bajo de 20 minutos, pero todo lo que se necesita son algunas entradas m谩s y algunos datos m谩s para aumentar el tiempo de entrenamiento en unas pocas horas o incluso d铆as, como ver谩 en mi ejemplo a continuaci贸n.

    Desafortunadamente, esta biblioteca ya ha sido abandonada por su autor (la descripci贸n de Github est谩 precedida por “[UNMAINTAINED]”). Si bien entiendo que puede ser dif铆cil mantener las demandas de una biblioteca de c贸digo abierto popular, es decepcionante verlo, y solo podemos esperar que alguien calificado pueda llenar el vac铆o. Estoy seguro de que hay una buena fork ya est谩 en proceso, pero puede ser necesario buscarlo para encontrarlo.

    Ejemplo

    Aqu铆 les mostrar茅 un ejemplo un poco m谩s complicado de c贸mo usar Brain. En este ejemplo, cre茅 un NN que puede reconocer un solo d铆gito escrito a mano (0-9). El conjunto de datos que estoy usando es el popular MNIST conjunto de datos, que contiene m谩s de 50.000 muestras de d铆gitos escritos a mano. Este tipo de problema se conoce como reconocimiento 贸ptico de caracteres (LOC), que es una aplicaci贸n popular de NN.

    El reconocimiento funciona tomando una imagen en escala de grises de 28×28 de un d铆gito escrito a mano y generando el d铆gito que la red cree que “vio”. Esto significa que tendremos 784 entradas (una para cada p铆xel) con valores entre 0-255, y habr谩 10 salidas (una para cada d铆gito). Cada salida tendr谩 un valor de 0-1, que act煤a esencialmente como el nivel de confianza de que ese d铆gito en particular es la respuesta correcta. El valor de confianza m谩s alto es entonces nuestra respuesta.

    En el c贸digo:

    var brain = require('brain');
    var fs = require('fs');
    
    var getMnistData = function(content) {
    	var lines = content.toString().split('n');
    
    	var data = [];
    	for (var i = 0; i < lines.length; i++) {
    		var input = lines[i].split(',').map(Number);
    
    		var output = Array.apply(null, Array(10)).map(Number.prototype.valueOf, 0);
    		output[input.shift()] = 1;
    
    		data.push({
    			input: input,
    			output: output
    		});
    	}
    
    	return data;
    };
    
    fs.readFile(__dirname + '/train.csv', function (err, trainContent) {
    	if (err) {
    		console.log('Error:', err);
    	}
    
    	var trainData = getMnistData(trainContent);
    
    	console.log('Got ' + trainData.length + ' samples');
    
    	var net = new brain.NeuralNetwork({hiddenLayers: [784, 392, 196]});
    
    	net.train(trainData, {
    		errorThresh: 0.025,
    		log: true,
    		logPeriod: 1,
    		learningRate: 0.1
    	});
    });
    

    los train.csv El archivo es solo un CSV con una imagen por l铆nea. El primer valor es el d铆gito que se muestra en la imagen y los siguientes 784 valores son los datos de p铆xeles.

    La cantidad de capas y nodes que eleg铆 fue un poco arbitraria y probablemente innecesariamente alta para esta aplicaci贸n de OCR. Sin embargo, cuando no puede aprovechar cosas como softmaxes o pooling, es posible que tenga m谩s suerte aumentando el n煤mero de capas y el recuento de nodes.

    El entrenamiento tom贸 f谩cilmente m谩s de una hora para obtener resultados decentes. Si bien esto era lo esperado, todav铆a me decepcion贸 un poco tener que esperar tanto tiempo para probar una nueva estructura de red o nuevos par谩metros de aprendizaje. Una aplicaci贸n simple como esta no deber铆a tomar tanto tiempo, pero ese es el precio que paga por una implementaci贸n de JavaScript.

    Para probar la red, cargu茅 otro archivo, test.csv, y lo us贸 como base para comparar redes. De esa manera, tenemos una mejor idea del rendimiento, ya que estamos probando entradas en las que la red a煤n no ha sido entrenada.

    As铆 es como prob茅 la red (solo estoy mostrando las partes relevantes):

    // Require packages...
    
    fs.readFile(__dirname + '/test.csv', function (err, testContent) {
    	if (err) {
    		console.log('Error:', err);
    	}
    
    	// Load training data...
    
    	// Train network...
    
    	// Test it out
    	var testData = getMnistData(testContent);
    
    	var numRight = 0;
    
    	console.log('Neural Network tests:');
    	for (i = 0; i < testData.length; i++) {
    		var resultArr = net.run(testData[i].input);
    		var result = resultArr.indexOf(Math.max.apply(Math, resultArr));
    		var actual = testData[i].output.indexOf(Math.max.apply(Math, testData[i].output));
    
    		var str="(" + i + ') GOT: ' + result + ', ACTUAL: ' + actual;
    		str += result === actual ? '' : ' -- WRONG!';
    
    		numRight += result === actual ? 1 : 0;
    
    		console.log(str);
    	}
    
    	console.log('Got', numRight, 'out of 350, or ' + String(100*(numRight/350)) + '%');
    });
    

    Conclusi贸n

    Si bien hay algunas deficiencias, en general creo que Brain.js puede ser muy 煤til y agregar mucho valor a las aplicaciones JavaScript / Node. Su facilidad de uso deber铆a permitir que casi cualquier persona se inicie en las redes neuronales.

    En caso de que desee algo con m谩s flexibilidad o le moleste la falta de compatibilidad con Brain.js, eche un vistazo a Sin谩ptico, lo que permite una personalizaci贸n mucho mayor en la arquitectura de su red. No tiene la popularidad / atenci贸n que tiene Brain, pero parece ser la siguiente mejor opci贸n para redes neuronales en JavaScript.

    驴Cu谩l es tu experiencia con Brain.js? 驴Hay alg煤n otro paquete de IA que recomiende? 隆H谩znoslo saber en los comentarios!

    .

    Deja una respuesta

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