多头注意力中的张量重塑

view

PyTorch 的view() 是张量「重塑(Reshape)」函数,用于改变张量的维度形状但不改变数据本身
在多头注意力中,view()的核心作用是将总隐藏维度拆分为「注意力头数 × 单头维度」,实现多头并行计算

核心规则

tensor.view(*shape)

作用:将张量重塑为指定的shape,要求「新形状的元素总数 = 原张量的元素总数」(否则报错)

核心特性:
不改变张量的底层数据,仅改变维度的 “视图”(轻量操作,无数据拷贝)
重塑后的张量与原张量共享内存(修改一个,另一个也会变)
支持用-1自动推导某一维度的大小(仅能有一个-1)

importtorch# 一维张量重塑为二维x=torch.arange(12)# shape=(12,),元素总数=12x_view1=x.view(3,4)# shape=(3,4),3×4=12x_view2=x.view(4,-1)# -1自动推导为3,shape=(4,3)print(x_view1.shape)# torch.Size([3,4])print(x_view2.shape)# torch.Size([4,3])# 三维张量重塑(核心:元素总数不变)y=torch.randn(2,6,768)# 2×6×768=9216y_view=y.view(2,6,12,64)# 2×6×12×64=9216print(y_view.shape)# torch.Size([2,6,12,64])
  1. 关键注意事项
    报错场景:新形状元素总数≠原总数 → x.view(3,5)(12≠15)会报错
    -1的用法:仅能指定一个-1,用于自动计算维度(如view(2,-1,64))
    内存连续性:若张量内存不连续(如经过transpose/permute),需先调用contiguous()再view,否则报错

多头注意力中view的核心作用

将总隐藏维度d_model拆分为num_heads × d_k(单头维度),view()是实现这一拆分的关键

完整流程如下:
步骤 1:先明确核心参数(以 BERT-base 为例)
batch_size=2(批次)、seq_len=6(序列长度);
d_model=768(总隐藏维度)、num_heads=12(注意力头数)、d_k=64(单头维度,768=12×64);
输入querys:shape=(2,6,768)(经W_query线性变换后的输出)。

步骤 2:用view()拆分注意力头

# 1. 原始querys:[batch, seq_len, d_model] = [2,6,768]querys=torch.randn(2,6,768)# 2. 拆分为多头:[2,6,12,64](batch, seq_len, num_heads, d_k)querys_heads=querys.view(2,6,12,64)print(querys_heads.shape)# torch.Size([2,6,12,64])# 3. 转置调整维度(为后续批量矩阵乘法):[2,12,6,64]# 注:transpose后内存不连续,需contiguous()才能再viewquerys_heads=querys_heads.transpose(1,2).contiguous()print(querys_heads.shape)# torch.Size([2,12,6,64])

步骤 3:注意力计算后,用view()合并多头

# 假设注意力计算后的输出:[2,12,6,64](batch, num_heads, seq_len, d_k)attn_output=torch.randn(2,12,6,64)# 1. 先转置回原维度:[2,6,12,64]attn_output=attn_output.transpose(1,2).contiguous()# 2. 合并多头:[2,6,768](还原为总隐藏维度)attn_output_merged=attn_output.view(2,6,768)print(attn_output_merged.shape)# torch.Size([2,6,768])

多头注意力完整实战代码

importtorchimporttorch.nnasnnclassMultiHeadAttention(nn.Module):def__init__(self,d_model=768,num_heads=12):super().__init__()self.d_model=d_model self.num_heads=num_heads self.d_k=d_model//num_heads# 64,用//保证整除# 定义Q/K/V线性层self.W_query=nn.Linear(d_model,d_model)self.W_key=nn.Linear(d_model,d_model)self.W_value=nn.Linear(d_model,d_model)defforward(self,x):# x: [batch_size, seq_len, d_model] = [2,6,768]batch_size,seq_len=x.shape[0],x.shape[1]# 1. 线性变换:Q/K/V均为[2,6,768]Q=self.W_query(x)K=self.W_key(x)V=self.W_value(x)# 2. 拆分为多头:[2,6,12,64]Q=Q.view(batch_size,seq_len,self.num_heads,self.d_k)K=K.view(batch_size,seq_len,self.num_heads,self.d_k)V=V.view(batch_size,seq_len,self.num_heads,self.d_k)# 3. 转置:[2,12,6,64](batch, num_heads, seq_len, d_k)# 必须contiguous(),否则后续view会报错Q=Q.transpose(1,2).contiguous()K=K.transpose(1,2).contiguous()V=V.transpose(1,2).contiguous()# 4. 计算注意力分数:Q @ K^T → [2,12,6,6]K_T=K.transpose(2,3)# [2,12,64,6]attn_scores=Q @ K_T# [2,12,6,6]# 5. softmax归一化(省略,核心看view)attn_weights=torch.softmax(attn_scores,dim=-1)# 6. 加权求和:[2,12,6,64]attn_output=attn_weights @ V# 7. 转置+合并多头:[2,6,768]attn_output=attn_output.transpose(1,2).contiguous()attn_output=attn_output.view(batch_size,seq_len,self.d_model)returnattn_output

