☰
小白程序员必看:轻松入门大模型之注意力机制(附收藏)
2026/10/30 2:40:05 网站建设 项目流程

本文详细介绍了注意力机制的概念、工作原理及其简单实现。通过类比数据库查询,解释了查询、键和值矩阵的来源和作用。文章还深入探讨了单头注意力和多头注意力机制,并通过可视化图解和代码实现帮助读者更好地理解。对于想要学习大模型的程序员和初学者来说,本文提供了宝贵的入门知识,并附有代码示例,方便读者实践和学习。

注意力机制

在整个注意力过程中,模型会学习了三个权重:查询、键和值。查询、键和值的思想来源于信息检索系统。所以我们先理解数据库查询的思想。

假设有一个数据库,里面有所有一些作家和他们的书籍信息。现在我想读一些Rabindranath写的书:

在数据库中,作者名字类似于键,图书类似于值。查询的关键词Rabindranath是这个问题的键。所以需要计算查询和数据库的键(数据库中的所有作者)之间的相似度,然后返回最相似作者的值(书籍)。

同样,注意力有三个矩阵,分别是查询矩阵(Q)、键矩阵(K)和值矩阵(V)。它们中的每一个都具有与输入嵌入相同的维数。模型在训练中学习这些度量的值。

我们可以假设我们从每个单词中创建一个向量,这样我们就可以处理信息。对于每个单词,生成一个512维的向量。所有3个矩阵都是512x512(因为单词嵌入的维度是512)。对于每个标记嵌入,我们将其与所有三个矩阵(Q, K, V)相乘,每个标记将有3个长度为512的中间向量。

接下来计算分数,它是查询和键向量之间的点积。分数决定了当我们在某个位置编码单词时,对输入句子的其他部分的关注程度。

然后将点积除以关键向量维数的平方根。这种缩放是为了防止点积变得太大或太小(取决于正值或负值),因为这可能导致训练期间的数值不稳定。选择比例因子是为了确保点积的方差近似等于1。

然后通过softmax操作传递结果。这将分数标准化:它们都是正的,并且加起来等于1。softmax输出决定了我们应该从不同的单词中获取多少信息或特征(值),也就是在计算权重。

这里需要注意的一点是,为什么需要其他单词的信息/特征?因为我们的语言是有上下文含义的,一个相同的单词出现在不同的语境,含义也不一样。

最后一步就是计算softmax与这些值的乘积,并将它们相加。

可视化图解

上面逻辑都是文字内容,看起来有一些枯燥,下面我们可视化它的矢量化实现。这样可以更加深入的理解。

查询键和矩阵的计算方法如下

同样的方法可以计算键向量和值向量。

最后计算得分和注意力输出。

简单代码实现

import torch import torch.nn as nn from typing import List def get_input_embeddings(words: List[str], embeddings_dim: int): # we are creating random vector of embeddings_dim size for each words # normally we train a tokenizer to get the embeddings. # check the blog on tokenizer to learn about this part embeddings = [torch.randn(embeddings_dim) for word in words] return embeddings text = "I should sleep now" words = text.split(" ") len(words) # 4 embeddings_dim = 512 # 512 dim because the original paper uses it. we can use other dim also embeddings = get_input_embeddings(words, embeddings_dim=embeddings_dim) embeddings[0].shape # torch.Size([512]) # initialize the query, key and value metrices query_matrix = nn.Linear(embeddings_dim, embeddings_dim) key_matrix = nn.Linear(embeddings_dim, embeddings_dim) value_matrix = nn.Linear(embeddings_dim, embeddings_dim) query_matrix.weight.shape, key_matrix.weight.shape, value_matrix.weight.shape # torch.Size([512, 512]), torch.Size([512, 512]), torch.Size([512, 512]) # query, key and value vectors computation for each words embeddings query_vectors = torch.stack([query_matrix(embedding) for embedding in embeddings]) key_vectors = torch.stack([key_matrix(embedding) for embedding in embeddings]) value_vectors = torch.stack([value_matrix(embedding) for embedding in embeddings]) query_vectors.shape, key_vectors.shape, value_vectors.shape # torch.Size([4, 512]), torch.Size([4, 512]), torch.Size([4, 512]) # compute the score scores = torch.matmul(query_vectors, key_vectors.transpose(-2, -1)) / torch.sqrt(torch.tensor(embeddings_dim, dtype=torch.float32)) scores.shape # torch.Size([4, 4]) # compute the attention weights for each of the words with the other words softmax = nn.Softmax(dim=-1) attention_weights = softmax(scores) attention_weights.shape # torch.Size([4, 4]) # attention output output = torch.matmul(attention_weights, value_vectors) output.shape # torch.Size([4, 512])

