阅读笔记:Deep Learning with PyTorch 2e(2026)
原文 17 个正文章(ch01–ch17),546 页。Part 1(ch1–8)基础;Part 2(ch9–17)生成模型+肺癌项目+分布式+部署。 作者四人:Howard Huang(PyTorch team @ Meta,分布式训练背景,2e 新增第一作者写 preface)、Luca Antiga(1e 主笔,生物医学工程出身,CTO)、Eli Stevens(1e 主笔,硅谷 startup,放疗软件 CTO,现自动驾驶 ML)、Thomas Viehmann(PyTorch core developer,数学 PhD,慕尼黑培训师)。 利益相关:四人中至少三人是 PyTorch 核心贡献者/开发者——这是一本由库维护者写的库教材。
ch01 Introducing deep learning and the PyTorch library (text/09, 533 行)
- 定义:deep learning = 训练 deep neural networks,presenting instructive examples;「approximate complicated, nonlinear processes very, very effectively」(L41)
- Dijkstra 引言:「Submarines Can Swim」(L72-74)
- feature engineering vs deep learning:手写数字例子,edge direction 过滤器 + enclosed holes(0,8,loopy 2)(L96-100);DL 自动学 representations,often better than handcrafted(L111)
- loss function = criterion = objective = cost function,同义词(L145-146);training = drive loss lower
- PyTorch 两大核心:GPU 加速(10×–1000× over CPU,L215)+ autograd 数值优化(L218);「high-performance library with optimization support for scientific computing」(L221)
- 竞争格局(1.4.1):Theano/TF/Lasagne/Keras/Caffe/Chainer/DyNet/Torch(Lua)/MXNet/CNTK/DL4J;TF consumed Keras,TF2.0 eager default;JAX by Google;PyTorch consumed Caffe2, replaced CNTK & Chainer, ONNX support, 2.0 引入 torch.compile(JIT)(L242-282)
- Hugging Face = high-level wrapper + model hub(L283-290)
- 项目全景图 1.2:DATA SOURCE → SAMPLE TENSORS → BATCH TENSOR(multiprocess data loading)→ TRAINING LOOP(可分布式)→ TRAINED MODEL → PRODUCTION(ONNX, JIT TorchScript)(L328-341)
- torch.nn 层/激活/损失;Dataset/Dataset→tensor 桥;DataLoader 多进程;optim 优化器;autograd 记历史(L343-386)
- eager mode:Python 解释器每执行一条立即跑 C++/CUDA(L404-408)
- 硬件:part 2 需 8GB GPU;GPU 比 CPU 快至少一个数量级,usually 40–50×(L424-428);癌症项目数据 60GB 下载/120GB 解压/共 200GB(L458-466)
- Jupyter notebooks 用法(L468-501)
ch02 Pretrained networks (text/10, 838 行)
- 主题:先玩四个预训练模型(图像分类/图像生成编辑/文本生成/图像描述),建立直觉;pretrained network = 程序,行为由 architecture + 训练时所见 examples 决定(L35-38)
- ImageNet:14M+ 图像,WordNet 名词层级标注;ILSVRC 2010 起,classification = 1000 类出 top-5;训练集 1.2M 图(L61-75);label/class 互换使用
- AlexNet 2012 ILSVRC top-5 error 15.4% vs 第二名非深度网络 26.2%(L169-172);现代架构 top-5 低至 3%(L175-176)
- 推理流程:resize/center crop/normalize → forward pass → 1000 scores → max → label(图 2.2,L86-98)
- ViT:vit_b_16 88.6M 参数(L243);top-5 error 5% vs AlexNet 15.3%,「it just took a whole 9 years」(L233-235)
- modules 可嵌套成树;modules = layers(L291-298);forward pass 定义(L211-214);未初始化网络 = blank/random slate,输出 garbage(L216-219)
- preprocess pipeline:Resize(256)→CenterCrop(224)→ToTensor→Normalize(mean=[0.485,0.456,0.406], std=[0.229,...])(L311-318);必须匹配训练时的预处理(L323)
- inference 要 eval mode;忘了会让 batch norm/dropout 出错(L361-370)
- softmax 归一化成 [0,1] 当 confidence(L410-414);bobby.jpg → golden retriever 86.4%;top-5 含 tennis ball 0.32%——「there's a 0.32% chance that I've completely misunderstood what a tennis ball is」bias 例子(L428-443)
- 训练集外的主题会「wrong answer with pretty high confidence」(L446-448)
- 2.2 inpainting:画家修复比喻,mask = 数字遮蔽胶带, 黑色保护/白色可改(L457-464);diffusion 学 reverse noising process(L471-476);prompt/image/mask 三角:prompt says what, image anchors where we begin, mask constrains where edits happen(L493-495)
- StableDiffusionInpaintPipeline 组成:tokenizer+text encoder, UNet denoiser, VAE(latent), scheduler(L538-542);guidance_scale=7.5, strength=0.8, seed 42
- 「The network is a scaffold—the juice is in the weights」(L622-623)
- 没有直接监督(没人手工描几千匹马)(L624-627);deep fakes 警告(L632-638)
- 2.3 Hugging Face = model zoo,统一接口(L646-656);GPT2 text generation pipeline 示例(L657-679)
- 2.4 BLIP(Salesforce):multimodal 图文;image→embedding,caption→embedding,比相似度训练;decoder 生成 caption(L692-709);训练前过滤噪声 caption+合成 caption 增广(L699-700)
- 演示:horse.jpg→「there is a brown horse grazing...」;生成的斑马图也骗不过 BLIP(L762-771)
- 收尾:<1000 行代码 + 通用架构 + 语料,无 hardcoded criterion,「everything, including the sentence, emerges from patterns in the data」(L772-776)
- fine-tune 预训练模型是数据不多时的有效路(L799-803)
ch03 It starts with a tensor (text/11, 1404 行)
- 3.1 世界即浮点数:网络学的是 input representation → output representation 的分阶段变换;中间层 = intermediate representations(早期=边缘/纹理,深层=耳朵/眼睛)(L34-39);「Similar inputs should lead to close representations」(图3.1);中间表示 = input 与上一层 weights 结合的结果(L67-70)
- tensor 定义:vectors/matrices 向任意维度推广;multidimensional array = ndarray;shape (4,3,3),dimension 0 左起(L75-85)
- NumPy = lingua franca of data science;tensor 超能力:GPU 快算、多设备分布、记住计算图(L99-108)
- 3.2.3 tensor 本质:Python list = 逐个分配的 boxed 对象;tensor = contiguous memory 上 unboxed C 数值的 view,homogeneous;1M float32 = 恰好 4MB + 少量 metadata(L193-201)
- points 例子:torch.zeros(6) 偶数位 X 奇数位 Y;2D 版 torch.tensor([[4,1],[5,3],[2,1]]);shape=torch.Size([3,2])(L212-263)
- points[0] 返回 view,不复制内存(L301-307)
- 3.3 索引:Python 切片语法 + 每维 range;points[None]/unsqueeze 加维(L309-338);advanced indexing 下章
- 3.4 broadcasting:从右向左比维;兼容 = 相等或其一为 1;size-1 维「virtually duplicated」;例:1×3 + 标量;1×3 × 3×1 → 3×3;2×1×3 + 2×3 → 2×2×3(L344-408)
- 3.5 named tensors:灰度权重 [0.2126, 0.7152, 0.0722];channels 总在 -3 维;Sasha Rush《Tensor Considered Harmful》;refine_names/align_as/sum('channels');实验特性,本书后面不用(L410-536)
- 3.6 dtype:boxing 低效;12 种 dtype;默认 float32;bfloat16(Google 2019,range 大 precision 低);indexing tensor 用 int64;mixed dtype 自动转大(L538-642)
- 3.7 API 分组:creation/indexing-slicing/math(pointwise, reduction, comparison, spectral, other, BLAS/LAPACK)/random sampling/serialization/parallelism(L644-696)
- 3.8 storage:torch.Storage = 1D contiguous block;Tensor = view with offset + per-dimension strides(L702-721);storage 永远一维(L771-773);in-place 方法尾部下划线 zero_(L787-807)
- 3.9 metadata:size/offset/stride;offset + stride[0]*i + stride[1]*j(L809-867);subtensor 改值影响原 tensor;clone 独立(L894-919);transpose = 只换 stride 顺序不复制(L921-978);contiguous 定义:从最右维起排;view 只工作于 contiguous;contiguous() 重排到新 storage(L1023-1108)
- 3.10 GPU:2025 起支持 CUDA/ROCm/MPS(Apple)/TPU(torch_xla)/Intel XPU;device 属性;.to(device='cuda') 复制;运算留在 GPU,不回 CPU(L1125-1211)
- 3.11 NumPy 互操作:zero-copy 共享 buffer(buffer protocol);numpy() 改数组会改 tensor;GPU tensor 会先复制回 CPU;NumPy 默认 float64 注意(L1213-1252)
- 3.12 generalized tensors:API 契约与存储分离;dispatcher 机制;sparse tensors 只存非零(L1254-1279)
- 3.13 序列化:pickle + storage 序列化,torch.save/load;HDF5/h5py 互操作,可索引盘上数据不整体加载(L1281-1354)
ch04 Real-world data representation using tensors (text/12, 1485 行)
- 主线:五种数据(图像/CT体数据/表格/时间序列/文本)→ 全部变成 tensor。N×C×H×W 是图像批的约定布局(L115,143)
- 图像:imageio 读 bobby.jpg (720,1280,3);permute(2,0,1) 换布局不复制数据(L118-134);batch uint8 预分配 N×3×256×256(L150);归一化:/255 或标准化(zero mean unit std)(L169-197)
- CT:DICOM 格式,99 张 512×512 切片堆成体;强度=密度(肺<脂肪<水<肌肉<骨)(L205-236);unsqueeze 加 channel 维;5D = N×C×D×H×W(L236)
- 表格:Wine Quality 4898 行×12 列(11 化学特征+quality 0-10)(L388-400);三种数值:continuous(ratio/interval 尺度)/ordinal/categorical(nominal)—大段专栏 L414-448;one-hot:score 5 → (0,0,0,0,1,0,...)(L490-497);scatter_ 原地写入(L511-542);硫阈值手工分类:74% 预测中的、61% 命中率,「barely better than random」(L735-738)——为神经网络出场铺垫
- 时间序列:Capital Bikeshare 2011-2012,17520 小时×17 列;view(730,24,17) 不重排数据,transpose(1,2)→N×C×L(L855-945);stride 解释:日维步长 408=17×24(L932-935);weather 序数变量 one-hot 或 rescale 到[0,1] (L949-1066)
- 文本:Jane Austen Pride and Prejudice;字符级 one-hot 128 维 ASCII(L1122-1182);词级 one-hot 7261 词词典,「impossible」=3394;11 词句子 → 11×7261 矩阵(L1220-1257);BPE 字节对编码:▁Im|pos|s|ible(L1271-1277);embedding:100 维浮点向量代替稀疏 one-hot;手工 2D 嵌入例子(fruit/flower/dog × 颜色)(L1319-1362);word2vec 用网络从上下文学;apple-red-sweet+yellow+sour≈lemon(L1395-1400);BERT/GPT 上下文敏感;embedding = one-hot × 嵌入矩阵(L1407-1414);fine-tuning 一词在此首现(L1421)
ch05 The mechanics of learning (text/13, 1556 行)——全书机制核心章
- Kepler 开场:第谷·布拉赫肉眼观测数据,Kepler 六年试形状→椭圆;七步「1609 年的数据科学手册」:拿数据→狂画图→选最简模型→留一部分数据做验证→迭代参数→独立数据验证→「looked back in disbelief」(L72-95)
- 主走查输入:温度计标定。t_u=[35.7,55.9,...] 未知单位 × t_c=[0.5,14,...] 摄氏,11 对(L189-190);模型 t_c=w*t_u+b;loss=均方误差 t_p-t_c 平方求均值(L244-310);初始 w=1,b=0,loss=1763.88(L333)
- 梯度下降直觉:旋钮机器七步剧本(L401-416);数值法 central difference delta=0.1(L437-442);learning_rate 1e-2(L455)
- 解析法:链式法则 dloss/dtp=2*(t_p-t_c)/N,dmodel_dw=t_u,dmodel_db=1(L501-552);epoch 定义=全数据集过一遍(L569-576)
- 发散实例:lr=1e-2 未归一化 → Epoch2 loss 580万 → Epoch11 inf(L607-624);lr=1e-4 收敛但慢(L658-683);梯度失衡:w 梯度 4517 vs b 83,50 倍差(L694-695);t_un=0.1*t_u 归一化后 lr=1e-2 收敛(L708-746);5000 epoch 后 w=5.367,b=-17.30 ≈ 华氏转摄氏 5/9 和 -17.78(×10 还原)(L791-805)
- autograd:requires_grad=True 让 tensor 记家谱(L880-888);loss.backward() 自动算链式导数;grad 是 accumulate 不是 store——必须 zero_()(L913-934);torch.no_grad() 里更新参数(L956-974)
- optim:SGD/Adam 等;optimizer.step() 读 grad 更新;SGD 的 stochastic 来自 minibatch(L1059-1063);Adam 自适应学习率,不怕未归一化输入,lr=1e-1 也稳(L1152-1176)
- 训练/验证/过拟合:train loss 不降=欠拟合(或数据没信息,气压计当温度计 L1241-1243);训练验证分叉=过拟合(L1244-1249);对策:正则化 L1/L2、数据增广、最简单的是把模型变小(L1260-1285);「increase the size until it fits and then scale it down until it stops overfitting」(L1283-1285);randperm 打乱索引切 80/20(L1289-1304);val 不 backward;val_loss 3.58 vs train 3.01(L1356-1366);图 5.14 四种曲线 A/B/C/D(L1378-1394)
- test set 只用一次;data leakage 定义(L1396-1418);两张计算图互不干扰,只对 train_loss 调 backward(L1420-1452);no_grad 省掉建图开销;set_grad_enabled(is_train)(L1459-1501)
ch06 Using a neural network to fit the data (text/14, 974 行)
- 神经元 = 线性变换 + 非线性激活 o=f(w*x+b)(L69-99);Rosenblatt 1958 perceptron 出处(L58-60);现代网络与大脑只有 slight resemblance
- 误差曲面:线性模型+平方损失是凸的、有唯一解;神经网络非凸,没有「single right answer」,参数没有 individual interpretability,同数据两次训练参数不同但性能相近(L134-151)
- 激活函数两个角色:中间层让函数在不同位置有不同斜率;输出层把输出压进合理范围(L158-170);Universal Approximation Theorem(拼 bump 函数,Nielsen 在线书)(L172-177)
- good doggo 例子:tanh 把垃圾车压到 -0.97、狗到 0.99,熊在敏感区(L179-245);ReLU 是目前最好的通用激活;Sigmoid 早期流行现少用;LeakyReLU 负侧小斜率 0.01(L247-258)
- 激活的要求:非线性(否则线性叠线性还是线性)、可微(ReLU 尖点可容忍)、有敏感区+饱和区(L280-314);饱和区梯度≈0 → 误差学不到那一侧
- 图 6.6 四个 tanh 神经元 A+B/C+D/复合:两层四神经元就能拼出双峰曲线(L346-390)
- 学习=拿通用模型+例子专业化,模型里没有编码任务规则(L400-407);「renouncing an explanation in exchange for…」(L417-423)
- nn.Module:模块可嵌套;nn.Parameter 默认 requires_grad;submodule 必须是顶层属性否则 optimizer 找不到(ModuleList/ModuleDict)(L433-447);nn.Linear(1,1) weight/bias;call 走 call 不是直接 forward(hooks)(L454-485)
- batch:模块期望 B×N_in;GPU 并行吃饱(L537-586);unsqueeze(1) 把 11 维变 11×1(L592-605)
- training loop 升级:model.parameters() 传给 optimizer;nn.MSELoss 替代手写 loss_fn;结果与手写相同(w=5.43,b=-17.97)(L646-707)
- 真正的网络:nn.Sequential(Linear(1,13),Tanh,Linear(13,1)),13 是任意选的(L755-776);hidden layer 名字来历;参数形状 [13,1],[13],[1,13],[1];OrderedDict 命名子模块;tanh 无参数(L778-848);训练后 val loss 2.02,输出 [-1.99, 20.87] vs 答案 [-4, 21];图 6.9 网络在样本间扭动追噪声(轻微过拟合)(L885-927)
ch07 Telling birds from airplanes (text/15, 1222 行)
- CIFAR-10:6 万张 32×32 彩图,10 类;Krizhevsky/Hinton 收集,80M tiny images(L31-39);torchvision.datasets.CIFAR10 下载;train=True/False 切训练/验证(L52-73)
- Dataset 抽象:len + getitem,不必持有数据(L90-112);cifar10[99] → PIL 图 + label 1 'automobile'(L127-131);transforms.ToTensor 转 C×H×W float32 [0,1] (L175-223);Normalize 用全数据集算的 mean=[0.4914,0.4822,0.4465] std=[0.2470,...] (L261-299);归一化原因接 ch5.4.4:激活在 0 附近线性,同尺度共享学习率(L243-253)
- 任务:Jane 的鸟 vs 飞机(L320-344);cifar2 过滤 + label_map 重映射(L354-369)
- 全连接模型:3072 输入(32×32×3 拉直)→ 512 隐藏 → 2 输出(L384-405);「structurally unaware」相邻像素(L435-437)
- 分类输出:输出是 categorical 不是数;one-hot [1,0]/[0,1];解释为概率,约束 [0,1] 且和为 1(L440-479);softmax = exp(x)/sum(exp(x)),x=[1,2,3]→[0.09,0.24,0.67];单调但不保比例(L484-546)
- 未训练输出 [0.4784,0.5216],「Pure luck」(L603,637);过度自信说明 + 贝叶斯网络一句(L611-614)
- 损失:要最大化正确类的概率(likelihood);NLL = -sum(log(out[c]));低概率 → NLL 无穷大(L642-700);NLLLoss 吃 log 概率不吃概率(数 值稳定),配 LogSoftmax(L701-707);CrossEntropyLoss = LogSoftmax+NLL 一步,吃 logits(L734-739,981-1007);图 7.11:cross-entropy 在接近正确时仍有梯度,MSE 早饱和(L740-749)
- SGD 的 S:每样本/minibatch 更新引入随机性,帮助跳出局部极小(L843-856);DataLoader batch_size=64 shuffle=True(L890-895);训练 100 epoch,loss 0.52→0.02(L929-937)
- 验证准确率 81.1%(L959);加深到 4 层(1024/512/128)只到 81.3% 但训练集 100%——两个模型都过拟合(L1008-1012)
- 参数量算账:第一个模型 157 万,深的 374 万;第一层占 314 万(1024×3072+1024)(L1021-1053);1024×1024 RGB → 第一层就 30 亿参数=12GB(L1054-1059)
- 平移不变性:飞机挪一格,像素关系全要重学(图 7.16)(L1088-1136);data augmentation 治标:要为平移副本存参数(L1138-1144);结尾引出卷积(L1155-1157)
ch08 Using convolutions to generalize (text/16, 1900 行)——Part 1 收官
- 卷积定义:kernel 与每个邻域的标量积;3×3 kernel o11=i11*w00+...(L71-103);PyTorch 的卷积其实是 cross-correlation(符号差)(L88-90);kernel 权重随机初始化+反向传播学;同一 kernel 滑过全图 → 每个权重的梯度汇集全图贡献(L104-109)
- 三大收益:locality + translation invariance + 参数少(参数数只依赖 kernel 大小和通道数,不依赖像素数)(L139-148);图 8.2:卷积=稀疏+权重共享(tied)的线性层(L149-170)
- nn.Conv2d(3,16,kernel_size=3):weight 形状 16×3×3×3,bias 16(L199-221);输出 32→30 丢边;padding=1 补零保住尺寸(L262-327);手工 kernel:全 1/9 = 模糊;[-1,0,1;-1,0,1;-1,0,1] = 垂直边缘检测 o22=(右列-左列)(L338-401);「计算机视觉专家的工作历史上就是设计滤波器组合」(L404-405)
- lottery ticket hypothesis 注:很多 kernel 训完也没用(L188-191)
- 大象问题:3×3 只看局部,大结构怎么办 → 堆叠+下采样(L464-482);max pooling 取 2×2 最大(丢 3/4 数据);average pooling 过时;strided conv 有前途未普及(L483-533);receptive field:conv3+pool+conv3 的输出像素受 8×8 输入影响(L567-577)
- 网络组装:Conv(3→16)+Tanh+MaxPool → Conv(16→8)+Tanh+MaxPool → view → Linear(512→32)+Tanh+Linear(32→2);参数 18090 vs 全连接 374 万(减 99%+)(L583-646);nn.Sequential 里缺 reshape → RuntimeError 64x8 vs 512x32(L664-676)
- subclass nn.Module:init 建子模块,forward 定义数据流;super().init();view(-1, 888)(L711-742);分类网络=信息压缩,中间尺寸渐缩;首层例外(扩维,kernel trick 联想)(L743-788)
- functional API:无内部状态的函数版;有参数用 module、无参数用 functional;表 8.1 对照(L826-899)
- 训练循环标准五步(L923-931);100 epoch loss 0.55→0.147;train acc 0.95 / val acc 0.90(错误率比全连接减半)(L1014-1060);「model architecture matters more than parameter count」(L1056-1057)
- 保存:torch.save(model.state_dict()) 只存参数不存结构;load_state_dict;map_location(L1062-1084,1194-1208)
- GPU:Module.to 原地改、Tensor.to 返回新;optimizer 要在 model.to 之后建;imgs/labels 也要 to(device)(L1086-1193)
- 宽度:NetWidth n_chans1=32 → 38386 参数(L1240-1295)
- 正则化三件套:L2=weight_decay(梯度 -2λw,等效按当前值缩小;SGD 的 weight_decay 参数直接给);dropout(2014 Hinton 组 Srivastava;训练时随机置零 p=0.4;Dropout2d 整通道;eval 时自动关闭,忘 eval 是 silent failure);batch norm(2015 Ioffe&Szegedy;minibatch 内归一化避免饱和;推理用 running estimates;running 统计在 train 模式更新)(L1305-1507)
- 深度:20+ 层到 2015 底才突破;vanishing gradient=长链乘法把早期层梯度乘没(L1509-1536);ResNet(He 2015-12,arXiv 1512.03385)skip connection:out = ...conv3(out) + out1;给梯度一条不乘长链的近路;Highway/U-Net 更早;DenseNet 更激进(L1537-1636);NetResDeep:ResBlock(conv+BN+ReLU, +x)×100 用 nn.Sequential(*[...]) 拼;kaiming_normal_ 初始化;BN 初始化 weight 0.5;PyTorch 默认初始化不理想(GitHub issue 18182);Glorot/Xavier 2010(L1637-1752)
- 图 8.16 各变体准确率对比;weight decay/dropout 的 train-val 差距更窄(更算正则化),BN 是收敛助手(L1753-1792)
- 8.6 结尾:Jane 还没解决的问题:大图中找鸟(bounding box)、Fred the cat 走进镜头——远离训练分布的输入会 0.99 自信乱答 = overgeneralization,「真实世界的大多数情况」(L1810-1820)
ch09 How transformers work (text/17, 1603 行)——Part 2 开门
- 开场 ELIZA(1960s Weizenbaum MIT,DOCTOR 配置,关键词触发,不懂意思)(L20-44);生成问题:输出理论无限;latent structure 拉丁语 lateo「隐藏」(L45-64)
- 主走查:生成人名。vocab="$abc…z" 27 字符,$=边界(L117-128);均匀采样生成垃圾名 zrcgahwsalcydnvq(L151-155);torch.multinomial 从分布采样
- bigram:美国社保局 31915 个婴儿名(2022);27×27 计数矩阵归一化;采 样得 liahuli/deiannnis/cl/de——可读但不真实(L176-266)
- self-supervised learning 定义在此登场:ground truth 从数据本身推出,不要人工标注(L267-281)
- bigram 极限:27²=729;词级词表上百万对;看前两个字符要 27³=19683——指数爆炸+data sparsity(L283-299);神经网络dense 表示,参数量不随词表/依赖长度涨(L300-306)
- 训练数据构造:$ada$ → 输入[0,1,4,1,0] 目标[1,4,1,0];一个名字切出 4 个样本(前缀→下一字符);pad 0/-1,ignore_index=-1(L308-409)
- nn.Embedding(27,3) 可查表,随机初始化边训边学(L413-448);SequenceMLP:每个位置取前缀→嵌入→拉直→Linear→ReLU→Linear(27)(L481-513);loss 2.61→2.34;生成 jatini/ceney(L576-631);嵌入可视化:元音聚一起、辅音聚一起、$ 单独(L638-652)
- attention:静态嵌入的缺陷(car vs care 的 a)(L664-674);spotlight 比喻;Q/K/V = 信息检索类比(Google query/索引页 key/结果 value)(L677-705);self-attention 四步:value=线性变换;attn_weights=softmax(q·k);输出=加权和(L707-763);代码:q@k.T → softmax → @v(L769-799)
- 三个扩展:batching、causal masking(tril 下三角,-inf 屏蔽未来)、scaling(/sqrt(d_k) 防梯度消失/爆炸)(L801-865);F.scaled_dot_product_attention 官方实现验证 allclose(L875-891)
- AttentionMLP 结果类似 MLP(loss 2.43)但不需展开前缀;图 9.9 john 的注意力网格:o 主要看自己+$+j(L893-997)
- Transformer:Vaswani 2017「Attention Is All You Need」(L999-1005);原架构 encoder+decoder(翻译);先讲 decoder(GPT/Claude/Llama 都是 decoder-only)(L1006-1019)
- decoder block 四件新增:residual/skip connection(对抗梯度消失)、multiheaded attention(4 头各学不同方面,拼接)、positional embeddings(并行处理没有顺序概念,否则当无序集合)、layer normalization(跨特征归一 vs batch norm 跨样本;图 9.11 对照)(L1036-1116)
- TransformerBlock 代码:n_embd%num_heads==0;view+transpose 分头;is_causal=True;norm(x+attn) 残差包裹(L1121-1170);Transformer 类:char_embedding+positional_embedding 相加→6 块→Linear;loss 2.29→1.93,生成 journe/green/bryce(L1181-1245)
- encoder:无 causal mask,看全句;BERT 2018 Google Bidirectional(L1251-1262);encoder-decoder:encoder 输出做 decoder 的 K/V(cross-attention),翻译用(L1292-1339)
- tokenization:词比字符有语义(dog vs god);HF tokenizers 库 pipeline:normalize→pretokenize→model→postprocess;WordLevel+[UNK];Odyssey 词级训练 500 步生成伪史诗(L1341-1456)
- ViT(arXiv 2010.11929):图像切 patch 当 token;224×224→196 个 16×16 patch→768 维;[CLS] token 聚合全局信息做分类,其他 token 丢弃(L1458-1529);transformer 不限于文本:任何能变 token 序列的数据都行(L1526-1529)
ch10 Diffusion models for images (text/18, 696 行)
- 生成图像 vs 文本:空间依赖而非序列;共同目标:学训练集的分布,采样出「可信地属于原数据集」的新样本(L16-32)
- 历史:VAE 2013(encoder/decoder,噪声当 latent 解码)(L42-50);GAN 2014(generator vs discriminator 对抗,图更锐利)(L51-60);diffusion 2015 Sohl-Dickstein「Deep Unsupervised Learning Using Nonequilibrium Thermodynamics」提出,2020 左右才流行(L61-86,118-124);DALL-E/Stable Diffusion XL 例子(L88-102)
- 核心思想:前向过程=系统性缓慢破坏结构(沙堡被浪冲刷比喻);噪声可逆 by design;学 reverse process 恢复结构(L104-139)
- 主走查:PyTorch logo 轮廓 → 3177 个 2D 点(L150-188);T=1000 步;linear beta schedule 0.0001→0.02(L236-243)
- 前向步:x_t = sqrt(1-β_t)*x_{t-1} + sqrt(β_t)*noise(L247-260);一个点 500 步逐渐漂移成随机(L264-285);全体 1000 步 logo 消失(L291-303)
- 闭式解:不用循环,x_t 直接由 x0 和累积 α 算出;alphas=1-betas,cumprod,sqrt_alphas_cumprod*x0+sqrt(1-cumprod)*noise(L304-374)
- 训练目标:给 x_noisy 和 t,预测加进去的噪声;loss=MSE(noise, noise_pred)(L380-487);DenoisingModel:sinusoidal embedding(来自 Transformer 论文)编码 t/x/y 各 128 维,cat → 3 层 Linear+ReLU → 输出 2 维预测噪声(L392-459);Adam lr=0.001,20000 epoch loss 0.97→0.70(L492-532)
- 采样(反向):无闭式解,逐步来——这就是扩散模型慢的原因(SDXL-Lightning 减少步数)(L534-547);公式:model_mean=sqrt_recip_alpha*(x - β*model(x,t)/sqrt(1-ᾱ));加回少量噪声「帮助探索多种可能重建」;t=0 不加噪声(L548-596);Ho et al. DDPM 论文(arXiv 2006.11239)推导在书外(L565-567)
- 1000 个随机点 999→0 步倒推 → 重建 PyTorch logo(L598-632);同套公式可用于 RGB 像素
ch11 Using PyTorch to fight cancer (text/19, 691 行)——肺癌项目总设计
- 目标:胸部 CT → 疑似恶性肿瘤位置。早期发现极影响存活率;人工审片=「100 个草垛找针」,绝大多数无癌(L48-57)
- 选这题的原因:unsolved、但在能力边缘、有大量论文开源可参考;教学声明:「output will not be accurate enough to use clinically」(L63-88)
- 与 ch8 的差别:大部分精力在模型之外(数据解析),ch13 才设计第一个模型(L98-107);GPU 8GB+220GB 磁盘;Colab 免费 GPU(L117-125)
- 三步流水线(图 11.4):①数据加载(ch12) ②segmentation 标记感兴趣 voxel(ch15) ③classification 判断候选是否结节/良恶(ch13-14)(L253-285);工厂装配线比喻
- CT scan=3D X 光,3D 数组单通道;voxel=3D pixel,本项目是长方体非立方(头脚轴间距不同——病人移动方向,图 11.3 观察推出)(L153-251);CT 值≈质量密度(radiodensity 严格说);X 光是 3D 投影到 2D,CT 保留第三维
- nodule 定义:≤3cm 的肺部小肿块,>3cm 叫 lung mass;约 40% 肺结节是恶性(此处);NCI 说过半检出的结节非恶性(L287-293,537-591);结节 vs 血管等结构:一张 CT 里约 1000 个看着像肿瘤的结构,专家只标 1 个(图 11.5)(L335-348)
- 为什么不 end-to-end:99.9999% voxel 不是癌(类比:高清电视上两个像素的色块/一书架小说里一个拼错的词)(L407-420);Fast R-CNN 类模型需要几十万张图且不受稀有类限制;Retina U-Net/FishNet 更好但教学不合适;分段做=梯度不端到端回传,上限受限但好教好学(L434-473)
- LUNA Grand Challenge:LUNA16 数据集,888 例 CT+标注;两赛道 NDET(≈segmentation)和 FPRED(≈classification);上榜要交论文(L593-623);下载:60GB 压缩/120GB 解压/再 100GB 缓存;10 个子集;candidates.csv+annotations.csv(L625-654)
- 「站在巨人肩上」专栏:借鉴已有成功结构;别盲目跑别人代码(L324-334)
ch12 Combining data sources into a unified dataset (text/20, 1123 行)
- 目标:原始 CT+标注 → 训练样本 tuple(图 12.2)。「把 messy 数据处理和训练代码隔离」TIP(L275-277)
- candidates.csv:551066 行,seriesuid,coordX/Y/Z,class;class=1 的真结节 1351 个;annotations.csv 1187 行带 diameter_mm(L168-210);两文件坐标对不齐(差零点几 mm),用直径/4 阈值做模糊匹配(for/else 结构)(L238-253,330-349);排序保证按大小取样有代表性
- Ct 类:SimpleITK 读 .mhd(隐含读 .raw);series_uid 是 DICOM UID;10 子集约 90 CT 共 888(L415-471)
- Hounsfield Units:空气 -1000、水 0、骨 +1000;clip(-1000,1000) 去掉视野外标记和金属——outlier 会带歪 batch norm 统计(L476-511)
- 患者坐标系 LPS:X=左,Y=后,Z=头;毫米制,原点任意;数组坐标 (I,R,C);voxel 非立方如 1.125×1.125×2.5mm(头脚轴不同);Mercator 投影类比(L523-651)
- xyz2irc/irc2xyz 四步:IRC→CRI 翻转、乘 voxel size、@方向矩阵、加 origin;反向按逆序逆操作(L653-705)
- getRawCandidate:以候选中心切固定 (32,48,48) 块;99.9999% voxel 无关——「让你从不懂语言的一书架小说里找一个拼错的词」(L729-764)
- LunaDataset:len/getitem;返回 (candidate_t[1,32,48,48], pos_t[0,1], series_uid, center_irc)(L803-912);val_stride=10 每隔 10 个取样做验证集;del 语法切;「同一病人的数据不能两边都出现」提醒(L975-1001)
- 缓存:getCt 用 lru_cache(1) 内存缓存;getCtRawCandidate 用 diskcache 落盘;无缓存慢 50 倍;215 float32 vs 225 int16 的 I/O 账(L914-950);改了函数要清缓存
- 渲染数据的价值:一眼看出「这个样本噪声特别大」(L1044-1069)
ch13 Training a classification model (text/21, 1667 行)
- 结构升级:完整 CLI 应用 LunaTrainingApp,argparse 在 init 解析(L138-212);「结构匹配项目复杂度,基础设施拖延症是陷阱」(L122-129)
- initModel:多 GPU 用 nn.DataParallel 透明包装(单机);DistributedDataParallel 留到 ch16;optimizer 必须在 model.to(device) 之后建(L272-321);SGD lr=0.001 momentum=0.99 是安全默认;hyperparameter search 名词(L322-337)
- DataLoader:num_workers 后台进程预取,pin_memory 加速 CPU→GPU;batch_size × GPU 数(L339-438);训练 495958 样本/验证 55107
- LunaModel 结构:tail=BatchNorm3d(1);backbone=4×LunaBlock(Conv3d+ReLU+Conv3d+ReLU+MaxPool3d);head=Linear(1152,2)+Softmax;尺寸 32×48×48 → 2×3×3(L440-531,596-647);tail/backbone/head 名词解释(L485-538)
- 两个 3×3×3 conv 叠起来的 receptive field = 5×5×5,比单个 5×5×5 参数少(L566-582)
- forward 返回 (logits, softmax 概率) 两个:训练用 logits 配 CrossEntropyLoss(数值稳定),展示用概率;「训练和生产输出不同很正常」(L648-689)
- Kaiming 初始化 init_weights:kaiming_normal(fan_out, relu);bias 按 1/sqrt(fan_out) 正态(L690-723)
- computeBatchLoss:CrossEntropyLoss(reduction='none') 拿每样本 loss 再 mean;metrics_g 三行(label/pred/loss)记录每个样本;detach 防梯度(L837-909)
- 验证循环:no_grad + model.eval();read-only 不用返回值(L931-1007)
- logMetrics:0.5 阈值做 neg/pos mask;loss/all、loss/neg、loss/pos、correct/all/neg/pos(L1052-1178);global_step 用累计样本数不用 epoch(epoch 长度可变就没法比)(L1566-1574)
- tqdm 插曲:预估「有没有时间去巴黎吃晚饭」(L1274-1328)
- 大揭露:E1 99.7% correct —— 但 trn_pos 0.2%(3/1215)、val_pos 0.0%;模型把所有都判负!99.7% 只是阴性占比(L1330-1359);E10 仍然 0%;val_pos loss 降但极慢;「这种失败模式在真实世界最危险」——漏诊肿瘤(L1360-1379)
- TensorBoard:torch.utils.tensorboard SummaryWriter;runs/ 目录;add_scalar(tag, value, global_step);斜杠分组;smoothing 0.6;清 junk runs(L1384-1574)
- 考试比喻:100 道 T/F 题 99 道 F,全答 F 得 99 分;答对一个 T 的学生其实更懂(L1576-1618)
ch14 Improving training with metrics and augmentation (text/22, 1531 行)
- 警犬比喻:Chirpy 见什么都叫(高 recall 低 precision,全是 false positive);Dozer 只对窃贼叫但睡死(高 precision 低 recall,全是 false negative);ch13 模型=Dozer(L104-167)
- 四象限:human label 阈值 × dog bark 阈值 → TP/TN/FP/FN;图用猫=FP、鼠贼=FN、鸟=TN、窃贼=TP(L169-248);模型输出一维分数+垂直分类线
- recall = TP/(TP+FN)「别漏」;precision = TP/(TP+FP)「别错」;recall 又叫 sensitivity(L250-294)
- F1 = 2PR/(P+R) = 调和平均;为何不算术平均:avg(1,0)=avg(0.5,0.5)=0.5 没用;min 太粗;乘积=几何平均在早期区域全≈0;F1 的等值线有深 elbow 奖励平衡(L358-493)
- 新指标下旧模型现形:precision/recall 全 0,F1=nan(除零);「从 A+ 变成零,如果幸运的话」——指标若没报垃圾才是指标的缺陷(L525-580)
- 400:1 不平衡;第一 epoch 权重更新分析:50 万负样本一半拉对一半拉错,阳性 1215 个一半拉对;组 2(25 万拉向负) vs 组 3(500 拉向正)——15 个 batch 才见 1 个阳性,14/15 batch 纯负 → 退化(L644-680)
- 解决:ratio_int 平衡,数据集交替返回正/负样本,len 硬编码 200000,modulus 回绕(L760-847);验证集不平衡(真实世界就是不平衡的)(L715-717);sampler 方案讨论后放弃(破坏封装)(L719-759)
- --balanced 结果:E1 trn F1 0.93;val recall 79.4% precision 0.11 F1 0.19(L891-903);算账:54971×1% 误报=550 vs 136 真阳性——假阳是真阳 4 倍;但筛掉 98.4% 阴性=放射科医生效率 10 倍(L910-925)
- 20 epoch 后:train F1 0.997 但 val_mal 从 84.6%(E2)降到 72.1%(E20)——过拟合确诊:训练 loss 归零、验证 loss 升;「阳性训练集只有 1215 个,重复多次也不会更难记」(L929-1010)
- 过拟合脸龄比喻:好模型学皱纹/灰发,过拟合模型记「那是 Frank,62.8 岁」;Frank Jr. 也被认成 Frank(L1034-1059)
- 数据增广:合成修改样本,让模型记不下被迫泛化;改角上 4 像素红通道=4 billion 倍数据但没用 vs 左右翻转(L1062-1103)
- 五种增广:flip/offset/scale/rotate/noise;affine_grid+grid_sample+三线性插值;缓存必须在增广之前!;flip 上下要留Gravity 方向的疑问(临床项目要问专家);rotate 只在 X-Y 平面(voxel 非立方);noise 是破坏性的,过量会淹没数据(L1105-1282)
- 结果:全增广 recall 大好但错更多;noise 单独反而更差;rotate 单用几乎追平全增广且 precision 更好(F1 被 precision 卡脖子);选全增广因 use case 要高 recall,F1 决定保存哪个 epoch(L1334-1443)
- 「discrimination」专栏:模型从有种族偏见的数据学= 继续偏见,「racism is learned」,unsolved(L690-703)
ch15 Using segmentation to find suspected nodules (text/23, 1106 行)——step 2
- 本章较独立:新模型+新数据集+新训练循环;从手工标注候选(candidates.csv)解放出来(L22-37)
- segmentation 定义:标记每个像素是否属于结节;语义分割(每像素分类) vs 实例分割(逐对象) vs 目标检测(bounding box);选语义分割(L111-133)
- 分类模型=漏斗/放大镜:大图→单个标签;分割要图像状输出(L135-189)
- SAM(Meta 2023, arXiv 2304.02643):ViT image encoder + prompt encoder(点/框/掩码) + mask decoder;zero-shot;11M 图 1.1B mask 训练;一次输出 3 个嵌套 mask(whole/part/subpart)+置信度(L191-269);Apache 2.0 license 专栏:无 license≠公有领域,代码和权重的 license 可能不同(L279-291)
- 试用:SamAutomaticMaskGenerator 对 astronaut 出 79 个 mask;predicted_iou 1.03(是置信度不是真 IoU);点提示 (320,260) → 狗鼻子 mask(L300-438);「自然图像 vs 医学影像的 domain gap」专栏:SAM 不是为医学设计(arXiv 2304.14660)(L443-455)
- SAM 只吃 2D → 从 3D CT 抽切片;切片厚度不一致的问题要靠增广扛(L478-520);getSingleSlice 按 axis 取 2D 切片(L522-616)
- 关键设计:用 SAM+标注点 生成 mask 当 ground truth(手工标注太贵),再 fine-tune 轻量 SegFormer 让它不用提示自动分割(L622-645);数据集 ct/+mask/+metadata.jsonl;上传 HF H-Huang/LUNA16_segmentation_data(L646-720)
- fine-tuning 定义:预训练模型在新数据集上继续训,保留已学知识(L778-784);SegFormer(arXiv 2105.15203,nvidia/mit-b0 轻量版);只微调 decode_head(其他权重已训好,「newly initialized」警告是预期的)(L765-844)
- AdamW=Adam+weight decay;Adam 每参数自适应学习率(arXiv 1412.6980);lr=0.00006 同原论文(L846-870)
- 训练循环:SegformerImageProcessor 预处理;model(pixel_values, labels) 直接出 loss;20 epoch train/val loss 都降(L872-951);保存 state_dict 而非整模型(pickle 整模型失灵活性);load_state_dict 要求参数 1:1 对应(L953-999)
- 推理:image_processor 预处理+post_process_semantic_segmentation;图 15.17 三例:ground truth vs 预测(L1001-1033)
ch16 Training models on multiple GPUs (text/24, 1029 行)——Howard Huang 主场
- 动机:LLaMA 3.1 405B 推理要 ~800GB 显存(L14-17);jigsaw 拼图比喻;thread vs process 专栏(进程隔离所以分布式用进程)(L23-84)
- 术语(MPI 血统):world size=进程总数(≈GPU 数);rank=进程编号;process group;node=机器;global vs local rank;SPMD(L86-153)
- 初始化三步:spawn 进程 → bootstrap 通信(TCPStore key-value store, MASTER_ADDR/PORT) → 改训练逻辑;torchrun 帮你做前两步,读 RANK/WORLD_SIZE 环境变量(L168-265)
- collective communication:gloo(CPU)/nccl(GPU)/mpi backend;broadcast(电台广播比喻)=rank0→所有;allreduce(凑菜比喻)=各自贡献+sum+回发所有人;例子 0+1+2=3(L267-372)
- data parallelism:forward 是 embarrassingly parallel;问题在第三步——各 GPU 梯度不同,直接 step 模型会分叉;要插入 allreduce 梯度同步(先 sum 再除 world_size)(图 16.4/16.5)(L375-486);手写版 → DDP 包装即可;DistributedSampler 给每个 rank 分不重复的数据片(shard)(L487-525)
- model parallelism:模型太大塞不下单卡;切模型到多设备,activations 用 send/recv P2P 传递;缺点:一个算其他闲着(L527-601)
- pipeline parallelism:模型切 stage + 输入切 microbatch → 各设备流水重叠;GPipe schedule(先全 forward 再全 backward);torch.distributed.pipelining;适合「skinnier and deeper」模型(L603-692)
- tensor parallelism:在层内部切参数(行切/列切),层太大塞不下时必须;Megatron 论文 arXiv 1909.08053;适合「wider and shallower」(L694-746)
- n 维并行:组合使用;tensor 并行要 fast interconnect 放单机内,pipeline 通信少跨机器;LLaMA 3 用 4D 并行(data+tensor+pipeline+context)(arXiv 2407.21783);DeviceMesh 抽象:init_device_mesh("cpu",(2,4),names),自动建 6 个进程组,按维度名索引(L748-837)
- FSDP:full parameter sharding,每设备只存一部分参数/梯度/优化器;forward 时 all_gather 临时收齐,用完释放;backward 用 reduce_scatter;ZeRO-3(arXiv 2101.06840);fully_shard(module, mesh);512 GPU 验证过;模型太大 DDP 不行时推荐(L839-905)
- LLM 专属:context parallelism(序列维切,attention O(L²) 内存;跨块维持 causal mask);expert parallelism(MoE:router 选 top-k expert,all-to-all 通信)(L907-942)
- TorchTitan:PyTorch 官方参考实现,LLaMA/DeepSeekV3 配置,一条命令起训(arXiv 2410.06511)(L943-961)
ch17 Deploying to production (text/25, 1397 行)——Thomas Viehmann 风格章
- 部署五路:Gradio 原型、FastAPI 服务、ONNX 导出、C++ LibTorch、ExecuTorch 移动端(L21-48)
- Gradio:gr.Interface(fn, inputs, outputs) 自动生成 UI;share=True 公网链接;不适合生产(L60-144)
- FastAPI:@app.post + Pydantic BaseModel 输入校验;/docs 自动文档;SmolLM2-360M-Instruct 例子(HuggingFaceTB);model.get_memory_footprint;apply_chat_template;no_grad+eval(L146-271)
- 部署要什么:async endpoint 并发;request batching(队列收请求,凑满 batch 或超时,后台 worker 线程跑 GPU,餐厅ticket 比喻);流式逐 token 返回(max_new_tokens=1 循环+StreamingResponse);GIL 问题;adversarial examples 提一句不管(L272-508)
- torch.compile:PyTorch 2.0;JIT;kernel fusion(pointwise 操作融合省 memory bandwidth)+operator reordering;推理提速 20%-200%,偶有更慢;先 to(device) 再 compile(L510-554)
- distillation(蒸馏):更少参数/操作做相同映射(DistilBERT 合层、CTranslate 训小模型模仿大模型)(L556-564)
- quantization:float32→int8;quantization-aware training vs post-training;SmolLM 6528MB→bfloat16 减半→int8 线性层 1825MB(-70%);为什么不能整个 .to(int8):norm/激活要浮点;quantize_dynamic(model, {nn.Linear}, dtype=torch.qint8);1-bit 量化研究(arXiv 2402.17764)(L565-683);为什么 int8 能工作:舍入误差≈随机,卷积/线性=加权平均,误差抵消(L610-616)
- vLLM、LitServe 现成方案(L684-693)
- ONNX:开放交换格式;trace 计算图序列化;torch.onnx.export(model, dummy_input, path)——dummy 输入只要形状类型对;onnxruntime InferenceSession;树莓派比直接跑 PyTorch 快;PyTorch 不能加载 ONNX(L721-773)
- torch.export:AOT 方式拿 traced graph(FX graph);参数变图输入;aten 操作;f32[2,5] 标注;exported_program.module() 还能当普通模型调;AOTInductor aoti_compile_and_package → model.pt2;aoti_load_package 加载;输入形状必须和导出时一致;「永远保留从源码重新生成的工作流」TIP(L775-888)
- torch.compile 深入:full graph capture(torch.export) vs graph breaks(torch.compile 遇到动态控制流就切图回退 Python);ConditionalModel if x.sum()>0 → export 报 Dynamic control flow not supported,compile 没事;历史:TF 静态图 → PyTorch eager 赢 → torch.jit.trace(样本追踪)/script(试图把 Python 当静态语言重实现,失败) → TorchDynamo 拦截 Python 字节码;jit 系进入维护模式;TorchInductor 默认后端,Triton 生成 GPU kernel,OpenMP CPU(L938-1086)
- torch.profiler:profile(activities=[CPU,CUDA]) 上下文;key_averages().table();aten::addmm 65% Self CPU;export_chrome_trace → chrome://tracing 或 ui.perfetto.dev;record_function 自定义标签;编译后 trace 大变样(fused,Compiled Region)(L1088-1168)
- LibTorch:C++ API 镜像 Python(torch::nn::Linear);CMake+CMAKE_PREFIX_PATH;C++ 训练循环 MNIST;torch::inductor::AOTIModelPackageLoader 加载 .pt2;C++ API 不如 Python 全(L1170-1288)
- ExecuTorch:移动端;torch.export → to_edge(Edge IR)→ to_executorch() → 序列化;_load_for_executorch;避免 JNI/ObjC++ 麻烦(L1289-1352)
通读完成确认(第二棒)
ch01-ch03 已由本棒亲自通读正文核对,前一棒笔记属实。全书 17 章通读完毕,readState 可填 read。 补充 ch01 细节:Dijkstra「Submarines Can Swim」(L72-74);「approximate complicated, nonlinear processes very, very effectively」(L41);feature engineering 手写数字 edge/holes(L96-100);loss=criterion=objective=cost(L145-146);GPU 10×–1000×(L215);competitive landscape:Theano 停更、TF 吃 Keras、TF2.0 eager、JAX、PyTorch 吃 Caffe2、torch.compile(L242-282);eager mode 定义(L404-408);GPU 40-50× faster(L428) 补充 ch02 细节:AlexNet 2012 ILSVRC top-5 15.4% vs 26.2%(L169-172);ViT 5%「it just took a whole 9 years」(L233-235);vit_b_16 88.6M 参数(L243);preprocess Resize(256)→CenterCrop(224)→ToTensor→Normalize(mean=[0.485...])(L311-318)必须与训练一致(L323);eval() 忘了会无声错(L361-370);bobby.jpg golden retriever 86.4%,tennis ball 0.32%「0.32% chance that I've completely misunderstood」(L428-443);训练集外高置信错误(L446-448);inpainting 画家修复胶带比喻(L457-464);prompt/mask/image 三角(L493-495);pipeline 组成 tokenizer+text encoder/UNet/VAE/scheduler(L538-542);「The network is a scaffold—the juice is in the weights」(L622-623);无直接监督(L624-627);deep fakes 警告(L632-638);Hugging Face model zoo(L646-656);BLIP Salesforce 多模态,embedding 比对相似度训练(L692-709);horse→「there is a brown horse grazing...」;斑马图 BLIP 也没被骗过(L762-771);<1000 行代码+通用架构,「everything, including the sentence, emerges from patterns in the data」(L772-776);fine-tune 预训练模型适合数据不多(L799-803) 补充 ch03 细节:tensor=vector/matrix 向任意维推广;ndarray;shape (4,3,3)(L75-85);NumPy lingua franca(L99-101);tensor 超能力:GPU/分布/计算图(L105-108);Python list=boxed 对象 vs tensor=contiguous unboxed;1M float32=4MB(L193-201);points 例子(L212-263);broadcasting 从右往左比,相等或 1(L344-408);named tensors 灰度权重 [0.2126,0.7152,0.0722];Sasha Rush《Tensor Considered Harmful》;实验特性本书弃用(L410-536);12 种 dtype;默认 float32;bfloat16 Google 2019 range 大;int64 索引;混型转大(L538-642);storage=1D contiguous;Tensor=view with offset+strides;stride(2,1);offset+stride[0]*i+stride[1]*j;in-place 尾部下划线;transpose 只换 stride 不复制;contiguous() 重排;view 需 contiguous(L700-1108);GPU:CUDA/ROCm/MPS/TPU/XPU;.to(device) 复制;运算留在 GPU(L1125-1211);NumPy zero-copy 共享 buffer;numpy() 修改影响 tensor;NumPy 默认 float64(L1213-1252);dispatcher 分离 API 与存储;sparse(L1254-1279);pickle 序列化;HDF5 盘上索引(L1281-1354)