Как создать нейронную сеть? zhitsoboy.ru

Как создать нейронную сеть?

Машинное зрение на Python. Обучаем нейросеть распознавать цифры

Содержание статьи

Для каждого примера я приведу код на Python 3.7. Ты можешь запустить его и посмотреть, как все это работает. Для запуска примеров потребуется библиотека Tensorflow. Установить ее можно командой pip install tensorflow-gpu , если видеокарта поддерживает CUDA, в противном случае используй команду pip install tensorflow . Вычисления с CUDA в несколько раз быстрее, так что, если твоя видеокарта их поддерживает, это сэкономит немало времени. И не забудь установить наборы данных для обучения сети командой pip install tensorflow-datasets .

Все приведенные в этой статье примеры работают полностью автономно. Это важно, потому что существуют различные онлайн-сервисы AI, например компании Amazon, которые берут оплату за каждый запрос. Создав и обучив собственную нейронную сеть с помощью Python и Tensorflow, ты сможешь использовать ее неограниченно и независимо от какого-либо провайдера.

Как работает нейронная сеть

Как работает один нейрон? Сигналы со входов (1) суммируются (2), причем каждый вход имеет свой «коэффициент передачи» — w . Затем к получившемуся результату применяется «функция активации» (3).

Модель нейрона

Типы этой функции различны, она может быть:

  • прямоугольной (на выходе 0 или 1);
  • линейной;
  • в виде сигмоиды.

Еще в 1943 году Мак-Каллок и Питтс доказали, что сеть из нейронов может выполнять различные операции. Но сначала эту сеть нужно обучить — настроить коэффициенты w каждого нейрона так, чтобы сигнал передавался нужным нам способом. Запрограммировать нейронную сеть и обучить ее с нуля сложно, но, к счастью для нас, все необходимые библиотеки уже написаны. Благодаря компактности языка Python все действия можно запрограммировать в несколько строк кода.

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

Простейшая нейронная сеть

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

Теперь мы готовы создать нейросеть. Благодаря Tensorflow на это понадобится всего лишь четыре строчки кода.

Мы создали модель нейронной сети — класс Sequential — и добавили в нее два слоя: входной и выходной. Такая сеть называется «многослойный перцептрон» (multilayer perceptron), в общем виде она выглядит так.

Сеть multilayer perceptron

В нашем случае сеть имеет два входа (внешний слой), два нейрона во внутреннем слое и один выход.

Можно посмотреть, что у нас получилось:

Параметры сети

Обучение нейросети состоит в нахождении значений параметров этой сети.
Наша сеть имеет девять параметров. Чтобы обучить ее, нам понадобится исходный набор данных, в нашем случае это результаты работы функции XOR .

Функция fit запускает алгоритм обучения, которое у нас будет выполняться тысячу раз, на каждой итерации параметры сети будут корректироваться. Наша сеть небольшая, так что обучение пройдет быстро. После обучения сетью уже можно пользоваться:

Результат соответствует тому, чему сеть обучалась.

Network test:
XOR(0,0): [[0.00741202]]
XOR(0,1): [[0.99845064]]
XOR(1,0): [[0.9984376]]
XOR(1,1): [[0.00741202]]

Мы можем вывести все значения найденных коэффициентов на экран.

W1: [[ 2.8668058 -2.904025 ] [-2.871452 2.9036295]]
b1: [-0.00128211 -0.00191825]
W2: [[3.9633768] [3.9168582]]
b2: [-4.897212]

Внутренняя реализация функции model.predict_proba выглядит примерно так:

Рассмотрим ситуацию, когда на вход сети подали значения [0,1]:

L1 = X1W1 + b1 = [02.8668058 + 1-2.871452 + -0.0012821, 0-2.904025 + 1*2.9036295 + -0.00191825] = [-2.8727343 2.9017112]

Функция активации ReLu (rectified linear unit) — это просто замена отрицательных элементов нулем.

Теперь найденные значения попадают на второй слой.

L2 = X2W2 + b2 = 03.9633768 +2.9017112*3.9633768 + -4.897212 = 6.468379

Наконец, в качестве выхода используется функция Sigmoid , которая приводит значения к диапазону 0. 1:

Мы совершили обычные операции умножения и сложения матриц и получили ответ: XOR(0,1) = 1 .

С этим примером на Python советую поэкспериментировать самостоятельно. Например, ты можешь менять число нейронов во внутреннем слое. Два нейрона, как в нашем случае, — это самый минимум, чтобы сеть работала.

Но алгоритм обучения, который используется в Keras, не идеален: нейросети не всегда удается обучиться за 1000 итераций, и результаты не всегда верны. Так, Keras инициализирует начальные значения случайными величинами, и при каждом запуске результат может отличаться. Моя сеть с двумя нейронами успешно обучалась лишь в 20% случаев. Неправильная работа сети выглядит примерно так:

XOR(0,0): [[0.66549516]]
XOR(0,1): [[0.66549516]]
XOR(1,0): [[0.66549516]]
XOR(1,1): [[0.00174837]]

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

Можно сделать сеть поумнее: использовать четыре нейрона вместо двух, для этого достаточно заменить строчку кода model.add(Dense(2, input_dim=2, activation=’relu’)) на model.add(Dense(4, input_dim=2, activation=’relu’)) . Такая сеть обучается уже в 60% случаев, а сеть из шести нейронов обучается с первого раза с вероятностью 90%.

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

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее

Как создать собственную нейронную сеть с нуля на языке Python

Джеймс Лой, Технологический университет штата Джорджия. Руководство для новичков, после которого вы сможете создать собственную нейронную сеть на Python.

Мотивация: ориентируясь на личный опыт в изучении глубокого обучения, я решил создать нейронную сеть с нуля без сложной учебной библиотеки, такой как, например, TensorFlow. Я считаю, что для начинающего Data Scientist-а важно понимание внутренней структуры нейронной сети.

Эта статья содержит то, что я усвоил, и, надеюсь, она будет полезна и для вас! Другие полезные статьи по теме:

Что такое нейронная сеть?

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

Нейронные сети состоят из следующих компонентов:

  • входной слой, x
  • произвольное количество скрытых слоев
  • выходной слой, ŷ
  • набор весов и смещений между каждым слоем Wи b
  • выбор функции активации для каждого скрытого слоя σ; в этой работе мы будем использовать функцию активации Sigmoid

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

Создание класса Neural Network на Python выглядит просто:

Обучение нейронной сети

Выход ŷ простой двухслойной нейронной сети:

В приведенном выше уравнении, веса W и смещения b являются единственными переменными, которые влияют на выход ŷ.

Читать еще:  Управление опциями загрузки и политики oprom

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

Каждая итерация обучающего процесса состоит из следующих шагов

  • вычисление прогнозируемого выхода ŷ, называемого прямым распространением
  • обновление весов и смещений, называемых обратным распространением

Последовательный график ниже иллюстрирует процесс:

Прямое распространение

Как мы видели на графике выше, прямое распространение — это просто несложное вычисление, а для базовой 2-слойной нейронной сети вывод нейронной сети дается формулой:

Давайте добавим функцию прямого распространения в наш код на Python-е, чтобы сделать это. Заметим, что для простоты, мы предположили, что смещения равны 0.

Однако нужен способ оценить «добротность» наших прогнозов, то есть насколько далеки наши прогнозы). Функция потери как раз позволяет нам сделать это.

Функция потери

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

Сумма квадратов ошибок — это среднее значение разницы между каждым прогнозируемым и фактическим значением.

Цель обучения — найти набор весов и смещений, который минимизирует функцию потери.

Обратное распространение

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

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

Напомним из анализа, что производная функции — это тангенс угла наклона функции.

Если у нас есть производная, то мы можем просто обновить веса и смещения, увеличив/уменьшив их (см. диаграмму выше). Это называется градиентным спуском.

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