以上代码只是为了展示注意力机制的实现,并未优化。

多头注意力

上面提到的注意力是单头注意力,在原论文中有8个头。对于多头和单多头注意力计算相同,只是查询(q0-q3),键(k0-k3),值(v0-v3)中间向量会有一些区别。

之后将查询向量分成相等的部分(有多少头就分成多少)。在上图中有8个头,查询,键和值向量的维度为512。所以就变为了8个64维的向量。

把前64个向量放到第一个头,第二组向量放到第二个头,以此类推。在上面的图片中,我只展示了第一个头的计算。

这里需要注意的是:不同的框架有不同的实现方法,pytorch官方的实现是上面这种,但是tf和一些第三方的代码中是将每个头分开计算了,比如8个头会使用8个linear(tf的dense)而不是一个大linear再拆解。还记得Pytorch的transformer里面要求emb_dim能被num_heads整除吗,就是因为这个

使用哪种方式都可以,因为最终的结果都类似影响不大。

当我们在一个head中有了小查询、键和值(64 dim的)之后,计算剩下的逻辑与单个head注意相同。最后得到的64维的向量来自每个头。

我们将每个头的64个输出组合起来,得到最后的512个dim输出向量。

多头注意力可以表示数据中的复杂关系。每个头都能学习不同的模式。多个头还提供了同时处理输入表示的不同子空间(本例:64个向量表示512个原始向量)的能力。

多头注意代码实现

num_heads = 8 # batch dim is 1 since we are processing one text. batch_size = 1 text = "I should sleep now" words = text.split(" ") len(words) # 4 embeddings_dim = 512 embeddings = get_input_embeddings(words, embeddings_dim=embeddings_dim) embeddings[0].shape # torch.Size([512]) # initialize the query, key and value metrices query_matrix = nn.Linear(embeddings_dim, embeddings_dim) key_matrix = nn.Linear(embeddings_dim, embeddings_dim) value_matrix = nn.Linear(embeddings_dim, embeddings_dim) query_matrix.weight.shape, key_matrix.weight.shape, value_matrix.weight.shape # torch.Size([512, 512]), torch.Size([512, 512]), torch.Size([512, 512]) # query, key and value vectors computation for each words embeddings query_vectors = torch.stack([query_matrix(embedding) for embedding in embeddings]) key_vectors = torch.stack([key_matrix(embedding) for embedding in embeddings]) value_vectors = torch.stack([value_matrix(embedding) for embedding in embeddings]) query_vectors.shape, key_vectors.shape, value_vectors.shape # torch.Size([4, 512]), torch.Size([4, 512]), torch.Size([4, 512]) # (batch_size, num_heads, seq_len, embeddings_dim) query_vectors_view = query_vectors.view(batch_size, -1, num_heads, embeddings_dim//num_heads).transpose(1, 2) key_vectors_view = key_vectors.view(batch_size, -1, num_heads, embeddings_dim//num_heads).transpose(1, 2) value_vectors_view = value_vectors.view(batch_size, -1, num_heads, embeddings_dim//num_heads).transpose(1, 2) query_vectors_view.shape, key_vectors_view.shape, value_vectors_view.shape # torch.Size([1, 8, 4, 64]), # torch.Size([1, 8, 4, 64]), # torch.Size([1, 8, 4, 64]) # We are splitting the each vectors into 8 heads. # Assuming we have one text (batch size of 1), So we split # the embedding vectors also into 8 parts. Each head will # take these parts. If we do this one head at a time. head1_query_vector = query_vectors_view[0, 0, ...] head1_key_vector = key_vectors_view[0, 0, ...] head1_value_vector = value_vectors_view[0, 0, ...] head1_query_vector.shape, head1_key_vector.shape, head1_value_vector.shape # The above vectors are of same size as before only the feature dim is changed from 512 to 64 # compute the score scores_head1 = torch.matmul(head1_query_vector, head1_key_vector.permute(1, 0)) / torch.sqrt(torch.tensor(embeddings_dim//num_heads, dtype=torch.float32)) scores_head1.shape # torch.Size([4, 4]) # compute the attention weights for each of the words with the other words softmax = nn.Softmax(dim=-1) attention_weights_head1 = softmax(scores_head1) attention_weights_head1.shape # torch.Size([4, 4]) output_head1 = torch.matmul(attention_weights_head1, head1_value_vector) output_head1.shape # torch.Size([4, 512]) # we can compute the output for all the heads outputs = [] for head_idx in range(num_heads): head_idx_query_vector = query_vectors_view[0, head_idx, ...] head_idx_key_vector = key_vectors_view[0, head_idx, ...] head_idx_value_vector = value_vectors_view[0, head_idx, ...] scores_head_idx = torch.matmul(head_idx_query_vector, head_idx_key_vector.permute(1, 0)) / torch.sqrt(torch.tensor(embeddings_dim//num_heads, dtype=torch.float32)) softmax = nn.Softmax(dim=-1) attention_weights_idx = softmax(scores_head_idx) output = torch.matmul(attention_weights_idx, head_idx_value_vector) outputs.append(output) [out.shape for out in outputs] # [torch.Size([4, 64]), # torch.Size([4, 64]), # torch.Size([4, 64]), # torch.Size([4, 64]), # torch.Size([4, 64]), # torch.Size([4, 64]), # torch.Size([4, 64]), # torch.Size([4, 64])] # stack the result from each heads for the corresponding words word0_outputs = torch.cat([out[0] for out in outputs]) word0_outputs.shape # lets do it for all the words attn_outputs = [] for i in range(len(words)): attn_output = torch.cat([out[i] for out in outputs]) attn_outputs.append(attn_output) [attn_output.shape for attn_output in attn_outputs] # [torch.Size([512]), torch.Size([512]), torch.Size([512]), torch.Size([512])] # Now lets do it in vectorize way. # We can not permute the last two dimension of the key vector. key_vectors_view.permute(0, 1, 3, 2).shape # torch.Size([1, 8, 64, 4]) # Transpose the key vector on the last dim score = torch.matmul(query_vectors_view, key_vectors_view.permute(0, 1, 3, 2)) # Q*k score = torch.softmax(score, dim=-1) # reshape the results attention_results = torch.matmul(score, value_vectors_view) attention_results.shape # [1, 8, 4, 64] # merge the results attention_results = attention_results.permute(0, 2, 1, 3).contiguous().view(batch_size, -1, embeddings_dim) attention_results.shape # torch.Size([1, 4, 512])

总结

注意力机制(attention mechanism)是Transformer模型中的重要组成部分。Transformer是一种基于自注意力机制(self-attention)的神经网络模型,广泛应用于自然语言处理任务,如机器翻译、文本生成和语言模型等。本文介绍的自注意力机制是Transformer模型的基础,在此基础之上衍生发展出了各种不同的更加高效的注意力机制,所以深入了解自注意力机制,将能够更好地理解Transformer模型的设计原理和工作机制,以及如何在具体的各种任务中应用和调整模型。这将有助于你更有效地使用Transformer模型并进行相关研究和开发。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

为什么要学习大模型?

我国在A大模型领域面临人才短缺,数量与质量均落后于发达国家。2023年,人才缺口已超百万,凸显培养不足。随着AI技术飞速发展,预计到2025年,这一缺口将急剧扩大至400万,严重制约我国AI产业的创新步伐。加强人才培养,优化教育体系,国际合作并进是破解困局、推动AI发展的关键。

大模型入门到实战全套学习大礼包

1、大模型系统化学习路线

作为学习AI大模型技术的新手,方向至关重要。 正确的学习路线可以为你节省时间,少走弯路;方向不对,努力白费。这里我给大家准备了一份最科学最系统的学习成长路线图和学习规划,带你从零基础入门到精通!


2、大模型学习书籍&文档

学习AI大模型离不开书籍文档,我精选了一系列大模型技术的书籍和学习文档(电子版),它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。

3、AI大模型最新行业报告

2025最新行业报告,针对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。

4、大模型项目实战&配套源码

学以致用,在项目实战中检验和巩固你所学到的知识,同时为你找工作就业和职业发展打下坚实的基础。

5、大模型大厂面试真题

面试不仅是技术的较量,更需要充分的准备。在你已经掌握了大模型技术之后,就需要开始准备面试,我精心整理了一份大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

适用人群

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范
  • …
第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署
  • …
第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建
  • …
第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案
  • …

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询