AlexeySpace.Ru

Пример простой нейронной сети на Unity

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

Unity на данный момент - это очень удобная и современная среда разработки приложений, для которой сейчас появляется достаточно много компонентов и фреймворков, которые позволяют работать с нейронными сетями. Но данная моя программа не использует никаких дополнительных модулей, так как нейронная сеть здесь достаточно простая, состоит всего из одного слоя, и выполнена она в виде обычного небольшого C# скрипта. Я сделал здесь все максимально просто, чтобы по этому скрипту можно было легко изучить алгоритм, по которому обучаются нейронные сети, то есть - это алгоритм обратного распространения ошибки.

Рис 1. Главное окно проекта Unity

Нейросеть, представленная в этой программе, показывает, как можно аппроксимировать различные математические функции, такие как синус, косинус, x2, и другие... На рисунке [2] показана схема данной нейронной сети.

Рис 2. Схема нейронной сети

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

Сеть состоит из двух так называемых "слоев" - скрытого и выходного. В скрытом слое содержится три нейрона. Но в программе число этих нейронов можно менять в реальном времени, т.е. прямо в процессе обучения сети. Что бы можно было в динамике посмотреть, как изменение кол-ва нейронов влияет на точность обучения сети. Причем в скрытом слое у каждого нейрона есть по два входа, на которые подаются значения x и 1 соответственно. Второй "выходной" слой сети, содержит только один нейрон.

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

В нейроне второго слоя функции активации нет. Там обычный сумматор. Если бы там тоже была функция активации, то мы бы уже не смогли построить график функции нейронной сети.

Рисунок [3] очень хорошо иллюстрирует, почему нелинейность так важна в нейронных сетях. Нелинейные функции активации позволяют нейронной сети строить более сложные границы между классами. Например в задаче классификации точек, без нелинейности нейронная сеть могла бы только провести прямую линию, которая разделяет черные и белые точки. Однако, с нелинейными функциями активации, нейронная сеть может построить более сложную границу между классами, которая может быть кривой и перегибаться, как показано на правом графике. Это позволяет нейронной сети более точно классифицировать данные, и достичь лучшей производительности в задаче классификации.

Рис 3. Иллюстрация нелинейности в нейронных сетях

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

Существует множество видов активационных функций, но самые распространенные из них - это так называемый "выпрямитель" ReLU (rectified linear unit), а также такие функции как сигмоид и гиперболический тангенс. Отличие всех этих активационных функций друг от друга состоит в том, что например релу ломает прямые и делает из них отрезки с острыми углами, а, например, сигмоид уже сгибает эту линию более плавно. Рисунок [4].

Рис 4. Виды функций активации в нейросетях

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

Суть обучения нейронной сети заключается в том чтобы правильно подобрать значения весовых коэффициентов. Т.е. значение весов нейронов скрытого и выходного слоя. Процесс обучения происходит следующим образом: Мы просто генерируем случайное вещественное число от - 2 до 2, вычисляем значение исходной функции и функции нейросети в этой точке, а также вычисляем ошибку, то есть разницу значений между исходной функцией и значением которое нам выдала нейронная сеть. И в соответствии с этой ошибкой, просто подстраиваем веса нужным образом, с помощью алгоритма обратного распространения ошибки. Рисунок [5].

Рис 5. Процесс обучения нейронной сети

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

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

Также, вы можете посмотреть видео, в котором более наглядно показано как работает данная программа.

Саму программу демонстрирующую работу нейронной сети можно скачать здесь.


Комментарии (0):

Добавить комментарий:

Имя:

email:

Защита от спама:

Введите число, изображенное на картинке:

Текст комментария:

AlexeySpace.Ru
(c) alex_ey (Alexey Sokolov)
2010 - 2024
alex_ey@mail.ru