Фух! Это было громоздко, но позволило получить то, что нам нужно — производную (наклон) функции потерь по отношению к весам. Теперь мы можем соответствующим образом регулировать веса.

Добавим функцию backpropagation (обратного распространения) в наш код на Python-е:

Проверка работы нейросети

Теперь, когда у нас есть наш полный код на Python-е для выполнения прямого и обратного распространения, давайте рассмотрим нашу нейронную сеть на примере и посмотрим, как это работает.

Идеальный набор весов

Наша нейронная сеть должна изучить идеальный набор весов для представления этой функции.

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

Посмотрим на окончательное предсказание (вывод) из нейронной сети после 1500 итераций.

Мы сделали это! Наш алгоритм прямого и обратного распространения показал успешную работу нейронной сети, а предсказания сходятся на истинных значениях.

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

Финальные размышления

Я многому научился в процессе написания с нуля своей собственной нейронной сети. Хотя библиотеки глубинного обучения, такие как TensorFlow и Keras, допускают создание глубоких сетей без полного понимания внутренней работы нейронной сети, я нахожу, что начинающим Data Scientist-ам полезно получить более глубокое их понимание.

Я инвестировал много своего личного времени в данную работу, и я надеюсь, что она будет полезной для вас!

Как построить свою собственную нейронную сеть с нуля в Python

Опубликовано Шамаев Иван в 11.09.2019 11.09.2019

Руководство для начинающих, чтобы понять внутреннюю работу глубокого обучения

Beginner’s Guide of Deep Learning

Мотивация: как часть моего личного пути, чтобы получить лучшее понимание глубокого обучения, я решил построить нейронную сеть с нуля без библиотеки глубокого обучения, такой как TensorFlow. Я считаю, что понимание внутренней работы нейронной сети важно для любого начинающего специалиста по данным.

Эта статья содержит то, что я узнал, и, надеюсь, это будет полезно и для вас!

Что такое нейронная сеть?

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

Нейронные сети состоят из следующих компонентов

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

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

Архитектура двухслойной нейронной сети

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

Обучение нейронной сети

Выход ŷ простой двухслойной нейронной сети:

Вы можете заметить, что в приведенном выше уравнении весовые коэффициенты W и смещения b являются единственными переменными, которые влияют на результат ŷ.

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

Каждая итерация учебного процесса состоит из следующих шагов:

  • Расчет прогнозируемого выхода known , известный как прямаясвязь
  • Обновление весов и уклонов, известных как обратное распространение

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

прогнозирование

Как мы видели на приведенном выше последовательном графике, прямая связь — это просто простое исчисление, и для базовой двухслойной нейронной сети результат работы нейронной сети:

Давайте добавим функцию обратной связи в наш код Python, чтобы сделать именно это. Обратите внимание, что для простоты мы приняли смещения равными 0.

Однако нам все еще нужен способ оценить «доброту» наших прогнозов (т. Е. Насколько далеки наши прогнозы)? Функция потерь позволяет нам делать именно это.

Функция потери

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

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

Наша цель в обучении — найти лучший набор весов и смещений, который минимизирует функцию потерь.

обратное распространение

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

Чтобы узнать соответствующую сумму, с помощью которой можно корректировать веса и смещения, нам необходимо знать производную функции потерь по весам и смещениям .

Напомним из исчисления, что производная функции — это просто наклон функции.

Алгоритм градиентного спуска

Если у нас есть производная, мы можем просто обновить веса и смещения, увеличивая / уменьшая ее (см. Диаграмму выше). Это известно как градиентный спуск .

Читать еще:  Недостаточно системных ресурсов для завершения операции fortnite

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

Уф! Это было некрасиво, но оно позволяет нам получить то, что нам нужно — производную (наклон) функции потерь по отношению к весам, чтобы мы могли соответствующим образом корректировать веса.

Теперь, когда у нас это есть, давайте добавим функцию обратного распространения в наш код Python.

