Объяснение SGD в функциональности керас - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь понять оптимизатор SGD на keras для реализации накопительной версии этого оптимизатора. Я застрял в точке, где я не могу по-настоящему следовать рассуждениям команд после определенной точки.

Фактическая функция такова:

def get_updates(self, loss, params):
    grads = self.get_gradients(loss, params)
    self.updates = [K.update_add(self.iterations, 1)]

    lr = self.learning_rate
    if self.initial_decay > 0:
        lr = lr * (1. / (1. + self.decay * K.cast(self.iterations,
                                                  K.dtype(self.decay))))
    # momentum
    shapes = [K.int_shape(p) for p in params]
    moments = [K.zeros(shape, name='moment_' + str(i)) for (i, shape) in enumerate(shapes)]
    self.weights = [self.iterations] + moments
    for p, g, m in zip(params, grads, moments):
        v = self.momentum * m - lr * g  # velocity
        self.updates.append(K.update(m, v))

        if self.nesterov:
            new_p = p + self.momentum * v - lr * g
        else:
            new_p = p + v

        # Apply constraints.
        if getattr(p, 'constraint', None) is not None:
            new_p = p.constraint(new_p)

        self.updates.append(K.update(p, new_p))
    return self.updates

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

Строка moments = [K.zeros(shape, name='moment_' + str(i)) for (i, shape) in enumerate(shapes)] создает пустой тензор для сохранения моментов, пока я его получаю. Но когда я вычисляю вручную, я не получаю результаты, которые ожидаю от теоретической формулы.

Например, для двух итераций мы имеем (предполагая self.momentum = 0.9 и не применяя Нестерова для простоты):

Iter # 1:

grads = self.get_gradients(loss, params): вычисляет градиент, назовем их grad1.
...
Внутри for p, g, m in zip(params, grads, moments) цикла:
v1 = self.momentum * m - lr * g = 0.9*0 - lr * grad1 = - lr * grad1.
Обновление m -> v1 и p -> new_p = p + v1 = - lr * grad1.

Iter # 2:

grads = self.get_gradients(loss, params): рассчитывает градиент, назовем их grad2.
...
Внутри for p, g, m in zip(params, grads, moments)цикл:
(m инициализируется на каждой итерации в 0 Я думаю. Исправьте меня, если я ошибаюсь)
v2 = self.momentum * m - lr * g = 0.9*0 - lr * grad2 = - lr * grad2Обновление m -> v and p -> new_p = p + v = v1 + v2 = - lr * grad1 - lr * grad2`.

Я ожидал бы что-то вроде: - 0.9*lr * grad1 - lr * grad2 подойдет сюда. Кроме того, судя по моим вычислениям m (моменты), похоже, не используется, поэтому я, вероятно, как-то ошибаюсь в своих расчетах. Может кто-нибудь объяснить менталитет SGD в кератах?

Кроме того, у меня есть некоторые проблемы с пониманием того, что повторяет for, что могло бы дать мне подсказку, что я здесь упускаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...