Содержание[Скрывать][Показывать]
Мозг можно сравнить с нейронными сетями. Это аналогия, которая обычно используется, чтобы помочь новичку понять идеи, лежащие в основе машинного обучения и искусственных нейронных сетей.
Поскольку за кулисами происходит несколько уровней математических и статистических вычислений, определение этих сетей как математической функции является более продвинутым методом.
Это для людей, которые действительно интересуются машинным обучением и хотят увидеть, как пишется код нейронной сети Python.
В этой статье мы покажем, как построить полносвязную глубокую нейронную сеть (DNN) с нуля в Питон 3.
Обзор файловой структуры для нашего кода нейронной сети Python
Здесь будут созданы три файла. Первый — это простой файл nn.py, который будет обсуждаться в разделах «Настройка вспомогательных функций» и «Создание нейронной сети с нуля».
У нас также будет файл с именем mnist loader.py для загрузки тестовых данных, как описано в разделе «Загрузка данных MNIST».
Наконец, у нас будет файл с именем test.py, который будет запущен в терминале для тестирования нашей нейронной сети.
Этот файл подробно описан в разделе «Выполнение тестов».
Установка
Библиотека Python NumPy должна быть загружена, чтобы следовать этому руководству. Вы можете сделать это, используя следующую команду в терминале:
Импорт модулей и настройка вспомогательной функции
Нам нужны только две библиотеки — random и NumPy, которые мы сразу же импортируем. Для начальных весов нашей нейронной сети мы будем перемешивать их с помощью случайной библиотеки.
Чтобы ускорить наши вычисления, мы будем использовать NumPy или np (по соглашению он часто импортируется как np). Две наши вспомогательные функции будут созданы после импорта. Две сигмовидные функции: единица и сигмовидная простая.
Логистическая регрессия будет классифицировать данные с помощью сигмовидной функции, а обратное распространение вычислит дельту или градиент с помощью сигмовидной простой функции.
Создание сетевого класса
Создание полностью связанной нейронной сети — единственная цель этого раздела. Класс сети будет охватывать все последующие функции. Функция Object() { [собственный код] } будет изначально создана в нашем сетевом классе.
Один аргумент, размеры, требуется функции Object() { [собственный код] }. Переменная размеров представляет собой набор числовых значений, представляющих количество входных узлов, присутствующих в каждом слое нашей нейронной сети.
Мы инициализируем четыре свойства в нашем методе __init__. Входные переменные, размеры, используются для установки списка размеров слоев и количества слоев, numlayers, соответственно.
Первый шаг — случайным образом назначить начальные смещения нашей сети каждому слою, следующему за входным слоем.
Наконец, каждая ссылка между входным и выходным слоями имеет свой вес, сгенерированный случайным образом. Np.Random.Randn() дает случайную выборку из нормального распределения для контекста.
Функция прямой связи
В нейронной сети информация отправляется функцией прямой связи. Этой функции потребуется один аргумент a, указывающий текущий вектор активации.
Эта функция оценивает активации на каждом уровне путем перебора всех смещений и весов в сети. Данным ответом является предсказание, то есть активация последнего слоя.
Мини-пакетный градиентный спуск
Рабочая лошадка нашего сетевого класса — Gradient Descent. В этой версии мы используем мини-пакетный (стохастический) градиентный спуск, модифицированный вариант градиентного спуска.
Это указывает на то, что для обновления нашей модели будет использоваться небольшой набор точек данных. В этот метод передаются четыре обязательных и один необязательный аргумент. Четыре обязательных переменных — это набор обучающих данных, количество эпох, размер мини-пакетов и скорость обучения (эта).
Данные испытаний доступны по запросу. Мы предоставим тестовые данные, когда в конечном итоге оценим эту сеть. Количество выборок в этой функции изначально устанавливается равным длине списка после того, как обучающие данные были преобразованы в тип списка.
Мы также применяем тот же процесс для проверки данных, которые приведены. Это потому, что вместо того, чтобы возвращаться к нам в виде списков, они на самом деле являются почтовыми индексами списков. Когда мы позже загрузим образцы данных MNIST, мы узнаем об этом больше.
Если мы можем быть уверены, что предоставляем оба типа данных в виде списков, то это приведение типов не обязательно необходимо.
Когда у нас есть данные, мы циклически проходим через эпохи обучения. Период обучения — это только один раунд обучения нейронной сети. Сначала мы перемешиваем данные в каждой эпохе, чтобы обеспечить случайность, прежде чем составлять список мини-пакетов.
Функция обновления мини-пакета, которая обсуждается ниже, будет вызываться для каждого мини-пакета. Точность теста также будет возвращена, если данные теста доступны.
Вспомогательная функция производной стоимости
Давайте сначала разработаем вспомогательную функцию, называемую производной стоимости, прежде чем мы действительно создадим код обратного распространения. Если мы допустим ошибку в нашем выходном слое, функция производной стоимости покажет это.
Для этого требуется два входа: массив выходных активаций и координаты y ожидаемых выходных значений.
Функция обратного распространения
Наш нынешний вектор активации, активация, а также любые другие векторы активации, активации и z-векторы, zs, все должны быть учтены. Сначала активируется слой, называемый входным слоем.
Мы пройдемся по каждому смещению и весу после их установки. Каждый цикл включает в себя вычисление вектора z как скалярного произведения весов и активации, добавление его в список z, пересчет активации и добавление обновленной активации в список активаций.
Наконец, математика. Дельта, равная ошибке предыдущего слоя, умноженной на сигмовидное простое число последнего элемента векторов zs, вычисляется до того, как мы начнем наш обратный проход.
Последний слой набла b установлен как дельта, а последний слой набла w установлен как скалярное произведение дельты и предпоследнего слоя активаций (транспонированных, чтобы мы могли фактически выполнить математику) .
Мы действуем, как и раньше, начиная со второго слоя и заканчивая последним, и повторяем процесс после завершения этих последних слоев. Затем наблы возвращаются в виде кортежа.
Обновление мини-пакетного градиентного спуска
Наш метод SGD (стохастический градиентный спуск) ранее включал мини-пакетное обновление. Поскольку она используется в SGD, но также требует обратного распространения, я долго спорил, куда поместить эту функцию.
Наконец, я решился опубликовать это здесь. Он начинается с генерации 0 векторов набла смещений и весов, точно так же, как это делала наша функция обратного распространения.
В качестве двух входных данных требуется мини-пакет и скорость обучения эта. Затем в мини-пакете мы используем функцию обратного распространения, чтобы получить дельту каждого массива набла для каждого входа x и выхода y. Затем списки набла обновляются этими дельтами.
Наконец, мы используем скорость обучения и наблас для обновления весов и смещений сети. Каждое значение обновляется до самого последнего значения за вычетом скорости обучения, умножается на размер мини-пакета, а затем добавляется к значению набла.
Оценить функцию
Функция оценки — последняя, которую нам нужно написать. Тестовые данные являются единственным входом для этой функции. В этой функции мы сравниваем только выходные данные сети с ожидаемым результатом y. Путем подачи на вход x вперед определяются выходы сети.
Полный код
Когда мы объединяем весь код, он выглядит так.
Тестирование нейронной сети
Загрузка данных MNIST
Ассоциация Данные MNIST находится в формате .pkl.gz, который мы откроем с помощью GZIP и загрузим с помощью pickle. Давайте напишем быстрый метод для загрузки этих данных в виде кортежа размера три, разделенного на обучающие, проверочные и тестовые данные.
Чтобы упростить управление нашими данными, мы напишем еще одну функцию для кодирования y в массив из 10 элементов. В массиве будут все 0, кроме 1, соответствующей правильной цифре изображения.
Мы будем использовать базовые данные загрузки и один метод горячего кодирования, чтобы загрузить наши данные в читаемый формат. Будет написана еще одна функция, которая преобразует наши значения x в список размером 784, соответствующий 784 пикселям изображения, и наши значения y в их единую векторную форму горячего кодирования.
Затем мы объединим значения x и y так, чтобы один индекс соответствовал другому. Это относится к наборам данных для обучения, проверки и тестирования. Затем мы возвращаем измененные данные.
Запуск тестов
Мы создадим новый файл под названием «загрузчик mnist», который будет импортировать как нейронную сеть, которую мы установили ранее (простой nn), так и загрузчик набора данных MNIST, прежде чем мы начнем тестирование.
В этом файле все, что нам нужно сделать, это импортировать данные, построить сеть с размером входного слоя 784 и размером выходного слоя 10, запустить функцию SGD сети на обучающих данных, а затем протестировать ее, используя тестовые данные.
Имейте в виду, что для нашего списка входных слоев не имеет значения, какие числа находятся между 784 и 10. Мы можем изменить другие слои как угодно; только размеры ввода и вывода фиксированы.
Три слоя не нужны; мы могли бы использовать четыре, пять или даже два. Получайте удовольствие, экспериментируя с ним.
Заключение
Здесь с помощью Python 3 мы создаем нейронную сеть с нуля. Наряду с математикой высокого уровня мы также обсудили особенности реализации.
Мы начали с реализации вспомогательных функций. Для работы нейронов решающее значение имеют сигмовидная и сигмовидная простые функции. Затем мы применяем на практике функцию прямой связи, которая является фундаментальным процессом для подачи данных в нейронную сеть.
Затем мы создали функцию градиентного спуска в Python, механизм, который управляет нашей нейронной сетью. Чтобы найти «локальные минимумы» и оптимизировать их веса и смещения, наша нейронная сеть использует градиентный спуск. Мы создали функцию обратного распространения, используя градиентный спуск.
Предоставляя обновления, когда выходные данные не соответствуют правильным меткам, эта функция позволяет нейронной сети «обучаться».
Наконец, мы помещаем наш совершенно новый Python нейронной сети к тесту с использованием набора данных MNIST. Все функционировало гладко.
Удачного кодирования!
Оставьте комментарий