Время прочтения: 8 мин.

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

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

Нейронные сети состоят из:

  • входного слоя I (input)
  • произвольного количества скрытых слоев H (hidden)
  • выходного слоя O (output)
  • набора весов W (weight) и смещений B (bias) между каждым слоем
  • функции активации f для каждого из скрытых слоев

У каждого из нейронов есть 2 основных параметра: входные данные (input data) и выходные данные (output data). В случае входного нейрона эти параметры равны, а в остальных случаях, в поле input попадает суммарная информация всех нейронов с предыдущего слоя, после чего, она нормализуется относительно функции активации и результат подает output.

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

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

Для наилучшего понимания давайте разберем это на примере. Скажем у нас есть искусственный нейрон с двумя входными данными I1 = 2, I2 = 1. В нейроне происходят три вещи.

  1. Каждый вход умножается на вес и в нашем случае пусть веса будут следующими W1 = 4, W2 = 3:

I1 = I1 * W1 = 2 * 4 = 8

I2 = I2 * W2 = 1 * 3 = 3

  • Полученные результаты складываем со смещением B (Скажем B = –9):

(I1 * W1)+ (I2 * W2) + B = 8 + 3 – 9 = 2

  • Данную сумму мы передаем через функцию активации:

O = f (I1 * W1)+ (I2 * W2) + B = f(2)

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

Теперь, когда у нас есть входные данные, мы можем получить выходные данные, подставив входное значение в функцию активации. И в итоге мы получаем что f(2) = 0,87 и так, мы повторяем для всех слоев, пока не дойдем до выходного нейрона. А весь этот процесс получения из входных данных результат называется прямым распространением.

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

Попробуем на практике реализовать работу одного нейрона в рамках задачи Классификации – распределения данных по заданным параметрам.

Практика

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

В качестве параметров мы рассмотрим:

  • размер компании (маленькая (0), средняя (0.5), крупная (1));
  • уже существующую кредитную историю (1 – отличная, 0 – нет кредитной истории, -1 – еще те плохиши);
  • рейтинг 1-10 (чем меньше, тем лучше);
  • срок ведения деятельности (больше или меньше года).

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

Кредитная историяРазмер компанииСрок ведения деятельностиРейтингСпецпредложение
-1 0 1 1 Нет
-1 0.5 0 2 Нет
-1 1 1 5 Нет
0 0 0 7 Нет
0 0 1 8 Нет
0 0.5 1 10 Да
0 0.5 0 4 Нет
0 0.5 1 3 Да
0 1 1 8 Нет
0 1 1 1 Да
0 1 1 4 Да
1 0 0 3 Нет
1 0.5 0 8 Нет
1 0.5 1 1 Да
1 1 0 4 Да
1 1 1 3 Да

Реализуем на python’e:

Вы спросите, что такое np? Да-да, держите:

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

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

Определим функцию активации (сигмоиду) и ее производную:

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

Ах, да. Забыл еще рассказать, что такое эпоха. Эпоха это один переход туда (прямое распространение) и обратно (обратное распространение). Вот собственно то, как происходит прямое и обратное распространение, да и сама тренировка:

Вот такие изменения весов после тренировки мы получили (не забывайте, что первоначальные веса случайны):

Теперь проверим то, что мы получили на новых данных, которые не использовались во время тренировки.

Скажу заранее, что мы получим какие-то значения от 0 до 1 (спасибо сигмоиде). Попробуем условно сказать, что они означают:

Собственно, вот что мы получили:

Хочу также показать Вам график зависимости ошибки от эпохи (для этого мы ошибки и логировали):

Из графика видно, что чем больше будет количество эпох, тем меньше будет ошибка. А вот что будет с результатом и графиком, если во время тренировки будет всего 100 эпох:

А что если тренировочные данные будут недобросовестными, скомпрометированными или вообще они сделаны наугад без какой-либо логики? А вот что:

И график будет выглядеть так:

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

Заключение

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

P.S.: Если Вы заинтересованы в теме нейросетей или у Вас есть замечания/пожелания/советы, то оставляйте обратную связь в комментариях.