2: Первая нейронная сеть
Last updated
Last updated
Сперва, давайте начнем с ответа на простой вопрос: Что такое Нейрон? Давайте рассмотрим формальное определение:
Нейрон, или нейрон, или нервная клетка - электрически возбудимая клетка, которая принимает, обрабатывает и передает информацию при помощи электрических и химических сигналов [1]
Как вы могли заметить, у Нейрона есть три основные функции:
Прием сигналов
Обработка сигналов
Передача результата после обработки
Эти три функции отлично сочетаются с тремя ключевыми компонентами настоящего Нейрона, посмотрите на следующий рисунок Нейрона:
Эти три компонента один к одному соответствуют основным функциям, исполняющимся Нейроном::
Дендриты - получает сигнал и передает его в тело клетки (нейрона)
Сома (тело) - обрабатывает сигнал (body)
Аксон - посылает сигнал другим нейронам
Теперь мы можем воссоздать математическую модель Нейрона:
Веса – каждый вес отражает дендрит и отвечает за прием сигнала из окружения. Поскольку у каждого дендрита есть свой размер (форма), существует некое отклонение между сигналом, передающимся дендриту, и сигналом, передающимся от дендрита в сому. Потому нам и нужен вес для каждой связи. Вес, по сути, говорит нам, как дендрит влияет на сигнал. Как только все сигналы собираются и перемножаются с весом, они суммируются и передаются в сому.
Функция Активации – это математическая функция, эмулирующая тело нейрона (сому), и единственная функция, которую она должна выполнять – преобразование входного сигнала в сигнал, передающийся другому нейрону в сети. Вы можете выбрать понравившуюся функцию, но, конечно, есть функции, которые подходят больше, а есть которые меньше на эту роль. О наиболее распространенных функциях активации мы будем говорить позже в этой книге.
Со всеми полученными знаниями мы наконец готовы приступить к написанию кода.
Весь обсуждаемый код можно найти в следующем бранче: https://github.com/DeepJavaUniverse/DJ-core/tree/chapter_2
Теперь давайте на самом деле разберем пример: случай с вечеринкой. Смоделируем его с помощью ручки и бумаги. 3 входных нейрона, 1 выходной с очень простой сигмоидальной функцией для активации.
Чтобы сделать сеть нам необходимо обозначить 2 типа нейронов:
Входные нейроны;
Связанные нейроны;
Входной нейрон:
Прежде чем мы сможем продолжить реализацию нашего первого настоящего Нейрона, нам необходимо обозначить некоторые вещи для начала:
Интерфейс для Функции Активации;
Нашу первую простейшую Функцию Активации;
Интерфейс будет простым:
Здесь, правда, ничего сложного, Double на входе, Double на выходе. В нашей первой реализации мы будем использовать ступенчатую функцию:
Если вы построите график функции, то он будет выглядеть так:
Сейчас мы готовы обсудить самую сложную часть этой главы – реализацию нашего первого настоящего Нейрона. Мы разберем его по частям. Для начала давайте опишем все поля, которые нам потребуются: Представляет соединения от нейрона к нейронам, от которых он получает сигналы. Например, в следующей сети:
К этому моменту должно стать очевидно, как работает добавление связей:
И главная функция, делающая всю магию:
Одна вещь, которую мы опускаем – Builder. Поскольку паттерн builder не имеет ничего общего с DeepLearning мы просто предположим, что Builder существует для нашего класса, но мы не показываем фрагмент кода здесь.
Сейчас мы можем создать нашу первую нейронную сеть (Neural Network, NN). Для начала давайте опишем нейронную сеть, которую мы собираемся построить. Наша первая NN будет предсказывать, нужно ли идти на вечеринку или нет. Для построения сети у нас должны быть данные для обучения сети. Поскольку мы не знаем, как тренировать нашу сеть, мы будем делать это вручную, наблюдая за шаблонами в наших данных и пытаясь подобрать такие веса, которые позволят сети делать верные предсказания. Итак, здесь есть то, что мы знаем о факторах, влияющих на опыт:
Факт того, будет ли наш лучший друг на вечеринке или нет;
Наличие любимого напитка (давайте назовем его "Vodka" :) );
Погода (солнечно или нет);
Сейчас мы можем создать комбинацию всех этих факторов и желаемое поведение для каждого из них. Чтобы сделать изображение более простым, мы используем 1 или 0, чтобы представить каждый фактор. 1 будет обозначать присутствие фактора, а 0 – его отсутствие. Так как мы говорим о трех факторах, входом для нашей NN будет 3 цифры (1 или 0 каждая), например, следующий массив отображает вход с информацией о том, что наш лучший друг будет на вечеринке, но не будет любимого напитка и погода будет не солнечная, в следствии чего мы не пойдем на вечеринку:
[1, 0, 0] => 0
Еще один пример с информацией об отсутствии лучшего на вечеринке, но будет напиток и солнечная погода на улице – нужно идти на вечеринку.
[0, 1, 1] => 1
Давайте построим все возможные комбинации данных и результатов:
[1, 0, 0] => 0 [0, 1, 0] => 0 [0, 0, 1] => 0 [1, 1, 0] => 1 [1, 0, 1] => 1 [0, 1, 1] => 1 [1, 1, 1] => 1
Как наша NN будет выглядеть? На самом деле, все просто. У нас будет 3 входных нейрона и 1 выходной нейрон. Пожалуй, можно сразу перейти к изображению NN, оно проще для понимания:
Эта сеть называется «полносвязная однослойная сеть». Звучит пугающе, я думаю, что многие люди в науке сознательно пытаются создать такое впечатление :) В любом случае, мы собираемся разделить название на части и последовательно обсудить. Полносвязная просто означает, что у каждого нейрона в слое есть связь с каждым нейроном предшествующего слоя. Слой – абстракция, которой не существует в настоящем мозге, просто упрощение, позволяющее инженерам проще изображать нейронные сети. Каждый слой – коллекция нейронов, у которых нет связи друг с другом. Нейроны в слое получают сигналы только от предшествующего слоя (если такой существует) и посылают сигналы в следующий слой (если такой существует). Глядя на нашу картинку, кто-то может подумать, что это двуслойная сеть. Исторически так сложилось, что входной слой не считают (или, может быть, мы считаем от 0, тогда это имеет смысл). Если мы не считаем входной слой, эта сеть, безусловно, однослойная.
На этом этапе у нас есть абсолютно все, что нам необходимо, чтобы продолжить реализацию нашей первой NN: данные, архитектура сети и даже веса, которые мы будем использовать. Так давайте реализуем: