动手学深度学习8.4 循环神经网络

132 阅读2分钟

这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

本系列更多文章可以看这里:草履虫都能看懂的 白话解析《动手学深度学习》专栏(juejin.cn)

还在更新中…………


多层感知机隐藏层的计算

image.png

上面的图是一个多层感知机模型。

输入X是四维向量,但个隐藏层是五维向量,输出结果是三维向量。

隐藏层H的计算公式为:

H=ϕ(whxX+bh)H = \phi(w_{hx}X+b_{h})
  • 其中[H]5×1[H]_{5 \times 1}[X]4×1[X]_{4 \times 1}[whx]5×4[w_{hx}]_{5 \times 4}[bh]5×1[b_h]_{5\times 1}
  • ϕ\phi为激活函数

上边就是一个普通隐藏层的计算。

那普通多层感知机的输出计算:

O=whqH+boO= w_{hq} H + b_o

循环神经网络隐状态的计算

循环神经网络(Recurrent neural networks, RNNs)是具有隐藏状态的神经网络。

隐状态和隐藏层是不同的 ,隐藏层是多层网络的一部分,隐藏在输入和输出之间的层。隐状态是在时序序列中,后边的内容要依赖于前边的计算结果而进行的计算。

image.png

上图就是带有隐状态的RNN的模型图。

计算方式:

Ht+1=ϕ(wxhXt+1+whhHt+bh) \\ H_{t+1} = \phi(w_{xh}X_{t+1} + w_{hh}H_{t}+b_{h})
  • ϕ\phi为激活函数

在这里加上了一个Ht1whhH_{t-1}w_{hh}这一项,实现了在时序上延续上一步的隐状态。计算过程就是将本部的输入和上一步的隐状态都考虑在内,并将其放入激活函数。

至于输出的计算和普通的MLP没什么区别:

Ot=whoHt+boOt+1=whoHt+1+boO_t = w_{ho} H_t + b_o \\ O_{t+1} = w_{ho} H_{t+1} + b_o

补充 隐状态的计算化简

Ht=ϕ(wxhXt+whhHt1+bh)H_t = \phi(w_{xh}X_t + w_{hh}H_{t-1}+b_{h})

这个公式可以化简为

Ht=ϕ(wh[Xt,Ht1]+bh)H_t = \phi(w_{h}[X_t,H_{t-1}]+b_{h})
  • 其中whw_h是将wxhw_{xh}whhw_{hh}拼接了
  • [Xt,Ht1][X_t,H_{t-1}]也是将XtX_tHt1H_{t-1}拼接了。

这个算一下矩阵计算就知道了。

假设每个输入都是一个三维的one-hot向量,所以每个[Xt]3×1[X_t]_{3\times 1}

假设每个隐藏层都是一个四维向量,那么[Ht]4×1[H_t]_{4\times 1}

这样我们可以知道每个[wxh]4×3[w_{xh}]_{4\times3}[whh]4×4[w_{hh}]_{4\times 4}[bh]4×1[b_h]_{4\times 1}

这样wxhXtw_{xh}X_twhhHt1w_{hh}H_{t-1}计算出来应该是个四维向量。

wxhw_{xh}whhw_{hh}横向拼接之后变为[wh]4×7[w_h]_{4\times 7}XtX_tHt1H_{t-1}竖着拼接之后变为七维向量,计算结果依旧是四维向量。

import torch
from d2l import torch as d2l
X, W_xh = torch.normal(0, 1, (3, 1)), torch.normal(0, 1, (1, 4))
H, W_hh = torch.normal(0, 1, (3, 4)), torch.normal(0, 1, (4, 4))
print(torch.matmul(X, W_xh) + torch.matmul(H, W_hh))
print(torch.matmul(torch.cat((X, H), 1), torch.cat((W_xh, W_hh), 0)))

最后这俩输出应该是一样的,都是

>>
tensor([[ 1.5454, -0.4014, -0.6478, -1.3016],
        [-0.5885,  0.5765,  1.6251,  0.7733],
        [ 0.9793,  0.1511,  1.0349,  0.4170]])