当前位置: 首页 > news >正文

RNN循环神经网络

一.RNN简介

1.RNN介绍

循环神经网络(Recurrent Neural Network, RNN)是一种专门处理序列数据的神经网络。与传统的前馈神经网络不同,RNN具有循环结构,能够处理和记住前面时间步的信息,使其特别适用于时间序列数据或有时序依赖的任务。

我们要明确什么是序列数据,时间序列数据是指在不同时间点上收集到的数据,这类数据反映了某一事物、现象等随时间的变化状态或程度。这是时间序列数据的定义,当然这里也可以不是时间,比如文字序列,但总归序列数据有一个特点——后面的数据跟前面的数据有关系

2.RNN的应用

l自然语言处理(NLP:文本生成、语言建模、机器翻译、情感分析等。
l时间序列预测:股市预测、气象预测、传感器数据分析等。
l语音识别:将语音信号转换为文字。
l音乐生成:通过学习音乐的时序模式来生成新乐曲。

3.自然语言处理

自然语言处理(Nature language Processing, NLP)研究的主要是通过计算机算法来理解自然语言。对于自然语言来说,处理的数据主要就是人类的语言,例如:汉语、英语、法语等,该类型的数据不像我们前面接触过的结构化数据、或者图像数据可以很方便的进行数值化。

二.词嵌入层

词嵌入层的作用就是将文本转换为向量。

词嵌入层在 RNN 中的作用有输入表示降低维度捕捉语义相似性

词嵌入层首先会根据输入的词的数量构建一个词向量矩阵,例如: 我们有 100 个词,每个词希望转换成 128 维度的向量,那么构建的矩阵形状即为: 100*128,输入的每个词都对应了一个该矩阵中的一个向量。

                                

词嵌入流程:
l初始化词向量:词嵌入层的初始词向量通常会使用随机初始化或者通过加载预训练的词向量(如Word2VecGloVe)进行初始化。
l输入索引:每个单词在词汇表中都有一个唯一的索引。输入文本(例如一个句子)会先被分词,然后每个单词会被转换为相应的索引。
l查找词向量:词嵌入层将这些单词索引映射为对应的词向量。这些词向量是一个低维稠密向量,表示该词的语义。
l输入到RNN:这些词向量作为RNN的输入,RNN处理它们并根据上下文生成一个序列的输出。

其步骤如下:

1.先将语料进行分词,构建词与索引的映射,我们可以把这个映射叫做词表,词表中每个词都对应了一个唯一的索引
2.然后使用 nn.Embedding 构建词嵌入矩阵,词索引对应的向量即为该词对应的数值化后的向量表示。

三.循环网络层

1.RNN的网络结构

RNNRecurrent Neural Network)是一种专为处理序列数据设计的神经网络结构,其核心特点是利用循环连接(隐藏层的输出反馈到输入)来捕捉时间或顺序上的动态信息。

例如: "我爱你", 这串文本就是具有序列关系的,"" 需要在 "" 之后,"" 需要在 "" 之后, 如果颠倒了顺序,那么可能就会表达不同的意思。

为了表示出数据的序列关系,需要使用循环神经网络(Recurrent Nearal Networks, RNN) 来对数据进行建模,RNN 是一个作用于处理带有序列特点的样本数据。

一般单层神经网络:

2.RNN模型的作用

RNN的核心作用是建模序列数据的时序依赖关系,适用于需要上下文信息的任务。尽管其基础版本存在局限性,但通过LSTM/GRU等改进和结合注意力机制,RNN家族在序列建模中仍有重要地位。如文本分类, 意图识别, 机器翻译等.

这里举一个例子方便理解:

第一步: 用户输入了"What time is it ?", 我们首先需要对它进行基本的分词, 因为RNN是按照顺序工作的, 每次只接收一个单词进行处理.

第二步: 首先将单词"What"输送给RNN, 它将产生一个输出O1.

第三步: 继续将单词"time"输送给RNN, 但此时RNN不仅仅利用"time"来产生输出O2, 还会使用来自上一层隐层输出O1作为输入信息.

第四步: 重复这样的步骤, 直到处理完所有的单词

第五步: 最后,将最终的隐层输出O5进行处理来解析用户意图

3.RNN网络原理

                                         

计算当前时刻的输出:网络的输出yt是当前时刻的隐藏状态经过一个线性变换得到的。

上述公式中:

1.yt 是当前时刻的输出(通常是一个向量,表示当前时刻的预测值,RNN层的预测值)
2.ht 是当前时刻的隐藏状态
3.Why 是从隐藏状态到输出的权重矩阵
4.by 是输出层的偏置项

词汇表映射:

输出yt是一个向量,该向量经过全连接层后输出得到最终预测结果YpredYpred中每个元素代表当前时刻生成词汇表中某个词的得分(或概率,通过激活函数如softmax)。词汇表有多少个词,Ypred就有多少个元素值,最大元素值对应的词就是当前时刻预测生成的词。

4.RNN:API的使用

参数意义是:

1.input_size:输入数据的维度,一般设为词向量的维度;
2.hidden_size:隐藏层h的维度,也是当前层神经元的输出维度;
3.num_layers: 隐藏层h的层数,默认为1.

RNN实例化就可以将数据送入进行处理。

输入数据和输出结果

RNN实例化就可以将数据送入其中进行处理,处理的方式如下所示:

n输入数据:输入主要包括词嵌入的x 、初始的隐藏层h0
px的表示形式为[seq_len, batch, input_size],即[句子的长度,batch的大小,词向量的维度]
ph0的表示形式为[num_layers, batch, hidden_size],即[隐藏层的层数,batch的大,隐藏层h的维数]
n输出结果:主要包括输出结果output,最后一层的hn
poutput的表示形式与输入x类似,为[seq_len, batch, hidden_size],即[句子的长度,batch的大小,输出向量的维度]
phn的表示形式与输入h0一样,为[num_layers, batch, hidden_size],即[隐藏层的层数,batch的大,隐藏层h的维度]

RNN层的代码实现:

import torchx = torch.randn(size=[5,32,128])
print(x)h0 = torch.zeros(size=[1,32,256])
print(h0)rnn = torch.nn.RNN(input_size=128,hidden_size=256,num_layers=1)
print(rnn)y,h1 = rnn(x,h0)
print(h1)
print(y)

接下来介绍一个案例来应用RNN

文本生成任务是一种常见的自然语言处理任务,输入一个开始词能够预测出后面的词序列。本案例将会使用循环神经网络来实现周杰伦歌词生成任务。

整体流程是:

