NLP 中 Bilstm-attentio的使用

2023-11-12

bilstm-attention 理解

bilstm-attention的作用

1:输入空间和输出空间的理解
在NLP的任务框架中,最基本的流程是 初步编码(比如one-hot vector,或者预训练词向量)作为输入,比如一句话进来 我开心,如果使用在分类模型中,我们就需要融合 我开心 这三个字,我们将这三个字 映射成向量,比如 [10,3] 3代表3个字,10代表表示向量的长度。 如果在一个分类的任务中,我们如何做到将其融合成一个词向量的表示呢,直白的来说 我想将 [10,3] 矩阵,从线性代数的角度来看,可以认为 是3个列向量,那么句子向量的表示,就可以表示成 [10,3]*[3,1] [3,1]是什么呢,我们就理解成权重,比如这句话如果在情感识别任务中,那么开心比较重要,那么 [3,1]的矩阵 写成 [0,0,1] 那么我们就可以直接抽取 开心的输入向量了。 输出也就是[10,1]的这个 开心这个词的向量。 但是因为任务是前变万化的,我们就想机器是否可以自适应的来学习 输入向量和输出向量呢,这就是本文的任务所在。

2: 为何要将输入的向量的重新表示

我们是否可以直接使用 [10,3]的输入向量作为输入呢,可以,但是前提是最好这些词的向量预先训练过,我们在学习线性代数的时候,还记得我们经常使用的 PCA呢,我们经常将一个向量表示成 out=w1v1+w2v2+… v1,v2,v3 那一般是什么,这就是我们通过pca计算出来的 独立主成分,它通过主要的特征向量来表示输出向量。 ok,其实大多数编码器就是做的这个工作。

