Реализация вашей первой нейронной сети на JavaScript

Нейронные сети звучат сексуально и интересно. Но какие именно? Как они достигают своей магии и, самое главное, можете ли вы создать ее, не будучи экспертом в области анализа данных?

В этой статье я собираюсь показать вам основы нейронных сетей и то, как вы можете реализовать их самостоятельно, используя существующие инструменты.

Это будет очень полезная статья, и в конце я покажу вам, как вы можете построить свою собственную нейронную сеть, чтобы нарисовать базовое изображение ASCII в вашем терминале.

Давайте приступим к делу!

Понимание нейронных сетей

Нейронные сети — это особый тип структуры данных, состоящий из отдельных элементов, известных как «нейроны». Нейроны сгруппированы в слои и соединяются с другими нейронами из других слоев.

Одной из самых основных структур нейронной сети является нейронная сеть с прямой связью, они состоят из входного слоя, одного или нескольких скрытых слоев и выходного слоя, а информация течет только в одном направлении (от входного слоя к выходному слою).

Вот базовая диаграмма, чтобы показать, что я имею в виду:

По сути, входная информация вводится на входной слой, а оттуда данные преобразуются с использованием значений, называемых «весами», и специальных функций активации (функций, которые принимают значение и выводят значение от 0 до 1).

Когда вы объединяете группу этих нейронов и корректируете веса должным образом (что вы делаете, когда «обучаете» сеть), то комбинированный результат является ожидаемым (или достаточно близким) на основе предоставленных вами входных данных.

Например, базовым примером является решение уравнения XOR. Мы все знаем, что XOR работает следующим образом:

[0,0] => 0
[0,1] => 1
[1,0] => 1
[1,1] => 0

Но если вы создадите сеть с прямой связью, которая имеет 2 входа и 1 выходной нейрон, после обучения вы сможете вводить любую комбинацию 0 и 1, и вы получите ожидаемый результат XOR без фактического программирования поведения XOR.

Это основная причина, по которой вы хотите использовать нейронные сети для достижения обобщенного поведения без фактического кодирования каждого отдельного правила.

Типы нейронных сетей

Существует много типов нейронных сетей, каждая из которых имеет свой собственный набор характеристик и способов использования. Перечисление их всех здесь и углубленное изучение того, почему вы хотите их использовать и как это реализовать, противоречит практическому подходу этой статьи.

Итак, вот список наиболее распространенных (имейте в виду, что есть и другие):

  1. Нейронные сети с прямой связью: мы уже рассмотрели это выше. Это самые распространенные и простые сети, но они все же имеют допустимые варианты использования.
  2. Сверточные нейронные сети (CNN). Это нейронные сети, предназначенные для задач распознавания и обработки изображений. Они особенно эффективны при изучении признаков из данных изображения и обычно используются в приложениях компьютерного зрения.
  3. Рекуррентные нейронные сети (RNN). Это нейронные сети, предназначенные для задач последовательной обработки данных, таких как языковой перевод или распознавание речи. Они особенно эффективны при изучении закономерностей в последовательных данных и обычно используются в приложениях обработки естественного языка (NLP).
  4. Автоэнкодеры. Это нейронные сети, предназначенные для задач уменьшения размерности и изучения признаков. Они состоят из входного слоя, скрытого слоя и выходного слоя и обучены восстанавливать входные данные на выходном слое.
  5. Генеративно-состязательные сети (GAN). Это нейронные сети, предназначенные для создания синтетических данных. Они состоят из двух сетей: сети генератора, которая генерирует синтетические данные, и сети дискриминатора, которая пытается отличить синтетические данные от реальных данных.
  6. Трансформеры: они очень хороши в НЛП и генерации текста. Они значительно улучшили современные результаты для многих задач обработки естественного языка и стали широко использоваться в полевых условиях. ChatGPT, например, использовал эти типы NN (нейронных сетей) в процессе обучения.

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

Понравилось ли вам то, что вы прочитали? Подпишитесь на мой БЕСПЛАТНЫЙ информационный бюллетень, где я делюсь со всеми своим 20-летним опытом работы в ИТ-индустрии. Присоединяйтесь к Бродяге старого разработчика!

