Sgd нейронные сети и 1.5. Стохастический градиентный спуск

Введение

В этом документе продолжается обсуждение многомерной линейной модели.
На её примере мы рассмотрим метод стохастического градиентного спуска и выбор оптимальных гиперпараметров.
Приведеный код на Python
с использованием библиотек Numpy, PyTorch и Keras,
можно найти в файле: ML_Line_Model.ipynb.

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

Больше контроля с warm_start

Если вы хотите получить больше контроля над критериев остановки или скорости обучения в СГД, или хотите сделать дополнительный мониторинг, используя warm_start=True и max_iter=1 и переборе сами могут быть полезны:

Советы по практическому использованию

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train) # Don’t cheat – fit only on training data
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test) # apply same transformation to test data

# Or better yet: use a pipeline!
from sklearn.pipeline import make_pipeline
est = make_pipeline(StandardScaler(), SGDClassifier())
est.fit(X_train)
est.predict(X_test)

Если ваши атрибуты имеют внутреннюю шкалу (например, частота слов или особенности индикатора), масштабирование не требуется.

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

Читайте также  Достигайте совершенства в кинопроизводстве вместе с талантливой командой ВКонтакте

SGD успешно применяется для решения крупномасштабных и разреженных задач машинного обучения, часто встречающихся при классификации текста и обработке естественного языка. Учитывая, что данные немногочисленны, классификаторы в этом модуле легко масштабируются для решения задач с более чем $10^5$ обучающими примерами и более чем $10^5$ функциями.

Строго говоря, SGD — это просто метод оптимизации и не соответствует конкретному семейству моделей машинного обучения. Это всего лишь способ обучить модель. Часто экземпляр SGDClassifier или SGDRegressor будет иметь эквивалентный оценщик в scikit-learn API, потенциально используя другой метод оптимизации. Например, использование SGDClassifier(loss=’log’) результатов в логистической регрессии, т. Е. Модель, эквивалент LogisticRegression которой подбирается через SGD, а не подгоняется одним из других решателей в LogisticRegression. Точно так же SGDRegressor(loss=’squared_loss’, penalty=’l2′) и Ridge решают одну и ту же задачу оптимизации разными способами.

Преимущества стохастического градиентного спуска:

К недостаткам стохастического градиентного спуска можно отнести:

Убедитесь, что вы переставляете (перемешиваете) свои обучающие данные перед подгонкой модели или используете shuffle=Trueдля перемешивания после каждой итерации (используется по умолчанию). Кроме того, в идеале функции должны быть стандартизированы, например, с помощью make_pipeline(StandardScaler(), SGDClassifier()) (см. « Конвейеры» ).

Численный поиск минимума

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

Обратим внимание, что обучающие
примеры перед началом каждой эпохи случайно перемешиваются.
Для этого, при помощи функции np.random.permutation
создаётся перемешенный список целых чисел о 0 до len(X)-1.
Следующая строчка собственно производит перемешивание. Перемешивать данные перед каждой эпохой
в принципе не обязательно, но если данных немного это может улучшить сходимость к минимуму.
Кроме этого, если число примеров N нацело не делятся на batch_size,
не все данные попадут в вычисление градиента. Перемешивание ослабляет эту проблему.

Справа приведены графики ошибки при различных скоростях обучения и mo=0.
Критическое значение lr находится в районе 1.75.
При приближении к этому значению скорость обучения заметно возрастает.

Математическая постановка

Мы описываем здесь математические детали процедуры SGD. Хороший обзор показателей сходимости можно найти в 12 .

Различные варианты для $L$ влекут за собой разные классификаторы или регрессоры:

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

Популярные варианты срока регуляризации $R$ ( penalty параметр) включают:

На рисунке ниже показаны контуры различных членов регуляризации в двумерном пространстве параметров ($m=2$) когда $R(w) = 1$.

SGD

Стохастический градиентный спуск — это метод оптимизации для задач безусловной оптимизации. В отличие от (пакетного) градиентного спуска, SGD аппроксимирует истинный градиент $E(w,b)$ рассматривая один обучающий пример за раз.

