Skip to content

SGD

Описание

Info

Родительский класс: Optimizer

Производные классы: MomentumSGD, NesterovSGD

Данный модуль реализует принцип работы стохастического градиентного спуска (stochastic gradient descent - SGD).

Пусть имеется некоторая модель, определяемая набором параметров \theta (в случае нейронных сетей - веса модели), и дана обучающая выборка, состоящая из l + 1 пар "объект-ответ" {(x_0, y_0),...,(x_l, y_l)}. Также необходимо определить целевую функцию (функция потерь) в общем виде - J(\theta), или J(\theta)_i для i-го объекта выборки.

Тогда задача оптимизации в данном случае формулируется следующим образом: $$ \sum_{i=0}^{l} J(\theta) \to min_{\theta} $$

А процесс оптимизации параметров (обучения весов): $$ \theta_{t+1} = \theta_t - \eta \cdot \frac{1}{l}\sum_{i=0}^{l} \nabla_{\theta}{J_i(\theta_t)} $$

где

\theta_{t+1} - обновлённый набор параметров для следующего шага оптимизации;
\theta_t - набор параметров на текущем шаге;
\eta - скорость обучения;
\nabla_{\theta}J_i(\theta_t) - градиент функции ошибки для i-го объекта обучающей выборки.

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

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

Пусть n - размер мини-батча, тогда процесс оптимизации параметров будет выглядеть следующим образом:

\theta_{t+1} = \theta_t - \eta \cdot \frac{1}{n}\sum_{i=j}^{j + n} \nabla_{\theta}{J_i(\theta_t)}

где

j - индекс случайно взятого элемента, причём j <= l - n

Инициализация

def __init__(self, learnRate=1e-3, nodeinfo=None):

Параметры

Параметр Возможные типы Описание По умолчанию
learnRate float Скорость обучения 1e-3
nodeinfo NodeInfo Объект, содержащий информацию о вычислительном узле None

Пояснения

-

Примеры


Необходимые импорты:

import numpy as np
from PuzzleLib.Optimizers import SGD
from PuzzleLib.Backend import gpuarray

Info

gpuarray необходим для правильного размещения тензора на GPU.

Создадим синтетическую обучающую выборку:

data = gpuarray.to_gpu(np.random.randn(16, 128).astype(np.float32))
target = gpuarray.to_gpu(np.random.randn(16, 1).astype(np.float32))

Объявляем оптимизатор:

optimizer = SGD(learnRate=0.01)

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

optimizer.setupOn(net, useGlobalState=True)

Info

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

Также пусть есть некая функция ошибки loss, наследованная от Cost, рассчитывающая в т.ч. её градиент. Тогда получаем реализацию процесса оптимизации:

for i in range(100):
... predictions = net(data)
... error, grad = loss(predictions, target)

... optimizer.zeroGradParams()
... net.backward(grad)
... optimizer.update()

... if (i + 1) % 5 == 0:
...   print("Iteration #%d error: %s" % (i + 1, error))