一看就懂的LSTM+Attention,此处用softmax求概率

2023-05-16

1。 序言

首先,我是看这两篇文章的。但是,他们一个写的很笼统,一个是根据Encoder-Decoder和Query(key,value)。第二个讲的太深奥了,绕来绕去,看了两天才知道他的想法。
https://segmentfault.com/a/1190000014574524 这个是讲的很笼统的
https://blog.csdn.net/qq_40027052/article/details/78421155 这个是讲的太深奥的。

本文 的一些基础知识还是基于第二个博客展开。但是我通过两张图可以直接让你明白attention和LSTM在一起的组合。

2. Attention+LSTM

2.1 Attention+LSTM的结构体

以翻译为例
在这里插入图片描述
上图就是Attention+LSTM的工作原理了。在这个结构里面,在attention计算注意力分配概率的时候,我选择使用softmax,这是很方便的一个方法,大家也可以选择直接使用归一化的方法,把softmax那一行换成用归一化方法归一化到(0,1)之间。当然也可以用其他方法

关于紫色这一行主要是求相似度的。求相似度也有很多方法,在这里为了表示方便,我具使用内积表示。其他方法也有很多,比如:

  • 用内积衡量
  • 用一个小型神经网络拟合。
  • 可以用余弦相似度计算

到这里,我们再来看一下原始的LSTM的结构是什么样的。

在这里插入图片描述
很显然啊,原始LSTM比上述Attention+LSTM少了左上角的那一块,而那一块就是Attention。从第一张图我们可以看出,这个attention就是重新计算这个 h 1 ′ {h_{1}}' h1
下面,我们用一个方块表示attention,也就是把第一张图简化:
在这里插入图片描述
现在,大家就能看清楚了,在每个 h i ′ {h_{i}}' hi之后呢,其实都是要用一次attention的。

到这里,大家应该都看的都理解的差不多了吧。

3. 用文字解释一下Attention+LSTM

用开头的第二个博客的说法,在没有引入注意力机制的LSTM中,模型在翻译每个单词时,前面的四个隐含层 h i {h_{i}} hi对其影响是一样的。然而事实上,我们不希望他们是一样的,因此提出了attention机制。这个机制其实就是计算相似度,然后使用softmax对其进行归一化。
就是这么简单,至于每一步的公式,我们这里以如下结构为例给出。

原始LSTM的隐含层 h i {h_{i}} hi
紫色部分求当前输出是的隐含层 h i ′ {h_{i}}' hi与前面四个输入隐含层的 h i {h_{i}} hi相似度,我们用余弦相似度计算,既有:
e i = h ′ ⋅ h ∥ h ′ ∥ ∥ h ∥ {e_{i}}=\frac{{h_{}}'\cdot h_{}}{\left \| {h_{}}' \right \|\left \| h_{}\right \|} ei=hhhh
在这一步,我们求出当前需要输出被翻译的字的英文名的隐含层与前面输入的所有隐含层之间的相似度的值 e i {e_{i}} ei
下一步,我们使用softmax根据相似度值计算每个隐含层对翻译给单词的贡献:
在这里插入图片描述
这一步,我们就求出了每个隐含层的贡献度了
在这里插入图片描述
然后,我们在根据每个隐含层的贡献度加权求和
在这里插入图片描述
得到当前输出隐含层 h 1 ′ {h_{1}}' h1的值

4。 用python实现注意力层代码

首先上代码

4.1 attention部分

def attention_3d_block(inputs):
    # inputs.shape = (batch_size, time_steps, input_dim)
    input_dim = int(inputs.shape[2])
    a = Permute((2, 1))(inputs)
    a = Reshape((input_dim, TIME_STEPS))(a) # this line is not useful. It's just to know which dimension is what.
    a = Dense(TIME_STEPS, activation='softmax')(a)
    if SINGLE_ATTENTION_VECTOR:
        a = Lambda(lambda x: K.mean(x, axis=1), name='dim_reduction')(a)
        a = RepeatVector(input_dim)(a)
    a_probs = Permute((2, 1), name='attention_vec')(a)
    output_attention_mul = Multiply()([inputs, a_probs])
    return output_attention_mul

这里面需要用到的几个函数,我先给解释一下
Permute:这个函数的作用就是行列互换,在这里可以认为是求矩阵inputs转置。
Reshape:同样是调整矩阵的行列,看到这里,是不觉得这一步是多余的?说实话,很多人都认为是多余的。INPUT_DIM = 2,TIME_STEPS = 20,就将其调整为了2行,20列。
Lambda: 官方解释:本函数用以对上一层的输出施以任何Theano/TensorFlow表达式。这里的“表达式”指得就是K.mean,其原型为keras.backend.mean(x, axis=None, keepdims=False),指张量在某一指定轴的均值。
我的解释:什么狗屁的x轴还是y轴的。x轴方向的均值,对于矩阵来讲就是按行求均值。。y轴方向的均值,对于矩阵来讲就是按列求均值。这一定很重要,要记住啊。
RepeatVector:作用为将输入重复n次。这里为什么要重复进行,下面我详细介绍。

详细解释
   先看第一个Permute层,由前面数据集的前三个输出我们知道,输入网络的数据的shape是(time_steps, input_dim),即(20,2),这是方便输入到LSTM层里的输入格式。无论注意力层放在LSTM的前面还是后面,最终输入到注意力层的数据shape仍为(time_steps, input_dim)(20,2),对于注意力结构里的Dense层而言,(input_dim, time_steps)(2,20)才是符合的,因此要进行维度变换。
  再看第一个Reshape层,可以发现其作用为将数据转化为(input_dim, time_steps)(2,20)。这个操作不是在第一个Permute层就已经完成了吗?没错,实际上这一步操作物理上是无效的,因为格式已经变换好了,但这样做有一个好处,就是可以清楚的知道此时的数据格式,shape的每一个值分别代表什么含义。
  接下来是一个Dense层,这个Dense层的激活函数是softmax,显然就是注意力结构里的Dense层,用于计算每个特征的权重。
  马上就到SINGLE_ATTENTION_VECTOR值的判断了,现在出现了一个问题,我们的特征在一个时间结点上的维度是多维的(input_dim维),即有可能是多个特征随时间变换一起发生了变换,那对应的,我们的注意力算出来也是多维的。此时,我们会想:是多维特征共享一个注意力权重,还是每一维特征单独有一个注意力权重呢? 这就是SINGLE_ATTENTION_VECTOR值的判断的由来了。SINGLE_ATTENTION_VECTOR=True,则共享一个注意力权重,如果=False则每维特征会单独有一个权重,换而言之,注意力权重也变成多维的了。
  下面对当SINGLE_ATTENTION_VECTOR=True时,代码进行分析。Lambda层将原本多维的注意力权重取平均,RepeatVector层再按特征维度复制粘贴,那么每一维特征的权重都是一样的了,也就是所说的共享一个注意力。
  接下来就是第二个Permute层,到这步就已经是算好的注意力权重了,我们知道Attention的第二个结构就是乘法,而这个乘法要对应元素相乘,因此要再次对维度进行变换。
  最后一个Multiply层,权重乘以输入,注意力层就此完工。
  想一想,权重是什么,输入是什么?我们看一下下面图的最上面一行,权重就是下图中softmax计算出来的概率,输入就是 h i h_{i} hi。这下看明白了吗
上面的代码是实现attention部分的
也就是图一中的这一部分
在这里插入图片描述

4.2 与LSTM结合

def model_attention_applied_after_lstm():
    K.clear_session() #清除之前的模型,省得压满内存
    inputs = Input(shape=(TIME_STEPS, INPUT_DIM,))
    lstm_units = 32
    lstm_out = LSTM(lstm_units, return_sequences=True)(inputs)
    attention_mul = attention_3d_block(lstm_out)
    attention_mul = Flatten()(attention_mul)
    output = Dense(1, activation='sigmoid')(attention_mul)
    model = Model(input=[inputs], output=output)
    return model

在该部分的代码里,我们可以在第三行看到attention_3d_block()这个函数
当我们知道这个函数的输入时,就很清楚的知道Attention-LSTM的运作原理了。
这个时候,我们看的还是云里雾里,现在我们将参数全部带入到函数里

def model_attention_applied_after_lstm():
    K.clear_session() #清除之前的模型,省得压满内存
    inputs = Input(shape=(20, 2,))
    #lstm_units = 32
    lstm_out = LSTM(32, return_sequences=True)(inputs)
    attention_mul = attention_3d_block(lstm_out)
    attention_mul = Flatten()(attention_mul)
    output = Dense(1, activation='sigmoid')(attention_mul)
    model = Model(input=[inputs], output=output)
    return model

关于LSTM的详细分析,可以参考这个博客。

逐行解释
大家在看代码的时候,一定要在脑子里回想第一张图,并且知道数据的流向。

inputs = Input(shape=(20, 2,))

这一步没什么好说的,输入数据是20行2列。
这个Input不要被他欺骗了,其实他是keras下面的一个函数,注意首字母大写
大家可以看到这个博客。
Input():用来实例化一个keras张量

Input(shape=None,batch_shape=None,name=None,dtype=K.floatx(),sparse=False,tensor=None)
lstm_out = LSTM(32, return_sequences=True)(inputs)

这一步就是调用LSTM了,先把输入数据输入到LSTM网络,这个网络的神经元个数为32个。通过LSTM网络,我们可以去求出来隐含层变量 h i h_{i} hi

继续向下,开始在隐含层后加入attention

attention_mul = attention_3d_block(lstm_out)

这边我需要解释一下,就是我们输入一组向量

下面这一层就很直观了,就是把矩阵拉成平的

attention_mul = Flatten()(attention_mul)

Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。

output = Dense(1, activation='sigmoid')(attention_mul)

Dense层就是所谓的全连接神经网络层,在这里,因为是回归问题,多输入单输出,所有最后一个全连接层的神经元的个数就是一个。

最后一行啊,关于这个Model这个函数,我还是需要解释一下的
大家可以参考这个博客。

当然,还有另一种使用方式,就是添加在lstm之前

def model_attention_applied_before_lstm():
    inputs = Input(shape=(TIME_STEPS, INPUT_DIM,))
    attention_mul = attention_3d_block(inputs)
    lstm_units = 32
    attention_mul = LSTM(lstm_units, return_sequences=False)(attention_mul)
    output = Dense(1, activation='sigmoid')(attention_mul)
    model = Model(input=[inputs], output=output)
    return model

keras让新手最蛋疼的地方就是开发了两个API
Keras通过两个API提供两种计算模型:

  • 函数式模型:通过Model类API;
  • 顺序式模型:通过Sequential类API;
    我个人觉得这个model类API就是为了跟TensorFlow区分才开发的,乍一看很不适应,怎么后面有两个()呢?我草,这是什么?用习惯了才知道,这个model力看着比Sequential明白多了。
model = Model(input=[inputs], output=output)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一看就懂的LSTM+Attention,此处用softmax求概率 的相关文章

  • VMware 虚拟网卡防火墙问题

    看了很多人遇到过一段时间会自己删除虚拟网卡的问题 xff0c 这里做一个补充 xff0c 关于防火墙问题 xff0c 如下 这里点进去 点击更改设置 xff08 先找到下图这一项 xff09 最后记得保存更改 xff0c 关于VMware的