测试代码

mha=MultiHeadAttention(d_model=768,num_heads=12)x=torch.randn(2,6,768)output=mha(x)print(output.shape)# 输出:torch.Size([2,6,768])

view vs reshape

新手常混淆view和reshape,二者均用于重塑张量,但核心差异如下:
特性 view() reshape()
内存共享 与原张量共享内存(无拷贝) 优先共享内存,不连续则拷贝新内存
内存连续性 要求张量内存连续(否则报错) 自动处理内存不连续,无需contiguous()
适用场景 内存连续的张量(如线性层输出) 内存不连续的张量(如 transpose 后)

大模型开发建议

若确定张量内存连续(如线性层输出、原始输入),用view()(更高效)
若张量经过transpose/permute(如多头注意力中的转置),用reshape()(无需手动contiguous())
permute:重排,置换

示例:

# 替代:transpose后直接reshape,更简洁Q=Q.transpose(1,2).reshape(batch_size,self.num_heads,seq_len,self.d_k)

总结

view()核心作用:改变张量维度形状,不改变数据,要求元素总数不变,支持-1自动推导维度

多头注意力中view()的核心用法

拆分:将[batch, seq_len, d_model]拆为[batch, seq_len, num_heads, d_k]
合并:注意力计算后,将[batch, seq_len, num_heads, d_k]合并回[batch, seq_len, d_model]
关键注意:transpose/permute后需contiguous()才能用view(),或直接用reshape()更便捷

contiguous

contiguous()用于将「内存不连续」的张量转换为「内存连续」的张量,保证张量的元素在内存中按维度顺序紧密排列
是view()等操作的前置必要条件

张量在计算机内存中是一维线性存储的
“连续” 指的是:张量的元素在内存中的排列顺序,和按「维度顺序(如从 0 维到最后一维)」遍历张量得到的顺序完全一致

直观示例(二维张量)
假设有张量x = torch.tensor([[1,2,3], [4,5,6]])(shape=(2,3)):
连续内存布局:内存中存储顺序是 1 → 2 → 3 → 4 → 5 → 6(按 “行优先” 遍历,先遍历 0 维,再遍历 1 维)
若对x做转置x.T,得到[[1,4], [2,5], [3,6]]

转置后的张量逻辑上是 3 行 2 列,但内存中仍存储为1→2→3→4→5→6(PyTorch 的transpose/permute仅修改 “维度视图”,不拷贝数据)
此时按转置后的维度遍历(行优先),期望顺序是1→4→2→5→3→6,但内存实际顺序不符 → 转置后的张量是内存不连续的

为什么张量会变得 “不连续”?

PyTorch 中以下操作会导致张量内存不连续(核心是 “只改视图,不改内存”):

  • 维度变换类:transpose()、permute()(最常见,如多头注意力中的维度交换)
  • 索引 / 切片类:非连续切片(如x[:, ::2])、高级索引
  • 其他操作:narrow()、expand()(部分场景)
    这些操作的设计初衷是 “轻量”—— 避免不必要的数据拷贝,提升效率,但代价是破坏了内存连续性

contiguous()的核心作用

contiguous()会创建一个新的内存连续的张量:

  • 新张量与原张量数据相同,但内存排列会按照 “当前维度顺序” 重新整理
  • 新张量与原张量不再共享内存(是数据拷贝操作)
  • 只有内存连续的张量,才能调用view()(view()要求张量元素在内存中是连续的,否则无法正确重塑维度)

实战示例(结合多头注意力的经典场景)

importtorch# 1. 创建连续张量x=torch.randn(2,6,768)# shape=(2,6,768),内存连续print(x.is_contiguous())# 输出:True# 2. 转置后内存不连续x_trans=x.transpose(1,2)# 交换1、2维,shape=(2,768,6)print(x_trans.is_contiguous())# 输出:False# 3. 直接调用view()会报错try:x_trans.view(2,768,12,5)# 768×6=12×60?不,768×6=4608=12×384,这里故意错,核心看报错exceptExceptionase:print("报错:",e)# 报错:view size is not compatible with input tensor's size and stride...# 4. 先contiguous()再view(),正常运行x_contig=x_trans.contiguous()print(x_contig.is_contiguous())# 输出:Truex_view=x_contig.view(2,768,12,64)# 2×768×12×64=2×768×768=1179648,和2×768×6=9216?哦,修正:x_trans.shape=(2,768,6),总元素=2×768×6=9216;view为2,768,12,0.5?重新来:x_view=x_contig.view(2,768,12,0.5)# 故意错,实际应保证总元素一致:x_view=x_contig.view(2,768,12,0.5)→ 正确示例: x_contig=x_trans.contiguous()x_view=x_contig.view(2,12,64,6)# 2×12×64×6=2×768×6=9216,总元素一致print(x_view.shape)# 输出:torch.Size([2, 12, 64, 6])

大模型开发中的核心应用场景(必掌握)

contiguous()几乎只在「transpose()/permute() + view()」的组合中使用,尤其是多头注意力层:

# 多头注意力中拆分注意力头的标准流程Q=torch.randn(2,6,768)# [batch, seq_len, d_model]Q=Q.view(2,6,12,64)# 拆分为多头:[2,6,12,64]Q=Q.transpose(1,2)# 交换维度:[2,12,6,64] → 内存不连续Q=Q.contiguous()# 转为连续内存

后续可安全调用view()(若需要)

Q=Q.view(2,12,6,64)# 正常运行

关键注意事项

contiguous()是数据拷贝操作:会消耗内存和时间,非必要时不要调用(比如仅做矩阵乘法,无需连续内存)
替代方案:reshape()会自动处理内存连续性(优先共享内存,不连续则自动拷贝),因此:
若只需重塑维度,用reshape()替代contiguous()+view()更简洁

示例:Q.transpose(1,2).reshape(2,12,6,64)(无需手动contiguous())
判断是否连续:用tensor.is_contiguous()快速检查,返回True则为连续

总结

contiguous()的核心:将内存不连续的张量转为连续,保证view()等操作能正常执行
触发场景:张量经过transpose()/permute()后,若要调用view(),必须先contiguous()
大模型实战建议:优先用reshape()替代contiguous()+view(),减少代码量且更安全

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

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

相关文章

第二周作业wp

第二周作业wp [SWPUCTF 2021 新生赛]easyupload3.0 题目提示已经很明显了,我们要提交一个.jpg的文件。那么我们就把一个木马文件做成jpg文件。 这里我们把文件成功上传,然后通过蚁剑连接 连接之后,寻找flag。 如图,成功找到。 2…

吐血推荐专科生必用TOP9AI论文网站

吐血推荐专科生必用TOP9AI论文网站 2026年专科生论文写作工具测评:为何需要一份精准榜单? 随着AI技术在教育领域的深入应用,越来越多的专科生开始借助AI工具提升论文写作效率。然而,面对市场上五花八门的论文辅助平台,…

Python 调用大模型(LLM) - 努力-

Python 调用大模型(LLM)Python 调用大模型(LLM),提示词工程一、提示词工程 提示词(Prompt):是引导大模型(LLM)进行内容生成的命令(一句话、一个问题等)。 提示词工程(Prompt Enginnering):通过有技巧的编写提示…

Python核心语法-Python自定义模块、Python包 - 努力-

Python核心语法-Python自定义模块、Python包Python核心语法,Python自定义模块、Python包一、python 模块 Python模块(module):一个Python文件(.py)就是一个模块,模块是Python程序的基本组织单位。在模块中可以定义…

亲测好用9个一键生成论文工具,助本科生轻松写论文!

亲测好用9个一键生成论文工具,助本科生轻松写论文! AI 工具的崛起,让论文写作不再难 对于本科生来说,写论文一直是令人头疼的事情。从选题、查资料到撰写和降重,每一个环节都可能成为“卡壳”的点。而随着 AI 技术的不…

为什么您的机房必须选择本地化 U 位资产管理系统?供应商服务深度解析

机房 U 位资产管理是数据中心运营的核心环节,传统云端管理模式在实时性、数据安全与服务响应上的短板,进一步放大了空间利用率低、资产跟踪难、安全合规难三大痛点,成为机房高效运营的阻碍。本地化 U 位资产管理系统依托数据本地存储、实时交…

人群仿真软件:Vadere_(3).用户界面操作

用户界面操作 1. 基本操作 Vadere是一款强大的人群仿真软件,其用户界面设计旨在为用户提供直观且易用的操作体验。在本节中,我们将详细介绍如何进行基本的用户界面操作,包括启动软件、创建和加载仿真场景、基本导航和工具栏的使用。 1.1 启…

