Должен заметить, что по большому счёту, этот пост служит напоминанием для меня самого, но может оказаться интересным и для других. Пришло время познать мир искусственного разума. Как громко это звучит! На самом деле, речь пойдёт всего лишь об очень грубой аппроксимации биологической нейронной сети. Основной задачей печатаемого является показать читающему, что боятся нейронных сетей и вовсе не стоит. Исторические сводки о победах и фиаско в сфере искусственного интеллекта (ИИ) можно и так найти в Интернете, например тут (раздел «Хронология») да и информации по нейронным сетям вообще очень много. Можно сказать, что даже больше, чем необходимо. Это скорее плохо чем хорошо, потому что разобраться и систематизировать все источники порой сложно. Поэтому, информация представленная здесь это не что иное, как вводная, которая позволит довольно просто создать свою нейронную сеть и обучить её.
Если вкратце, то нейронные сети возникли как следствие попытки понять, разобраться и описать мозг биологического организма. Иными словами это результат попытки воссоздать мозг живого существа с помощью электроники (пока что только с её помощью). Повторить один-в-один даже мозг кальмара нынче составляет очень большую, пока неразрешимую задачу. Перетерпев несколько поражений в познании ИИ учёные не остановились и продолжили использовать архитектуру мозга в полезных целях и не прогадали. Нейронные сети, в ряде случаев, могут быть очень полезными. Это задачи распознавания, аппроксимации, генерации…

В очередной раз разбираясь с нейронными сетями (дальше НС) я понял, что учиться лучше разрабатывая. Поэтому, решил написать простенький, но вполне рабочий фреймворк по нейронным сетям. Ко всему прочему сие произведение обладает 2мя полезными качествами:

  • простота;
  • возможность создания произвольной архитектуры сети (ведь из простых решений для быстрого старта в Интернете встречались только «захардкоженые» версии).

Постараюсь в нескольких словах описать, что же такое нейрон — составную часть нейронной сети. Рассмотрим пример. Представьте чёрную коробку с одним входом и одним выходом. На входах и выходах коробки будут числа от 0 до 1.
Например,

Вход    Выход
0         1
1         0

 

Т. е. когда подали на вход 0 — получили 1 и когда подали 0 — получили 1. Именно так и работает логический элемент под названием «НЕ».
Теперь предположим, что мы захотели, чтобы чёрная коробка работала по другому, например, так:

 

Вход    Выход
0         0
1         1

 

В данном случае это простой повторитель входного сигнала.

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

 

Вход    Выход
0         1
1         0

 

достаточно следующего архитектурного решения:

Formula 1

Т.е., математически это виглядит так:

Out = sigmoid(In\cdot(-8.216) + 4.0038),

где

sigmoid(x) = \frac{1}{1 + e^{-x}}.

Следовательно:

Out = \frac{1}{1 + e^{-(In\cdot(-8.216) + 4.0038)}}.

Если In=0:

\frac{1}{1 + e^{-(0\cdot(-8.216) + 4.0038)}} = 0.98208 \approx 1.

Если In=1:

 \frac{1}{1 + e^{-(1\cdot(-8.216) + 4.0038)}} = 0.014597 \approx 0.

Для случая повторителя:

 

Вход    Выход
0         0
1         1

Formula 2

 

Если In=0:

\frac{1}{1 + e^{-(0\cdot(8.2142)  - 4.0029)}} = 0.0179 \approx 0

Если In=1:

\frac{1}{1 + e^{-(1\cdot(8.2142)  - 4.0029)}} = 0.985 \approx 1.

Итого, имеем одну и ту же архитектуру, но разный функционал. Без преувеличения данный подход можно назвать перепрограммируемым. В чем же отличие между решениями? Как можно заметить, разница только в 2 числах по левую сторону от прямоугольника. Описанная в этом примере архитектура и есть так называемый нейрон — составная ячейка более сложной нейронной сети. Стоит также заметить, что на выходе была использована функция сигмоиды. Это так называемая функция активации. Также, в качестве функции активации возможно использовать и другие функции, но сие действие не входит в число проделываемых мною в рамках данной статьи.

Всё это хорошо, но вот наверняка читатель заметил, что числа по левую сторону от нейрона магически взяты как бы «из потолка». В действительности, этим рассуждением мы вплотную подобрались к процессу обучения нейронных сетей. Обучением нейросети есть не что иное как подбор коэффициентов для нейронов. Есть множество способов обучить нейросеть, но наиболее часто используемым является способ обратного распространения ошибки. То, как происходит обучение нейронной сети с помощью метода обратного распространения доходчиво расписано по следующему адресу. Руководствуясь данной статей я написал простенький фреймворк. В результате, получено 2 файла:

  • файл фреймворка (размером меньше чем 300 строк кода);
  • файл с примерами использования (файл размером меньше 200 строк кода).

Результатом делюсь с вами.

Скачать исходный код

И ещё! Для чего же вообще тогда нужны нейронные сети, если описанный пример можно реализовать не прибегая к их помощи? Ответ следующий. Нейронную сеть можно обучить фиксированным набором данных, но если даже после обучения, попросить НС дать ответ на входные данные, которые не были использованы в процессе обучения, то сеть выдаст предполагаемый ответ — спрогнозирует, либо аппроксимирует его. Может и ошибиться, если недостаточно обучена. Это всё равно, что показать ребёнку несколько разных яблок красного цвета, а потом взять яблоко зелёного цвета и показать его ребёнку спросив, что это.

P.S. В следующей статье, для тех, кто не осилит мой пример, покажу как им пользоваться :).