随机推荐

  • postman汉化包下载

    postman汉化包 https github com hlmd Postman cn releases postman官网下载地址 Download Postman Get Started for Free
  • 一帧数据接收方法

    最近在做485数据通讯 xff0c 遇到一些通讯问题 xff0c 特意去查找资料 xff0c 一帧数据接收有三种方法 xff0c 现分享如下 xff1a 第一种方法 xff1a 根据帧头和帧尾进行校验 xff0c 串口发送2字节例如 xff
  • 如何使用RTKLIB进行RTK定位(一)

    今天从这个demo xff0c 教给大家如何使用RTKLIB进行RTK定位 xff0c 包括配置文件 数据等 xff1b RTKLIB源码和exe下载地址 xff1a RTKLIB An Open Source Program Packag
  • C++ “::” 作用域符 双冒号

    一 是作用域符 xff0c 是运算符中等级最高的 xff0c 它分为三种 1 global scope 全局作用域符 xff09 xff0c 用法 xff08 name 2 class scope 类作用域符 xff09 xff0c 用法
  • OpenMv测距(Apriltag)

    利用OpenMv测离Apriltag的距离 xff08 其他色块啥的算法都差不多 xff0c 主要是Apriltag精确一些 xff09 span class token comment 本次利用OpenMv单目测距Apriltag离摄像头
  • CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Qt5Core/Qt5CoreConfig.cmake:27 (message)

    CMake Error at usr lib x86 64 linux gnu cmake Qt5Core Qt5CoreConfig cmake 27 message 在catkin make的时候 xff0c 如果提示 so文件报错 x
  • Deep-Sort多目标追踪算法代码解析

    Deep SORT是多目标跟踪 Multi Object Tracking 中常用到的一种算法 xff0c 是一个Detection Based Tracking的方法 这个算法工业界关注度非常高 xff0c 在知乎上有很多文章都是使用了D
  • 红黑树的查找时间复杂度O(logn)

    红黑树查找时间复杂度 如果二叉排序树是平衡的 xff0c 则n个节点的二叉排序树的高度为Log2n 43 1 其查找效率为O Log2n xff0c 近似于折半查找 如果二叉排序树完全不平衡 xff0c 则其深度可达到n xff0c 查找效
  • Ubuntu16.04环境下STM32和ROS间的串口通信

    目录 前言介绍 lt 1 gt 最终协议的样子 lt 2 gt 本方案提供的API实现的功能 原理 lt 1 gt 简要叙述 lt 2 gt 这里是如何使用共用体的 xff1f 前期准备 lt 1 gt 确保硬件连接 lt 2 gt 查看串
  • C++版本OpenCv教程(三十五 )Laplacian算子

    上述的边缘检测算子都具有方向性 xff0c 因此需要分别求取X方向的边缘和Y方向的边缘 xff0c 之后将两个方向的边缘综合得到图像的整体边缘 Laplacian算子具有各方向同性的特点 xff0c 能够对任意方向的边缘进行提取 xff0c
  • 【从零开始学深度学习编译器】五,TVM Relay以及Pass简介

    TVM Relay以及Pass简介 0x0 介绍0x2 Relay介绍0x2 1 使用Relay建立一个计算图0x2 2 Module xff1a 支持多个函数 xff08 Graphs xff09 0x2 3 Let Binding an
  • 模型量化的原理与实践 —基于YOLOv5实践目标检测的PTQ与QAT量化

    这里写自定义目录标题 一 量化基础知识 1 1 Tops是什么意思 1 2 什么是定点数 1 3 定点数转换 1 4 什么是量化 1 5 定点计算 1 5 1 定点计算 误差计算 1 5 2 定点计算 内存对比 1 5 3 定点计算 速度对
  • TensorRT INT8量化说明文档

    TensorRT developer guide intro quantization 7 Working with INT8 7 1 Introduction to Quantization 7 1 1 Quantization Work
  • YOLO-NAS讲解

    Meet YOLO NAS New YOLO Object Detection Model Beats YOLOv6 amp YOLOv8 代码链接 What is YOLO NAS What does the NAS in YOLO NA
  • Windows下jupyter notebook的安装和使用

    1 安装 xff1a xff08 1 xff09 首先打开Windows命令终端 xff1a 输入命令 xff1a pip install jupyter notebook 慢慢等待安装完成就可以了 我的是已经是安装完成了 在命令行窗口中输
  • 无人驾驶模型预测控制carSIM和MATLAB联合仿真

    本例参照龚建伟的 无人驾驶车辆模型预测控制 书中第四章节 1 carSIM软件介绍 carSIM是由美国MSC公司开发的车辆动力学仿真软件 xff0c 它可以方便灵活地定义实验环境和试验过程 xff0c 准确预测和仿真汽车的操纵稳定性 动力
  • Ubuntu之间通过有线网sftp传输文件

    两台Ubuntu设备之间有线网直连 xff0c 通过sftp传输文件 xff1a 打开有线连接 xff0c 配置ipv4 xff0c 可参考下图 xff1a 两台Ubuntu设备使用同一个网关 xff0c 但是地址ip必须不同 xff0c
  • 虚拟机VMware15中安装Ubuntu18.04步骤

    先安装虚拟机VMware15 xff1a 下载地址 xff1a Windows 10 64位下载链接 xff1a pan baidu com s 1Q9MVsEzVVoeOb99lQ1tsVQ 提取码 xff1a dggh Windows
  • 机械手基础知识(2)之机械手的正运动学和逆运动学问题

    开篇总结 xff1a 机械手运动学是机器人控制中的重要研究内容 xff0c 得知机械手各关节变量的大小 xff0c 可以计算出机械手末端的位姿 xff0c 这个过程叫做机械手的正向运动学 xff1b 获得机械手末端在笛卡尔空间中的位姿 xf
  • 一看就懂的LSTM+Attention,此处用softmax求概率

    1 序言 首先 xff0c 我是看这两篇文章的 但是 xff0c 他们一个写的很笼统 xff0c 一个是根据Encoder Decoder和Query key value 第二个讲的太深奥了 xff0c 绕来绕去 xff0c 看了两天才知道