Хранить обновления веса для momemntum - PullRequest
0 голосов
/ 07 февраля 2019

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

parameters -= (lr * (p.grad*0.1 + p_delta_prev*0.9))

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

Вот что я имею в своей функции обновления:

#we now want to do the update with momentum
#momentum takes derivative, multiplies it by 0.1, then takes the previous update,
#multiplies it by 0.9 and we add the two together
#alpha = 0.1, beta = 0.9;  p-=grad*0.1 + p*0.9
def update(x,y,lr):
    wd = 1e-5
    y_hat = model(x)
    # weight decay
    w2 = 0.
    for p in model.parameters(): w2 += (p**2).sum()
    # add to regular loss
    loss = loss_func(y_hat, y) + w2*wd
    loss.backward()
    with torch.no_grad():
        for p in model.parameters():
            #p.grad is the slope of the line of that parameter
            #current_p-previous_p to get difference
            p_update = (lr * (p.grad*0.1 + p*0.9))
            p.sub_(p_update)
            p.grad.zero_()
    return loss.item()

Здесь p*0.9 следует заменить на p_delta_prev.Но как мне хранить эти дельты для каждого параметра?Если бы я сохранил их в тензор, я бы эффективно скопировал дельты веса в память, сделав мою модель в два раза больше.Что было бы хорошим способом сделать это?Я не хочу использовать встроенную функцию, которая выполняет эту активацию для меня.Я заглянул в pytorch sgd.py, и он выглядит как хранилище состояний.

Я обновил код:

#we now want to do the update with momentum
#momentum takes derivative, multiplys it by 0.1, then takes the previous update,
#multiplies it by 0.9 and we add the two together
#alpha = 0.1, beta = 0.9;  p-=grad*0.1 + p*0.9
p_delta = {}
def update(x,y,lr):
    wd = 1e-5
    y_hat = model(x)
    # weight decay
    w2 = 0.
    for p in model.parameters(): w2 += (p**2).sum()
    # add to regular loss
    loss = loss_func(y_hat, y) + w2*wd
    loss.backward()
    with torch.no_grad():
        i = 0
        for p in model.parameters():
            #p.grad is the slope of the line of that parameter
            if i not in p_delta:#check if key exists
                p_delta[i] = torch.zeros_like(p)
            p_update = (lr *p.grad) + (p_delta[i]*0.9)
            p_delta[i] = p_update.clone()
            p.sub_(p_update)
            p.grad.zero_()
            print((p_delta[i]))
            i+=1
    return loss.item()

Я думаю, что код в электронной таблице Excel неверен.Джереми, кажется, показывает: lr* ((p.grad*0.1) + (p_delta[i]*0.9)), но многие уроки, кажется, показывают: (lr *p.grad) + (p_delta[i]*0.9) Если мы реализуем код Джереми, потери на самом деле медленнее, чем ванильный GD.Часть видео здесь: https://youtu.be/CJKnDu2dxOE?t=6581

1 Ответ

0 голосов
/ 07 февраля 2019

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

При этом я бы не стал беспокоиться, потому что размер моделиредко является большим фактором потребления памяти всего алгоритма - хранение промежуточных сетевых активаций для алгоритма обратного распространения намного дороже.На примере сети VGG-16 она имеет 138 миллионов параметров (эта цифра взята из здесь ), что составляет чуть более 0,5 ГБ, если хранится с одинарной точностью.Сравните это с 6 ГБ +, найденными на современных современных графических процессорах.

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