一、概述(Overview)
本视频是一节由人工智能专家 Andrej Karpathy 主讲的深度实战教学课程。视频的核心论题在于,当今以 ChatGPT 为代表的顶尖大语言模型,其底层架构在技术本质上是一个纯解码器(Decoder-only)的 Transformer 神经网络。视频的核心结论是,通过极其简洁的架构设计和大约几百行原生的 PyTorch 代码,就可以在本地从零开始完整构建、训练并运行一个具备生成莎士比亚风格文本能力的 GPT(Generative Pre-trained Transformer,生成式预训练 Transformer)模型。Andrej Karpathy 强调,虽然现代工业界的超级大模型(如 GPT-3 或 GPT-4)在参数量和数据规模上比视频中的教学模型大出数万到上百万倍,但在数学原理和代码架构上,它们与视频中写出的每一行代码是几乎完全一致的。
二、按照主题来梳理
1. 数据准备与字符级分词机制
在构建 GPT 模型的初始阶段,数据准备和分词(Tokenization)是奠定模型输入基础的第一步。视频中采用了一个小型的文本数据集,即著名的 Tiny Shakespeare(小型的莎士比亚数据集,大小约为 1MB)。这个数据集包含了莎士比亚作品的戏剧对白,整体数据量虽然不大,但足以支撑一个小型 Transformer 模型的拟合与特征学习。
为了让神经网络能够处理文本,我们必须建立一套将离散的文本符号转换为连续的数字向量的映射机制。Andrej Karpathy 在视频中没有直接使用现代工业界复杂的 Subword(子词分词,如 BPE 算法),而是回归到了最本质、最易于理解的 Character-level Tokenization(字符级分词)。他首先通过 Python 的 set 构造函数提取出数据集中所有出现过的去重字符,并将其转换为一个有序的列表。在 Tiny Shakespeare 数据集中,这些字符总共包含 65 个(包括大小写字母、标点符号、空格以及换行符)。这 65 就是该模型的 Vocabulary Size(词表大小)。
基于这个固定词表,视频中手写了两个基础的映射字典:一个是 stoi(String to Integer,字符串到整数的映射),另一个是 itos(Integer to String,整数到字符串的映射)。这两个字典能够将词表中的每一个字符赋予一个从 0 到 64 的唯一整数编码。有了这两套字典后,文本的预处理就可以通过两个核心函数来实现:encode(编码函数)接收一段纯文本字符串,将其逐字替换为对应的整数序列;decode(解码函数)则接收一个整数列表,将其重新还原为人类可读的文本字符串。
字符级分词机制的优势在于其极致的简洁性,模型的词表非常小,不会出现未登录词(Out-of-Vocabulary)的现象。然而,Karpathy 在括号中也特别补充注释指出,字符级分词虽然简化了编码实现,但其代价是牺牲了单个 Token(特征标记)所能承载的信息密度。在现代大规模语言模型(如 GPT-4 或 Google 发布的各大模型)中,工业界普遍使用更为高级的分词器(比如基于 Byte-Pair Encoding,即字节对编码算法的分词器),其词表大小通常会达到 32,000 甚至 50,000 以上。现代分词器能够将诸如 “Google” 这样的高频单词识别为一个单独的 Token,而视频中的字符级分词则需要将其切分为 6 个独立的字符 Token。这意味着字符级分词在处理相同长度的文本时,会拉长其序列长度,增加了模型的长距离建模负担。
2. 数据集切分与批处理数据流设计
在完成了整体文本的整数编码后,整个 Tiny Shakespeare 数据集被转换成了一个巨大的一维张量(Tensor),其类型为 PyTorch 的 torch.tensor。为了在后续对模型的泛化能力进行客观公正的评估,必须对数据进行合理的划分。视频中采取了 90% 与 10% 的切分原则:前 90% 的编码数据被单独抽离出来作为 Training Set(训练集),用于模型参数的梯度更新;后 10% 的数据则作为 Validation Set(验证集),专门用于在训练期间监控模型是否发生了 Overfitting(过拟合)。
为了将这些连续的数字流送入 Transformer 模型进行并行化训练,我们需要引入两个极为关键的心智超参数:block_size(块大小,在某些文献中也被称为上下文长度 context length)和 batch_size(批次大小)。在视频的教学演示中,block_size 被初始化为 8,而 batch_size 被初始化为 4。
理解 block_size 的底层逻辑对于掌握自回归语言模型(Autoregressive Language Model)至关重要。当 block_size 为 8 时,意味着模型在进行预测时,最多只能同时观测到前面 8 个字符。但这并不意味着一个长度为 9 的数据块只包含一个训练样本。相反,在自回归模型的设计中,一个长度为 9 的文本切片里实际上蕴含着 8 个独立的隐式训练样本。举例来说,假设一个文本切片为 [18, 47, 56, 57, 58, 1, 15, 47, 56],模型在内部训练时会同时并行学习以下 8 个前置序列到后续目标的映射:
- 当输入为
[18]时,期望的下一个目标是47; - 当输入为
[18, 47]时,期望的下一个目标是56; - 当输入为
[18, 47, 56]时,期望的下一个目标是57; - 依此类推,直到输入前 8 个字符,期望预测出第 9 个字符。
通过这种巧妙的设计,模型在不同的位置上同时训练了处理长度从 1 到 block_size 不等的各种上下文的能力。为了提高计算设备(如 GPU)的硬件吞吐量和并行计算效率,我们不能一次只处理一个这样的长条样本。因此,需要引入 batch_size。在每个训练步骤中,代码会利用随机数生成器在长文本张量中随机抽取 batch_size 个起始索引,然后各自向后截取长度为 block_size 的片段。这些片段被堆叠在一起,最终形成一个形状为 (batch_size, block_size) 的二维输入张量
3. 从 Bigram Baseline 走向基础语言模型框架
在正式引入复杂的 Transformer 架构之前,Andrej Karpathy 遵循了软件工程和算法工程中的最佳实践:先构建一个最简单的 Baseline(基线模型)。在这个视频中,这个基线模型就是传统的 Bigram Language Model(二元语法语言模型)。
二元语法模型的底层假设非常直白:它认为当前位置预测下一个字符的概率,仅仅取决于当前这一个字符本身,而与当前字符之前更遥远的历史上下文完全无关。在 PyTorch 中,这个 Bigram 模型被定义为一个继承自 nn.Module 的简单类。其核心参数只有一个嵌入矩阵(Embedding Table),其实质是一个形状为 (vocab_size, vocab_size) 的二维权重矩阵。
当输入一个形状为 (B, T) 的张量时(其中 nn.Embedding 查找每一行输入标识符对应的概率分布对数。查找出来的结果形状为 (B, T, C),在这个初级模型中,这里的通道数 vocab_size。这里的输出实际上就是所谓的 Logits(未归一化的概率对数)。
为了衡量这个基线模型的预测好坏,我们需要计算损失函数。在分类预测任务中,标准工具是 Cross Entropy Loss(交叉熵损失函数)。然而,PyTorch 的 F.cross_entropy 函数对输入的维度有着严格的要求。它期望接收一个二维的 Logits,形状为 (N, C),其中 (N,) 的标签。为此,Karpathy 在代码中演示了关键的张量维度重构(Reshape)操作。具体来说,通过调用 logits.view(B*T, C) 将三维的 Logits 展平为二维,同时通过 targets.view(B*T) 将目标张量展平为一维。只有经过这样重构之后,交叉熵损失才能被正确计算。
通过简单的微积分原理,我们可以得出一个极具指导意义的数学常识:由于词表大小为 65,如果一个模型完全处于随机瞎猜的初始状态,那么它在每个位置猜对字符的概率就是
尽管 Bigram 模型可以通过 PyTorch 的 AdamW 优化器进行多轮梯度迭代训练,使其 Loss 从 4.17 降低到 2.5 左右,但由于它缺乏对长距离历史上下文的理解能力,它所自回归生成的文本依然是一堆完全无法读懂、甚至无法拼成正常单词的随机字母组合。这自然而然地引出了引入更强大架构——Transformer 的迫切需求。
4. 自注意力机制的数学演进与物理含义
为了克服 Bigram 模型无法利用长上下文的致命缺陷,视频进入了整堂课程最核心的理论高地:Self-Attention Mechanism(自注意力机制)的推导与实现。
Andrej Karpathy 首先提出了一个直观的物理问题:如果我们希望让当前位置的 Token 融合之前所有出现过的历史 Token 的信息,最朴素的数学手段是什么?答案是求平均。也就是说,把从第 0 个位置到当前第
为了在 PyTorch 中高效、并行地实现这种对历史信息的渐进式累加平均,Karpathy 展示了三种不断递进的代码编写方案:
- 第一种方案: 采用极其低效的双重
for循环。外层循环遍历每一个时间步,内层循环从 0 累加到 。这种写法虽然符合人类的直观思维,但在 GPU 上完全无法实现并行加速。 - 第二种方案: 引入线性代数中的矩阵乘法技巧。利用一个下三角矩阵(Lower Triangular Matrix)进行矩阵乘法。通过 PyTorch 的
torch.tril函数,可以生成一个对角线及以下全为 1、其余地方全为 0 的方阵。如果将这个矩阵的每一行进行归一化,使其行和为 1,它就变成了一个巧妙的权重矩阵。当我们用这个下三角权重矩阵去左乘输入张量时,由于矩阵乘法的规则,输出的第行正好就是输入前 行的算术平均值。这一步演示完美展示了如何利用二维矩阵乘法来消除一维的时间循环。 - 第三种方案: 引入 Softmax 函数与掩码(Masking)。这也是现代 Transformer 的标准写法。首先创建一个全零的矩阵,然后使用
tril == 0作为条件,利用.masked_fill方法将所有属于未来位置的元素全部替换为-inf(负无穷大)。接着,对这个处理后的矩阵在最后一个维度上调用F.softmax。根据 Softmax 的数学特性,,而原本为 0 的有效历史位置则会在指数映射后经过分母归一化,其效果与第二种方案的下三角平均矩阵完全等价。
在确立了基于掩码和 Softmax 的计算框架后,Karpathy 正式揭示了自注意力机制中三种不同物理含义的向量:Query(查询向量)、Key(键向量)和 Value(值向量)。
- Query(查询向量):代表”我当前正在寻找什么信息”。
- Key(键向量):代表”我手里包含着什么样的主题信息”。
- Value(值向量):代表”如果别人觉得我重要,我愿意向外输出的实际具体内容”。
在具体的 PyTorch 代码中,我们通过三个独立的线性映射层(nn.Linear)将输入的特征张量分别投影为 wei(Weights,原始注意力权重)的张量:
这个矩阵乘法的物理本质是在计算不同位置之间的相关性评分(Affinity Scores)。第 -inf 掩码填充,以确保未来的 Token 信息绝对不会泄露给当前位置。随后通过 Softmax 归一化,得到真正的注意力权重分布矩阵。最后,用这个权重矩阵去乘真正的 Value(值向量)张量。这样一来,每一个位置输出的特征,就不再是盲目的算术平均,而是根据语义相关性进行加权聚合的高级特征表示。
5. 缩放点积注意力与多头注意力架构
在手写完基础的自注意力计算流后,Andrej Karpathy 进一步剖析了 Transformer 论文中一个看似不起眼但极其关键的数学设计:Scaled Dot-Product Attention(缩放点积注意力)中的”缩放”操作。
在论文的公式中,Query 和 Key 在做完点积之后,必须除以一个缩放因子
如果直接把一个方差非常巨大、数值分布极度发散的张量送进 Softmax 函数,会导致一个灾难性的后果:Softmax 会被完全”饱和”(Saturated)。也就是说,由于输入值之间差异过大,经过指数化后,最大的一部分数值会牢牢占据几乎接近 1 的概率,而其他绝大多数位置的概率会被压制到接近 0。在神经网络的反向传播过程中,由于 Softmax 处于饱和状态,其对应位置的局部梯度(Gradient)会变得极其微小,甚至直接趋近于 0。这就会引发深度学习中经典的 Gradient Vanishing(梯度消失)问题,导致模型完全无法通过随机梯度下降来更新前面的参数。通过除以
为了进一步增强模型的表征能力,模型不能只从一个视角去看待上下文。因此,我们需要构建 Multi-Head Attention(多头注意力机制)。多头注意力的核心思想是,允许模型同时运行多个独立的自注意力计算过程。例如,我们可以设置 4 个独立的注意力头(num_heads=4),每个头都在一个较小的特征空间里独立计算自己的 Query、Key 和 Value。
在代码实现上,Karpathy 首先编写了一个单独的 Head 类来处理单头的注意力计算。随后,他编写了一个名为 MultiHeadAttention 的类。在这个类的内部,通过 nn.ModuleList 实例化了 4 个 Head 对象。在前向传播过程中,输入特征会同时被送入这 4 个头中分别进行计算,然后将 4 个头输出的张量在最后一个维度上通过 torch.cat 拼接(Concatenate)起来。最后,再用一个线性投影层(Projection Layer)对拼接后的整体特征进行一次混合线性变换。这种设计可以让不同的注意力头各司其职,比如某个头专门负责关注前文中的代词指代,另一个头专门负责寻找句式中的动词关联,从而极大地丰富了模型的空间感知能力。
6. 解码器 Block 的完整组装与优化稳定技术
当多头注意力机制构建完毕后,我们依然不能直接通过疯狂堆叠注意力层来构建深层网络。因为纯粹的注意力层只是在做空间上的特征”聚合”与信息交互,它本身严重缺乏对融合后特征进行深度非线性变换与加工的能力。因此,在每一个完整的 Transformer Block(Transformer 块)内部,紧跟在多头注意力层后面的必须是一个独立的 Feed-Forward Network(FFN,前馈神经网络层)。
在前向传播代码中,这个 FFN 被实现为一个简单的连续小网络:它包含一个线性层,将特征维度放大到原本的 4 倍(按照 Attention Is All You Need 论文中的标准设计);紧接着是一个激活函数层,视频中使用了 nn.ReLU(在现代 GPT 中通常使用 GeLU,但 Karpathy 为了保持代码极端纯粹,在初级阶段使用了 ReLU);然后是一个将维度缩回原样的线性层。这个前馈网络是独立作用于每一个时间步(Token)上的,它的核心职责在于让每个位置的特征在融合完上下文后,进行充分的自我消化与非线性特征提取。
随着网络层数的不断加深(例如将 Block 堆叠到 6 层甚至更高),深层网络普遍会面临两个巨大的物理惩罚:梯度消失和梯度爆炸。为了让上百层的神经网络能够稳定收敛,必须引入两项革命性的工程优化技术:Residual Connections(残差连接,或称 Skip Connections)和 Layer Normalization(层归一化)。
残差连接的数学形式极其优雅:
而 Layer Normalization(层归一化)则负责在训练过程中动态保持数据各维度的统计稳定性。Karpathy 在视频中特意手写了一段小代码来演示 LayerNorm 与 BatchNorm(批归一化)的本质区别:BatchNorm 是对单个特征维度在整个 Batch(批次)的所有样本上求均值和方差;而 LayerNorm 则是对单个样本(即单个 Token 向量)内部的所有通道维度求均值和方差。这意味着 LayerNorm 的操作完全独立于 Batch 之间的干扰,非常适合处理序列长度高度可变的文本数据。
此外,视频中采用的是现代工业界更为推崇的 Pre-LN(前置层归一化)架构。也就是说,在数据进入多头注意力和前馈网络之前,先对其进行 LayerNorm 归一化,然后再进行层计算,最后与残差边相加。这与 2017 年原始 Transformer 论文中的 Post-LN(后置层归一化)有所不同,Pre-LN 已经被无数实验证明能够在训练初始阶段提供高得多的数值稳定度。为了防止模型在 Tiny Shakespeare 这种小数据集上产生极其严重的过拟合,Karpathy 还在每个残差层以及注意力权重后面细心地插入了 nn.Dropout(丢弃法)层,通过随机失活一部分神经元来强迫模型学习更具鲁棒性的特征。
7. 模型的自回归生成与预训练/微调全景图
当所有的 Transformer Block、Token 嵌入层(nn.Embedding)以及用于感知绝对位置信息的 Position Embedding(位置嵌入层)被完美组装进一个庞大的 GPTLanguageModel 类中后,模型便具备了前向推理和计算 Loss 的全部功能。然而,训练好的语言模型最终是要拿来产出文本的,这就需要引入 Autoregressive Generation(自回归生成算法)。
在 GPTLanguageModel 内部,Karpathy 编写了一个名为 generate 的核心成员函数。这个函数接收一个初始的上下文张量,并指定希望新生成的 Token 数量。自回归生成的精妙步骤在代码中展现得淋漓尽致:
- 步骤一: 考虑到模型在设计时有严格的
block_size上下文限制,如果当前输入的总长度超过了block_size,必须使用 Python 的切片操作idx[:, -self.block_size:]截取最后最新的block_size个 Token。因为模型内部的位置编码矩阵无法接收超出其设计范围的索引。 - 步骤二: 将截取后的输入送入模型,运行完整的前向传播,拿到当前时间步在整个词表上的 Logits。
- 步骤三: 重点关注 Logits 张量在时间维度上的最后一个位置(即
位置)。这个位置对应的概率分布,正是模型对”下一个字符”的最新预测。 - 步骤四: 对这个最新的 Logits 调用
F.softmax,将其转化为和为 1 的概率概率分布张量。 - 步骤五: 不采取贪婪策略(即不直接取概率最大的那个),而是使用
torch.multinomial函数,根据算出的概率分布进行概率采样。这种随机采样赋予了模型某种创造力,也是为什么输入相同提示词模型会给出不同结果的原因。 - 步骤六: 将新采样出来的字符整数通过
torch.cat追加到原始输入张量的末尾,从而更新上下文。接着进入下一个循环,周而复始。
在视频的尾声部分,Andrej Karpathy 站在更高的高度,为所有观众梳理了从他手写的这个纳米级 nanoGPT 走向真正如日中天的 ChatGPT 的全景式发展路径。他指出,他们在这堂课上完整编写并实现的过程,在工业界被称为 Pre-training Stage(预训练阶段)。预训练的核心目的是为了得到一个强大的 Base Model(基线大模型)。这个模型在本质上扮演的角色只是一个极其擅长根据前文进行续写的”Document Completer”(文档补全器)。如果你给它输入一个问题”如何修理自行车?“,基线大模型可能不会回答你,而是倾向于为你续写出另一个类似论坛帖子里的新问题。
为了将一个只会机械补全大块网页文本的基线模型,改造成能够像人类专家一样温柔听话、对答如流的智能对话助手(如 ChatGPT),必须在预训练的基础之上,继续进行极其复杂的 Aligning / Fine-tuning Stage(对齐与微调阶段)。这一后续阶段在工业界通常包含以下三大核心硬核步骤:
- SFT(Supervised Fine-Tuning,监督微调): 人工撰写海量的高质量”提示词-完美回答”对。强制让模型去拟合这些特定的问答格式,使其从文档续写器转变为形式上的问答机器。
- 训练奖励模型(Reward Model): 让模型针对一个提示词给出多个不同的候选回答,由人类标注员(Human Raters)对这些回答的好坏进行 Preference Ranking(偏好排序)。利用这些排序数据去训练另一个独立的神经网络,使其学会像人类一样去对AI的回答打分。
- RLHF(Reinforcement Learning from Human Feedback,基于人类反馈的强化学习): 利用刚才训练好的奖励模型作为环境的反馈,采用 PPO(Proximal Policy Optimization,近端策略优化算法)这种复杂的策略梯度强化学习算法,去反复迭代微调大模型的采样策略。这能确保模型最终生成的每一个字,都能获得奖励模型最高的分数。
Karpathy 坦言,微调和对齐阶段需要耗费大量非公开的内部人工标注数据,这在开源社区通常是极难完美复制的。而通过 nanoGPT 深入理解预训练阶段的每一行矩阵乘法,才是真正揭开人工智能神秘面纱的最底层心智钥匙。
三、框架与心智模型(Framework & Mindset)
1. 探索性张量维度对齐与调试心智模型(Exploratory Tensor Alignment Framework)
在利用 PyTorch 等现代深度学习框架构建任何复杂的神经网络(如 Transformer)时,AI 研究员和软件工程师面临的最大心智挑战通常并非数学公式本身的艰深,而是海量多维张量在经历各类矩阵变换、切片、拼接以及视角重构时所发生的维度冲突。Andrej Karpathy 在视频中展现出了一套极为成熟的”探索性张量维度对齐与调试心智模型”。这套模型可以被抽象并重写为以下条理清晰的工程实践步骤:
- 静态数学维度预设: 在编写任何一行模型网络层代码之前,必须在脑海或草稿纸中明确定义基础的核心维度代号。对于 Transformer 而言,这套标准代号是
(Batch Size,批次大小)、 (Time / Block Size,时间步长/上下文长度)和 (Channels / Embedding Dimension,特征通道数/嵌入维度)。在编写每一个具体的类(例如 Head或FeedForward)的前向传播函数forward时,应当始终在函数的第一行通过注释写明当前输入张量的形状,例如# input of shape (B, T, C)。 - 侵入式交互单步验证: 永远不要试图一次性写完几百行网络模型代码然后直接运行。Karpathy 示范的方法是,在 Jupyter Notebook 中首先实例化一个最简单的网络层(例如一个初始的
nn.Embedding(65, 65)),然后手动将一组合法的假数据(Dummy Data)喂进去。紧接着,立即调用.shape打印其物理维度,并在控制台肉眼观察其真实的张量结构是否与第一步的静态预设完全吻合。 - 边界损失理论基准测试: 当张量顺利流经整个网络并输出 Logits 后,在计算 Loss 的关卡,必须利用概率论的边界极端情况(Edge Cases)来强制进行一致性检验。正如视频中所示,如果词表大小为
,在一个完全未经训练的随机初始化模型中,交叉熵损失的理论期望值必然是 。在写完 Loss 计算代码后,第一件事就是观察打印出来的第一个 Epoch 的 Loss 是否与该数学基准高度接近。如果理论值应当是 4.17,而程序输出是 10.5 或者是 0.2,那么无需继续向下训练,可以直接断定在多维张量的展平(Reshape)或转置(Transpose)过程中发生了维度错配,导致标签和预测概率完全没有对齐。
这套心智模型的底层核心在于,将高维、抽象且不可视的张量运算流,通过”预设维度注释-单步打印验证-极端数学理论值对齐”的三段式严密逻辑链条进行锚定。它能帮助开发者在面对复杂的自注意力多头拼接时,始终保持对底层硬件显存中数据排列形态的极致掌控,是避免写出带有隐式维度 Bug 的最高效的系统化方法。
2. 向量交互语义矩阵化转换心智模型(Vector Affinity Matricization Mindset)
在处理序列数据(如文本、音频或时间序列)时,传统程序员往往会陷入一种自发的”序列循环(Sequential Looping)“心智陷阱,即习惯性地使用 for 循环去逐个处理每个时间步。然而,现代深度学习的算力核心(GPU)在本质上是一个极为恐怖的矩阵并行乘法加速器。Karpathy 在解释自注意力机制时,成功展示了如何将一个抽象的”时间步信息融合问题”一步步升华为”高度并行化的语义矩阵化转换心智模型”。其重写后的系统化步骤如下:
- 依赖关系的下三角矩阵化解耦: 当我们需要让位置
的元素融合从 0 到 的历史信息,且不能偷看未来的元素时,这种时间上的因果因果限制(Causal Restriction)在矩阵视野下可以被完美抽象为一个下三角结构。通过在空间中创建一个全零的二维方阵,并利用掩码技术将上三角部分全部无情地擦除为 -inf,我们实际上是用一个静态的空间几何矩阵,一步到位地表达了时间轴上的因果先后顺序。 - 基于空间 Affinity(相关性)的多重向量投影: 为了让这种融合具备高级语义,不能再使用死板的算术平均。我们需要赋予文本中每个位置三个完全不同的科幻化身份:代表主动探寻的 Query、代表被动等待匹配的 Key、以及代表具体语义实体的 Value。这三个身份的本质就是通过三个矩阵进行空间线性变换(Linear Projections)。
- 点积高维能量释放与收敛控制: 当我们用 Query 矩阵去乘以 Key 矩阵的转置时,其数学本质是在全空间中并行进行所有位置两两之间的内积运算(Dot Product)。这个运算会瞬间爆发性地生成一个二维的相关性分布图。为了防止这个高维空间在进行能量爆发(数值方差急剧扩大)时导致后续的 Softmax 梯度坏死,必须引入精密的物理制动机制——即除以
进行尺度缩放。这一步的心智模型在于,认识到高维向量空间在做点积时必然带来方差膨胀的数学宿命,并主动通过分母阻尼来维持信息流的稳定。
这套心智模型彻底颠覆了传统的流式数据处理观。它告诉我们,无论是自回归的因果限制,还是错综复杂的语义相关性,在高度发达的深度学习框架眼里,最终都可以而且必须被合并、打包并升华为一个统一的、可以在 GPU 架构中瞬间完成吞吐的庞大矩阵乘法公式。掌握了这一思维框架,才能在设计新的神经网络架构时,自然而然地做到既符合数学逻辑,又对硬件性能极度友好。