Некоторое время назад у меня впервые зародилось желание написать свою нейросеть и поэкспериментировать с ней, с тех пор я собирал попадающуюся мне информацию, но до дела у меня дошли руки только сейчас. Я твердо решил написать свою нейросеть с блекджеком, с разными методами обучения и без сторонних библиотек. Собственно это я и сделал, а так как у меня самого опыта в этом еще не было, я подумал, что это может быть полезно и для других людей, которые хотят в этом разобраться. Хочу сказать, что смысл этой статьи не в самом оптимизированном способе создания нейросетей, а в способе понять, что такое нейросети и наконец перейти к практике. Итак, поехали. Вероятно вы уже множество раз прочитали что‑нибудь подобное, так что постараюсь покороче. Говоря простым языком: нейронная сеть — несколько слоев, состоящих из искусственных нейронов и синапсов, которые их соединяют. Значение нейрона формируется из активированной суммы дочерних нейронов, умноженных на вес их синапсов. Первый (следующий после нулевого) слой формируется из активированных входных данных, тоже умноженных на веса синапсов. Обычно веса синапсов изначально генерируются случайно, а потом корректируются в зависимости от процесса обучения. «Активированное значение» — значение, которое преобразовано с помощью выбранной функции активации. Дело в том, что когда я «твердо решил написать свою нейросеть», я совершенно не подумал о том, какую задачу эта нейросеть будет решать, так что это я решил на ходу: Задумавшись над задачей для нейронной сети, я решил выбрать что‑нибудь подходящее под два критерия: наглядное, чтобы на выходом было какое‑то графическое действие и не очень тяжелое, ибо мой текущий компьютер не справится. После длительного отбора идей, я вспомнил статью про эксперименты над обучением одноклеточных организмов и пришел к выводу, что правильным решением будет создать примитивную нейросеть, которая будет выполнять роль клетки в чашке Петри. Предварительный анализ задачи показал, что логичней будет ограничить поле зрения: я выбрал поле 5 на 5 вокруг клетки. В итоге я решил сделать нейронную сеть, имеющую входной слой в 25 нейрона, скрытый в 16 и выходной слой в 14. Почему именно столько? В конструировании нейросетей нет четких правил, но для нашей задачи больше одного слоя не требуется (вообще эта задача может решаться без скрытых слоев вообще, но тогда у нейросети будут очень примитивные решения) количество нейронов в скрытом слою, принято делать между количеством во входном и выходном, а дальше корректировать, в зависимости от эмпирических данных, так что спустя несколько попыток, я выбрал именно 16. Ещё нужна функция активации, чтобы значение нейрона для удобства варьировалось между -1 и 1. Я выбираю стандартный гиперболический тангенс, который на самом деле является модифицированной экспонентой. Писать я буду на python, хотя принцип остается тем же и для других языков. Обычно для нейронных сетей используют NumPy с его многомерными массивами, но мне показалось, что для первой нейросети это слишком не наглядно, так что, вдохновившись идеей о создании нейросети методами ООП, я решил реализовать ее через классы. Что я имею ввиду? Я создам класс нейросети, а потом уже буду с этим работать. Нейросеть должна содежать форму(кол‑во слоев и нейронов в них) и массив синапсов. Добавляем функцию вывода. Вывод каждого нейрона считается по формуле - (активированная сумма всех нейронов предыдущего слоя умноженных на соответствующие веса): Функция принимает параметр inp –  массив входных значений. Функция возвращает массив значений нейронов. Самая важная функция - обучение обратным распространением ошибки:  На этом сама нейросеть закончена, пора приступать к разработке среды обучения. Подробное описание процесса разработки среды не имеет ценности для темы, так что я просто опишу принцип работы: Изначально создается массив, который является картой среды. Массив изначально состоит из 0.1, а потом каждый ход наполняется 1 и -1 случайным образом. Также создается клетка, которая управляется нейросетью, которой на вход подается массив из значений полей в квадрате 5*5, а на выходе число от 0 до 3, обозначающие ход (0 — шаг вверх, 1 — вниз, 2 — вправо, 3 — влево). Проверяется по одной клетке вокруг клетки и если находится 1 — то по этому направлению применяется положительное подкрепление, а если -1 — то отрицательное. Также я добавил к этому графический интерфейс на tkinter. Таким образом происходит обучение, что наглядно видно на графике, который строится автоматически. График строится на основе значений положительного и отрицательного подкрепления за ход. Рост графика означает преобладание положительного подкрепления над отрицательным.  Гитхаб репозиторий: ссылка Нейронки это круто! Сохраняйте в закладки и поставьте апвоут, пожалуйста, это очень мотивирует. Следующая часть про эволюционный алгоритм уже доступна!  Программист