Нейронные сети простым языком. Часть 4. Задачи.
В прошлой статье мы узнали как нейронную сеть, а так же рассмотрели примеры реализации на Python.
В этой статье для большего понимания рассмотрим реальные задачи, а также реализуем их на Python. Весь код приведенный ниже можно найти в моем GitHub.
Светофор
Сфетофор - простая, достаточно популярная задача. Всего 3 входных параметра, значения должны быть либо 0, либо 1. Нейросеть должна найти закономерность - значение по центру и является ответом.
Рассмотрим реализацию на Python. Для начала напишем основной класс, который отвечает за обучение и предсказание.
Импотрируем нужные модули библиотеки NumPy, а так же создадим объект класса для инициализации параметров сети.
Далее создадим функцию активации, в данной задаче будет достаточно сигмоиды.
Создадим объект отвечающий за вычисление предсказания.
Создадим объект отвечающий за корректировку весов.
А так же создадим объект тренировки сети и объект для возможности предсказания после обучения.
Теперь импотрируем написаный нами класс, а так же модуль для создания массива Numpy.
В данном случае, переменная data - это и есть наш набор данных, где первые три колонки это входные данные, а последняя так называемые лэйблы, то есть то что должно получится на выходе. Далее происходит разделение данных и корректное формирование массивов для предотвращения ошибок при вычислении.
Инициализиреум сеть, задаем гиперпараметры, подаем данные для обучения, а так же зададим новый случай.
Результат:
Как видим, ошибка уменьшается, а сеть выдала отличный результат.
Ирисы Фишера
Ирисы Фишера - популярная задача классификации. В данной задаче 4 входных параметра: длина/ширина двух типов лепестков. Суть в том, чтобы нейросеть смогла найти закономерности между данными и определить сорт растения.
Будем использовать тот же класс, но для более точного определения добавим нейроны отклонения.
По скольку набор данных уже в разы больше будет неразумно добавлять его в скрипт. По этому скачиваем датасет и импортируем в скрипте с помощью модуля NumPy - loadtxt. loadtxt загружает файл и разделяет содержимое на указанные значения.
Так же инициализируем сеть, задаем гиперпараметры и загружаем данные.
Результат:
Как видим 500 эпох сети достаточно чтобы обучиться, правильность распознавания - 98%.
Распознавание рукописных цифр
Переходим к самому сложному в данной стетье - распознваванию рукописных цифр. Для этого нам так же понадобится скачать набор рукописных цифр MNIST.
Так же будем использовать написанный ранее класс (с нейронами отклонения), но одной функции активации уже недостаточно, будем использовать софтмакс для вычисления выходного слоя.
Инициализируем сеть, задаем гиперпараметры и загружаем данные.
Так как набор данный большой, 10 эпох будет достаточно. Стоит заметить что установленный шаг ниже чем в предыдущих примерах, это нужно для более лучшего обобщения.
Для проверки выберем случайное значение из набора и подадим сети на вход после обучения.
Результат:
Как видим все работает, ошибка уменьшается - правильность растет, случайное значение из набора успешно распознано.
Стоит отметить что это не идеальная реализация, так как существуют различные варианты оптимизаторов, функций вычисления ошибки и т. д. Разделение пакетов используют по разному, а могут вообще и не использовать (в зависимости от набора данных), кроме этого, зачастую требуется перемещивать данные во избежание проблем обобщения сети. Так же данная реализация довольно медленная, т. к. для повышения скорости обучения обычно используют распараллеливание и мультипроцессорность (+GPU), а прописывать это вручную достаточно проблематично.