Для более глубокого понимания применения исчисления и правила цепочки в обратном распространении я настоятельно рекомендую этот урок от 3Blue1Brown.

Собираем все вместе

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

Наша нейронная сеть должна изучить идеальный набор весов для представления этой функции. Обратите внимание, что для нас не совсем просто вычислить вес только одним осмотром.

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

Давайте посмотрим на окончательный прогноз (выход) из нейронной сети после 1500 итераций.

Мы сделали это! Наш алгоритм обратной связи и обратного распространения успешно обучил нейронную сеть, и прогнозы сошлись на истинных значениях.

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

Что дальше?

К счастью для нас, наше путешествие не закончено. Еще многое предстоит узнать о нейронных сетях и глубоком обучении. Например:

  • Какую другую функцию активации мы можем использовать, кроме функции Sigmoid?
  • Использование скорости обучения при обучении нейронной сети
  • Использование сверток для задач классификации изображений

Я скоро напишу больше на эти темы, так что следите за мной на Medium и следите за ними!

Последние мысли

Я, конечно, многому научился писать свою собственную нейронную сеть с нуля.

Хотя библиотеки глубокого обучения, такие как TensorFlow и Keras, позволяют легко создавать глубокие сети без полного понимания внутренней работы нейронной сети, я считаю, что для начинающего ученого-исследователя полезно получить более глубокое понимание нейронных сетей.

Пишем нейросеть прямого распространения с нуля | Как создать свою нейросеть

Время чтения: 8 минут

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

Что такое нейросеть?

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

Более простыми словами, это некий чёрный ящик, который превращает входные данные в выходные, или, говоря более математическим языком, является отображением пространства входных признаков X в пространство выходных признаков Y: X → Y. То есть мы хотим найти какую-то функцию F, которая сможет выполнять это преобразование. Для начала этой информации нам будет достаточно. Для более подробного ознакомления рекомендуем ознакомиться с этой статьёй на хабре.

Коротко об искусственном нейроне

Чаще всего в подобных статьях начинают расписывать про устройство биологического нейрона, связь с его искусственной моделью и прочую лирику. Мы же этого делать не будем, а сразу перейдём к сути. Искусственный нейрон — это всего лишь взвешенная сумма значений входного вектора элементов, которая передаётся на нелинейную функцию активации f: z = f(y), где y = w·x + w1·x1 + . + wm — 1·xm — 1 . Здесь w, . wm — 1 — коэффициенты, веса каждого элемента вектора, x, . xm — 1 — значения входного вектора X, y — взвешенная сумма элементов X, а z — результат применения функции активации. Мы вернёмся к функции активации немного позднее, а пока давайте придумаем, как вместо одного выходного значения получить n.

Нейронный слой

Один нейрон способен входной вектор превратить в одну точку, однако по условию мы хотим получить несколько точек, так как выходной вектор Y может иметь произвольную размерность, определяемую лишь конкретной ситуацией (один выход для XOR, 10 выходов для определения принадлежности к одному из 10 классов и т.д.). Как же нам получить n точек, преобразуя элементы входного вектора X? Оказывается, всё довольно просто: для того, чтобы получить n выходных значений, необходимо использовать не один нейрон, а n. Тогда для каждого из элементов выходного вектора Y будет использовано ровно n различных взвешенных сумм от вектора X. То есть мы получаем, что zi = f(yi) = f(wi0·x + wi1·x1 + . + wim — 1·xm — 1)

Если внимательно посмотреть, то оказывается, что написанная выше формула является определением умножения матрицы на вектор. И действительно, если взять матрицу W размера n на m и умножить её на вектор X размерности m, то получится другой вектор размерности n, то есть ровно то, что нам и нужно. Таким образом, получение выходного вектора по входному для n нейронов можно записать в более удобной матричной форме: Y = W·X , где W — матрица весовых коэффициентов, X — входной вектор и Y — выходной вектор. Однако полученный вектор является неактивированным состоянием (промежуточным, невыходным) всех нейронов, а чтобы получить выходное значение,, необходимо каждое неактивированное значение подать на вход функции активации. Результат её применения и будет выходным значением слоя.

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

