news 2026/9/27 22:49:28

第 8 篇:注意力到底是什么(零门槛入门系列)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第 8 篇:注意力到底是什么(零门槛入门系列)

一句话导读:注意力(attention)不神秘,它就是"每个词按相关度,对其它词做一次加权平均":先算像不像,再把分数归一化成一组比例,最后按比例把历史信息混起来。

关键词:注意力、查询/键/值、分数、归一化(softmax)、加权平均

承接上一章:第 7 篇讲的是权重"怎么存得省",这一篇看模型怎么用这些权重去理解一句话,核心机制就是注意力。很多入门材料把它讲成一堆矩阵乘法,读者看完还是不知道它在干嘛;我们先不谈实现,先把它的"想法"讲清楚。

① 一句话概念

注意力就是按相关度做一次加权平均。

② 起点:会议室里的速记员

想象你在一个长会上做记录。会议室里每个人都在说话,你要一句一句写下来。关键的一点是:你写下新的一句时,并不是把前面所有话平等地过一遍。刚才财务同事报的那组数字,对你现在要写的这句最重要;开头那段闲聊停车位的话,几乎可以忽略。

你脑子里的动作其实是三步:先判断"前面哪些话跟现在这句有关"、给每句话一个重视程度;然后这个重视程度不是拍脑袋定的,它有高有低,加在一起正好是满满的一份;最后你落笔写的那句,是被前面最相关的那几句带偏的结果。

还有两个细节值得记住。第一,"相关"是相对当前这句而言的——同一段历史,你现在写的是总结,和你要写的是反驳,重点完全不同。第二,越相关的话,影响越大,但不是独占——最相关的那句可能占了七成影响,可剩下那几成还是来自其它句子。这种"按重视程度把信息搅在一起"的动作,就是下面要讲的机制。

③ 伪代码:像不像 → 归一化 → 加权平均

函数 注意力(查询q, 键列表K, 值列表V, 维度) -> 输出: 分数列表 = [] 对每个 键k 于 键列表K: 分数列表.追加(点积(q, k)) # 当前词与历史词逐个比"像不像" 比例 = 归一化(分数列表 / 开方(维度)) # 变成加起来等于 1 的一组比例 输出 = 0 对每个 位置i 于 比例: 输出 = 输出 + 比例[i] * 值列表V[i] # 按比例把历史信息混起来 -> 输出 # 代价: O(历史长度 × 维度)

逐行要点:

  1. 第 2–4 行的分数就是"像不像"的量化。当前词会产出一个"查询"(query,我现在想找什么),每个历史词会产出一个"键"(key,我能提供什么)。两者做一次点积,得到一个数——越像,数越大。这一步是"打分"。
  2. 第 5 行先缩放再归一化。光有分数还不能用,因为分数有大有小、甚至可能是负数。先除以维度的开方把数值压一压,再"归一化"(softmax)成一组加起来正好等于 1 的比例。归一化不是耍花招,它保证后面是"平均"而不是"累加"。
  3. 第 6–8 行是加权平均。每个历史位置还有一个"值"(value),把它们的值按上面的比例加起来。注意输出的长度是固定的,和"历史有多长"无关——再多历史,混出来的也只是一份结果。
  4. 最后一行# 代价。这一步要跟每一个历史词比一次,所以代价随历史长度线性增长。这个数字看着还好,但第 10 篇会告诉你它很快会变成平方级的麻烦。

分数怎么一步一步变成输出,如图 1 所示。

图 1注意力三步:像不像 → 归一化 → 加权平均:最左边是"当前词的 Q",下面竖排着"历史词 1~4 的 K",几条细箭头从它们汇进右边的"① 逐个点积 / 分数:像不像";再向右依次是"② 归一化 / 变成加起来等于 1 的比例"和"③ 按比例混合 / 把历史词的 V 加权求和",最后是"输出(长度与历史无关)";图下半部分画出归一化之后的四条比例条(0.45、0.30、0.18、0.07),长短不同而加起来正好是 1;红框提醒"分数一大,指数就会溢出"。

