Нейронные сети в JavaScript с Brain.js

Введение. Особенно за последние несколько лет нейронные сети (НС) действительно стали практичным и эффективным способом решения проблем, которые не могут быть легко решены с помощью алгоритма, таких как обнаружение лиц, распознавание голоса и медицинская диагностика. Во многом это стало возможным благодаря недавним открытиям в отношении того, как лучше обучать и настраивать сеть, а также увеличению скорости компьютеров. Совсем недавно студент Имперского колледжа Лондона создал сеть сетей под названием Giraffe [http: //www.technologyreview.c

Вступление

Особенно за последние несколько лет нейронные сети (НС) действительно стали практичным и эффективным способом решения проблем, которые не могут быть легко решены с помощью алгоритма, таких как обнаружение лиц, распознавание голоса и медицинская диагностика. Во многом это стало возможным благодаря недавним открытиям в отношении того, как лучше обучать и настраивать сеть, а также увеличению скорости компьютеров.

Совсем недавно студент Имперского колледжа Лондона создал НС под названием Жираф, которую можно было обучить всего за 72 часа, чтобы играть в шахматы на том же уровне, что и международный мастер ФИДЕ. Компьютеры, играющие в шахматы на этом уровне, на самом деле не новы, но способ создания этой программы - новый. На создание этих программ обычно уходят годы, и они настраиваются с помощью настоящего гроссмейстера, в то время как Giraffe, с другой стороны, был построен просто с использованием глубокой нейронной сети, некоторого творчества и огромного набора данных о шахматных партиях. Это еще один пример обещания, которое нейронные сети демонстрируют в последнее время, и они будут только улучшаться.

Brain.js

Обратной стороной NN и искусственного интеллекта в целом является то, что эта область очень сложна с математикой, что имеет тенденцию отпугивать людей еще до того, как они начнутся. Сугубо технический характер НС и весь сопутствующий ей жаргон затрудняют непосвященным воспользоваться преимуществом. Здесь на помощь приходит Brain.js. Brain.js отлично справляется с задачей упрощения процесса создания и обучения NN, используя простоту использования JavaScript и ограничивая API несколькими вызовами методов и опциями.

Не поймите меня неправильно, вам все равно нужно знать некоторые концепции, лежащие в основе NN, но это упрощение делает его менее пугающим.

Например, чтобы обучить сеть приближению функции XOR (которая является одним из стандартных примеров NN), все, что вам нужно, это:

 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] 

Этот код просто создает новую сеть ( net ), train сеть, используя массив примеров, а затем run сеть с вводом [1, 0] , что правильно приводит к [0.933] (также известному как 1 ).

Хотя в Brain.js нет множества опций, позволяющих настраивать сети, API принимает достаточно параметров, чтобы сделать его полезным для простых приложений. Вы можете установить количество и размер ваших скрытых слоев, порог ошибки, скорость обучения и многое другое:

 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 
 }); 

См. Полный список опций в документации.

Хотя вы ограничены в типах сетей, которые вы можете построить, это не значит, что вы не можете сделать ничего значимого. Возьмем, к примеру, этот проект. Автор собрал кучу изображений капчи для своего набора данных, использовал простую обработку изображений для предварительной обработки изображений, а затем использовал Brain.js для создания нейронной сети, которая идентифицирует каждого отдельного символа.

Преимущества

Как я уже упоминал, Brain.js отлично подходит для быстрого создания простой сетевой сети на языке высокого уровня, где вы можете воспользоваться преимуществами огромного количества библиотек с открытым исходным кодом. Имея хороший набор данных и несколько строк кода, вы можете создать действительно интересную функциональность.

Научные / вычислительные библиотеки, написанные на JavaScript, подобные этой, как правило, довольно сильно критикуются , но лично я думаю, что Brain.js имеет свое место в JS, если у вас есть правильные ожидания и применение. Например, JS является доминирующим (единственным?) Языком, работающим на стороне клиента в браузере, так почему бы не воспользоваться преимуществами этой библиотеки для таких вещей, как игры в браузере, размещение рекламы (скучно, я знаю) или распознавание символов?

Недостатки

