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

【NLP】循环神经网络RNN

目录

一、词嵌入层

二、循环网络层

2.1 RNN网络原理

2.2 Pytorch RNN API


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

一、词嵌入层

在进行文本数据处理时,需要将文本进行数据值化,然后进行后续的训练工作。词嵌入层的作用就是将文本转换为向量的

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

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

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

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

  1. num_embeddings 表示词的数量
  2. embedding_dim 表示用多少维的向量来表示每个词
import torch
import torch.nn as nn
import jieba

def main():
    text = '北京冬奥的进度条已经过半,不少外国运动员在完成自己的比赛后踏上归途。'
    # 1. 分词
    words = jieba.lcut(text)
    print('words:', words)

    # 2. 构建词表
    index_to_word = {}
    word_to_index = {}
    # 分词去重
    unique_words = list(set(words))
    for idx, word in enumerate(unique_words):
        index_to_word[idx] = word
        word_to_index[word] = idx
    
    # 3.构建词嵌入层
    # num_embeddings为词的数量,embedding_dim为词嵌入的维度
    embedding = nn.Embedding(num_embeddings=len(index_to_word), embedding_dim=4)

    # 4.文本转为词向量表示
    for word in words:
        idx = word_to_index[word]
        word_vector = embedding(torch.tensor(idx))
        print('%3s\t' % word, word_vector)

if __name__ == "__main__":
    main()
words: ['北京', '冬奥', '的', '进度条', '已经', '过半', ',', '不少', '外国', '运动员', '在', '完成', '自己', '的', '比赛', '后', '踏上', '归途', '。']
 北京    tensor([1.1339, 1.1262, 0.6638, 1.5691], grad_fn=<EmbeddingBackward0>)
 冬奥    tensor([0.2753, 0.3262, 1.7691, 1.2225], grad_fn=<EmbeddingBackward0>)
  的     tensor([-0.7507,  1.8850,  1.4340, -0.8074], grad_fn=<EmbeddingBackward0>)
进度条   tensor([ 0.5693, -0.0951, -0.4607,  0.0555], grad_fn=<EmbeddingBackward0>)
 已经    tensor([-0.5726,  0.0812,  1.1051, -0.0020], grad_fn=<EmbeddingBackward0>)
 过半    tensor([0.0691, 0.1430, 1.9346, 1.4653], grad_fn=<EmbeddingBackward0>)
  ,     tensor([-1.1009,  0.7833, -0.9021,  1.8811], grad_fn=<EmbeddingBackward0>)
 不少    tensor([ 0.7913,  0.0890, -0.7459,  1.1473], grad_fn=<EmbeddingBackward0>)
 外国    tensor([-0.6079,  0.2563,  0.8344, -0.5977], grad_fn=<EmbeddingBackward0>)
运动员   tensor([-1.9587,  0.0995, -1.0728, -0.2779], grad_fn=<EmbeddingBackward0>)
  在     tensor([-1.6571, -1.2508, -0.8138, -2.6821], grad_fn=<EmbeddingBackward0>)
 完成    tensor([-1.4124, -0.5624,  1.2548,  0.1708], grad_fn=<EmbeddingBackward0>)
 自己    tensor([-2.5485, -0.1839, -0.0079,  0.1326], grad_fn=<EmbeddingBackward0>)
  的     tensor([-0.7507,  1.8850,  1.4340, -0.8074], grad_fn=<EmbeddingBackward0>)
 比赛    tensor([ 0.3826, -1.8883,  0.5677,  0.1951], grad_fn=<EmbeddingBackward0>)
  后     tensor([ 0.2585, -1.2181,  1.0165, -0.4775], grad_fn=<EmbeddingBackward0>)
 踏上    tensor([-1.6933,  1.2826,  0.9993, -0.2306], grad_fn=<EmbeddingBackward0>)
 归途    tensor([ 3.8709,  0.5133,  0.1683, -0.9699], grad_fn=<EmbeddingBackward0>)
  。     tensor([-0.9352, -1.2663, -1.5860, -0.2301], grad_fn=<EmbeddingBackward0>)

词嵌入层默认使用的是均值为 0,标准差为 1 的正态分布进行初始化,也可以理解为是随机初始化。这个用来表示词的文本真的能够表达出词的含义吗?

nn.Embedding 中对每个词的向量表示都是随机生成的,当一个词输入进来后,会使用随机产生的向量来表示该词。该词向量参与到下游任务的计算,下游任务计算后,会和目标结果进行对比产生损失。接下来,通过反向传播更新所有的网络参数,就包括了 nn.Embedding 中的词向量表示。这样通过反复的前向计算、反向传播、参数更新,最终每个词的向量表示就会变得更合理

二、循环网络层

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

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

2.1 RNN网络原理

上图中 h 表示隐藏状态,每一次的输入都会有包含两个值:上一个时间步的隐藏状态、当前状态的输入值,输出当前时间步的隐藏状态

