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

【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()


http://www.kler.cn/a/546821.html

相关文章:

  • 动态规划LeetCode-494.目标和
  • wps或office的word接入豆包API(VBA版本)
  • Django中实现简单易用的分页工具
  • PyTorch Lightning pytorch.loggers模块介绍
  • Linux 常见的虚拟文件系统
  • 数据结构(陈越,何钦铭)第三讲 树(上)
  • 《Keras 3 :当 Recurrence 遇到 Transformers 时》
  • 配置 Nginx 以支持 HTTPS
  • 二叉树链式结构:数据结构中的灵动之舞
  • 20250214 随笔 线程安全 线程不安全
  • C++实用技巧之 --- 观察者模式详解
  • OpenEuler学习笔记(三十三):在 OpenEuler 上搭建 OpenGauss 数据库环境
  • Swift 的 KeyPath 是什么?
  • Java网络编程学习(二)
  • 西门子S7-1500 PLC的自动化控制系统解决方案
  • 28 在可以控制 postgres 服务器, 不知道任何用户名的情况下怎 进入 postgres 服务器
  • 芯谷 D2761:专为扬声器保护设计的音频限幅器
  • maven-antrun-plugin插件的用法
  • 制造业物联网的十大用例
  • 国家队出手!DeepSeek上线国家超算互联网平台!