1. 参考资料
强烈推荐B站刘二大人的《PyTorch深度学习实践》非常适合小白入门,墙裂推荐。
2. 什么情况用RNN?
- RNN用来处理有明显时间序列信息。下图是传统的D(dense or depp)NN结构图,其中[x1, x2, …x8]是一个样本中的8个特征作为输出,经过计算生成y_hat。
- 而RNN的处理对象是具有明显时间序列信息的样本。比如气象资料就是是典型的时间序列数据。如下表,我们已知前三个时次的气象数据和是否下雨的资料,需要知道第四个时次是否下雨,每个时次的气象数据都受到上些时次的影响,是连续的信息。
每个x1中有三个特征,传统的方法是把{x1, x2, x3}连接成为一个维度为3(时间长度)*3(特征个数)=9的长向量,然后通过DNN全连接的方式进行训练计算y_hat,但明显这种方法在时间序列较长,气象要素(维度)较多时计算非常耗时耗力。
时间 | 气温 | 气压 | 雨 |
---|
1(x1) | 25 | 1030 | 0 | 2 (x2) | 24 | 1029 | 1 | 3 (x3) | 23 | 1031 | 1 | 4 | 22 | 1027 | ? |
RNN 就是用来处理这类有明显时间序列关系的最好的方式。
3. 什么是RNN cell?
-
重点:处理有明显时间序列信息时,能够实现权重共享,比DNN全连接层权重大大减少。 下图中的RNN cell 就实现了权重共享。x1(第一个时刻)的输入信息通过RNN cell(线性层 wx+b)计算可以得到h1(隐藏层),h1通过参与x2的RNN cell的计算生成h2,依次类推,这样使得每一个时刻xt都参与下一个时刻xt+1的计算,使得各个层连接起来。x1时刻需要给一个初始化的h0, 一般是直接给一个长度和h1等相同的0向量。 图中每个RNN cell线性层都是同一个,实现了权重共享。 这个过程用简化的非正规的代码来写,就是: h0 = 0 for x in X: h1 = linear( x1, h0) h2 = linear(x2, h1) 大概就是这个意思。 -
那么h1是怎么参与x2的线性层计算的呢?最重要的是理清楚各种维度信息! 定义第t个时刻的气象数据xt有5个特征(包含气温,气压,水汽含量,U, V,此处便于个例理解忽略了空间信息),也就是: xt.shape = input_size = 5, hidden_size = 8,(自己定义) 因为输出的h.shape =8 ,所以输入的xt(input_size=5)经过线性层计算(wx+b)需要得到长度为8的向量,这样要求权重Wih(计算输入x的权重)的维度为一个8行5列的向量,所以Wih.shape = (hidden_size, input_size)= (8, 5)。 ht-1.shape = (hidden_size), 是一个长度为8的向量,为了便于和x1结合,它经过线性层的变换,也需要输出一个长度为8的向量,这样要求计算h的权重Whh.shape = (hidden_size, hidden_size)= (8, 8),是一个8*8的向量。 ht-1通过线性层RNN cell计算得出的长度为8的向量和xt经过线性层变换得到的长度为8的向量相加,再经过激活函数tanh,共同生成了xt时刻下的ht,维度为8(hidden_size)。 也就是一个线性层RNN cell中有两个W和b。
4. 如何在pytorch中建立RNN cell
不得不说,刘老师讲的太详细了。 建立RNN cell 用torch.nn.RNN,其中主要的输入变量为input_size, hidden_size,和num_layers,前两个都好理解,num_layer指的是RNN cell在垂直方向上有多少层,也就是xt经过多少次线性层才能得到h1. 之前的例子中num_layers都是1,也就是垂直方向上只有1个层。 RNN cell 建立好后,out, hidden = cell (inputs, hidden)中 inputs是{x1…xn}数据,维度为(Nt,batch_size, input_size),hidden是h0, 输出的话out是{h1, … hn},维度为(num_layers, batch_size, hidden_size),hidden输出的是hn。这样就不用对每一个时次进行遍历循环,比torch.nn.RNNcell用起来方便啦。 这样RNN的建立和使用就非常清晰,其实不麻烦,就是搞清楚维度问题。 记录!
|