上图中,为了更加容易理解,画了 3 个神经元, 但是实际上只有一个神经元,"我爱你" 三个字是重复输入到同一个神经元中的

举例

假设要实现文本生成,也就是输入"我爱" 这两个字,来预测出"你",其如下图所示:

将上图展开成不同时间步的形式,如下图所示:

首先初始化出第一个隐藏状态,一般都是全0的一个向量,然后将 "我" 进行词嵌入,转换为向量的表示形式,送入到第一个时间步,然后输出隐藏状态 h1,然后将 h1 和 "爱" 输入到第二个时间步,得到隐藏状态 h2,将 h2 送入到全连接网络,得到 "你" 的预测概率

循环网络网络可以有多个神经元

依次将 "你爱我" 三个字分别送入到每个神经元进行计算,假设词嵌入时 "你爱我" 的维度为 128,经过循环网络 "你爱我" 三个字的词向量维度就会变成 4。循环神经网络的的神经元个数会影响到输出的数据维度

神经元内部如何计算?

  1. W_{ih} 表示输入数据的权重
  2. b_{ih} 表示输入数据的偏置
  3. W_{hh} 表示输入隐藏状态的权重
  4. b_{hh} 表示输入隐藏状态的偏置

最后对输出的结果使用 tanh 激活函数进行计算,得到该神经元的输出

2.2 Pytorch RNN API

RNN 层输入的数据为三个维度:(seq_len,batch_size,input_size)

import torch
import torch.nn as nn

# 输入单个数据
def test01():
    # seq_len, batch_size, input_size
    inputs = torch.randn(1, 1, 128)
    # 隐藏层 num_layers, batch_size, hidden_size
    hn = torch.zeros(1, 1, 256)
    # input_size 输入词向量的维度
    # hidden_size 隐藏层的大小, 隐藏层的神经元个数, 影响最终输出结果的维度
    rnn = nn.RNN(input_size=128, hidden_size=256)
    outputs, hn = rnn(inputs, hn)
    print("outputs shape", outputs.shape)
    # outputs shape torch.Size([1, 1, 256])
    print("hidden shape", hn.shape)
    # hidden shape torch.Size([1, 1, 256])

# 输入句子
def test02():
    # seq_len, batch_size, input_size
    inputs = torch.randn(8, 1, 128)
    hn = torch.zeros(1, 1, 256)

    rnn = nn.RNN(input_size=128, hidden_size=256)
    outputs, hn = rnn(inputs, hn)
    print("outputs shape", outputs.shape)
    # outputs shape torch.Size([8, 1, 256])
    print("hidden shape", hn.shape)
    # hidden shape torch.Size([1, 1, 256])

# 输入批量数据
def test03():
    # seq_len, batch_size, input_size
    inputs = torch.randn(8, 32, 128)
    hn = torch.zeros(1, 32, 256)

    rnn = nn.RNN(input_size=128, hidden_size=256)
    outputs, hn = rnn(inputs, hn)
    print("outputs shape", outputs.shape)
    # outputs shape torch.Size([8, 32, 256])
    print("hidden shape", hn.shape)
    # hidden shape torch.Size([1, 32, 256])

if __name__ == "__main__":
    # test01()
    # test02()
    test03()

相关文章:

  • Java 后端开发:如何提取请求头中的 Cookie 和身份验证 Token
  • Qt QOpenGLWidget详解
  • 示例代码:C# MQTTS双向认证(客户端)(服务器EMQX)
  • 【Elasticsearch】多字段查询方式汇总
  • 【VS2022】创建本地仓库,开启Git管理控制
  • 笔记8——模式匹配 match语句(仅在Python 3.10及以上版本中可用)
  • Qt工作总结03 <qSort按某一属性进行排序>
  • SpringAI集成DeepSeek实战
  • 【Linux网络-网络基础】计算机网络背景+协议+OSI七层模型
  • 解释 Git 的基本概念和使用方式。
  • 渗透利器:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)
  • 2025前端面试题超全面解析(附答案与深度扩展)
  • PicoShare实操:轻松实现远程文件共享无需公网IP与云服务器
  • 大数据学习之SparkStreaming、PB级百战出行网约车项目一
  • 华纳云:如何从服务器日志中发现僵尸进程?
  • UGUI Canvas为Overlay模式下的UI元素的position和localPosition
  • 2月14日笔记
  • 安装OpenJDK21(linux、macos)
  • 站群服务器和普通服务器有哪些不同之处?
  • 【分布式理论9】分布式协同:分布式系统进程互斥与互斥算法
  • 中方是否认同俄方关于新纳粹主义观点?外交部:联大曾多次通过相关决议
  • 铲屎官花5万带猫狗旅行,宠旅生意有多赚?
  • 人民日报整版聚焦:铭记二战历史,传承深厚友谊
  • 比尔·盖茨:未来20年通过盖茨基金会捐出几乎全部财富,2045年底基金会停止运营
  • 国防部:正告菲方停止以任何方式冲撞中方核心利益
  • 从“重规模”向“重回报”转变,公募基金迎系统性改革