一、什么是RNN模型
循环神经网络,一般以序列数据为输入,通过网络内部的结构有效捕捉
二、RNN单层网络结构
1.句子中的词全部处理完
2.循环次数达到我们的要求
只有一个神经元:对标代码理解就是一个result。
展开:

RNN的循环机制使模型隐层上一时间产生的结果,能够作为当下时间步输入的一部分(当下时间步的输入除了正常的输入外还包括上一步的隐藏层输出)对当下时间步的输出产出影响。
RNN模型的作用
是处理序列数据 ,并捕捉数据中的时间依赖关系。
广泛应用于NLP领域的各项任务,如文本分类、情感分析、意图识别、机器翻译等。
三、RNN模型的分类
按输入和输出的结构进行分类
① N vs N - RNN (理解为对联)

应用场景 -> 词性标注(POS Tagging):为每个单词标注词性
② N vs 1 - RNN (文本分类 -> 对N个句子 进行分类)
应用场景:
- 情感分析 :根据一段文本判断情感倾向。
- 输入:
["I", "love", "programming"] - 输出:
"Positive"
- 输入:
- 文本分类:将一段文本分类到某个类别。

③ 1 vs N - RNN (文生成图片、图片生成文字. eg:一句话 生成多张图片)
应用场景:
- 文本生成 :根据一个初始词生成一段文本。
- 输入:
"I" - 输出:
["I", "love", "programming"]
- 输入:
- 图像描述生成 :根据一张图像生成描述文本。
- 输入:
图像特征 - 输出:
["A", "dog", "is", "running"]
- 输入:

④ N vs M - RNN (语义理解、文本摘要。eg: 一篇文章->得出一篇摘要)
它由编码器和解码器两部分组成,两者的内部结构都是某类RNN,它也被称为seq2seq架构
应用场景:
- 机器翻译 :将一种语言的句子翻译成另一种语言。
- 输入:
["I", "love", "programming"](英文) - 输出:
["我", "喜欢", "编程"](中文)
- 输入:
- 文本摘要 :将长文本压缩为短文本。
- 输入:
["The", "quick", "brown", "fox", ...] - 输出:
["Quick", "fox", "story"]
- 输入:


按RNN内部构造(神经元内部)进行分类:
传统 RNN
LSTM
BI-LSTM
GRU
BI-GRU
四、RNN内部结构
图解:

公式:
激活函数tanh的作用:用于帮助调节流经网络的值,tanh函数将值压缩在-1和1之间。
分析:
单层:

OUT(t-1) 是 第1个时间步的输出

RNN的输出可以是y向量和最后一个时刻隐藏层的输出
多层:
output 记录的是 最后一层 在每个时间步的隐藏状态
hidden 记录的是每一层 在 最后一个时间步的隐藏状态
不管 RNN 有多少层,最后时刻
++输出层 output 的最后一个值 = 隐藏层 hidden 的最后一个值++

五、RNN代码使用
注意:下面示例是 RNN的batch_first = True 的情况。默认是False
False 时
x = torch.randn(size=(4, 3, 5)) #(seq_len, batch_size, input_size)
True 时
x = torch.randn(size=(3, 4, 5)) #(batch_size, seq_len, input_size)

python
import torch.nn as nn
import torch
def rnn_init():
"""
定义数据
batch_size: 3个句子,
seq_len: 每个句子 4个词 (时间步数)
input_size: 每个词的向量维度 5
"""
x = torch.randn(size=(3, 4, 5)) #(batch_size, seq_len, input_size)
"""
定义ho 初始值 全0
num_layers: RNN层数 默认1 层
batch_size: 3 个句子
hidden_size : 6 个隐藏层维度
"""
h0 = torch.zeros(size=(1, 3, 6)) #(num_layers, batch_size, hidden_size)
rnn = nn.RNN(input_size=5, #输入数据的向量维度,也就是词的向量维度 embed_dim
hidden_size=6, #隐藏状态向量维度
num_layers=1, #隐藏层RNN的层数
batch_first=True) #输入/输出张量的0轴是否为batch轴,默认为False, 设为True时,输入和输出张量的0轴为batch轴
output, hn = rnn(x, h0)
"""
输出 output 的形状是 (batch_size, seq_len, hidden_size)
隐藏状态 hn 的形状是 (num_layers, batch_size, hidden_size)
"""
print(f'{output.shape} \n')
print(f'{hn.shape} \n')
print(f'output last: {output[...,-1,:][-1]} \n')
print(f'hn last: {hn[...,-1,:][-1]} \n')
print(f'输出层的最后一个值 output last 和 隐藏层的最后一个值 相同h0 last')
if __name__ == '__main__':
rnn_init()