где η- это скорость обучения, которая контролирует размер шага в пространстве параметров. Перехватbобновляется аналогично, но без регуляризации (и с дополнительным распадом для разреженных матриц, как подробно описано в деталях реализации ).

где $t$ шаг по времени (всего шагов по времени n_samples * n_iter), $t_0$ определяется на основе эвристики, предложенной Леоном Ботту, так что ожидаемые начальные обновления сопоставимы с ожидаемым размером весов (это предполагает, что норма обучающих выборок составляет приблизительно 1). Точное определение можно найти _init_t в BaseSGD.

где $eta_0$ а также $power_t$- гиперпараметры, выбираемые пользователем с помощью eta0 и power_t, соответственно.

Для постоянной скорости обучения используйте learning_rate=’constant’ и используйте, eta0 чтобы указать скорость обучения.

Для адаптивного уменьшения скорости обучения используйте learning_rate=’adaptive’ и используйте eta0, чтобы указать начальную скорость обучения. Когда критерий остановки достигнут, скорость обучения делится на 5, и алгоритм не останавливается. Алгоритм останавливается, когда скорость обучения опускается ниже 1e-6.

Параметры модели могут быть доступны через coef_ и intercept_ атрибуты: coef_ держат весыwи intercept_ держит $b$.

Вычисление градиента

В матричном виде это можно записать так:

Регуляризация

Оба MLPRegressor и MLPClassifier используют параметр alpha для термина регуляризации (L2-регуляризация), который помогает избежать переобучения, штрафуя веса большими величинами. Следующий график отображает изменяющуюся функцию решения со значением альфа.

См. Примеры ниже для получения дополнительной информации.

Сохранение и загрузка

Метод torch.save сохраняет в бинарном виде любой словарь,
в том числе состояния модели и оптимизатора:

Затем их можно загрузить, создав предварительно модель и оптимизатор (его парметры могут быть любыми,
т.к. они загрузятся из файла):

Обучение сети

Для обучения сети необходимо создать функцию ошибки (то, что следует минимизировать)
и оптимизатор (который будет минимизировать ошибку).
Оптимизатору передаются параметры модели. В качестве ошибки выберем бинарную кросс-энтропию (BCELoss),
а оптимизатором будет SGD (Stochastic Gradient Descent):

model = TwoLayersNet(2, 5, 1) # экземпляр сети

loss = nn.BCELoss()
optimizer = torch.optim.SGD(model.parameters(), # параметры модели
lr=0.5, momentum=0.8) # параметры оптимизатора

На каждой итерации из обучающих примеров формируется массив батчей,
запускается прямое распространение y = model(bx) и
вычисляется ошибка loss (из сравнения выхода y модели с “правильными” значениями yb).
На вычислительном графе ошибки метод loss.backward() даёт
градиенты параметров модели, при помощи которых оптимизатор optimizer в методе step()
получает новые значения параметров:

Функция fit делает проход по всем данным. Это называется
эпохой обучения.
Если параметр leran=True, то происходит обучение модели (изменение её параметров).
Значение leran=False используется при оценке качества модели без её изменения.
В качестве метрик качества используется средняя ошибка по всем примерам и средняя точность (доля
правильно предсказанных классов).
Обычно требуется достаточно много эпох обучения:

В результате получим что-то типа:

Для улучшения обучения, обычно стоит перемешивать данные.
Это можно сделать двумя способами. Первый запускается перед функцией fit
в начале каждой эпохи:

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

Памяти при этом используется меньше, но при проходе по одной эпохе в обучение
могут попасть не все примеры, а в батч могут попасть одинаковые примеры.
Этот метод используется в классе DataLoader (параметр shuffle), см. ниже.

Таким образом, по сравнению с Keras в TensorFloor,
процедуру обучения
необходимо написать самостоятельно.
Однако в сложных случаях это позволяет вмешиваться в процесс на любом этапе.
Например, можно вставить свой оптимизатор :)