Функция активации

Функция активации — это функция, которая добавляет в сеть нелинейность, благодаря чему нейроны могут довольно точно имитировать любую функцию. Наиболее распространёнными функциями активации являются:

  • Сигмоида: f(x) = 1 / (1 + e -x )
  • Гиперболический тангенс: f(x) = tanh(x)
  • ReLU: f(x) = max(x,0)

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

Хватит бла бла, давайте писать код

Теперь нам достаточно знаний, чтобы написать код получения результата нейронной сети. Мы будем писать код на языке C#, однако, уверяем, код будет практически идентичным для других языков программирования. Давайте разберёмся, что нам потребуется для реализации сети прямого распространения:

  1. Вектор (входные, выходные);
  2. Матрица (каждый слой содержит матрицу весовых коэффициентов);
  3. Нейросеть.
  • Вектор можно создавать из количества элементов (длины);
  • Вектор можно создавать из перечисления вещественных чисел;
  • Можно получать значения по индексу i.
  • Можно изменять значения по индексу i.
  • Матрицу можно создавать из числа строк, столбцов и генератора случайных чисел для заполнения случайными значениями;
  • Можно получать значения по индексам i и j;
  • Можно изменять значения по индексам i и j;
Читать еще:  Как очистить оперативную память на телефоне?

3. Сама нейросеть:

Сеть есть, но её ответы случайны. Как обучать?

На данный момент мы имеем случайную (необученную) нейронную сеть, которая может по входному вектору input выдать случайный ответ, однако нам требуется ответы, удовлетворяющие конкретной задаче. Чтобы добиться этого нашу сеть необходимо обучить. Для этого нам необходима база тренировочных примеров, то есть множество пар векторов X — Y, на которых будет обучаться сеть. Обучать нейросеть мы будем с помощью алгоритма обратного распространения ошибки. Если кратко, то он работает следующим образом:

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

Сам же алгоритм обучения выглядит так:

Обучаем нейронную сеть

Для обратного распространения ошибки нам потребуется знать значения входов, выходов и значения производных функции активации сети на каждом из слоёв, поэтому создадим структуру LayerT, в которой будет 3 вектора: x — вход слоя, z — выход слоя, df — производная функции активации. Также для каждого слоя потребуются векторы дельт, поэтому добавим в наш класс ещё и их. С учётом вышесказанного наш класс станет выглядеть так:

Обратное распространение ошибки

Перейдём к обратному распространению ошибки. В качестве функции оценки сети E(W) возьмём среднее квадратичное отклонение: E = 0.5 · Σ(y1i — y2i) 2 . Чтобы найти значение ошибки E, нам нужно найти сумму квадратов разности значений вектора, который выдала сеть в качестве ответа, и вектора, который мы ожидаем увидеть при обучении. Также нам потребуется найти дельту для каждого слоя, причём для последнего слоя она будет равна вектору разности полученного и ожидаемого векторов, умноженному (покомпонентно) на вектор значений производных последнего слоя: δlast = (zlast — d)·f’last , где zlast — выход последнего слоя сети, d — ожидаемый вектор сети, f’last — вектор значений производной функции активации последнего слоя.

Теперь, зная дельту последнего слоя, мы можем найти дельты всех предыдущих слоёв. Для этого нужно умножить транспонированную матрицы текущего слоя на дельту текущего слоя и затем умножить полученный вектор на вектор производных функции активации предыдущего слоя: δk-1 = W T k·δk·f’k .

Что ж, давайте реализуем это в коде:

Изменение весов