人群仿真软件:Vadere_(1).Vadere简介与安装

Vadere简介与安装 Vadere简介 Vadere是一款开源的人群仿真软件,旨在模拟复杂环境中的行人流动行为。它结合了多种先进的仿真算法和模型,能够准确地预测和分析人群在不同环境下的动态行为。Vadere不仅可以用于学术研究,还可以在城市规划、建…

人群仿真软件:Vadere_(2).Vadere基本操作与界面

Vadere基本操作与界面 启动Vadere 启动过程 Vadere是一款基于Java的人群仿真软件,可以通过以下步骤启动: 安装Java环境:确保您的计算机上安装了Java运行环境(JRE)或Java开发工具包(JDK)。您可…

AI原生应用领域:思维树带来的变革

AI原生应用领域:思维树带来的变革 关键词:AI原生应用、思维树(Tree of Thoughts)、大语言模型、多步推理、认知架构、智能决策、生成式AI 摘要:传统AI应用常因“单步思维”局限于简单任务,而“思维树&#…

免费工艺流程模板下载_在线编辑建筑/汽车/物流工艺流程图图表

良功绘图网站 (https://www.lghuitu.com ) 在建筑、汽车、物流等行业的日常运营与项目推进中,工艺流程可视化是提升效率、规范管理的核心手段。无论是建筑工程的施工管控、汽车制造的生产线优化,还是物流行业的仓储配送调度,一份清晰、规范的…

亲测好用!8个AI论文平台测评,研究生毕业论文必备

亲测好用!8个AI论文平台测评,研究生毕业论文必备 2026年AI论文平台测评:从功能到体验的深度解析 随着人工智能技术在学术领域的广泛应用,越来越多的研究生开始依赖AI工具来提升论文写作效率。然而,面对市场上五花八门的…

提升效率:如何为企业挑选完美的RFID解决方案

在物联网赋能企业数字化转型的进程中,RFID(射频识别)技术凭借非接触式批量读取、数据实时上传、标签抗磨损等核心优势,已成为物流仓储、智能制造、零售管控等领域提升效率的关键抓手。然而,多数企业在选型时易陷入“参…

第三十四周 学习周报

摘要 今日通过排气岐管的模型学习了CFD前处理中几何结构定义的关键设置,通过回答模型类型、开口封堵及区域抽取等核心问题,将实体CAD模型转化为可用于流体仿真的计算域,为网格划分奠定基础。 Abstract Today, through the exhaust manifol…

智能座舱:汽车内饰的交互革命

一、引言:从交通工具到第三空间的本质变革 汽车产业的百年演进中,座舱始终是连接人与车的核心载体。从最初仅满足驾乘功能的机械空间,到如今集成人工智能、物联网、显示技术的智能终端,座舱的进化史本质上是一部人机交互的革命史。…

学校教室多功能布局平面图在线设计的实用技巧和方法

在教育多元化发展的当下,学校教室早已不再是单一的“授课空间”,而是需要兼顾知识传授、小组协作、实践操作、活动开展等多重需求的多功能场景。一套科学合理的教室布局平面图,不仅能提升空间利用率,还能适配不同教学模式&#xf…

柔性生产:小批量定制与大规模生产的完美融合

一、生产模式的时代演进:从规模标准化到柔性协同化 工业革命以来,生产模式的变革始终围绕着“效率”与“需求”的平衡不断迭代。上世纪初,福特汽车开创的流水线大规模生产模式,以标准化产品、专业化分工和连续性作业为核心&#x…

循环经济在不同行业的应用前景比较

循环经济在不同行业的应用前景比较 关键词:循环经济、行业应用、应用前景、可持续发展、资源利用 摘要:本文旨在深入探讨循环经济在不同行业的应用前景并进行比较。首先介绍了循环经济的背景知识,包括其目的、适用读者、文档结构和相关术语。接着阐述了循环经济的核心概念、…

LoRA微调的指标

目录1. train/num_tokens2. train/mean_token_accuracy3. train/loss4. train/learning_rate5. train/grad_norm6. train/global_step7. train/epoch8. train/entropy什么是梯度爆炸1. 梯度爆炸的典型表现(与当前图对…

【避坑指南】Listing 莫名被限流?可能是图片里的“中文残留”害了你!揭秘 AI 如何实现 100% 深度清洗

Python Listing优化 亚马逊被限流 图片合规 去中文 跨境电商运营 账号安全摘要在亚马逊、TikTok Shop 等平台的算法中,图片质量 是影响权重的核心指标。很多卖家直接使用厂家提供的图片,虽然修掉了大标题,但往往忽略了包装盒上的小字、产品背…