l获取文本数据
l分词,并进行去重
l构建词表
import time
import jieba
import torch.utils.data
import torch# TODO 1.构建词表
def build_vocab():# 分别储存所有杭分此列表和去重后每个分词all_words = []unique_words = []for line in open(r'/data/jaychou_lyrics.txt', mode='r', encoding='utf-8'):words = jieba.lcut(line)all_words.append(words)for word in words:if word not in unique_words:unique_words.append(word)# 去重后单词数量unique_words_cnt = len(unique_words)# 构建小词表: 每个单词对应一个索引unique_words_to_idx = {word: idx for idx, word in enumerate(unique_words)}print(f'词表大小:{unique_words_cnt}')all_words_idx = []for words in all_words:temp = []for word in words:temp.append(unique_words_to_idx[word])temp.append(unique_words_to_idx[' '])all_words_idx.extend(temp)return unique_words, unique_words_cnt, unique_words_to_idx, all_words_idx# TODO 2.构建数据集
class MyDataset(torch.utils.data.Dataset):def __init__(self, all_words_idx, number_chars):self.all_words_idx = all_words_idx# 属性2:每个句子的长度self.number_chars = number_charsself.all_words_idx_cnt = len(self.all_words_idx)self.number = self.all_words_idx_cnt // self.number_charsdef __len__(self):return self.numberdef __getitem__(self, index):start = min(max(0, index), self.all_words_idx_cnt - 1 - self.number_chars)end = start + self.number_charsx = self.all_words_idx[start:end]y = self.all_words_idx[start + 1:end + 1]x = torch.tensor(x)y = torch.tensor(y)return x, y# TODO 3.构建神经网络模型class MyModel(torch.nn.Module):# 重写__init__方法def __init__(self, unique_words_cnt):# 调用父类方法super().__init__()# todo 定义网络结构# 创建一个嵌入层self.embedding = torch.nn.Embedding(num_embeddings=unique_words_cnt, embedding_dim=128)# 创建一个rnn层self.rnn = torch.nn.RNN(input_size=128, hidden_size=256, num_layers=1)# 创建一个全连接层self.out = torch.nn.Linear(in_features=256, out_features=unique_words_cnt)# 重写forward方法def forward(self, x, h):# todo 获取嵌入层输出ebd_x = self.embedding(x)# todo 获取rnn层输出# TODO ebd_x[batch_size, seq_len, input_size]->(seq_len,batch_size, hidden_size)rnn_out, h = self.rnn(ebd_x.transpose(0, 1), h)# todo 全连接层: 只能处理2维张量,此处需要把rnn_out转成2维张量out = self.out(rnn_out.reshape(-1, rnn_out.shape[-1]))# todo 返回结果return out, h# 定义初始化隐藏状态方法def init_hidden(self, batch_size):# 创建初始隐藏状态return torch.zeros(size=[1, batch_size, 256])# TODO 4.模型训练
def train_model(unique_word_to_idx, train_loader, model, epochs, batch_size):# 1.获取数据(本次已经传参)# 2.获取模型(本次已经传参)# 3.创建损失函数对象loss_fn = torch.nn.CrossEntropyLoss()# 4.创建优化器对象optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)# 5.训练模型for epoch in range(epochs):total_loss, sample_cnt, start = 0.0, 0, time.time()for x, y in train_loader:# todo 正(前)向传播:从输入到输出: 预测值和损失值# 先获取隐藏状态h = model.init_hidden(x.size(0))# 然后预测获取预测值和隐藏状态y_pred, h = model(x, h)# 计算损失值loss = loss_fn(y_pred, y.transpose(0, 1).reshape(-1))# 累加损失值和批次数量total_loss += loss.item()sample_cnt += 1# todo 反向传播:从输出到输入: 梯度计算和参数更新optimizer.zero_grad()loss.backward()optimizer.step()# 走到此处,说明一轮结束: 计算每轮损失值epoch_loss = total_loss / sample_cntprint(f"第{epoch + 1}轮,运行时间{time.time() - start:.2f}秒,损失值为:{epoch_loss:.2f}")# 6.保存训练好的模型参数字典torch.save(model.state_dict(), 'model')# TODO 5.模型预测
def eval_model(start_word, length, unique_words_cnt, unique_words, unique_word_to_idx):# 1.获取起始词对应的索引,并封装成列表word_idx = unique_word_to_idx[start_word]words = [word_idx]# 2.创建新模型model = MyModel(unique_words_cnt)model.load_state_dict(torch.load('model'))# 3.模型预测# 提前获取隐藏状态h = model.init_hidden(batch_size=1)for i in range(length):# 模型预测ypred, h = model(torch.tensor([[word_idx]]), h)# 获取预测值索引word_idx = torch.argmax(ypred).item()words.append(word_idx)# print(words)# 4.将索引列表转成词列表words = [unique_words[idx] for idx in words]print(''.join(words))# 程序主入口
if __name__ == '__main__':# TODO 1.构建词表unique_words, unique_words_cnt, unique_word_to_idx, all_words_idx = build_vocab()# TODO 2.构建数据集number_chars = 32dataset = MyDataset(all_words_idx, number_chars)# print(f'数据集大小: {len(dataset)}')  # 自动调用__len__方法# print(dataset[0])  # 自动调用了__getitem__方法: (tensor([ 0,  1,  2,  3, 40]), tensor([ 1,  2,  3, 40,  0]))batch_size = 5train_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)# TODO 3.构建神经网络模型model = MyModel(unique_words_cnt)print(model)# TODO 4.模型训练epochs = 10# train_model(unique_word_to_idx, train_loader, model, epochs, batch_size)# TODO 5.模型预测# 注意: start_word必须在词表中有,否则报错start_word = '星星'length = 99eval_model(start_word, length, unique_words_cnt, unique_words, unique_word_to_idx)

train后的结果为:

http://www.dtcms.com/a/281913.html

相关文章:

  • 面试问题:
  • STM32硬件I2C的注意事项
  • CCK-8 实验详解及 Graphpad 作图指南
  • 阿里云 RabbitMQ 可观测性最佳实践
  • 恶补DSP:1.F28335的时钟系统
  • Swarm Network 选择 Walrus 实现可验证 AI
  • 网络安全(初级)(Python实现sql自动化布尔盲注)
  • JWT基础详解
  • 【云原生网络】Istio基础篇
  • 使用 CrewAI 进行股票分析:自动化投资决策的新途径
  • Capture One24下载与保姆级安装教程!
  • 解决“Windows 无法启动服务”问题指南
  • 数据库询问RAG框架Vanna的总体架构
  • 线上崩溃复盘
  • Unity Android Logcat插件 输出日志中文乱码解决
  • FPGA基础 -- Verilog 访问寄存器数组的指定位示例
  • 第六章 OBProxy 路由与使用运维
  • [Linux入门] Linux 账号和权限管理入门:从基础到实践
  • Linux实现进程之间Socket通信详解
  • 30 天自制 C++ 服务器--Day3
  • NO.6数据结构树|二叉树|满二叉树|完全二叉树|顺序存储|链式存储|先序|中序|后序|层序遍历
  • 【SpringBoot】实战-开发接口-用户-注册
  • 参数检验?非参数检验?
  • 【openbmc3】时间相关
  • 代码随想录算法训练营第五十一天|图论part2
  • 【FreeRTOS】03任务管理
  • 工业相机GigE数据接口的优势及应用
  • django安装、跨域、缓存、令牌、路由、中间件等配置
  • Jenkins全方位CI/CD实战指南
  • LabVIEW Occurrence功能