8.4 手动实现 RNN

本章代码:https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson8/rnn_demo.py

这篇文章主要介绍了循环神经网络(Recurrent Neural Network),简称 RNN。

RNN 常用于处理不定长输入,常用于 NLP 以及时间序列的任务,这种数据一半具有前后关系。

RNN 网络结构如下:

上图的数据说明如下:

  • $x_{t}$:时刻 t 的输入,$shape=(1,57)$,表示 (batch_size, feature_dim)。57 表示词向量的长度。

  • $s_{t}$:时刻 t 的状态值,$shape=(1,128)$,表示 (batch_size, hidden_dim)。这个状态值有两个作用:经过一个全连接层得到输出;输入到下一个时刻,影响下一个时刻的状态值。也称为hedden_state,隐藏层状态信息,记录过往时刻的信息。第一个时刻的$s_{t}$会初始化为全 0 的向量。

  • $o_{t}$:时刻 t 的输出,$shape=(1,18)$,表示 (batch_size, classes)

  • $U$:linear 层输入$x_{t}$的权重参数,$shape=(57, 128)$,表示 (feature_dim, hidden_dim)

  • $W$:linear 层状态值$s_{t-1}$的权重参数,$shape=(128,128)$,表示 (hidden_dim, hidden_dim)

  • $V$:linear 层状态值$s_{t}$的权重参数,$shape=(128,18)$,表示 (hidden_dim, classes)

公式如下:

$s_{t}=f\left(x_{t} U+s_{t-1} W \right)$

$o_{t}=\operatorname{softmax}\left(s_{t} V \right)$

下面的例子是使用 RNN 实现人人名分类:输入任意长度姓名(字符串),输出姓名来自哪个国家(18 分类任务)。数据来源于:http://download.pytorch.org/tutorial/data.zip

# Chou(字符串) -> RNN -> Chinese(分类类别)
for string in [C,h,o,u]:
    首先把每个字母转换成 one-hot -> [0,0,...,1,...,0]
    y,h=model([0,0,...,1,...,0], h) # h 就是隐藏层的状态信息

这里没有使用 DataLoader 和 Dataset,而是手动构造了数据集的结构,训练数据使用 dict 存储,包括 18 个元素,每个元素是一个 list,存储了 18 个类别的名字列表。label 存放在一个 list 中。在迭代训练过程如下:

  • 首先随机选择 label 和名字,名字转换为 one-hot 的张量,形状为$[length,1,57]$,其中length表示名字的长度,label 也转换为张量,形状为 1。

  • 初始化隐藏层状态信息。

  • 循环把名字中的每个字符的 one-hot 向量输入到 RNN 中。

  • 最后得到 18 分类的 output。

  • 这里没有使用优化器,而是手动进行反向传播更新参数值。

代码如下:

参考资料

如果你觉得这篇文章对你有帮助,不妨点个赞,让我有更多动力写出好文章。

我的文章会首发在公众号上,欢迎扫码关注我的公众号张贤同学

最后更新于

这有帮助吗?