シリーズ記事ディレクトリ
序文
リカレント ニューラル ネットワーク (RNN) は、シーケンス データを処理するためのニューラル ネットワークです。一般的なニューラルネットワークと比較して、配列変化のデータを扱うことができます。たとえば、単語の意味は上記の内容の違いによって異なる意味を持ちますが、RNN はそのような問題をうまく解決できます。
LSTM は RNN の一種であり、RNN の長いシーケンスのトレーニング プロセスにおける勾配の消失と勾配の爆発の問題を解決できます。シーケンスが十分に長い場合、RNN は前のタイム ステップから後のタイム ステップに情報を転送することが困難になります。 LSTM は、長期に依存する情報を学習し、以前のタイム ステップからの情報を記憶できるため、コンテキストと関連付けることができます。
RNN とは異なり、RNN はすべての情報を記憶したいので、それが役立つかどうかは気にしません. LSTM は、スクリーニング機能として機能するメモリセルを設計し、選択して記憶するために使用されるメモリを選択する機能を備えています。重要な情報。ノイズと重要でない情報をフィルタリングしてメモリ負荷を軽減します。その外観により、グラデーションの歪みの問題が解決されます。さらに、RNN の収束速度は通常の RNN よりもはるかに高速です。
LSTM の中核となる概念は、セル状態と「ゲート」構造です。セルの状態は情報伝達の経路に相当し、シリアル接続では情報を伝達することができます。ネットワークの「メモリ」と考えることができます。理論的には、セルの状態はシーケンス処理全体を通して関連情報を伝えることができます。
GRU (Gate Recurrent Unit) はリカレント ニューラル ネットワーク (RNN) の一種で、長期記憶ができない RNN の問題やバックプロパゲーションの勾配を解決することができ、LSTM に似ていますが、LSTM よりもシンプルで簡単です。訓練する。LSTM と非常によく似ていますが、LSTM と比較すると、GRU はセル状態を削除し、隠し状態を使用して情報を送信します。これには、更新ゲートとリセット ゲートの 2 つのゲートのみが含まれています。
GRU は LSTM の変形であり、バックプロパゲーションにおける長期記憶や勾配などの問題を解決することも提案されています。多くの場合、GRU と LSTM のパフォーマンスはほぼ同じですが、GRU の計算の方が単純で実装が簡単です。
1.LSTMモデルの構造
RNN構造
LSTMの構造
LSTM モデルは RNN モデルと比較されます。
- XtX_tバツた位置のモデル構造の複雑さは大きく異なります
- LSTM には 2 つの出力がありますが、RNN には 1 つの出力しかありません
X t X_tを入れますバツた別に取り出して
CCC はメモリセルを意味し、式は Cell State
hhh は状態
XXX は新しいコンテンツを意味します
σ σσはゲート単位
ft f_tfたForget Gate、式は Forget Gate
it i_tです私た入力ゲート、式は入力ゲート
ot o_tです。ああた出力ゲート、式は出力ゲートです
vs.フィート f_tfた、それは私た、オットオットああたそれらの法則は σ ( W × X t + W × ht − 1 + b ) σ(W×X_t+W×{h_{t-1}}+b) であることがわかります。s ( W×バツた+W×ht − 1+b )タイプ。上記のモデル構造図によれば、 ( X t , ht − 1 ) (X_t,h{_t-1}) であることがわかります。( Xた、hた−1 )は σ ゲートに入力されるため、3 つのゲートの X 値と h 値は同じになります。( X t , ht − 1 ) (X_t,h{_t-1}) を介して( Xた、hた−1 ) 4つの値ft f_tを計算可能fた、それは私た,C ~ \widetilde{C}C それと、それはああた。タンタンどこt anhは活性化関数であり、その出力ベクトルの各要素は -1~1,W , b W,bわ、bは各ゲート ニューロンのパラメーターであり、トレーニング プロセス中に学習されます。
- Forget Gate : どの情報を破棄するか保持するかを決定します。以前の隠し状態からの情報と現在の入力情報が同時にシグモイド関数に渡され、出力値は 0 から 1 の間になります。0 に近いほど破棄する必要があることを意味し、1 に近いほど破棄することを意味します。それは保持されるべきだということ。ft f_tが取得されますfた入力C t − 1 C_{t-1}を使用Ct − 1乗算、つまりベクトルの乗算です。
- 入力ゲート: 入力ゲートはセルの状態を更新するために使用されます。まず、前の層の隠れ状態の情報と現在の入力の情報がシグモイド関数に渡されます。値を 0 ~ 1 の間で調整して、更新する情報を決定します。0 は重要ではないことを意味し、1 は重要であることを意味します。私た価値。次に、前の層の隠れ状態の情報と現在の入力の情報を Tanh 関数に渡して、新しい候補値ベクトルを作成し、 C ~ \ widetilde{C}を取得する必要があります。C 価値。最後に、シグモイドの出力値とtanh it i_tの出力値私たそしてC ~ \widetilde{C}C 乗算、つまりベクトル乗算。sigmoid の出力値によって、tanh の出力値のどの情報が重要で、保存する必要があるかが決まります。保持する必要がある情報は、フォーゲットゲートによって得られた出力に追加され、最終的に新しいメモリセルC t = ( ft ⨀ C t − 1 ) + ( it ⨀ C ~ ) {C_t} = ({f_t }⨀ {C_{t-1}})+({i_t}⨀{\widetilde{C}})Cた=( fた⨀Ct − 1)+(私はた⨀C )
- 出力ゲート: 出力ゲートは、前の入力の情報を含む次の隠れ状態の値を決定するために使用されます。まず、前の隠れ状態と現在の入力をシグモイド関数に渡し、次に新しく取得したセルの状態を Tanh 関数に渡します。最後に、tanh の出力と sigmoid の出力を乗算する (ベクトル乗算) ことで、隠れ状態が保持する情報が決定されます。次に、非表示状態を現在のセルの出力として使用し、新しいセルの状態と新しい非表示状態ht h_tを使用します。hた次のタイムステップに移ります。つまり、新たに得られたメモリセルC t {C_t}Cた重みの計算に Tanh を渡しますmt = Tanh ( C t ) {m_t} = Tanh({C_t})メートルた=私(年上)た)、その後はot o_tああた体重に応じてmt{m_t}メートルた新しい隠れ状態を計算します。ht = ot ⨀ mt {h_t} = {o_t} ⨀{m_t}hた=ああた⨀メートルた、どの部分を出力する必要があるか、どの部分が必要な答えであるかを制御するためです。
2. GRUモデルの構造
数式:
zt = σ ( W xz × X t + W hz × ht − 1 + bz ) z_t = σ(W_{xz}×X_t+W_{hz}×{h_{t-1}}+b_z)zた=s ( Wxz _×バツた+WHz _×ht − 1+bz)
rt = σ ( W xr × X t + W hr × ht − 1 + br ) r_t = σ(W_{xr}×X_t+W_{hr}×{h_{t-1}}+b_r)rた=s ( W× r×バツた+W時間_×ht − 1+br)
h ~ t = Tanh ( W xh × X t + W hh × ( rt ⨀ ht − 1 ) + bh ) \widetilde{h}_t = Tanh(W_{xh}×X_t+W_{hh}×(r_t⨀) {h_{t-1}})+b_h)h
た=英語( W_ _×時間×バツた+Wふーん×( rた⨀ht − 1)+bふ)
ht = ( 1 − zt ) ⨀ ht − 1 + zt ⨀ h ~ t h_t = (1-z_t)⨀h_{t-1}+z_t⨀\widetilde{h}_thた=( 1−zた)⨀ht − 1+zた⨀h
た
GRU には 2 つのゲートしかありません。LSTM の入力ゲートと忘却ゲートの組み合わせは更新ゲートと呼ばれます。式はzt z_tです。zた、一方、リセットゲートと呼ばれる別の式はrt r_tです。rた。2 つのゲートの式も σ ( W × X t + W × ht − 1 + b ) σ(W×X_t+W×{h_{t-1}}+b) であることがわかります
。s ( W×バツた+W×ht − 1+b )と入力しますが、ここではh ~ t \widetilde{h}_t と入力します。h
たおよび LSTM のC ~ \widetilde{C}C
異なります。LSTM のC ~ \widetilde{C}C
ht − 1 , X t h_{t-1},X_tによるht − 1、バツたGRU のh ~ t \widetilde{h}_tで構成されます。h
たは( rt ⨀ ht − 1 ) , X t (r_t⨀h_{t-1}),X_tで与えられます。(rた⨀ht − 1)、バツたからなる。タンタンどこt anhは活性化関数であり、その出力ベクトルの各要素は -1~1,W , b W,bわ、bは各ゲート ニューロンのパラメーターであり、トレーニング プロセス中に学習されます。
- ゲートを更新zt z_tzた: アテンションの役割を果たすメカニズム。前の瞬間の状態情報が現在の状態にどの程度反映されるかを制御するために使用されます。つまり、更新ゲートは、モデルがどれだけの過去の情報を未来に渡すかを決定するのに役立ちます。 、簡単に言えば、メモリを更新するために使用されます。
- リセットゲートrt r_trた: 忘れることに役割を果たし、新しい入力情報を以前の記憶と組み合わせる方法を決定し、過去の情報をどれだけ忘れるかを制御し、隠れた状態に将来の予測に関係のない情報を忘れさせるメカニズム。よりタイトな表現の構築。
3. GRU と LSTM の比較
アドバンテージ:
- LSTM と比較すると、GRU は出力ゲートが少なく、パラメータも LSTM よりも少なく、計算量も LSTM より少なく、よりシンプルで実装が容易で、モデルをより速くトレーニングできます。
- GRU には 2 つのゲートしかありませんが、LSTM には 3 つのゲートがあり、GRU の方がパラメータの制御と調整が容易です。
欠点:
- GRU は LSTM ほど強力なメモリ容量を持っていません。長期的な依存関係の問題に関しては、LSTM は簡単に無限にカウントできるのに対し、GRU はそれができないため、厳密には GRU よりも強力です。これが、LSTM が学習できる簡単な言語を GRU が学習できない理由です。
- GRU には LSTM ほど多くのパラメータがないため、アンダーフィッティングが発生する傾向があります。
4. コードの実装
1.GRUコード
import torch
from torch import nn
from d2l import torch as d2l
batch_size, num_steps = 32, 35
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)
def get_params(vocab_size, num_hiddens, device):
num_inputs = num_outputs = vocab_size
def normal(shape):
return torch.randn(size=shape, device=device)*0.01
def three():
# torch.normal:返回一个张量,包含从给定参数num_inputs, num_hiddens的离散正态分布中抽取随机数
# torch.zeros:创建num_hiddens大小的维度,里面元素全部填充为0device输出张量的设备
return (normal((num_inputs, num_hiddens)),
normal((num_hiddens, num_hiddens)),
torch.zeros(num_hiddens, device=device))
# 初始化模型参数,定义更新门z_t、重置门r_t和隐藏态h_t公式的训练参数
# 通过def three()给这些参数定义随机数和和0矩阵
W_xz, W_hz, b_z = three() # 更新门参数
W_xr, W_hr, b_r = three() # 重置门参数
W_xh, W_hh, b_h = three() # 候选隐状态参数
# 输出层参数
W_hq = normal((num_hiddens, num_outputs))
b_q = torch.zeros(num_outputs, device=device)
# requires_grad:附加梯度,设置参数为True,程序将会追踪所有对于该张量的操作
# 当完成计算后通过调用 .backward(),自动计算所有的梯度, 这个张量的所有梯度将会自动积累到 .grad 属性。
params = [W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q]
for param in params:
param.requires_grad_(True)
return params
# 定义隐状态的初始化函数,返回一个形状为(批量大小,隐藏单元个数)的张量,张量的值全部为零
def init_gru_state(batch_size, num_hiddens, device):
return (torch.zeros((batch_size, num_hiddens), device=device),)
def gru(inputs, state, params):
# 使用的是有梯度的训练参数
W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q = params
H, = state
outputs = []
# 公式的复现
# torch.sigmoid将样本值映射到0到1之间。
for X in inputs:
Z = torch.sigmoid((X @ W_xz) + (H @ W_hz) + b_z)
R = torch.sigmoid((X @ W_xr) + (H @ W_hr) + b_r)
H_tilda = torch.tanh((X @ W_xh) + ((R * H) @ W_hh) + b_h)
H = Z * H + (1 - Z) * H_tilda
Y = H @ W_hq + b_q
outputs.append(Y)
# torch.cat:将两个张量按指定维度拼接在一起
return torch.cat(outputs, dim=0), (H,)
vocab_size, num_hiddens, device = len(vocab), 256, d2l.try_gpu()
num_epochs, lr = 500, 1
model = d2l.RNNModelScratch(len(vocab), num_hiddens, device, get_params,
init_gru_state, gru)
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)