【Transformer】手撕Attention

import torch  
from torch import nn   
import torch.functional as F  
import mathX = torch.randn(16,64,512) # B,T,Dd_model = 512 # 模型的维度  
n_head = 8 # 注意力头的数量

多头注意力机制

在这里插入图片描述

class multi_head_attention(nn.Module):  def __init__(self, d_model, n_head):  # 调用父类构造函数  super(multi_head_attention, self).__init__()  # 保存注意力头的数量和模型的维度  self.n_head = n_head  self.d_model = d_model  # 定义查询(Q)、键(K)、值(V)的线性变换层  self.w_q = nn.Linear(d_model, d_model)  # 输入d_model维度,输出d_model维度  self.w_k = nn.Linear(d_model, d_model)  # 输入d_model维度,输出d_model维度  self.w_v = nn.Linear(d_model, d_model)  # 输入d_model维度,输出d_model维度  self.w_o = nn.Linear(d_model, d_model)  # 输出线性变换层,用来做一个线形缩放  # 定义softmax函数,用于计算注意力得分的归一化  self.softmax = nn.Softmax(dim=-1)  # softmax会在最后一维(dim=-1)上操作  def forward(self, q, k, v):  # 获取输入查询(q),键(k),值(v)的形状  B, T, D = q.shape  # B: batch size, T: sequence length, D: feature dimension (d_model)  # 每个注意力头的维度  n_d = self.d_model // self.n_head  # 每个头的维度(d_model / n_head)  # 将输入的q、k、v通过各自的线性变换层映射到新的空间  q, k, v = self.w_q(q), self.w_k(k), self.w_v(v)  # 将q, k, v 按头数进行拆分(reshape),并转置使得各头的计算可以并行  # q, k, v的形状变为 (B, T, n_head, n_d),然后转置变为 (B, n_head, T, n_d)        q = q.view(B, T, self.n_head, n_d).transpose(1, 2)  # (B, n_head, T, n_d)  k = k.view(B, T, self.n_head, n_d).transpose(1, 2)  # (B, n_head, T, n_d)  v = v.view(B, T, self.n_head, n_d).transpose(1, 2)  # (B, n_head, T, n_d)  # 计算缩放点积注意力(scaled dot-product attention)  score = q @ k.transpose(2, 3) / math.sqrt(n_d)  # (B, n_head, T, T)  # score是查询q与键k之间的相似度矩阵,进行缩放以防止数值过大  # 生成一个下三角矩阵,用于实现自注意力中的"masking",屏蔽未来的信息  mask = torch.tril(torch.ones(T, T, dtype=bool))  # 生成一个下三角的布尔矩阵  # 使用mask进行屏蔽,mask为0的位置会被填充为一个非常大的负值(-10000)  score = score.masked_fill(mask == 0, -10000)  # 把mask == 0的位置置为-10000  # 对score进行softmax归一化处理,得到注意力权重  score = self.softmax(score)  # (B, n_head, T, T)  # 将注意力权重与值(v)相乘,得到加权后的值  score = score @ v  # (B, n_head, T, n_d)  # 将多个头的结果合并(concatenate),并通过线性层进行映射  # 首先将score的维度变为 (B, T, n_head * n_d),然后通过w_o进行线性变换  x_concate = score.transpose(1, 2).contiguous().view(B, T, self.d_model)  # (B, T, d_model)  x_output = self.w_o(x_concate)  # (B, T, d_model)  # 返回最终的输出  return x_output  attn = multi_head_attention(d_model, n_head)  
Y = attn(X,X,X)  
print(Y.shape)

层归一化

# layer norm  
class layer_norm(nn.Module):  def __init__(self, d_model, eps = 1e-12):  super(layer_norm, self).__init__()  self.gamma = nn.Parameter(torch.ones(d_model))  self.beta = nn.Parameter(torch.zeros(d_model))  self.eps = eps  def forward(self, x):  mean = x.mean(-1, keepdim = True)  var = x.var(-1, unbiased=False, keepdim = True)  out = (x - mean) / torch.sqrt(var + self.eps)  out = self.gamma * out + self.beta  return out  d_model = 512  
X = torch.randn(2,5,512) # 2句话, 5个token,词向量512  
ln = layer_norm(d_model)  
print("d_model: ", d_model)  
print(f"ln gamma: {ln.gamma.shape}")  
print(f"ln beta: {ln.beta.shape}")  
Y_ln = ln(X)  
print(Y_ln.shape)

这段代码实现了一个多头注意力机制(Multi-Head Attention),这是Transformer模型中的核心组件之一。多头注意力机制允许模型在处理序列数据时,同时关注序列中不同位置的信息,并且可以从不同的子空间中学习到不同的特征表示。

层归一化

代码解读

1. 初始化部分 (__init__ 方法)
def __init__(self, d_model, n_head):super(multi_head_attention, self).__init__()self.n_head = n_headself.d_model = d_modelself.w_q = nn.Linear(d_model, d_model)self.w_k = nn.Linear(d_model, d_model)self.w_v = nn.Linear(d_model, d_model)self.w_o = nn.Linear(d_model, d_model)self.softmax = nn.Softmax(dim=-1)
  • d_model:模型的维度,即输入向量的维度。
  • n_head:注意力头的数量。
  • w_q, w_k, w_v:分别是对查询(Query)、键(Key)、值(Value)进行线性变换的层,将输入映射到新的空间。
  • w_o:输出线性变换层,用于将多个头的输出合并并映射回原始维度。
  • softmax:用于对注意力得分进行归一化。
2. 前向传播部分 (forward 方法)
def forward(self, q, k, v):B, T, D = q.shapen_d = self.d_model // self.n_headq, k, v = self.w_q(q), self.w_k(k), self.w_v(v)q = q.view(B, T, self.n_head, n_d).transpose(1, 2)k = k.view(B, T, self.n_head, n_d).transpose(1, 2)v = v.view(B, T, self.n_head, n_d).transpose(1, 2)
  • B:批量大小(batch size)。
  • T:序列长度(sequence length)。
  • D:特征维度(feature dimension),即 d_model
  • n_d:每个注意力头的维度,等于 d_model / n_head
  • q, k, v:通过线性变换层映射到新的空间后,再按头数进行拆分和转置,以便并行计算。
  • [[q = q.view(B, T, self.n_head, n_d).transpose(1, 2)]]
    score = q @ k.transpose(2, 3) / math.sqrt(n_d)mask = torch.tril(torch.ones(T, T, dtype=bool))score = score.masked_fill(mask == 0, -10000)score = self.softmax(score)
  • score:计算查询 q 和键 k 之间的相似度矩阵,并进行缩放(防止数值过大)。
  • mask:生成一个下三角矩阵,用于屏蔽未来的信息(在自注意力机制中,当前时间步只能看到之前的时间步)。
  • score:通过 mask 屏蔽未来的信息,并对得分进行 softmax 归一化,得到注意力权重。
  • [[mask = torch.tril(torch.ones(T, T, dtype=bool))]]
    score = score @ vx_concate = score.transpose(1, 2).contiguous().view(B, T, self.d_model)x_output = self.w_o(x_concate)return x_output
  • score @ v:将注意力权重与值 v 相乘,得到加权后的值。
  • x_concate:将多个头的输出合并(concatenate),并通过 w_o 进行线性变换,得到最终的输出。
  • [[x_concate = score.transpose(1, 2).contiguous().view(B, T, self.d_model)]]
3. 使用示例
attn = multi_head_attention(d_model, n_head)
Y = attn(X, X, X)
print(Y.shape)
  • attn:创建一个多头注意力机制的实例。
  • Y = attn(X, X, X):将输入 X 分别作为查询、键、值传入多头注意力机制,得到输出 Y
  • print(Y.shape):输出 Y 的形状,通常与输入 X 的形状相同,即 (B, T, d_model)

总结

这段代码实现了一个完整的多头注意力机制,包括线性变换、缩放点积注意力、掩码处理、softmax归一化、多头结果的合并和最终的线性变换。多头注意力机制是Transformer模型的核心组件,广泛应用于自然语言处理、计算机视觉等领域。