Хотя мы определенно можем получить некоторую ценность от такой библиотеки, она не идеальна. Как я уже упоминал, библиотека ограничивает вашу сетевую архитектуру до такой степени, что вы можете делать только простые приложения. Возможности для слоев softmax или другой структуры маловероятны. Было бы неплохо иметь хотя бы возможность дополнительной настройки архитектуры вместо того, чтобы скрывать все от вас.

Наверное, самая большая моя претензия заключается в том, что библиотека написана на чистом JavaScript. Обучение NN - это медленный процесс, который может занять тысячи итераций (то есть миллионы или миллиарды операций) для обучения миллионам точек данных. JavaScript ни в коем случае не является быстрым языком и действительно должен иметь дополнения для подобных вещей, чтобы ускорить вычисления во время обучения. Взломщик капчи, показанный выше, занял удивительно небольшое время обучения - 20 минут, но все, что требуется, - это еще несколько вводов и еще несколько данных, чтобы увеличить время обучения на несколько часов или даже дней, как вы увидите в моем примере ниже.

К сожалению, эта библиотека уже заброшена ее автором (к описанию на Github добавляется "[НЕПОДДЕРЖИВАЕТСЯ]"). Хотя я понимаю, что может быть трудно удовлетворить требования популярной библиотеки с открытым исходным кодом, это все еще вызывает разочарование, и мы можем только надеяться, что кто-то квалифицированный сможет заполнить этот пробел. Я уверен, что в разработке уже есть хороший форк, но, возможно, потребуется поискать его.

Пример

Здесь я покажу вам более сложный пример использования Brain. В этом примере я создал сетевую сеть, которая может распознавать одну рукописную цифру (0–9). Набор данных, который я использую, - это популярный набор данных MNIST , который содержит более 50 000 образцов рукописных цифр. Этот вид проблемы известен как оптическое распознавание символов (OCR), которое является популярным приложением NN.

Распознавание работает путем получения изображения в оттенках серого 28x28 рукописной цифры и вывода цифры, которую, по мнению сети, она «видела». Это означает, что у нас будет 784 входа (по одному на каждый пиксель) со значениями от 0 до 255, и будет 10 выходов (по одному на каждую цифру). Каждый вывод будет иметь значение 0-1, что по сути является уровнем уверенности в том, что эта конкретная цифра является правильным ответом. Тогда наш ответ - это высшая степень достоверности.

К коду:

 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 
 }); 
 }); 

train.csv - это просто CSV с одним изображением в строке. Первое значение - это цифра, показанная на изображении, а следующие 784 значения - это данные пикселей.

Количество слоев и узлов, которые я выбрал, было немного произвольным и, вероятно, излишне большим для этого приложения OCR. Однако, если вы не можете воспользоваться такими вещами, как softmaxes или пул, возможно, вам больше повезет, увеличив количество слоев и количество узлов.

Чтобы получить достойные результаты, тренировка заняла больше часа. Хотя это было ожидаемо, я все же был немного разочарован тем, что пришлось ждать так долго, чтобы протестировать новую структуру сети или новые параметры обучения. Такое простое приложение не должно занимать так много времени, но это цена, которую вы платите за реализацию, полностью основанную на JavaScript.

Чтобы протестировать сеть, я загрузил другой файл, test.csv , и использовал его в качестве основы для сравнения сетей. Таким образом, мы получаем лучшее представление о производительности, поскольку тестируем входы, на которых сеть еще не обучена.

Вот как я тестировал сеть (я показываю только соответствующие части):

 // 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)) + '%'); 
 }); 

Заключение

Хотя есть некоторые недостатки, в целом я думаю, что Brain.js может быть очень полезным и добавить большую ценность приложениям JavaScript / Node. Его простота использования должна позволить практически любому начать работу с нейронными сетями.

Если вам нужно что-то более гибкое или вас беспокоит отсутствие поддержки Brain.js, взгляните на Synaptic , который позволяет гораздо больше настраивать вашу сетевую архитектуру. У него не такая популярность / внимание, как у Brain, но он кажется следующим лучшим выбором для нейронных сетей в JavaScript.

Какой у вас опыт работы с Brain.js? Вы порекомендуете какие-либо другие пакеты AI? Дайте нам знать об этом в комментариях!

comments powered by Disqus