Реализация вашей первой нейронной сети

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

В моем случае я выбрал Synaptic, так как он предоставляет низкоуровневый интерфейс, но базовые строительные блоки уже есть. Таким образом, вы получаете хорошее представление о том, что нужно сделать для создания NN, не беспокоясь о сложной математике.

Вместо решения уравнения XOR с нашей NN, что является одним из базовых примеров, я хотел использовать его для «отрисовки» ASCII-изображения на терминале. Изображение относительно маленькое, потому что мы пытаемся сократить время обучения.

Это та матрица, которую я хочу нарисовать, точнее, я хочу, чтобы НС научилась рисовать. Итак, что мы сделаем, так это создадим NN с теми же тремя слоями, что и раньше:

  • Входной слой с двумя нейронами для координат X и Y.
  • Скрытый слой с 15 нейронами.
  • И выходной слой всего с 1 нейроном, потому что я хочу понять, нужно ли для каждого набора координат печатать 1 или 0.

Мы установим NN следующим образом, используя Synaptic:

Теперь для обучения мы будем использовать скорость обучения 0,3, что означает, что наши веса между нейронами будут корректировать свое значение на 0,3 на каждой итерации. Затем они сравнивают результат с тем, что они должны печатать, и на следующей итерации вносят соответствующие коррективы.

Константа image содержит результат, которого я хочу достичь, я буду использовать его для обучения сети. Это матрица 8x6 из 0 и 1.

Затем я прогоню 30к итераций для обучения, на каждом «пикселе» вызову метод activate, который вводит входные данные во входной слой, а затем запускает NN. Затем, используя метод propagate, с learningRate и ожидаемым значением для последней активации, сеть настроится сама.

Примечание: небольшая формула «y * 8 + x» — это небольшой трюк для навигации по одномерному массиву с использованием декартовых координат. По сути, вы делаете «‹y coord› * ‹width› + ‹x coord›», и вам больше не нужен двумерный массив.

После завершения обучения все, что нам нужно сделать, это снова просмотреть координаты и попросить их активировать, только на этот раз мы распечатаем результаты. Для этого я создал следующую функцию:

Для каждой координаты Y мы сохраним все результаты активации в список, а затем, как только строка будет завершена (после того, как мы пройдем все координаты X для этой Y), мы распечатаем ее.

Я использую Math.round здесь с результатом, потому что вывод NN не будет 0 или 1, вместо этого это будет число между обоими.

Результат? Взглянем:

Как видите, результат не идеален, обратите внимание на 2 ошибки на этом изображении. Возможно, тренируя его немного дольше, мы получим лучшие результаты, но это также один из лучших результатов, которые я получил.

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

Вот почему вы получаете странные руки при создании изображений с помощью Dall-e или Midjourney, или почему ChatGPT иногда пишет предложения, которые не соответствуют действительности, или код с ошибками. Они достаточно близки, судя по цифрам, полученным в результате их тренировок.

Нейронные сети могут быть очень полезны, когда вы хотите добиться поведения, которое либо должно адаптироваться к различному количеству входных данных, либо просто для того, чтобы его кодирование потребовало много работы.

Вместо этого, тренируясь с использованием правильных входных данных, вы можете получить достаточно близкие результаты.

Вы использовали NN раньше? Для чего вы их использовали?

Создавайте приложения с повторно используемыми компонентами, как Lego

Инструмент с открытым исходным кодом Bit помогает более чем 250 000 разработчиков создавать приложения с компонентами.

Превратите любой пользовательский интерфейс, функцию или страницу в компонент многократного использования — и поделитесь им со своими приложениями. Легче сотрудничать и строить быстрее.

Подробнее

Разделите приложения на компоненты, чтобы упростить разработку приложений, и наслаждайтесь наилучшими возможностями для рабочих процессов, которые вы хотите:

Микро-интерфейсы

Система дизайна

Совместное использование кода и повторное использование

Монорепо

Узнать больше