![48db0107e7838b8a89a421db8cd20b4b.png](https://i-blog.csdnimg.cn/blog_migrate/f8671676819e6c4fee7e9247f7770312.jpeg)
循环神经网络(Recurrent Neural Network,RNN)是一类具有短期记忆能力的神经网络。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,也就是说隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。简单来说,设计 RNN 就是为了处理序列数据。如果说 CNN 是对人类视觉的仿真,那 RNN 不妨先看作是对人类记忆能力的模拟。
为什么需要 RNN? 和 CNN 的主要区别?
- CNN 相当于人类视觉,是没有记忆能力的,没有办法根据以前的记忆来处理新任务。而 RNN 是基于人的记忆的想法,期望网络能够机主前面出现的特征,根据特征完成下游任务。
- CNN 需要固定长度的输入、输出,RNN 的输入和输出可以是不定长且不等长的
- CNN 只有 one-to-one 一种结构,而 RNN 有多种结构。
结构组成
一个简单 RNN 由三个部分组成,输入层、隐藏层,输出层(废话)如果我们把上面的图展开,循环神经网络也可以画成下面这个样子:
![2f7db28f8b31141b45acb3e5ec5c3f35.png](https://i-blog.csdnimg.cn/blog_migrate/01da8481a51a37fca3e4748423869bc3.jpeg)
为什么循环神经网络可以往前看任意多个输入值呢?
看啊这个是输出层 o和隐藏层 s 的计算公式
如果把公式 2 一直往公式 1 里带,则有:
记忆能力
该模型具有一定的记忆能力,能够按时序依次处理任意长度的信息。前面的输入对未来产生影响。什么意思呢下图所示。当我们将“ What time is it ?" 每个词进入神经网络后都会对下一个词产生影响,
![bd2c1413ec6ddf4dcd4b4bfde4ea2261.png](https://i-blog.csdnimg.cn/blog_migrate/57664b531a6db17b35c9ec8906a62322.jpeg)
缺点:梯度消失和梯度爆炸
![b307f0581d3af722bc543186ac95c577.png](https://i-blog.csdnimg.cn/blog_migrate/7f23dfd4d8454c1b5852f5863c4faaad.png)
通过上面的例子,我们已经发现,短期的记忆影响较大(如橙色区域),但是长期的记忆影响就很小(如黑色和绿色区域),这就是 RNN 存在的短期记忆问题。
莫烦 Python 这里讲解的非常生动形象:
‘我今天要做红烧排骨, 首先要准备排骨, 然后…., 最后美味的一道菜就出锅了’。现在请 RNN 来分析, 我今天做的到底是什么菜呢. RNN可能会给出“辣子鸡”这个答案. 由于判断失误, RNN就要开始学习 这个长序列 X 和 ‘红烧排骨’ 的关系 , 而RNN需要的关键信息 ”红烧排骨”却出现在句子开头。
![37caba9fa8bf48cfed44599bf2dd5549.png](https://i-blog.csdnimg.cn/blog_migrate/43a3c274a1eb275dbdf28f24161a6699.jpeg)
![aa5215a06529f298d3f483a17f75c205.png](https://i-blog.csdnimg.cn/blog_migrate/b92b20a4bfd0bdb4df1df0e342378efa.jpeg)
红烧排骨这个信息原的记忆要进过长途跋涉才能抵达最后一个时间点. 然后我们得到误差, 而且在 反向传递 得到的误差的时候, 他在每一步都会 乘以一个自己的参数 W. 如果这个 W 是一个小于1 的数, 比如0.9. 这个0.9 不断乘以误差, 误差传到初始时间点也会是一个接近于零的数, 所以对于初始时刻, 误差相当于就消失了. 我们把这个问题叫做梯度消失或者梯度弥散 Gradient vanishing. 反之如果 W 是一个大于1 的数, 比如1.1 不断累乘, 则到最后变成了无穷大的数, RNN被这无穷大的数撑死了, 这种情况我们叫做梯度爆炸, 这就是普通 RNN 没有办法回忆起久远记忆的原因.
在此感谢 @莫烦 前辈关于机器学习机器学习基础知识的讲解,让晚辈能够迅速成长,知识分享是人的一种高贵品质。我由衷感谢您!
基础模型的 PyTorch 实现
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(RNN, self).__init__()
self.input_size = input_size
self.hidden_size = hidden_size
self.output_size = output_size
self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
self.i2o = nn.Linear(input_size + hidden_size, output_size)
def forward(self, input, hidden):
# 将input和之前的网络中的隐藏层参数合并。
combined = torch.cat((input, hidden), 1)
hidden = self.i2h(combined) # 计算隐藏层参数
output = self.i2o(combined) # 计算网络输出的结果
return output, hidden
def init_hidden(self):
# 初始化隐藏层参数hidden
return torch.zeros(1, self.hidden_size)
参考资料
https://morvanzhou.github.io/tutorials/machine-learning/ML-intro/2-4-LSTM/
https://easyai.tech/ai-definition/lstm/
代码地址:
https://github.com/zy1996code/nlp_basic_model/blob/master/rnn.py
欢迎 star!