. if train: # в режиме обучения
L.backward() # вычисляем градиенты
with torch.no_grad():
for p in model.parameters():
p.add_(p.grad, alpha=-0.7) # p += -0.7*grad
p.grad.zero_()

Алгоритмы

где $eta$ — это скорость обучения, которая контролирует размер шага при поиске в пространстве параметров. $Loss$ — функция потерь, используемая для сети.

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

С SGD или Adam обучение поддерживает онлайн и мини-пакетное обучение.

L-BFGS — это решающая программа, которая аппроксимирует матрицу Гессе, которая представляет собой частную производную второго порядка функции. Кроме того, он аппроксимирует обратную матрицу Гессе для обновления параметров. Реализация использует версию L-BFGS Scipy .

Если выбран решатель «L-BFGS», обучение не поддерживает ни онлайн, ни мини-пакетное обучение.

Сложность

Основным преимуществом SGD является его эффективность, которая в основном линейна по количеству обучающих примеров. Если $X$ — матрица размера $(n, p)$, обучение стоит $O(k n ar p)$, где $k$ — количество итераций (эпох), а $ar p$ — среднее количество ненулевых атрибутов в выборке.

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

Последовательность слоёв

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

Простые нейронные сети с последовательной архитектурой
можно создавать при помощи стопочного интерфейса.
Например, двухслойная полносвязная сеть с двумя входами (nX=2 признака),
одним (nY=1) сигмоидным выходом (2 класса) и
пятью нейронами (nH=5) в скрытом слое
имеет вид:

import torch
import torch.nn as nn

nX, nH, nY = 2, 5, 1

model = nn.Sequential(
nn.Linear(nX, nH), # первый слой
nn.Sigmoid(), # активация скрытого слоя
nn.Linear(nH, nY), # второй, выходной слой
nn.Sigmoid() ) # его активационная фу-я

Слой Linear делает линейное преобразование входного тензора
формы (N, nX), где N – число примеров.
На выходе слоя получается тензор формы (N, nH),
который пропускается через сигмоид (новые nH признаков).
Второй слой даёт тензор (N, nY)
от которого также берётся через сигмоид. Если его значение меньше 0.5 – это первый
класс, если больше 0.5 – второй.

Собственные слои

Слои, как и вся сеть, являются наследником класса nn.Module.
Пример реализации линейного слоя:

Детали реализации

Реализация SGD находится под влиянием Stochastic Gradient из 7 . Подобно SvmSGD, вектор весов представлен как произведение скаляра и вектора, что позволяет эффективно обновлять вес в случае регуляризации L2. В случае разреженного ввода перехват обновляется с меньшей скоростью обучения (умноженной на 0,01), чтобы учесть тот факт, что он обновляется чаще. Примеры обучения выбираются последовательно, и скорость обучения снижается после каждого наблюдаемого примера. Мы приняли график скорости обучения от 8 . Для мультиклассовой классификации используется подход «один против всех». Мы используем алгоритм усеченного градиента, предложенный в 9 для регуляризации L1 (и эластичной сети). Код написан на Cython.

Нейронная сеть на PyTorch

Параметры линейной модели можно также найти при помощи
нейронной сети из одного слоя без активационной функции:

import torch.nn as nn

model = nn.Sequential( nn.Linear(nX, nY) )

Создадим SGD оптимизатор (который будет подправлять параметры)
и mse функцию ошибки:

optimizer = torch.optim.SGD(model.parameters(), lr=1, momentum=0.9)
criterion = nn.MSELoss()

Цикл обучения выглядит следующим образом.
На каждой итерации на сеть передают пачку примеров y=model(xb), в результате чего происходит
прямое распространение (forward).
Полученный выход сети y, вместе с “истинными” значениями yb
передают функции ошибки. Для неё вызывают обратное распространение backward,
в результате которого будут вычислены градиенты. Метод оптимизатора step,
при помощи этих градиентов, подправляет параметры модели. Затем
оптимизатор обнуляет градиенты (zero_grad):

После обучения можно вывести параметры модели:

Матрица весов weight, как и в sklearn,
хранится в транспонированном виде.

Stochastic Gradient Descent

SGD (Stochastic Gradient Descent) – несколько более продвинутый градиентный метод оптимизации.
В нём ошибка $L$ вычисляется не по всем данным, а по выборке (пачка, batch) размера batch_size.
Это ускоряет сходимость, т.к. для вычисления очередного шага требуются не все данные, а лишь небольшое их подмножество.
После каждой подправки параметров, выборка меняется (поэтому метод называется “stochastic”).
При прохождении через все N примеров (одна эпоха), происходит int(N/btach_size)
итераций (шагов в пространстве признаков).

Величины batch_size и $eta$ скоррелированы. Чем они больше, тем
сильнее сглажен градиент. Увеличение batch_size замедляет обучение (за эпоху делается меньше итераций).
Однако на графических карточках, благодаря быстрому перемножению больших матриц, увеличение
batch_size может уменьшать время прохода по всем данным, даже в расчёте на одну итерацию.

Ниже приведен пример сглаживания данных при помощи скользящего среднего. Синяя линия – это
одномерное стохастическое случайное блуждание (подобное цене на акцию).
Гладкие жёлтая и зеленая линии – это усреднение с различным параметром $eta$.

Понятно, что чем больше усреднение (ближе $eta$ к единице), тем сильнее отстаёт среднее от исходных данных.

lr_t = lr * (1. / (1. + decay * iterations ))

Далее происходят вычисления:

v = momentum * v – lr_t * grad
if nesterov: params = params + momentum * v – lr_t * grad
else: params = params + v

По умолчанию приняты следующие параметры: SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False).

где $z_i$ представляет $i$-тый элемент ввода в softmax, который соответствует классу $i$, а также $K$ количество классов. Результатом является вектор, содержащий вероятности, которые выбирают $x$ принадлежат к каждому классу. На выходе получается класс с наибольшей вероятностью.

В регрессии результат остается как $f(x)$; следовательно, функция активации выхода — это просто функция идентичности.

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

где $i$ — шаг итерации, а ϵ скорость обучения со значением больше 0.

Алгоритм останавливается, когда достигает заданного максимального количества итераций; или когда улучшение потерь ниже определенного небольшого числа.

Стохастический градиентный спуск для разреженных данных

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

Имеется встроенная поддержка разреженных данных, представленных в любой матрице в формате, поддерживаемом scipy.sparse . Однако для максимальной эффективности используйте формат матрицы CSR, как определено в scipy.sparse.csr_matrix .

Модельные данные

X = torch.rand (1200,2)
Y = (torch.sum((X – 0.5)**2, axis=1) < 0.1).float().view(-1,1)

Метод float преобразует логические значения оператора меньше в
вещественные числа (0.0 или 1.0).
Затем при помощи view превращаем Y
в матрицу из одного столбика (в котором находится 0 или 1).
По строчкам идут классы примеров.

При помощи библиотеки matplotlib нарисуем то, что в результате получилось:

Классификация

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

Как и другие классификаторы, SGD должен быть оснащен двумя массивами: массивом X формы (n_samples, n_features), содержащим обучающие образцы, и массивом формы y (n_samples,), содержащим целевые значения (метки классов) для обучающих образцов:

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

SGD подгоняет линейную модель к обучающим данным. Атрибут coef_ содержит параметры модели:

Атрибут intercept_ содержит перехват (ака смещение или смещение):

Параметр определяет, должна ли модель использовать точку пересечения, т. Е. Смещенную гиперплоскость fit_intercept.

Расстояние со знаком до гиперплоскости (вычисленное как скалярное произведение между коэффициентами и входной выборкой плюс точка пересечения) определяется как SGDClassifier.decision_function:

Конкретную функцию потерь можно установить с помощью loss параметра.  SGDClassifier поддерживает следующие функции потерь:

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

Конкретный штраф можно установить с помощью penalty параметра. SGD поддерживает следующие штрафы:

По умолчанию установлено penalty=”l2″. Штраф L1 приводит к разреженным решениям, сводя большинство коэффициентов к нулю. Elastic Net 11  устраняет некоторые недостатки штрафа L1 при наличии сильно коррелированных атрибутов. Параметр l1_ratioуправляет выпуклой комбинацией штрафов L1 и L2.

SGDClassifier поддерживает многоклассовую классификацию путем объединения нескольких двоичных классификаторов по схеме «один против всех» (OVA). Для каждого из $K$ классов, изучается двоичный классификатор, который отличает этот классификатор от всех остальных $K−1$ классы. Во время тестирования мы вычисляем показатель достоверности (т. е. Подписанные расстояния до гиперплоскости) для каждого классификатора и выбираем класс с наибольшей достоверностью. На рисунке ниже показан подход OVA к набору данных радужной оболочки глаза. Пунктирные линии представляют три классификатора OVA; цвета фона показывают поверхность принятия решения, вызванную тремя классификаторами.

В случае мультиклассовой классификации coef_это двумерный массив формы (n_classes, n_features) и intercept_одномерный массив формы (n_classes,). I-я строка coef_ содержит весовой вектор классификатора OVA для i-го класса; классы индексируются в порядке возрастания (см. атрибут classes_). Обратите внимание, что, в принципе, они позволяют создать вероятностную модель loss=”log”и loss=”modified_huber” больше подходят для классификации «один против всех».

SGDClassifier поддерживает как взвешенные классы, так и взвешенные экземпляры через параметры соответствия class_weightи sample_weight. См. Примеры ниже и строку документации SGDClassifier.fit для получения дополнительной информации.

SGDClassifier поддерживает усредненный SGD (ASGD) 10 . Усреднение можно включить настройкой average=True. ASGD выполняет те же обновления, что и обычный SGD (см. Математическая формулировка ), но вместо использования последнего значения коэффициентов в качестве coef_ атрибута (т.е. значений последнего обновления) coef_вместо этого устанавливается среднее значение коэффициентов по всем параметрам. обновления. То же самое и с intercept_ атрибутом. При использовании ASGD скорость обучения может быть больше и даже постоянной, что приводит к сокращению времени обучения на некоторых наборах данных.

Для классификации с логистическими потерями доступен другой вариант SGD со стратегией усреднения с алгоритмом стохастического среднего градиента (SAG), доступным в качестве решателя в LogisticRegression.

Градиентный метод

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

Чтобы найти минимум $L$, необходимо двигаться
в обратном к градиенту направлении (вдоль антиградиента), с шагом пропорциональным некоторому числу $lambda$.
Этот гиперпараметр называется скоростью обучения:

Чем больше скорость обучения $lambda$, тем быстрее параметры модели приближаются к оптимальным
значениям. Однако при больших $lambda$ существует риск проскочить минимум (несмотря на
уменьшение длины градиента в его окрестности). Проиллюстрируем это примерами.

Многослойный персептрон

Рисунок 1: Один скрытый слой MLP.

Модуль содержит публичные атрибуты coefs_ и intercepts_. coefs_список весовых матриц, где весовая матрица с индексомi представляет собой веса между слоями i и слой $i+1$. intercepts_ список векторов смещения, где вектор с индексом $i$ представляет значения смещения, добавленные к слою $i+1$.

Преимущества многослойного перцептрона:

К недостаткам многослойного персептрона (MLP) можно отнести:

См. Раздел «Советы по практическому использованию», в котором рассматриваются некоторые из этих недостатков.

Регрессия

Конкретную функцию потерь можно установить с помощью loss параметра. SGDRegressor поддерживает следующие функции потерь:

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

penaltyПараметр определяет регуляризации , который должен использоваться (смотри описание выше в разделе классификации).

SGDRegressor также поддерживает среднюю ставку SGD 10 (и здесь снова см. описание выше в разделе классификации).

Для регрессии с квадратом потерь и штрафом l2 доступен другой вариант SGD со стратегией усреднения с алгоритмом стохастического среднего градиента (SAG), доступным в качестве решателя в Ridge.