这段代码实现了一个层归一化(Layer Normalization)模块

层归一化是深度学习中常用的一种归一化技术,用于稳定训练过程并加速收敛


1. 初始化部分 (__init__ 方法)

def __init__(self, d_model, eps=1e-12):super(layer_norm, self).__init__()self.gamma = nn.Parameter(torch.ones(d_model))self.beta = nn.Parameter(torch.zeros(d_model))self.eps = eps
  • d_model:输入特征的维度(即词向量的维度)。
  • gammabeta
  • gamma可学习缩放参数,初始值为全 1,形状为 (d_model,)
    • beta可学习偏移参数,初始值为全 0,形状为 (d_model,)
    • 这两个参数用于对归一化后的数据进行缩放和偏移,以增强模型的表达能力。
  • eps:一个小常数,用于防止分母为零的情况,通常设置为 1e-12

2. 前向传播部分 (forward 方法)

def forward(self, x):mean = x.mean(-1, keepdim=True)var = x.var(-1, unbiased=False, keepdim=True)out = (x - mean) / torch.sqrt(var + self.eps)out = self.gamma * out + self.betareturn out
  • 输入 x:假设 x 的形状为 (B, T, d_model),其中:

    • B 是批量大小(batch size)。
    • T 是序列长度(sequence length)。
    • d_model 是特征维度(即词向量的维度)。
  • 步骤 1:计算均值和方差

    • mean = x.mean(-1, keepdim=True):沿着最后一个维度(d_model)计算均值,形状为 (B, T, 1)
    • var = x.var(-1, unbiased=False, keepdim=True):沿着最后一个维度计算方差,形状为 (B, T, 1)
    • unbiased=False 表示计算方差时不使用无偏估计(即除以 n 而不是 n-1)。
  • 步骤 2:归一化

    • out = (x - mean) / torch.sqrt(var + self.eps):对输入 x 进行归一化,减去均值并除以标准差(加上 eps 防止除零)。
  • 步骤 3:缩放和偏移

    • out = self.gamma * out + self.beta:对归一化后的数据进行缩放和偏移,gammabeta 是可学习的参数。
  • 输出 out:形状与输入 x 相同,为 (B, T, d_model)


3. 代码运行示例

d_model = 512
X = torch.randn(2, 5, 512)  # 2句话, 5个token,词向量512
ln = layer_norm(d_model)
print("d_model: ", d_model)
print(f"ln gamma: {ln.gamma.shape}")
print(f"ln beta: {ln.beta.shape}")
Y_ln = ln(X)
print(Y_ln.shape)
  • 输入 X:形状为 (2, 5, 512),表示 2 个句子,每个句子有 5 个 token,每个 token 的词向量维度为 512。
  • ln.gammaln.beta
    • ln.gamma 的形状为 (512,)
    • ln.beta 的形状为 (512,)
  • 输出 Y_ln:形状与输入 X 相同,为 (2, 5, 512)

4. 层归一化的作用

  • 稳定训练:通过对每个样本的特征进行归一化,减少内部协变量偏移(Internal Covariate Shift),从而稳定训练过程。
  • 加速收敛:归一化后的数据分布更加稳定,有助于加速模型的收敛。
  • 增强表达能力:通过可学习的参数 gammabeta,模型可以学习到适合当前任务的归一化方式。

5. 与批量归一化(Batch Normalization)的区别

  • 批量归一化:沿着批量维度(B)计算均值和方差,适用于批量较大的情况。
  • 层归一化:沿着特征维度(d_model)计算均值和方差,适用于序列数据(如 NLP 中的句子)或批量较小的情况。

6. 总结

  • 这段代码实现了一个层归一化模块,对输入的特征进行归一化,并通过可学习的参数 gammabeta 进行缩放和偏移。
  • 层归一化在 Transformer 等模型中广泛应用,用于稳定训练和加速收敛。
  • 输入形状为 (B, T, d_model),输出形状与输入相同。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】 冯诺依曼体系与计算机系统架构全解

Linux相关知识点可以通过点击以下链接进行学习一起加油!初识指令指令进阶权限管理yum包管理与vim编辑器GCC/G编译器make与Makefile自动化构建GDB调试器与Git版本控制工具Linux下进度条 冯诺依曼体系是现代计算机设计的基石,其统一存储和顺序执行理念推动…

冯·诺依曼体系结构

目录 冯诺依曼体系结构推导 内存提高冯诺依曼体系结构效率的方法 你使用QQ和朋友聊天时,整个数据流是怎么流动的(不考虑网络情况) 与冯诺依曼体系结构相关的一些知识 冯诺依曼体系结构推导 计算机的存在就是为了解决问题,而解…

全面认识了解DeepSeek+利用ollama在本地部署、使用和体验deepseek-r1大模型

文章目录 一、DeepSeek简介二、技术特点三、架构设计3.1、DeepSeek-V33.2、DeepSeek-V23.3、DeepSeek-R1 四、DeepSeek算法4.1、DeepSeek LLM 算法4.2、DeepSeek-V2 算法4.3、DeepSeek-R1 算法4.4、DeepSeek 在算力优化上的算法 五、DeepSeek的使用六、本地部署DeepSeek R1模型…

Python 梯度下降法(七):Summary

文章目录 Python 梯度下降法(七):Summary一、核心思想1.1 核心思想1.2 优化方法概述1.3 第三方库的使用 二、 BGD2.1 介绍2.2 torch 库算法2.2 代码示例2.3 SGD2.4 SGD代码示例2.5 MBGD2.6 MBGD 代码示例 三、 Adagrad3.1 介绍3.2 torch 库算…

SpringBoot Web开发(SpringMVC)

SpringBoot Web开发(SpringMVC) MVC 核心组件和调用流程 Spring MVC与许多其他Web框架一样,是围绕前端控制器模式设计的,其中中央 Servlet DispatcherServlet 做整体请求处理调度! . 除了DispatcherServletSpringMVC还会提供其他…

Web_php_unserialize

