循环神经网络RNN

1 RNN介绍

1.1 RNN概念

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

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

1.2 RNN应用场景

  • **自然语言处理(NLP)**:文本生成、语言建模、机器翻译、情感分析等。

  • **时间序列预测**:股市预测、气象预测、传感器数据分析等。

  • **语音识别**:将语音信号转换为文字。

  • **音乐生成**:通过学习音乐的时序模式来生成新乐曲。

1.3 自然语言处理概述

自然语言处理(Nature language Processing, NLP)研究的主要是==通过计算机算法来理解自然语言。==

对于自然语言来说,处理的数据主要就是**人类的语言**,例如:汉语、英语、法语等,该类型的数据不像我们前面接触过的结构化数据、或者图像数据可以很方便的进行数值化。

NLP的目标是让机器能够"听懂"和"读懂"自然语言,并进行有效的交流和分析。

NLP涵盖了从文本到语音、从语音到文本的各个方面,它涉及多种技术,包括语法分析、语义理解、情感分析、机器翻译等。

2 词嵌入层

在 **RNN(Recurrent Neural Network)** 中,**词嵌入层(Word Embedding Layer)** 是处理自然语言数据的关键组成部分。它将输入的离散单词(通常是词汇表中的索引)转换为连续的、低维的向量表示,从而使得神经网络能够理解和处理这些词汇的语义信息。

2.1 词嵌入层作用

词嵌入层的主要目的是**将每个词映射为一个固定长度的向量(将文本转换为向量)**,这些向量能够捕捉词与词之间的语义关系。

传统的文本表示方法(如one-hot编码)无法反映单词之间的相似性,因为在one-hot编码中,每个单词都被表示为一个**高维稀疏向量**,而词嵌入通过**低维稠密向量**表示单词,能够更好地捕捉词汇之间的语义相似性。

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

**词嵌入层在RNN中的作用**:

  • **输入表示**:RNN通常用于处理序列数据。在处理文本时,RNN的输入是由单词构成的序列。由于神经网络不能直接处理离散的单词标识符(如整数索引或字符),因此需要通过词嵌入层将每个单词转换为一个固定长度的稠密向量。这些向量作为RNN的输入,帮助RNN理解词语的语义。

  • **降低维度**:词嵌入层将原本高维的稀疏表示(如one-hot编码)转化为低维的稠密向量,减少了计算量,同时保持了词汇之间的语义关系。

  • **捕捉语义相似性**:通过训练,词嵌入能够学习到词语之间的关系。例如,语义相似的词(如"猫"和"狗")在向量空间中会比较接近,而语义不相关的词(如"猫"和"汽车")则会较为遥远。

2.2 词嵌入层工作流程

  • **初始化词向量**:词嵌入层的初始词向量通常会使用随机初始化或者通过加载预训练的词向量(如Word2Vec或GloVe)进行初始化。

  • **输入索引**:每个单词在词汇表中都有一个唯一的索引。输入文本(例如一个句子)会先被分词,然后每个单词会被转换为相应的索引。

  • **查找词向量**:词嵌入层将这些单词索引映射为对应的词向量。这些词向量是一个低维稠密向量,表示该词的语义。

  • **输入到RNN**:这些词向量作为RNN的输入,RNN处理它们并根据上下文生成一个序列的输出。

2.3 词嵌入层使用

在PyTorch中,我们可以**使用 nn.Embedding 词嵌入层来实现输入词的向量化**。

nn.Embedding 对象构建时,最主要有两个参数:

  • num_embeddings:表示**词的数量**

  • embedding_dim:表示**用多少维的向量来表示每个词**

python 复制代码
nn.Embedding(num_embeddings=10, embedding_dim=4)

接下来,我们将会学习如何将词转换为词向量,其步骤如下:

  1. 先将语料进行分词,构建词与索引的映射,我们可以把这个映射叫做词表,词表中每个词都对应了一个唯一的索引;

  2. 然后使用 nn.Embedding 构建词嵌入矩阵,词索引对应的向量即为该词对应的数值化后的向量表示。

例子:

python 复制代码
import torch
import torch.nn as nn
import jieba # pip install jieba -i https://pypi.mirrors.ustc.edu.cn/simple/