Предположим, есть $n$ обучающие образцы, $m$ Особенности, $k$ скрытые слои, каждый из которых содержит $h$ нейроны — для простоты и $o$ выходные нейроны. Временная сложность обратного распространения ошибки равна $O(ncdot m cdot h^k cdot o cdot i)$, где $i$- количество итераций. Поскольку обратное распространение имеет высокую временную сложность, рекомендуется начинать с меньшего количества скрытых нейронов и нескольких скрытых слоев для обучения.

Градиент на графе в PyTorch

Воспроизведём на PyTorch простой градиентный метод.
Параметры модели W,B
являются терминальными узлами вычислительного графа, для которых
будет вычисляться градиент (requires_grad=True):

Метод randn возвращает тензор нормально распределённых
случайных чисел. По умолчанию они имеют тип float32.
Чтобы он совпадал с типом обучающих данных X,Y, происходит
явное задание типа аргументом dtype.

Затем идёт основной цикл вычислений:

Вначале формируются torch-тензоры пачек из numpy-тензоров
(новая память при этом не выделяется). Затем строится вычислительный граф, корнем
которого будет ошибка модели loss. Попутно происходят вычисления
на графе. Затем для корня запускается метод backward, который возвращается
по веткам и вычисляет градиенты.

Любое выражение с тензорами, имеющими свойство requires_grad=True
приводит к динамической перестройке вычислительного графа,
ведущего к его корню (ошибке модели loss).
Чтобы этого не произошло, после backward
устанавливается окружение no_grad(), которое блокирует изменение графа
При этом, меняя параметры, мы не создаём новых тензоров (функция add_ это “инкрементация”).
После изменения W,B необходимо сбросить в ноль градиенты (для следующей итерации).

Персептрон или перцептрон — это одной из самых простых и первых моделей нейронных сетей, которая была разработана в 1940-х годах Франклином Россом и его коллегами. персептрон состоит из одного или нескольких входных нейронов и одного выходного нейрона. Входные нейроны принимают входные данные и передают их на обработку выходному нейрону.

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

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

Сегодня персептрон мало используется в сравнении с более современными и точными моделями нейронных сетей.

Многослойные персептроны (MLP)

Многослойный персептрон (MLP) — это тип нейронной сети, который основан на архитектуре персептрона, но имеет несколько скрытых слоев между входным и выходным слоем. Это позволяет модели обрабатывать более сложные и нелинейные данные, что делает их более пригодными для многих задач классификации и регрессии.

MLP использует методы обратного распространения ошибки (Backpropagation) для обучения модели. Этот метод использует ошибку между выходными данными модели и истинными значениями для адаптации весов входных данных и производит обновление весов в направлении уменьшения ошибки.

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

Рекуррентные нейронные сети (RNN)

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

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

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

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

Свёрточные нейронные сети (CNN)

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

CNN состоят из трёх основных типов слоёв: свёрточных, макс-пулинга и полносвязных.

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

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

— Полносвязные слои используются для классификации или регрессии. Они преобразуют информацию из предыдущих слоёв в выходные значения.

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

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

Глубокое обучение (DL)

Глубокое обучение (DL) — это метод машинного обучения, который использует глубокие нейронные сети для обработки и анализа данных. Этот метод основан на идее, что с помощью большого количества слоёв нейронной сети можно извлечь более сложные и высокоуровневые признаки из данных.

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

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

Одной из особенностей DL является использование методов обучения с подкреплением, которые позволяют модели адаптироваться к новым данным и улучшать свою точность со временем.

Генетические алгоритмы (GA)

Генетические алгоритмы (GA) — это метод машинного обучения, который использует механизмы естественного отбора и селекции для поиска оптимальных решений в задачах оптимизации и поиска.

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

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

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

Автоэнкодеры (AE)

Автоэнкодеры (AE) — это модели машинного обучения, которые используют принципы нейронных сетей для извлечения признаков из данных. Они обычно состоят из двух частей: энкодера, который кодирует данные в низкоразмерное представление, и декодера, который декодирует это представление обратно в исходный вид.

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

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

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