bilstm-attention 编码实现`

如下 是代码的,语料分析部分,这部分不做分析了

import torch
import numpy as np
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import matplotlib.pyplot as plt
import torch.utils.data as Data

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# Bi-LSTM(Attention) Parameters
batch_size = 4
embedding_dim = 2
n_hidden = 5 # number of hidden units in one cell
num_classes = 2  # 0 or 1

# 3 words sentences (=sequence_length is 3)
sentences = ["i love you", "he loves me", "she likes baseball", "i hate you", "sorry for that", "this is awful"]
labels = [1, 1, 1, 0, 0, 0]  # 1 is good, 0 is not good.

vocab = list(set(" ".join(sentences).split()))
word2idx = {w: i for i, w in enumerate(vocab)}
vocab_size = len(word2idx)

def make_data(sentences):
  inputs = []
  for sen in sentences:
      inputs.append(np.asarray([word2idx[n] for n in sen.split()]))

  targets = []
  for out in labels:
      targets.append(out) # To using Torch Softmax Loss function

  return torch.LongTensor(inputs), torch.LongTensor(targets)

inputs, targets = make_data(sentences)
dataset = Data.TensorDataset(inputs, targets)
loader = Data.DataLoader(dataset, batch_size, True)

我们作中分析如下部分:

class BiLSTM_Attention(nn.Module):
    def __init__(self):
        super(BiLSTM_Attention, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, n_hidden, bidirectional=True)
        self.out = nn.Linear(n_hidden * 2, num_classes)

nn.Embedding 的作用就是将我们输入的 字或者词 转成词输入向量,训练出来的就是基于我们自己语料的词向量模型。 self.lstm 就是我们使用的编码层,我们通过 双向lstm将我们的输入编码输出,然后就是我们上文所述的,我们需要将 比如[10,3]的输入向量,表示成一个总体的我们可以称之为句向量表示的 [10.1] 最后 self.out 就是输出层,很直白,我们需要将最终的输入向量,映射为 最终的分类数。
实现方式一,我们通过隐藏层的参数作为attention的编码。

  def attention_net(self, lstm_output, final_state):
        batch_size = len(lstm_output)
        hidden = final_state.view(batch_size, -1, 1)   # hidden : [batch_size, n_hidden * num_directions(=2), n_layer(=1)]
        attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # attn_weights : [batch_size, n_step]
        soft_attn_weights = F.softmax(attn_weights, 1)

        # context : [batch_size, n_hidden * num_directions(=2)]
        context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2)
        return context, soft_attn_weights 

实现方二,我们可以直接通过linear来实现。

  def __init__(self):
        super(BiLSTM_Attention, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, n_hidden, bidirectional=True)
        #这里我们直接使用linear层,来做attention。
        self.attention=nn.Linear(n_hidden*2,1)
        self.out = nn.Linear(n_hidden * 2, num_classes)
    def attention_net(self, lstm_output, final_state):
        batch_size = len(lstm_output)
        hidden = final_state.view(batch_size, -1,
                                  1)  # hidden : [batch_size, n_hidden * num_directions(=2), n_layer(=1)]
        # attn_weights = torch.bmm(lstm_output, hidden).squeeze(2)  # attn_weights : [batch_size, n_step]
        #第二种方式实现。我们通过linear层来实现,在试验中,效果更好。
        attn_weights=self.attention(lstm_output).squeeze(2)
        soft_attn_weights = F.softmax(attn_weights, 1)

        # context : [batch_size, n_hidden * num_directions(=2)]
        context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2)
        return context, soft_attn_weights

这一层,就是我们这里要使用的注意力模型,注意力模型学的是什么呢,就是学习的我们上文中描述的 [3,1]向量,我们想计算出 针对[10,3]这三个列向量中,每一个列向量对应的权重。最终的context就是将输入空间映射成最终的输出空间。

好了,到目前,我们基本组件已经构建完成,下面我们进行,前向网络的构建。

 def forward(self, X):
        '''
        X: [batch_size, seq_len]
        '''
        input = self.embedding(X) # input : [batch_size, seq_len, embedding_dim]
        input = input.transpose(0, 1) # input : [seq_len, batch_size, embedding_dim]

        # final_hidden_state, final_cell_state : [num_layers(=1) * num_directions(=2), batch_size, n_hidden]
        output, (final_hidden_state, final_cell_state) = self.lstm(input)
        output = output.transpose(0, 1) # output : [batch_size, seq_len, n_hidden]
        attn_output, attention = self.attention_net(output, final_hidden_state)
        return self.out(attn_output), attention # model : [batch_size, num_classes], attention : [batch_size, n_step]

X为输入,输入的维度为 [4,3] 即 batch_size,seq_len.
self.embedding(X) 将X映射进词向量空间。 因此,input 变为 [4,3,2]
因为lstm 是序列模型,所以 batch_size和seq_len 交换,变成[3,4,2].进入self.lstm lstm为一个序列模型,每一个时间步长都会生成一个输出。看下具体lstm的网络 LSTM(2, 5, bidirectional=True)。 那么输出时为 [3,4,52] 因为为双向,所以有两个维度为5的拼接在一起。所以输出为 [3,4,10] lstm网络有两个各隐藏层,分别为 c和h,我们一般只保留最后一个一个时间序列的隐藏层,所有 c和h的输出均为 [2,4,5] 2因为我们是双向的。
下面进入我们的重点代码attention, 上面我们已经描述过,是为了求得针对编码输出的每个向量的输出。编码输出为 [3,4,10] 转置成[batch_size,seq_len,out_dim] [4,3,10] 那么我们需要有一个向量去做attention,这个向量的设计方法挺多,这里选择了用隐藏层的输出[2,4,5] 作为attention,当然我们也可以选择其他。比如直接使用 nn.linear ,后面我们会描述。 我们可以得知 attention_weights 理论为 [4,3,1] ,我们可以去掉batch_size, 那么 encoder 层是 [10,3] 那么 attention 层求得的权重向量为 [3,1] , 然后用我们上述的 讲过的 [10,3]
[3,1] 得到了 [10.1]的句向量。到这里,我们基本做完了基于lstm的注意力机制。

核心重点:

1:设计计算出权重向量的方式。我们这里有两种实现,1:使用隐藏层来实现。2:使用linear层实现。

model = BiLSTM_Attention().to(device)
criterion = nn.CrossEntropyLoss().to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Training
for epoch in range(500):
    for x, y in loader:
        x, y = x.to(device), y.to(device)
        pred, attention = model(x)
        loss = criterion(pred, y)
        if (epoch + 1) % 10 == 0:
            print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
            writer.add_scalar("Loss/train", loss, epoch)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
writer.flush()
#save the model
torch.save(model.state_dict(),"bi-lstmattention-para")
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NLP 中 Bilstm-attentio的使用 的相关文章

  • webpack引入第三方库的方式,以及注意事项

    一般情况下 我们不用担心所使用的第三方库 在npm管理仓库中找不到 如果需要某一个库 如 jquery 可以直接运行npm install jquery脚本命令来安装这个项目所需要的依赖 然后 在使用jquery的模块文件中 通过impor
  • vs2019找不着工具箱了_VS2019 Nuget找不到包的问题处理

    VS不记得改了什么设置之后 发现找不到EF 解决办法 1 点击右侧的设置按钮 2 弹出窗中左侧树形结构选择 程序包源 再点击右上方的添加按钮 然后点击更新 确定按钮 再次搜索就可找到EF安装包 vs2019中NuGet控制台的常用命令 Db

随机推荐

  • 关于Flink Time中的Watermaker案例的详解

    需求 自定义数据源 产出交易订单数据 设置基于事件时间窗口统计 1 交易订单数据 import lombok AllArgsConstructor import lombok Data import lombok NoArgsConstru
  • 三个审稿人,两个同意,一个不同意,最后被录用希望大吗?

    链接 https www zhihu com question 340821507 编辑 深度学习与计算机视觉 声明 仅做学术分享 侵删 作者 知乎用户 https www zhihu com question 340821507 answ
  • 【转】C++类中对同类对象private成员访问

    私有成员变量的概念 在脑海中的现象是 以private关键字声明 是类的实现部分 不对外公开 不能在对象外部访问对象的私有成员变量 然而 在实现拷贝构造函数和赋值符函数时 在函数里利用对象直接访问了私有成员变量 因而 产生了困惑 下面以具体
  • 基于Matlab实现图像配准技术(附上源码+图像)

    图像配准是数字图像处理中的重要技术之一 它的目标是将多幅图像进行准确的对齐 使得它们在空间上保持一致 图像配准在许多领域都有广泛的应用 如医学影像 遥感图像 计算机视觉等 本文将介绍如何使用Matlab实现图像配准技术 并提供一个简单的案例
  • linux文件内容操作命令,linux 操作系统中cat查看文件内容命令的使用

    cat命令的用途是连接文件或标准输入并打印 这个命令常用来显示文件内容 或者将几个文件连接起来显示 或者从标准输入读取内容并显示 它常与重定向符号配合使用 1 命令格式 cat 选项 文件 2 命令功能 cat主要有三大功能 1 一次显示整
  • 华为安防产品VCN资料下载

    首先登录网站 华为入口 下载后安装 win10 然后就能看到客户端 注册登录 点击资料领航 进入网页 然后就可以下载了
  • 您的计算机已被Malloxx勒索病毒感染?恢复您的数据的方法在这里!

    导言 在数字时代 malloxx勒索病毒已经成为一个可怕的威胁 给个人 企业和组织带来了无法估量的损失 本文91数据恢复将深入探讨 malloxx勒索病毒的运作方式 并提供一些独特的方法来恢复被它加密的数据文件 以及如何在被其困扰之前采取
  • Linux高性能服务器编程|阅读笔记:第5章 - Linux网络编程基础API

    目录 简介 5 1 socket地址API 5 1 1 主机字节序和网络字节序 5 1 2 通用socket地址 5 1 3 专用socket地址 5 1 4 IP地址转换函数 5 2 创建socket 5 3 命名socket 5 4 监
  • 面试题目收集(1)

    本博客的 面试题目搜集系列不错 1 面试题目搜集1 2 面试题目搜集2 3 面试题目搜集3 4 面试题目搜集4 5 面试题目搜集5 6 面试题目搜集6 1 字符串取除多余的空格 包括行首的空格 单词与单词之间只能有多余的空格 结尾不能有空格
  • pytorch简单的逻辑回归

    import torch import torch nn as nn import torchvision import torchvision transforms as transforms Hyper parameters input
  • vue与ios、Android交互问题总结

    1 ios与vue交互可以显示iframe的页面内容 但是不能与iframe交互 Android可以 2 ios可以直接调用html页面 但是url传参只能是问号传参 不可用json对象 Android可以 3 Android对js语法要求
  • Spark高手之路3—Spark运行架构

    文章目录 Spark 运行架构 一 运行架构 二 核心组件 Driver Executor Master Worker ApplicationMaster 三 核心概念 1 Executor 与 Core 2 并行度 Parallelism
  • 【学习笔记向】零基础小白快速制作最简陋MMD(VRoid + Unity)

    特别鸣谢B站UP主十七时的大力支援 学生时期总会有一两个没有安排的周末 不如我们来嗑CP 学习 做MMD吧 第一天 下载软件和素材 熟悉Unity 下载软件可能需要很久 请耐心 一 软件 1 VRoid Studio 用于零基础建模 B站上
  • java必知必会_Java必知必会-Spring Security

    一 Spring Security介绍 1 框架介绍 Spring 是一个非常流行和成功的 Java 应用开发框架 Spring Security 基于 Spring 框架 提供了一套 Web 应用安全性的完整解决方案 一般来说 Web 应
  • 基于DFA方法的健康人与癫痫病人EEG数据分析附代码

    引言 DFA分析方法是由C K提出的一种研究时间序列波动长时相关性的方法 主要用来区别复杂系统本身产生的波动和由外界及环境刺激作用在系统上产生的波动 外部刺激产生的变化假设引起了局部效应 而系统本身内部的动力学产生的变化假设展示了长时的相关
  • 浅拷贝和深拷贝: copy模块的copy()和deepcopy()函数(*^▽^*)

    我们在平时处理列表和字典的时候 有时候希望创建一个列表或者字典的副本拿出来使用 但是同时我们也不希望列表 字典 和其列表 字典 副本还保留着某种联系的时候 比如说我们在修改列表的时候副本也跟着同步被修改了 这是我们最不想看到的情况 这种情况
  • 树莓派教程 - 1.2 树莓派GPIO库wiringPi 软件PWM

    Git例程源码仓库 https github com ZhiliangMa raspberry git 使用到的硬件 led 200 左右的电阻 杜邦线 上一节使用硬件PWM来控制led亮度 可树莓派的硬件PWM引脚只有1路 在实际应用中
  • php生成密码及密码检验

    1 生成密码 password hash test password PASSWORD DEFAULT 2 密码检验 hash 2y 10 ckeTXO nnKfWTDDYRSwGWu0xste 55Cp0RIpolBldDOXZ61ecZ
  • vscode同时编辑多处文字 批量替换编辑内容

    先按Ctrl F打开搜索框 然后搜索要编辑的内容 接着按Ctrl Shift L就可以选中对应的所有内容了 然后可以全部编辑和替换了 按了Ctrl shift L之后把搜索框关闭就可以同时编辑多处了 此处我就是搜索items
  • NLP 中 Bilstm-attentio的使用

    NLP 中 Bilstm attentio的使用 bilstm attention 理解 bilstm attention的作用 bilstm attention 编码实现 bilstm attention 理解 bilstm attent