代码审计 <?php class Demo { private $file index.php;public function __construct($file) { $this->file $file; }、 //接收一个参数 $file 并赋值给私有属性 $filefunction __destruct() { echo highlight_file($this->file, true); } //在对象销毁时调用&…

Spring Web MVC基础第一篇

目录 1.什么是Spring Web MVC&#xff1f; 2.创建Spring Web MVC项目 3.注解使用 3.1RequestMapping&#xff08;路由映射&#xff09; 3.2一般参数传递 3.3RequestParam&#xff08;参数重命名&#xff09; 3.4RequestBody&#xff08;传递JSON数据&#xff09; 3.5Pa…

安装anaconda3 后 电脑如何单独运行python,python还需要独立安装吗?

安装anaconda3 后 电脑如何单独运行python&#xff0c;python还需要独立安装吗? 电脑第一此安装anaconda用于jupyter notebook使用。 但是在运行cmd的时候&#xff0c;输入python --version 显示未安装或跳转商店提示安装。 明明我可以运行python但是为什么cmd却说我没安装呢…

分布式事务组件Seata简介与使用,搭配Nacos统一管理服务端和客户端配置

文章目录 一. Seata简介二. 官方文档三. Seata分布式事务代码实现0. 环境简介1. 添加undo_log表2. 添加依赖3. 添加配置4. 开启Seata事务管理5. 启动演示 四. Seata Server配置Nacos1. 修改配置类型2. 创建Nacos配置 五. Seata Client配置Nacos1. 增加Seata关联Nacos的配置2. 在…

使用真实 Elasticsearch 进行高级集成测试

作者&#xff1a;来自 Elastic Piotr Przybyl 掌握高级 Elasticsearch 集成测试&#xff1a;更快、更智能、更优化。 在上一篇关于集成测试的文章中&#xff0c;我们介绍了如何通过改变数据初始化策略来缩短依赖于真实 Elasticsearch 的集成测试的执行时间。在本期中&#xff0…

OpenEuler学习笔记(十四):在OpenEuler上搭建.NET运行环境

一、在OpenEuler上搭建.NET运行环境 基于包管理器安装 添加Microsoft软件源&#xff1a;运行命令sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm&#xff0c;将Microsoft软件源添加到系统中&#xff0c;以便后续能够从该源安装.…

基于Python的简单企业维修管理系统的设计与实现

以下是一个基于Python的简单企业维修管理系统的设计与实现&#xff0c;这里我们会使用Flask作为Web框架&#xff0c;SQLite作为数据库来存储相关信息。 1. 需求分析 企业维修管理系统主要功能包括&#xff1a; 维修工单的创建、查询、更新和删除。设备信息的管理。维修人员…

Van-Nav:新年,将自己学习的项目地址统一整理搭建自己的私人导航站,供自己后续查阅使用,做技术的同学应该都有一个自己网站的梦想

嗨&#xff0c;大家好&#xff0c;我是小华同学&#xff0c;关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 Van-Nav是一个基于Vue.js开发的导航组件库&#xff0c;它提供了多种预设的样式和灵活的配置选项&#xff0c;使得开发者可以轻松地定制出符合项目需求…

Android 音视频编解码 -- MediaCodec

引言 如果我们只是简单玩一下音频、视频播放&#xff0c;那么使用 MediaPlayer SurfaceView 播放就可以了&#xff0c;但如果想加个水印&#xff0c;加点其他特效什么的&#xff0c;那就不行了&#xff1b; 学习 Android 自带的硬件码类 – MediaCodec。 MediaCodec 介绍 在A…

UE 5.3 C++ 对垃圾回收的初步认识

一.UObject的创建 UObject 不支持构造参数。 所有的C UObject都会在引擎启动的时候初始化&#xff0c;然后引擎会调用其默认构造器。如果没有默认的构造器&#xff0c;那么 UObject 将不会编译。 有修改父类参数的需求&#xff0c;就使用指定带参构造 // Sets default value…

使用LLaMA-Factory对AI进行认知的微调

使用LLaMA-Factory对AI进行认知的微调 引言1. 安装LLaMA-Factory1.1. 克隆仓库1.2. 创建虚拟环境1.3. 安装LLaMA-Factory1.4. 验证 2. 准备数据2.1. 创建数据集2.2. 更新数据集信息 3. 启动LLaMA-Factory4. 进行微调4.1. 设置模型4.2. 预览数据集4.3. 设置学习率等参数4.4. 预览…

2025最新源支付V7全套开源版+Mac云端+五合一云端

2025最新源支付V7全套开源版Mac云端五合一云端 官方1999元&#xff0c; 最新非网上那种功能不全带BUG开源版&#xff0c;可以自己增加授权或二开 拥有卓越的性能和丰富的功能。它采用全新轻量化的界面UI&#xff0c;让您能更方便快捷地解决知识付费和运营赞助的难题 它基于…

Linux02——Linux的基本命令

目录 ls 常用选项及功能 综合示例 注意事项 cd和pwd命令 cd命令 pwd命令 相对路径、绝对路径和特殊路径符 特殊路径符号 mkdir命令 1. 功能与基本用法 2. 示例 3. 语法与参数 4. -p选项 touch-cat-more命令 1. touch命令 2. cat命令 3. more命令 cp-mv-rm命…

[EAI-023] FAST,机器人动作专用的Tokenizer,提高VLA模型的能力和训练效率

Paper Card 论文标题&#xff1a;FAST: Efficient Action Tokenization for Vision-Language-Action Models 论文作者&#xff1a;Karl Pertsch, Kyle Stachowicz, Brian Ichter, Danny Driess, Suraj Nair, Quan Vuong, Oier Mees, Chelsea Finn, Sergey Levine 论文链接&…

LeGO LOAM坐标系问题的自我思考

LeGO LOAM坐标系问题的自我思考 总体思考流程IMU坐标系LeGO LOAM代码分析代码 对于IMU输出测量值的integration积分过程欧拉角的旋转矩阵VeloToStartIMU()函数TransformToStartIMU(PointType *p) 总体思考流程 第一页 第二页 第三页 IMU坐标系 在LeGO LOAM中IMU坐标系的形式…