機器學習(ML)九之GRU、LSTM、深度神經網絡、雙向循環神經網絡


門控循環單元(GRU)

循環神經網絡中的梯度計算方法。當時間步數較大或者時間步較小時,循環神經網絡的梯度較容易出現衰減或爆炸。雖然裁剪梯度可以應對梯度爆炸,但無法解決梯度衰減的問題。通常由於這個原因,循環神經網絡在實際中較難捕捉時間序列中時間步距離較大的依賴關系。

門控循環神經網絡(gated recurrent neural network)的提出,正是為了更好地捕捉時間序列中時間步距離較大的依賴關系。它通過可以學習的門來控制信息的流動。其中,門控循環單元(gated recurrent unit,GRU)是一種常用的門控循環神經網絡。

門控循環單元

門控循環單元的設計。它引入了重置門(reset gate)和更新門(update gate)的概念,從而修改了循環神經網絡中隱藏狀態的計算方式。

重置門和更新門

門控循環單元中的重置門和更新門的輸入均為當前時間步輸入Xt與上一時間步隱藏狀態Ht1,輸出由激活函數為sigmoid函數的全連接層計算得到。

 

候選隱藏狀態

 

隱藏狀態

 

 

 代碼實現

  1 #!/usr/bin/env python
  2 # coding: utf-8
  3 
  4 # In[10]:
  5 
  6 
  7 import d2lzh as d2l
  8 from mxnet import nd
  9 from mxnet.gluon import rnn
 10 import zipfile
 11 
 12 
 13 # In[11]:
 14 
 15 
 16 def load_data_jay_lyrics(file):
 17     """Load the Jay Chou lyric data set (available in the Chinese book)."""
 18     with zipfile.ZipFile(file) as zin:
 19         with zin.open('jaychou_lyrics.txt') as f:
 20             corpus_chars = f.read().decode('utf-8')
 21     corpus_chars = corpus_chars.replace('\n', ' ').replace('\r', ' ')
 22     corpus_chars = corpus_chars[0:10000]
 23     idx_to_char = list(set(corpus_chars))
 24     char_to_idx = dict([(char, i) for i, char in enumerate(idx_to_char)])
 25     vocab_size = len(char_to_idx)
 26     corpus_indices = [char_to_idx[char] for char in corpus_chars]
 27     return corpus_indices, char_to_idx, idx_to_char, vocab_size
 28 
 29 
 30 # In[12]:
 31 
 32 
 33 file ='/Users/James/Documents/dev/test/data/jaychou_lyrics.txt.zip'
 34 (corpus_indices, char_to_idx, idx_to_char, vocab_size) = load_data_jay_lyrics(file)
 35 
 36 
 37 # In[13]:
 38 
 39 
 40 num_inputs, num_hiddens, num_outputs = vocab_size, 256, vocab_size
 41 ctx = d2l.try_gpu()
 42 
 43 def get_params():
 44     def _one(shape):
 45         return nd.random.normal(scale=0.01, shape=shape, ctx=ctx)
 46 
 47     def _three():
 48         return (_one((num_inputs, num_hiddens)),
 49                 _one((num_hiddens, num_hiddens)),
 50                 nd.zeros(num_hiddens, ctx=ctx))
 51 
 52     W_xz, W_hz, b_z = _three()  # 更新門參數
 53     W_xr, W_hr, b_r = _three()  # 重置門參數
 54     W_xh, W_hh, b_h = _three()  # 候選隱藏狀態參數
 55     # 輸出層參數
 56     W_hq = _one((num_hiddens, num_outputs))
 57     b_q = nd.zeros(num_outputs, ctx=ctx)
 58     # 附上梯度
 59     params = [W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q]
 60     for param in params:
 61         param.attach_grad()
 62     return params
 63 
 64 
 65 # In[14]:
 66 
 67 
 68 def init_gru_state(batch_size, num_hiddens, ctx):
 69     return (nd.zeros(shape=(batch_size, num_hiddens), ctx=ctx), )
 70 
 71 
 72 # In[15]:
 73 
 74 
 75 def gru(inputs, state, params):
 76     W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q = params
 77     H, = state
 78     outputs = []
 79     for X in inputs:
 80         Z = nd.sigmoid(nd.dot(X, W_xz) + nd.dot(H, W_hz) + b_z)
 81         R = nd.sigmoid(nd.dot(X, W_xr) + nd.dot(H, W_hr) + b_r)
 82         H_tilda = nd.tanh(nd.dot(X, W_xh) + nd.dot(R * H, W_hh) + b_h)
 83         H = Z * H + (1 - Z) * H_tilda
 84         Y = nd.dot(H, W_hq) + b_q
 85         outputs.append(Y)
 86     return outputs, (H,)
 87 
 88 
 89 # In[16]:
 90 
 91 
 92 num_epochs, num_steps, batch_size, lr, clipping_theta = 160, 35, 32, 1e2, 1e-2
 93 pred_period, pred_len, prefixes = 40, 50, ['分開', '不分開']
 94 
 95 
 96 # In[ ]:
 97 
 98 
 99 d2l.train_and_predict_rnn(gru, get_params, init_gru_state, num_hiddens,
100                           vocab_size, ctx, corpus_indices, idx_to_char,
101                           char_to_idx, False, num_epochs, num_steps, lr,
102                           clipping_theta, batch_size, pred_period, pred_len,
103                           prefixes)
View Code

長短期記憶(LSTM)

常用的門控循環神經網絡:長短期記憶(long short-term memory,LSTM)。它比門控循環單元的結構稍微復雜一點。

長短期記憶

LSTM 中引入了3個門,即輸入門(input gate)、遺忘門(forget gate)和輸出門(output gate),以及與隱藏狀態形狀相同的記憶細胞(某些文獻把記憶細胞當成一種特殊的隱藏狀態),從而記錄額外的信息。

輸入門、遺忘門和輸出門

候選記憶細胞

記憶細胞

隱藏狀態

 

代碼實現

 1 #LSTM 初始化參數
 2 num_inputs, num_hiddens, num_outputs = vocab_size, 256, vocab_size
 3 ctx = d2l.try_gpu()
 4 
 5 def get_params():
 6     def _one(shape):
 7         return nd.random.normal(scale=0.01, shape=shape, ctx=ctx)
 8 
 9     def _three():
10         return (_one((num_inputs, num_hiddens)),
11                 _one((num_hiddens, num_hiddens)),
12                 nd.zeros(num_hiddens, ctx=ctx))
13 
14     W_xi, W_hi, b_i = _three()  # 輸入門參數
15     W_xf, W_hf, b_f = _three()  # 遺忘門參數
16     W_xo, W_ho, b_o = _three()  # 輸出門參數
17     W_xc, W_hc, b_c = _three()  # 候選記憶細胞參數
18     # 輸出層參數
19     W_hq = _one((num_hiddens, num_outputs))
20     b_q = nd.zeros(num_outputs, ctx=ctx)
21     # 附上梯度
22     params = [W_xi, W_hi, b_i, W_xf, W_hf, b_f, W_xo, W_ho, b_o, W_xc, W_hc,
23               b_c, W_hq, b_q]
24     for param in params:
25         param.attach_grad()
26     return params
27 
28 
29 # In[19]:
30 
31 
32 def init_lstm_state(batch_size, num_hiddens, ctx):
33     return (nd.zeros(shape=(batch_size, num_hiddens), ctx=ctx),
34             nd.zeros(shape=(batch_size, num_hiddens), ctx=ctx))
View Code

深度循環神經網絡

雙向循環神經網絡


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM