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

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

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

Параметр. Параметры модели машинного обучения — это веса и смещения, которые изменяются по мере выполнения итерации. Как правило, нашим параметрам назначаются случайным образом значения, которые изменяются по мере повторения нашей модели, и эти параметры корректируются для создания все более и более точной модели. Некоторыми примерами параметров являются коэффициенты уравнения вашей модели (например, значения m и b в нашей модели линейной регрессии), а также веса и смещения в нейронных сетях.

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

Скорость обучения.Скорость обучения вашей модели — это значение, которое вы ей присваиваете и которое показывает, насколько ваша модель корректирует свои параметры во время своих итераций, обычно от 0 до 1. Слишком высокая скорость обучения приведет к ваша модель будет постоянно пропускать оптимальную точку, тогда как при слишком низкой скорости обучения потребуется бессчетное количество итераций, чтобы достичь оптимальной точки.

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

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

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

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

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

Данные проверки и тестирования.Проверочный набор представляет собой небольшую стопку, которая используется для проверки того, насколько хорошо работают наши гиперпараметры, и дает нам оценку того, насколько хорошо будет работать наша модель. Набор проверки также помогает нам определить, не перетренирована ли обученная модель на обучающих примерах. Затем наши тестовые данные подвергаются реальной проверке на нашей модели, как только она будет готова. Данные тестирования будут фактическими данными, которые мы используем для отчета о производительности наших моделей, и мы будем использовать гораздо меньше данных, чем мы использовали для нашего обучающего набора (обычно рекомендуется, чтобы около 80% ваших данных использовались для обучения и остальное для проверки и тестирования).

Градиент.Градиент — самая важная часть нашей модели: это значение, которое говорит нам, как нам нужно изменить наши параметры. Обычно мы находим это значение, устанавливая производную нашей функции потерь равной 0, потому что, когда наша производная равна 0, это означает, что мы достигли локального оптимума. Подумайте об этом так: если производная нашей функции представляет собой наклон в определенной точке, а наклон в этой точке равен 0, то это означает, что наши потери находятся в относительно низкой точке, что хорошо, потому что это означает, что наша модель является более точным.

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

Самый простой способ обновить веса использует уравнение:

Это уравнение в основном берет наши веса и вычитает градиент, умноженный на скорость обучения. Однако более сложные оптимизаторы, такие как Adam и Adagrad, дополняют это уравнение.

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

Наиболее распространенными функциями активации являются Sigmoid, ReLU, TanH и LeakyReLU. Кратко пробежимся по ним всем:

Сигмоид

Сигмовидная функция вставляет входные данные в уравнение, указанное выше, и ограничивает значение между 0 и 1. Из-за формы сигмовидного графика мы можем видеть, что мы нарушаем эту линейную форму и вводим более гибкий алгоритм для наших данных. Однако сигмовидная функция делает большинство отрицательных значений близкими к 0, что может быть плохо для нашей модели.

ТанХ

Функция TanH довольно похожа на сигмовидную функцию, за исключением того, что она ограничивает наши значения между -1 и 1, что частично решает нашу проблему с нашими отрицательными значениями. Мы также используем немного другое уравнение:

РеЛУ

Функция ReLU, или Rectified Linear Unit, — это функция, которая связывает все отрицательные значения с 0, но позволяет нашим положительным значениям работать свободно. Хотя у него нет конкретного уравнения, формула обычно представляет собой некоторое значение, умноженное на x, если x > 0. ReLU довольно прост по сравнению с сигмовидной функцией и функцией TanH, но у нас снова возникает та же проблема, когда наши отрицательные значения застрял на 0. LeakyReLU - возможное решение этой проблемы.

LeakyReLU

Функция LeakyReLU очень похожа на функцию ReLU, за исключением того, что теперь мы добавляем «утечку», чтобы позаботиться об отрицательных значениях. Мы немного ограничиваем утечку, но не привязываем ее к какому-либо конкретному значению.

Итак, теперь давайте посмотрим на нашу модель логистической регрессии. При логистической регрессии у нас нет скрытых слоев, но мы повторяем нашу сеть. Во-первых, наши данные проходят через нашу модель, через входной слой и выходной слой. Затем градиент нашей модели вычисляется после того, как мы проходим через все, и на основе нашего градиента обновляются наши веса. После всего этого мы снова проходим всю последовательность, основываясь на значении эпохи, которое мы даем нашей модели. И это все! Логистическая регрессия — очень простая модель, поскольку архитектура модели довольно проста.

Давайте посмотрим, как теперь работает наш код!

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

Строки 9 и 10 вычисляют наши потери вручную, используя функцию наименьших квадратов, которую мы видели в линейной регрессии, а строки с 12 по 14 делают то же самое, но мы используем функции Torch для вычисления потерь.

Далее мы определим архитектуру нашей модели. Мы определяем ее как последовательную модель всякий раз, когда выполняем задачу регрессии. Кроме того, мы определяем наш входной и выходной слой. В этой модели у нас есть четыре входа и один выход, и, поскольку это линейный слой, все наши входы связаны с нашим выходом. Затем мы добавляем оптимизатор, который представляет собой функцию, которая может помочь улучшить наши веса. Существует множество различных оптимизаторов, но в этом примере мы будем использовать тот, который называется Adagrad. После этого у нас есть цикл for, который в основном представляет собой цикл, проходящий через нашу модель, которую я описал ранее. Мы проходим его пять раз, что является нашим значением эпохи, и вычисляем наши потери. Две самые важные строки нашей модели идут после: loss.backward() и optimizer.step(). Loss.backward() отвечает за расчет нашего градиента, а Optimizer.step() отвечает за обновление наших весов. Затем мы можем распечатать нашу потерю и посмотреть, как работает наша модель.

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

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

И это все! Однако теперь мы можем перейти к многоуровневым персептронам, поскольку персептроны строятся на основе логистической регрессии.

Код очень похож; мы будем использовать все тот же код, пока не перейдем к архитектуре модели:

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

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