Тензоры PyTorch имеют одинаковое значение после добавления в список - PullRequest
0 голосов
/ 02 августа 2020

Изучая градиенты и оптимизируя процесс с помощью Pytorch, я хотел выяснить изменение значений функции потерь и значений весов с помощью графика. Пока я пытался построить график, я использовал как numpy, так и torch, потому что хотел сравнить. Во время хранения списка град. и значения функции потерь. Работает на numpy:

def gradient(x,y, y_predicted):
  return np.dot(2*x, y_predicted-y).mean() 

dw = gradient(x,y,y_pred)
dw_list.append(dw)

[-120.0, -112.8, -106.032, -99.67008, -93.68988, -88.06848, -82.78437, -77.81731, -73.14827, -68.75938]

Не работает на факеле:

  for epoch in range(n_iters):
    # prediction = forward pass
    y_pred = forward(x)
    
    # loss
    l = loss(y, y_pred)
    loss_list.append(l)
    print('loss')
    print(l_list)
    # gradients = backward pass
    l.backward()  # calculate w.grad = dl/dw   and cumulative 
    
    # update weights
    with torch.no_grad():
        w -= learning_rate * w.grad
    print(f'w.grad before zero setting = {w.grad}')
    dw_list.append(w.grad) 
    print(dw_list)
    #print(f'w.grad before zero setting = {w.grad}')
    # zero gradients
    w.grad.zero_()

[tensor(-6.9485), tensor(-6.9485), tensor(-6.9485), tensor(-6.9485), tensor(-6.9485), tensor(-6.9485), tensor(-6.9485), tensor(-6.9485), tensor(-6.9485), tensor(-6.9485)]

Почему dw_list.append(dw) работает на numpy, а dw_list.append(w.grad) не работает на torch?

Почему только новое значение grad заполняло весь массив на каждом итере. при тензоре факела?

1 Ответ

1 голос
/ 03 августа 2020

w.grad - тензор; он ( тот же тензор) добавляется к списку на каждой итерации, поэтому список содержит копии одного и того же тензора, а не копии его значения в каждый момент времени, когда вы ' d, вероятно, имел в виду.

Стандартный способ обработки этого - использовать:

dw_list.append(w.grad.detach().cpu().numpy()) 

Пожалуйста, прочтите это обсуждение, чтобы узнать, почему необходим detach (): https://discuss.pytorch.org/t/should-it-really-be-necessary-to-do-var-detach-cpu-numpy/35489/6

Напротив, np.mean () возвращает new python объект с плавающей запятой каждый раз, когда он вызывается, и поэтому значения в конце будут разными. Список append () не делает ничего другого в этих двух случаях.

PS Я думаю, что это тоже сработает:

dw_list.append(w.grad.clone())

, однако он сохранит клонированные тензоры на графике (и на gpu, если оригиналы были на gpu). Это может быть то, что вам нужно, а может и не быть.

...