[DL]關於莫煩【RNN 循环神经网络 (回归)】裡面沒有講到的事情

Posted by John on 2019-02-18
Words 683 and Reading Time 2 Minutes
Viewed Times

今天在看莫煩的Pytorch教學,在練習RNN 循环神经网络 (回归)這篇時發現了一些問題想要記錄下來,下面我就直接拿他在github上的code來說比較快:

關於增加資料維度的方法

第一個要講的在code第83行的地方

1
2
3
...
x = torch.from_numpy(x_np[np.newaxis, :, np.newaxis])
y = torch.from_numpy(y_np[np.newaxis, :, np.newaxis])

這兩行是為了將ndarray增加維度後轉成tensor,一開始看到x_np[np.newaxis, :, np.newaxis]的時候其實有點不知道這在幹啥,不過其實印出來就知道了,它是一種增加資料維度的形式, 如果原本x_np的shape是(1),x_np[np.newaxis, :, np.newaxis]後的shape會變成(1, 1, 1)。

也可以透過np.expand(x_np, dim=0)達到相同的效果,不過似乎一次只能增加一個維度。

或是,也可以先轉成tensor在透過view()來任意改變你想要的維度:

1
2
x = torch.from_numpy(x_np).view(1, -1, 1)               
y = torch.from_numpy(y_np).view(1, -1, 1)

關於backward()的小細節

第二個要講的在code第86行

86
87
88
89
90
91
92
93
94
...
prediction, h_state = rnn(x, h_state) # rnn output
# !! next step is important !!
h_state = h_state.data

loss = loss_func(prediction, y) # calculate loss
optimizer.zero_grad() # clear gradients for this training step
loss.backward() # backpropagation, compute gradients
optimizer.step() # apply gradients

莫煩上課說這一步很重要,要用.data把h_state的值取出來,不然會出錯,不過好像沒有詳細講到為什麼,所以我想來提一下,不過我也不是很清楚,有錯誤還請糾正。

我練習的時候還真的不信邪,就是不打那一行,然後就出錯了,到底加這一行的原因是什麼呢?

大家都知道在Pytorch中是動態建立計算圖的,之所以要把ndarray轉成tensor(注意,在0.4.0後variable和tensor合併了,不然以前還是要將tensor要轉成variable的)就是為了要建立這個計算圖,不過,tensor不只儲存了資料,他還儲存了梯度的資訊。

另外一點,為了節省記憶體,pytorch每次執行backward()的時候會將計算圖清空。

所以基於這兩點,其實h_state是計算圖的一部分,如果不信可以把h_state印出來會看到類似的訊息:

tensor(..., device='cuda:0', grad_fn=)

如果該tensor是一個單純的計算結果,grad_fn會返回None,否則他會返回與該函數相關的對象。在這一個練習中,rnn每次都會將h_state的值餵入下一次的訓練,但只是需要h_state的值而已,所以要透過.data將值取出來,如果沒有.data,則下一次餵入的時候由於計算圖在上一次已經被清空了,屆時h_state就會產生錯誤。

參考資料

Autograd:PyTorch中的梯度计算


>