if __name__ == '__main__':
    # 0.文本数据
    text = '北京冬奥的进度条已经过半,不少外国运动员在完成自己的比赛后踏上归途。'
    # 1. 文本分词
    words = jieba.lcut(text)
    print('文本分词:', words)
    # 2.分词去重并保留原来的顺序获取所有的词语
    unique_words = list(set(words))
    print("去重后词的个数:\n",len(unique_words))
    # 3. 构建词嵌入层
    # num_embeddings: 表示词的总数量
    # embedding_dim: 表示词嵌入的维度
    embed = nn.Embedding(num_embeddings=len(unique_words), embedding_dim=4)
    print("词嵌入的结果:\n",embed)
    # 4. 词语的词向量表示
    for i, word in enumerate(unique_words):
        # 获得词嵌入向量
        word_vec = embed(torch.tensor(i))
        print('%s\t' % word, word_vec)

3 循环网络层

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

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

3.1 RNN网络层原理

上图中h表示==隐藏状态==,隐藏状态保存了**序列数据中的历史信息**,并将这些信息传递给下一个时间步,从而允许RNN处理和预测序列数据中的元素。

每一次的输入都会包含两个值:**上一个时间步的隐藏状态、当前状态的输入值x**

每一次的输出都会包含两个值:**输出当前时间步的隐藏状态、当前时间步的预测结果y**

**隐藏状态作用:**

  • **记忆功能**:隐藏状态就像RNN的记忆,它能够在不同的时间步之间传递信息。当一个新的输入进入网络时,当前的隐藏状态会结合这个新输入来生成新的隐藏状态。

  • **上下文理解**:由于隐藏状态携带了过去的信息,它可以用于理解和生成与上下文相关的输出。这对于语言模型、机器翻译等任务尤其重要。

  • **连接不同时间步**:隐藏状态通过网络内部的循环连接将各个时间步连接起来,使得网络可以处理变长的序列数据。

**小结:**在循环神经网络中,**词与输出的对应关系**通常通过以下几个步骤建立

  1. **词嵌入**:将词转化为向量表示(词向量)。

  2. **RNN处理**:通过RNN层逐步处理词向量,生成每个时间步的隐藏状态。

  3. **输出映射**:通过线性变换将隐藏状态映射到输出,通常是一个词汇表中的词的概率分布。

3.2 PyTorch RNN层的使用

API介绍:

RNN = nn.RNN(input_size, hidden_size,num_layers)

参数意义是:

  • input_size:输入数据的维度,一般设为词向量的维度

  • hidden_size:隐藏层h的维度,也是当前层神经元的输出维度

  • num_layers: 隐藏层h的层数,默认为1

python 复制代码
import torch
import torch.nn as nn


#  RNN层送入批量数据
def test():
    # 词向量维度 128, 隐藏向量维度 256
    rnn = nn.RNN(input_size=128, hidden_size=256)
    # 第一个数字: 表示句子长度,也就是词语个数
    # 第二个数字: 批量个数,也就是句子的个数
    # 第三个数字: 词向量维度
    inputs = torch.randn(5, 32, 128)
    hn = torch.zeros(1, 32, 256)
    # 获取输出结果
    output, hn = rnn(inputs, hn)
    print("输出向量的维度:\n",output.shape)
    print("隐藏层输出的维度:\n",hn.shape)

    
if __name__ == '__main__':
    test()
相关推荐
阿里云大数据AI技术1 小时前
闲鱼「鱼卖卖」的长期记忆实践:用阿里云 Milvus 记住卖家的经营偏好
人工智能·agent
bdy_y91 小时前
推理引擎测试指南:像调校赛车一样测试AI引擎
人工智能·大模型·性能测试
艾络迅Acceleronix1 小时前
从连接到落地|移远艾络迅携手NAXEON构建电摩智能化能力
人工智能
尺度商业1 小时前
摩尔线程迎来解禁:谁在割肉,谁在捡筹?
人工智能
月华路1 小时前
《模型不玄学》第24章 第二个标签怎么造:层级标签
人工智能·深度学习·机器学习
咖啡星人k1 小时前
2026 上下文缓存进阶:把前缀契约写进SPEC,MonkeyCode 云端跑通
人工智能·机器学习·缓存
维克兜率天1 小时前
【维克】特征归一化与标准化:为什么模型对数据的“尺度“很敏感?
人工智能·笔记·python·机器学习·量化
朝阳5811 小时前
如何用 AI 自动生成规范的 Git 提交信息:从暂存区 diff 到 Conventional Commit
人工智能·git
CV山月1 小时前
大模型强化学习对齐:从 RLHF 框架到 PPO 算法原理
人工智能·python·大模型·强化学习·多模态·研究生