Posts
2026
风险也不是一个数字:波动率、最大回撤和 VaR 到底在衡量什么?
在收益率那篇里,同样赚了 10%,可能来自完全不同的路径。要继续比较,就得知道风险指标各自省略了什么。
这次复习时,我把波动率、最大回撤和 VaR 放在一起看:它们分别描述收益的不稳定程度、历史上的峰谷跌幅,以及给定概率下的损失阈值。用哪一个,取决于想回答什么问题。
从 RNN / LSTM / GRU 到早期 Attention:为什么“压缩历史”最终变成了“按需读取”
·5757 words·12 mins
上一篇《从 RNN 到 LSTM,再到 GRU》把 gate 机制理了一遍:LSTM / GRU 把 recurrent state 的信息流变成了可学习的动态控制,决定什么写入、什么保留、什么暴露。写到那里,我以为 RNN 这条线差不多收尾了。
翻到 2017 年的简历,我才想起自己还做过一个游戏
很多项目随着工作年限增加,会自然从简历里消失,这很正常。但从简历里消失,不代表这些事情没有发生过。
最近翻到了自己 2017 年的简历,用 LaTeX 写的。看到这一段:
塔防类游戏《像素战争》(类似《部落冲突》) 小组合作;使用 Unity 3D 以及 PlayMaker,主要负责 AI 算法和游戏逻辑的编写。
从 RNN 到 LSTM,再到 GRU:循环网络真正改变的是什么?
·3007 words·7 mins
最近复习 RNN、LSTM 和 GRU,我把它们的状态更新公式放在一起看。有一处值得单独想想:candidate 和 input gate 最后只是相乘,为什么要分成两组参数来学?从这个问题往回看,才能看清几个 gate 各自控制了什么。
把 RNN 沿时间展开之后:理解 BPTT 与梯度传播
复习 RNN 的 backward 时,我关注的是参数共享:同一份 weight 在多个 timestep 被使用,各处产生的梯度最后怎么汇到它上面?把时间展开成计算图之后,这件事就可以用普通的 chain rule 来算。
training loop 那篇重新理过 forward / backward / optimizer 的职责划分,RNN state transition 那篇理过 hidden state、output、prediction 的区别和 weight sharing,next-token prediction 那篇解释了为什么每个 timestep 都能产生一个 loss。这篇把这几块拼起来,回答一个问题:
从局部线性化到 RNN:理解 Jacobian 连乘
·4986 words·10 mins
最近在重拾一些深度学习基础,发现了一个很有意思的视角。
以前在看 RNN(Recurrent Neural Network)的长距离梯度传播公式时,总能看到一堆 Jacobian 矩阵的连乘,比如 \(\frac{\partial h_T}{\partial h_0} = J_T J_{T-1} \dots J_1\)。
为什么一个 Python Library 既要锁依赖,又不能锁依赖
起因 # 最近在团队内部重新整理 Python 项目的打包、发布和依赖管理规范,逐渐把各个工程统一收敛到:
1pyproject.toml 2uv 3uv.lock 4wheel 5src layout 6internal package registry 在这个过程中,大家交流最多的往往是一些具体的工具用法:私有源怎么配、build backend 选哪一个、uv 的命令参数怎么写。但我越梳理越发现,这些工程细节很容易盖住一个更基础的问题:
训练数据从哪里来:回看 2018 年的一套图片与视频采集系统
·4643 words·10 mins
起因 # 写训练代码的时候,经常从这里开始:
1dataset = load_dataset(...) 2model = build_model(...) 3train(model, dataset) dataset 像是一个天然存在的东西。打开一个 benchmark,下载一个压缩包,解压,加载,开始训练。ML 课程、论文、demo 大多也是从这一步开始。
从一次训练集群卡顿,理解 Linux Overcommit
·7429 words·15 mins
起因 # 最近偶然看到一篇文章,里面提到一个 Linux 和 Windows 的差异:在 Linux 下,即使机器实际上没有足够的物理内存,一个很大的 malloc 仍然可能成功返回。而 Windows 对 committed memory 的管理要严格得多,类似的 allocation 更容易被直接拒绝。
从 Token ID 到 Dense Vector:Embedding 到底在做什么
起因 # 最近在继续 CS336 和 MIT 6.S191。
之前那篇写了 BPE tokenizer——从训练到编解码,关注的是 raw text 怎么变成 token,token 怎么映射成 token ID。做完之后,对这条链路的前半段算是搞清楚了:
Next-Token Prediction:语言模型的训练目标从哪来
·3691 words·8 mins
起因 # 上一篇把 RNN 拆成了两层:state transition 和 output projection。State transition 维护 hidden state,output projection 从 hidden state 中映射出当前任务需要的预测结果。
重新理解 RNN:Hidden State、Output 和 Prediction 的区别
·3174 words·7 mins
起因 # 最近在复习 MIT 6.S191 的 RNN 部分,看到下面这张 slide 时停了一下。
左边代码里这一行:
1prediction, hidden_state = my_rnn(word, hidden_state) 右边图里同时画了 \(h_t\) 的回环和 \(\hat{y}_t\) 的向上输出。但 PyTorch API 里的 output 又指每一步的 hidden state,并不直接等于任务的 prediction。
从 Forward 到 Optimizer:再看一遍 Training Loop
起因 # CS336 的 training loop 里,loss.backward() 和 optimizer.step() 挨在一起。前者计算 gradient,后者更新 parameter;但 gradient 存在哪里、什么时候清零、optimizer 还维护什么状态,需要分开看。于是结合 MIT 6.S191 的 Lecture 1,把一次训练迭代重新过了一遍。
从推理到训练:模型调度中的显存约束
·2607 words·6 mins
推理任务能放下,为什么训练任务放不下 # 上一篇讨论了模型调度中的 Capacity Constraint:一组模型到底能不能同时放进一张 GPU。
从 CS336 到 ML Infra:理解 Arithmetic Intensity、Accelerator Intensity,以及 Compute Bound / Memory Bound
·6012 words·12 mins
起因 # 这是 CS336 系列的又一篇。
之前那篇讨论了 FLOPs 到 Latency 之间的鸿沟:FLOPs 相同的两个 GEMM,latency 可能差几倍甚至十几倍。那篇文章的核心结论是 FLOPs 是 workload metric,不是 performance metric,并且引入了 Arithmetic Intensity 和 Roofline Model 作为分析工具。