深度学习---------------------------------自注意力和位置编码

news2024/11/23 21:54:36

目录

  • 自注意力
  • 跟CNN、RNN对比
  • 位置编码
    • 位置编码矩阵
  • 绝对位置信息
  • 相对位置信息
  • 总结
  • 自注意力和位置编码
    • 自注意力
      • 该部分总代码
    • 位置编码
      • 该部分总代码
    • 二进制表示
      • 在编码维度上降低频率
      • 该部分总代码

自注意力

给定一个由词元组成的输入序列 x 1 x_1 x1,…, x n x_n xn,∀ x i x_i xi R d R^d Rd

自注意力池化层 x i x_i xi当作key、value、query来对序列抽取特征得到 y 1 y_1 y1,… y n y_n yn,这里

在这里插入图片描述

在这里插入图片描述




跟CNN、RNN对比

在这里插入图片描述

CNN:k:窗口的大小(每次看一个k大小的东西)
     n:序列长度
     d:输入和输出的通道数量

并行度:每一个输出可以自己并行做运算.

最长路径:O(n/k)

在这里插入图片描述



RNN:
时间复杂度:序列长度为为n,当更新循环神经网络的隐状态时, d×d的权重矩阵和d维隐状态的乘法计算复杂度为O( d 2 d^2 d2),所以复杂度为O(n d 2 d^2 d2)

并行度:每一个 y i y_i yi的输出要等 y i − 1 y_{i-1} yi1算完

在这里插入图片描述

最长路径 x 1 x_1 x1的信息要一直传递到 x n x_n xn,需要经过一个O(n)的一个序列。

在这里插入图片描述



自注意力在自注意力中,查询、键和值都是n×d矩阵。其中n×d矩阵乘以d×n矩阵,之后输出的n×n矩阵乘以n×d矩阵。因此,自注意力具有O( n 2 d n^2d n2d)计算复杂度。

并行度:O(n)

最长路径:O(1),也就是说任何一个地方的信息要到任何一个输出的话,是可以直接过去的。

在这里插入图片描述
自注意力适合比较长的文本,因为能看的比较宽。但计算复杂度比较高。




位置编码

跟CNN/RNN不同,自注意力并没有记录位置信息

如果纯用自注意力机制来做序列模型的话,那么没有位置信息,那肯定是有问题的。所以一个加入位置信息的办法是位置编码。
它不是把位置信息加入到模型里面,因为一旦位置信息加入到模型里面总会有各种问题,CNN的会导致每一次得看一个比较长的序列,RNN的话并行度就低了,所以不是改变注意力机制本身,然后就把位置编码信息放到输入里,让输入有位置信息。

    假设长度为n的序列是X∈ R n × d R^{n×d} Rn×d,那么使用位置编码矩阵P∈ R n × d R^{n×d} Rn×d来输出X+P作为自编码输入。

P的元素计算:

在这里插入图片描述


位置编码矩阵

在这里插入图片描述
X坐标是它的一个行数,就是说对第i个序列加的那个值是什么?然后四根曲线对应的是第6、7、8、9列

对每一个样本,它的维度每一个加的值是不一样的。样本和样本之间也是不一样的。

在这里插入图片描述
在这里插入图片描述




绝对位置信息

在这里插入图片描述




相对位置信息

在这里插入图片描述




总结

①自注意力池化层将 x i x_i xi当做key、value、query来对序列抽取特征。

②完全并行、最长序列为1、但对长序列计算复杂度高。

③位置编码在输入中加入位置信息,使得自注意力能够记忆位置信息。




自注意力和位置编码

import math
import torch
from torch import nn
from d2l import torch as d2l



自注意力

from d2l import torch as d2l

num_hiddens, num_heads = 100, 5
# 创建多头注意力实例
# 输入参数为隐藏单元数量、查询维度、键维度、值维度、头的数量和dropout率
attention = d2l.MultiHeadAttention(num_hiddens, num_hiddens, num_hiddens,
                                   num_hiddens, num_heads, 0.5)
# 将多头注意力设置为评估模式,不进行训练
print(attention.eval())

在这里插入图片描述


# 设置批量大小、查询数和有效长度
batch_size, num_queries, valid_lens = 2, 4, torch.tensor([3, 2])
X = torch.ones((batch_size, num_queries, num_hiddens))
# 对输入张量X应用多头注意力机制,并获取输出的形状
print(attention(X, X, X, valid_lens).shape)

在这里插入图片描述


该部分总代码