Функциональная архитектура

При проектировании сложных нейронных сетей, их архитектуру удобнее задавать в функциональном виде.
Для этого создаётся наследник класса nn.Module.
В нём переопределяется конструктор и метод forward.
В конструкторе задаются необходимые слои и инициализируются их параметры.
Обратим внимание на вызов конструктора предка которому необходимо передать имя нашего класса.
В методе forward (прямое распространение) строится архитектура сети (слои связываются
в вычислительный граф):

class TwoLayersNet(nn.Module):
def __init__(self, nX, nH, nY):
super(TwoLayersNet, self).__init__() # конструктор предка с этим именем

self.fc1 = nn.Linear(nX, nH) # создаём параметры модели
self.fc2 = nn.Linear(nH, nY) # в полносвязных слоях

def forward(self, x): # задаётся прямой проход
x = self.fc1(x) # выход первого слоя
x = nn.Sigmoid()(x) # пропускаем через Sigmoid
x = self.fc2(x) # выход второго слоя
x = nn.Sigmoid()(x) # пропускаем через сигмоид
return x

model = TwoLayersNet(2, 5, 1) # экземпляр сети

Вызов nn.Line(in_features, out_features) создаёт два экземпляра линейного полносвязного
слоя fc1, fc2 (fully connected).
Одновременно с этим задаются случайные значения их весов и смещений. Скобочный оператор
fc1(x) в методе forward
запускает вычисления внутри слоя и на выходе выдаёт результирующий тензор.

Критерий остановки

Классы SGDClassifier и SGDRegressor предоставляют два критерия для остановки алгоритма при достижении заданного уровня сходимости:

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

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

Параметры готовых оптимизаторов можно также менять непосредственно в процессе обучения

Класс MLPClassifier реализует алгоритм многослойного перцептрона (MLP), который обучается с использованием обратного распространения .

MLP обучается на двух массивах: массив X размера (n_samples, n_features), который содержит обучающие образцы, представленные как векторы признаков с плавающей запятой; и массив y размера (n_samples,), который содержит целевые значения (метки классов) для обучающих выборок:

После подгонки (обучения) модель может предсказывать метки для новых образцов:

MLP может подгонять нелинейную модель к обучающим данным. clf.coefs_ содержит весовые матрицы, составляющие параметры модели:

В настоящее время MLPClassifier поддерживает только функцию потерь кросс-энтропии, которая позволяет оценивать вероятность путем запуска predict_proba метода.

MLPClassifier поддерживает мультиклассовую классификацию, применяя Softmax в качестве выходной функции.

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

См. Примеры ниже и строку документации MLPClassifier.fit для получения дополнительной информации.

Вычисления на GPU

Для вычисления на GPU (как и в общем случае)
необходимо создать соответствующие вычислительные устройства:

gpu = torch.device(“cuda:0” if torch.cuda.is_available() else “cpu”)
cpu = torch.device(“cpu”)

После создания модели, её можно отправить на графическую карточку и (если позволяет её память)
тоже сделать с обучающими данными:

model = TwoLayersNet(2, 5, 1) # экземпляр сети
model.to(gpu) # отправляем его на GPU

X = X.to(gpu) # отправляем обучающие данные на GPU
Y = Y.to(gpu)

Если для обучающих данных места на GPU не хватает,
их можно отправлять туда батчами.

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

Оптимальные гиперпараметры

Любой метод оптимизации зависит от гиперпараметров, выбор которых иногда оказывается очень важным.

Нарисуем карту высот ошибки Loss линейной модели, как функцию
гиперпараметров $lambda$ (=lr) и $eta$ (=mo).
Синий цвет – минимум ошибки, коричневый – максимум.
Количество эпох epochs = 10 и размер пачки batch_size = 10 фиксированы (точек N=100).
Голубая линия с точками означает значение $eta$ соответствующее минимальной ошибке при данном $lambda$.
Под картой высот приведен график ошибки как функции $lambda$ (при оптимальном $eta$ для данного $lambda$).
Коричневый цвет на карте высот соответствует области неустойчивости градиентного метода:

Как видно, для такой простой модели, при $eta sim 0.8$, значение $lambda$ может
меняться в широких пределах.
Оптимальные гиперпараметры: mo=0.63, lr=5.31, loss=0.00013.
Отметим, что подходящая параметризация гиперпараметров важна.
Например, если выбрать как в Keras
lr=$lambda,(1-eta)$, то получится менее устойчивая картина:

Оптимальные гиперпараметры в этом случае: mo=0.58, lr=2.25, loss=0.00013.

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

MLPRegressor также поддерживает регрессию с несколькими выходами, при которой в выборке может быть более одной цели.

Классы датасетов

В PyTorch принято оборачивать обучающие данные
в класс. Он является наследником класса Dataset
и переопределяет метод __len__
числа примеров и метод __getitem__
получения примера по индексу idx:

Создав датасет, его можно передать объекту DataLoader,
который будет выдавать батчи, перемешивать, разбивать на обучение и тест, нормализовать данные и т.п.
(см. документацию).

Нейронная сеть на Keras

Библиотека Keras является простым в использовании инструментом для
проектирования нейронных сетей. В настоящее время она является составной частью фреймворка tensorflow
от Google.
Введение в Keras можно найти в документе NN_Base_Keras.

Линейная модель (один слой без активационной функции) в Keras
реализован в полносвязном слое Dense.
Создания нейронной сети с одним таким слоем делается следующим образом:

from tensorflow import keras # keras из tensorflow
from keras.models import Sequential # способ формирования слоёв (стопка)
from keras.layers import Dense # полносвязный слой
from keras.optimizers import SGD # метод оптимизации

model = Sequential() # линейная стопка слоёв
model.add(Dense(units=nY, input_dim=nX))

После создания модели, она компилируется (compile)
и запускается её обучением (fit).
При обучении будем использовать SGD-оптимизатор и mse-ошибку:

model.compile(optimizer = SGD(lr=2, momentum=0.5), loss = ‘mse’)

res = model.fit(X, Y, batch_size=batch_size, epochs=10, verbose=0 ) )

После обучения можно вывести график ошибок, как функцию числа эпох:

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

Вывод структуры сети

Простейший способ увидеть слои сети, это просто вывести на печать модель:

print(model) # текстовое представление модели

Удобнее воспользоваться сторонним модулем modelsummary.
В его функцию summary передаётся входной тензор
с любыми значениями (но правильной формы) из одного примера
(в shape это будет первая размерность -1):

from modelsummary import summary

summary(model, torch.zeros(1, 2), show_input=False) # аналог summary в keras

Если установить show_input=True, то, вместо формы выхода,
будет печататься форма входа каждого слоя
Для составных моделей можно запускать функцию summary
с параметром show_hierarchical=True.

Вывести параметры модели при стопочном (Sequential) способе её задания
можно послойно:

for layer in model:
print(“***”, layer)
for param in layer.parameters():
print(param.data.numpy())

В общем случае параметры модели выводятся таким образом:

for param in model.parameters():
print(param.numel(), param.size(), param.data.numpy())

Доступ к параметрам через атрибут data необходим, т.к. они являются
узлами графа (можно вместо этого написать param.detach(),
см. введение в PyTotch).
Ещё один способ вывода обучаемых параметров с их именами числом параметров и формами:

fc1.weight : 10 shape: (5, 2)
fc1.bias : 5 shape: (5,)
fc2.weight : 5 shape: (1, 5)
fc2.bias : 1 shape: (1,)
total : 21

Наконец, библиотека torchviz позволяет
изобразить вычислительный граф модели (рисунок справа):

import torchviz

torchviz.make_dot(model(X),
params = dict(model.named_parameters()) )

В первом аргументе функции make_dot
передаётся корень графа модели,
который получается при подаче в неё входного тензора (правильной формы, с любым числом примеров).

Понравилась статья? Поделиться с друзьями:
ТВОЙ ВК
Добавить комментарий