Нейронные сети
May 17, 2021

Нейронные сети простым языком. Часть 3. Обучение.

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

Сейчас вы узнаете как же обучить нейронную сеть, а так же рассмотрим примеры реализации.

Что такое обратное распространение?

Метод обратного распространения ошибки (backward propagation) – это метод вычисления градиента, который используется при обновлении весов в нейронной сети. Суть метода в том, чтобы распространять ошибку в обратном порядке.

Обратного распространение

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

random.seed()

Генерация случайных чисел не является «случайной». random выдает не случайное число, а число которое вычисляется алгоритмом на основе другого числа, по умолчанию это текущее время. random.seed() позволяет изменить число, которое передается в random для генерации случайного числа, а т.к. "случайные" числа выдаются одним и тем же алгоритмом, то при одинаковом параметре в random.seed() будут и одинаковые "случайные" числа.

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

Что такое гиперпараметры?

Гиперпараметр модели – это конфигурация, внешняя по отношению к модели.

К гиперпараметрам относятся: количество нейронов в слое, шаг обучения, количество итераций, а так же наличие/отсутствие нейронов отклонения.

Почему веса должны быть инициализированы случайным образом?

Приведу аналогию.

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

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

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

Вот что подразумевается под нарушением симметрии. Инициализация асимметрична, поэтому вы можете найти разные решения одной и той же проблемы.

Что такое градиентный спуск?

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

Градиентный спуск

Что такое среднеквадратичная ошибка?

Среднеквадратичная ошибка (Mean Squared Error) – это функция потери. Чтобы рассчитать MSE, вы берете разницу между предсказаниями вашей модели и основополагающей правдой, вычеркиваете ее и затем усредняете по всему набору данных.
Результат всегда положительный, независимо от знака предсказанных и основанных значений истинности, и идеальное значение равно 0.

Формула для вычисления ошибки сети

Что такое итерация?

Итерация сравнима с шагом в цикле. Одна итерация равна одной пройденной эпохе.

Что такое эпоха?

Эпоха - это вся пройденная выборка (набор данных).

Транспонирование

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

Конкретно в реализации метода обратного распространения на NumPy транспонирование нужно для получения доступа к данным, т. к. в обычном виде функция dot() не сможет произвести произведение матриц параметров.

Недостатки метода

Паралич сети

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

Локальные минимумы

Метод градиентного спуска может застрять в локальном минимуме, так и не попав в глобальный минимум

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

Размер шага

Если размер шага фиксирован и очень мал, то сходимость слишком медленная, если же он фиксирован и слишком велик, то может возникнуть паралич или постоянная неустойчивость. Эффективно увеличивать шаг до тех пор, пока не прекратится улучшение оценки в данном направлении антиградиента и уменьшать, если такого улучшения не происходит.

Переобучение

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

Реализация на Python

Для начала рассмотрим пошаговую реализацию для понимания алгоритма. Будем использовать сеть приведенную в прошлой статье.

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

Создаем класс нейронной сети и инициализируем параметры.

Вычисляем нейроны скрытого слоя, а так же их активацию.

Вычисляем выходной нейрон нейросети.

Вычисляем ошибку и дельты выходного и скрытых нейронов.

Вычисляем значения обновления весов.

Обновляем веса.

Обновляем нейроны отклонения.

Создадим объект класса для тренировки сети.

Набор данных.

Тренируем нейронную сеть.

Сделаем небольшую функцию для просмотра конечного результата сети.

Результат.

Рассмотрим реализацию на NumPy

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

Создаем класс нейронной сети и инициализируем параметры.

Производим прямое распространение (вычисляем предсказание сети).

Вычисляем ошибку и дельты выходного и скрытых нейронов.

*.T - транспонирование в NumPy.

Вычисляем значения обновления весов.

Обновляем веса.

Создадим объект класса для тренировки сети.

Набор данных.

Тренируем нейронную сеть.

Результат.

С нейроном отклонения

Нейрон смещения обычно добавляется к каждому слою, кроме входного.

Реализация на Python

Для начала рассмотрим пошаговую реализацию для понимания алгоритма. Будем использовать сеть приведенную выше.

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

Теперь инициализируем параметры.

Вычисляем нейроны скрытого слоя.

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

Ответ сети: 0.7075

Этот метод не совсем корректен, так как при большом количестве параметров сети, код будет просто огромным, да и сам Python считается достаточно медленным, поэтому реализуем все на NumPy.

Что такое NumPy?

NumPy - это библиотека с открытым исходным кодом для языка программирования Python. Поддерживает многомерные массивы; высокоуровневые математических функций, предназначенных для работы с многомерными массивами и т. д.

Импортируем нужные нам функции, а так же создадим функцию сигмоиды.

Инициализируем параметры случайным образом.

random.randn(2, 2) - создает 2 ячейки по 2 случайных значения

random.randn(2, 1) - создает 1 ячейку по 2 случайных значения

В данном случае массивы с весами инициализируются таким образом - кол. нейронов входного слоя -> кол. нейронов скрытого слоя, кол. нейронов скрытого слоя -> кол. нейронов выходного слоя.

Вычисляем скрытый слой.

Вычисляем выходной слой.

Сгенерированные параметры:

weights_1 = [[1.76, 0.40], [0.99, 2.24]]
weights_2 = [[ 1.87], [-0.98]]
bias1 = 0.95

bias2 = -0.15

Ответ сети: 0.6951

Что такое dot() в NumPy?

Функция dot() выполняет произведение матриц. В нашем случае это требуется для вычисления слоев.

Что такое random.seed() для чего нужна эта функция, узнаете в следующей статье.

В следующей статье рассмотрим как обучить нейронную сеть.

Ссылки

https://ru.wikipedia.org/wiki/Метод_обратного_распространения_ошибки

https://qna.habr.com/q/422558

https://coderoad.ru/20027598/Почему-веса-нейронных-сетей-должны-быть-инициализированными-случайными-числами

https://neurohive.io/ru/osnovy-data-science/gradient-descent/

https://www.machinelearningmastery.ru/importance-of-loss-function-in-machine-learning-eddaaec69519/