Для того, чтобы уменьшить ошибку сети нужно изменить весовые коэффициенты каждого слоя. Как же именно нужно менять весовые коэффициенты матриц на каждом слое? Оказывается, всё довольно просто. Для этого используется метод градиентного спуска, а значит нам необходимо вычислить градиент по весам и сделать шаг в отрицательную сторону от этого градиента. На этапе прямого распространения мы зачем-то запоминали входные сигналы, а при обратном распространении ошибки мы вычисляли дельты в каждом слое. Именно их мы и будем сейчас использовать для нахождения градиента! Градиент по весам равен перемножению входного вектора и вектора дельт (не покомпонентно). Поэтому, чтобы обновить весовые коэффициенты и уменьшить тем самым ошибку сети нужно всего лишь вычесть из матрицы весов результат перемножения дельт и входных векторов, умноженный на скорость обучения. Это можно записать в таком виде: Wt+1 = Wt — η·δ·X , где Wt+1 — новая матрица весов, Wt — текущая матрица весов, X — входное значение слоя, δ — дельта этого слоя. Почему именно так с математической точки зрения хорошо описано в этой статье.

Обучение сети

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

Сеть готова. Давайте же её чему-нибудь научим!

Тренируем нейросеть на функции XOR

Почему функция XOR так интересна? Просто потому, что её невозможно получить одним нейроном: 0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0. Однако она легко получается увеличением числа нейронов. Мы же попробуем выполнить обучение сети с 3 нейронами в скрытом слое и 1 выходным (так как выход у нас всего один). Для этого нам необходимо создать массив векторов X и Y с обучающими данными и саму нейросеть:

После чего запустим обучение со следующими параметрами: скорость обучения — 0.5, число эпох — 100000, величина ошибки — 1e-7:

После обучения посмотрим на результаты выполнив прямой проход для всех элементов:

В результате вывод может быть таким:

Проверять результаты на тренировочной же выборке довольно скучно, ведь как никак на ней мы сеть обучали, но, увы, для XOR проблемы ничего другого не остаётся. В качестве более серьёзного примера рекомендуем выполнить задачу распознавания картинок с рукописными цифрами MNIST. Это база содержит 60000 картинок написанных от руки цифр размером 28 на 28 пикселей и используется как один из основных датасетов для начала изучения машинного обучения. Не смотря на простоту нашей сети, при грамотном выборе параметров (число нейронов, число слоёв, скорость обучения, число эпох. ) можно получить точность распознавания до 98%! Проверить свою сеть вы можете, поучаствовав в соревновании на сайте Kaggle. Нашей команде удалось достичь точности в 98.171%! А вы сможете больше? 🙂

В заключение

Мы написали с вами нейронную сеть прямого распространения и даже обучили её функции XOR. При этом мы позаботились об универсальности, благодаря чему нейросеть может быть обучена на любых данных, главное только подготовить два массива обучающих векторов X и Y, подобрать параметры обучения и запустить само обучение, после чего наблюдать за процессом. Важно помнить, что при использовании сигмоидальной функции активации, выходные значения сети не будут превышать 1, а значит, для обучения данным, которые значительно больше 1 необходимо отнормировать их, то есть привести к отрезку [0, 1].

Программист, сооснователь programforyou.ru, в постоянном поиске новых задач и алгоритмов

Студент МГУ им. М.В. Ломоносова

Программист, соосновательница programforyou.ru, рукодельница, всегда готова придти на помощь и помочь во всём разобраться

Студентка МГТУ им. Н.Э. Баумана

А Вы знаете, что мы пишем программы на C, C++, C#, Pascal и Python?

Так что если Вам нужно написать программу на C/C++, C#, Pascal или Python — мы с радостью поможем с этим!

В том числе мы занимаемся репетиторством по информатике и программированию, а также готовим к ОГЭ и ЕГЭ!

Почему именно мы?

  • Более 1800 выполненных заказов;
  • Более 170 отзывов;
  • Качественное решение
  • Короткие сроки и привлекательные цены
  • Различные акции и скидки

Как с нами связаться?

  • группа Вконтакте: vk.com/programforyou
  • наша почта: order@programforyou.ru

Programforyou — позвольте нам писать код для вас и вы получите качественное решение в короткие сроки по привлекательной цене!

Ссылка на основную публикацию
Adblock
detector