from d2l import torch as d2l

num_hiddens, num_heads = 100, 5
# 创建多头注意力实例
# 输入参数为隐藏单元数量、查询维度、键维度、值维度、头的数量和dropout率
attention = d2l.MultiHeadAttention(num_hiddens, num_hiddens, num_hiddens,
                                   num_hiddens, num_heads, 0.5)
attention.eval()
# 设置批量大小、查询数和有效长度
batch_size, num_queries, valid_lens = 2, 4, torch.tensor([3, 2])
X = torch.ones((batch_size, num_queries, num_hiddens))
# 对输入张量X应用多头注意力机制,并获取输出的形状
print(attention(X, X, X, valid_lens).shape)



位置编码

class PositionalEncoding(nn.Module):
    # 初始化函数,接收隐藏单元数量、dropout率和最大序列长度作为输入
    def __init__(self, num_hiddens, dropout, max_len=1000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(dropout)
        # 创建一个形状为(batch_size, max_len, num_hiddens)的位置编码张量P,初始化为全0
        self.P = torch.zeros((1, max_len, num_hiddens))
        # 生成位置编码矩阵X,其中每一行表示一个位置的编码,编码方式采用sin和cos函数
        # 编码公式:X[i, j] = sin(i / 10000^(2j / num_hiddens)) 或 cos(i / 10000^(2j / num_hiddens))
        X = torch.arange(max_len, dtype=torch.float32).reshape(-1, 1) / torch.pow(10000, torch.arange(0, num_hiddens, 2,
                                                                                                      dtype=torch.float32) / num_hiddens)
        # 第一维度、第二维的所有元素,第三维将位置编码矩阵中的偶数维度的元素替换为sin函数的结果
        self.P[:, :, 0::2] = torch.sin(X)
        # 将位置编码矩阵中的奇数维度的元素替换为cos函数的结果
        self.P[:, :, 1::2] = torch.cos(X)

    def forward(self, X):
        # 将位置编码张量P与输入张量X相加,并将结果移动到与X相同的设备上
        # self.P[:, :X.shape[1], :]第二维从索引0到 X 的第二维大小的所有元素➡确保P的第二维和X的第二维一致,因为可能是不同的序列长度,为了动态的适应不同长度的输入
        X = X + self.P[:, :X.shape[1], :].to(X.device)
        # 对相加后的结果应用dropout,并返回结果
        return self.dropout(X)



该部分总代码

import torch
from torch import nn
from d2l import torch as d2l


# 位置编码
class PositionalEncoding(nn.Module):
    # 初始化函数,接收隐藏单元数量、dropout率和最大序列长度作为输入
    def __init__(self, num_hiddens, dropout, max_len=1000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(dropout)
        # 创建一个形状为(batch_size, max_len, num_hiddens)的位置编码张量P,初始化为全0
        self.P = torch.zeros((1, max_len, num_hiddens))
        # 生成位置编码矩阵X,其中每一行表示一个位置的编码,编码方式采用sin和cos函数
        # 编码公式:X[i, j] = sin(i / 10000^(2j / num_hiddens)) 或 cos(i / 10000^(2j / num_hiddens))
        X = torch.arange(max_len, dtype=torch.float32).reshape(-1, 1) / torch.pow(10000, torch.arange(0, num_hiddens, 2,
                                                                                                      dtype=torch.float32) / num_hiddens)
        # 第一维度、第二维的所有元素,第三维将位置编码矩阵中的偶数维度的元素替换为sin函数的结果
        self.P[:, :, 0::2] = torch.sin(X)
        # 将位置编码矩阵中的奇数维度的元素替换为cos函数的结果
        self.P[:, :, 1::2] = torch.cos(X)

    def forward(self, X):
        # 将位置编码张量P与输入张量X相加,并将结果移动到与X相同的设备上
        # self.P[:, :X.shape[1], :]第二维从索引0到 X 的第二维大小的所有元素➡确保P的第二维和X的第二维一致,因为可能是不同的序列长度,为了动态的适应不同长度的输入
        X = X + self.P[:, :X.shape[1], :].to(X.device)
        # 对相加后的结果应用dropout,并返回结果
        return self.dropout(X)


num_hiddens, num_heads = 100, 5
# 创建多头注意力实例
# 输入参数为隐藏单元数量、查询维度、键维度、值维度、头的数量和dropout率
attention = d2l.MultiHeadAttention(num_hiddens, num_hiddens, num_hiddens,
                                   num_hiddens, num_heads, 0.5)
# 将多头注意力设置为评估模式,不进行训练
attention.eval()

# 设置批量大小、查询数和有效长度
batch_size, num_queries, valid_lens = 2, 4, torch.tensor([3, 2])
X = torch.ones((batch_size, num_queries, num_hiddens))
# 对输入张量X应用多头注意力机制,并获取输出的形状
print(attention(X, X, X, valid_lens).shape)




行代表标记在序列中的位置,列代表位置编码的不同维度。

import torch
from torch import nn
from d2l import torch as d2l


# 位置编码
class PositionalEncoding(nn.Module):
    # 初始化函数,接收隐藏单元数量、dropout率和最大序列长度作为输入
    def __init__(self, num_hiddens, dropout, max_len=1000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(dropout)
        # 创建一个形状为(batch_size, max_len, num_hiddens)的位置编码张量P,初始化为全0
        self.P = torch.zeros((1, max_len, num_hiddens))
        # 生成位置编码矩阵X,其中每一行表示一个位置的编码,编码方式采用sin和cos函数
        # 编码公式:X[i, j] = sin(i / 10000^(2j / num_hiddens)) 或 cos(i / 10000^(2j / num_hiddens))
        X = torch.arange(max_len, dtype=torch.float32).reshape(-1, 1) / torch.pow(10000, torch.arange(0, num_hiddens, 2,
                                                                                                      dtype=torch.float32) / num_hiddens)
        # 第一维度、第二维的所有元素,第三维将位置编码矩阵中的偶数维度的元素替换为sin函数的结果
        self.P[:, :, 0::2] = torch.sin(X)
        # 将位置编码矩阵中的奇数维度的元素替换为cos函数的结果
        self.P[:, :, 1::2] = torch.cos(X)

    def forward(self, X):
        # 将位置编码张量P与输入张量X相加,并将结果移动到与X相同的设备上
        # self.P[:, :X.shape[1], :]第二维从索引0到 X 的第二维大小的所有元素➡确保P的第二维和X的第二维一致,因为可能是不同的序列长度,为了动态的适应不同长度的输入
        X = X + self.P[:, :X.shape[1], :].to(X.device)
        # 对相加后的结果应用dropout,并返回结果
        return self.dropout(X)


# 设置位置编码的维度和序列的长度
encoding_dim, num_steps = 32, 60
pos_encoding = PositionalEncoding(encoding_dim, 0)
pos_encoding.eval()
# 应用位置编码器到全0张量上,得到位置编码后的张量X
X = pos_encoding(torch.zeros((1, num_steps, encoding_dim)))
# 获取位置编码器中的位置编码张量P,截取与X相同长度的部分
P = pos_encoding.P[:, :X.shape[1], :]
# 绘制位置编码张量P中特定维度的子集
d2l.plot(torch.arange(num_steps), P[0, :, 6:10].T, xlabel='Row (position)',
        figsize=(6, 2.5), legend=["Col %d" % d for d in torch.arange(6, 10)])
d2l.plt.show()


在这里插入图片描述




二进制表示

for i in range(8):
    # 打印当前数字的二进制表示,使用字符串格式化进行对齐和补零
    print(f'{i} in binary is {i:>03b}')

在这里插入图片描述


在编码维度上降低频率

# 在编码维度上降低频率
# 从位置编码张量P中获取第一个样本的编码部分,并添加两个维度
P = P[0, :, :].unsqueeze(0).unsqueeze(0)
# 显示热力图,以编码维度为x轴,位置为y轴
d2l.show_heatmaps(P, xlabel='Column (encoding dimension)',
                  ylabel='Row (position)', figsize=(3.5, 4), cmap='Blues')

在这里插入图片描述



该部分总代码

import torch
from torch import nn
from d2l import torch as d2l


# 位置编码
class PositionalEncoding(nn.Module):
    # 初始化函数,接收隐藏单元数量、dropout率和最大序列长度作为输入
    def __init__(self, num_hiddens, dropout, max_len=1000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(dropout)
        # 创建一个形状为(batch_size, max_len, num_hiddens)的位置编码张量P,初始化为全0
        self.P = torch.zeros((1, max_len, num_hiddens))
        # 生成位置编码矩阵X,其中每一行表示一个位置的编码,编码方式采用sin和cos函数
        # 编码公式:X[i, j] = sin(i / 10000^(2j / num_hiddens)) 或 cos(i / 10000^(2j / num_hiddens))
        X = torch.arange(max_len, dtype=torch.float32).reshape(-1, 1) / torch.pow(10000, torch.arange(0, num_hiddens, 2,
                                                                                                      dtype=torch.float32) / num_hiddens)
        # 第一维度、第二维的所有元素,第三维将位置编码矩阵中的偶数维度的元素替换为sin函数的结果
        self.P[:, :, 0::2] = torch.sin(X)
        # 将位置编码矩阵中的奇数维度的元素替换为cos函数的结果
        self.P[:, :, 1::2] = torch.cos(X)

    def forward(self, X):
        # 将位置编码张量P与输入张量X相加,并将结果移动到与X相同的设备上
        # self.P[:, :X.shape[1], :]第二维从索引0到 X 的第二维大小的所有元素➡确保P的第二维和X的第二维一致,因为可能是不同的序列长度,为了动态的适应不同长度的输入
        X = X + self.P[:, :X.shape[1], :].to(X.device)
        # 对相加后的结果应用dropout,并返回结果
        return self.dropout(X)


# 设置位置编码的维度和序列的长度
encoding_dim, num_steps = 32, 60
pos_encoding = PositionalEncoding(encoding_dim, 0)
pos_encoding.eval()
# 应用位置编码器到全0张量上,得到位置编码后的张量X
X = pos_encoding(torch.zeros((1, num_steps, encoding_dim)))
# 获取位置编码器中的位置编码张量P,截取与X相同长度的部分
P = pos_encoding.P[:, :X.shape[1], :]
# 在编码维度上降低频率
# 从位置编码张量P中获取第一个样本的编码部分,并添加两个维度
P = P[0, :, :].unsqueeze(0).unsqueeze(0)
# 显示热力图,以编码维度为x轴,位置为y轴
d2l.show_heatmaps(P, xlabel='Column (encoding dimension)',
                  ylabel='Row (position)', figsize=(3.5, 4), cmap='Blues')
d2l.plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2195851.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于web的网上摄影工作室的开发与实现源码+论文

项目简介 基于springboot实现的,主要功能如下: 技术栈 后端框框:springboot/mybatis 前端框架:html/JavaScript/Css/vue/elementui 运行环境:JDK1.8/MySQL5.7/idea(可选)/Maven3&#xff08…

基于ssm实现的建筑装修图纸管理平台(源码+文档)

项目简介 基于ssm实现的建筑装修图纸管理平台,主要功能如下: 技术栈 后端框框:spring/springmvc/mybatis 前端框架:html/JavaScript/Css/vue/elementui 运行环境:JDK1.8/MySQL5.7/idea(可选&#xff09…

农业政策与市场分析:解读当前政策导向下的农业发展趋势

在快速变化的全球经济格局中,农业作为国家稳定发展的基石,其政策走向与市场动态备受瞩目。本文将深入剖析当前的农业政策背景,探讨其对设计的导向作用,以及市场趋势的反馈与影响,为农业可持续发展提供洞见。 1. 政策背…

SAP学习笔记 - 豆知识11 - 如何查询某个字段/DataElement/Domain在哪个表里使用?

大家知道SAP的表有10几万个(也有说30多万个的,总之很多就是了),而且不断增多,那么当想知道一个字段在哪个表里使用的时候该怎么办呢? 思路就是SAP的表其实也是存在表里的:)&#xf…

k8s 中的 PV 的动态供给

目录 1 存储类 Storageclass 介绍 1.1 StorageClass 说明 1.2 StorageClass 的属性 2 存储分配器 NFS Client Provisioner 2.1 官网存储分配器的部署介绍 2.2 实现动态创建 PV 模版清单文件的介绍 2.2.1 Storageclass 存储类的模版 2.2.2 创建 Provisioner 制备器的模版 2.2.3…

数据结构与算法——动态规划算法简析

1.初步了解动态规划 由于本篇博客属于动态规划的初阶学习,所以大多都是简单的表示,更深层次的学术用语会在之后深度学习动态规划之后出现,本文主要是带各位了解一下动态规划的大致框架 1.1状态表示 通常的我们会开辟一个dp数组来存储需要表示…

centos7 yum仓库无法使用的问题

1、问题 如下 2、按照csdn等网页说的做了没有用!CentOS-yum源不可用报错:Could not retrieve mirrorlist 问题解决_yum could not retrieve mirrorlist-CSDN博客 3、使用b站博主的方法解决! LinuxMirrors: GNU/Linux 一键更换系统软件源脚本…

切片辅助超推理-sahi库-slice_image使用

代码地址:https://github.com/obss/sahi slice_image是sahi库中一个函数,理解这个函数是理解切片的入口。 一、官方函数使用示例 from sahi.slicing import slice_imageimage_pathrsmall-vehicles1.jpeg output_dirrashi_result output_file_name1-#手…

LeetCode 3311. 构造符合图结构的二维矩阵

LeetCode 3311. 构造符合图结构的二维矩阵 给你一个二维整数数组 edges ,它表示一棵 n 个节点的 无向 图,其中 edges[i] [ui, vi] 表示节点 ui 和 vi 之间有一条边。 请你构造一个二维矩阵,满足以下条件: 矩阵中每个格子 一一对应…

力扣之1336.每次访问的交易次数

题目: sql建表语句: Create table If Not Exists Visits (user_id int, visit_date date); Create table If Not Exists Transactions (user_id int, transaction_date date, amount int); Truncate table Visits; insert into Visits (user_id,…

如何让客户主动成为你的品牌大使

在销售领域,转介绍被公认为一把无坚不摧的利器,它不仅铸就了高成交率的辉煌,更以惊人的速度缩短了成交周期。一位精通转介绍艺术的销售员,其业绩自然熠熠生辉,工作之路亦显得游刃有余。 然而,面对这一宝藏…

Bianchi模型、python计算及ns3验证_关于2~10 STA验证的补充

首先就是预设修改, NS3中bitrate是OfdmRate54Mbps,STA数目我设置了2-10,ack长度是14bytes,数据长36,头36(trace中只有1536和14两个长度,也就是数据长度1500,头36,ack14),SIFS和SLOT是16us和9us(在phy的定义中,11a的时候,sifs是16,slot是9),difs是34us(在bia…

2024Java最新面试题总结(针对于一些小厂、中厂)

这是根据个人面试经历总结出来的一些经验希望可以帮助到有需要的人。 面试的时候,会先让你进行自我介绍,这个大家准备一两分钟的面试稿就可以。然后就是正式面试,面试官一般是两个人以上,开始,面试官会先提问一些基本…

【NLP自然语言处理】01-基础学习路径简介

目的:让大家能够在 AI-NLP 领域由基础到入门具体安排: NLP介绍 文本预处理RNN 及其变体(涉及案例)Transformer 原理详解迁移学习 和 Bert 模型详解 (涉及案例)特点: 原理 实践每个文章会有练习…

Nat. Commun.:飞秒激光书写受蚂蚁启发的可重构微型机器人集体

背景介绍生物在各种环境中的集体行为十分普遍,它们能够自发有序地完成单个个体难以完成的任务。目前,生物集体的形成主要分为两大类。第一类生物个体之间没有直接接触,如蜜蜂、鱼和鸟类,这导致这些集体不稳定,容易受到…

Ubuntu24 Firefox和Window Firefox同步问题

由于平常开发在Ubuntu系统,但是日常学习查资料又在Window系统,查资料保存网页到浏览器中时,经常遇到两个平台标签同步问题,希望可以选一个支持Ubuntu、Window的浏览器。 选用Google Chrome浏览器,确实挺好用&#xff…

微服务seata解析部署使用全流程

官网地址: Seata 是什么? | Apache Seata 1、Seata术语 用来管理分布式事务,由阿里巴巴出品。 【1、TC (Transaction Coordinator) - 事务协调者】 用来维护事务的,包括主事务和分支事务。 【2、TM (Transaction Manager) - …

TCP与UDP协议(三次握手四次挥手)

TCP与UDP 简介TCP和UDP一、TCP1.1 TCP的三次握手问题来了:为啥是三次握手而不是两次呢? 1.2建立连接后的通信过程(丢包与乱序问题)1.3四次挥手问题来了:为什么要四次挥手? 二、UDP 简介TCP和UDP TCP、UDP都…

机器学习笔记(持续更新)

重复值处理: 重复值处理代码: import pandas as pd data pd.DataFrame({学号: [1, 2, 3, 4, 5, 6, 7, 7, 8],身高: [172,162,175,170,168,160,164,164,160],体重: [70,62,75,68,67,58,64,64,53] }) data.drop_duplicates([学号], keep last, inplaceT…

SQL第13课挑战题

1. 使用inner join,以检索每个顾客的名称(customers表中的cust_name)和所有的订单号(orders表中的order_num). 2. 修改第一题,仅列出所有顾客,及时他们没有下过订单。 3. 使用outer join联结products表和or…