归一化这一步到底把分数变成了什么,如图 2 所示。

图 2softmax 在做什么:把任意分数变成加起来等于 1 的比例:左边一列是原始分数(2.0、0.5、−1.0、1.0,既有负数也有大数);中间一个方框写着"先取指数 / 再除以 / 总和";右边是四条比例长条(0.61、0.14、0.03、0.22),条越长表示原来的分数越高,右下角标着"总和 = 1.00";底部一句"取指数保证是正数;除以总和保证加起来是 1"。

④ 纸笔实验(必做)

设定(5 分钟):3 个历史词,它们跟当前词的相似度分数是[2, 1, 0]。手算一次归一化(这里假设 开方(维度) = 1,也就是分数不需要再缩放)。先备一张指数的小表:e⁰ = 1.00、e¹ = 2.72、e² = 7.39。

  1. 取指数:7.39、2.72、1.00
  2. 求和:7.39 + 2.72 + 1.00 = 11.11
  3. 逐个除以和:比例 = 0.665、0.245、0.090(加起来 ≈ 1.000)
  4. 按比例混合:假设三个历史词的值分别是 10、20、30,输出 = 0.665×10 + 0.245×20 + 0.090×30 = 6.65 + 4.90 + 2.70 =14.25

预期结果:输出 ≈ 14.25。同时你会看到一件有意思的事——最大的分数(2)只比第二名(1)大了 1,却占了 66.5% 的份量。取指数会把差距放大,这是 softmax 的性格:它让"明显更相关"的那一项很快占主导。

可选 REPL 版(Python 伪代码):

import math 分数 = [2, 1, 0] 指数 = [math.exp(s) for s in 分数] 比例 = [e / sum(指数) for e in 指数] 值 = [10, 20, 30] 输出 = sum(w * v for w, v in zip(比例, 值)) print([round(w, 3) for w in 比例], round(输出, 2)) # 预期 [0.665, 0.245, 0.09] 14.25

⑤ 进阶锚点

进阶锚点:本篇概念在《30 天手搓推理引擎》Day 8里被真正实现——8-1 自注意力数学:Q·K^T / softmax / V/8-2 在线 softmax:为什么不能先算完 e^x 再除/8-3 KV 缓存结构:按 token 还是按头存。

入门版到这里就够了;进阶版会多出:真实源码里 Q、K、V 是怎么算出来又怎么相乘的、"在线 softmax"为什么要在数值上绕一圈(附踩坑实验),以及 KV 缓存到底按词(token)存还是按头存。

想动手 → 仓库 https://gitee.com/pei-xiaoguang/kestrel-llm,从 Day 1 开始。

下篇预告:第 9 篇我们回答一个很实际的问题——模型每吐出一个字,为什么不必把前面所有字重新想一遍?答案是:把中间结果存下来,也就是 KV 缓存(KV cache)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 22:48:19

PLC编程必学!S7-1200定时器指令用法,一篇讲透TP/TON/TOF/TONR

做工控PLC编程,延时启动、定时停机、脉冲触发、设备累计计时这些功能,90%都要靠定时器实现。可以说,定时器是西门子S7-1200 PLC编程的核心指令,也是新手入门必须吃透的基础内容。很多刚接触S7-1200的朋友,总是分不清TP…

作者头像 李华
网站建设 2026/9/27 22:47:41

static 的五种含义:同一个关键字,五种不同的事

static 大概是 C 里最「身兼数职」的关键字:放在函数里的局部变量前、放在全局变量前、放在类成员前,意思全不一样,新手极易混淆。但万变不离其宗——它要么改变存储期(storage duration,变量活多久)&#…

作者头像 李华
网站建设 2026/9/27 22:46:42

VsCode 前端常用快捷键:用 TaoToken 统一 Key 打通 AI 补全配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/27 22:46:21

Open Computer Use 安装与使用方法全解:从零配置到跑通第一个任务

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华